xref: /freebsd/sys/dev/cardbus/cardbus_cis.c (revision 09e8dea79366f1e5b3a73e8a271b26e4b6bf2e6a)
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 <dev/pccard/pccardvar.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 * const *)b)->count -
590 	    (*(const struct resource_list_entry * const *)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 }
1016