cardbus_cis.c (82375) | cardbus_cis.c (82378) |
---|---|
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 --- 11 unchanged lines hidden (view full) --- 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * | 1/* 2 * Copyright (c) 2000,2001 Jonathan Chen. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * |
28 * $FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82375 2001-08-26 23:55:34Z jon $ | 28 * $FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82378 2001-08-27 00:09:42Z jon $ |
29 */ 30 31/* 32 * CIS Handling for the Cardbus Bus 33 */ 34 35#define CARDBUS_DEBUG 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40#include <sys/malloc.h> 41 42#include <sys/bus.h> 43#include <machine/bus.h> 44#include <machine/resource.h> 45#include <sys/rman.h> 46 | 29 */ 30 31/* 32 * CIS Handling for the Cardbus Bus 33 */ 34 35#define CARDBUS_DEBUG 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/kernel.h> 40#include <sys/malloc.h> 41 42#include <sys/bus.h> 43#include <machine/bus.h> 44#include <machine/resource.h> 45#include <sys/rman.h> 46 |
47#include | 47#include <dev/pci/pcivar.h> 48#include <dev/pci/pcireg.h> 49#include <sys/pciio.h> |
48 49#include <dev/cardbus/cardbusreg.h> | 50 51#include <dev/cardbus/cardbusreg.h> |
52#include <dev/cardbus/cardbusvar.h> |
|
50#include <dev/cardbus/cardbus_cis.h> 51 52#include "card_if.h" 53 54#if defined CARDBUS_DEBUG 55#define DPRINTF(a) printf a 56#define DEVPRINTF(x) device_printf x 57#else 58#define DPRINTF(a) 59#define DEVPRINTF(x) 60#endif 61 62#if !defined(lint) 63static const char rcsid[] = | 53#include <dev/cardbus/cardbus_cis.h> 54 55#include "card_if.h" 56 57#if defined CARDBUS_DEBUG 58#define DPRINTF(a) printf a 59#define DEVPRINTF(x) device_printf x 60#else 61#define DPRINTF(a) 62#define DEVPRINTF(x) 63#endif 64 65#if !defined(lint) 66static const char rcsid[] = |
64 "$FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82375 2001-08-26 23:55:34Z jon $"; | 67 "$FreeBSD: head/sys/dev/cardbus/cardbus_cis.c 82378 2001-08-27 00:09:42Z jon $"; |
65#endif 66 67#define DECODE_PARAMS \ 68 (device_t cbdev, device_t child, int id, int len, \ | 68#endif 69 70#define DECODE_PARAMS \ 71 (device_t cbdev, device_t child, int id, int len, \ |
69 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, \ | 72 u_int8_t *tupledata, u_int32_t start, u_int32_t *off, \ |
70 struct tuple_callbacks *info) 71 72struct tuple_callbacks { 73 int id; 74 char *name; 75 int (*func) DECODE_PARAMS; 76}; 77 --- 5 unchanged lines hidden (view full) --- 83DECODE_PROTOTYPE(vers_1); 84DECODE_PROTOTYPE(funcid); 85DECODE_PROTOTYPE(manfid); 86DECODE_PROTOTYPE(funce); 87DECODE_PROTOTYPE(bar); 88DECODE_PROTOTYPE(unhandled); 89DECODE_PROTOTYPE(end); 90static int cardbus_read_tuple_conf(device_t cbdev, device_t child, | 73 struct tuple_callbacks *info) 74 75struct tuple_callbacks { 76 int id; 77 char *name; 78 int (*func) DECODE_PARAMS; 79}; 80 --- 5 unchanged lines hidden (view full) --- 86DECODE_PROTOTYPE(vers_1); 87DECODE_PROTOTYPE(funcid); 88DECODE_PROTOTYPE(manfid); 89DECODE_PROTOTYPE(funce); 90DECODE_PROTOTYPE(bar); 91DECODE_PROTOTYPE(unhandled); 92DECODE_PROTOTYPE(end); 93static int cardbus_read_tuple_conf(device_t cbdev, device_t child, |
91 u_int32_t *start, u_int32_t *off, int *tupleid, int *len, | 94 u_int32_t start, u_int32_t *off, int *tupleid, int *len, |
92 u_int8_t *tupledata); | 95 u_int8_t *tupledata); |
93static int cardbus_read_tuple_exrom(device_t cbdev, struct resource *mem, 94 u_int32_t *start, u_int32_t *off, int *tupleid, int *len, | 96static int cardbus_read_tuple_mem(device_t cbdev, struct resource *res, 97 u_int32_t start, u_int32_t *off, int *tupleid, int *len, |
95 u_int8_t *tupledata); | 98 u_int8_t *tupledata); |
96static int cardbus_read_tuple_mem(device_t cbdev, device_t child, 97 u_int32_t *start, u_int32_t *off, int *tupleid, int *len, 98 u_int8_t *tupledata); | |
99static int cardbus_read_tuple(device_t cbdev, device_t child, | 99static int cardbus_read_tuple(device_t cbdev, device_t child, |
100 u_int32_t *start, u_int32_t *off, int *tupleid, int *len, 101 u_int8_t *tupledata); | 100 struct resource *res, u_int32_t start, u_int32_t *off, 101 int *tupleid, int *len, u_int8_t *tupledata); 102static void cardbus_read_tuple_finish(device_t cbdev, device_t child, 103 int rid, struct resource *res); 104static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child, 105 u_int32_t *start, int *rid); |
102static int decode_tuple(device_t cbdev, device_t child, int tupleid, | 106static int decode_tuple(device_t cbdev, device_t child, int tupleid, |
103 int len, u_int8_t *tupledata, u_int32_t *start, | 107 int len, u_int8_t *tupledata, u_int32_t start, |
104 u_int32_t *off, struct tuple_callbacks *callbacks); 105static int cardbus_parse_cis(device_t cbdev, device_t child, 106 struct tuple_callbacks *callbacks); | 108 u_int32_t *off, struct tuple_callbacks *callbacks); 109static int cardbus_parse_cis(device_t cbdev, device_t child, 110 struct tuple_callbacks *callbacks); |
111static int barsort(const void *a, const void *b); 112static int cardbus_alloc_resources(device_t cbdev, device_t child); 113static void cardbus_add_map(device_t cbdev, device_t child, int reg); 114static void cardbus_pickup_maps(device_t cbdev, device_t child); |
|
107 | 115 |
116 |
|
108#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 109 110static 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 | 117#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 118 119static char *funcnames[] = { 120 "Multi-Functioned", 121 "Memory", 122 "Serial Port", 123 "Parallel Port", 124 "Fixed Disk", 125 "Video Adaptor", 126 "Network Adaptor", 127 "AIMS", 128 "SCSI", 129 "Security" 130}; 131 |
132struct cardbus_quirk { 133 u_int32_t devid; /* Vendor/device of the card */ 134 int type; 135#define CARDBUS_QUIRK_MAP_REG 1 /* PCI map register in weird place */ 136 int arg1; 137 int arg2; 138}; 139 140struct cardbus_quirk cardbus_quirks[] = { 141 { 0 } 142}; 143 |
|
123static struct cis_tupleinfo *cisread_buf; 124static int ncisread_buf; 125 126/* 127 * Handler functions for various CIS tuples 128 */ 129 130DECODE_PROTOTYPE(generic) --- 122 unchanged lines hidden (view full) --- 253} 254 255DECODE_PROTOTYPE(bar) 256{ 257 if (len != 6) { 258 printf("*** ERROR *** BAR length not 6 (%d)\n", len); 259 return EINVAL; 260 } else { | 144static struct cis_tupleinfo *cisread_buf; 145static int ncisread_buf; 146 147/* 148 * Handler functions for various CIS tuples 149 */ 150 151DECODE_PROTOTYPE(generic) --- 122 unchanged lines hidden (view full) --- 274} 275 276DECODE_PROTOTYPE(bar) 277{ 278 if (len != 6) { 279 printf("*** ERROR *** BAR length not 6 (%d)\n", len); 280 return EINVAL; 281 } else { |
282 struct cardbus_devinfo *dinfo = device_get_ivars(child); |
|
261 int type; 262 int reg; 263 u_int32_t bar; | 283 int type; 284 int reg; 285 u_int32_t bar; |
264 u_int32_t len; 265 struct resource *res; | |
266 267 reg = *(u_int16_t*)tupledata; 268 len = *(u_int32_t*)(tupledata + 2); 269 if (reg & TPL_BAR_REG_AS) { 270 type = SYS_RES_IOPORT; 271 } else { 272 type = SYS_RES_MEMORY; 273 } 274 bar = (reg & TPL_BAR_REG_ASI_MASK) - 1; 275 if (bar < 0 || bar > 5 || 276 (type == SYS_RES_IOPORT && bar == 5)) { 277 device_printf(cbdev, "Invalid BAR number: %02x(%02x)\n", 278 reg, bar); 279 return 0; 280 } 281 bar = CARDBUS_BASE0_REG + bar * 4; | 286 287 reg = *(u_int16_t*)tupledata; 288 len = *(u_int32_t*)(tupledata + 2); 289 if (reg & TPL_BAR_REG_AS) { 290 type = SYS_RES_IOPORT; 291 } else { 292 type = SYS_RES_MEMORY; 293 } 294 bar = (reg & TPL_BAR_REG_ASI_MASK) - 1; 295 if (bar < 0 || bar > 5 || 296 (type == SYS_RES_IOPORT && bar == 5)) { 297 device_printf(cbdev, "Invalid BAR number: %02x(%02x)\n", 298 reg, bar); 299 return 0; 300 } 301 bar = CARDBUS_BASE0_REG + bar * 4; |
282 DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x\n", 283 (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len)); 284 res = bus_generic_alloc_resource(child, child, type, &bar, 0, 285 ~0, len, rman_make_alignment_flags(len) | RF_ACTIVE); 286 if (res == NULL) { 287 device_printf(cbdev, "Cannot allocate BAR %02x\n", bar); | 302 if (type == SYS_RES_MEMORY) { 303 if (bar & TPL_BAR_REG_PREFETCHABLE) 304 dinfo->mprefetchable |= BARBIT(bar); 305 if (bar & TPL_BAR_REG_BELOW1MB) 306 dinfo->mbelow1mb |= BARBIT(bar); 307 } else if (type == SYS_RES_IOPORT) { 308 if (bar & TPL_BAR_REG_BELOW1MB) 309 dinfo->ibelow1mb |= BARBIT(bar); |
288 } | 310 } |
311 DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, " 312 "len=%04x%s%s\n", 313 (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len, 314 (type==SYS_RES_MEMORY&&dinfo->mprefetchable&BARBIT(bar))? 315 " (Prefetchable)":"", 316 type==SYS_RES_MEMORY? 317 ((dinfo->mbelow1mb&BARBIT(bar))?" (Below 1Mb)":"") 318 :(dinfo->ibelow1mb&BARBIT(bar))?" (Below 1Mb)":"" 319 )); 320 321 resource_list_add(&dinfo->resources, type, bar, 0UL, ~0UL, len); |
|
289 } 290 return 0; 291} 292 293DECODE_PROTOTYPE(unhandled) 294{ 295 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len); 296 return -1; --- 5 unchanged lines hidden (view full) --- 302 return 0; 303} 304 305/* 306 * Functions to read the a tuple from the card 307 */ 308 309static int | 322 } 323 return 0; 324} 325 326DECODE_PROTOTYPE(unhandled) 327{ 328 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len); 329 return -1; --- 5 unchanged lines hidden (view full) --- 335 return 0; 336} 337 338/* 339 * Functions to read the a tuple from the card 340 */ 341 342static int |
310cardbus_read_tuple_conf(device_t cbdev, device_t child, u_int32_t *start, | 343cardbus_read_tuple_conf(device_t cbdev, device_t child, u_int32_t start, |
311 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata) 312{ 313 int i, j; 314 u_int32_t e; 315 u_int32_t loc; 316 | 344 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata) 345{ 346 int i, j; 347 u_int32_t e; 348 u_int32_t loc; 349 |
317 loc = CARDBUS_CIS_ADDR(*start) + *off; | 350 loc = start + *off; |
318 319 e = pci_read_config(child, loc - loc % 4, 4); 320 for (j = loc % 4; j > 0; j--) 321 e >>= 8; 322 *len = 0; 323 for (i = loc, j = -2; j < *len; j++, i++) { 324 if (i % 4 == 0) 325 e = pci_read_config(child, i, 4); --- 5 unchanged lines hidden (view full) --- 331 tupledata[j] = 0xff & e; 332 e >>= 8; 333 } 334 *off += *len + 2; 335 return 0; 336} 337 338static int | 351 352 e = pci_read_config(child, loc - loc % 4, 4); 353 for (j = loc % 4; j > 0; j--) 354 e >>= 8; 355 *len = 0; 356 for (i = loc, j = -2; j < *len; j++, i++) { 357 if (i % 4 == 0) 358 e = pci_read_config(child, i, 4); --- 5 unchanged lines hidden (view full) --- 364 tupledata[j] = 0xff & e; 365 e >>= 8; 366 } 367 *off += *len + 2; 368 return 0; 369} 370 371static int |
339cardbus_read_tuple_exrom(device_t cbdev, struct resource *mem, u_int32_t *start, | 372cardbus_read_tuple_mem(device_t cbdev, struct resource *res, u_int32_t start, |
340 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata) 341{ | 373 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata) 374{ |
342#define READROM(rom, type, offset) \ 343 (*((u_int ## type ##_t *)(((unsigned char*)rom) + offset))) | 375 bus_space_tag_t bt; 376 bus_space_handle_t bh; 377 int ret; |
344 | 378 |
345 int romnum = 0; 346 unsigned char *data; 347 u_int32_t imagesize; 348 unsigned char *image; 349 int imagenum; | 379 bt = rman_get_bustag(res); 380 bh = rman_get_bushandle(res); |
350 | 381 |
351 image = (unsigned char*)rman_get_virtual(mem); 352 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start); 353 do { 354 if (READROM(image, 16, CARDBUS_EXROM_SIGNATURE) != 0xaa55) { 355 device_printf(cbdev, "Bad header in rom %d: %04x\n", 356 romnum, *(u_int16_t*)(image + 357 CARDBUS_EXROM_SIGNATURE)); 358 return ENXIO; 359 } 360 data = image + READROM(image, 16, CARDBUS_EXROM_DATA_PTR); 361 imagesize = READROM(data, 16, CARDBUS_EXROM_DATA_IMAGE_LENGTH); 362 363 if (imagesize == 0) { 364 /* 365 * XXX some ROMs seem to have this as zero, 366 * can we assume this means 1 block? 367 */ 368 imagesize = 1; 369 } 370 imagesize <<= 9; 371 372 if (imagenum == romnum) { 373 image += CARDBUS_CIS_ADDR(*start) + *off; 374 *tupleid = image[0]; 375 *len = image[1]; 376 memcpy(tupledata, image+2, *len); 377 *off += *len+2; 378 return 0; 379 } 380 image += imagesize; 381 romnum++; 382 } while ((READROM(data, 8, CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0); 383 device_printf(cbdev, "Cannot read CIS: Not enough images of rom\n"); 384 return ENOENT; 385#undef READROM | 382 *tupleid = bus_space_read_1(bt, bh, start + *off); 383 *len = bus_space_read_1(bt, bh, start + *off + 1); 384 bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len); 385 ret = 0; 386 *off += *len + 2; 387 return ret; |
386} 387 388static int | 388} 389 390static int |
389cardbus_read_tuple_mem(device_t cbdev, device_t child, u_int32_t *start, 390 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata) | 391cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res, 392 u_int32_t start, u_int32_t *off, int *tupleid, int *len, 393 u_int8_t *tupledata) |
391{ | 394{ |
392 struct resource *mem; 393 bus_space_tag_t bt; 394 bus_space_handle_t bh; 395 int rid; 396 int ret; 397 398 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) { 399 rid = CARDBUS_ROM_REG; | 395 if (res == (struct resource*)~0UL) { 396 return cardbus_read_tuple_conf(cbdev, child, start, off, 397 tupleid, len, tupledata); |
400 } else { | 398 } else { |
401 rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4; | 399 return cardbus_read_tuple_mem(cbdev, res, start, off, 400 tupleid, len, tupledata); |
402 } | 401 } |
402} |
|
403 | 403 |
404 mem = bus_alloc_resource(child, SYS_RES_MEMORY, &rid, 0, ~0, 405 1, RF_ACTIVE); 406 bt = rman_get_bustag(mem); 407 bh = rman_get_bushandle(mem); 408 if (mem == NULL) { 409 device_printf(cbdev, "Failed to get memory for CIS reading\n"); 410 return ENOMEM; | 404static void 405cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid, 406 struct resource *res) 407{ 408 if (res != (struct resource*)~0UL) { 409 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); 410 pci_write_config(child, rid, 0, 4); 411 PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY); |
411 } | 412 } |
412 413 if(CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) { 414 ret = cardbus_read_tuple_exrom(cbdev, mem, start, off, tupleid, 415 len, tupledata); 416 } else { 417 *tupleid = bus_space_read_1(bt, bh, 418 CARDBUS_CIS_ADDR(*start) + *off); 419 *len = bus_space_read_1(bt, bh, 420 CARDBUS_CIS_ADDR(*start) + *off + 1); 421 bus_space_read_multi_1(rman_get_bustag(mem), 422 rman_get_bushandle(mem), 423 *off + CARDBUS_CIS_ADDR(*start), tupledata, *len); 424 ret = 0; 425 *off += *len+2; 426 } 427 bus_release_resource(child, SYS_RES_MEMORY, rid, mem); 428 return ret; | |
429} 430 | 413} 414 |
431static int 432cardbus_read_tuple(device_t cbdev, device_t child, u_int32_t *start, 433 u_int32_t *off, int *tupleid, int *len, u_int8_t *tupledata) | 415static struct resource * 416cardbus_read_tuple_init(device_t cbdev, device_t child, u_int32_t *start, 417 int *rid) |
434{ | 418{ |
435 switch(CARDBUS_CIS_SPACE(*start)) { | 419 u_int32_t testval; 420 u_int32_t size; 421 struct resource *res; 422 423 switch (CARDBUS_CIS_SPACE(*start)) { |
436 case CARDBUS_CIS_ASI_TUPLE: | 424 case CARDBUS_CIS_ASI_TUPLE: |
437 return cardbus_read_tuple_conf(cbdev, child, start, off, 438 tupleid, len, tupledata); | 425 /* CIS in tuple space need no initialization */ 426 return (struct resource*)~0UL; |
439 case CARDBUS_CIS_ASI_BAR0: 440 case CARDBUS_CIS_ASI_BAR1: 441 case CARDBUS_CIS_ASI_BAR2: 442 case CARDBUS_CIS_ASI_BAR3: 443 case CARDBUS_CIS_ASI_BAR4: 444 case CARDBUS_CIS_ASI_BAR5: | 427 case CARDBUS_CIS_ASI_BAR0: 428 case CARDBUS_CIS_ASI_BAR1: 429 case CARDBUS_CIS_ASI_BAR2: 430 case CARDBUS_CIS_ASI_BAR3: 431 case CARDBUS_CIS_ASI_BAR4: 432 case CARDBUS_CIS_ASI_BAR5: |
433 *rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4; 434 pci_write_config(child, *rid, ~0UL, 4); 435 break; |
|
445 case CARDBUS_CIS_ASI_ROM: | 436 case CARDBUS_CIS_ASI_ROM: |
446 return cardbus_read_tuple_mem(cbdev, child, start, off, 447 tupleid, len, tupledata); | 437 *rid = CARDBUS_ROM_REG; 438 pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4); 439 break; |
448 default: 449 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n", 450 CARDBUS_CIS_SPACE(*start)); | 440 default: 441 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n", 442 CARDBUS_CIS_SPACE(*start)); |
451 return EINVAL; | 443 return NULL; |
452 } | 444 } |
445 446 /* figure out how much space we need */ 447 testval = pci_read_config(child, *rid, 4); 448 if (testval & 1) { 449 device_printf(cbdev, "CIS Space is IO, expecting memory.\n"); 450 return NULL; 451 } 452 size = CARDBUS_MAPREG_MEM_SIZE(testval); 453 if (size < 4096) 454 size = 4096; 455 /* allocate the memory space to read CIS */ 456 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size, 457 rman_make_alignment_flags(size) | RF_ACTIVE); 458 if (res == NULL) { 459 device_printf(cbdev, "Unable to allocate resource " 460 "to read CIS.\n"); 461 return NULL; 462 } 463 pci_write_config(child, *rid, 464 rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)? 465 CARDBUS_ROM_ENABLE : 0), 466 4); 467 PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY); 468 469 /* Flip to the right ROM image if CIS is in ROM */ 470 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) { 471 bus_space_tag_t bt; 472 bus_space_handle_t bh; 473 int imagenum; 474 u_int32_t imagesize; 475 int mystart = 0; 476 int romnum = 0; 477 int dataptr; 478 479 bt = rman_get_bustag(res); 480 bh = rman_get_bushandle(res); 481 482 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start); 483 for (romnum = 0;; romnum++) { 484 if (bus_space_read_2(bt, bh, 485 mystart+CARDBUS_EXROM_SIGNATURE) != 0xaa55) { 486 device_printf(cbdev, "Bad header in rom %d: " 487 "[%x] %04x\n", romnum, mystart + 488 CARDBUS_EXROM_SIGNATURE, 489 bus_space_read_2(bt, bh, 490 mystart+CARDBUS_EXROM_SIGNATURE)); 491 bus_release_resource(cbdev, SYS_RES_MEMORY, 492 *rid, res); 493 *rid = 0; 494 return NULL; 495 } 496 dataptr = mystart + bus_space_read_2(bt, bh, 497 mystart + CARDBUS_EXROM_DATA_PTR); 498 imagesize = bus_space_read_2(bt, bh, 499 dataptr + CARDBUS_EXROM_DATA_IMAGE_LENGTH); 500 501 if (imagesize == 0) { 502 /* 503 * XXX some ROMs seem to have this as zero, 504 * can we assume this means 1 block? 505 */ 506 imagesize = 1; 507 } 508 imagesize <<= 9; 509 510 if (romnum == imagenum) 511 break; 512 if ((bus_space_read_1(bt, bh, mystart + 513 CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0) { 514 device_printf(cbdev, "Cannot read CIS: " 515 "Not enough images of rom\n"); 516 return NULL; 517 } 518 mystart += imagesize; 519 } 520 *start = mystart + CARDBUS_CIS_ADDR(*start); 521 } else { 522 *start = CARDBUS_CIS_SPACE(*start); 523 } 524 return res; |
|
453} 454 455/* 456 * Dispatch the right handler function per tuple 457 */ 458 459static int 460decode_tuple(device_t cbdev, device_t child, int tupleid, int len, | 525} 526 527/* 528 * Dispatch the right handler function per tuple 529 */ 530 531static int 532decode_tuple(device_t cbdev, device_t child, int tupleid, int len, |
461 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, | 533 u_int8_t *tupledata, u_int32_t start, u_int32_t *off, |
462 struct tuple_callbacks *callbacks) 463{ 464 int i; 465 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) { 466 if (tupleid == callbacks[i].id) 467 return callbacks[i].func(cbdev, child, tupleid, len, 468 tupledata, start, off, &callbacks[i]); 469 } --- 11 unchanged lines hidden (view full) --- 481cardbus_parse_cis(device_t cbdev, device_t child, 482 struct tuple_callbacks *callbacks) 483{ 484 u_int8_t tupledata[MAXTUPLESIZE]; 485 int tupleid; 486 int len; 487 int expect_linktarget; 488 u_int32_t start, off; | 534 struct tuple_callbacks *callbacks) 535{ 536 int i; 537 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) { 538 if (tupleid == callbacks[i].id) 539 return callbacks[i].func(cbdev, child, tupleid, len, 540 tupledata, start, off, &callbacks[i]); 541 } --- 11 unchanged lines hidden (view full) --- 553cardbus_parse_cis(device_t cbdev, device_t child, 554 struct tuple_callbacks *callbacks) 555{ 556 u_int8_t tupledata[MAXTUPLESIZE]; 557 int tupleid; 558 int len; 559 int expect_linktarget; 560 u_int32_t start, off; |
561 struct resource *res; 562 int rid; |
|
489 490 bzero(tupledata, MAXTUPLESIZE); 491 expect_linktarget = TRUE; 492 start = pci_read_config(child, CARDBUS_CIS_REG, 4); 493 off = 0; | 563 564 bzero(tupledata, MAXTUPLESIZE); 565 expect_linktarget = TRUE; 566 start = pci_read_config(child, CARDBUS_CIS_REG, 4); 567 off = 0; |
568 res = cardbus_read_tuple_init(cbdev, child, &start, &rid); 569 if (res == NULL) 570 return ENXIO; |
|
494 do { | 571 do { |
495 cardbus_read_tuple(cbdev, child, &start, &off, &tupleid, &len, 496 tupledata); | 572 if (0 != cardbus_read_tuple(cbdev, child, res, start, &off, 573 &tupleid, &len, tupledata)) { 574 device_printf(cbdev, "Failed to read CIS.\n"); 575 cardbus_read_tuple_finish(cbdev, child, rid, res); 576 return ENXIO; 577 } |
497 498 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) { 499 device_printf(cbdev, "Expecting link target, got 0x%x\n", 500 tupleid); | 578 579 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) { 580 device_printf(cbdev, "Expecting link target, got 0x%x\n", 581 tupleid); |
582 cardbus_read_tuple_finish(cbdev, child, rid, res); |
|
501 return EINVAL; 502 } 503 expect_linktarget = decode_tuple(cbdev, child, tupleid, len, | 583 return EINVAL; 584 } 585 expect_linktarget = decode_tuple(cbdev, child, tupleid, len, |
504 tupledata, &start, &off, 505 callbacks); 506 if (expect_linktarget != 0) | 586 tupledata, start, &off, callbacks); 587 if (expect_linktarget != 0) { 588 cardbus_read_tuple_finish(cbdev, child, rid, res); |
507 return expect_linktarget; | 589 return expect_linktarget; |
590 } |
|
508 } while (tupleid != CISTPL_END); | 591 } while (tupleid != CISTPL_END); |
592 cardbus_read_tuple_finish(cbdev, child, rid, res); |
|
509 return 0; 510} 511 | 593 return 0; 594} 595 |
596static int 597barsort(const void *a, const void *b) 598{ 599 return (*(const struct resource_list_entry **)b)->count - 600 (*(const struct resource_list_entry **)a)->count; 601} 602 603static int 604cardbus_alloc_resources(device_t cbdev, device_t child) 605{ 606 struct cardbus_devinfo *dinfo = device_get_ivars(child); 607 int count; 608 struct resource_list_entry *rle; 609 struct resource_list_entry **barlist; 610 int tmp; 611 u_int32_t mem_psize = 0, mem_nsize = 0, io_size = 0; 612 struct resource *res; 613 u_int32_t start,end; 614 int rid, flags; 615 616 count = 0; 617 SLIST_FOREACH(rle, &dinfo->resources, link) { 618 count++; 619 } 620 if (count == 0) 621 return 0; 622 barlist = malloc(sizeof(struct resource_list_entry*) * count, M_DEVBUF, 623 M_WAITOK); 624 count = 0; 625 SLIST_FOREACH(rle, &dinfo->resources, link) { 626 barlist[count] = rle; 627 if (rle->type == SYS_RES_IOPORT) { 628 io_size += rle->count; 629 } else if (rle->type == SYS_RES_MEMORY) { 630 if (dinfo->mprefetchable & BARBIT(rle->rid)) 631 mem_psize += rle->count; 632 else 633 mem_nsize += rle->count; 634 } 635 count++; 636 } 637 638 /* 639 * We want to allocate the largest resource first, so that our 640 * allocated memory is packed. 641 */ 642 qsort(barlist, count, sizeof(struct resource_list_entry*), barsort); 643 644 /* Allocate prefetchable memory */ 645 flags = 0; 646 for (tmp = 0; tmp < count; tmp++) { 647 if (barlist[tmp]->res == NULL && 648 barlist[tmp]->type == SYS_RES_MEMORY && 649 dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) { 650 flags = rman_make_alignment_flags(barlist[tmp]->count); 651 break; 652 } 653 } 654 if (flags > 0) { /* If any prefetchable memory is requested... */ 655 /* 656 * First we allocate one big space for all resources of this 657 * type. We do this because our parent, pccbb, needs to open 658 * a window to forward all addresses within the window, and 659 * it would be best if nobody else has resources allocated 660 * within the window. 661 * (XXX: Perhaps there might be a better way to do this?) 662 */ 663 rid = 0; 664 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0, 665 (dinfo->mprefetchable & dinfo->mbelow1mb)?0xFFFFF:~0UL, 666 mem_psize, flags); 667 start = rman_get_start(res); 668 end = rman_get_end(res); 669 DEVPRINTF((cbdev, "Prefetchable memory at %x-%x\n", start, end)); 670 /* 671 * Now that we know the region is free, release it and hand it 672 * out piece by piece. 673 */ 674 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); 675 for (tmp = 0; tmp < count; tmp++) { 676 if (barlist[tmp]->res == NULL && 677 barlist[tmp]->type == SYS_RES_MEMORY && 678 dinfo->mprefetchable & BARBIT(barlist[tmp]->rid)) { 679 barlist[tmp]->res = bus_alloc_resource(cbdev, 680 barlist[tmp]->type, 681 &barlist[tmp]->rid, start, end, 682 barlist[tmp]->count, 683 rman_make_alignment_flags( 684 barlist[tmp]->count)); 685 if (barlist[tmp]->res == NULL) { 686 mem_nsize += barlist[tmp]->count; 687 dinfo->mprefetchable &= 688 ~BARBIT(barlist[tmp]->rid); 689 DEVPRINTF((cbdev, "Cannot pre-allocate " 690 "prefetchable memory, will try as " 691 "non-prefetchable.\n")); 692 } else { 693 barlist[tmp]->start = 694 rman_get_start(barlist[tmp]->res); 695 barlist[tmp]->end = 696 rman_get_end(barlist[tmp]->res); 697 pci_write_config(child, 698 barlist[tmp]->rid, 699 barlist[tmp]->start, 4); 700 DEVPRINTF((cbdev, "Prefetchable memory " 701 "rid=%x at %lx-%lx\n", 702 barlist[tmp]->rid, 703 barlist[tmp]->start, 704 barlist[tmp]->end)); 705 } 706 } 707 } 708 } 709 710 /* Allocate non-prefetchable memory */ 711 flags = 0; 712 for (tmp = 0; tmp < count; tmp++) { 713 if (barlist[tmp]->res == NULL && 714 barlist[tmp]->type == SYS_RES_MEMORY) { 715 flags = rman_make_alignment_flags(barlist[tmp]->count); 716 break; 717 } 718 } 719 if (flags > 0) { /* If any non-prefetchable memory is requested... */ 720 /* 721 * First we allocate one big space for all resources of this 722 * type. We do this because our parent, pccbb, needs to open 723 * a window to forward all addresses within the window, and 724 * it would be best if nobody else has resources allocated 725 * within the window. 726 * (XXX: Perhaps there might be a better way to do this?) 727 */ 728 rid = 0; 729 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, &rid, 0, 730 ((~dinfo->mprefetchable) & dinfo->mbelow1mb)?0xFFFFF:~0UL, 731 mem_nsize, flags); 732 start = rman_get_start(res); 733 end = rman_get_end(res); 734 DEVPRINTF((cbdev, "Non-prefetchable memory at %x-%x\n", 735 start, end)); 736 /* 737 * Now that we know the region is free, release it and hand it 738 * out piece by piece. 739 */ 740 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); 741 for (tmp = 0; tmp < count; tmp++) { 742 if (barlist[tmp]->res == NULL && 743 barlist[tmp]->type == SYS_RES_MEMORY) { 744 barlist[tmp]->res = bus_alloc_resource(cbdev, 745 barlist[tmp]->type, &barlist[tmp]->rid, 746 start, end, barlist[tmp]->count, 747 rman_make_alignment_flags( 748 barlist[tmp]->count)); 749 if (barlist[tmp]->res == NULL) { 750 DEVPRINTF((cbdev, "Cannot pre-allocate " 751 "memory for cardbus device\n")); 752 return ENOMEM; 753 } 754 barlist[tmp]->start = 755 rman_get_start(barlist[tmp]->res); 756 barlist[tmp]->end = rman_get_end( 757 barlist[tmp]->res); 758 pci_write_config(child, barlist[tmp]->rid, 759 barlist[tmp]->start, 4); 760 DEVPRINTF((cbdev, "Non-prefetchable memory " 761 "rid=%x at %lx-%lx (%lx)\n", 762 barlist[tmp]->rid, barlist[tmp]->start, 763 barlist[tmp]->end, barlist[tmp]->count)); 764 } 765 } 766 } 767 768 /* Allocate IO ports */ 769 flags = 0; 770 for (tmp = 0; tmp < count; tmp++) { 771 if (barlist[tmp]->res == NULL && 772 barlist[tmp]->type == SYS_RES_IOPORT) { 773 flags = rman_make_alignment_flags(barlist[tmp]->count); 774 break; 775 } 776 } 777 if (flags > 0) { /* If any IO port is requested... */ 778 /* 779 * First we allocate one big space for all resources of this 780 * type. We do this because our parent, pccbb, needs to open 781 * a window to forward all addresses within the window, and 782 * it would be best if nobody else has resources allocated 783 * within the window. 784 * (XXX: Perhaps there might be a better way to do this?) 785 */ 786 rid = 0; 787 res = bus_alloc_resource(cbdev, SYS_RES_IOPORT, &rid, 0, 788 (dinfo->ibelow1mb)?0xFFFFF:~0UL, io_size, flags); 789 start = rman_get_start(res); 790 end = rman_get_end(res); 791 DEVPRINTF((cbdev, "IO port at %x-%x\n", start, end)); 792 /* 793 * Now that we know the region is free, release it and hand it 794 * out piece by piece. 795 */ 796 bus_release_resource(cbdev, SYS_RES_IOPORT, rid, res); 797 for (tmp = 0; tmp < count; tmp++) { 798 if (barlist[tmp]->res == NULL && 799 barlist[tmp]->type == SYS_RES_IOPORT) { 800 barlist[tmp]->res = bus_alloc_resource(cbdev, 801 barlist[tmp]->type, &barlist[tmp]->rid, 802 start, end, barlist[tmp]->count, 803 rman_make_alignment_flags( 804 barlist[tmp]->count)); 805 if (barlist[tmp]->res == NULL) { 806 DEVPRINTF((cbdev, "Cannot pre-allocate " 807 "IO port for cardbus device\n")); 808 return ENOMEM; 809 } 810 barlist[tmp]->start = 811 rman_get_start(barlist[tmp]->res); 812 barlist[tmp]->end = 813 rman_get_end(barlist[tmp]->res); 814 pci_write_config(child, barlist[tmp]->rid, 815 barlist[tmp]->start, 4); 816 DEVPRINTF((cbdev, "IO port rid=%x at %lx-%lx\n", 817 barlist[tmp]->rid, barlist[tmp]->start, 818 barlist[tmp]->end)); 819 } 820 } 821 } 822 823 /* Allocate IRQ */ 824 /* XXX: Search CIS for IRQ description */ 825 rid = 0; 826 res = bus_alloc_resource(cbdev, SYS_RES_IRQ, &rid, 0, ~0UL, 1, 827 RF_SHAREABLE); 828 resource_list_add(&dinfo->resources, SYS_RES_IRQ, rid, 829 rman_get_start(res), rman_get_end(res), 1); 830 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid); 831 rle->res = res; 832 dinfo->cfg.intline = rman_get_start(res); 833 pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1); 834 835 return 0; 836} 837 838/* 839 * Adding a memory/io resource (sans CIS) 840 */ 841 842static void 843cardbus_add_map(device_t cbdev, device_t child, int reg) 844{ 845 struct cardbus_devinfo *dinfo = device_get_ivars(child); 846 struct resource_list_entry *rle; 847 u_int32_t size; 848 u_int32_t testval; 849 int type; 850 851 SLIST_FOREACH(rle, &dinfo->resources, link) { 852 if (rle->rid == reg) 853 return; 854 } 855 856 if (reg == CARDBUS_ROM_REG) 857 testval = CARDBUS_ROM_ADDRMASK; 858 else 859 testval = ~0; 860 861 pci_write_config(child, reg, testval, 4); 862 testval = pci_read_config(child, reg, 4); 863 864 if (testval == ~0 || testval == 0) 865 return; 866 867 if ((testval & 1) == 0) 868 type = SYS_RES_MEMORY; 869 else 870 type = SYS_RES_IOPORT; 871 872 size = CARDBUS_MAPREG_MEM_SIZE(testval); 873 device_printf(cbdev, "Resource not specified in CIS: id=%x, size=%x\n", 874 reg, size); 875 resource_list_add(&dinfo->resources, type, reg, 0UL, ~0UL, size); 876} 877 878static void 879cardbus_pickup_maps(device_t cbdev, device_t child) 880{ 881 struct cardbus_devinfo *dinfo = device_get_ivars(child); 882 struct cardbus_quirk *q; 883 int reg; 884 885 /* 886 * Try to pick up any resources that was not specified in CIS. 887 * Some devices (eg, 3c656) does not list all resources required by 888 * the driver in its CIS. 889 * XXX: should we do this or use quirks? 890 */ 891 for (reg = 0; reg < dinfo->cfg.nummaps; reg++) { 892 cardbus_add_map(cbdev, child, PCIR_MAPS + reg * 4); 893 } 894 895 for (q = &cardbus_quirks[0]; q->devid; q++) { 896 if (q->devid == ((dinfo->cfg.device << 16) | dinfo->cfg.vendor) 897 && q->type == CARDBUS_QUIRK_MAP_REG) { 898 cardbus_add_map(cbdev, child, q->arg1); 899 } 900 } 901} 902 |
|
512int 513cardbus_cis_read(device_t cbdev, device_t child, u_int8_t id, 514 struct cis_tupleinfo **buff, int *nret) 515{ 516 struct tuple_callbacks cisread_callbacks[] = { 517 MAKETUPLE(NULL, nothing), 518 /* first entry will be overwritten */ 519 MAKETUPLE(NULL, nothing), --- 46 unchanged lines hidden (view full) --- 566 ret = cardbus_parse_cis(cbdev, child, cisread_callbacks); 567 568 *buff = cisread_buf; 569 *nret = ncisread_buf; 570 return ret; 571} 572 573void | 903int 904cardbus_cis_read(device_t cbdev, device_t child, u_int8_t id, 905 struct cis_tupleinfo **buff, int *nret) 906{ 907 struct tuple_callbacks cisread_callbacks[] = { 908 MAKETUPLE(NULL, nothing), 909 /* first entry will be overwritten */ 910 MAKETUPLE(NULL, nothing), --- 46 unchanged lines hidden (view full) --- 957 ret = cardbus_parse_cis(cbdev, child, cisread_callbacks); 958 959 *buff = cisread_buf; 960 *nret = ncisread_buf; 961 return ret; 962} 963 964void |
574cardbus_cis_free(device_t cbdev, struct cis_tupleinfo *buff, int* nret) | 965cardbus_cis_free(device_t cbdev, struct cis_tupleinfo *buff, int *nret) |
575{ 576 int i; 577 for (i = 0; i < *nret; i++) 578 free(buff[i].data, M_DEVBUF); 579 if (*nret > 0) 580 free(buff, M_DEVBUF); 581} 582 583int 584cardbus_do_cis(device_t cbdev, device_t child) 585{ | 966{ 967 int i; 968 for (i = 0; i < *nret; i++) 969 free(buff[i].data, M_DEVBUF); 970 if (*nret > 0) 971 free(buff, M_DEVBUF); 972} 973 974int 975cardbus_do_cis(device_t cbdev, device_t child) 976{ |
977 int ret; |
|
586 struct tuple_callbacks init_callbacks[] = { 587 MAKETUPLE(NULL, generic), 588 MAKETUPLE(DEVICE, generic), 589 MAKETUPLE(LONG_LINK_CB, unhandled), 590 MAKETUPLE(INDIRECT, unhandled), 591 MAKETUPLE(CONFIG_CB, generic), 592 MAKETUPLE(CFTABLE_ENTRY_CB, generic), 593 MAKETUPLE(LONGLINK_MFC, unhandled), --- 25 unchanged lines hidden (view full) --- 619 MAKETUPLE(GEOMETRY, generic), 620 MAKETUPLE(BYTEORDER, generic), 621 MAKETUPLE(DATE, generic), 622 MAKETUPLE(BATTERY, generic), 623 MAKETUPLE(ORG, generic), 624 MAKETUPLE(END, end), 625 MAKETUPLE(GENERIC, generic), 626 }; | 978 struct tuple_callbacks init_callbacks[] = { 979 MAKETUPLE(NULL, generic), 980 MAKETUPLE(DEVICE, generic), 981 MAKETUPLE(LONG_LINK_CB, unhandled), 982 MAKETUPLE(INDIRECT, unhandled), 983 MAKETUPLE(CONFIG_CB, generic), 984 MAKETUPLE(CFTABLE_ENTRY_CB, generic), 985 MAKETUPLE(LONGLINK_MFC, unhandled), --- 25 unchanged lines hidden (view full) --- 1011 MAKETUPLE(GEOMETRY, generic), 1012 MAKETUPLE(BYTEORDER, generic), 1013 MAKETUPLE(DATE, generic), 1014 MAKETUPLE(BATTERY, generic), 1015 MAKETUPLE(ORG, generic), 1016 MAKETUPLE(END, end), 1017 MAKETUPLE(GENERIC, generic), 1018 }; |
627 return cardbus_parse_cis(cbdev, child, init_callbacks); | 1019 1020 ret = cardbus_parse_cis(cbdev, child, init_callbacks); 1021 if (ret < 0) 1022 return ret; 1023 cardbus_pickup_maps(cbdev, child); 1024 return cardbus_alloc_resources(cbdev, child); |
628} | 1025} |