xref: /freebsd/sys/dev/cardbus/cardbus_cis.c (revision 9fb92b64ad1a01bdfe12d74c0a7b0e800b546e98)
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 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
269 	int type;
270 	int reg;
271 	u_int32_t bar;
272 
273 	if (len != 6) {
274 		printf("*** ERROR *** BAR length not 6 (%d)\n", len);
275 		return (EINVAL);
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, len=%04x%s%s\n",
302 	    (type == SYS_RES_MEMORY) ? "MEM" : "IO", bar, len,
303 	    (type == SYS_RES_MEMORY && dinfo->mprefetchable & BARBIT(bar)) ?
304 	    " (Prefetchable)" : "", type == SYS_RES_MEMORY ?
305 	    ((dinfo->mbelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "") :
306 	    (dinfo->ibelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "" ));
307 
308 	resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len);
309 
310 	/*
311 	 * Mark the appropriate bit in the PCI command register so that
312 	 * device drivers will know which BARs can be used.
313 	 */
314 	pci_enable_io(child, type);
315 	return (0);
316 }
317 
318 DECODE_PROTOTYPE(unhandled)
319 {
320 	printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
321 	return (-1);
322 }
323 
324 DECODE_PROTOTYPE(end)
325 {
326 	printf("CIS reading done\n");
327 	return (0);
328 }
329 
330 /*
331  * Functions to read the a tuple from the card
332  */
333 
334 static int
335 cardbus_read_tuple_conf(device_t cbdev, device_t child, u_int32_t start,
336     u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
337 {
338 	int i, j;
339 	u_int32_t e;
340 	u_int32_t loc;
341 
342 	loc = start + *off;
343 
344 	e = pci_read_config(child, loc - loc % 4, 4);
345 	for (j = loc % 4; j > 0; j--)
346 		e >>= 8;
347 	*len = 0;
348 	for (i = loc, j = -2; j < *len; j++, i++) {
349 		if (i % 4 == 0)
350 			e = pci_read_config(child, i, 4);
351 		if (j == -2)
352 			*tupleid = 0xff & e;
353 		else if (j == -1)
354 			*len = 0xff & e;
355 		else
356 			tupledata[j] = 0xff & e;
357 		e >>= 8;
358 	}
359 	*off += *len + 2;
360 	return (0);
361 }
362 
363 static int
364 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, u_int32_t start,
365     u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata)
366 {
367 	bus_space_tag_t bt;
368 	bus_space_handle_t bh;
369 	int ret;
370 
371 	bt = rman_get_bustag(res);
372 	bh = rman_get_bushandle(res);
373 
374 	*tupleid = bus_space_read_1(bt, bh, start + *off);
375 	*len = bus_space_read_1(bt, bh, start + *off + 1);
376 	bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len);
377 	ret = 0;
378 	*off += *len + 2;
379 	return (ret);
380 }
381 
382 static int
383 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
384     u_int32_t start, u_int32_t *off, int *tupleid, int *len,
385     u_int8_t *tupledata)
386 {
387 	if (res == (struct resource*)~0UL) {
388 		return (cardbus_read_tuple_conf(cbdev, child, start, off,
389 		    tupleid, len, tupledata));
390 	} else {
391 		return (cardbus_read_tuple_mem(cbdev, res, start, off,
392 		    tupleid, len, tupledata));
393 	}
394 }
395 
396 static void
397 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
398     struct resource *res)
399 {
400 	if (res != (struct resource*)~0UL) {
401 		bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
402 		pci_write_config(child, rid, 0, 4);
403 		PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
404 	}
405 }
406 
407 static struct resource *
408 cardbus_read_tuple_init(device_t cbdev, device_t child, u_int32_t *start,
409     int *rid)
410 {
411 	u_int32_t testval;
412 	u_int32_t size;
413 	struct resource *res;
414 
415 	switch (CARDBUS_CIS_SPACE(*start)) {
416 	case CARDBUS_CIS_ASI_TUPLE:
417 		/* CIS in PCI config space need no initialization */
418 		return ((struct resource*)~0UL);
419 	case CARDBUS_CIS_ASI_BAR0:
420 	case CARDBUS_CIS_ASI_BAR1:
421 	case CARDBUS_CIS_ASI_BAR2:
422 	case CARDBUS_CIS_ASI_BAR3:
423 	case CARDBUS_CIS_ASI_BAR4:
424 	case CARDBUS_CIS_ASI_BAR5:
425 		*rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
426 		break;
427 	case CARDBUS_CIS_ASI_ROM:
428 		*rid = CARDBUS_ROM_REG;
429 #if 0
430 		/*
431 		 * This mask doesn't contain the bit that actually enables
432 		 * the Option ROM.
433 		 */
434 		pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4);
435 #endif
436 		break;
437 	default:
438 		device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
439 		    CARDBUS_CIS_SPACE(*start));
440 		return (NULL);
441 	}
442 
443 	/* figure out how much space we need */
444 	pci_write_config(child, *rid, 0xffffffff, 4);
445 	testval = pci_read_config(child, *rid, 4);
446 
447 	/*
448 	 * This bit has a different meaning depending if we are dealing
449 	 * with a normal BAR or an Option ROM BAR.
450 	 */
451 	if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) {
452 		device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
453 		return (NULL);
454 	}
455 
456 	size = CARDBUS_MAPREG_MEM_SIZE(testval);
457 	/* XXX Is this some kind of hack? */
458 	if (size < 4096)
459 		size = 4096;
460 	/* allocate the memory space to read CIS */
461 	res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
462 	    rman_make_alignment_flags(size) | RF_ACTIVE);
463 	if (res == NULL) {
464 		device_printf(cbdev, "Unable to allocate resource "
465 		    "to read CIS.\n");
466 		return (NULL);
467 	}
468 	pci_write_config(child, *rid,
469 	    rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
470 		CARDBUS_ROM_ENABLE : 0),
471 	    4);
472 	PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
473 
474 	/* Flip to the right ROM image if CIS is in ROM */
475 	if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
476 		bus_space_tag_t bt;
477 		bus_space_handle_t bh;
478 		u_int32_t imagesize;
479 		u_int32_t imagebase = 0;
480 		u_int32_t pcidata;
481 		u_int16_t romsig;
482 		int romnum = 0;
483 		int imagenum;
484 
485 		bt = rman_get_bustag(res);
486 		bh = rman_get_bushandle(res);
487 
488 		imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
489 		for (romnum = 0;; romnum++) {
490 			romsig = bus_space_read_2(bt, bh,
491 			    imagebase + CARDBUS_EXROM_SIGNATURE);
492 			if (romsig != 0xaa55) {
493 				device_printf(cbdev, "Bad header in rom %d: "
494 				    "[%x] %04x\n", romnum, imagebase +
495 				    CARDBUS_EXROM_SIGNATURE, romsig);
496 				bus_release_resource(cbdev, SYS_RES_MEMORY,
497 				    *rid, res);
498 				*rid = 0;
499 				return (NULL);
500 			}
501 
502 			/*
503 			 * If this was the Option ROM image that we were
504 			 * looking for, then we are done.
505 			 */
506 			if (romnum == imagenum)
507 				break;
508 
509 			/* Find out where the next Option ROM image is */
510 			pcidata = imagebase + bus_space_read_2(bt, bh,
511 			    imagebase + CARDBUS_EXROM_DATA_PTR);
512 			imagesize = bus_space_read_2(bt, bh,
513 			    pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
514 
515 			if (imagesize == 0) {
516 				/*
517 				 * XXX some ROMs seem to have this as zero,
518 				 * can we assume this means 1 block?
519 				 */
520 				device_printf(cbdev, "Warning, size of Option "
521 				    "ROM image %d is 0 bytes, assuming 512 "
522 				    "bytes.\n", romnum);
523 				imagesize = 1;
524 			}
525 
526 			/* Image size is in 512 byte units */
527 			imagesize <<= 9;
528 
529 			if ((bus_space_read_1(bt, bh, pcidata +
530 			    CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
531 				device_printf(cbdev, "Cannot find CIS in "
532 				    "Option ROM\n");
533 				bus_release_resource(cbdev, SYS_RES_MEMORY,
534 				    *rid, res);
535 				*rid = 0;
536 				return (NULL);
537 			}
538 			imagebase += imagesize;
539 		}
540 		*start = imagebase + CARDBUS_CIS_ADDR(*start);
541 	} else {
542 		*start = CARDBUS_CIS_ADDR(*start);
543 	}
544 
545 	return (res);
546 }
547 
548 /*
549  * Dispatch the right handler function per tuple
550  */
551 
552 static int
553 decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
554     u_int8_t *tupledata, u_int32_t start, u_int32_t *off,
555     struct tuple_callbacks *callbacks)
556 {
557 	int i;
558 	for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
559 		if (tupleid == callbacks[i].id)
560 			return (callbacks[i].func(cbdev, child, tupleid, len,
561 			    tupledata, start, off, &callbacks[i]));
562 	}
563 
564 	if (tupleid < CISTPL_CUSTOMSTART) {
565 		device_printf(cbdev, "Undefined tuple encountered, "
566 		    "CIS parsing terminated\n");
567 		return (EINVAL);
568 	}
569 	return (callbacks[i].func(cbdev, child, tupleid, len,
570 	    tupledata, start, off, NULL));
571 }
572 
573 static int
574 cardbus_parse_cis(device_t cbdev, device_t child,
575     struct tuple_callbacks *callbacks)
576 {
577 	u_int8_t tupledata[MAXTUPLESIZE];
578 	int tupleid;
579 	int len;
580 	int expect_linktarget;
581 	u_int32_t start, off;
582 	struct resource *res;
583 	int rid;
584 
585 	bzero(tupledata, MAXTUPLESIZE);
586 	expect_linktarget = TRUE;
587 	if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0)
588 		return (ENXIO);
589 	off = 0;
590 	res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
591 	if (res == NULL)
592 		return (ENXIO);
593 	do {
594 		if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
595 		    &tupleid, &len, tupledata)) {
596 			device_printf(cbdev, "Failed to read CIS.\n");
597 			cardbus_read_tuple_finish(cbdev, child, rid, res);
598 			return (ENXIO);
599 		}
600 
601 		if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
602 			device_printf(cbdev, "Expecting link target, got 0x%x\n",
603 			    tupleid);
604 			cardbus_read_tuple_finish(cbdev, child, rid, res);
605 			return (EINVAL);
606 		}
607 		expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
608 		    tupledata, start, &off, callbacks);
609 		if (expect_linktarget != 0) {
610 			cardbus_read_tuple_finish(cbdev, child, rid, res);
611 			return (expect_linktarget);
612 		}
613 	} while (tupleid != CISTPL_END);
614 	cardbus_read_tuple_finish(cbdev, child, rid, res);
615 	return (0);
616 }
617 
618 static int
619 barsort(const void *a, const void *b)
620 {
621 	return ((*(const struct resource_list_entry * const *)b)->count -
622 	    (*(const struct resource_list_entry * const *)a)->count);
623 }
624 
625 static int
626 cardbus_alloc_resources(device_t cbdev, device_t child)
627 {
628 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
629 	int count;
630 	struct resource_list_entry *rle;
631 	struct resource_list_entry **barlist;
632 	int tmp;
633 	u_int32_t mem_psize = 0, mem_nsize = 0, io_size = 0;
634 	struct resource *res;
635 	u_int32_t start,end;
636 	int rid, flags;
637 
638 	count = 0;
639 	SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
640 		count++;
641 	}
642 	if (count == 0)
643 		return (0);
644 	barlist = malloc(sizeof(struct resource_list_entry*) * count, M_DEVBUF,
645 	    M_WAITOK);
646 	count = 0;
647 	SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
648 		barlist[count] = rle;
649 		if (rle->type == SYS_RES_IOPORT) {
650 			io_size += rle->count;
651 		} else if (rle->type == SYS_RES_MEMORY) {
652 			if (dinfo->mprefetchable & BARBIT(rle->rid))
653 				mem_psize += rle->count;
654 			else
655 				mem_nsize += rle->count;
656 		}
657 		count++;
658 	}
659 
660 	/*
661 	 * We want to allocate the largest resource first, so that our
662 	 * allocated memory is packed.
663 	 */
664 	qsort(barlist, count, sizeof(struct resource_list_entry*), barsort);
665 
666 	/* Allocate prefetchable memory */
667 	flags = 0;
668 	for (tmp = 0; tmp < count; tmp++) {
669 		if (barlist[tmp]->res == NULL &&
670 		    barlist[tmp]->type == SYS_RES_MEMORY &&
671 		    dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) {
672 			flags = rman_make_alignment_flags(barlist[tmp]->count);
673 			break;
674 		}
675 	}
676 	if (flags > 0) { /* If any prefetchable memory is requested... */
677 		/*
678 		 * First we allocate one big space for all resources of this
679 		 * type.  We do this because our parent, pccbb, needs to open
680 		 * a window to forward all addresses within the window, and
681 		 * it would be best if nobody else has resources allocated
682 		 * within the window.
683 		 * (XXX: Perhaps there might be a better way to do this?)
684 		 */
685 		rid = 0;
686 		res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0,
687 		    (dinfo->mprefetchable & dinfo->mbelow1mb)?0xFFFFF:~0UL,
688 		    mem_psize, flags);
689 		start = rman_get_start(res);
690 		end = rman_get_end(res);
691 		DEVPRINTF((cbdev, "Prefetchable memory at %x-%x\n", start, end));
692 		/*
693 		 * Now that we know the region is free, release it and hand it
694 		 * out piece by piece.
695 		 */
696 		bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
697 		for (tmp = 0; tmp < count; tmp++) {
698 			if (barlist[tmp]->res == NULL &&
699 			    barlist[tmp]->type == SYS_RES_MEMORY &&
700 			    dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) {
701 				barlist[tmp]->res = bus_alloc_resource(cbdev,
702 				    barlist[tmp]->type,
703 				    &barlist[tmp]->rid, start, end,
704 				    barlist[tmp]->count,
705 				    rman_make_alignment_flags(
706 				    barlist[tmp]->count));
707 				if (barlist[tmp]->res == NULL) {
708 					mem_nsize += barlist[tmp]->count;
709 					dinfo->mprefetchable &=
710 					    ~BARBIT(barlist[tmp]->rid);
711 					DEVPRINTF((cbdev, "Cannot pre-allocate "
712 					    "prefetchable memory, will try as "
713 					    "non-prefetchable.\n"));
714 				} else {
715 					barlist[tmp]->start =
716 					    rman_get_start(barlist[tmp]->res);
717 					barlist[tmp]->end =
718 					    rman_get_end(barlist[tmp]->res);
719 					pci_write_config(child,
720 					    barlist[tmp]->rid,
721 					    barlist[tmp]->start, 4);
722 					DEVPRINTF((cbdev, "Prefetchable memory "
723 					    "rid=%x at %lx-%lx\n",
724 					    barlist[tmp]->rid,
725 					    barlist[tmp]->start,
726 					    barlist[tmp]->end));
727 				}
728 			}
729 		}
730 	}
731 
732 	/* Allocate non-prefetchable memory */
733 	flags = 0;
734 	for (tmp = 0; tmp < count; tmp++) {
735 		if (barlist[tmp]->res == NULL &&
736 		    barlist[tmp]->type == SYS_RES_MEMORY) {
737 			flags = rman_make_alignment_flags(barlist[tmp]->count);
738 			break;
739 		}
740 	}
741 	if (flags > 0) { /* If any non-prefetchable memory is requested... */
742 		/*
743 		 * First we allocate one big space for all resources of this
744 		 * type.  We do this because our parent, pccbb, needs to open
745 		 * a window to forward all addresses within the window, and
746 		 * it would be best if nobody else has resources allocated
747 		 * within the window.
748 		 * (XXX: Perhaps there might be a better way to do this?)
749 		 */
750 		rid = 0;
751 		res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0,
752 		    ((~dinfo->mprefetchable) & dinfo->mbelow1mb)?0xFFFFF:~0UL,
753 		    mem_nsize, flags);
754 		start = rman_get_start(res);
755 		end = rman_get_end(res);
756 		DEVPRINTF((cbdev, "Non-prefetchable memory at %x-%x\n",
757 		    start, end));
758 		/*
759 		 * Now that we know the region is free, release it and hand it
760 		 * out piece by piece.
761 		 */
762 		bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
763 		for (tmp = 0; tmp < count; tmp++) {
764 			if (barlist[tmp]->res == NULL &&
765 			    barlist[tmp]->type == SYS_RES_MEMORY) {
766 				barlist[tmp]->res = bus_alloc_resource(cbdev,
767 				    barlist[tmp]->type, &barlist[tmp]->rid,
768 				    start, end, barlist[tmp]->count,
769 				    rman_make_alignment_flags(
770 				    barlist[tmp]->count));
771 				if (barlist[tmp]->res == NULL) {
772 					DEVPRINTF((cbdev, "Cannot pre-allocate "
773 					    "memory for cardbus device\n"));
774 					free(barlist, M_DEVBUF);
775 					return (ENOMEM);
776 				}
777 				barlist[tmp]->start =
778 				    rman_get_start(barlist[tmp]->res);
779 				barlist[tmp]->end = rman_get_end(
780 					barlist[tmp]->res);
781 				pci_write_config(child, barlist[tmp]->rid,
782 				    barlist[tmp]->start, 4);
783 				DEVPRINTF((cbdev, "Non-prefetchable memory "
784 				    "rid=%x at %lx-%lx (%lx)\n",
785 				    barlist[tmp]->rid, barlist[tmp]->start,
786 				    barlist[tmp]->end, barlist[tmp]->count));
787 			}
788 		}
789 	}
790 
791 	/* Allocate IO ports */
792 	flags = 0;
793 	for (tmp = 0; tmp < count; tmp++) {
794 		if (barlist[tmp]->res == NULL &&
795 		    barlist[tmp]->type == SYS_RES_IOPORT) {
796 			flags = rman_make_alignment_flags(barlist[tmp]->count);
797 			break;
798 		}
799 	}
800 	if (flags > 0) { /* If any IO port is requested... */
801 		/*
802 		 * First we allocate one big space for all resources of this
803 		 * type.  We do this because our parent, pccbb, needs to open
804 		 * a window to forward all addresses within the window, and
805 		 * it would be best if nobody else has resources allocated
806 		 * within the window.
807 		 * (XXX: Perhaps there might be a better way to do this?)
808 		 */
809 		rid = 0;
810 		res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0,
811 		    (dinfo->ibelow1mb)?0xFFFFF:~0UL, io_size, flags);
812 		start = rman_get_start(res);
813 		end = rman_get_end(res);
814 		DEVPRINTF((cbdev, "IO port at %x-%x\n", start, end));
815 		/*
816 		 * Now that we know the region is free, release it and hand it
817 		 * out piece by piece.
818 		 */
819 		bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res);
820 		for (tmp = 0; tmp < count; tmp++) {
821 			if (barlist[tmp]->res == NULL &&
822 			    barlist[tmp]->type == SYS_RES_IOPORT) {
823 				barlist[tmp]->res = bus_alloc_resource(cbdev,
824 				    barlist[tmp]->type, &barlist[tmp]->rid,
825 				    start, end, barlist[tmp]->count,
826 				    rman_make_alignment_flags(
827 				    barlist[tmp]->count));
828 				if (barlist[tmp]->res == NULL) {
829 					DEVPRINTF((cbdev, "Cannot pre-allocate "
830 					    "IO port for cardbus device\n"));
831 					free(barlist, M_DEVBUF);
832 					return (ENOMEM);
833 				}
834 				barlist[tmp]->start =
835 				    rman_get_start(barlist[tmp]->res);
836 				barlist[tmp]->end =
837 				    rman_get_end(barlist[tmp]->res);
838 			pci_write_config(child, barlist[tmp]->rid,
839 			    barlist[tmp]->start, 4);
840 			DEVPRINTF((cbdev, "IO port rid=%x at %lx-%lx\n",
841 			    barlist[tmp]->rid, barlist[tmp]->start,
842 			    barlist[tmp]->end));
843 			}
844 		}
845 	}
846 
847 	/* Allocate IRQ */
848 	rid = 0;
849 	res = bus_alloc_resource(cbdev, SYS_RES_IRQ, &rid, 0, ~0UL, 1,
850 	    RF_SHAREABLE);
851 	resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid,
852 	    rman_get_start(res), rman_get_end(res), 1);
853 	rle = resource_list_find(&dinfo->pci.resources, SYS_RES_IRQ, rid);
854 	rle->res = res;
855 	dinfo->pci.cfg.intline = rman_get_start(res);
856 	pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1);
857 
858 	free(barlist, M_DEVBUF);
859 	return (0);
860 }
861 
862 /*
863  * Adding a memory/io resource (sans CIS)
864  */
865 
866 static void
867 cardbus_add_map(device_t cbdev, device_t child, int reg)
868 {
869 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
870 	struct resource_list_entry *rle;
871 	u_int32_t size;
872 	u_int32_t testval;
873 	int type;
874 
875 	SLIST_FOREACH(rle, &dinfo->pci.resources, link) {
876 		if (rle->rid == reg)
877 			return;
878 	}
879 
880 	if (reg == CARDBUS_ROM_REG)
881 		testval = CARDBUS_ROM_ADDRMASK;
882 	else
883 		testval = ~0;
884 
885 	pci_write_config(child, reg, testval, 4);
886 	testval = pci_read_config(child, reg, 4);
887 
888 	if (testval == ~0 || testval == 0)
889 		return;
890 
891 	if ((testval & 1) == 0)
892 		type = SYS_RES_MEMORY;
893 	else
894 		type = SYS_RES_IOPORT;
895 
896 	size = CARDBUS_MAPREG_MEM_SIZE(testval);
897 	device_printf(cbdev, "Resource not specified in CIS: id=%x, size=%x\n",
898 	    reg, size);
899 	resource_list_add(&dinfo->pci.resources, type, reg, 0UL, ~0UL, size);
900 }
901 
902 static void
903 cardbus_pickup_maps(device_t cbdev, device_t child)
904 {
905 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
906 	struct cardbus_quirk *q;
907 	int reg;
908 
909 	/*
910 	 * Try to pick up any resources that was not specified in CIS.
911 	 * Some devices (eg, 3c656) does not list all resources required by
912 	 * the driver in its CIS.
913 	 * XXX: should we do this or use quirks?
914 	 */
915 	for (reg = 0; reg < dinfo->pci.cfg.nummaps; reg++) {
916 		cardbus_add_map(cbdev, child, PCIR_MAPS + reg * 4);
917 	}
918 
919 	for (q = &cardbus_quirks[0]; q->devid; q++) {
920 		if (q->devid == ((dinfo->pci.cfg.device << 16) | dinfo->pci.cfg.vendor)
921 		    && q->type == CARDBUS_QUIRK_MAP_REG) {
922 			cardbus_add_map(cbdev, child, q->arg1);
923 		}
924 	}
925 }
926 
927 int
928 cardbus_cis_read(device_t cbdev, device_t child, u_int8_t id,
929     struct cis_tupleinfo **buff, int *nret)
930 {
931 	struct tuple_callbacks cisread_callbacks[] = {
932 		MAKETUPLE(NULL,			nothing),
933 		/* first entry will be overwritten */
934 		MAKETUPLE(NULL,			nothing),
935 		MAKETUPLE(DEVICE,		nothing),
936 		MAKETUPLE(LONG_LINK_CB,		unhandled),
937 		MAKETUPLE(INDIRECT,		unhandled),
938 		MAKETUPLE(CONFIG_CB,		nothing),
939 		MAKETUPLE(CFTABLE_ENTRY_CB,	nothing),
940 		MAKETUPLE(LONGLINK_MFC,		unhandled),
941 		MAKETUPLE(BAR,			nothing),
942 		MAKETUPLE(PWR_MGMNT,		nothing),
943 		MAKETUPLE(EXTDEVICE,		nothing),
944 		MAKETUPLE(CHECKSUM,		nothing),
945 		MAKETUPLE(LONGLINK_A,		unhandled),
946 		MAKETUPLE(LONGLINK_C,		unhandled),
947 		MAKETUPLE(LINKTARGET,		nothing),
948 		MAKETUPLE(NO_LINK,		nothing),
949 		MAKETUPLE(VERS_1,		nothing),
950 		MAKETUPLE(ALTSTR,		nothing),
951 		MAKETUPLE(DEVICE_A,		nothing),
952 		MAKETUPLE(JEDEC_C,		nothing),
953 		MAKETUPLE(JEDEC_A,		nothing),
954 		MAKETUPLE(CONFIG,		nothing),
955 		MAKETUPLE(CFTABLE_ENTRY,	nothing),
956 		MAKETUPLE(DEVICE_OC,		nothing),
957 		MAKETUPLE(DEVICE_OA,		nothing),
958 		MAKETUPLE(DEVICE_GEO,		nothing),
959 		MAKETUPLE(DEVICE_GEO_A,		nothing),
960 		MAKETUPLE(MANFID,		nothing),
961 		MAKETUPLE(FUNCID,		nothing),
962 		MAKETUPLE(FUNCE,		nothing),
963 		MAKETUPLE(SWIL,			nothing),
964 		MAKETUPLE(VERS_2,		nothing),
965 		MAKETUPLE(FORMAT,		nothing),
966 		MAKETUPLE(GEOMETRY,		nothing),
967 		MAKETUPLE(BYTEORDER,		nothing),
968 		MAKETUPLE(DATE,			nothing),
969 		MAKETUPLE(BATTERY,		nothing),
970 		MAKETUPLE(ORG,			nothing),
971 		MAKETUPLE(END,			end),
972 		MAKETUPLE(GENERIC,		nothing),
973 	};
974 	int ret;
975 
976 	cisread_callbacks[0].id = id;
977 	cisread_callbacks[0].name = "COPY";
978 	cisread_callbacks[0].func = decode_tuple_copy;
979 	ncisread_buf = 0;
980 	cisread_buf = NULL;
981 	ret = cardbus_parse_cis(cbdev, child, cisread_callbacks);
982 
983 	*buff = cisread_buf;
984 	*nret = ncisread_buf;
985 	return (ret);
986 }
987 
988 void
989 cardbus_cis_free(device_t cbdev, struct cis_tupleinfo *buff, int *nret)
990 {
991 	int i;
992 	for (i = 0; i < *nret; i++)
993 		free(buff[i].data, M_DEVBUF);
994 	if (*nret > 0)
995 		free(buff, M_DEVBUF);
996 }
997 
998 int
999 cardbus_do_cis(device_t cbdev, device_t child)
1000 {
1001 	int ret;
1002 	struct tuple_callbacks init_callbacks[] = {
1003 		MAKETUPLE(NULL,			generic),
1004 		MAKETUPLE(DEVICE,		generic),
1005 		MAKETUPLE(LONG_LINK_CB,		unhandled),
1006 		MAKETUPLE(INDIRECT,		unhandled),
1007 		MAKETUPLE(CONFIG_CB,		generic),
1008 		MAKETUPLE(CFTABLE_ENTRY_CB,	generic),
1009 		MAKETUPLE(LONGLINK_MFC,		unhandled),
1010 		MAKETUPLE(BAR,			bar),
1011 		MAKETUPLE(PWR_MGMNT,		generic),
1012 		MAKETUPLE(EXTDEVICE,		generic),
1013 		MAKETUPLE(CHECKSUM,		generic),
1014 		MAKETUPLE(LONGLINK_A,		unhandled),
1015 		MAKETUPLE(LONGLINK_C,		unhandled),
1016 		MAKETUPLE(LINKTARGET,		linktarget),
1017 		MAKETUPLE(NO_LINK,		generic),
1018 		MAKETUPLE(VERS_1,		vers_1),
1019 		MAKETUPLE(ALTSTR,		generic),
1020 		MAKETUPLE(DEVICE_A,		generic),
1021 		MAKETUPLE(JEDEC_C,		generic),
1022 		MAKETUPLE(JEDEC_A,		generic),
1023 		MAKETUPLE(CONFIG,		generic),
1024 		MAKETUPLE(CFTABLE_ENTRY,	generic),
1025 		MAKETUPLE(DEVICE_OC,		generic),
1026 		MAKETUPLE(DEVICE_OA,		generic),
1027 		MAKETUPLE(DEVICE_GEO,		generic),
1028 		MAKETUPLE(DEVICE_GEO_A,		generic),
1029 		MAKETUPLE(MANFID,		manfid),
1030 		MAKETUPLE(FUNCID,		funcid),
1031 		MAKETUPLE(FUNCE,		funce),
1032 		MAKETUPLE(SWIL,			generic),
1033 		MAKETUPLE(VERS_2,		generic),
1034 		MAKETUPLE(FORMAT,		generic),
1035 		MAKETUPLE(GEOMETRY,		generic),
1036 		MAKETUPLE(BYTEORDER,		generic),
1037 		MAKETUPLE(DATE,			generic),
1038 		MAKETUPLE(BATTERY,		generic),
1039 		MAKETUPLE(ORG,			generic),
1040 		MAKETUPLE(END,			end),
1041 		MAKETUPLE(GENERIC,		generic),
1042 	};
1043 
1044 	ret = cardbus_parse_cis(cbdev, child, init_callbacks);
1045 	if (ret < 0)
1046 		return (ret);
1047 	cardbus_pickup_maps(cbdev, child);
1048 	return (cardbus_alloc_resources(cbdev, child));
1049 }
1050