Deleted Added
full compact
cardbus_cis.c (92301) cardbus_cis.c (97613)
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 *
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: head/sys/dev/cardbus/cardbus_cis.c 92301 2002-03-15 06:41:01Z imp $
28 * $FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 97613 2002-05-30 17:38:00Z takawata $
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
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"
53#include <dev/pccard/pccardvar.h>
54
55extern 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
65struct 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
72DECODE_PROTOTYPE(generic);
73DECODE_PROTOTYPE(nothing);
74DECODE_PROTOTYPE(copy);
75DECODE_PROTOTYPE(linktarget);
76DECODE_PROTOTYPE(vers_1);
77DECODE_PROTOTYPE(funcid);
78DECODE_PROTOTYPE(manfid);
79DECODE_PROTOTYPE(funce);
80DECODE_PROTOTYPE(bar);
81DECODE_PROTOTYPE(unhandled);
82DECODE_PROTOTYPE(end);
83static 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);
86static 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);
89static 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);
92static void cardbus_read_tuple_finish(device_t cbdev, device_t child,
93 int rid, struct resource *res);
94static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
95 u_int32_t *start, int *rid);
96static 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);
99static int cardbus_parse_cis(device_t cbdev, device_t child,
100 struct tuple_callbacks *callbacks);
101static int barsort(const void *a, const void *b);
102static int cardbus_alloc_resources(device_t cbdev, device_t child);
103static void cardbus_add_map(device_t cbdev, device_t child, int reg);
104static void cardbus_pickup_maps(device_t cbdev, device_t child);
105
106
107#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
108
109static 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
122struct 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
130struct cardbus_quirk cardbus_quirks[] = {
131 { 0 }
132};
133
134static struct cis_tupleinfo *cisread_buf;
135static int ncisread_buf;
136
137/*
138 * Handler functions for various CIS tuples
139 */
140
141DECODE_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
161DECODE_PROTOTYPE(nothing)
162{
163 return (0);
164}
165
166DECODE_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
187DECODE_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
211DECODE_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
228DECODE_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
246DECODE_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
256DECODE_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
266DECODE_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
316DECODE_PROTOTYPE(unhandled)
317{
318 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
319 return (-1);
320}
321
322DECODE_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
332static int
333cardbus_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
361static int
362cardbus_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
380static int
381cardbus_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
394static void
395cardbus_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
405static struct resource *
406cardbus_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
521static int
522decode_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
542static int
543cardbus_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
586static int
587barsort(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
593static int
594cardbus_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
832static void
833cardbus_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
868static void
869cardbus_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
893int
894cardbus_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
954void
955cardbus_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
964int
965cardbus_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}
54
55extern 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
65struct 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
72DECODE_PROTOTYPE(generic);
73DECODE_PROTOTYPE(nothing);
74DECODE_PROTOTYPE(copy);
75DECODE_PROTOTYPE(linktarget);
76DECODE_PROTOTYPE(vers_1);
77DECODE_PROTOTYPE(funcid);
78DECODE_PROTOTYPE(manfid);
79DECODE_PROTOTYPE(funce);
80DECODE_PROTOTYPE(bar);
81DECODE_PROTOTYPE(unhandled);
82DECODE_PROTOTYPE(end);
83static 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);
86static 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);
89static 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);
92static void cardbus_read_tuple_finish(device_t cbdev, device_t child,
93 int rid, struct resource *res);
94static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
95 u_int32_t *start, int *rid);
96static 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);
99static int cardbus_parse_cis(device_t cbdev, device_t child,
100 struct tuple_callbacks *callbacks);
101static int barsort(const void *a, const void *b);
102static int cardbus_alloc_resources(device_t cbdev, device_t child);
103static void cardbus_add_map(device_t cbdev, device_t child, int reg);
104static void cardbus_pickup_maps(device_t cbdev, device_t child);
105
106
107#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
108
109static 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
122struct 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
130struct cardbus_quirk cardbus_quirks[] = {
131 { 0 }
132};
133
134static struct cis_tupleinfo *cisread_buf;
135static int ncisread_buf;
136
137/*
138 * Handler functions for various CIS tuples
139 */
140
141DECODE_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
161DECODE_PROTOTYPE(nothing)
162{
163 return (0);
164}
165
166DECODE_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
187DECODE_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
211DECODE_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
228DECODE_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
246DECODE_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
256DECODE_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
266DECODE_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
316DECODE_PROTOTYPE(unhandled)
317{
318 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
319 return (-1);
320}
321
322DECODE_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
332static int
333cardbus_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
361static int
362cardbus_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
380static int
381cardbus_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
394static void
395cardbus_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
405static struct resource *
406cardbus_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
521static int
522decode_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
542static int
543cardbus_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
586static int
587barsort(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
593static int
594cardbus_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
832static void
833cardbus_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
868static void
869cardbus_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
893int
894cardbus_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
954void
955cardbus_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
964int
965cardbus_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}