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 #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 <pci/pcivar.h> 48 49 #include <dev/cardbus/cardbusreg.h> 50 #include <dev/cardbus/cardbus_cis.h> 51 52 #include "card_if.h" 53 54 #if defined CARDBUS_DEBUG 55 #define STATIC 56 #define DPRINTF(a) printf a 57 #define DEVPRINTF(x) device_printf x 58 #else 59 #define STATIC static 60 #define DPRINTF(a) 61 #define DEVPRINTF(x) 62 #endif 63 64 #if !defined(lint) 65 static const char rcsid[] = 66 "$FreeBSD$"; 67 #endif 68 69 struct tuple_callbacks; 70 71 static int cardbus_read_tuple_conf(device_t dev, device_t child, 72 u_int32_t *start, u_int32_t *off, 73 int *tupleid, int *len, u_int8_t *tupledata); 74 static int cardbus_read_tuple_exrom(device_t dev, struct resource *mem, 75 u_int32_t *start, u_int32_t *off, 76 int *tupleid, int *len, u_int8_t *tupledata); 77 static int cardbus_read_tuple_mem(device_t dev, device_t child, u_int32_t *start, 78 u_int32_t *off, int *tupleid, int *len, 79 u_int8_t *tupledata); 80 static int cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start, 81 u_int32_t *off, int *tupleid, int *len, 82 u_int8_t *tupledata); 83 static int decode_tuple(device_t dev, device_t child, int tupleid, int len, 84 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, 85 struct tuple_callbacks *callbacks); 86 static int cardbus_parse_cis(device_t dev, device_t child, 87 struct tuple_callbacks *callbacks); 88 89 #define DECODE_PARAMS \ 90 (device_t dev, device_t child, int id, int len, \ 91 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, \ 92 struct tuple_callbacks *info) 93 #define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME DECODE_PARAMS 94 DECODE_PROTOTYPE(generic); 95 DECODE_PROTOTYPE(nothing); 96 DECODE_PROTOTYPE(copy); 97 DECODE_PROTOTYPE(bar); 98 DECODE_PROTOTYPE(linktarget); 99 DECODE_PROTOTYPE(vers_1); 100 DECODE_PROTOTYPE(manfid); 101 DECODE_PROTOTYPE(funcid); 102 DECODE_PROTOTYPE(funce); 103 DECODE_PROTOTYPE(end); 104 DECODE_PROTOTYPE(unhandled); 105 106 struct tuple_callbacks { 107 int id; 108 char* name; 109 int (*func) DECODE_PARAMS; 110 }; 111 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 112 113 static char* funcnames[] = { 114 "Multi-Functioned", 115 "Memory", 116 "Serial Port", 117 "Parallel Port", 118 "Fixed Disk", 119 "Video Adaptor", 120 "Network Adaptor", 121 "AIMS", 122 "SCSI", 123 "Security" 124 }; 125 126 static struct cis_tupleinfo* cisread_buf; 127 static int ncisread_buf; 128 129 DECODE_PROTOTYPE(generic) 130 { 131 #ifdef CARDBUS_DEBUG 132 int i; 133 134 if (info) 135 printf ("TUPLE: %s [%d]:", info->name, len); 136 else 137 printf ("TUPLE: Unknown(0x%02x) [%d]:", id, len); 138 139 for (i = 0; i < len; i++) { 140 if (i % 0x10 == 0 && len > 0x10) 141 printf ("\n 0x%02x:", i); 142 printf (" %02x", tupledata[i]); 143 } 144 printf ("\n"); 145 #endif 146 return 0; 147 } 148 149 DECODE_PROTOTYPE(nothing) 150 { 151 return 0; 152 } 153 154 DECODE_PROTOTYPE(copy) 155 { 156 struct cis_tupleinfo* tmpbuf; 157 158 tmpbuf = malloc(sizeof(struct cis_tupleinfo)*(ncisread_buf+1), 159 M_DEVBUF, M_WAITOK); 160 if (ncisread_buf > 0) { 161 memcpy(tmpbuf, cisread_buf, 162 sizeof(struct cis_tupleinfo)*ncisread_buf); 163 free(cisread_buf, M_DEVBUF); 164 } 165 cisread_buf = tmpbuf; 166 167 cisread_buf[ncisread_buf].id = id; 168 cisread_buf[ncisread_buf].len = len; 169 cisread_buf[ncisread_buf].data = malloc(len, M_DEVBUF, M_WAITOK); 170 memcpy (cisread_buf[ncisread_buf].data, tupledata, len); 171 ncisread_buf++; 172 return 0; 173 } 174 175 DECODE_PROTOTYPE(linktarget) 176 { 177 #ifdef CARDBUS_DEBUG 178 int i; 179 180 printf ("TUPLE: %s [%d]:", info->name, len); 181 182 for (i = 0; i < len; i++) { 183 if (i % 0x10 == 0 && len > 0x10) 184 printf ("\n 0x%02x:", i); 185 printf (" %02x", tupledata[i]); 186 } 187 printf ("\n"); 188 #endif 189 if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' || 190 tupledata[2] != 'S') { 191 printf("Invalid data for CIS Link Target!\n"); 192 decode_tuple_generic(dev, child, id, len, tupledata, 193 start, off, info); 194 return EINVAL; 195 } 196 return 0; 197 } 198 199 DECODE_PROTOTYPE(vers_1) 200 { 201 int i; 202 printf("Product version: %d.%d\n", tupledata[0], tupledata[1]); 203 printf("Product name: "); 204 for (i = 2; i < len; i++) { 205 if (tupledata[i] == '\0') 206 printf (" | "); 207 else if (tupledata[i] == 0xff) 208 break; 209 else 210 printf("%c", tupledata[i]); 211 } 212 printf("\n"); 213 return 0; 214 } 215 216 DECODE_PROTOTYPE(funcid) 217 { 218 int i; 219 int numnames = sizeof(funcnames)/sizeof(funcnames[0]); 220 221 printf("Functions: "); 222 for(i = 0; i < len; i++) { 223 if (tupledata[i] < numnames) 224 printf ("%s", funcnames[tupledata[i]]); 225 else 226 printf ("Unknown(%d)", tupledata[i]); 227 if (i < len-1) printf(", "); 228 } 229 printf ("\n"); 230 return 0; 231 } 232 233 DECODE_PROTOTYPE(manfid) 234 { 235 int i; 236 printf ("Manufacturer ID: "); 237 for (i = 0; i < len; i++) 238 printf("%02x", tupledata[i]); 239 printf("\n"); 240 return 0; 241 } 242 243 DECODE_PROTOTYPE(funce) 244 { 245 int i; 246 printf ("Function Extension: "); 247 for (i = 0; i < len; i++) 248 printf("%02x", tupledata[i]); 249 printf("\n"); 250 return 0; 251 } 252 253 DECODE_PROTOTYPE(bar) 254 { 255 if (len != 6) { 256 printf ("*** ERROR *** BAR length not 6 (%d)\n", len); 257 return EINVAL; 258 } else { 259 int type; 260 int reg; 261 u_int32_t bar; 262 u_int32_t len; 263 struct resource *res; 264 265 reg = *(u_int16_t*)tupledata; 266 len = *(u_int32_t*)(tupledata+2); 267 if (reg & TPL_BAR_REG_AS) { 268 type = SYS_RES_IOPORT; 269 } else { 270 type = SYS_RES_MEMORY; 271 } 272 bar = (reg & TPL_BAR_REG_ASI_MASK) - 1; 273 if (bar < 0 || bar > 5 || (type == SYS_RES_IOPORT && bar == 5)) { 274 device_printf(dev, "Invalid BAR number: %02x(%02x)\n", 275 reg, bar); 276 return 0; 277 } 278 bar = CARDBUS_BASE0_REG + bar * 4; 279 DEVPRINTF((dev, "Opening BAR: type=%s, bar=%02x, len=%04x\n", 280 (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len)); 281 res = bus_generic_alloc_resource(child, child, type, &bar, 0, 282 ~0, len, rman_make_alignment_flags(len) | RF_ACTIVE); 283 if (res == NULL) { 284 device_printf(dev, "Cannot allocate BAR %02x\n", bar); 285 } 286 } 287 return 0; 288 } 289 290 DECODE_PROTOTYPE(unhandled) 291 { 292 printf ("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len); 293 return -1; 294 } 295 296 DECODE_PROTOTYPE(end) 297 { 298 printf("CIS reading done\n"); 299 return 0; 300 } 301 302 static int 303 cardbus_read_tuple_conf(device_t dev, device_t child, u_int32_t *start, 304 u_int32_t *off, int *tupleid, int *len, 305 u_int8_t *tupledata) 306 { 307 int i, j; 308 u_int32_t e; 309 u_int32_t loc; 310 311 loc = CARDBUS_CIS_ADDR(*start) + *off; 312 313 e = pci_read_config(child, loc - loc%4, 4); 314 for (j = loc % 4; j>0; j--) 315 e >>= 8; 316 *len = 0; 317 for (i = loc, j = -2; j < *len; j++, i++) { 318 if (i % 4 == 0) 319 e = pci_read_config(child, i, 4); 320 if (j == -2) 321 *tupleid = 0xff & e; 322 else if (j == -1) 323 *len = 0xff & e; 324 else 325 tupledata[j] = 0xff & e; 326 e >>= 8; 327 } 328 *off += *len+2; 329 return 0; 330 } 331 332 333 static int 334 cardbus_read_tuple_exrom(device_t dev, struct resource *mem, u_int32_t *start, 335 u_int32_t *off, int *tupleid, int *len, 336 u_int8_t *tupledata) 337 { 338 #define READROM(rom, type, offset) \ 339 (*((u_int ## type ##_t *)(((unsigned char*)rom) + offset))) 340 341 int romnum = 0; 342 unsigned char *data; 343 u_int32_t imagesize; 344 unsigned char *image; 345 int imagenum; 346 347 image = (unsigned char*)rman_get_virtual(mem); 348 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start); 349 do { 350 if (READROM(image, 16, CARDBUS_EXROM_SIGNATURE) != 0xaa55) { 351 device_printf (dev, "Bad header in rom %d: %04x\n", 352 romnum, *(u_int16_t*)(image + 353 CARDBUS_EXROM_SIGNATURE)); 354 return ENXIO; 355 } 356 data = image + READROM(image, 16, CARDBUS_EXROM_DATA_PTR); 357 imagesize = READROM(data, 16, CARDBUS_EXROM_DATA_IMAGE_LENGTH); 358 359 if (imagesize == 0) { 360 /* 361 * XXX some ROMs seem to have this as zero, 362 * can we assume this means 1 block? 363 */ 364 imagesize = 1; 365 } 366 imagesize <<= 9; 367 368 if (imagenum == romnum) { 369 image += CARDBUS_CIS_ADDR(*start) + *off; 370 *tupleid = image[0]; 371 *len = image[1]; 372 memcpy(tupledata, image+2, *len); 373 *off += *len+2; 374 return 0; 375 } 376 image += imagesize; 377 romnum++; 378 } while ((READROM(data, 8, CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0); 379 device_printf(dev, "Cannot read CIS: Not enough images of rom\n"); 380 return ENOENT; 381 #undef READROM 382 } 383 384 static int 385 cardbus_read_tuple_mem(device_t dev, device_t child, u_int32_t *start, 386 u_int32_t *off, int *tupleid, int *len, 387 u_int8_t *tupledata) 388 { 389 struct resource *mem; 390 int rid; 391 int ret; 392 393 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) { 394 rid = CARDBUS_ROM_REG; 395 } else { 396 rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4; 397 } 398 399 mem = bus_alloc_resource(child, SYS_RES_MEMORY, &rid, 0, ~0, 400 1, RF_ACTIVE); 401 if (mem == NULL) { 402 device_printf(dev, "Failed to get memory for CIS reading\n"); 403 return ENOMEM; 404 } 405 406 if(CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) { 407 ret = cardbus_read_tuple_exrom(dev, mem, start, off, tupleid, 408 len, tupledata); 409 } else { 410 /* XXX byte order? */ 411 unsigned char* ptr; 412 ptr = (unsigned char*)rman_get_virtual(mem) 413 + CARDBUS_CIS_ADDR(*start) + *off; 414 *tupleid = ptr[0]; 415 *len = ptr[1]; 416 memcpy(tupledata, ptr+2, *len); 417 ret = 0; 418 *off += *len+2; 419 } 420 bus_release_resource(child, SYS_RES_MEMORY, rid, mem); 421 return ret; 422 } 423 424 static int 425 cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start, 426 u_int32_t *off, int *tupleid, int *len, 427 u_int8_t *tupledata) 428 { 429 switch(CARDBUS_CIS_SPACE(*start)) { 430 case CARDBUS_CIS_ASI_TUPLE: 431 return cardbus_read_tuple_conf(dev, child, start, off, 432 tupleid, len, tupledata); 433 case CARDBUS_CIS_ASI_BAR0: 434 case CARDBUS_CIS_ASI_BAR1: 435 case CARDBUS_CIS_ASI_BAR2: 436 case CARDBUS_CIS_ASI_BAR3: 437 case CARDBUS_CIS_ASI_BAR4: 438 case CARDBUS_CIS_ASI_BAR5: 439 case CARDBUS_CIS_ASI_ROM: 440 return cardbus_read_tuple_mem(dev, child, start, off, 441 tupleid, len, tupledata); 442 default: 443 device_printf(dev, "Unable to read CIS: Unknown space: %d\n", 444 CARDBUS_CIS_SPACE(*start)); 445 return EINVAL; 446 } 447 } 448 449 static int 450 decode_tuple(device_t dev, device_t child, int tupleid, int len, 451 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, 452 struct tuple_callbacks *callbacks) 453 { 454 int i; 455 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) { 456 if (tupleid == callbacks[i].id) 457 return callbacks[i].func(dev, child, tupleid, len, 458 tupledata, start, off, 459 &callbacks[i]); 460 } 461 462 if (tupleid < CISTPL_CUSTOMSTART) { 463 device_printf(dev, "Undefined tuple encountered, CIS parsing terminated\n"); 464 return EINVAL; 465 } 466 return callbacks[i].func(dev, child, tupleid, len, 467 tupledata, start, off, 468 NULL); 469 } 470 471 static int 472 cardbus_parse_cis(device_t dev, device_t child, 473 struct tuple_callbacks *callbacks) 474 { 475 u_int8_t tupledata[MAXTUPLESIZE]; 476 int tupleid; 477 int len; 478 int expect_linktarget; 479 u_int32_t start, off; 480 481 bzero(tupledata, MAXTUPLESIZE); 482 expect_linktarget = TRUE; 483 start = pci_read_config(child, CARDBUS_CIS_REG, 4); 484 off = 0; 485 do { 486 cardbus_read_tuple(dev, child, &start, &off, &tupleid, &len, 487 tupledata); 488 489 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) { 490 device_printf(dev, "Expecting link target, got 0x%x\n", 491 tupleid); 492 return EINVAL; 493 } 494 expect_linktarget = decode_tuple(dev, child, tupleid, len, 495 tupledata, &start, &off, 496 callbacks); 497 if (expect_linktarget != 0) 498 return expect_linktarget; 499 } while (tupleid != CISTPL_END); 500 return 0; 501 } 502 503 int 504 cardbus_cis_read(device_t dev, device_t child, u_int8_t id, 505 struct cis_tupleinfo** buff, int* nret) 506 { 507 struct tuple_callbacks cisread_callbacks[] = { 508 MAKETUPLE(NULL, nothing), 509 /* first entry will be overwritten */ 510 MAKETUPLE(NULL, nothing), 511 MAKETUPLE(DEVICE, nothing), 512 MAKETUPLE(LONG_LINK_CB, unhandled), 513 MAKETUPLE(INDIRECT, unhandled), 514 MAKETUPLE(CONFIG_CB, nothing), 515 MAKETUPLE(CFTABLE_ENTRY_CB, nothing), 516 MAKETUPLE(LONGLINK_MFC, unhandled), 517 MAKETUPLE(BAR, nothing), 518 MAKETUPLE(PWR_MGMNT, nothing), 519 MAKETUPLE(EXTDEVICE, nothing), 520 MAKETUPLE(CHECKSUM, nothing), 521 MAKETUPLE(LONGLINK_A, unhandled), 522 MAKETUPLE(LONGLINK_C, unhandled), 523 MAKETUPLE(LINKTARGET, nothing), 524 MAKETUPLE(NO_LINK, nothing), 525 MAKETUPLE(VERS_1, nothing), 526 MAKETUPLE(ALTSTR, nothing), 527 MAKETUPLE(DEVICE_A, nothing), 528 MAKETUPLE(JEDEC_C, nothing), 529 MAKETUPLE(JEDEC_A, nothing), 530 MAKETUPLE(CONFIG, nothing), 531 MAKETUPLE(CFTABLE_ENTRY, nothing), 532 MAKETUPLE(DEVICE_OC, nothing), 533 MAKETUPLE(DEVICE_OA, nothing), 534 MAKETUPLE(DEVICE_GEO, nothing), 535 MAKETUPLE(DEVICE_GEO_A, nothing), 536 MAKETUPLE(MANFID, nothing), 537 MAKETUPLE(FUNCID, nothing), 538 MAKETUPLE(FUNCE, nothing), 539 MAKETUPLE(SWIL, nothing), 540 MAKETUPLE(VERS_2, nothing), 541 MAKETUPLE(FORMAT, nothing), 542 MAKETUPLE(GEOMETRY, nothing), 543 MAKETUPLE(BYTEORDER, nothing), 544 MAKETUPLE(DATE, nothing), 545 MAKETUPLE(BATTERY, nothing), 546 MAKETUPLE(ORG, nothing), 547 MAKETUPLE(END, end), 548 MAKETUPLE(GENERIC, nothing), 549 }; 550 int ret; 551 552 cisread_callbacks[0].id = id; 553 cisread_callbacks[0].name = "COPY"; 554 cisread_callbacks[0].func = decode_tuple_copy; 555 ncisread_buf = 0; 556 cisread_buf = NULL; 557 ret = cardbus_parse_cis(dev, child, cisread_callbacks); 558 559 *buff = cisread_buf; 560 *nret = ncisread_buf; 561 return ret; 562 } 563 564 void 565 cardbus_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret) 566 { 567 int i; 568 for (i = 0; i < *nret; i++) 569 free(buff[i].data, M_DEVBUF); 570 if (*nret > 0) 571 free(buff, M_DEVBUF); 572 } 573 574 int 575 cardbus_do_cis(device_t dev, device_t child) 576 { 577 struct tuple_callbacks init_callbacks[] = { 578 MAKETUPLE(NULL, generic), 579 MAKETUPLE(DEVICE, generic), 580 MAKETUPLE(LONG_LINK_CB, unhandled), 581 MAKETUPLE(INDIRECT, unhandled), 582 MAKETUPLE(CONFIG_CB, generic), 583 MAKETUPLE(CFTABLE_ENTRY_CB, generic), 584 MAKETUPLE(LONGLINK_MFC, unhandled), 585 MAKETUPLE(BAR, bar), 586 MAKETUPLE(PWR_MGMNT, generic), 587 MAKETUPLE(EXTDEVICE, generic), 588 MAKETUPLE(CHECKSUM, generic), 589 MAKETUPLE(LONGLINK_A, unhandled), 590 MAKETUPLE(LONGLINK_C, unhandled), 591 MAKETUPLE(LINKTARGET, linktarget), 592 MAKETUPLE(NO_LINK, generic), 593 MAKETUPLE(VERS_1, vers_1), 594 MAKETUPLE(ALTSTR, generic), 595 MAKETUPLE(DEVICE_A, generic), 596 MAKETUPLE(JEDEC_C, generic), 597 MAKETUPLE(JEDEC_A, generic), 598 MAKETUPLE(CONFIG, generic), 599 MAKETUPLE(CFTABLE_ENTRY, generic), 600 MAKETUPLE(DEVICE_OC, generic), 601 MAKETUPLE(DEVICE_OA, generic), 602 MAKETUPLE(DEVICE_GEO, generic), 603 MAKETUPLE(DEVICE_GEO_A, generic), 604 MAKETUPLE(MANFID, manfid), 605 MAKETUPLE(FUNCID, funcid), 606 MAKETUPLE(FUNCE, funce), 607 MAKETUPLE(SWIL, generic), 608 MAKETUPLE(VERS_2, generic), 609 MAKETUPLE(FORMAT, generic), 610 MAKETUPLE(GEOMETRY, generic), 611 MAKETUPLE(BYTEORDER, generic), 612 MAKETUPLE(DATE, generic), 613 MAKETUPLE(BATTERY, generic), 614 MAKETUPLE(ORG, generic), 615 MAKETUPLE(END, end), 616 MAKETUPLE(GENERIC, generic), 617 }; 618 return cardbus_parse_cis(dev, child, init_callbacks); 619 } 620