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