1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2021 Oxide Computer Company 14 */ 15 16 /* 17 * This file contains logic to walk and print a large chunk of configuration 18 * space and many of the capabilities. There are multiple sub-commands that 19 * vector into the same logic (e.g. 'save-cfgspace' and 'show-cfgspace'). In 20 * general, there are a few major goals with this bit of code: 21 * 22 * o Every field should strive to be parsable and therefore selectable for 23 * output. This drove the idea that every field has both a short name and a 24 * human name. The short name is a dot-delineated name. When in parsable 25 * mode, the name will always refer to a single field. However, for 26 * convenience for humans, when not trying to be parsable, we show the 27 * parents in the tree. That is if you specify something like 28 * 'pcie.linkcap.maxspeed', in parsable mode you'll only get that; however, 29 * in non-parsable mode, you'll get an indication of the capability and 30 * register that field was in. 31 * 32 * o Related to the above, parsable mode always outputs a raw, uninterpreted 33 * value. This was done on purpose. Some fields require interpreting multiple 34 * registers to have meaning and long strings aren't always the most useful. 35 * 36 * o Every field isn't always pretty printed. This was generally just a 37 * decision based upon the field itself and how much work it'd be to fit it 38 * into the framework we have. In general, the ones we're mostly guilty of 39 * doing this with are related to cases where there's a scaling value in a 40 * subsequent register. If you find yourself wanting this, feel free to add 41 * it. 42 * 43 * o Currently designated vendor-specific capabilities aren't included here (or 44 * any specific vendor-specific capabilities for that matter). If they are 45 * added, they should follow the same angle of using a name to represent a 46 * sub-capability as we did with HyperTransport. 47 */ 48 49 #include <err.h> 50 #include <strings.h> 51 #include <sys/sysmacros.h> 52 #include <sys/pci.h> 53 #include <sys/pcie.h> 54 #include <sys/debug.h> 55 #include <ofmt.h> 56 #include <sys/types.h> 57 #include <sys/stat.h> 58 #include <fcntl.h> 59 #include <unistd.h> 60 61 #include "pcieadm.h" 62 63 typedef enum pcieadm_cfgspace_op { 64 PCIEADM_CFGSPACE_OP_PRINT, 65 PCIEADM_CFGSPACE_OP_WRITE 66 } pcieadm_cfgspace_op_t; 67 68 typedef enum piceadm_cfgspace_flag { 69 PCIEADM_CFGSPACE_F_PARSE = 1 << 0, 70 PCIEADM_CFGSPACE_F_SHORT = 1 << 1, 71 } pcieadm_cfgspace_flags_t; 72 73 typedef enum pcieadm_cfgspace_otype { 74 PCIEADM_CFGSPACE_OT_SHORT, 75 PCIEADM_CFGSPACE_OT_HUMAN, 76 PCIEADM_CFGSPACE_OT_VALUE 77 } pcieadm_cfgsapce_otype_t; 78 79 typedef struct pcieadm_cfgspace_ofmt { 80 const char *pco_base; 81 const char *pco_short; 82 const char *pco_human; 83 uint64_t pco_value; 84 const char *pco_strval; 85 } pcieadm_cfgspace_ofmt_t; 86 87 typedef enum pcieadm_regdef_val { 88 PRDV_STRVAL, 89 PRDV_BITFIELD, 90 PRDV_HEX 91 } pcieadm_regdef_val_t; 92 93 typedef struct pcieadm_regdef_addend { 94 uint8_t pra_shift; 95 int64_t pra_addend; 96 } pcieadm_regdef_addend_t; 97 98 typedef struct pcieadm_regdef { 99 uint8_t prd_lowbit; 100 uint8_t prd_hibit; 101 const char *prd_short; 102 const char *prd_human; 103 pcieadm_regdef_val_t prd_valtype; 104 union { 105 /* 106 * Enough space for up to an 8-bit fields worth of values 107 * (though we expect most to be sparse). 108 */ 109 const char *prdv_strval[128]; 110 pcieadm_regdef_addend_t prdv_hex; 111 } prd_val; 112 } pcieadm_regdef_t; 113 114 typedef struct pcieadm_unitdef { 115 const char *pcd_unit; 116 uint32_t pcd_mult; 117 } pcieadm_unitdef_t; 118 119 typedef struct pcieadm_strmap { 120 const char *psr_str; 121 uint64_t psr_val; 122 } pcieadm_strmap_t; 123 124 typedef struct pcieadm_cfgspace_filter { 125 const char *pcf_string; 126 size_t pcf_len; 127 boolean_t pcf_used; 128 } pcieadm_cfgspace_filter_t; 129 130 typedef struct pcieadm_strfilt { 131 struct pcieadm_strfilt *pstr_next; 132 const char *pstr_str; 133 char pstr_curgen[256]; 134 } pcieadm_strfilt_t; 135 136 /* 137 * Data is sized to be large enough that we can hold all of PCIe extended 138 * configuration space. 139 */ 140 typedef union pcieadm_cfgspace_data { 141 uint8_t pcb_u8[PCIE_CONF_HDR_SIZE]; 142 uint32_t pcb_u32[PCIE_CONF_HDR_SIZE / 4]; 143 } pcieadm_cfgspace_data_t; 144 145 typedef struct pcieadm_cfgspace_walk { 146 pcieadm_t *pcw_pcieadm; 147 pcieadm_cfgspace_op_t pcw_op; 148 uint32_t pcw_valid; 149 pcieadm_cfgspace_data_t *pcw_data; 150 uint16_t pcw_capoff; 151 uint32_t pcw_caplen; 152 int pcw_outfd; 153 uint_t pcw_dtype; 154 uint_t pcw_nlanes; 155 uint_t pcw_pcietype; 156 uint_t pcw_nfilters; 157 pcieadm_cfgspace_filter_t *pcw_filters; 158 pcieadm_cfgspace_flags_t pcw_flags; 159 ofmt_handle_t pcw_ofmt; 160 pcieadm_strfilt_t *pcw_filt; 161 } pcieadm_cfgspace_walk_t; 162 163 void 164 pcieadm_strfilt_pop(pcieadm_cfgspace_walk_t *walkp) 165 { 166 pcieadm_strfilt_t *filt; 167 168 VERIFY3P(walkp->pcw_filt, !=, NULL); 169 filt = walkp->pcw_filt; 170 walkp->pcw_filt = filt->pstr_next; 171 free(filt); 172 } 173 174 void 175 pcieadm_strfilt_push(pcieadm_cfgspace_walk_t *walkp, const char *str) 176 { 177 pcieadm_strfilt_t *filt; 178 size_t len; 179 180 filt = calloc(1, sizeof (*filt)); 181 if (filt == NULL) { 182 errx(EXIT_FAILURE, "failed to allocate memory for string " 183 "filter"); 184 } 185 186 filt->pstr_str = str; 187 if (walkp->pcw_filt == NULL) { 188 len = strlcat(filt->pstr_curgen, str, 189 sizeof (filt->pstr_curgen)); 190 } else { 191 len = snprintf(filt->pstr_curgen, sizeof (filt->pstr_curgen), 192 "%s.%s", walkp->pcw_filt->pstr_curgen, str); 193 filt->pstr_next = walkp->pcw_filt; 194 } 195 196 if (len >= sizeof (filt->pstr_curgen)) { 197 errx(EXIT_FAILURE, "overflowed internal string buffer " 198 "appending %s", str); 199 } 200 201 walkp->pcw_filt = filt; 202 } 203 204 static boolean_t 205 pcieadm_cfgspace_filter(pcieadm_cfgspace_walk_t *walkp, const char *str) 206 { 207 char buf[1024]; 208 size_t len; 209 210 if (walkp->pcw_nfilters == 0) { 211 return (B_TRUE); 212 } 213 214 if (str == NULL) { 215 return (B_FALSE); 216 } 217 218 if (walkp->pcw_filt != NULL) { 219 len = snprintf(buf, sizeof (buf), "%s.%s", 220 walkp->pcw_filt->pstr_curgen, str); 221 } else { 222 len = snprintf(buf, sizeof (buf), "%s", str); 223 } 224 225 if (len >= sizeof (buf)) { 226 abort(); 227 } 228 229 for (uint_t i = 0; i < walkp->pcw_nfilters; i++) { 230 if (strcmp(buf, walkp->pcw_filters[i].pcf_string) == 0) { 231 walkp->pcw_filters[i].pcf_used = B_TRUE; 232 return (B_TRUE); 233 } 234 235 /* 236 * If we're in non-parsable mode, we want to do a little bit 237 * more in a few cases. We want to make sure that we print the 238 * parents of more-specific entries. That is, if someone 239 * specified 'header.command.serr', then we want to print 240 * 'header', and 'header.command'. Similarly, if someone 241 * specifies an individual field, we want to print all of its 242 * subfields, that is asking for 'header.command', really gets 243 * that and all of 'header.command.*'. 244 */ 245 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_PARSE) != 0) { 246 continue; 247 } 248 249 if (len >= walkp->pcw_filters[i].pcf_len) { 250 if (strncmp(buf, walkp->pcw_filters[i].pcf_string, 251 walkp->pcw_filters[i].pcf_len) == 0 && 252 buf[walkp->pcw_filters[i].pcf_len] == '.') { 253 return (B_TRUE); 254 } 255 } else { 256 if (strncmp(buf, walkp->pcw_filters[i].pcf_string, 257 len) == 0 && 258 walkp->pcw_filters[i].pcf_string[len] == '.') { 259 return (B_TRUE); 260 } 261 } 262 } 263 264 return (B_FALSE); 265 } 266 267 static boolean_t 268 pcieadm_cfgspace_ofmt_cb(ofmt_arg_t *ofarg, char *buf, uint_t buflen) 269 { 270 pcieadm_cfgspace_ofmt_t *pco = ofarg->ofmt_cbarg; 271 272 switch (ofarg->ofmt_id) { 273 case PCIEADM_CFGSPACE_OT_SHORT: 274 if (snprintf(buf, buflen, "%s.%s", pco->pco_base, 275 pco->pco_short) >= buflen) { 276 return (B_FALSE); 277 } 278 break; 279 case PCIEADM_CFGSPACE_OT_HUMAN: 280 if (strlcpy(buf, pco->pco_human, buflen) >= buflen) { 281 return (B_FALSE); 282 } 283 break; 284 case PCIEADM_CFGSPACE_OT_VALUE: 285 if (pco->pco_strval != NULL) { 286 if (strlcpy(buf, pco->pco_strval, buflen) >= buflen) { 287 return (B_FALSE); 288 } 289 } else { 290 if (snprintf(buf, buflen, "0x%" PRIx64, 291 pco->pco_value) >= buflen) { 292 return (B_FALSE); 293 } 294 } 295 break; 296 default: 297 abort(); 298 } 299 300 return (B_TRUE); 301 } 302 303 304 static const ofmt_field_t pcieadm_cfgspace_ofmt[] = { 305 { "SHORT", 30, PCIEADM_CFGSPACE_OT_SHORT, pcieadm_cfgspace_ofmt_cb }, 306 { "HUMAN", 30, PCIEADM_CFGSPACE_OT_HUMAN, pcieadm_cfgspace_ofmt_cb }, 307 { "VALUE", 20, PCIEADM_CFGSPACE_OT_VALUE, pcieadm_cfgspace_ofmt_cb }, 308 { NULL, 0, 0, NULL } 309 }; 310 311 static void 312 pcieadm_cfgspace_print_parse(pcieadm_cfgspace_walk_t *walkp, 313 const char *sname, const char *human, uint64_t value) 314 { 315 pcieadm_cfgspace_ofmt_t pco; 316 317 VERIFY3P(walkp->pcw_filt, !=, NULL); 318 pco.pco_base = walkp->pcw_filt->pstr_curgen; 319 pco.pco_short = sname; 320 pco.pco_human = human; 321 pco.pco_value = value; 322 pco.pco_strval = NULL; 323 ofmt_print(walkp->pcw_ofmt, &pco); 324 } 325 326 typedef struct pcieadm_cfgspace_print pcieadm_cfgspace_print_t; 327 typedef void (*pcieadm_cfgspace_print_f)(pcieadm_cfgspace_walk_t *, 328 pcieadm_cfgspace_print_t *, void *); 329 330 struct pcieadm_cfgspace_print { 331 uint8_t pcp_off; 332 uint8_t pcp_len; 333 const char *pcp_short; 334 const char *pcp_human; 335 pcieadm_cfgspace_print_f pcp_print; 336 void *pcp_arg; 337 }; 338 339 static void 340 pcieadm_field_printf(pcieadm_cfgspace_walk_t *walkp, const char *shortf, 341 const char *humanf, uint64_t val, const char *fmt, ...) 342 { 343 va_list ap; 344 345 if (!pcieadm_cfgspace_filter(walkp, shortf)) 346 return; 347 348 if (walkp->pcw_ofmt != NULL) { 349 pcieadm_cfgspace_print_parse(walkp, shortf, humanf, val); 350 return; 351 } 352 353 if (walkp->pcw_pcieadm->pia_indent > 0) { 354 (void) printf("%*s", walkp->pcw_pcieadm->pia_indent, ""); 355 } 356 357 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 358 (void) printf("|--> %s (%s.%s): ", humanf, 359 walkp->pcw_filt->pstr_curgen, shortf); 360 } else { 361 (void) printf("|--> %s: ", humanf); 362 } 363 364 va_start(ap, fmt); 365 (void) vprintf(fmt, ap); 366 va_end(ap); 367 368 } 369 370 static void 371 pcieadm_cfgspace_printf(pcieadm_cfgspace_walk_t *walkp, 372 pcieadm_cfgspace_print_t *print, uint64_t val, const char *fmt, ...) 373 { 374 va_list ap; 375 376 if (!pcieadm_cfgspace_filter(walkp, print->pcp_short)) 377 return; 378 379 if (walkp->pcw_ofmt != NULL) { 380 pcieadm_cfgspace_print_parse(walkp, print->pcp_short, 381 print->pcp_human, val); 382 return; 383 } 384 385 if (walkp->pcw_pcieadm->pia_indent > 0) { 386 (void) printf("%*s", walkp->pcw_pcieadm->pia_indent, ""); 387 } 388 389 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 390 (void) printf("%s (%s.%s): ", print->pcp_human, 391 walkp->pcw_filt->pstr_curgen, print->pcp_short); 392 } else { 393 (void) printf("%s: ", print->pcp_human); 394 } 395 396 va_start(ap, fmt); 397 (void) vprintf(fmt, ap); 398 va_end(ap); 399 } 400 401 static void 402 pcieadm_cfgspace_puts(pcieadm_cfgspace_walk_t *walkp, 403 pcieadm_cfgspace_print_t *print, const char *str) 404 { 405 if (!pcieadm_cfgspace_filter(walkp, print->pcp_short)) 406 return; 407 408 if (walkp->pcw_ofmt != NULL) { 409 pcieadm_cfgspace_ofmt_t pco; 410 411 VERIFY3P(walkp->pcw_filt, !=, NULL); 412 pco.pco_base = walkp->pcw_filt->pstr_curgen; 413 pco.pco_short = print->pcp_short; 414 pco.pco_human = print->pcp_human; 415 pco.pco_strval = str; 416 ofmt_print(walkp->pcw_ofmt, &pco); 417 return; 418 } 419 420 if (walkp->pcw_pcieadm->pia_indent > 0) { 421 (void) printf("%*s", walkp->pcw_pcieadm->pia_indent, ""); 422 } 423 424 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 425 (void) printf("%s (%s.%s): %s\n", print->pcp_human, 426 walkp->pcw_filt->pstr_curgen, print->pcp_short, str); 427 } else { 428 (void) printf("%s: %s\n", print->pcp_human, str); 429 } 430 } 431 432 static uint64_t 433 pcieadm_cfgspace_extract(pcieadm_cfgspace_walk_t *walkp, 434 pcieadm_cfgspace_print_t *print) 435 { 436 uint32_t val = 0; 437 438 VERIFY3U(print->pcp_len, <=, 8); 439 VERIFY3U(print->pcp_off + print->pcp_len + walkp->pcw_capoff, <=, 440 walkp->pcw_valid); 441 for (uint8_t i = print->pcp_len; i > 0; i--) { 442 val <<= 8; 443 val |= walkp->pcw_data->pcb_u8[walkp->pcw_capoff + 444 print->pcp_off + i - 1]; 445 } 446 447 return (val); 448 } 449 450 static uint16_t 451 pcieadm_cfgspace_extract_u16(pcieadm_cfgspace_walk_t *walkp, 452 pcieadm_cfgspace_print_t *print) 453 { 454 VERIFY(print->pcp_len == 2); 455 return ((uint16_t)pcieadm_cfgspace_extract(walkp, print)); 456 } 457 458 static void 459 pcieadm_cfgspace_print_unit(pcieadm_cfgspace_walk_t *walkp, 460 pcieadm_cfgspace_print_t *print, void *arg) 461 { 462 pcieadm_unitdef_t *unit = arg; 463 uint64_t rawval = pcieadm_cfgspace_extract(walkp, print); 464 uint64_t val = rawval; 465 466 if (unit->pcd_mult > 1) { 467 val *= unit->pcd_mult; 468 } 469 pcieadm_cfgspace_printf(walkp, print, rawval, "0x%" PRIx64 " %s%s\n", 470 val, unit->pcd_unit, val != 1 ? "s" : ""); 471 } 472 473 static void 474 pcieadm_cfgspace_print_regdef(pcieadm_cfgspace_walk_t *walkp, 475 pcieadm_cfgspace_print_t *print, void *arg) 476 { 477 pcieadm_regdef_t *regdef = arg; 478 uint64_t val = pcieadm_cfgspace_extract(walkp, print); 479 480 pcieadm_cfgspace_printf(walkp, print, val, "0x%" PRIx64 "\n", val); 481 482 pcieadm_indent(); 483 pcieadm_strfilt_push(walkp, print->pcp_short); 484 485 for (regdef = arg; regdef->prd_short != NULL; regdef++) { 486 uint32_t nbits = regdef->prd_hibit - regdef->prd_lowbit + 1UL; 487 uint32_t bitmask = (1UL << nbits) - 1UL; 488 uint64_t regval = (val >> regdef->prd_lowbit) & bitmask; 489 const char *strval; 490 uint64_t actval; 491 492 if (!pcieadm_cfgspace_filter(walkp, regdef->prd_short)) { 493 continue; 494 } 495 496 switch (regdef->prd_valtype) { 497 case PRDV_STRVAL: 498 strval = regdef->prd_val.prdv_strval[regval]; 499 if (strval == NULL) { 500 strval = "reserved"; 501 } 502 pcieadm_field_printf(walkp, regdef->prd_short, 503 regdef->prd_human, regval, "%s (0x%" PRIx64 ")\n", 504 strval, regval << regdef->prd_lowbit); 505 break; 506 case PRDV_HEX: 507 actval = regval; 508 if (regdef->prd_val.prdv_hex.pra_shift > 0) { 509 actval <<= regdef->prd_val.prdv_hex.pra_shift; 510 } 511 actval += regdef->prd_val.prdv_hex.pra_addend; 512 513 pcieadm_field_printf(walkp, regdef->prd_short, 514 regdef->prd_human, regval, "0x% " PRIx64 "\n", 515 actval); 516 break; 517 case PRDV_BITFIELD: 518 pcieadm_field_printf(walkp, regdef->prd_short, 519 regdef->prd_human, regval, "0x%" PRIx64 "\n", 520 regval << regdef->prd_lowbit); 521 522 if (walkp->pcw_ofmt == NULL) { 523 pcieadm_indent(); 524 for (uint32_t i = 0; i < nbits; i++) { 525 if (((1 << i) & regval) == 0) 526 continue; 527 pcieadm_print("|--> %s (0x%x)\n", 528 regdef->prd_val.prdv_strval[i], 529 1UL << (i + regdef->prd_lowbit)); 530 } 531 pcieadm_deindent(); 532 } 533 break; 534 } 535 } 536 537 pcieadm_strfilt_pop(walkp); 538 pcieadm_deindent(); 539 } 540 541 static void 542 pcieadm_cfgspace_print_strmap(pcieadm_cfgspace_walk_t *walkp, 543 pcieadm_cfgspace_print_t *print, void *arg) 544 { 545 pcieadm_strmap_t *strmap = arg; 546 uint64_t val = pcieadm_cfgspace_extract(walkp, print); 547 const char *str = "reserved"; 548 549 for (uint_t i = 0; strmap[i].psr_str != NULL; i++) { 550 if (strmap[i].psr_val == val) { 551 str = strmap[i].psr_str; 552 break; 553 } 554 } 555 556 pcieadm_cfgspace_printf(walkp, print, val, "0x%x -- %s\n", val, str); 557 } 558 559 static void 560 pcieadm_cfgspace_print_hex(pcieadm_cfgspace_walk_t *walkp, 561 pcieadm_cfgspace_print_t *print, void *arg) 562 { 563 uint64_t val = pcieadm_cfgspace_extract(walkp, print); 564 565 pcieadm_cfgspace_printf(walkp, print, val, "0x%" PRIx64 "\n", val); 566 } 567 568 static void 569 pcieadm_cfgspace_print_vendor(pcieadm_cfgspace_walk_t *walkp, 570 pcieadm_cfgspace_print_t *print, void *arg) 571 { 572 pcidb_vendor_t *vend; 573 uint16_t vid = pcieadm_cfgspace_extract_u16(walkp, print); 574 575 vend = pcidb_lookup_vendor(walkp->pcw_pcieadm->pia_pcidb, vid); 576 if (vend != NULL) { 577 pcieadm_cfgspace_printf(walkp, print, vid, "0x%x -- %s\n", vid, 578 pcidb_vendor_name(vend)); 579 } else { 580 pcieadm_cfgspace_printf(walkp, print, vid, "0x%x\n", vid); 581 } 582 } 583 584 static void 585 pcieadm_cfgspace_print_device(pcieadm_cfgspace_walk_t *walkp, 586 pcieadm_cfgspace_print_t *print, void *arg) 587 { 588 pcidb_device_t *dev; 589 uint16_t did = pcieadm_cfgspace_extract_u16(walkp, print); 590 uint16_t vid = walkp->pcw_data->pcb_u8[PCI_CONF_VENID] + 591 (walkp->pcw_data->pcb_u8[PCI_CONF_VENID + 1] << 8); 592 593 dev = pcidb_lookup_device(walkp->pcw_pcieadm->pia_pcidb, vid, did); 594 if (dev != NULL) { 595 pcieadm_cfgspace_printf(walkp, print, did, "0x%x -- %s\n", did, 596 pcidb_device_name(dev)); 597 } else { 598 pcieadm_cfgspace_printf(walkp, print, did, "0x%x\n", did); 599 } 600 } 601 602 /* 603 * To print out detailed information about a subsystem vendor or device, we need 604 * all of the information about the vendor and device due to the organization of 605 * the PCI IDs db. 606 */ 607 static void 608 pcieadm_cfgspace_print_subid(pcieadm_cfgspace_walk_t *walkp, 609 pcieadm_cfgspace_print_t *print, void *arg) 610 { 611 uint16_t vid = walkp->pcw_data->pcb_u8[PCI_CONF_VENID] + 612 (walkp->pcw_data->pcb_u8[PCI_CONF_VENID + 1] << 8); 613 uint16_t did = walkp->pcw_data->pcb_u8[PCI_CONF_DEVID] + 614 (walkp->pcw_data->pcb_u8[PCI_CONF_DEVID + 1] << 8); 615 uint16_t svid = walkp->pcw_data->pcb_u8[PCI_CONF_SUBVENID] + 616 (walkp->pcw_data->pcb_u8[PCI_CONF_SUBVENID + 1] << 8); 617 uint16_t sdid = walkp->pcw_data->pcb_u8[PCI_CONF_SUBSYSID] + 618 (walkp->pcw_data->pcb_u8[PCI_CONF_SUBSYSID + 1] << 8); 619 uint16_t val = pcieadm_cfgspace_extract_u16(walkp, print); 620 boolean_t isvendor = print->pcp_off == PCI_CONF_SUBVENID; 621 622 if (isvendor) { 623 pcidb_vendor_t *vend; 624 vend = pcidb_lookup_vendor(walkp->pcw_pcieadm->pia_pcidb, 625 svid); 626 if (vend != NULL) { 627 pcieadm_cfgspace_printf(walkp, print, val, 628 "0x%x -- %s\n", val, pcidb_vendor_name(vend)); 629 } else { 630 pcieadm_cfgspace_printf(walkp, print, val, 631 "0x%x\n", val); 632 } 633 } else { 634 pcidb_subvd_t *subvd; 635 subvd = pcidb_lookup_subvd(walkp->pcw_pcieadm->pia_pcidb, vid, 636 did, svid, sdid); 637 if (subvd != NULL) { 638 pcieadm_cfgspace_printf(walkp, print, val, 639 "0x%x -- %s\n", val, pcidb_subvd_name(subvd)); 640 } else { 641 pcieadm_cfgspace_printf(walkp, print, val, "0x%x\n", 642 val); 643 } 644 } 645 } 646 647 /* 648 * The variable natures of BARs is a pain. This makes printing this out and the 649 * fields all a bit gross. 650 */ 651 static void 652 pcieadm_cfgspace_print_bars(pcieadm_cfgspace_walk_t *walkp, 653 pcieadm_cfgspace_print_t *print, void *arg) 654 { 655 uint32_t *barp = &walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 656 print->pcp_off) / 4]; 657 char barname[32]; 658 const char *typestrs[2] = { "Memory Space", "I/O Space" }; 659 660 for (uint_t i = 0; i < print->pcp_len / 4; i++) { 661 uint_t type; 662 (void) snprintf(barname, sizeof (barname), "%s%u", 663 print->pcp_short, i); 664 665 type = barp[i] & PCI_BASE_SPACE_M; 666 667 if (pcieadm_cfgspace_filter(walkp, barname) && 668 walkp->pcw_ofmt == NULL) { 669 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_SHORT) != 670 0) { 671 pcieadm_print("%s %u (%s.%s)\n", 672 print->pcp_human, i, 673 walkp->pcw_filt->pstr_curgen, barname); 674 } else { 675 pcieadm_print("%s %u\n", print->pcp_human, i); 676 } 677 } 678 679 pcieadm_strfilt_push(walkp, barname); 680 pcieadm_indent(); 681 682 pcieadm_field_printf(walkp, "space", "Space", type, 683 "%s (0x%x)\n", typestrs[type], type); 684 685 if (type == PCI_BASE_SPACE_IO) { 686 uint32_t addr = barp[i] & PCI_BASE_IO_ADDR_M; 687 688 pcieadm_field_printf(walkp, "addr", "Address", addr, 689 "0x%" PRIx32 "\n", addr); 690 } else { 691 uint8_t type, pre; 692 uint64_t addr; 693 const char *locstr; 694 695 type = barp[i] & PCI_BASE_TYPE_M; 696 pre = barp[i] & PCI_BASE_PREF_M; 697 addr = barp[i] & PCI_BASE_M_ADDR_M; 698 699 if (type == PCI_BASE_TYPE_ALL) { 700 addr += (uint64_t)barp[i+1] << 32; 701 i++; 702 } 703 704 pcieadm_field_printf(walkp, "addr", "Address", addr, 705 "0x%" PRIx64 "\n", addr); 706 707 switch (type) { 708 case PCI_BASE_TYPE_MEM: 709 locstr = "32-bit"; 710 break; 711 case PCI_BASE_TYPE_LOW: 712 locstr = "Sub-1 MiB"; 713 break; 714 case PCI_BASE_TYPE_ALL: 715 locstr = "64-bit"; 716 break; 717 case PCI_BASE_TYPE_RES: 718 default: 719 locstr = "Reserved"; 720 break; 721 } 722 723 pcieadm_field_printf(walkp, "addr", "Address", addr, 724 "%s (0x%x)\n", locstr, type >> 1); 725 pcieadm_field_printf(walkp, "prefetch", "Prefetchable", 726 pre != 0, "%s (0x%x)\n", pre != 0 ? "yes" : "no", 727 pre != 0); 728 } 729 730 pcieadm_deindent(); 731 pcieadm_strfilt_pop(walkp); 732 } 733 } 734 735 static void 736 pcieadm_cfgspace_print_ecv(pcieadm_cfgspace_walk_t *walkp, 737 pcieadm_cfgspace_print_t *print, void *arg) 738 { 739 uint16_t bitlen, nwords; 740 741 if (BITX(walkp->pcw_data->pcb_u8[walkp->pcw_capoff + 4], 5, 5) == 0) { 742 return; 743 } 744 745 bitlen = walkp->pcw_data->pcb_u8[walkp->pcw_capoff + 5]; 746 if (bitlen == 0) { 747 bitlen = 256; 748 } 749 750 nwords = bitlen / 32; 751 if ((bitlen % 8) != 0) { 752 nwords++; 753 } 754 755 for (uint16_t i = 0; i < nwords; i++) { 756 char tshort[32], thuman[128]; 757 pcieadm_cfgspace_print_t p; 758 759 (void) snprintf(tshort, sizeof (tshort), "ecv%u", i); 760 (void) snprintf(thuman, sizeof (thuman), "Egress Control " 761 "Vector %u", i); 762 p.pcp_off = print->pcp_off + i * 4; 763 p.pcp_len = 4; 764 p.pcp_short = tshort; 765 p.pcp_human = thuman; 766 p.pcp_print = pcieadm_cfgspace_print_hex; 767 p.pcp_arg = NULL; 768 769 p.pcp_print(walkp, &p, p.pcp_arg); 770 } 771 } 772 773 static void 774 pcieadm_cfgspace_print_dpa_paa(pcieadm_cfgspace_walk_t *walkp, 775 pcieadm_cfgspace_print_t *print, void *arg) 776 { 777 uint8_t nents; 778 779 nents = BITX(walkp->pcw_data->pcb_u8[walkp->pcw_capoff + 4], 4, 0) + 1; 780 if (nents == 0) { 781 return; 782 } 783 784 for (uint8_t i = 0; i < nents; i++) { 785 char tshort[32], thuman[128]; 786 pcieadm_cfgspace_print_t p; 787 788 (void) snprintf(tshort, sizeof (tshort), "%s%u", 789 print->pcp_short, i); 790 (void) snprintf(thuman, sizeof (thuman), "%s %u", 791 print->pcp_human, i); 792 793 p.pcp_off = print->pcp_off + i; 794 p.pcp_len = 1; 795 p.pcp_short = tshort; 796 p.pcp_human = thuman; 797 p.pcp_print = pcieadm_cfgspace_print_hex; 798 p.pcp_arg = NULL; 799 800 p.pcp_print(walkp, &p, p.pcp_arg); 801 } 802 } 803 804 /* 805 * Config Space Header Table Definitions 806 */ 807 static pcieadm_regdef_t pcieadm_regdef_command[] = { 808 { 0, 0, "io", "I/O Space", PRDV_STRVAL, 809 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 810 { 1, 1, "mem", "Memory Space", PRDV_STRVAL, 811 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 812 { 2, 2, "bus", "Bus Master", PRDV_STRVAL, 813 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 814 { 3, 3, "spec", "Special Cycle", PRDV_STRVAL, 815 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 816 { 4, 4, "mwi", "Memory Write and Invalidate", PRDV_STRVAL, 817 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 818 { 5, 5, "vga", "VGA Palette Snoop", PRDV_STRVAL, 819 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 820 { 6, 6, "per", "Parity Error Response", PRDV_STRVAL, 821 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 822 { 7, 7, "idsel", "IDSEL Stepping/Wait Cycle Control", PRDV_STRVAL, 823 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 824 { 8, 8, "serr", "SERR# Enable", PRDV_STRVAL, 825 .prd_val = { .prdv_strval = { "disabled", "enabled" } }, }, 826 { 9, 9, "fbtx", "Fast Back-to-Back Transactions", PRDV_STRVAL, 827 .prd_val = { .prdv_strval = { "disabled", "enabled" } }, }, 828 { 10, 10, "intx", "Interrupt X", PRDV_STRVAL, 829 .prd_val = { .prdv_strval = { "enabled", "disabled" } } }, 830 { -1, -1, NULL } 831 }; 832 833 static pcieadm_regdef_t pcieadm_regdef_status[] = { 834 { 0, 0, "imm", "Immediate Readiness", PRDV_STRVAL, 835 .prd_val = { .prdv_strval = { "unsupported", "supported" } }, }, 836 { 3, 3, "istat", "Interrupt Status", PRDV_STRVAL, 837 .prd_val = { .prdv_strval = { "not pending", "pending" } }, }, 838 { 4, 4, "capsup", "Capabilities List", PRDV_STRVAL, 839 .prd_val = { .prdv_strval = { "unsupported", "supported" } }, }, 840 { 5, 5, "66mhz", "66 MHz Capable", PRDV_STRVAL, 841 .prd_val = { .prdv_strval = { "unsupported", "supported" } }, }, 842 { 7, 7, "fbtxcap", "Fast Back-to-Back Capable", PRDV_STRVAL, 843 .prd_val = { .prdv_strval = { "unsupported", "supported" } }, }, 844 { 8, 8, "mdperr", "Master Data Parity Error", PRDV_STRVAL, 845 .prd_val = { .prdv_strval = { "no error", "error detected" } }, }, 846 { 9, 10, "devsel", "DEVSEL# Timing", PRDV_STRVAL, 847 .prd_val = { .prdv_strval = { "fast", "medium", "slow", 848 "reserved" } } }, 849 { 11, 11, "sta", "Signaled Target Abort", PRDV_STRVAL, 850 .prd_val = { .prdv_strval = { "no", "yes" } } }, 851 { 12, 12, "rta", "Received Target Abort", PRDV_STRVAL, 852 .prd_val = { .prdv_strval = { "no", "yes" } } }, 853 { 13, 13, "rma", "Received Master Abort", PRDV_STRVAL, 854 .prd_val = { .prdv_strval = { "no", "yes" } } }, 855 { 14, 14, "sse", "Signaled System Error", PRDV_STRVAL, 856 .prd_val = { .prdv_strval = { "no", "yes" } } }, 857 { 15, 15, "dpe", "Detected Parity Error", PRDV_STRVAL, 858 .prd_val = { .prdv_strval = { "no", "yes" } } }, 859 { -1, -1, NULL } 860 }; 861 862 /* 863 * It might be interesting to translate these into numbers at a future point. 864 */ 865 static pcieadm_regdef_t pcieadm_regdef_class[] = { 866 { 16, 23, "class", "Class Code", PRDV_HEX }, 867 { 7, 15, "sclass", "Sub-Class Code", PRDV_HEX }, 868 { 0, 7, "pi", "Programming Interface", PRDV_HEX }, 869 { -1, -1, NULL } 870 }; 871 872 static pcieadm_regdef_t pcieadm_regdef_bridge_iobase[] = { 873 { 0, 3, "cap", "Addressing Capability", PRDV_STRVAL, 874 .prd_val = { .prdv_strval = { "16-bit", "32-bit" } } }, 875 { 4, 7, "base", "Base", PRDV_HEX, 876 .prd_val = { .prdv_hex = { 12 } } }, 877 { -1, -1, NULL } 878 }; 879 880 static pcieadm_regdef_t pcieadm_regdef_bridge_iolim[] = { 881 { 0, 3, "cap", "Addressing Capability", PRDV_STRVAL, 882 .prd_val = { .prdv_strval = { "16-bit", "32-bit" } } }, 883 { 4, 7, "limit", "Limit", PRDV_HEX, 884 .prd_val = { .prdv_hex = { 12, 0xfff } } }, 885 { -1, -1, NULL } 886 }; 887 888 889 static pcieadm_regdef_t pcieadm_regdef_bridgests[] = { 890 { 5, 5, "66mhz", "66 MHz", PRDV_STRVAL, 891 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 892 { 7, 7, "fastb2b", "Fast Back-to-Back Transactions", PRDV_STRVAL, 893 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 894 { 8, 8, "mdperr", "Master Data Parity Error", PRDV_STRVAL, 895 .prd_val = { .prdv_strval = { "no error", "error detected" } } }, 896 { 9, 10, "devsel", "DEVSEL# Timing", PRDV_STRVAL, 897 .prd_val = { .prdv_strval = { "fast", "medium", "slow" } } }, 898 { 11, 11, "sta", "Signaled Target Abort", PRDV_STRVAL, 899 .prd_val = { .prdv_strval = { "no abort", "aborted" } } }, 900 { 12, 12, "rta", "Received Target Abort", PRDV_STRVAL, 901 .prd_val = { .prdv_strval = { "no abort", "aborted" } } }, 902 { 13, 13, "rma", "Received Master Abort", PRDV_STRVAL, 903 .prd_val = { .prdv_strval = { "no abort", "aborted" } } }, 904 { 14, 14, "rsyserr", "Received System Error", PRDV_STRVAL, 905 .prd_val = { .prdv_strval = { "no error", "error received" } } }, 906 { 15, 15, "dperr", "Detected Parity Error", PRDV_STRVAL, 907 .prd_val = { .prdv_strval = { "no error", "error detected" } } }, 908 { -1, -1, NULL } 909 }; 910 911 static pcieadm_regdef_t pcieadm_regdef_bridge_membase[] = { 912 { 4, 16, "base", "Base", PRDV_HEX, 913 .prd_val = { .prdv_hex = { 20 } } }, 914 { -1, -1, NULL } 915 }; 916 917 static pcieadm_regdef_t pcieadm_regdef_bridge_memlim[] = { 918 { 4, 16, "limit", "Limit", PRDV_HEX, 919 .prd_val = { .prdv_hex = { 20, 0xfffff } } }, 920 { -1, -1, NULL } 921 }; 922 923 static pcieadm_regdef_t pcieadm_regdef_bridge_pfbase[] = { 924 { 0, 3, "cap", "Addressing Capability", PRDV_STRVAL, 925 .prd_val = { .prdv_strval = { "32-bit", "64-bit" } } }, 926 { 4, 16, "base", "Base", PRDV_HEX, 927 .prd_val = { .prdv_hex = { 20 } } }, 928 { -1, -1, NULL } 929 }; 930 931 static pcieadm_regdef_t pcieadm_regdef_bridge_pflim[] = { 932 { 0, 3, "cap", "Addressing Capability", PRDV_STRVAL, 933 .prd_val = { .prdv_strval = { "32-bit", "64-bit" } } }, 934 { 4, 16, "limit", "Limit", PRDV_HEX, 935 .prd_val = { .prdv_hex = { 20, 0xfffff } } }, 936 { -1, -1, NULL } 937 }; 938 939 static pcieadm_regdef_t pcieadm_regdef_bridge_ctl[] = { 940 { 0, 0, "perrresp", "Parity Error Response", PRDV_STRVAL, 941 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 942 { 1, 1, "serr", "SERR#", PRDV_STRVAL, 943 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 944 { 2, 2, "isa", "ISA", PRDV_STRVAL, 945 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 946 { 3, 3, "vga", "VGA", PRDV_STRVAL, 947 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 948 { 4, 4, "vgadec", "VGA 16-bit Decode", PRDV_STRVAL, 949 .prd_val = { .prdv_strval = { "10-bit", "16-bit" } } }, 950 { 5, 5, "mabort", "Master Abort", PRDV_STRVAL, 951 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 952 { 6, 6, "secrst", "Secondary Bus Reset", PRDV_HEX }, 953 { 7, 7, "fastb2b", "Fast Back-to-Back Transactions", PRDV_STRVAL, 954 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 955 { 8, 8, "pridisc", "Primary Discard Timer", PRDV_STRVAL, 956 .prd_val = { .prdv_strval = { "2^15 cycles", "2^10 cycles" } } }, 957 { 9, 9, "secdisc", "Secondary Discard Timer", PRDV_STRVAL, 958 .prd_val = { .prdv_strval = { "2^15 cycles", "2^10 cycles" } } }, 959 { 10, 10, "disctimer", "Discard Timer Error", PRDV_STRVAL, 960 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 961 { 11, 11, "discserr", "Discard Timer SERR#", PRDV_STRVAL, 962 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 963 { -1, -1, NULL } 964 }; 965 966 static pcieadm_unitdef_t pcieadm_unitdef_cache = { 967 "byte", 4 968 }; 969 970 static pcieadm_unitdef_t pcieadm_unitdef_latreg = { "cycle" }; 971 972 static pcieadm_regdef_t pcieadm_regdef_header[] = { 973 { 0, 6, "layout", "Header Layout", PRDV_STRVAL, 974 .prd_val = { .prdv_strval = { "Device", "Bridge", "PC Card" } } }, 975 { 7, 7, "mfd", "Multi-Function Device", PRDV_STRVAL, 976 .prd_val = { .prdv_strval = { "no", "yes" } } }, 977 { -1, -1, NULL } 978 }; 979 980 static pcieadm_regdef_t pcieadm_regdef_bist[] = { 981 { 0, 3, "code", "Completion Code", PRDV_HEX }, 982 { 6, 6, "start", "Start BIST", PRDV_HEX }, 983 { 7, 7, "cap", "BIST Capable", PRDV_STRVAL, 984 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 985 { -1, -1, NULL } 986 }; 987 988 static pcieadm_regdef_t pcieadm_regdef_exprom[] = { 989 { 0, 0, "enable", "Enable", PRDV_STRVAL, 990 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 991 { 11, 31, "addr", "Base Address", PRDV_HEX, 992 .prd_val = { .prdv_hex = { 21 } } }, 993 { -1, -1, NULL } 994 }; 995 996 static pcieadm_strmap_t pcieadm_strmap_ipin[] = { 997 { "none", 0 }, 998 { "INTA", PCI_INTA }, 999 { "INTB", PCI_INTB }, 1000 { "INTC", PCI_INTC }, 1001 { "INTD", PCI_INTD }, 1002 { NULL } 1003 }; 1004 1005 1006 static pcieadm_cfgspace_print_t pcieadm_cfgspace_type0[] = { 1007 { 0x0, 2, "vendor", "Vendor ID", pcieadm_cfgspace_print_vendor }, 1008 { 0x2, 2, "device", "Device ID", pcieadm_cfgspace_print_device }, 1009 { 0x4, 2, "command", "Command", pcieadm_cfgspace_print_regdef, 1010 pcieadm_regdef_command }, 1011 { 0x6, 2, "status", "Status", pcieadm_cfgspace_print_regdef, 1012 pcieadm_regdef_status }, 1013 { 0x8, 1, "revision", "Revision ID", pcieadm_cfgspace_print_hex }, 1014 { 0x9, 3, "class", "Class Code", pcieadm_cfgspace_print_regdef, 1015 pcieadm_regdef_class }, 1016 { 0xc, 1, "cache", "Cache Line Size", pcieadm_cfgspace_print_unit, 1017 &pcieadm_unitdef_cache }, 1018 { 0xd, 1, "latency", "Latency Timer", pcieadm_cfgspace_print_unit, 1019 &pcieadm_unitdef_latreg }, 1020 { 0xe, 1, "type", "Header Type", pcieadm_cfgspace_print_regdef, 1021 pcieadm_regdef_header }, 1022 { 0xf, 1, "bist", "BIST", pcieadm_cfgspace_print_regdef, 1023 pcieadm_regdef_bist }, 1024 { 0x10, 24, "bar", "Base Address Register", 1025 pcieadm_cfgspace_print_bars }, 1026 { 0x28, 4, "cis", "Cardbus CIS Pointer", pcieadm_cfgspace_print_hex }, 1027 { 0x2c, 2, "subvid", "Subsystem Vendor ID", 1028 pcieadm_cfgspace_print_subid }, 1029 { 0x2e, 2, "subdev", "Subsystem Device ID", 1030 pcieadm_cfgspace_print_subid }, 1031 { 0x30, 4, "rom", "Expansion ROM", pcieadm_cfgspace_print_regdef, 1032 pcieadm_regdef_exprom }, 1033 { 0x34, 1, "cap", "Capabilities Pointer", pcieadm_cfgspace_print_hex }, 1034 { 0x3c, 1, "iline", "Interrupt Line", pcieadm_cfgspace_print_hex }, 1035 { 0x3d, 1, "ipin", "Interrupt Pin", pcieadm_cfgspace_print_strmap, 1036 pcieadm_strmap_ipin }, 1037 { 0x3e, 1, "gnt", "Min_Gnt", pcieadm_cfgspace_print_hex }, 1038 { 0x3f, 1, "lat", "Min_Lat", pcieadm_cfgspace_print_hex }, 1039 { -1, -1, NULL } 1040 }; 1041 1042 static pcieadm_cfgspace_print_t pcieadm_cfgspace_type1[] = { 1043 { 0x0, 2, "vendor", "Vendor ID", pcieadm_cfgspace_print_vendor }, 1044 { 0x2, 2, "device", "Device ID", pcieadm_cfgspace_print_device }, 1045 { 0x4, 2, "command", "Command", pcieadm_cfgspace_print_regdef, 1046 pcieadm_regdef_command }, 1047 { 0x6, 2, "status", "Status", pcieadm_cfgspace_print_regdef, 1048 pcieadm_regdef_status }, 1049 { 0x8, 1, "revision", "Revision ID", pcieadm_cfgspace_print_hex }, 1050 { 0x9, 3, "class", "Class Code", pcieadm_cfgspace_print_regdef, 1051 pcieadm_regdef_class }, 1052 { 0xc, 1, "cache", "Cache Line Size", pcieadm_cfgspace_print_unit, 1053 &pcieadm_unitdef_cache }, 1054 { 0xd, 1, "latency", "Latency Timer", pcieadm_cfgspace_print_unit, 1055 &pcieadm_unitdef_latreg }, 1056 { 0xe, 1, "type", "Header Type", pcieadm_cfgspace_print_regdef, 1057 pcieadm_regdef_header }, 1058 { 0xf, 1, "bist", "BIST", pcieadm_cfgspace_print_regdef, 1059 pcieadm_regdef_bist }, 1060 { 0x10, 8, "bar", "Base Address Register", 1061 pcieadm_cfgspace_print_bars }, 1062 { PCI_BCNF_PRIBUS, 1, "pribus", "Primary Bus Number", 1063 pcieadm_cfgspace_print_hex }, 1064 { PCI_BCNF_SECBUS, 1, "secbus", "Secondary Bus Number", 1065 pcieadm_cfgspace_print_hex }, 1066 { PCI_BCNF_SUBBUS, 1, "subbus", "Subordinate Bus Number", 1067 pcieadm_cfgspace_print_hex }, 1068 { PCI_BCNF_LATENCY_TIMER, 1, "latency2", "Secondary Latency timer", 1069 pcieadm_cfgspace_print_unit, &pcieadm_unitdef_latreg }, 1070 { PCI_BCNF_IO_BASE_LOW, 1, "iobase", "I/O Base Low", 1071 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_iobase }, 1072 { PCI_BCNF_IO_LIMIT_LOW, 1, "iolimit", "I/O Limit Low", 1073 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_iolim }, 1074 { PCI_BCNF_SEC_STATUS, 2, "status2", "Secondary Status", 1075 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridgests }, 1076 { PCI_BCNF_MEM_BASE, 2, "membase", "Memory Base", 1077 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_membase }, 1078 { PCI_BCNF_MEM_LIMIT, 2, "memlimit", "Memory Limit", 1079 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_memlim }, 1080 { PCI_BCNF_PF_BASE_LOW, 2, "pfbase", "Prefetchable Memory Base", 1081 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_pfbase }, 1082 { PCI_BCNF_PF_LIMIT_LOW, 2, "pflimit", "Prefetchable Memory Limit", 1083 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_pflim }, 1084 { PCI_BCNF_PF_BASE_HIGH, 4, "pfbasehi", 1085 "Prefetchable Base Upper 32 bits", 1086 pcieadm_cfgspace_print_hex }, 1087 { PCI_BCNF_PF_LIMIT_HIGH, 4, "pflimihi", 1088 "Prefetchable Limit Upper 32 bits", 1089 pcieadm_cfgspace_print_hex }, 1090 { PCI_BCNF_IO_BASE_HI, 2, "iobasehi", "I/O Base Upper 16 bits", 1091 pcieadm_cfgspace_print_hex }, 1092 { PCI_BCNF_IO_LIMIT_HI, 2, "iobasehi", "I/O Limit Upper 16 bits", 1093 pcieadm_cfgspace_print_hex }, 1094 { PCI_BCNF_CAP_PTR, 1, "cap", "Capabilities Pointer", 1095 pcieadm_cfgspace_print_hex }, 1096 { PCI_BCNF_ROM, 4, "rom", "Expansion ROM", 1097 pcieadm_cfgspace_print_regdef, pcieadm_regdef_exprom }, 1098 { PCI_BCNF_ILINE, 1, "iline", "Interrupt Line", 1099 pcieadm_cfgspace_print_hex }, 1100 { PCI_BCNF_IPIN, 1, "ipin", "Interrupt Pin", 1101 pcieadm_cfgspace_print_strmap, pcieadm_strmap_ipin }, 1102 { PCI_BCNF_BCNTRL, 2, "bctl", "Bridge Control", 1103 pcieadm_cfgspace_print_regdef, pcieadm_regdef_bridge_ctl }, 1104 { -1, -1, NULL } 1105 }; 1106 1107 static pcieadm_cfgspace_print_t pcieadm_cfgspace_unknown[] = { 1108 { 0x0, 2, "vendor", "Vendor ID", pcieadm_cfgspace_print_vendor }, 1109 { 0x2, 2, "device", "Device ID", pcieadm_cfgspace_print_device }, 1110 { 0x8, 1, "revision", "Revision ID", pcieadm_cfgspace_print_hex }, 1111 { 0xe, 1, "type", "Header Type", pcieadm_cfgspace_print_regdef, 1112 pcieadm_regdef_header }, 1113 { -1, -1, NULL } 1114 }; 1115 1116 /* 1117 * Power Management Capability Version 3. Note versions two and three seem to be 1118 * the same, but are used to indicate compliance to different revisions of the 1119 * PCI power management specification. 1120 */ 1121 static pcieadm_regdef_t pcieadm_regdef_pmcap[] = { 1122 { 0, 2, "vers", "Version", PRDV_HEX }, 1123 { 3, 3, "clock", "PME Clock", PRDV_STRVAL, 1124 .prd_val = { .prdv_strval = { "not required", "required" } } }, 1125 { 4, 4, "irrd0", "Immediate Readiness on Return to D0", PRDV_STRVAL, 1126 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1127 { 5, 5, "dsi", "Device Specific Initialization", PRDV_STRVAL, 1128 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1129 { 6, 8, "auxcur", "Auxiliary Current", PRDV_STRVAL, 1130 .prd_val = { .prdv_strval = { "0", "55 mA", "100 mA", "160 mA", 1131 "220 mA", "270 mA", "320 mA", "375 mA" } } }, 1132 { 9, 9, "d1", "D1", PRDV_STRVAL, 1133 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1134 { 10, 10, "d2", "D2", PRDV_STRVAL, 1135 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1136 { 11, 15, "pme", "PME Support", PRDV_BITFIELD, 1137 .prd_val = { .prdv_strval = { "D0", "D1", "D2", "D3hot", 1138 "D3cold" } } }, 1139 { -1, -1, NULL } 1140 }; 1141 1142 1143 static pcieadm_cfgspace_print_t pcieadm_cap_pcipm_v3[] = { 1144 { PCI_PMCAP, 2, "pmcap", "Power Management Capabilities", 1145 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pmcap }, 1146 { -1, -1, NULL } 1147 }; 1148 1149 /* 1150 * PCI Bridge Subsystem Capability 1151 */ 1152 static pcieadm_cfgspace_print_t pcieadm_cap_bridge_subsys[] = { 1153 { 0x4, 2, "subvid", "Subsystem Vendor ID", pcieadm_cfgspace_print_hex }, 1154 { 0x6, 2, "subdev", "Subsystem Device ID", pcieadm_cfgspace_print_hex }, 1155 { -1, -1, NULL } 1156 }; 1157 1158 /* 1159 * MSI Capability 1160 */ 1161 static pcieadm_regdef_t pcieadm_regdef_msictrl[] = { 1162 { 0, 0, "enable", "MSI Enable", PRDV_STRVAL, 1163 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1164 { 1, 3, "mmsgcap", "Multiple Message Capable", PRDV_STRVAL, 1165 .prd_val = { .prdv_strval = { "1 vector", "2 vectors", 1166 "4 vectors", "8 vectors", "16 vectors", "32 vectors" } } }, 1167 { 4, 6, "mmsgen", "Multiple Message Enabled", PRDV_STRVAL, 1168 .prd_val = { .prdv_strval = { "1 vector", "2 vectors", 1169 "4 vectors", "8 vectors", "16 vectors", "32 vectors" } } }, 1170 { 7, 7, "addr64", "64-bit Address Capable", PRDV_STRVAL, 1171 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1172 { 8, 8, "pvm", "Per-Vector Masking Capable", PRDV_STRVAL, 1173 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1174 { 9, 9, "extmdcap", "Extended Message Data Capable", 1175 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1176 { 10, 10, "extmden", "extended Message Data Enable", 1177 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1178 { -1, -1, NULL } 1179 }; 1180 1181 static pcieadm_cfgspace_print_t pcieadm_cap_msi_32[] = { 1182 { PCI_MSI_CTRL, 2, "ctrl", "Message Control", 1183 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msictrl }, 1184 { PCI_MSI_ADDR_OFFSET, 4, "addr", "Message Address", 1185 pcieadm_cfgspace_print_hex }, 1186 { PCI_MSI_32BIT_DATA, 2, "data", "Message Data", 1187 pcieadm_cfgspace_print_hex }, 1188 { -1, -1, NULL } 1189 }; 1190 1191 static pcieadm_cfgspace_print_t pcieadm_cap_msi_32ext[] = { 1192 { PCI_MSI_CTRL, 2, "ctrl", "Message Control", 1193 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msictrl }, 1194 { PCI_MSI_ADDR_OFFSET, 4, "addr", "Message Address", 1195 pcieadm_cfgspace_print_hex }, 1196 { PCI_MSI_32BIT_DATA, 2, "data", "Message Data", 1197 pcieadm_cfgspace_print_hex }, 1198 { PCI_MSI_32BIT_EXTDATA, 2, "extdata", "Extended Message Data", 1199 pcieadm_cfgspace_print_hex }, 1200 { -1, -1, NULL } 1201 }; 1202 1203 static pcieadm_cfgspace_print_t pcieadm_cap_msi_32pvm[] = { 1204 { PCI_MSI_CTRL, 2, "ctrl", "Message Control", 1205 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msictrl }, 1206 { PCI_MSI_ADDR_OFFSET, 4, "addr", "Message Address", 1207 pcieadm_cfgspace_print_hex }, 1208 { PCI_MSI_32BIT_DATA, 2, "data", "Message Data", 1209 pcieadm_cfgspace_print_hex }, 1210 { PCI_MSI_32BIT_EXTDATA, 2, "extdata", "Extended Message Data", 1211 pcieadm_cfgspace_print_hex }, 1212 { PCI_MSI_32BIT_MASK, 4, "mask", "Mask Bits", 1213 pcieadm_cfgspace_print_hex }, 1214 { PCI_MSI_32BIT_PENDING, 4, "pend", "Pending Bits", 1215 pcieadm_cfgspace_print_hex }, 1216 { -1, -1, NULL } 1217 }; 1218 1219 static pcieadm_cfgspace_print_t pcieadm_cap_msi_64[] = { 1220 { PCI_MSI_CTRL, 2, "ctrl", "Message Control", 1221 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msictrl }, 1222 { PCI_MSI_ADDR_OFFSET, 4, "addr", "Message Address", 1223 pcieadm_cfgspace_print_hex }, 1224 { PCI_MSI_64BIT_ADDR, 4, "upadd", "Upper Message Address", 1225 pcieadm_cfgspace_print_hex }, 1226 { PCI_MSI_64BIT_DATA, 2, "data", "Message Data", 1227 pcieadm_cfgspace_print_hex }, 1228 { -1, -1, NULL } 1229 }; 1230 1231 static pcieadm_cfgspace_print_t pcieadm_cap_msi_64ext[] = { 1232 { PCI_MSI_CTRL, 2, "ctrl", "Message Control", 1233 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msictrl }, 1234 { PCI_MSI_ADDR_OFFSET, 4, "addr", "Message Address", 1235 pcieadm_cfgspace_print_hex }, 1236 { PCI_MSI_64BIT_ADDR, 4, "upadd", "Upper Message Address", 1237 pcieadm_cfgspace_print_hex }, 1238 { PCI_MSI_64BIT_DATA, 2, "data", "Message Data", 1239 pcieadm_cfgspace_print_hex }, 1240 { PCI_MSI_64BIT_EXTDATA, 2, "extdata", "Extended Message Data", 1241 pcieadm_cfgspace_print_hex }, 1242 { -1, -1, NULL } 1243 }; 1244 1245 static pcieadm_cfgspace_print_t pcieadm_cap_msi_64pvm[] = { 1246 { PCI_MSI_CTRL, 2, "ctrl", "Message Control", 1247 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msictrl }, 1248 { PCI_MSI_ADDR_OFFSET, 4, "addr", "Message Address", 1249 pcieadm_cfgspace_print_hex }, 1250 { PCI_MSI_64BIT_ADDR, 4, "upadd", "Upper Message Address", 1251 pcieadm_cfgspace_print_hex }, 1252 { PCI_MSI_64BIT_DATA, 2, "data", "Message Data", 1253 pcieadm_cfgspace_print_hex }, 1254 { PCI_MSI_64BIT_EXTDATA, 2, "extdata", "Extended Message Data", 1255 pcieadm_cfgspace_print_hex }, 1256 { PCI_MSI_64BIT_MASKBITS, 4, "mask", "Mask Bits", 1257 pcieadm_cfgspace_print_hex }, 1258 { PCI_MSI_64BIT_PENDING, 4, "pend", "Pending Bits", 1259 pcieadm_cfgspace_print_hex }, 1260 { -1, -1, NULL } 1261 }; 1262 1263 /* 1264 * MSI-X Capability 1265 */ 1266 static pcieadm_regdef_t pcieadm_regdef_msixctrl[] = { 1267 { 0, 10, "size", "Table Size", PRDV_HEX, 1268 .prd_val = { .prdv_hex = { 0, 1 } } }, 1269 { 14, 14, "mask", "Function Mask", PRDV_STRVAL, 1270 .prd_val = { .prdv_strval = { "unmasked", "masked" } } }, 1271 { 15, 15, "enable", "MSI-X Enable", PRDV_STRVAL, 1272 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1273 { -1, -1, NULL } 1274 }; 1275 1276 static pcieadm_regdef_t pcieadm_regdef_msixtable[] = { 1277 { 0, 2, "bir", "Table BIR", PRDV_STRVAL, 1278 .prd_val = { .prdv_strval = { "BAR 0", "BAR 1", "BAR 2", "BAR 3", 1279 "BAR 4", "BAR 5" } } }, 1280 { 3, 31, "offset", "Table Offset", PRDV_HEX, 1281 .prd_val = { .prdv_hex = { 3 } } }, 1282 { -1, -1, NULL } 1283 }; 1284 1285 static pcieadm_regdef_t pcieadm_regdef_msixpba[] = { 1286 { 0, 2, "bir", "PBA BIR", PRDV_STRVAL, 1287 .prd_val = { .prdv_strval = { "BAR 0", "BAR 1", "BAR 2", "BAR 3", 1288 "BAR 4", "BAR 5" } } }, 1289 { 3, 31, "offset", "PBA Offset", PRDV_HEX, 1290 .prd_val = { .prdv_hex = { 3 } } }, 1291 { -1, -1, NULL } 1292 }; 1293 1294 1295 static pcieadm_cfgspace_print_t pcieadm_cap_msix[] = { 1296 { PCI_MSIX_CTRL, 2, "ctrl", "Control Register", 1297 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msixctrl }, 1298 { PCI_MSIX_TBL_OFFSET, 4, "table", "Table Offset", 1299 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msixtable }, 1300 { PCI_MSIX_PBA_OFFSET, 4, "pba", "PBA Offset", 1301 pcieadm_cfgspace_print_regdef, pcieadm_regdef_msixpba }, 1302 { -1, -1, NULL } 1303 }; 1304 1305 /* 1306 * PCI Express Capability 1307 */ 1308 static pcieadm_regdef_t pcieadm_regdef_pcie_cap[] = { 1309 { 0, 3, "vers", "Version", PRDV_HEX }, 1310 { 4, 7, "type", "Device/Port Type", PRDV_STRVAL, 1311 .prd_val = { .prdv_strval = { "PCIe Endpoint", 1312 "Legacy PCIe Endpoint", NULL, NULL, 1313 "Root Port of PCIe Root Complex", 1314 "Upstream Port of PCIe Switch", 1315 "Downstream Port of PCIe Switch", 1316 "PCIe to PCI/PCI-X Bridge", 1317 "PCI/PCI-x to PCIe Bridge", 1318 "RCiEP", 1319 "Root Complex Event Collector" } } }, 1320 { 8, 8, "slot", "Slot Implemented", PRDV_STRVAL, 1321 .prd_val = { .prdv_strval = { "No", "Yes" } } }, 1322 { 9, 13, "intno", "Interrupt Message Number", PRDV_HEX }, 1323 { -1, -1, NULL } 1324 }; 1325 1326 static pcieadm_regdef_t pcieadm_regdef_pcie_devcap[] = { 1327 { 0, 2, "mps", "Max Payload Size Supported", PRDV_STRVAL, 1328 .prd_val = { .prdv_strval = { "128 bytes", "256 bytes", 1329 "512 bytes", "1024 byes", "2048 bytes", "4096 bytes" } } }, 1330 { 3, 4, "pfunc", "Phantom Functions Supported", PRDV_STRVAL, 1331 .prd_val = { .prdv_strval = { "No", "1-bit", "2-bits", 1332 "3-bits" } } }, 1333 { 5, 5, "exttag", "Extended Tag Field", PRDV_STRVAL, 1334 .prd_val = { .prdv_strval = { "5-bit", "8-bit" } } }, 1335 { 6, 8, "l0slat", "L0s Acceptable Latency", PRDV_STRVAL, 1336 .prd_val = { .prdv_strval = { "64 ns", "128 ns", "256 ns", 1337 "512 ns", "1 us", "2 us", "4 us", "No limit" } } }, 1338 { 9, 11, "l1lat", "L1 Acceptable Latency", PRDV_STRVAL, 1339 .prd_val = { .prdv_strval = { "1 us", "2 us", "4 us", "8 us", 1340 "16 us", "32 us", "64 us", "No limit" } } }, 1341 { 15, 15, "rber", "Role Based Error Reporting", PRDV_STRVAL, 1342 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1343 { 16, 16, "errcor", "ERR_COR Subclass", PRDV_STRVAL, 1344 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1345 { 18, 25, "csplv", "Captured Slot Power Limit", PRDV_HEX }, 1346 { 26, 27, "cspls", "Captured Slot Power Limit Scale", PRDV_STRVAL, 1347 .prd_val = { .prdv_strval = { "1.0x", "0.1x", "0.01x", 1348 "0.001x" } } }, 1349 { 28, 28, "flr", "Function Level Reset", PRDV_STRVAL, 1350 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1351 { -1, -1, NULL } 1352 }; 1353 1354 static pcieadm_regdef_t pcieadm_regdef_pcie_devctl[] = { 1355 { 0, 0, "corerr", "Correctable Error Reporting", PRDV_STRVAL, 1356 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1357 { 1, 1, "nferr", "Non-Fatal Error Reporting", PRDV_STRVAL, 1358 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1359 { 2, 2, "ferr", "Fatal Error Reporting", PRDV_STRVAL, 1360 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1361 { 3, 3, "unsupreq", "Unsupported Request Reporting", PRDV_STRVAL, 1362 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1363 { 4, 4, "relord", "Relaxed Ordering", PRDV_STRVAL, 1364 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1365 { 5, 7, "mps", "Max Payload Size", PRDV_STRVAL, 1366 .prd_val = { .prdv_strval = { "128 bytes", "256 bytes", 1367 "512 bytes", "1024 byes", "2048 bytes", "4096 bytes" } } }, 1368 { 8, 8, "exttag", "Extended Tag Field", PRDV_STRVAL, 1369 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1370 { 9, 9, "pfunc", "Phantom Functions", PRDV_STRVAL, 1371 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1372 { 9, 9, "auxpm", "Aux Power PM", PRDV_STRVAL, 1373 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1374 { 11, 11, "nosnoop", "No Snoop", PRDV_STRVAL, 1375 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1376 { 12, 14, "mrrs", "Max Read Request Size", PRDV_STRVAL, 1377 .prd_val = { .prdv_strval = { "128 bytes", "256 bytes", 1378 "512 bytes", "1024 byes", "2048 bytes", "4096 bytes" } } }, 1379 { 15, 15, "bcrflr", "Bridge Configuration Retry / Function Level Reset", 1380 PRDV_HEX }, 1381 { -1, -1, NULL } 1382 }; 1383 1384 static pcieadm_regdef_t pcieadm_regdef_pcie_devsts[] = { 1385 { 0, 0, "corerr", "Correctable Error Detected", PRDV_STRVAL, 1386 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1387 { 1, 1, "nferr", "Non-Fatal Error Detected", PRDV_STRVAL, 1388 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1389 { 2, 2, "ferr", "Fatal Error Detected", PRDV_STRVAL, 1390 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1391 { 3, 3, "unsupreq", "Unsupported Request Detected", PRDV_STRVAL, 1392 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1393 { 4, 4, "auxpm", "AUX Power Detected", PRDV_STRVAL, 1394 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1395 { 5, 5, "txpend", "Transactions Pending", PRDV_STRVAL, 1396 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1397 { 6, 6, "eprd", "Emergency Power Reduction Detected", PRDV_STRVAL, 1398 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1399 { -1, -1, NULL } 1400 }; 1401 1402 static pcieadm_regdef_t pcieadm_regdef_pcie_linkcap[] = { 1403 { 0, 3, "maxspeed", "Maximum Link Speed", PRDV_STRVAL, 1404 .prd_val = { .prdv_strval = { NULL, "2.5 GT/s", "5.0 GT/s", 1405 "8.0 GT/s", "16.0 GT/s", "32.0 GT/s" } } }, 1406 { 4, 9, "maxwidth", "Maximum Link Width", PRDV_HEX }, 1407 { 10, 11, "aspm", "ASPM Support", PRDV_STRVAL, 1408 .prd_val = { .prdv_strval = { "None", "L0s", "L1", "L0s/L1" } } }, 1409 { 12, 14, "l0slat", "L0s Exit Latency", PRDV_STRVAL, 1410 .prd_val = { .prdv_strval = { "<64ns", "64-128ns", "128-256ns", 1411 "256-512ns", "512ns-1us", "1-2us", "2-4us", ">4us" } } }, 1412 { 15, 17, "l1lat", "L1 Exit Latency", PRDV_STRVAL, 1413 .prd_val = { .prdv_strval = { "<1us", "1-2us", "2-4us", "4-8us", 1414 "8-16us", "16-32us" "32-64us", ">64us" } } }, 1415 { 18, 18, "clockpm", "Clock Power Management", PRDV_STRVAL, 1416 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1417 { 19, 19, "supdown", "Surprise Down Error Reporting", PRDV_STRVAL, 1418 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1419 { 20, 20, "dlact", "Data Link Layer Active Reporting", PRDV_STRVAL, 1420 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1421 { 21, 21, "linkbw", "Link Bandwidth Notification Capability", 1422 PRDV_STRVAL, 1423 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1424 { 22, 22, "aspmcomp", "ASPM Optionality Compliance", PRDV_STRVAL, 1425 .prd_val = { .prdv_strval = { "not compliant", "compliant" } } }, 1426 { 24, 31, "portno", "Port Number", PRDV_HEX }, 1427 { -1, -1, NULL } 1428 }; 1429 1430 static pcieadm_regdef_t pcieadm_regdef_pcie_linkctl[] = { 1431 { 0, 1, "aspmctl", "ASPM Control", PRDV_STRVAL, 1432 .prd_val = { .prdv_strval = { "None", "L0s", "L1", "L0s/L1" } } }, 1433 { 3, 3, "rcb", "Read Completion Boundary", PRDV_STRVAL, 1434 .prd_val = { .prdv_strval = { "64 byte", "128 byte" } } }, 1435 { 4, 4, "disable", "Link Disable", PRDV_STRVAL, 1436 .prd_val = { .prdv_strval = { "not force disabled", 1437 "force disabled" } } }, 1438 { 5, 5, "retrain", "Retrain Link", PRDV_HEX }, 1439 { 6, 6, "ccc", "Common Clock Configuration", PRDV_STRVAL, 1440 .prd_val = { .prdv_strval = { "asynchronous", "common" } } }, 1441 { 7, 7, "extsync", "Extended Sync", PRDV_HEX, 1442 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1443 { 8, 8, "clkpm", "Clock Power Management", PRDV_HEX, 1444 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1445 { 9, 9, "hwawd", "Hardware Autonomous Width", PRDV_HEX, 1446 .prd_val = { .prdv_strval = { "enabled", "disabled" } } }, 1447 { 10, 10, "linkbwint", "Link Bandwidth Management Interrupt", PRDV_HEX, 1448 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1449 { 11, 11, "linkabwint", "Link Autonomous Bandwidth Interrupt", PRDV_HEX, 1450 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1451 { 14, 15, "drs", "DRS Signaling Control", PRDV_HEX, 1452 .prd_val = { .prdv_strval = { "not reported", "Interrupt enabled", 1453 "DRS->FRS enabled" } } }, 1454 { -1, -1, NULL } 1455 }; 1456 1457 static pcieadm_regdef_t pcieadm_regdef_pcie_linksts[] = { 1458 { 0, 3, "speed", "Link Speed", PRDV_STRVAL, 1459 .prd_val = { .prdv_strval = { NULL, "2.5 GT/s", "5.0 GT/s", 1460 "8.0 GT/s", "16.0 GT/s", "32.0 GT/s" } } }, 1461 { 4, 9, "width", "Link Width", PRDV_HEX }, 1462 { 11, 11, "training", "Link Training", PRDV_STRVAL, 1463 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1464 { 12, 12, "slotclk", "Slot Clock Configuration", PRDV_STRVAL, 1465 .prd_val = { .prdv_strval = { "asynchronous", "common" } } }, 1466 { 13, 13, "dllact", "Data Link Layer Link Active", PRDV_STRVAL, 1467 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1468 { 14, 14, "linkbw", "Link Bandwidth Management Status", PRDV_STRVAL, 1469 .prd_val = { .prdv_strval = { "no change", "change occurred" } } }, 1470 { 15, 15, "linkabw", "Link Autonomous Bandwidth Status", PRDV_STRVAL, 1471 .prd_val = { .prdv_strval = { "no change", "change occurred" } } }, 1472 { -1, -1, NULL } 1473 }; 1474 1475 static pcieadm_regdef_t pcieadm_regdef_pcie_slotcap[] = { 1476 { 0, 0, "attnbtn", "Attention Button Present", PRDV_STRVAL, 1477 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1478 { 1, 1, "pwrctrl", "Power Controller Present", PRDV_STRVAL, 1479 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1480 { 2, 2, "mrlsen", "MRL Sensor Present", PRDV_STRVAL, 1481 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1482 { 3, 3, "attnind", "Attention Indicator Present", PRDV_STRVAL, 1483 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1484 { 4, 4, "powind", "Power Indicator Present", PRDV_STRVAL, 1485 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1486 { 5, 5, "hpsup", "Hot-Plug Surprise", PRDV_STRVAL, 1487 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1488 { 6, 6, "hpcap", "Hot-Plug Capable ", PRDV_STRVAL, 1489 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1490 { 7, 14, "slotplv", "Slot Power Limit Value", PRDV_HEX }, 1491 { 15, 16, "slotpls", "Slot Power Limit Scale", PRDV_HEX }, 1492 { 17, 17, "emi", "Electromechanical Interlock Present", 1493 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1494 { 18, 18, "ncc", "No Command Completed", PRDV_HEX, 1495 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1496 { 19, 31, "slotno", "Physical Slot Number", PRDV_HEX }, 1497 { -1, -1, NULL } 1498 }; 1499 1500 static pcieadm_regdef_t pcieadm_regdef_pcie_slotctl[] = { 1501 { 0, 0, "attnbtn", "Attention Button Pressed", PRDV_STRVAL, 1502 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1503 { 1, 1, "powflt", "Power Fault Detected", PRDV_STRVAL, 1504 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1505 { 2, 2, "mrlsen", "MRL Sensor Changed", PRDV_STRVAL, 1506 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1507 { 3, 3, "presdet", "Presence Detect Changed", PRDV_STRVAL, 1508 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1509 { 4, 4, "ccmpltint", "Command Complete Interrupt", PRDV_STRVAL, 1510 .prd_val = { .prdv_strval = { "disabled", "Enabled" } } }, 1511 { 5, 5, "hpi", "Hot Plug Interrupt Enable", PRDV_STRVAL, 1512 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1513 { 6, 7, "attnind", "Attention Indicator Control", PRDV_STRVAL, 1514 .prd_val = { .prdv_strval = { NULL, "on", "blink", "off" } } }, 1515 { 8, 9, "powin", "Power Indicator Control", PRDV_STRVAL, 1516 .prd_val = { .prdv_strval = { NULL, "on", "blink", "off" } } }, 1517 { 10, 10, "pwrctrl", "Power Controller Control", PRDV_STRVAL, 1518 .prd_val = { .prdv_strval = { "power on", "power off" } } }, 1519 { 11, 11, "emi", "Electromechanical Interlock Control", PRDV_HEX }, 1520 { 12, 12, "dll", "Data Link Layer State Changed", PRDV_STRVAL, 1521 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1522 { 13, 13, "autopowdis", "Auto Slot Power Limit", PRDV_STRVAL, 1523 .prd_val = { .prdv_strval = { "enabled", "disabled" } } }, 1524 { 14, 14, "ibpddis", "In-Band PD", PRDV_STRVAL, 1525 .prd_val = { .prdv_strval = { "enabled", "disabled" } } }, 1526 { -1, -1, NULL } 1527 }; 1528 1529 static pcieadm_regdef_t pcieadm_regdef_pcie_slotsts[] = { 1530 { 0, 0, "attnbtn", "Attention Button Pressed", PRDV_STRVAL, 1531 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1532 { 1, 1, "powflt", "Power Fault Detected", PRDV_STRVAL, 1533 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1534 { 2, 2, "mrlsen", "MRL Sensor Changed", PRDV_STRVAL, 1535 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1536 { 3, 3, "presdet", "Presence Detect Changed", PRDV_STRVAL, 1537 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1538 { 4, 4, "ccmplt", "Command Complete", PRDV_STRVAL, 1539 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1540 { 5, 5, "mrlsen", "MRL Sensor State", PRDV_STRVAL, 1541 .prd_val = { .prdv_strval = { "closed", "open" } } }, 1542 { 6, 6, "presdet", "Presence Detect State", PRDV_STRVAL, 1543 .prd_val = { .prdv_strval = { "not present", "present" } } }, 1544 { 7, 7, "emi", "Electromechanical Interlock", PRDV_STRVAL, 1545 .prd_val = { .prdv_strval = { "disengaged", "engaged" } } }, 1546 { 8, 8, "dll", "Data Link Layer State Changed", PRDV_STRVAL, 1547 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1548 { -1, -1, NULL } 1549 }; 1550 1551 static pcieadm_regdef_t pcieadm_regdef_pcie_rootcap[] = { 1552 { 0, 0, "syscorerr", "System Error on Correctable Error", PRDV_STRVAL, 1553 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1554 { 1, 1, "sysnonftl", "System Error on Non-Fatal Error", PRDV_STRVAL, 1555 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1556 { 2, 2, "sysfatal", "System Error on Fatal Error", PRDV_STRVAL, 1557 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1558 { 3, 3, "pmeie", "PME Interrupt", PRDV_STRVAL, 1559 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1560 { 4, 4, "crssw", "CRS Software Visibility", PRDV_STRVAL, 1561 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1562 { -1, -1, NULL } 1563 }; 1564 1565 static pcieadm_regdef_t pcieadm_regdef_pcie_rootctl[] = { 1566 { 0, 0, "crssw", "CRS Software Visibility", PRDV_STRVAL, 1567 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1568 { -1, -1, NULL } 1569 }; 1570 1571 static pcieadm_regdef_t pcieadm_regdef_pcie_rootsts[] = { 1572 { 0, 15, "pmereqid", "PME Requester ID", PRDV_HEX }, 1573 { 16, 16, "pmests", "PME Status", PRDV_STRVAL, 1574 .prd_val = { .prdv_strval = { "deasserted", "asserted" } } }, 1575 { 17, 17, "pmepend", "PME Pending", PRDV_STRVAL, 1576 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1577 { -1, -1, NULL } 1578 }; 1579 1580 static pcieadm_regdef_t pcieadm_regdef_pcie_devcap2[] = { 1581 { 0, 3, "cmpto", "Completion Timeout Ranges Supported", PRDV_BITFIELD, 1582 .prd_val = { .prdv_strval = { "50us-10ms", "10ms-250ms", 1583 "250ms-4s", "4s-64s" } } }, 1584 { 4, 4, "cmptodis", "Completion Timeout Disable", PRDV_STRVAL, 1585 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1586 { 5, 5, "ari", "ARI Forwarding", PRDV_STRVAL, 1587 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1588 { 6, 6, "atomroute", "AtomicOp Routing", PRDV_STRVAL, 1589 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1590 { 7, 7, "atom32", "32-bit AtomicOp Completer", PRDV_STRVAL, 1591 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1592 { 8, 8, "atom64", "64-bit AtomicOp Completer", PRDV_STRVAL, 1593 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1594 { 9, 9, "cas128", "128-bit CAS Completer", PRDV_STRVAL, 1595 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1596 { 10, 10, "norelord", "No Ro-enabld PR-PR Passing", PRDV_STRVAL, 1597 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1598 { 11, 11, "ltr", "LTR Mechanism", PRDV_STRVAL, 1599 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1600 { 12, 13, "tph", "TPH Completer", PRDV_STRVAL, 1601 .prd_val = { .prdv_strval = { "unsupported", "TPH supported", 1602 NULL, "TPH and Extended TPH supported" } } }, 1603 { 14, 15, "lncls", "LN System CLS", PRDV_STRVAL, 1604 .prd_val = { .prdv_strval = { "unsupported", 1605 "LN with 64-byte cachelines", "LN with 128-byte cachelines" } } }, 1606 { 16, 16, "tag10comp", "10-bit Tag Completer", PRDV_STRVAL, 1607 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1608 { 17, 17, "tag10req", "10-bit Tag Requester", PRDV_STRVAL, 1609 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1610 { 18, 19, "obff", "OBFF", PRDV_STRVAL, 1611 .prd_val = { .prdv_strval = { "unsupported", "Message Signaling", 1612 "WAKE# Signaling", "WAKE# and Message Signaling" } } }, 1613 { 20, 20, "extfmt", "Extended Fmt Field Supported", PRDV_STRVAL, 1614 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1615 { 21, 21, "eetlp", "End-End TLP Prefix Supported", PRDV_STRVAL, 1616 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1617 { 22, 23, "maxeetlp", "Max End-End TLP Prefixes", PRDV_STRVAL, 1618 .prd_val = { .prdv_strval = { "4", "1", "2", "3" } } }, 1619 { 24, 25, "empr", "Emergency Power Reduction", PRDV_STRVAL, 1620 .prd_val = { .prdv_strval = { "unsupported", 1621 "supported, device-specific", 1622 "supported, from factor or device-specific" } } }, 1623 { 21, 21, "emprinit", 1624 "Emergency Power Reduction Initialization Required", PRDV_STRVAL, 1625 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1626 { 31, 31, "frs", "Function Readiness Status", PRDV_STRVAL, 1627 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1628 { -1, -1, NULL } 1629 }; 1630 1631 static pcieadm_regdef_t pcieadm_regdef_pcie_devctl2[] = { 1632 { 0, 3, "cmpto", "Completion Timeout", PRDV_STRVAL, 1633 .prd_val = { .prdv_strval = { "50us-50ms", "50us-100us", 1634 "1ms-10ms", NULL, NULL, "16ms-55ms", "65ms-210ms", NULL, NULL, 1635 "260ms-900ms", "1s-3.5s", NULL, NULL, "4s-13s", "17s-64s" } } }, 1636 { 4, 4, "cmptodis", "Completion Timeout Disabled", PRDV_STRVAL, 1637 .prd_val = { .prdv_strval = { "not disabled", "disabled" } } }, 1638 { 5, 5, "ari", "ARI Forwarding", PRDV_STRVAL, 1639 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1640 { 6, 6, "atomreq", "AtomicOp Requester", PRDV_STRVAL, 1641 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1642 { 7, 7, "atomblock", "AtomicOp Egress Blocking", PRDV_STRVAL, 1643 .prd_val = { .prdv_strval = { "unblocked", "blocked" } } }, 1644 { 8, 8, "idoreq", "ID-Based Ordering Request", PRDV_STRVAL, 1645 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1646 { 9, 9, "idocomp", "ID-Based Ordering Completion", PRDV_STRVAL, 1647 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1648 { 10, 10, "ltr", "LTR Mechanism", PRDV_STRVAL, 1649 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1650 { 11, 11, "empowred", "Emergency Power Reduction", PRDV_STRVAL, 1651 .prd_val = { .prdv_strval = { "not requested", "requested" } } }, 1652 { 12, 12, "tag10req", "10-bit Tag Requester", PRDV_STRVAL, 1653 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1654 { 13, 14, "obff", "OBFF", PRDV_STRVAL, 1655 .prd_val = { .prdv_strval = { "disabled", "message signaling - A", 1656 "message signaling - B", "WAKE# signaling" } } }, 1657 { 15, 15, "eetlpblk", "End-End TLP Prefix Blocking", PRDV_STRVAL, 1658 .prd_val = { .prdv_strval = { "unblocked", "blocked" } } }, 1659 { -1, -1, NULL } 1660 }; 1661 1662 static pcieadm_regdef_t pcieadm_regdef_pcie_devsts2[] = { 1663 { -1, -1, NULL } 1664 }; 1665 1666 static pcieadm_regdef_t pcieadm_regdef_pcie_linkcap2[] = { 1667 { 1, 7, "supspeeds", "Supported Link Speeds", PRDV_BITFIELD, 1668 .prd_val = { .prdv_strval = { "2.5 GT/s", "5.0 GT/s", "8.0 GT/s", 1669 "16.0 GT/s", "32.0 GT/s" } } }, 1670 { 8, 8, "crosslink", "Crosslink", PRDV_STRVAL, 1671 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1672 { 9, 15, "skposgen", "Lower SKP OS Generation Supported Speeds Vector", 1673 PRDV_BITFIELD, 1674 .prd_val = { .prdv_strval = { "2.5 GT/s", "5.0 GT/s", "8.0 GT/s", 1675 "16.0 GT/s", "32.0 GT/s" } } }, 1676 { 16, 22, "skposrecv", "Lower SKP OS Reception Supported Speeds Vector", 1677 PRDV_BITFIELD, 1678 .prd_val = { .prdv_strval = { "2.5 GT/s", "5.0 GT/s", "8.0 GT/s", 1679 "16.0 GT/s", "32.0 GT/s" } } }, 1680 { 23, 23, "retimedet", "Retimer Presence Detect Supported", PRDV_STRVAL, 1681 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1682 { 24, 24, "retime2det", "Two Retimers Presence Detect Supported", 1683 PRDV_STRVAL, 1684 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1685 { 31, 31, "drs", "Device Readiness Status", PRDV_STRVAL, 1686 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1687 { -1, -1, NULL } 1688 }; 1689 1690 static pcieadm_regdef_t pcieadm_regdef_pcie_linkctl2[] = { 1691 { 0, 3, "targspeed", "Target Link Speed", PRDV_STRVAL, 1692 .prd_val = { .prdv_strval = { NULL, "2.5 GT/s", "5.0 GT/s", 1693 "8.0 GT/s", "16.0 GT/s", "32.0 GT/s" } } }, 1694 { 4, 4, "comp", "Enter Compliance", PRDV_STRVAL, 1695 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1696 { 5, 5, "hwautosp", "Hardware Autonomous Speed Disable", PRDV_STRVAL, 1697 .prd_val = { .prdv_strval = { "not disabled", "disabled" } } }, 1698 { 6, 6, "seldeemph", "Selectable De-emphasis", PRDV_STRVAL, 1699 .prd_val = { .prdv_strval = { "-6 dB", "-3.5 dB" } } }, 1700 { 7, 9, "txmarg", "TX Margin", PRDV_HEX }, 1701 { 10, 10, "modcomp", "Enter Modified Compliance", PRDV_STRVAL, 1702 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1703 { 11, 11, "compsos", "Compliance SOS", 1704 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1705 { 12, 15, "compemph", "Compliance Preset/De-emphasis", PRDV_HEX }, 1706 { -1, -1, NULL } 1707 }; 1708 1709 static pcieadm_regdef_t pcieadm_regdef_pcie_linksts2[] = { 1710 { 0, 0, "curdeemph", "Current De-emphasis Level", PRDV_STRVAL, 1711 .prd_val = { .prdv_strval = { "-6 dB", "-3.5 dB" } } }, 1712 { 1, 1, "eq8comp", "Equalization 8.0 GT/s Complete", PRDV_STRVAL, 1713 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1714 { 2, 2, "eq8p1comp", "Equalization 8.0 GT/s Phase 1", PRDV_STRVAL, 1715 .prd_val = { .prdv_strval = { "unsuccessful", "successful" } } }, 1716 { 3, 3, "eq8p2comp", "Equalization 8.0 GT/s Phase 2", PRDV_STRVAL, 1717 .prd_val = { .prdv_strval = { "unsuccessful", "successful" } } }, 1718 { 4, 4, "eq8p3comp", "Equalization 8.0 GT/s Phase 3", PRDV_STRVAL, 1719 .prd_val = { .prdv_strval = { "unsuccessful", "successful" } } }, 1720 { 5, 5, "linkeq8req", "Link Equalization Request 8.0 GT/s", PRDV_STRVAL, 1721 .prd_val = { .prdv_strval = { "not requested", "requested" } } }, 1722 { 6, 6, "retimedet", "Retimer Presence Detected", PRDV_STRVAL, 1723 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1724 { 7, 7, "retime2det", "Two Retimers Presence Detected", PRDV_STRVAL, 1725 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1726 { 8, 9, "crosslink", "Crosslink Resolution", PRDV_STRVAL, 1727 .prd_val = { .prdv_strval = { "unsupported", "upstream port", 1728 "downstream port", "incomplete" } } }, 1729 { 12, 14, "dscomppres", "Downstream Component Presence", PRDV_STRVAL, 1730 .prd_val = { .prdv_strval = { "link down - undetermined", 1731 "link down - not present", "link down - present", NULL, 1732 "link up - present", "link up - present and DRS" } } }, 1733 { 15, 15, "drsrx", "DRS Message Received", PRDV_STRVAL, 1734 .prd_val = { .prdv_strval = { "no", "yes" } } }, 1735 { -1, -1, NULL } 1736 }; 1737 1738 static pcieadm_regdef_t pcieadm_regdef_pcie_slotcap2[] = { 1739 { 0, 0, "ibpddis", "In-Band PD Disable", PRDV_STRVAL, 1740 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1741 { -1, -1, NULL } 1742 }; 1743 1744 static pcieadm_regdef_t pcieadm_regdef_pcie_slotctl2[] = { 1745 { -1, -1, NULL } 1746 }; 1747 1748 static pcieadm_regdef_t pcieadm_regdef_pcie_slotsts2[] = { 1749 { -1, -1, NULL } 1750 }; 1751 1752 1753 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v1[] = { 1754 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1755 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1756 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1757 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1758 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1759 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1760 { PCIE_LINKCAP, 4, "linkcap", "Link Capabilities", 1761 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap }, 1762 { PCIE_LINKCTL, 2, "linkctl", "Link Control", 1763 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl }, 1764 { PCIE_LINKSTS, 2, "linksts", "Link Status", 1765 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts }, 1766 { PCIE_SLOTCAP, 4, "slotcap", "Slot Capabilities", 1767 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap }, 1768 { PCIE_SLOTCTL, 2, "slotctl", "Slot Control", 1769 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl }, 1770 { PCIE_SLOTSTS, 2, "slotsts", "Slot Status", 1771 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts }, 1772 { PCIE_ROOTCTL, 2, "rootctl", "Root control", 1773 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootctl }, 1774 { PCIE_ROOTCAP, 2, "rootcap", "Root Capabilities", 1775 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootcap }, 1776 { PCIE_ROOTSTS, 4, "rootsts", "Root Status", 1777 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootsts }, 1778 { -1, -1, NULL } 1779 }; 1780 1781 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v2[] = { 1782 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1783 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1784 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1785 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1786 { PCIE_DEVCTL, 2, "devctl", "Device Control", 1787 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devctl }, 1788 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1789 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1790 { PCIE_LINKCAP, 4, "linkcap", "Link Capabilities", 1791 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap }, 1792 { PCIE_LINKCTL, 2, "linkctl", "Link Control", 1793 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl }, 1794 { PCIE_LINKSTS, 2, "linksts", "Link Status", 1795 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts }, 1796 { PCIE_SLOTCAP, 4, "slotcap", "Slot Capabilities", 1797 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap }, 1798 { PCIE_SLOTCTL, 2, "slotctl", "Slot Control", 1799 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl }, 1800 { PCIE_SLOTSTS, 2, "slotsts", "Slot Status", 1801 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts }, 1802 { PCIE_ROOTCTL, 2, "rootctl", "Root Control", 1803 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootctl }, 1804 { PCIE_ROOTCAP, 2, "rootcap", "Root Capabilities", 1805 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootcap }, 1806 { PCIE_ROOTSTS, 4, "rootsts", "Root Status", 1807 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootsts }, 1808 { PCIE_DEVCAP2, 4, "devcap2", "Device Capabilities 2", 1809 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap2 }, 1810 { PCIE_DEVCTL2, 2, "devctl2", "Device Control 2", 1811 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devctl2 }, 1812 { PCIE_DEVSTS2, 2, "devsts2", "Device Status 2", 1813 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts2 }, 1814 { PCIE_LINKCAP2, 4, "linkcap2", "Link Capabilities 2", 1815 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap2 }, 1816 { PCIE_LINKCTL2, 2, "linkctl2", "Link Control 2", 1817 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl2 }, 1818 { PCIE_LINKSTS2, 2, "linksts2", "Link Status 2", 1819 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts2 }, 1820 { PCIE_SLOTCAP2, 4, "slotcap2", "Slot Capabilities 2", 1821 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap2 }, 1822 { PCIE_SLOTCTL2, 2, "slotctl2", "Slot Control 2", 1823 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl2 }, 1824 { PCIE_SLOTSTS2, 2, "slotsts2", "Slot Status 2", 1825 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts2 }, 1826 { -1, -1, NULL } 1827 }; 1828 1829 /* 1830 * PCIe Extended Capability Header 1831 */ 1832 static pcieadm_regdef_t pcieadm_regdef_pcie_caphdr[] = { 1833 { 0, 15, "capid", "Capability ID", PRDV_HEX }, 1834 { 16, 19, "version", "Capability Version", PRDV_HEX }, 1835 { 20, 32, "offset", "Next Capability Offset", PRDV_HEX }, 1836 { -1, -1, NULL } 1837 }; 1838 1839 /* 1840 * VPD Capability 1841 */ 1842 static pcieadm_regdef_t pcieadm_regdef_vpd_addr[] = { 1843 { 0, 14, "addr", "VPD Address", PRDV_HEX }, 1844 { 15, 15, "flag", "Flag", PRDV_HEX }, 1845 { -1, -1, NULL } 1846 }; 1847 1848 static pcieadm_cfgspace_print_t pcieadm_cap_vpd[] = { 1849 { 0x2, 2, "addr", "VPD Address Register", 1850 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vpd_addr }, 1851 { 0x4, 4, "data", "VPD Data", pcieadm_cfgspace_print_hex }, 1852 { -1, -1, NULL } 1853 }; 1854 1855 /* 1856 * SATA Capability per AHCI 1.3.1 1857 */ 1858 static pcieadm_regdef_t pcieadm_regdef_sata_cr0[] = { 1859 { 0, 3, "minrev", "Minor Revision", PRDV_HEX }, 1860 { 4, 7, "majrev", "Major Revision", PRDV_HEX }, 1861 { -1, -1, NULL } 1862 }; 1863 1864 static pcieadm_regdef_t pcieadm_regdef_sata_cr1[] = { 1865 { 0, 3, "bar", "BAR Location", PRDV_HEX, 1866 .prd_val = { .prdv_hex = { 2 } } }, 1867 { 4, 23, "offset", "BAR Offset", PRDV_HEX, 1868 .prd_val = { .prdv_hex = { 2 } } }, 1869 { -1, -1, NULL } 1870 }; 1871 1872 static pcieadm_cfgspace_print_t pcieadm_cap_sata[] = { 1873 { 0x2, 2, "satacr0", "SATA Capability Register 0", 1874 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sata_cr0 }, 1875 { 0x4, 4, "satacr1", "SATA Capability Register 1", 1876 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sata_cr1 }, 1877 { -1, -1, NULL } 1878 }; 1879 1880 /* 1881 * Debug Capability per EHCI 1882 */ 1883 static pcieadm_regdef_t pcieadm_regdef_debug[] = { 1884 { 0, 12, "offset", "BAR Offset", PRDV_HEX }, 1885 { 13, 15, "bar", "BAR Location ", PRDV_STRVAL, 1886 .prd_val = { .prdv_strval = { NULL, "BAR 0", "BAR 1", "BAR 2", 1887 "BAR 3", "BAR 4", "BAR 5" } } }, 1888 { -1, -1, NULL } 1889 }; 1890 1891 static pcieadm_cfgspace_print_t pcieadm_cap_debug[] = { 1892 { 0x2, 2, "port", "Debug Port", 1893 pcieadm_cfgspace_print_regdef, pcieadm_regdef_debug }, 1894 { -1, -1, NULL } 1895 }; 1896 1897 /* 1898 * AER Capability 1899 */ 1900 static pcieadm_regdef_t pcieadm_regdef_aer_ue[] = { 1901 { 4, 4, "dlp", "Data Link Protocol Error", PRDV_HEX }, 1902 { 5, 5, "sde", "Surprise Down Error", PRDV_HEX }, 1903 { 12, 12, "ptlp", "Poisoned TLP Received", PRDV_HEX }, 1904 { 13, 13, "fcp", "Flow Control Protocol Error", PRDV_HEX }, 1905 { 14, 14, "cto", "Completion Timeout", PRDV_HEX }, 1906 { 15, 15, "cab", "Completion Abort", PRDV_HEX }, 1907 { 16, 16, "unco", "Unexpected Completion", PRDV_HEX }, 1908 { 17, 17, "rxov", "Receiver Overflow", PRDV_HEX }, 1909 { 18, 18, "maltlp", "Malformed TLP", PRDV_HEX }, 1910 { 19, 19, "ecrc", "ECRC Error", PRDV_HEX }, 1911 { 20, 20, "usuprx", "Unsupported Request Error", PRDV_HEX }, 1912 { 21, 21, "acs", "ACS Violation", PRDV_HEX }, 1913 { 22, 22, "ueint", "Uncorrectable Internal Error", PRDV_HEX }, 1914 { 23, 23, "mcbtlp", "MC Blocked TLP", PRDV_HEX }, 1915 { 24, 24, "atoomeb", "AtomicOp Egress Blocked", PRDV_HEX }, 1916 { 25, 25, "tlppb", "TLP Prefix Blocked Error", PRDV_HEX }, 1917 { 26, 26, "ptlpeb", "Poisoned TLP Egress Blocked", PRDV_HEX }, 1918 { -1, -1, NULL } 1919 }; 1920 1921 static pcieadm_regdef_t pcieadm_regdef_aer_ce[] = { 1922 { 0, 0, "rxerr", "Receiver Error", PRDV_HEX }, 1923 { 6, 6, "badtlp", "Bad TLP", PRDV_HEX }, 1924 { 7, 7, "baddllp", "Bad DLLP", PRDV_HEX }, 1925 { 8, 8, "replayro", "REPLAY_NUM Rollover", PRDV_HEX }, 1926 { 12, 12, "rtto", "Replay timer Timeout", PRDV_HEX }, 1927 { 13, 13, "advnfe", "Advisory Non-Fatal Error", PRDV_HEX }, 1928 { 14, 14, "ceint", "Correctable Internal Error", PRDV_HEX }, 1929 { 15, 15, "headlov", "Header Log Overflow", PRDV_HEX }, 1930 { -1, -1, NULL } 1931 }; 1932 1933 static pcieadm_regdef_t pcieadm_regdef_aer_ctrl[] = { 1934 { 0, 4, "feptr", "First Error Pointer", PRDV_HEX }, 1935 { 5, 5, "ecgencap", "ECRC Generation Capable", PRDV_STRVAL, 1936 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1937 { 6, 6, "ecgenen", "ECRC Generation Enable", PRDV_STRVAL, 1938 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1939 { 7, 7, "ecchkcap", "ECRC Check Capable", PRDV_STRVAL, 1940 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1941 { 8, 8, "ecchken", "ECRC Check Enable", PRDV_STRVAL, 1942 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1943 { -1, -1, NULL } 1944 }; 1945 1946 static pcieadm_regdef_t pcieadm_regdef_aer_rootcom[] = { 1947 { 0, 0, "corerr", "Correctable Error Reporting", PRDV_STRVAL, 1948 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1949 { 1, 1, "nferr", "Non-Fatal Error Reporting", PRDV_STRVAL, 1950 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1951 { 2, 2, "faterr", "Fatal Error Reporting", PRDV_STRVAL, 1952 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1953 { -1, -1, NULL } 1954 }; 1955 1956 static pcieadm_regdef_t pcieadm_regdef_aer_rootsts[] = { 1957 { 0, 0, "errcor", "ERR_COR Received", PRDV_HEX }, 1958 { 1, 1, "merrcor", "Multiple ERR_COR Received", PRDV_HEX }, 1959 { 2, 2, "errfnf", "ERR_FATAL/NONFATAL Received", PRDV_HEX }, 1960 { 3, 3, "merrfnf", "Multiple ERR_FATAL/NONFATAL Received", PRDV_HEX }, 1961 { 4, 4, "fuefat", "First Uncorrectable Fatal", PRDV_HEX }, 1962 { 5, 5, "nferrrx", "Non-Fatal Error Messages Received", PRDV_HEX }, 1963 { 6, 6, "faterrx", "Fatal Error Messages Received", PRDV_HEX }, 1964 { 7, 8, "errcorsc", "ERR_COR Subclass", PRDV_STRVAL, 1965 .prd_val = { .prdv_strval = { "ECS Legacy", "ECS SIG_SFW", 1966 "ECS SIG_OS", "ECS Extended" } } }, 1967 { 27, 31, "inum", "Advanced Error Interrupt Message", PRDV_HEX }, 1968 { -1, -1, NULL } 1969 }; 1970 1971 static pcieadm_regdef_t pcieadm_regdef_aer_esi[] = { 1972 { 0, 15, "errcorr", "ERR_COR Source", PRDV_HEX }, 1973 { 16, 31, "errfnf", "ERR_FATAL/NONFATAL Source", PRDV_HEX }, 1974 { -1, -1, NULL } 1975 }; 1976 1977 static pcieadm_regdef_t pcieadm_regdef_aer_secue[] = { 1978 { 0, 0, "taosc", "Target-Abort on Split Completion", PRDV_HEX }, 1979 { 1, 1, "maosc", "Master-Abort on Split Completion", PRDV_HEX }, 1980 { 2, 2, "rxta", "Received Target-Abort", PRDV_HEX }, 1981 { 3, 3, "rxma", "Received Master-Abort", PRDV_HEX }, 1982 { 5, 5, "unsce", "Unexpected Split Completion Error", PRDV_HEX }, 1983 { 6, 6, "uescmd", "Uncorrectable Split Completion Message Data Error", 1984 PRDV_HEX }, 1985 { 7, 7, "uede", "Uncorrectable Data Error", PRDV_HEX }, 1986 { 8, 8, "ueattre", "Uncorrectable Attribute Error", PRDV_HEX }, 1987 { 9, 9, "ueaddre", "Uncorrectable Address Error", PRDV_HEX }, 1988 { 10, 10, "dtdte", "Delayed Transaction Discard Timer Expired", 1989 PRDV_HEX }, 1990 { 11, 11, "perr", "PERR# Assertion", PRDV_HEX }, 1991 { 12, 12, "serr", "SERR# Assertion", PRDV_HEX }, 1992 { 13, 13, "internal", "Internal Bridge Error", PRDV_HEX }, 1993 { -1, -1, NULL } 1994 }; 1995 1996 static pcieadm_regdef_t pcieadm_regdef_aer_secctl[] = { 1997 { 0, 4, "feptr", "Secondary Uncorrectable First Error Pointer", 1998 PRDV_HEX }, 1999 { -1, -1, NULL } 2000 }; 2001 2002 static pcieadm_cfgspace_print_t pcieadm_cap_aer_v1[] = { 2003 { PCIE_AER_CAP, 4, "caphdr", "Capability Header", 2004 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2005 { PCIE_AER_UCE_STS, 4, "uestatus", "Uncorrectable Error Status", 2006 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2007 { PCIE_AER_UCE_MASK, 4, "uemask", "Uncorrectable Error Mask", 2008 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2009 { PCIE_AER_UCE_SERV, 4, "ueserv", "Uncorrectable Error Severity", 2010 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2011 { PCIE_AER_CE_STS, 4, "cestatus", "Correctable Error Status", 2012 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2013 { PCIE_AER_CE_MASK, 4, "cemask", "Correctable Error Mask", 2014 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2015 { PCIE_AER_CTL, 4, "ctrl", "Advanced Error Capabilities and Control", 2016 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ctrl }, 2017 { PCIE_AER_HDR_LOG + 4, 4, "hl0", "Header Log 0", 2018 pcieadm_cfgspace_print_hex }, 2019 { PCIE_AER_HDR_LOG + 8, 4, "hl1", "Header Log 1", 2020 pcieadm_cfgspace_print_hex }, 2021 { PCIE_AER_HDR_LOG + 12, 4, "hl2", "Header Log 2", 2022 pcieadm_cfgspace_print_hex }, 2023 { PCIE_AER_HDR_LOG + 12, 4, "hl3", "Header Log 3", 2024 pcieadm_cfgspace_print_hex }, 2025 { PCIE_AER_CTL, 4, "rootcmd", "Root Error Command", 2026 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootcom }, 2027 { PCIE_AER_RE_STS, 4, "rootsts", "Root Error Status", 2028 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootsts }, 2029 { PCIE_AER_CE_SRC_ID, 4, "esi", "Error Source Identification", 2030 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_esi }, 2031 { -1, -1, NULL } 2032 }; 2033 2034 static pcieadm_cfgspace_print_t pcieadm_cap_aer_v2[] = { 2035 { PCIE_AER_CAP, 4, "caphdr", "Capability Header", 2036 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2037 { PCIE_AER_UCE_STS, 4, "uestatus", "Uncorrectable Error Status", 2038 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2039 { PCIE_AER_UCE_MASK, 4, "uemask", "Uncorrectable Error Mask", 2040 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2041 { PCIE_AER_UCE_SERV, 4, "ueserv", "Uncorrectable Error Severity", 2042 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2043 { PCIE_AER_CE_STS, 4, "cestatus", "Correctable Error Status", 2044 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2045 { PCIE_AER_CE_MASK, 4, "cemask", "Correctable Error Mask", 2046 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2047 { PCIE_AER_CTL, 4, "ctrl", "Advanced Error Capabilities and Control", 2048 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ctrl }, 2049 { PCIE_AER_HDR_LOG + 4, 4, "hl0", "Header Log 0", 2050 pcieadm_cfgspace_print_hex }, 2051 { PCIE_AER_HDR_LOG + 8, 4, "hl1", "Header Log 1", 2052 pcieadm_cfgspace_print_hex }, 2053 { PCIE_AER_HDR_LOG + 12, 4, "hl2", "Header Log 2", 2054 pcieadm_cfgspace_print_hex }, 2055 { PCIE_AER_HDR_LOG + 12, 4, "hl3", "Header Log 3", 2056 pcieadm_cfgspace_print_hex }, 2057 { PCIE_AER_CTL, 4, "rootcmd", "Root Error Command", 2058 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootcom }, 2059 { PCIE_AER_RE_STS, 4, "rootsts", "Root Error Status", 2060 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootsts }, 2061 { PCIE_AER_TLP_PRE_LOG, 4, "tlplog0", "TLP Prefix Log 0", 2062 pcieadm_cfgspace_print_hex }, 2063 { PCIE_AER_TLP_PRE_LOG + 4, 4, "tlplog1", "TLP Prefix Log 1", 2064 pcieadm_cfgspace_print_hex }, 2065 { PCIE_AER_TLP_PRE_LOG + 8, 4, "tlplog2", "TLP Prefix Log 2", 2066 pcieadm_cfgspace_print_hex }, 2067 { PCIE_AER_TLP_PRE_LOG + 12, 4, "tlplog3", "TLP Prefix Log 3", 2068 pcieadm_cfgspace_print_hex }, 2069 { -1, -1, NULL } 2070 }; 2071 2072 static pcieadm_cfgspace_print_t pcieadm_cap_aer_bridge[] = { 2073 { PCIE_AER_CAP, 4, "caphdr", "Capability Header", 2074 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2075 { PCIE_AER_UCE_STS, 4, "uestatus", "Uncorrectable Error Status", 2076 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2077 { PCIE_AER_UCE_MASK, 4, "uemask", "Uncorrectable Error Mask", 2078 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2079 { PCIE_AER_UCE_SERV, 4, "ueserv", "Uncorrectable Error Severity", 2080 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2081 { PCIE_AER_CE_STS, 4, "cestatus", "Correctable Error Status", 2082 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2083 { PCIE_AER_CE_MASK, 4, "cemask", "Correctable Error Mask", 2084 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2085 { PCIE_AER_CTL, 4, "ctrl", "Advanced Error Capabilities and Control", 2086 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ctrl }, 2087 { PCIE_AER_HDR_LOG + 4, 4, "hl0", "Header Log 0", 2088 pcieadm_cfgspace_print_hex }, 2089 { PCIE_AER_HDR_LOG + 8, 4, "hl1", "Header Log 1", 2090 pcieadm_cfgspace_print_hex }, 2091 { PCIE_AER_HDR_LOG + 12, 4, "hl2", "Header Log 2", 2092 pcieadm_cfgspace_print_hex }, 2093 { PCIE_AER_HDR_LOG + 12, 4, "hl3", "Header Log 3", 2094 pcieadm_cfgspace_print_hex }, 2095 { PCIE_AER_CTL, 4, "rootcmd", "Root Error Command", 2096 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootcom }, 2097 { PCIE_AER_RE_STS, 4, "rootsts", "Root Error Status", 2098 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootsts }, 2099 { PCIE_AER_CE_SRC_ID, 4, "esi", "Error Source Identification", 2100 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_esi }, 2101 { PCIE_AER_SUCE_STS, 4, "secuests", 2102 "Secondary Uncorrectable Error Status", 2103 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secue }, 2104 { PCIE_AER_SUCE_MASK, 4, "secuests", 2105 "Secondary Uncorrectable Error Mask", 2106 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secue }, 2107 { PCIE_AER_SUCE_SERV, 4, "secuests", 2108 "Secondary Uncorrectable Error Severity", 2109 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secue }, 2110 { PCIE_AER_SCTL, 4, "secctrl", 2111 "Secondary Error Capabilityes and Control", 2112 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secctl }, 2113 { PCIE_AER_SHDR_LOG, 4, "shl0", "Secondary Header Log 0", 2114 pcieadm_cfgspace_print_hex }, 2115 { PCIE_AER_SHDR_LOG + 4, 4, "shl1", "Secondary Header Log 1", 2116 pcieadm_cfgspace_print_hex }, 2117 { PCIE_AER_SHDR_LOG + 8, 4, "shl1", "Secondary Header Log 2", 2118 pcieadm_cfgspace_print_hex }, 2119 { PCIE_AER_SHDR_LOG + 12, 4, "shl1", "Secondary Header Log 3", 2120 pcieadm_cfgspace_print_hex }, 2121 { -1, -1, NULL } 2122 }; 2123 2124 /* 2125 * Secondary PCI Express Extended Capability 2126 */ 2127 static pcieadm_regdef_t pcieadm_regdef_pcie2_linkctl3[] = { 2128 { 0, 0, "peq", "Perform Equalization", PRDV_HEX }, 2129 { 1, 1, "leqrie", "Link Equalization Request Interrupt Enable", 2130 PRDV_STRVAL, 2131 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2132 { 9, 15, "elskpos", "Enable Lower SKP OS Generation Vector", 2133 PRDV_BITFIELD, 2134 .prd_val = { .prdv_strval = { "2.5 GT/s", "5.0 GT/s", "8.0 GT/s", 2135 "16.0 GT/s", "32.0 GT/s" } } }, 2136 { -1, -1, NULL } 2137 }; 2138 2139 static pcieadm_regdef_t pcieadm_regdef_pcie2_linkeq[] = { 2140 { 0, 3, "dstxpre", "Downstream Port 8.0 GT/s Transmitter Preset", 2141 PRDV_HEX }, 2142 { 4, 6, "dstxhint", "Downstream Port 8.0 GT/s Receiver Hint", 2143 PRDV_HEX }, 2144 { 8, 11, "ustxpre", "Upstream Port 8.0 GT/s Transmitter Preset", 2145 PRDV_HEX }, 2146 { 12, 14, "ustxhint", "Upstream Port 8.0 GT/s Receiver Hint", 2147 PRDV_HEX }, 2148 { -1, -1, NULL } 2149 }; 2150 2151 static void 2152 pcieadm_cfgspace_print_laneq(pcieadm_cfgspace_walk_t *walkp, 2153 pcieadm_cfgspace_print_t *print, void *arg) 2154 { 2155 if (walkp->pcw_nlanes == 0) { 2156 warnx("failed to capture lane count, but somehow have " 2157 "secondary PCIe cap"); 2158 return; 2159 } 2160 2161 for (uint_t i = 0; i < walkp->pcw_nlanes; i++) { 2162 char eqshort[32], eqhuman[128]; 2163 pcieadm_cfgspace_print_t p; 2164 2165 (void) snprintf(eqshort, sizeof (eqshort), "lane%u", i); 2166 (void) snprintf(eqhuman, sizeof (eqhuman), "Lane %u EQ Control", 2167 i); 2168 p.pcp_off = print->pcp_off + i * 2; 2169 p.pcp_len = 2; 2170 p.pcp_short = eqshort; 2171 p.pcp_human = eqhuman; 2172 p.pcp_print = pcieadm_cfgspace_print_regdef; 2173 p.pcp_arg = pcieadm_regdef_pcie2_linkeq; 2174 2175 p.pcp_print(walkp, &p, p.pcp_arg); 2176 } 2177 } 2178 2179 static pcieadm_cfgspace_print_t pcieadm_cap_pcie2[] = { 2180 { 0x0, 4, "caphdr", "Capability Header", 2181 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2182 { 0x4, 4, "linkctl3", "Link Control 3", 2183 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie2_linkctl3 }, 2184 { 0x8, 4, "laneerr", "Lane Error Status", pcieadm_cfgspace_print_hex }, 2185 { 0xc, 2, "eqctl", "Lane Equalization Control", 2186 pcieadm_cfgspace_print_laneq }, 2187 { -1, -1, NULL } 2188 }; 2189 2190 /* 2191 * Access Control Services 2192 */ 2193 static pcieadm_regdef_t pcieadm_regdef_acs_cap[] = { 2194 { 0, 0, "srcvd", "ACS Source Validation", PRDV_STRVAL, 2195 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2196 { 1, 1, "tranblk", "ACS Transaction Blocking", PRDV_STRVAL, 2197 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2198 { 2, 2, "p2prr", "ACS P2P Request Redirect", PRDV_STRVAL, 2199 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2200 { 3, 3, "p2pcr", "ACS P2P Completion Redirect", PRDV_STRVAL, 2201 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2202 { 4, 4, "upfwd", "ACS Upstream Forwarding", PRDV_STRVAL, 2203 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2204 { 5, 5, "p2pegctl", "ACS P2P Egress Control", PRDV_STRVAL, 2205 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2206 { 6, 6, "dtp2p", "ACS Direct Translated P2P", PRDV_STRVAL, 2207 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2208 { 7, 7, "enhcap", "ACS Enhanced Capability", PRDV_STRVAL, 2209 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2210 { 8, 15, "ecvsz", "Egress Control Vector Size", PRDV_HEX }, 2211 { -1, -1, NULL } 2212 }; 2213 2214 static pcieadm_regdef_t pcieadm_regdef_acs_ctl[] = { 2215 { 0, 0, "srcvd", "ACS Source Validation", PRDV_STRVAL, 2216 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2217 { 1, 1, "tranblk", "ACS Transaction Blocking", PRDV_STRVAL, 2218 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2219 { 2, 2, "p2prr", "ACS P2P Request Redirect", PRDV_STRVAL, 2220 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2221 { 3, 3, "p2pcr", "ACS P2P Completion Redirect", PRDV_STRVAL, 2222 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2223 { 4, 4, "upfwd", "ACS Upstream Forwarding", PRDV_STRVAL, 2224 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2225 { 5, 5, "p2pegctl", "ACS P2P Egress Control", PRDV_STRVAL, 2226 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2227 { 6, 6, "dtp2p", "ACS Direct Translated P2P", PRDV_STRVAL, 2228 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2229 { 7, 7, "iorb", "ACS I/O Request Blocking", PRDV_STRVAL, 2230 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2231 { 8, 9, "dspmta", "ACS DSP Memory Target Access Control", PRDV_STRVAL, 2232 .prd_val = { .prdv_strval = { "Direct Request access", 2233 "Request blocking", "Request redirect" } } }, 2234 { 10, 11, "uspmta", "ACS USP Memory Target Access Control", PRDV_STRVAL, 2235 .prd_val = { .prdv_strval = { "Direct Request access", 2236 "Request blocking", "Request redirect" } } }, 2237 { -1, -1, NULL } 2238 }; 2239 2240 static pcieadm_cfgspace_print_t pcieadm_cap_acs[] = { 2241 { 0x0, 4, "caphdr", "Capability Header", 2242 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2243 { 0x4, 2, "cap", "ACS Capability", 2244 pcieadm_cfgspace_print_regdef, pcieadm_regdef_acs_cap }, 2245 { 0x6, 2, "ctl", "ACS Control", 2246 pcieadm_cfgspace_print_regdef, pcieadm_regdef_acs_ctl }, 2247 { 0x8, 4, "ecv", "Egress Control Vector", pcieadm_cfgspace_print_ecv }, 2248 { -1, -1, NULL } 2249 }; 2250 2251 /* 2252 * L1 PM Substates 2253 */ 2254 static pcieadm_regdef_t pcieadm_regdef_l1pm_cap[] = { 2255 { 0, 0, "pcil1.2", "PCI-PM L1.2", PRDV_STRVAL, 2256 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2257 { 1, 1, "pcil1.1", "PCI-PM L1.1", PRDV_STRVAL, 2258 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2259 { 2, 2, "aspml1.2", "ASPM L1.2", PRDV_STRVAL, 2260 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2261 { 3, 3, "aspml1.1", "ASPM L1.1", PRDV_STRVAL, 2262 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2263 { 4, 4, "l1pmsub", "L1 PM Substates", PRDV_STRVAL, 2264 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2265 { 5, 5, "linkact", "Link Activation", PRDV_STRVAL, 2266 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2267 { 8, 15, "pcmrt", "Port Common_Mode_Restore_Time", PRDV_HEX }, 2268 { 16, 17, "poscale", "Port T_POWER_ON Scale", PRDV_STRVAL, 2269 .prd_val = { .prdv_strval = { "2 us", "10 us", "100 us" } } }, 2270 { 19, 23, "portpo", "Port T_POWER_ON Value", PRDV_HEX }, 2271 { -1, -1, NULL } 2272 }; 2273 2274 static pcieadm_regdef_t pcieadm_regdef_l1pm_ctl1[] = { 2275 { 0, 0, "pcil1.2", "PCI-PM L1.2", PRDV_STRVAL, 2276 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2277 { 1, 1, "pcil1.1", "PCI-PM L1.1", PRDV_STRVAL, 2278 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2279 { 2, 2, "aspml1.2", "ASPM L1.2", PRDV_STRVAL, 2280 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2281 { 3, 3, "aspml1.1", "ASPM L1.1", PRDV_STRVAL, 2282 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2283 { 4, 4, "laie", "Link Activation Interrupt Enable", PRDV_STRVAL, 2284 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2285 { 5, 5, "lactl", "Link Activation Control", PRDV_STRVAL, 2286 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2287 { 8, 15, "cmrt", "Common_Mode_Restore_Time", PRDV_HEX }, 2288 { 16, 25, "ltrl1.2", "LTR L1.2 Threshold Value", PRDV_HEX }, 2289 { 29, 31, "ltrl1.2s", "LTR L1.2 Threshold Scale", PRDV_STRVAL, 2290 .prd_val = { .prdv_strval = { "1 ns", "32 ns", "1024 ns", 2291 "32,768 ns", "1,048,576 ns", "33,554,432 ns" } } }, 2292 { -1, -1, NULL } 2293 }; 2294 2295 static pcieadm_regdef_t pcieadm_regdef_l1pm_ctl2[] = { 2296 { 0, 1, "poscale", "T_POWER_ON Scale", PRDV_STRVAL, 2297 .prd_val = { .prdv_strval = { "2 us", "10 us", "100 us" } } }, 2298 { 3, 7, "portpo", "T_POWER_ON Value", PRDV_HEX }, 2299 { -1, -1, NULL } 2300 }; 2301 2302 static pcieadm_regdef_t pcieadm_regdef_l1pm_sts[] = { 2303 { 0, 0, "la", "Link Activation", PRDV_HEX }, 2304 { -1, -1, NULL } 2305 }; 2306 2307 2308 static pcieadm_cfgspace_print_t pcieadm_cap_l1pm_v1[] = { 2309 { 0x0, 4, "caphdr", "Capability Header", 2310 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2311 { 0x4, 4, "caps", "L1 PM Substates Capabilities", 2312 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_cap }, 2313 { 0x8, 4, "ctl1", "L1 PM Substates Control 1", 2314 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl1 }, 2315 { 0xc, 4, "ctl1", "L1 PM Substates Control 2", 2316 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl2 }, 2317 { -1, -1, NULL } 2318 }; 2319 2320 static pcieadm_cfgspace_print_t pcieadm_cap_l1pm_v2[] = { 2321 { 0x0, 4, "caphdr", "Capability Header", 2322 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2323 { 0x4, 4, "caps", "L1 PM Substates Capabilities", 2324 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_cap }, 2325 { 0x8, 4, "ctl1", "L1 PM Substates Control 1", 2326 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl1 }, 2327 { 0xc, 4, "ctl1", "L1 PM Substates Control 2", 2328 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl2 }, 2329 { 0x10, 4, "sts", "L1 PM Substates Status", 2330 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_sts }, 2331 { -1, -1, NULL } 2332 }; 2333 2334 /* 2335 * Latency Tolerance Reporting (LTR) 2336 */ 2337 static pcieadm_regdef_t pcieadm_regdef_ltr[] = { 2338 { 0, 9, "latval", "Latency Value", PRDV_HEX }, 2339 { 10, 12, "latscale", "Latency Scale", PRDV_STRVAL, 2340 .prd_val = { .prdv_strval = { "1 ns", "32 ns", "1024 ns", 2341 "32,768 ns", "1,048,576 ns", "33,554,432 ns" } } }, 2342 { -1, -1, NULL } 2343 }; 2344 2345 static pcieadm_cfgspace_print_t pcieadm_cap_ltr[] = { 2346 { 0x0, 4, "caphdr", "Capability Header", 2347 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2348 { 0x4, 2, "snoop", "Max Snoop Latency", 2349 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ltr }, 2350 { 0x6, 2, "snoop", "Max No-Snoop Latency", 2351 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ltr }, 2352 { -1, -1, NULL } 2353 }; 2354 2355 /* 2356 * Alternative Routing ID 2357 */ 2358 static pcieadm_regdef_t pcieadm_regdef_ari_cap[] = { 2359 { 0, 0, "mfvcfg", "MFVC Function Groups", PRDV_STRVAL, 2360 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2361 { 1, 1, "acsfg", "ACS Function Groups", PRDV_STRVAL, 2362 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2363 { 8, 15, "nfunc", "Next Function Number", PRDV_HEX }, 2364 { -1, -1, NULL } 2365 }; 2366 2367 static pcieadm_regdef_t pcieadm_regdef_ari_ctl[] = { 2368 { 0, 0, "mfvcfg", "MFVC Function Groups", PRDV_STRVAL, 2369 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2370 { 1, 1, "acsfg", "ACS Function Groups", PRDV_STRVAL, 2371 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2372 { 4, 6, "fgrp", "Function Group", PRDV_HEX }, 2373 { -1, -1, NULL } 2374 }; 2375 2376 static pcieadm_cfgspace_print_t pcieadm_cap_ari[] = { 2377 { 0x0, 4, "caphdr", "Capability Header", 2378 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2379 { 0x4, 2, "cap", "ARI Capability", 2380 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ari_cap }, 2381 { 0x6, 2, "ctl", "ARI Control", 2382 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ari_ctl }, 2383 { -1, -1, NULL } 2384 }; 2385 2386 /* 2387 * PASID 2388 */ 2389 static pcieadm_regdef_t pcieadm_regdef_pasid_cap[] = { 2390 { 1, 1, "exec", "Execution Permission", PRDV_STRVAL, 2391 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2392 { 2, 2, "priv", "Privileged Mode", PRDV_STRVAL, 2393 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2394 { 8, 12, "width", "Max PASID Width", PRDV_HEX }, 2395 { -1, -1, NULL } 2396 }; 2397 2398 static pcieadm_regdef_t pcieadm_regdef_pasid_ctl[] = { 2399 { 0, 0, "pasid", "PASID", PRDV_STRVAL, 2400 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2401 { 1, 1, "exec", "Execution Permission", PRDV_STRVAL, 2402 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2403 { 2, 2, "priv", "Privileged Mode", PRDV_STRVAL, 2404 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2405 { -1, -1, NULL } 2406 }; 2407 2408 2409 static pcieadm_cfgspace_print_t pcieadm_cap_pasid[] = { 2410 { 0x0, 4, "caphdr", "Capability Header", 2411 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2412 { 0x4, 2, "cap", "PASID Capability", 2413 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pasid_cap }, 2414 { 0x6, 2, "ctl", "PASID Control", 2415 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pasid_ctl }, 2416 { -1, -1, NULL } 2417 }; 2418 2419 /* 2420 * "Advanced Features" 2421 */ 2422 static pcieadm_regdef_t pcieadm_regdef_af_cap[] = { 2423 { 0, 0, "tp", "Transactions Pending", PRDV_STRVAL, 2424 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2425 { 1, 1, "flr", "Function Level Reset", PRDV_STRVAL, 2426 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2427 { -1, -1, NULL } 2428 }; 2429 2430 static pcieadm_regdef_t pcieadm_regdef_af_ctl[] = { 2431 { 0, 0, "flr", "Function Level Reset", PRDV_HEX }, 2432 { -1, -1, NULL } 2433 }; 2434 2435 static pcieadm_regdef_t pcieadm_regdef_af_sts[] = { 2436 { 0, 0, "tp", "Transactions Pending", PRDV_STRVAL, 2437 .prd_val = { .prdv_strval = { "none pending", "pending" } } }, 2438 { -1, -1, NULL } 2439 }; 2440 2441 static pcieadm_cfgspace_print_t pcieadm_cap_af[] = { 2442 { 0x2, 2, "cap", "AF Capabilities", 2443 pcieadm_cfgspace_print_regdef, pcieadm_regdef_af_cap }, 2444 { 0x4, 1, "ctl", "AF Control", 2445 pcieadm_cfgspace_print_regdef, pcieadm_regdef_af_ctl }, 2446 { 0x5, 1, "sts", "AF Status", 2447 pcieadm_cfgspace_print_regdef, pcieadm_regdef_af_sts }, 2448 { -1, -1, NULL } 2449 }; 2450 2451 /* 2452 * Multicast 2453 */ 2454 static pcieadm_regdef_t pcieadm_regdef_mcast_cap[] = { 2455 { 0, 5, "maxgrp", "Max Group", PRDV_HEX, 2456 .prd_val = { .prdv_hex = { 0, 1 } } }, 2457 { 8, 13, "winsize", "Window Size (raw)", PRDV_HEX }, 2458 { 15, 15, "ecrc", "ECRC Regeneration", PRDV_STRVAL, 2459 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2460 { -1, -1, NULL } 2461 }; 2462 2463 static pcieadm_regdef_t pcieadm_regdef_mcast_ctl[] = { 2464 { 0, 5, "numgrp", "Number of Groups", PRDV_HEX, 2465 .prd_val = { .prdv_hex = { 0, 1 } } }, 2466 { 15, 15, "enable", "Enable", PRDV_STRVAL, 2467 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2468 { -1, -1, NULL } 2469 }; 2470 2471 static pcieadm_regdef_t pcieadm_regdef_mcast_base[] = { 2472 { 0, 5, "index", "Multicast Index Position", PRDV_HEX }, 2473 { 12, 63, "addr", "Base Address", PRDV_HEX, 2474 .prd_val = { .prdv_hex = { 12 } } }, 2475 { -1, -1, NULL } 2476 }; 2477 2478 static pcieadm_regdef_t pcieadm_regdef_mcast_overlay[] = { 2479 { 0, 5, "size", "Overlay Size (raw)", PRDV_HEX }, 2480 { 6, 63, "addr", "Overlay Base Address", PRDV_HEX, 2481 .prd_val = { .prdv_hex = { 6 } } }, 2482 { -1, -1, NULL } 2483 }; 2484 2485 static pcieadm_cfgspace_print_t pcieadm_cap_mcast[] = { 2486 { 0x0, 4, "caphdr", "Capability Header", 2487 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2488 { 0x4, 2, "cap", "Multicast Capability", 2489 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_cap }, 2490 { 0x6, 2, "ctl", "Multicast Control", 2491 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_ctl }, 2492 { 0x8, 8, "base", "Multicast Base Address", 2493 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_base }, 2494 { 0x10, 8, "rx", "Multicast Receive", pcieadm_cfgspace_print_hex }, 2495 { 0x18, 8, "block", "Multicast Block All", pcieadm_cfgspace_print_hex }, 2496 { 0x20, 8, "blockun", "Multicast Block Untranslated", 2497 pcieadm_cfgspace_print_hex }, 2498 { 0x28, 8, "overlay", "Multicast Overlay BAR", 2499 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_overlay }, 2500 { -1, -1, NULL } 2501 }; 2502 2503 /* 2504 * Various vendor extensions 2505 */ 2506 static pcieadm_regdef_t pcieadm_regdef_vsec[] = { 2507 { 0, 15, "id", "ID", PRDV_HEX }, 2508 { 16, 19, "rev", "Revision", PRDV_HEX }, 2509 { 20, 31, "len", "Length", PRDV_HEX }, 2510 { -1, -1, NULL } 2511 }; 2512 2513 static pcieadm_cfgspace_print_t pcieadm_cap_vs[] = { 2514 { 0x2, 2, "length", "Length", pcieadm_cfgspace_print_hex }, 2515 { -1, -1, NULL } 2516 }; 2517 2518 static pcieadm_cfgspace_print_t pcieadm_cap_vsec[] = { 2519 { 0x0, 4, "caphdr", "Capability Header", 2520 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2521 { 0x4, 4, "header", "Vendor-Specific Header", 2522 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vsec }, 2523 { -1, -1, NULL } 2524 }; 2525 2526 /* 2527 * Data Link Feature 2528 */ 2529 static pcieadm_regdef_t pcieadm_regdef_dlf_cap[] = { 2530 { 0, 0, "lsfc", "Local Scaled Flow Control", PRDV_STRVAL, 2531 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2532 { 31, 31, "dlex", "Data Link Exchange", PRDV_STRVAL, 2533 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2534 { -1, -1, NULL } 2535 }; 2536 2537 static pcieadm_regdef_t pcieadm_regdef_dlf_sts[] = { 2538 { 0, 0, "rsfc", "Remote Scaled Flow Control", PRDV_STRVAL, 2539 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2540 { 31, 31, "valid", "Remote Data Link Feature Valid", PRDV_STRVAL, 2541 .prd_val = { .prdv_strval = { "invalid", "valid" } } }, 2542 { -1, -1, NULL } 2543 }; 2544 2545 static pcieadm_cfgspace_print_t pcieadm_cap_dlf[] = { 2546 { 0x0, 4, "caphdr", "Capability Header", 2547 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2548 { 0x4, 4, "cap", "Data Link Feature Capabilities", 2549 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dlf_cap }, 2550 { 0x8, 4, "sts", "Data Link Feature Status", 2551 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dlf_sts }, 2552 { -1, -1, NULL } 2553 }; 2554 2555 /* 2556 * 16.0 GT/s cap 2557 */ 2558 static pcieadm_regdef_t pcieadm_regdef_16g_cap[] = { 2559 { -1, -1, NULL } 2560 }; 2561 2562 static pcieadm_regdef_t pcieadm_regdef_16g_ctl[] = { 2563 { -1, -1, NULL } 2564 }; 2565 2566 static pcieadm_regdef_t pcieadm_regdef_16g_sts[] = { 2567 { 0, 0, "eqcomp", "Equalization 16.0 GT/s Complete", PRDV_STRVAL, 2568 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2569 { 1, 1, "eqp1", "Equalization 16.0 GT/s Phase 1", PRDV_STRVAL, 2570 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2571 { 2, 2, "eqp2", "Equalization 16.0 GT/s Phase 2", PRDV_STRVAL, 2572 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2573 { 3, 3, "eqp3", "Equalization 16.0 GT/s Phase 3", PRDV_STRVAL, 2574 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2575 { 4, 4, "req", "Link Equalization Request 16.0 GT/s", PRDV_HEX }, 2576 { -1, -1, NULL } 2577 }; 2578 2579 static pcieadm_regdef_t pcieadm_regdef_16g_eq[] = { 2580 { 0, 3, "dstxpre", "Downstream Port 16.0 GT/s Transmitter Preset", 2581 PRDV_HEX }, 2582 { 4, 7, "ustxpre", "Upstream Port 16.0 GT/s Transmitter Preset", 2583 PRDV_HEX }, 2584 { -1, -1, NULL } 2585 }; 2586 2587 static void 2588 pcieadm_cfgspace_print_16geq(pcieadm_cfgspace_walk_t *walkp, 2589 pcieadm_cfgspace_print_t *print, void *arg) 2590 { 2591 if (walkp->pcw_nlanes == 0) { 2592 warnx("failed to capture lane count, but somehow have " 2593 "secondary PCIe cap"); 2594 return; 2595 } 2596 2597 for (uint_t i = 0; i < walkp->pcw_nlanes; i++) { 2598 char eqshort[32], eqhuman[128]; 2599 pcieadm_cfgspace_print_t p; 2600 2601 (void) snprintf(eqshort, sizeof (eqshort), "lane%u", i); 2602 (void) snprintf(eqhuman, sizeof (eqhuman), "Lane %u EQ Control", 2603 i); 2604 p.pcp_off = print->pcp_off + i * 1; 2605 p.pcp_len = 1; 2606 p.pcp_short = eqshort; 2607 p.pcp_human = eqhuman; 2608 p.pcp_print = pcieadm_cfgspace_print_regdef; 2609 p.pcp_arg = pcieadm_regdef_16g_eq; 2610 2611 p.pcp_print(walkp, &p, p.pcp_arg); 2612 } 2613 } 2614 2615 static pcieadm_cfgspace_print_t pcieadm_cap_16g[] = { 2616 { 0x0, 4, "caphdr", "Capability Header", 2617 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2618 { 0x4, 4, "cap", "16.0 GT/s Capabilities", 2619 pcieadm_cfgspace_print_regdef, pcieadm_regdef_16g_cap }, 2620 { 0x8, 4, "ctl", "16.0 GT/s Control", 2621 pcieadm_cfgspace_print_regdef, pcieadm_regdef_16g_ctl }, 2622 { 0xc, 4, "sts", "16.0 GT/s Status", 2623 pcieadm_cfgspace_print_regdef, pcieadm_regdef_16g_sts }, 2624 { 0x10, 4, "ldpmis", "16.0 GT/s Local Data Parity Mismatch", 2625 pcieadm_cfgspace_print_hex }, 2626 { 0x14, 4, "frpmis", "16.0 GT/s First Retimer Data Parity Mismatch", 2627 pcieadm_cfgspace_print_hex }, 2628 { 0x18, 4, "srpmis", "16.0 GT/s Second Retimer Data Parity Mismatch", 2629 pcieadm_cfgspace_print_hex }, 2630 { 0x1c, 4, "rsvd", "16.0 GT/s Second Retimer Data Parity Mismatch", 2631 pcieadm_cfgspace_print_hex }, 2632 { 0x20, 1, "eqctl", "16.0 GT/s EQ Control", 2633 pcieadm_cfgspace_print_16geq }, 2634 { -1, -1, NULL } 2635 }; 2636 2637 /* 2638 * Receiver Margining 2639 */ 2640 static pcieadm_regdef_t pcieadm_regdef_margin_cap[] = { 2641 { 0, 0, "sw", "Margining uses Driver Software", PRDV_STRVAL, 2642 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2643 { -1, -1, NULL } 2644 }; 2645 2646 static pcieadm_regdef_t pcieadm_regdef_margin_sts[] = { 2647 { 0, 0, "ready", "Margining Ready", PRDV_STRVAL, 2648 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2649 { 1, 1, "sw", "Margining Software Ready", PRDV_STRVAL, 2650 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2651 { -1, -1, NULL } 2652 }; 2653 2654 static pcieadm_regdef_t pcieadm_regdef_margin_lane[] = { 2655 { 0, 2, "rxno", "Receiver Number", PRDV_HEX }, 2656 { 3, 5, "type", "Margin Type", PRDV_HEX }, 2657 { 6, 6, "model", "Usage Model", PRDV_HEX }, 2658 { 8, 15, "payload", "Margin Payload", PRDV_HEX }, 2659 { -1, -1, NULL } 2660 }; 2661 2662 static void 2663 pcieadm_cfgspace_print_margin(pcieadm_cfgspace_walk_t *walkp, 2664 pcieadm_cfgspace_print_t *print, void *arg) 2665 { 2666 if (walkp->pcw_nlanes == 0) { 2667 warnx("failed to capture lane count, but somehow have " 2668 "lane margining capability"); 2669 return; 2670 } 2671 2672 for (uint_t i = 0; i < walkp->pcw_nlanes; i++) { 2673 char mshort[32], mhuman[128]; 2674 pcieadm_cfgspace_print_t p; 2675 2676 (void) snprintf(mshort, sizeof (mshort), "lane%uctl", i); 2677 (void) snprintf(mhuman, sizeof (mhuman), "Lane %u Margining " 2678 "Control", i); 2679 p.pcp_off = print->pcp_off + i * 4; 2680 p.pcp_len = 2; 2681 p.pcp_short = mshort; 2682 p.pcp_human = mhuman; 2683 p.pcp_print = pcieadm_cfgspace_print_regdef; 2684 p.pcp_arg = pcieadm_regdef_margin_lane; 2685 2686 p.pcp_print(walkp, &p, p.pcp_arg); 2687 2688 (void) snprintf(mshort, sizeof (mshort), "lane%usts", i); 2689 (void) snprintf(mhuman, sizeof (mhuman), "Lane %u Margining " 2690 "Status", i); 2691 p.pcp_off = print->pcp_off + 2 + i * 4; 2692 p.pcp_len = 2; 2693 p.pcp_short = mshort; 2694 p.pcp_human = mhuman; 2695 p.pcp_print = pcieadm_cfgspace_print_regdef; 2696 p.pcp_arg = pcieadm_regdef_margin_lane; 2697 2698 p.pcp_print(walkp, &p, p.pcp_arg); 2699 } 2700 } 2701 2702 static pcieadm_cfgspace_print_t pcieadm_cap_margin[] = { 2703 { 0x0, 4, "caphdr", "Capability Header", 2704 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2705 { 0x4, 2, "cap", "Margining Port Capabilities", 2706 pcieadm_cfgspace_print_regdef, pcieadm_regdef_margin_cap }, 2707 { 0x6, 2, "sts", "Margining Port Status", 2708 pcieadm_cfgspace_print_regdef, pcieadm_regdef_margin_sts }, 2709 { 0x8, 4, "lane", "Margining Lane", pcieadm_cfgspace_print_margin }, 2710 { -1, -1, NULL } 2711 }; 2712 2713 /* 2714 * Serial Number Capability 2715 */ 2716 static void 2717 pcieadm_cfgspace_print_sn(pcieadm_cfgspace_walk_t *walkp, 2718 pcieadm_cfgspace_print_t *print, void *arg) 2719 { 2720 char sn[64]; 2721 uint16_t off = walkp->pcw_capoff + print->pcp_off; 2722 2723 (void) snprintf(sn, sizeof (sn), 2724 "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 2725 walkp->pcw_data->pcb_u8[off + 7], walkp->pcw_data->pcb_u8[off + 6], 2726 walkp->pcw_data->pcb_u8[off + 5], walkp->pcw_data->pcb_u8[off + 4], 2727 walkp->pcw_data->pcb_u8[off + 3], walkp->pcw_data->pcb_u8[off + 2], 2728 walkp->pcw_data->pcb_u8[off + 1], walkp->pcw_data->pcb_u8[off]); 2729 2730 pcieadm_cfgspace_puts(walkp, print, sn); 2731 } 2732 2733 static pcieadm_cfgspace_print_t pcieadm_cap_sn[] = { 2734 { 0x0, 4, "caphdr", "Capability Header", 2735 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2736 { 0x4, 8, "sn", "Serial Number", pcieadm_cfgspace_print_sn }, 2737 { -1, -1, NULL } 2738 }; 2739 2740 /* 2741 * TLP Processing Hints (TPH) 2742 */ 2743 static pcieadm_regdef_t pcieadm_regdef_tph_cap[] = { 2744 { 0, 0, "nost", "No ST Mode", PRDV_STRVAL, 2745 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2746 { 1, 1, "ivec", "Interrupt Vector Mode", PRDV_STRVAL, 2747 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2748 { 2, 2, "dev", "Device Specific Mode", PRDV_STRVAL, 2749 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2750 { 8, 8, "exttph", "Extended TPH Requester", PRDV_STRVAL, 2751 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2752 { 9, 10, "loc", "ST Table Location", PRDV_STRVAL, 2753 .prd_val = { .prdv_strval = { "Not Present", 2754 "In Capability Structure", "MSI-X" } } }, 2755 { 16, 26, "size", "ST Table Size", PRDV_HEX, { .prdv_hex = { 0, 1 } } }, 2756 { -1, -1, NULL } 2757 }; 2758 2759 static pcieadm_regdef_t pcieadm_regdef_tph_ctl[] = { 2760 { 0, 2, "mode", "ST Mode Select", PRDV_STRVAL, 2761 .prd_val = { .prdv_strval = { "No ST", "Interrupt Vector", 2762 "Device Specific" } } }, 2763 { 8, 9, "en", "TPH Requester", PRDV_STRVAL, 2764 .prd_val = { .prdv_strval = { "Not Permitted", "TPH", NULL, 2765 "TPH and Extended TPH" } } }, 2766 { -1, -1, NULL } 2767 }; 2768 2769 static pcieadm_regdef_t pcieadm_regdef_tph_st[] = { 2770 { 0, 7, "low", "ST Lower", PRDV_HEX }, 2771 { 8, 15, "up", "ST Upper", PRDV_HEX }, 2772 { -1, -1, NULL } 2773 }; 2774 2775 /* 2776 * The TPH ST table is only conditionally present in the capability. So we need 2777 * to read the TPH capability register and then check if the table location and 2778 * size are set here. 2779 */ 2780 static void 2781 pcieadm_cfgspace_print_tphst(pcieadm_cfgspace_walk_t *walkp, 2782 pcieadm_cfgspace_print_t *print, void *arg) 2783 { 2784 uint_t nents; 2785 uint32_t tphcap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 2786 2787 if (BITX(tphcap, 10, 9) != 1) { 2788 return; 2789 } 2790 2791 nents = BITX(tphcap, 26, 16) + 1; 2792 for (uint_t i = 0; i < nents; i++) { 2793 char tshort[32], thuman[128]; 2794 pcieadm_cfgspace_print_t p; 2795 2796 (void) snprintf(tshort, sizeof (tshort), "st%u", i); 2797 (void) snprintf(thuman, sizeof (thuman), "ST Table %u", 2798 i); 2799 p.pcp_off = print->pcp_off + i * 2; 2800 p.pcp_len = 2; 2801 p.pcp_short = tshort; 2802 p.pcp_human = thuman; 2803 p.pcp_print = pcieadm_cfgspace_print_regdef; 2804 p.pcp_arg = pcieadm_regdef_tph_st; 2805 2806 p.pcp_print(walkp, &p, p.pcp_arg); 2807 } 2808 } 2809 2810 static pcieadm_cfgspace_print_t pcieadm_cap_tph[] = { 2811 { 0x0, 4, "caphdr", "Capability Header", 2812 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2813 { 0x4, 4, "cap", "TPH Requester Capability", 2814 pcieadm_cfgspace_print_regdef, pcieadm_regdef_tph_cap }, 2815 { 0x8, 4, "ctl", "TPH Requester Control", 2816 pcieadm_cfgspace_print_regdef, pcieadm_regdef_tph_ctl }, 2817 { 0xc, 2, "table", "ST Table", pcieadm_cfgspace_print_tphst }, 2818 { -1, -1, NULL } 2819 }; 2820 2821 /* 2822 * SR-IOV 2823 */ 2824 static pcieadm_regdef_t pcieadm_regdef_sriov_cap[] = { 2825 { 0, 0, "migration", "Migration", PRDV_STRVAL, 2826 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2827 { 1, 1, "ari", "ARI Capable Hierarchy Preserved", PRDV_STRVAL, 2828 .prd_val = { .prdv_strval = { "unpreserved", "preserved" } } }, 2829 { 2, 2, "vf10b", "VF 10-bit Tag Requester", PRDV_STRVAL, 2830 .prd_val = { .prdv_strval = { "unpreserved", "preserved" } } }, 2831 { 21, 31, "inum", "VF Migration Interrupt Message Number", PRDV_HEX }, 2832 { -1, -1, NULL } 2833 }; 2834 2835 static pcieadm_regdef_t pcieadm_regdef_sriov_ctl[] = { 2836 { 0, 0, "vf", "VF", PRDV_STRVAL, 2837 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2838 { 1, 1, "vfm", "VF Migration", PRDV_STRVAL, 2839 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2840 { 2, 2, "vfmi", "VF Migration Interrupt", PRDV_STRVAL, 2841 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2842 { 3, 3, "ari", "ARI Capable Hierarchy", PRDV_STRVAL, 2843 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2844 { 4, 4, "vf10b", "VF 10-bit Tag Requester", PRDV_STRVAL, 2845 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2846 { -1, -1, NULL } 2847 }; 2848 2849 static pcieadm_regdef_t pcieadm_regdef_sriov_sts[] = { 2850 { 0, 0, "vfm", "VF Migration", PRDV_STRVAL, 2851 .prd_val = { .prdv_strval = { "none", "requested" } } }, 2852 { -1, -1, NULL } 2853 }; 2854 2855 static pcieadm_regdef_t pcieadm_regdef_sriov_pgsup[] = { 2856 { 0, 31, "pgsz", "Supported Page Sizes", PRDV_BITFIELD, 2857 .prd_val = { .prdv_strval = { "4 KB", "8 KB", "16 KB", "32 KB", 2858 "64 KB", "128 KB", "256 KB", "512 KB", "1 MB", "2 MB", "4 MB", 2859 "8 MB", "16 MB", "32 MB", "64 MB", "128 MB", "256 MB", "512 MB", 2860 "1 GB", "2 GB", "4 GB", "8 GB", "16 GB", "32 GB", "64 GB", 2861 "128 GB", "256 GB", "512 GB", "1 TB", "2 TB", "4 TB", "8 TB" } } }, 2862 { -1, -1, NULL } 2863 }; 2864 2865 static pcieadm_regdef_t pcieadm_regdef_sriov_pgen[] = { 2866 { 0, 31, "pgsz", "System Page Sizes", PRDV_BITFIELD, 2867 .prd_val = { .prdv_strval = { "4 KB", "8 KB", "16 KB", "32 KB", 2868 "64 KB", "128 KB", "256 KB", "512 KB", "1 MB", "2 MB", "4 MB", 2869 "8 MB", "16 MB", "32 MB", "64 MB", "128 MB", "256 MB", "512 MB", 2870 "1 GB", "2 GB", "4 GB", "8 GB", "16 GB", "32 GB", "64 GB", 2871 "128 GB", "256 GB", "512 GB", "1 TB", "2 TB", "4 TB", "8 TB" } } }, 2872 { -1, -1, NULL } 2873 }; 2874 2875 static pcieadm_regdef_t pcieadm_regdef_sriov_mig[] = { 2876 { 0, 2, "bir", "VF Migration State BIR", PRDV_STRVAL, 2877 .prd_val = { .prdv_strval = { "BAR 0", "BAR 1", "BAR 2", "BAR 3", 2878 "BAR 4", "BAR 5" } } }, 2879 { 3, 31, "offset", "VF Migration State Offset", PRDV_HEX, 2880 .prd_val = { .prdv_hex = { 3 } } }, 2881 { -1, -1, NULL } 2882 }; 2883 2884 static pcieadm_cfgspace_print_t pcieadm_cap_sriov[] = { 2885 { 0x0, 4, "caphdr", "Capability Header", 2886 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2887 { 0x4, 4, "cap", "SR-IOV Capabilities", 2888 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_cap }, 2889 { 0x8, 2, "ctl", "SR-IOV Control", 2890 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_ctl }, 2891 { 0xa, 2, "sts", "SR-IOV Status", 2892 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_sts }, 2893 { 0xc, 2, "initvfs", "Initial VFs", pcieadm_cfgspace_print_hex }, 2894 { 0xe, 2, "totvfs", "Total VFs", pcieadm_cfgspace_print_hex }, 2895 { 0x10, 2, "numvfs", "Number VFs", pcieadm_cfgspace_print_hex }, 2896 { 0x12, 1, "dep", "Function Dependency Link", 2897 pcieadm_cfgspace_print_hex }, 2898 { 0x14, 2, "offset", "First VF Offset", pcieadm_cfgspace_print_hex }, 2899 { 0x16, 2, "stride", "VF Stride", pcieadm_cfgspace_print_hex }, 2900 { 0x1a, 2, "devid", "VF Device ID", pcieadm_cfgspace_print_hex }, 2901 { 0x1c, 4, "pgsz", "Supported Page Sizes", 2902 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_pgsup }, 2903 { 0x20, 4, "pgsz", "System Page Sizes", 2904 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_pgen }, 2905 { 0x24, 24, "vfbar", "Virtual Base Address Register", 2906 pcieadm_cfgspace_print_bars }, 2907 { 0x3c, 4, "migration", "VF Migration State Array", 2908 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_mig }, 2909 { -1, -1, NULL } 2910 }; 2911 2912 /* 2913 * PCI-X 2914 */ 2915 static pcieadm_regdef_t pcieadm_regdef_pcix_dev_ctl[] = { 2916 { 0, 0, "dper", "Data Parity Error Recovery", PRDV_STRVAL, 2917 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2918 { 1, 1, "ro", "Relaxed Ordering", PRDV_STRVAL, 2919 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2920 { 2, 3, "maxread", "Maximum Memory Read Byte Count", PRDV_STRVAL, 2921 .prd_val = { .prdv_strval = { "512 bytes", "1024 bytes", 2922 "2048 byes", "4096 bytes" } } }, 2923 { 4, 6, "maxsplit", "Maximum Outstanding Split Transactions", 2924 PRDV_STRVAL, .prd_val = { .prdv_strval = { "1", "2", "3", "4", "8", 2925 "12", "16", "32" } } }, 2926 { -1, -1, NULL } 2927 }; 2928 2929 static pcieadm_regdef_t pcieadm_regdef_pcix_dev_sts[] = { 2930 { 0, 2, "func", "Function Number", PRDV_HEX }, 2931 { 3, 7, "dev", "Device Number", PRDV_HEX }, 2932 { 8, 15, "bus", "Bus Number", PRDV_HEX }, 2933 { 16, 16, "64bit", "64-bit Device", PRDV_STRVAL, 2934 .prd_val = { .prdv_strval = { "unsupported (32-bit)", 2935 "supported" } } }, 2936 { 17, 17, "133mhz", "133 MHz Capable", PRDV_STRVAL, 2937 .prd_val = { .prdv_strval = { "unsupported (66 MHz)", 2938 "supported" } } }, 2939 { 18, 18, "spcodis", "Split Completion Discarded", PRDV_STRVAL, 2940 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2941 { 19, 19, "unspco", "Unexpected Split Completion", PRDV_STRVAL, 2942 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2943 { 20, 20, "complex", "Device Complexity", PRDV_STRVAL, 2944 .prd_val = { .prdv_strval = { "simple", "bridge" } } }, 2945 { 21, 22, "maxread", "Designed Maximum Memory Read Byte Count", 2946 PRDV_STRVAL, .prd_val = { .prdv_strval = { "512 bytes", 2947 "1024 bytes", "2048 byes", "4096 bytes" } } }, 2948 { 23, 25, "maxsplit", "Designed Maximum Outstanding Split Transactions", 2949 PRDV_STRVAL, .prd_val = { .prdv_strval = { "1", "2", "3", "4", "8", 2950 "12", "16", "32" } } }, 2951 { 26, 28, "maxcread", "Designed Maximum Cumulative Read Size", 2952 PRDV_STRVAL, .prd_val = { .prdv_strval = { "8/1KB", "16/2KB", 2953 "32/4KB", "64/8KB", "128/16KB", "256/32KB", "512/64KB", 2954 "1024/128KB" } } }, 2955 { 29, 29, "rxspcoer", "Received Split Completion Error Message", 2956 PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, 2957 { -1, -1, NULL } 2958 }; 2959 2960 static pcieadm_regdef_t pcieadm_regdef_pcix_sec_sts[] = { 2961 { 0, 0, "64bit", "64-bit Device", PRDV_STRVAL, 2962 .prd_val = { .prdv_strval = { "unsupported (32-bit)", 2963 "supported" } } }, 2964 { 1, 1, "133mhz", "133 MHz Capable", PRDV_STRVAL, 2965 .prd_val = { .prdv_strval = { "unsupported (66 MHz)", 2966 "supported" } } }, 2967 { 2, 2, "spcodis", "Split Completion Discarded", PRDV_STRVAL, 2968 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2969 { 3, 3, "unspco", "Unexpected Split Completion", PRDV_STRVAL, 2970 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2971 { 4, 4, "spcoor", "Split Completion Overrun", PRDV_STRVAL, 2972 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2973 { 5, 5, "sprde", "Split Request Delayed", PRDV_STRVAL, 2974 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2975 { 6, 8, "freq", "Secondary Clock Frequency", PRDV_STRVAL, 2976 .prd_val = { .prdv_strval = { "conventional", "66 MHz", "100 Mhz", 2977 "133 MHz" } } }, 2978 { -1, -1, NULL } 2979 }; 2980 2981 static pcieadm_regdef_t pcieadm_regdef_pcix_bridge_sts[] = { 2982 { 0, 2, "func", "Function Number", PRDV_HEX }, 2983 { 3, 7, "dev", "Device Number", PRDV_HEX }, 2984 { 8, 15, "bus", "Bus Number", PRDV_HEX }, 2985 { 16, 16, "64bit", "64-bit Device", PRDV_STRVAL, 2986 .prd_val = { .prdv_strval = { "unsupported (32-bit)", 2987 "supported" } } }, 2988 { 17, 17, "133mhz", "133 MHz Capable", PRDV_STRVAL, 2989 .prd_val = { .prdv_strval = { "unsupported (66 MHz)", 2990 "supported" } } }, 2991 { 18, 18, "spcodis", "Split Completion Discarded", PRDV_STRVAL, 2992 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2993 { 19, 19, "unspco", "Unexpected Split Completion", PRDV_STRVAL, 2994 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2995 { 20, 20, "spcoor", "Split Completion Overrun", PRDV_STRVAL, 2996 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2997 { 21, 21, "sprde", "Split Request Delayed", PRDV_STRVAL, 2998 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2999 { -1, -1, NULL } 3000 }; 3001 3002 static pcieadm_regdef_t pcieadm_regdef_pcix_bridge_split[] = { 3003 { 0, 15, "cap", "Split Transaction Capacity", PRDV_HEX }, 3004 { 16, 31, "limit", "Split Transaction Commitment Limit", PRDV_HEX }, 3005 { -1, -1, NULL } 3006 }; 3007 3008 static pcieadm_cfgspace_print_t pcieadm_cap_pcix_dev[] = { 3009 { 0x2, 2, "ctl", "PCI-X Command", 3010 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_dev_ctl }, 3011 { 0x4, 4, "sts", "PCI-X Status", 3012 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_dev_sts }, 3013 { -1, -1, NULL } 3014 }; 3015 3016 static pcieadm_cfgspace_print_t pcieadm_cap_pcix_bridge[] = { 3017 { 0x2, 2, "secsts", "PCI-X Secondary Status", 3018 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_sec_sts }, 3019 { 0x4, 4, "sts", "PCI-X Bridge Status", 3020 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_bridge_sts }, 3021 { 0x8, 4, "ussplit", "Upstream Split Transaction", 3022 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_bridge_split }, 3023 { 0x8, 4, "dssplit", "Downstream Split Transaction", 3024 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_bridge_split }, 3025 { -1, -1, NULL } 3026 }; 3027 3028 /* 3029 * Dynamic Power Allocation 3030 */ 3031 static pcieadm_regdef_t pcieadm_regdef_dpa_cap[] = { 3032 { 0, 4, "substates", "Substate Max", PRDV_HEX, 3033 { .prdv_hex = { 0, 1 } } }, 3034 { 8, 9, "tlu", "Transition Latency Unit", PRDV_STRVAL, 3035 .prd_val = { .prdv_strval = { "1 ms", "10 ms", "100 ms" } } }, 3036 { 12, 13, "pas", "Power Allocation Scale", PRDV_STRVAL, 3037 .prd_val = { .prdv_strval = { "10.0x", "1.0x", "0.1x", 3038 "0.01x" } } }, 3039 { 16, 23, "tlv0", "Transition Latency Value 0", PRDV_HEX }, 3040 { 24, 31, "tlv0", "Transition Latency Value 1", PRDV_HEX }, 3041 { -1, -1, NULL } 3042 }; 3043 3044 static pcieadm_regdef_t pcieadm_regdef_dpa_sts[] = { 3045 { 0, 4, "substate", "Substate Status", PRDV_HEX }, 3046 { 8, 8, "ctlen", "Substate Control Enabled", PRDV_STRVAL, 3047 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3048 { -1, -1, NULL } 3049 }; 3050 3051 static pcieadm_regdef_t pcieadm_regdef_dpa_ctl[] = { 3052 { 0, 4, "substate", "Substate Control", PRDV_HEX }, 3053 { -1, -1, NULL } 3054 }; 3055 3056 static pcieadm_cfgspace_print_t pcieadm_cap_dpa[] = { 3057 { 0x0, 4, "caphdr", "Capability Header", 3058 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3059 { 0x4, 4, "cap", "DPA Capability", 3060 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpa_cap }, 3061 { 0x8, 4, "lat", "DPA Latency Indicator", pcieadm_cfgspace_print_hex }, 3062 { 0xc, 2, "sts", "DPA Status", 3063 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpa_sts }, 3064 { 0xe, 2, "sts", "DPA Control", 3065 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpa_ctl }, 3066 { 0x10, 1, "paa", "DPA Power Allocation Array", 3067 pcieadm_cfgspace_print_dpa_paa }, 3068 { -1, -1, NULL } 3069 }; 3070 3071 /* 3072 * Power Budgeting 3073 */ 3074 static pcieadm_regdef_t pcieadm_regdef_powbudg_data[] = { 3075 { 0, 7, "base", "Base Power", PRDV_HEX }, 3076 { 8, 9, "scale", "Data Scale", PRDV_STRVAL, 3077 .prd_val = { .prdv_strval = { "1.0x", "0.1x", "0.01x", 3078 "0.001x" } } }, 3079 { 10, 12, "pmsub", "PM Substate", PRDV_STRVAL, 3080 .prd_val = { .prdv_strval = { "Default", "Device Specific", 3081 "Device Specific", "Device Specific", "Device Specific", 3082 "Device Specific", "Device Specific", "Device Specific" } } }, 3083 { 13, 14, "pmstate", "PM State", PRDV_STRVAL, 3084 .prd_val = { .prdv_strval = { "D0", "D1", "D2", "D3" } } }, 3085 { 15, 17, "type", "Type", PRDV_STRVAL, 3086 .prd_val = { .prdv_strval = { "PME Aux", "Axiliary", "Idle", 3087 "Sustained", "Sustained - EPRS", "Maximum - EPRS", NULL, 3088 "Maximum" } } }, 3089 { 18, 20, "rail", "Power Rail", PRDV_STRVAL, 3090 .prd_val = { .prdv_strval = { "Power (12V)", "Power (3.3V)", 3091 "Power (1.5V or 1.8V)", NULL, NULL, NULL, NULL, "Thermal" } } }, 3092 { -1, -1, NULL } 3093 }; 3094 3095 static pcieadm_regdef_t pcieadm_regdef_powbudg_cap[] = { 3096 { 0, 0, "sa", "System Allocated", PRDV_STRVAL, 3097 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3098 { -1, -1, NULL } 3099 }; 3100 3101 3102 static pcieadm_cfgspace_print_t pcieadm_cap_powbudg[] = { 3103 { 0x0, 4, "caphdr", "Capability Header", 3104 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3105 { 0x4, 1, "sel", "Data Select", pcieadm_cfgspace_print_hex }, 3106 { 0x8, 4, "data", "Data Regiser", pcieadm_cfgspace_print_regdef, 3107 pcieadm_regdef_powbudg_data }, 3108 { 0xc, 0x1, "cap", "Power Budget Capability", 3109 pcieadm_cfgspace_print_regdef, pcieadm_regdef_powbudg_cap }, 3110 { -1, -1, NULL } 3111 }; 3112 3113 /* 3114 * Precision Time Management 3115 */ 3116 static pcieadm_regdef_t pcieadm_regdef_ptm_cap[] = { 3117 { 0, 0, "req", "PTM Requester", PRDV_STRVAL, 3118 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3119 { 1, 1, "resp", "PTM Responder", PRDV_STRVAL, 3120 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3121 { 2, 2, "root", "PTM Root", PRDV_STRVAL, 3122 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3123 { 3, 3, "eptm", "ePTM", PRDV_STRVAL, 3124 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3125 { 8, 15, "gran", "Local Clock Granularity", PRDV_HEX }, 3126 { -1, -1, NULL } 3127 }; 3128 3129 static pcieadm_regdef_t pcieadm_regdef_ptm_ctl[] = { 3130 { 0, 0, "en", "PTM Enable", PRDV_STRVAL, 3131 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3132 { 1, 1, "root", "Root Select", PRDV_STRVAL, 3133 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3134 { 8, 15, "gran", "Effective Granularity", PRDV_HEX }, 3135 { -1, -1, NULL } 3136 }; 3137 3138 static pcieadm_cfgspace_print_t pcieadm_cap_info_ptm[] = { 3139 { 0x0, 4, "caphdr", "Capability Header", 3140 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3141 { 0x4, 4, "cap", "PTM Capability", 3142 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ptm_cap }, 3143 { 0x8, 4, "cap", "PTM Control", 3144 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ptm_ctl }, 3145 { -1, -1, NULL } 3146 }; 3147 3148 /* 3149 * Address Translation Services (ATS) 3150 */ 3151 static pcieadm_regdef_t pcieadm_regdef_ats_cap[] = { 3152 { 0, 4, "invqd", "Invalidate Queue Depth", PRDV_HEX }, 3153 { 5, 5, "pgalign", "Page Aligned Request", PRDV_STRVAL, 3154 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3155 { 6, 6, "glbinv", "Global Invalidate", PRDV_STRVAL, 3156 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3157 { 7, 7, "relo", "Relaxed Ordering", PRDV_STRVAL, 3158 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3159 { -1, -1, NULL } 3160 }; 3161 3162 static pcieadm_regdef_t pcieadm_regdef_ats_ctl[] = { 3163 { 0, 4, "stu", "Smallest Translation Unit", PRDV_HEX }, 3164 { 15, 15, "en", "Enable", PRDV_STRVAL, 3165 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3166 { -1, -1, NULL } 3167 }; 3168 3169 static pcieadm_cfgspace_print_t pcieadm_cap_ats[] = { 3170 { 0x0, 4, "caphdr", "Capability Header", 3171 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3172 { 0x4, 2, "cap", "ATS Capability", 3173 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ats_cap }, 3174 { 0x6, 2, "cap", "ATS Control", 3175 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ats_ctl }, 3176 { -1, -1, NULL } 3177 }; 3178 3179 /* 3180 * Page Request 3181 */ 3182 static pcieadm_regdef_t pcieadm_regdef_pgreq_ctl[] = { 3183 { 0, 0, "en", "Enable", PRDV_STRVAL, 3184 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3185 { 1, 1, "reset", "Reset", PRDV_HEX }, 3186 { -1, -1, NULL } 3187 }; 3188 3189 static pcieadm_regdef_t pcieadm_regdef_pgreq_sts[] = { 3190 { 0, 0, "rf", "Response Failure", PRDV_STRVAL, 3191 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3192 { 1, 1, "uprgi", "Unexpected Page Request Group Index", PRDV_STRVAL, 3193 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3194 { 8, 8, "stopped", "Stopped", PRDV_STRVAL, 3195 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3196 { 15, 15, "prgrpreq", "PRG Response PASID", PRDV_STRVAL, 3197 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3198 { -1, -1, NULL } 3199 }; 3200 3201 static pcieadm_cfgspace_print_t pcieadm_cap_pgreq[] = { 3202 { 0x0, 4, "caphdr", "Capability Header", 3203 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3204 { 0x4, 2, "ctl", "Page Request Control", 3205 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pgreq_ctl }, 3206 { 0x6, 2, "ctl", "Page Request Status", 3207 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pgreq_sts }, 3208 { 0x8, 4, "cap", "Outstanding Page Request Capacity", 3209 pcieadm_cfgspace_print_hex }, 3210 { 0xc, 4, "alloc", "Outstanding Page Request Allocation", 3211 pcieadm_cfgspace_print_hex }, 3212 { -1, -1, NULL } 3213 }; 3214 3215 /* 3216 * NULL Capability 3217 */ 3218 static pcieadm_cfgspace_print_t pcieadm_cap_null[] = { 3219 { 0x0, 4, "caphdr", "Capability Header", 3220 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3221 { -1, -1, NULL } 3222 }; 3223 3224 /* 3225 * Downstream Port Containment 3226 */ 3227 static pcieadm_regdef_t pcieadm_regdef_dpc_cap[] = { 3228 { 0, 4, "inum", "DPC Interrupt Message Number", PRDV_HEX }, 3229 { 5, 5, "rpext", "Root Port Extensions", PRDV_STRVAL, 3230 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3231 { 6, 6, "ptlpeb", "Poisoned TLP Egress Blocking", PRDV_STRVAL, 3232 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3233 { 7, 7, "swtrig", "Software Triggering", PRDV_STRVAL, 3234 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3235 { 8, 11, "logsz", "RP PIO Log Size", PRDV_HEX }, 3236 { 12, 12, "errcorr", "DL_Active ERR_COR Signaling", PRDV_STRVAL, 3237 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3238 { -1, -1, NULL } 3239 }; 3240 3241 static pcieadm_regdef_t pcieadm_regdef_dpc_ctl[] = { 3242 { 0, 1, "trigger", "DPC Trigger", PRDV_STRVAL, 3243 .prd_val = { .prdv_strval = { "disabled", "enabled, fatal", 3244 "enabled, non-fatal" } } }, 3245 { 2, 2, "comp", "Completion Control", PRDV_STRVAL, 3246 .prd_val = { .prdv_strval = { "Completer Abort", 3247 "Unsupported Request" } } }, 3248 { 3, 3, "intr", "Interrupt", 3249 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3250 { 4, 4, "errcor", "ERR_COR", 3251 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3252 { 5, 5, "ptlpeb", "Poisoned TLP Egress Blocking", PRDV_STRVAL, 3253 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3254 { 6, 6, "swtrig", "Software Trigger", PRDV_HEX }, 3255 { 7, 7, "corerr", "DL_Active ERR_COR", 3256 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3257 { 8, 8, "sigsfw", "SIG_SFW", 3258 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3259 { -1, -1, NULL } 3260 }; 3261 3262 static pcieadm_regdef_t pcieadm_regdef_dpc_sts[] = { 3263 { 0, 0, "trigger", "Trigger Status", PRDV_STRVAL, 3264 .prd_val = { .prdv_strval = { "not triggered", "triggered" } } }, 3265 { 1, 2, "reason", "Trigger Reason", PRDV_STRVAL, 3266 .prd_val = { .prdv_strval = { "unmasked uncorrectable", 3267 "ERR_NONFATAL received", "ERR_FATAL received", 3268 "see extension" } } }, 3269 { 3, 3, "istatus", "Interrupt Status", PRDV_HEX }, 3270 { 4, 4, "rpbusy", "RP Busy", PRDV_STRVAL, 3271 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3272 { 5, 6, "extreason", "Trigger Reason Extension", PRDV_STRVAL, 3273 .prd_val = { .prdv_strval = { "RP PIO", "Software Trigger" } } }, 3274 { 8, 12, "feptr", "RP PIO, First Error Pointer", PRDV_HEX }, 3275 { 13, 13, "sigsfw", "SIG_SFW Status", PRDV_HEX }, 3276 { -1, -1, NULL } 3277 }; 3278 3279 static pcieadm_regdef_t pcieadm_regdef_dpc_rppio_bits[] = { 3280 { 0, 0, "cfgur", "Configuration Request UR Completion", PRDV_HEX }, 3281 { 1, 1, "cfgca", "Configuration Request CA Completion", PRDV_HEX }, 3282 { 2, 2, "cfgcto", "Configuration Request Completion Timeout", 3283 PRDV_HEX }, 3284 { 8, 8, "iour", "I/O UR Completion", PRDV_HEX }, 3285 { 9, 9, "ioca", "I/O CA Completion", PRDV_HEX }, 3286 { 10, 10, "iocto", "I/O Completion Timeout", PRDV_HEX }, 3287 { 8, 8, "memur", "Memory UR Completion", PRDV_HEX }, 3288 { 9, 9, "memca", "Memory CA Completion", PRDV_HEX }, 3289 { 10, 10, "memcto", "Memory Completion Timeout", PRDV_HEX }, 3290 { -1, -1, NULL } 3291 }; 3292 3293 static void 3294 pcieadm_cfgspace_print_dpc_rppio(pcieadm_cfgspace_walk_t *walkp, 3295 pcieadm_cfgspace_print_t *print, void *arg) 3296 { 3297 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3298 3299 if (BITX(cap, 5, 5) == 0) { 3300 return; 3301 } 3302 3303 pcieadm_cfgspace_print_regdef(walkp, print, arg); 3304 } 3305 3306 static void 3307 pcieadm_cfgspace_print_dpc_piohead(pcieadm_cfgspace_walk_t *walkp, 3308 pcieadm_cfgspace_print_t *print, void *arg) 3309 { 3310 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3311 uint32_t nwords = BITX(cap, 11, 8); 3312 3313 if (BITX(cap, 5, 5) == 0 || nwords < 4) { 3314 return; 3315 } 3316 3317 pcieadm_cfgspace_print_hex(walkp, print, NULL); 3318 } 3319 3320 static void 3321 pcieadm_cfgspace_print_dpc_impspec(pcieadm_cfgspace_walk_t *walkp, 3322 pcieadm_cfgspace_print_t *print, void *arg) 3323 { 3324 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3325 uint32_t nwords = BITX(cap, 11, 8); 3326 3327 if (BITX(cap, 5, 5) == 0 || nwords < 5) { 3328 return; 3329 } 3330 3331 pcieadm_cfgspace_print_hex(walkp, print, NULL); 3332 } 3333 3334 static void 3335 pcieadm_cfgspace_print_dpc_tlplog(pcieadm_cfgspace_walk_t *walkp, 3336 pcieadm_cfgspace_print_t *print, void *arg) 3337 { 3338 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3339 int32_t nwords = BITX(cap, 11, 8); 3340 3341 if (nwords == 0 || BITX(cap, 5, 5) == 0) { 3342 return; 3343 } 3344 3345 if (nwords <= 9) { 3346 nwords -= 5; 3347 } else { 3348 nwords -= 4; 3349 } 3350 3351 for (int32_t i = 0; i < nwords; i++) { 3352 char tlpshort[32], tlphuman[128]; 3353 pcieadm_cfgspace_print_t p; 3354 3355 (void) snprintf(tlpshort, sizeof (tlpshort), "%s%u", 3356 print->pcp_short, i); 3357 (void) snprintf(tlphuman, sizeof (tlphuman), "%s %u", 3358 print->pcp_human, i); 3359 p.pcp_off = print->pcp_off + i * 4; 3360 p.pcp_len = 4; 3361 p.pcp_short = tlpshort; 3362 p.pcp_human = tlphuman; 3363 p.pcp_print = pcieadm_cfgspace_print_hex; 3364 p.pcp_arg = NULL; 3365 3366 p.pcp_print(walkp, &p, p.pcp_arg); 3367 } 3368 } 3369 3370 static pcieadm_cfgspace_print_t pcieadm_cap_dpc[] = { 3371 { 0x0, 4, "caphdr", "Capability Header", 3372 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3373 { 0x4, 2, "cap", "DPC Capability", 3374 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpc_cap }, 3375 { 0x6, 2, "ctl", "DPC Control", 3376 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpc_ctl }, 3377 { 0x8, 2, "sts", "DPC Status", 3378 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpc_sts }, 3379 { 0xa, 2, "srcid", "DPC Error Source ID", 3380 pcieadm_cfgspace_print_hex }, 3381 { 0x10, 4, "rppiosts", "RP PIO Status", 3382 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3383 { 0x14, 4, "rppiomask", "RP PIO Mask ID", 3384 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3385 { 0x14, 4, "rppiosev", "RP PIO Severity", 3386 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3387 { 0x18, 4, "rppiose", "RP PIO SysError", 3388 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3389 { 0x1c, 4, "rppioex", "RP PIO Exception", 3390 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3391 { 0x20, 4, "rppiohl0", "RP PIO Header Log 0", 3392 pcieadm_cfgspace_print_dpc_piohead }, 3393 { 0x24, 4, "rppiohl1", "RP PIO Header Log 1", 3394 pcieadm_cfgspace_print_dpc_piohead }, 3395 { 0x28, 4, "rppiohl2", "RP PIO Header Log 2", 3396 pcieadm_cfgspace_print_dpc_piohead }, 3397 { 0x2c, 4, "rppiohl3", "RP PIO Header Log 3", 3398 pcieadm_cfgspace_print_dpc_piohead }, 3399 { 0x30, 4, "impspec", "RP PIO ImpSpec Log", 3400 pcieadm_cfgspace_print_dpc_impspec }, 3401 { 0x34, 16, "tlplog", "RP PIO TLP Prefix Log", 3402 pcieadm_cfgspace_print_dpc_tlplog }, 3403 { -1, -1, NULL } 3404 }; 3405 3406 /* 3407 * Virtual Channel Capability 3408 */ 3409 static pcieadm_regdef_t pcieadm_regdef_vc_cap1[] = { 3410 { 0, 2, "count", "Extended VC Count", PRDV_HEX }, 3411 { 4, 6, "lpcount", "Low Priority Extended VC Count", PRDV_HEX }, 3412 { 8, 9, "refclk", "Reference Clock", PRDV_STRVAL, 3413 .prd_val = { .prdv_strval = { "100ns" } } }, 3414 { 10, 11, "patsz", "Port Arbitration Table Size", PRDV_STRVAL, 3415 .prd_val = { .prdv_strval = { "1 bit", "2 bits", "4 bits", 3416 "8 bits" } } }, 3417 { -1, -1, NULL } 3418 }; 3419 3420 static pcieadm_regdef_t pcieadm_regdef_vc_cap2[] = { 3421 { 0, 7, "arbcap", "VC Arbitration Capability", PRDV_BITFIELD, 3422 .prd_val = { .prdv_strval = { "hardware fixed", 3423 "32 phase weighted round robin", "64 phase weighted round robin", 3424 "128 phase weighted round robin" } } }, 3425 { 24, 31, "offset", "VC Arbitration Table Offset", PRDV_HEX }, 3426 { -1, -1, NULL } 3427 }; 3428 3429 static pcieadm_regdef_t pcieadm_regdef_vc_ctl[] = { 3430 { 0, 0, "loadtbl", "Load VC Arbitration Table", PRDV_HEX }, 3431 { 1, 3, "arbtype", "VC Arbitration Select", PRDV_STRVAL, 3432 .prd_val = { .prdv_strval = { "hardware fixed", 3433 "32 phase weighted round robin", "64 phase weighted round robin", 3434 "128 phase weighted round robin" } } }, 3435 { -1, -1, NULL } 3436 }; 3437 3438 static pcieadm_regdef_t pcieadm_regdef_vc_sts[] = { 3439 { 0, 0, "table", "VC Arbitration Table Status", PRDV_HEX }, 3440 { -1, -1, NULL } 3441 }; 3442 3443 static pcieadm_regdef_t pcieadm_regdef_vc_rsrccap[] = { 3444 { 0, 7, "arbcap", "Port Arbitration Capability", PRDV_BITFIELD, 3445 .prd_val = { .prdv_strval = { "hardware fixed", 3446 "32 phase weighted round robin", "64 phase weighted round robin", 3447 "128 phase weighted round robin", 3448 "128 phase time-based weighted round robin", 3449 "256 phase weighted round robin" } } }, 3450 { 14, 14, "aps", "Advanced Packet Switching", PRDV_STRVAL, 3451 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3452 { 15, 15, "rstx", "Reject Snoop Transactions", PRDV_STRVAL, 3453 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3454 { 16, 22, "nslots", "Maximum Time Slots", PRDV_HEX, 3455 { .prdv_hex = { 0, 1 } } }, 3456 { 24, 31, "offset", "VC Arbitration Table Offset", PRDV_HEX }, 3457 { -1, -1, NULL } 3458 }; 3459 3460 static pcieadm_regdef_t pcieadm_regdef_vc_rsrcctl[] = { 3461 { 0, 7, "tcmap", "TC/VC Map", PRDV_HEX }, 3462 { 16, 16, "loadtbl", "Load VC Arbitration Table", PRDV_HEX }, 3463 { 17, 19, "arbtype", "Port Arbitration Select", PRDV_STRVAL, 3464 .prd_val = { .prdv_strval = { "hardware fixed", 3465 "32 phase weighted round robin", "64 phase weighted round robin", 3466 "128 phase weighted round robin", 3467 "128 phase time-based weighted round robin", 3468 "256 phase weighted round robin" } } }, 3469 { 24, 26, "vcid", "VC ID", PRDV_HEX }, 3470 { 31, 31, "en", "VC Enable", 3471 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3472 { -1, -1, NULL } 3473 }; 3474 3475 static pcieadm_regdef_t pcieadm_regdef_vc_rsrcsts[] = { 3476 { 0, 0, "table", "Port Arbitration Table Status", PRDV_HEX }, 3477 { -1, -1, NULL } 3478 }; 3479 3480 static void 3481 pcieadm_cfgspace_print_vc_rsrc(pcieadm_cfgspace_walk_t *walkp, 3482 pcieadm_cfgspace_print_t *print, void *arg) 3483 { 3484 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3485 uint32_t nents = BITX(cap, 2, 0) + 1; 3486 3487 for (uint32_t i = 0; i < nents; i++) { 3488 char vcshort[32], vchuman[128]; 3489 pcieadm_cfgspace_print_t p; 3490 3491 (void) snprintf(vcshort, sizeof (vcshort), "rsrccap%u", i); 3492 (void) snprintf(vchuman, sizeof (vchuman), "VC Resource %u " 3493 "Capability", i); 3494 p.pcp_off = print->pcp_off + i * 0x10; 3495 p.pcp_len = 4; 3496 p.pcp_short = vcshort; 3497 p.pcp_human = vchuman; 3498 p.pcp_print = pcieadm_cfgspace_print_regdef; 3499 p.pcp_arg = pcieadm_regdef_vc_rsrccap; 3500 3501 p.pcp_print(walkp, &p, p.pcp_arg); 3502 3503 (void) snprintf(vcshort, sizeof (vcshort), "rsrcctl%u", i); 3504 (void) snprintf(vchuman, sizeof (vchuman), "VC Resource %u " 3505 "Control", i); 3506 p.pcp_off = print->pcp_off + i * 0x10 + 4; 3507 p.pcp_len = 4; 3508 p.pcp_short = vcshort; 3509 p.pcp_human = vchuman; 3510 p.pcp_print = pcieadm_cfgspace_print_regdef; 3511 p.pcp_arg = pcieadm_regdef_vc_rsrcctl; 3512 3513 p.pcp_print(walkp, &p, p.pcp_arg); 3514 3515 (void) snprintf(vcshort, sizeof (vcshort), "rsrcsts%u", i); 3516 (void) snprintf(vchuman, sizeof (vchuman), "VC Resource %u " 3517 "Status", i); 3518 p.pcp_off = print->pcp_off + i * 0x10 + 0xa; 3519 p.pcp_len = 2; 3520 p.pcp_short = vcshort; 3521 p.pcp_human = vchuman; 3522 p.pcp_print = pcieadm_cfgspace_print_regdef; 3523 p.pcp_arg = pcieadm_regdef_vc_rsrcsts; 3524 3525 p.pcp_print(walkp, &p, p.pcp_arg); 3526 } 3527 } 3528 3529 static pcieadm_cfgspace_print_t pcieadm_cap_vc[] = { 3530 { 0x0, 4, "caphdr", "Capability Header", 3531 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3532 { 0x4, 4, "cap1", "Port VC Capability 1", 3533 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_cap1 }, 3534 { 0x8, 4, "cap2", "Port VC Capability 2", 3535 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_cap2 }, 3536 { 0xc, 2, "ctl", "Port VC Control", 3537 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_ctl }, 3538 { 0xe, 2, "sts", "Port VC Status", 3539 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_sts }, 3540 { 0x10, 12, "vcrec", "VC Resource", pcieadm_cfgspace_print_vc_rsrc }, 3541 { -1, -1, NULL } 3542 }; 3543 3544 /* 3545 * HyperTransport 3546 */ 3547 static pcieadm_cfgspace_print_t pcieadm_cap_ht_intr[] = { 3548 { 0x2, 1, "index", "Interrupt Discovery Index", 3549 pcieadm_cfgspace_print_hex }, 3550 { 0x4, 4, "dataport", "Interrupt Dataport", 3551 pcieadm_cfgspace_print_hex }, 3552 { -1, -1, NULL } 3553 }; 3554 3555 static pcieadm_regdef_t pcieadm_regdef_ht_command_pri[] = { 3556 { 0, 4, "unitid", "Base Unit ID", PRDV_HEX }, 3557 { 5, 9, "count", "Unit Count", PRDV_HEX }, 3558 { 10, 10, "host", "Master Host", PRDV_HEX }, 3559 { 11, 11, "dir", "Default Direction", PRDV_STRVAL, 3560 .prd_val = { .prdv_strval = { "towards host", 3561 "away from host" } } }, 3562 { 12, 12, "drop", "Drop on Uninitialized Link", PRDV_HEX }, 3563 { 13, 15, "cap", "Capability ID", PRDV_HEX }, 3564 { -1, -1, NULL } 3565 }; 3566 3567 static pcieadm_regdef_t pcieadm_regdef_ht_command_sec[] = { 3568 { 0, 0, "reset", "Warm Reset", PRDV_HEX }, 3569 { 1, 1, "de", "Double Ended", PRDV_HEX }, 3570 { 2, 6, "devno", "Device Number", PRDV_HEX }, 3571 { 7, 7, "chain", "Chain Side", PRDV_STRVAL, 3572 .prd_val = { .prdv_strval = { "from host", "from chain" } } }, 3573 { 8, 8, "hide", "Host Hide", PRDV_STRVAL, 3574 .prd_val = { .prdv_strval = { "visible", "hidden" } } }, 3575 { 10, 10, "target", "Act as Target", PRDV_HEX }, 3576 { 11, 11, "eocerr", "Host Inbound End of Chain Error", PRDV_HEX }, 3577 { 12, 12, "drop", "Drop on Uninitialized Link", PRDV_HEX }, 3578 { 13, 15, "cap", "Capability ID", PRDV_HEX }, 3579 { -1, -1, NULL } 3580 }; 3581 3582 static pcieadm_regdef_t pcieadm_regdef_ht_linkctl[] = { 3583 { 0, 0, "srcid", "Source ID", PRDV_STRVAL, 3584 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3585 { 1, 1, "cfl", "CRC Flood", PRDV_STRVAL, 3586 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3587 { 2, 2, "cst", "CRC Start Test", PRDV_HEX }, 3588 { 3, 3, "cfer", "CRC Force Error", PRDV_STRVAL, 3589 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3590 { 4, 4, "linkfail", "Link Failure", PRDV_HEX }, 3591 { 5, 5, "initcmp", "Initialization Complete", PRDV_HEX }, 3592 { 6, 6, "eoc", "End of Chain", PRDV_HEX }, 3593 { 7, 7, "txoff", "Transmitter Off", PRDV_STRVAL, 3594 .prd_val = { .prdv_strval = { "transmitter on", 3595 "transmitter off" } } }, 3596 { 8, 11, "crcerr", "CRC Error", PRDV_HEX }, 3597 { 12, 12, "isoc", "Isochronous Flow Control", PRDV_STRVAL, 3598 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3599 { 13, 13, "ls", "LDTSTOP# Tristate", PRDV_STRVAL, 3600 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3601 { 14, 14, "extctl", "Extended CTL Time", PRDV_HEX }, 3602 { 15, 15, "64b", "64-bit Addressing", PRDV_STRVAL, 3603 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3604 { -1, -1, NULL } 3605 }; 3606 3607 static pcieadm_regdef_t pcieadm_regdef_ht_linkcfg[] = { 3608 { 0, 2, "maxin", "Maximum Link Width In", PRDV_STRVAL, 3609 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3610 "2 bits", "4 bits", NULL, "not connected" } } }, 3611 { 3, 3, "dwfcinsup", "Doubleword Flow Control In", PRDV_STRVAL, 3612 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3613 { 4, 6, "maxout", "Maximum Link Width Out", PRDV_STRVAL, 3614 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3615 "2 bits", "4 bits", NULL, "not connected" } } }, 3616 { 7, 7, "dwfcoutsup", "Doubleword Flow Control Out", PRDV_STRVAL, 3617 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3618 { 8, 10, "linkin", "Link Width In", PRDV_STRVAL, 3619 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3620 "2 bits", "4 bits", NULL, "not connected" } } }, 3621 { 11, 11, "dwfcin", "Doubleword Flow Control In", PRDV_STRVAL, 3622 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3623 { 12, 14, "linkout", "Link Width Out", PRDV_STRVAL, 3624 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3625 "2 bits", "4 bits", NULL, "not connected" } } }, 3626 { 15, 15, "dwfcout", "Doubleword Flow Control Out", PRDV_STRVAL, 3627 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3628 { -1, -1, NULL } 3629 }; 3630 3631 static pcieadm_regdef_t pcieadm_regdef_ht_rev[] = { 3632 { 0, 4, "minor", "Minor Revision", PRDV_HEX }, 3633 { 5, 7, "major", "Major Revision", PRDV_HEX }, 3634 { -1, -1, NULL } 3635 }; 3636 3637 static pcieadm_regdef_t pcieadm_regdef_ht_linkfreq[] = { 3638 { 0, 4, "freq", "Link Frequency", PRDV_STRVAL, 3639 .prd_val = { .prdv_strval = { "200 MHz", "300 MHz", "400 MHz", 3640 "500 MHz", "600 MHz", "800 MHz", "1000 MHz", "1200 MHz", "1400 MHz", 3641 "1600 MHz", "1800 MHz", "2000 MHz", "2200 MHz", "2400 MHz", 3642 "2600 MHz", "Vendor Specfic" } } }, 3643 { -1, -1, NULL } 3644 }; 3645 3646 static pcieadm_regdef_t pcieadm_regdef_ht_linkerr[] = { 3647 { 4, 4, "prot", "Protocol Error", PRDV_HEX }, 3648 { 5, 5, "over", "Overflow Error", PRDV_HEX }, 3649 { 6, 6, "eoc", "End of Chain Error", PRDV_HEX }, 3650 { 7, 7, "ctl", "CTL Timeout", PRDV_HEX }, 3651 { -1, -1, NULL } 3652 }; 3653 3654 static pcieadm_regdef_t pcieadm_regdef_ht_linkcap[] = { 3655 { 0, 15, "freq", "Link Frequency", PRDV_BITFIELD, 3656 .prd_val = { .prdv_strval = { "200 MHz", "300 MHz", "400 MHz", 3657 "500 MHz", "600 MHz", "800 MHz", "1000 MHz", "1200 MHz", "1400 MHz", 3658 "1600 MHz", "1800 MHz", "2000 MHz", "2200 MHz", "2400 MHz", 3659 "2600 MHz", "Vendor Specfic" } } }, 3660 { -1, -1, NULL } 3661 }; 3662 3663 static pcieadm_regdef_t pcieadm_regdef_ht_feature[] = { 3664 { 0, 0, "isofc", "Isochronous Flow Control", PRDV_STRVAL, 3665 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3666 { 1, 1, "ls", "LDTSTOP#", PRDV_STRVAL, 3667 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3668 { 2, 2, "crct", "CRC Test Mode", PRDV_STRVAL, 3669 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3670 { 3, 3, "ectl", "Extended CTL Time", PRDV_STRVAL, 3671 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3672 { 4, 4, "64b", "64-bit Addressing", PRDV_STRVAL, 3673 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3674 { 5, 5, "unitid", "UnitID Reorder", PRDV_STRVAL, 3675 .prd_val = { .prdv_strval = { "enabled", "disabled" } } }, 3676 { 6, 6, "srcid", "Source Identification Extension", PRDV_STRVAL, 3677 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3678 { 8, 8, "extreg", "Extended Register Set", PRDV_STRVAL, 3679 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3680 { 9, 9, "uscfg", "Upstream Configuration", PRDV_STRVAL, 3681 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3682 { -1, -1, NULL } 3683 }; 3684 3685 static pcieadm_regdef_t pcieadm_regdef_ht_error[] = { 3686 { 0, 0, "protfl", "Protocol Error Flood", PRDV_STRVAL, 3687 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3688 { 1, 1, "ovfl", "Overflow Error Flood", PRDV_STRVAL, 3689 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3690 { 2, 2, "protf", "Protocol Error Fatal", PRDV_STRVAL, 3691 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3692 { 3, 3, "ovf", "Overflow Error Fatal", PRDV_STRVAL, 3693 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3694 { 4, 4, "eocf", "End of Chain Fatal Error", PRDV_STRVAL, 3695 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3696 { 5, 5, "respf", "Response Error Fatal", PRDV_STRVAL, 3697 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3698 { 6, 6, "crcf", "CRC Error Fatal", PRDV_STRVAL, 3699 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3700 { 7, 7, "sysf", "System Error Fatal", PRDV_STRVAL, 3701 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3702 { 8, 8, "chain", "Chain Fail", PRDV_HEX }, 3703 { 9, 9, "resp", "Response Error", PRDV_HEX }, 3704 { 10, 10, "protnf", "Protocol Error Non-Fatal", PRDV_STRVAL, 3705 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3706 { 11, 11, "ovfnf", "Overflow Error Non-Fatal", PRDV_STRVAL, 3707 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3708 { 12, 12, "eocnf", "End of Chain Error Non-Fatal", PRDV_STRVAL, 3709 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3710 { 13, 13, "respnf", "Response Error Non-Fatal", PRDV_STRVAL, 3711 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3712 { 14, 14, "crcnf", "CRC Error Non-Fatal", PRDV_STRVAL, 3713 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3714 { 15, 15, "sysnf", "System Error Non-Fatal", PRDV_STRVAL, 3715 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3716 { -1, -1, NULL } 3717 }; 3718 3719 static pcieadm_regdef_t pcieadm_regdef_ht_memory[] = { 3720 { 0, 8, "base", "Memory Base Upper 8 Bits", PRDV_HEX, 3721 .prd_val = { .prdv_hex = { 32 } } }, 3722 { 9, 15, "limit", "Memory Limit Upper 8 Bits", PRDV_HEX, 3723 .prd_val = { .prdv_hex = { 32 } } }, 3724 { -1, -1, NULL } 3725 }; 3726 3727 static pcieadm_cfgspace_print_t pcieadm_cap_ht_pri[] = { 3728 { 0x2, 2, "command", "Command", 3729 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_command_pri }, 3730 { 0x4, 2, "linkctl0", "Link Control 0", 3731 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkctl }, 3732 { 0x6, 2, "linkcfg0", "Link Configuration 0", 3733 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcfg }, 3734 { 0x8, 2, "linkctl1", "Link Control 1", 3735 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkctl }, 3736 { 0xa, 2, "linkcfg1", "Link Configuration 1", 3737 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcfg }, 3738 { 0xc, 1, "rev", "Revision", 3739 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_rev }, 3740 { 0xd, 1, "linkfreq0", "Link Frequency 0", 3741 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkfreq }, 3742 { 0xd, 1, "linkerr0", "Link Error 0", 3743 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkerr }, 3744 { 0xe, 2, "linkfcap0", "Link Frequency Cap 0", 3745 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcap }, 3746 { 0x10, 1, "feature", "Feature Capability", 3747 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_feature }, 3748 { 0x11, 1, "linkfreq1", "Link Frequency 1", 3749 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkfreq }, 3750 { 0x11, 1, "linkerr1", "Link Error 1", 3751 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkerr }, 3752 { 0x12, 2, "linkfcap1", "Link Frequency Cap 1", 3753 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcap }, 3754 { 0x14, 2, "scratch", "Enumeration Scratchpad", 3755 pcieadm_cfgspace_print_hex }, 3756 { 0x16, 2, "error", "Error Handling", 3757 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_error }, 3758 { 0x18, 2, "memory", "Memory", 3759 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_memory }, 3760 { 0x1a, 1, "bus", "Bus Number", pcieadm_cfgspace_print_hex }, 3761 { -1, -1, NULL } 3762 }; 3763 3764 static pcieadm_cfgspace_print_t pcieadm_cap_ht_sec[] = { 3765 { 0x2, 2, "command", "Command", 3766 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_command_sec }, 3767 { 0x4, 2, "linkctl", "Link Control", 3768 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkctl }, 3769 { 0x6, 2, "linkcfg", "Link Configuration", 3770 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcfg }, 3771 { 0x8, 1, "rev", "Revision", 3772 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_rev }, 3773 { 0x9, 1, "linkfreq", "Link Frequency 0", 3774 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkfreq }, 3775 { 0x9, 1, "linkerr", "Link Error 0", 3776 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkerr }, 3777 { 0xa, 2, "linkfcap", "Link Frequency Cap 0", 3778 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcap }, 3779 { 0xc, 2, "feature", "Feature Capability", 3780 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_feature }, 3781 { 0x10, 2, "scratch", "Enumeration Scratchpad", 3782 pcieadm_cfgspace_print_hex }, 3783 { 0x12, 2, "error", "Error Handling", 3784 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_error }, 3785 { 0x14, 2, "memory", "Memory", 3786 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_memory }, 3787 { -1, -1, NULL } 3788 }; 3789 3790 static pcieadm_regdef_t pcieadm_regdef_ht_msi[] = { 3791 { 0, 0, "en", "Enable", PRDV_STRVAL, 3792 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3793 { 1, 1, "fixed", "Fixed", PRDV_STRVAL, 3794 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3795 { -1, -1, NULL } 3796 }; 3797 3798 static void 3799 pcieadm_cfgspace_print_ht_msi_addr(pcieadm_cfgspace_walk_t *walkp, 3800 pcieadm_cfgspace_print_t *print, void *arg) 3801 { 3802 uint8_t fixed = walkp->pcw_data->pcb_u8[walkp->pcw_capoff + 2]; 3803 3804 if (BITX(fixed, 1, 1) != 0) 3805 return; 3806 3807 pcieadm_cfgspace_print_hex(walkp, print, arg); 3808 } 3809 3810 static pcieadm_cfgspace_print_t pcieadm_cap_ht_msi[] = { 3811 { 0x2, 2, "command", "Command", 3812 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_msi }, 3813 { 0x4, 8, "address", "MSI Address", 3814 pcieadm_cfgspace_print_ht_msi_addr }, 3815 { -1, -1, NULL } 3816 }; 3817 3818 /* 3819 * Capability related tables 3820 */ 3821 typedef struct pcieadm_cap_vers { 3822 uint32_t ppr_vers; 3823 uint32_t ppr_len; 3824 pcieadm_cfgspace_print_t *ppr_print; 3825 } pcieadm_cap_vers_t; 3826 3827 typedef struct pcieadm_subcap { 3828 const char *psub_short; 3829 const char *psub_human; 3830 } pcieadm_subcap_t; 3831 3832 typedef struct pcieadm_pci_cap pcieadm_pci_cap_t; 3833 3834 typedef void (*pcieadm_cap_info_f)(pcieadm_cfgspace_walk_t *, 3835 const pcieadm_pci_cap_t *, uint32_t, const pcieadm_cap_vers_t **, 3836 uint32_t *, const pcieadm_subcap_t **); 3837 3838 struct pcieadm_pci_cap { 3839 uint32_t ppc_id; 3840 const char *ppc_short; 3841 const char *ppc_human; 3842 pcieadm_cap_info_f ppc_info; 3843 pcieadm_cap_vers_t ppc_vers[4]; 3844 }; 3845 3846 /* 3847 * Capability version determinations. 3848 */ 3849 3850 static void 3851 pcieadm_cap_info_fixed(pcieadm_cfgspace_walk_t *walkp, 3852 const pcieadm_pci_cap_t *cap, uint32_t off, 3853 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3854 const pcieadm_subcap_t **subcap) 3855 { 3856 *versp = &cap->ppc_vers[0]; 3857 *lenp = cap->ppc_vers[0].ppr_len; 3858 *subcap = NULL; 3859 } 3860 3861 static void 3862 pcieadm_cap_info_vers(pcieadm_cfgspace_walk_t *walkp, 3863 const pcieadm_pci_cap_t *cap, uint32_t off, 3864 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3865 const pcieadm_subcap_t **subcap) 3866 { 3867 uint8_t vers; 3868 3869 *subcap = NULL; 3870 vers = walkp->pcw_data->pcb_u8[off + 2] & 0xf; 3871 for (uint32_t i = 0; i < ARRAY_SIZE(cap->ppc_vers); i++) { 3872 if (vers == cap->ppc_vers[i].ppr_vers && 3873 cap->ppc_vers[i].ppr_vers != 0) { 3874 *versp = &cap->ppc_vers[i]; 3875 *lenp = cap->ppc_vers[i].ppr_len; 3876 return; 3877 } 3878 } 3879 3880 *versp = NULL; 3881 *lenp = 0; 3882 } 3883 3884 /* 3885 * The PCI Power Management capability uses a 3-bit version ID as opposed to the 3886 * standard 4-bit version. 3887 */ 3888 static void 3889 pcieadm_cap_info_pcipm(pcieadm_cfgspace_walk_t *walkp, 3890 const pcieadm_pci_cap_t *cap, uint32_t off, 3891 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3892 const pcieadm_subcap_t **subcap) 3893 { 3894 uint8_t vers; 3895 3896 *subcap = NULL; 3897 vers = walkp->pcw_data->pcb_u8[off + 2] & 0x7; 3898 for (uint32_t i = 0; i < ARRAY_SIZE(cap->ppc_vers); i++) { 3899 if (vers == cap->ppc_vers[i].ppr_vers) { 3900 *versp = &cap->ppc_vers[i]; 3901 *lenp = cap->ppc_vers[i].ppr_len; 3902 return; 3903 } 3904 } 3905 3906 *versp = NULL; 3907 *lenp = 0; 3908 } 3909 3910 /* 3911 * The length of the MSI capability depends on bits in its control field. As 3912 * such we use a custom function to extract the length and treat each of these 3913 * variants as thought it were a different version. 3914 */ 3915 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_32 = { 3916 0, 0xa, pcieadm_cap_msi_32 3917 }; 3918 3919 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_32ext = { 3920 0, 0xc, pcieadm_cap_msi_32ext 3921 }; 3922 3923 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_64 = { 3924 0, 0xe, pcieadm_cap_msi_64 3925 }; 3926 3927 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_64ext = { 3928 0, 0x10, pcieadm_cap_msi_64ext 3929 }; 3930 3931 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_32pvm = { 3932 0, 0x14, pcieadm_cap_msi_32pvm 3933 }; 3934 3935 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_64pvm = { 3936 0, 0x18, pcieadm_cap_msi_64pvm 3937 }; 3938 3939 static void 3940 pcieadm_cap_info_msi(pcieadm_cfgspace_walk_t *walkp, 3941 const pcieadm_pci_cap_t *cap, uint32_t off, 3942 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3943 const pcieadm_subcap_t **subcap) 3944 { 3945 uint16_t ctrl; 3946 boolean_t addr64, pvm, ext; 3947 3948 *subcap = NULL; 3949 ctrl = walkp->pcw_data->pcb_u8[off + 2] | 3950 (walkp->pcw_data->pcb_u8[off + 3] << 8); 3951 if (ctrl == PCI_EINVAL16) { 3952 warnx("failed to read MSI Message Control register"); 3953 *lenp = 0; 3954 *versp = NULL; 3955 return; 3956 } 3957 3958 /* 3959 * The MSI capability has three main things that control its size. 3960 * 64-bit addressing adds 4 bytes. Per-Vector Masking adds 8 bytes and 3961 * causes the Extended data addressing piece to always be present. 3962 * Therefore we check first for pvm as it implies evt, effectively. 3963 */ 3964 addr64 = (ctrl & PCI_MSI_64BIT_MASK) != 0; 3965 pvm = (ctrl & PCI_MSI_PVM_MASK) != 0; 3966 ext = (ctrl & PCI_MSI_EMD_MASK) != 0; 3967 3968 if (pvm && addr64) { 3969 *versp = &pcieadm_cap_vers_msi_64pvm; 3970 } else if (pvm) { 3971 *versp = &pcieadm_cap_vers_msi_32pvm; 3972 } else if (addr64 && ext) { 3973 *versp = &pcieadm_cap_vers_msi_64ext; 3974 } else if (addr64) { 3975 *versp = &pcieadm_cap_vers_msi_64; 3976 } else if (ext) { 3977 *versp = &pcieadm_cap_vers_msi_32ext; 3978 } else { 3979 *versp = &pcieadm_cap_vers_msi_32; 3980 } 3981 3982 *lenp = (*versp)->ppr_len; 3983 } 3984 3985 /* 3986 * The AER Capability is technically different for PCIe-PCI bridges. If we find 3987 * that device type here, then we need to use a different version information 3988 * rather than the actual set defined with the device (which have changed over 3989 * time). 3990 */ 3991 static const pcieadm_cap_vers_t pcieadm_cap_vers_aer_bridge = { 3992 1, 0x4c, pcieadm_cap_aer_bridge 3993 }; 3994 3995 static void 3996 pcieadm_cap_info_aer(pcieadm_cfgspace_walk_t *walkp, 3997 const pcieadm_pci_cap_t *cap, uint32_t off, 3998 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3999 const pcieadm_subcap_t **subcap) 4000 { 4001 if (walkp->pcw_dtype == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) { 4002 uint8_t vers; 4003 4004 *subcap = NULL; 4005 vers = walkp->pcw_data->pcb_u8[off + 2] & 0xf; 4006 if (vers != pcieadm_cap_vers_aer_bridge.ppr_vers) { 4007 warnx("encountered PCIe to PCI bridge with unknown " 4008 "AER capability version: %u", vers); 4009 *lenp = 0; 4010 *versp = NULL; 4011 return; 4012 } 4013 *lenp = pcieadm_cap_vers_aer_bridge.ppr_len; 4014 *versp = &pcieadm_cap_vers_aer_bridge; 4015 } 4016 4017 return (pcieadm_cap_info_vers(walkp, cap, off, versp, lenp, subcap)); 4018 } 4019 4020 /* 4021 * The PCI-X capability varies depending on the header type of the device. 4022 * Therefore we simply use the device type to figure out what to do. 4023 */ 4024 static pcieadm_cap_vers_t pcieadm_cap_vers_pcix_dev = { 4025 0, 0x8, pcieadm_cap_pcix_dev 4026 }; 4027 4028 static pcieadm_cap_vers_t pcieadm_cap_vers_pcix_bridge = { 4029 0, 0x10, pcieadm_cap_pcix_bridge 4030 }; 4031 4032 static void 4033 pcieadm_cap_info_pcix(pcieadm_cfgspace_walk_t *walkp, 4034 const pcieadm_pci_cap_t *cap, uint32_t off, 4035 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 4036 const pcieadm_subcap_t **subcap) 4037 { 4038 4039 *subcap = NULL; 4040 switch (walkp->pcw_dtype) { 4041 case PCI_HEADER_ZERO: 4042 *versp = &pcieadm_cap_vers_pcix_dev; 4043 break; 4044 case PCI_HEADER_ONE: 4045 *versp = &pcieadm_cap_vers_pcix_bridge; 4046 break; 4047 default: 4048 warnx("encountered PCI-X capability with unsupported device " 4049 "type: 0x%x\n", walkp->pcw_dtype); 4050 *lenp = 0; 4051 *versp = NULL; 4052 return; 4053 } 4054 4055 *lenp = (*versp)->ppr_len; 4056 } 4057 4058 typedef struct pcieadm_cap_ht { 4059 uint32_t pch_capid; 4060 pcieadm_subcap_t pch_subcap; 4061 pcieadm_cap_vers_t pch_vers; 4062 } pcieadm_cap_ht_t; 4063 4064 static pcieadm_cap_ht_t pcieadm_ht_cap_pri = { 4065 0x00, { "pri", "Primary" }, { 0, 0x1c, pcieadm_cap_ht_pri } 4066 }; 4067 4068 static pcieadm_cap_ht_t pcieadm_ht_cap_sec = { 4069 0x01, { "sec", "Secondary" }, { 0, 0x18, pcieadm_cap_ht_sec } 4070 }; 4071 4072 static pcieadm_cap_ht_t pcieadm_ht_caps[] = { 4073 { 0x08, { "switch", "Switch" } }, 4074 { 0x10, { "intr", "Interrupt Discovery and Configuration" }, 4075 { 0, 8, pcieadm_cap_ht_intr } }, 4076 { 0x11, { "rev", "Revision ID" } }, 4077 { 0x12, { "unitid", "UnitID Clumping" } }, 4078 { 0x13, { "extcfg", "Extended Configuration Space Access" } }, 4079 { 0x14, { "addrmap", "Address Mapping" } }, 4080 { 0x15, { "msi", "MSI Mapping" }, 4081 { 0, 4, pcieadm_cap_ht_msi } }, 4082 { 0x16, { "dir", "DirectRoute" } }, 4083 { 0x17, { "vcset", "VCSet" } }, 4084 { 0x18, { "retry", "Retry Mode" } }, 4085 { 0x19, { "x86", "X86 Encoding" } }, 4086 { 0x1a, { "gen3", "Gen3" } }, 4087 { 0x1b, { "fle", "Function-Level Extension" } }, 4088 { 0x1c, { "pm", "Power Management" } }, 4089 { UINT32_MAX, NULL }, 4090 }; 4091 4092 static void 4093 pcieadm_cap_info_ht(pcieadm_cfgspace_walk_t *walkp, 4094 const pcieadm_pci_cap_t *cap, uint32_t off, 4095 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 4096 const pcieadm_subcap_t **subcap) 4097 { 4098 uint32_t base = walkp->pcw_data->pcb_u32[off / 4]; 4099 uint32_t caplo = BITX(base, 31, 29); 4100 pcieadm_cap_ht_t *htcap = NULL; 4101 4102 *versp = NULL; 4103 *lenp = 0; 4104 *subcap = NULL; 4105 4106 if (caplo > 1) { 4107 uint32_t capid = BITX(base, 31, 27); 4108 4109 for (uint32_t i = 0; pcieadm_ht_caps[i].pch_capid != UINT32_MAX; 4110 i++) { 4111 if (capid == pcieadm_ht_caps[i].pch_capid) { 4112 htcap = &pcieadm_ht_caps[i]; 4113 break; 4114 } 4115 } 4116 } else if (caplo == 0) { 4117 htcap = &pcieadm_ht_cap_pri; 4118 } else if (caplo == 1) { 4119 htcap = &pcieadm_ht_cap_sec; 4120 } 4121 4122 if (htcap == NULL) { 4123 warnx("encountered unknown HyperTransport Capability 0x%x", 4124 BITX(base, 31, 27)); 4125 return; 4126 } 4127 4128 *subcap = &htcap->pch_subcap; 4129 if (htcap->pch_vers.ppr_print != NULL) { 4130 *versp = &htcap->pch_vers; 4131 *lenp = htcap->pch_vers.ppr_len; 4132 } 4133 } 4134 4135 pcieadm_pci_cap_t pcieadm_pci_caps[] = { 4136 { PCI_CAP_ID_PM, "pcipm", "PCI Power Management", 4137 pcieadm_cap_info_pcipm, { { 2, 8, pcieadm_cap_pcipm_v3 }, 4138 { 3, 8, pcieadm_cap_pcipm_v3 } } }, 4139 { PCI_CAP_ID_AGP, "agp", "Accelerated Graphics Port" }, 4140 { PCI_CAP_ID_VPD, "vpd", "Vital Product Data", pcieadm_cap_info_fixed, 4141 { { 0, 8, pcieadm_cap_vpd } } }, 4142 { PCI_CAP_ID_SLOT_ID, "slot", "Slot Identification" }, 4143 { PCI_CAP_ID_MSI, "msi", "Message Signaled Interrupts", 4144 pcieadm_cap_info_msi }, 4145 { PCI_CAP_ID_cPCI_HS, "cpci", "CompactPCI Hot Swap" }, 4146 { PCI_CAP_ID_PCIX, "pcix", "PCI-X", pcieadm_cap_info_pcix }, 4147 { PCI_CAP_ID_HT, "ht", "HyperTransport", pcieadm_cap_info_ht }, 4148 { PCI_CAP_ID_VS, "vs", "Vendor Specific", pcieadm_cap_info_fixed, 4149 { { 0, 3, pcieadm_cap_vs } } }, 4150 { PCI_CAP_ID_DEBUG_PORT, "dbg", "Debug Port", pcieadm_cap_info_fixed, 4151 { { 0, 4, pcieadm_cap_debug } } }, 4152 { PCI_CAP_ID_cPCI_CRC, "cpcicrc", 4153 "CompactPCI Central Resource Control" }, 4154 { PCI_CAP_ID_PCI_HOTPLUG, "pcihp", "PCI Hot-Plug" }, 4155 { PCI_CAP_ID_P2P_SUBSYS, "bdgsub", "PCI Bridge Subsystem Vendor ID", 4156 pcieadm_cap_info_fixed, { 0, 8, pcieadm_cap_bridge_subsys } }, 4157 { PCI_CAP_ID_AGP_8X, "agp8x", "AGP 8x" }, 4158 { PCI_CAP_ID_SECURE_DEV, "secdev", "Secure Device" }, 4159 { PCI_CAP_ID_PCI_E, "pcie", "PCI Express", pcieadm_cap_info_vers, 4160 { { 1, 0x24, pcieadm_cap_pcie_v1 }, 4161 { 2, 0x3c, pcieadm_cap_pcie_v2 } } }, 4162 { PCI_CAP_ID_MSI_X, "msix", "MSI-X", pcieadm_cap_info_fixed, 4163 { { 0, 12, pcieadm_cap_msix } } }, 4164 { PCI_CAP_ID_SATA, "sata", "Serial ATA Configuration", 4165 pcieadm_cap_info_fixed, { { 0, 8, pcieadm_cap_sata } } }, 4166 /* 4167 * Note, the AF feature doesn't have a version but encodes a length in 4168 * the version field, so we cheat and use that. 4169 */ 4170 { PCI_CAP_ID_FLR, "af", "Advanced Features", pcieadm_cap_info_vers, 4171 { { 6, 6, pcieadm_cap_af } } }, 4172 { PCI_CAP_ID_EA, "ea", "Enhanced Allocation" }, 4173 { PCI_CAP_ID_FPB, "fpb", "Flattening Portal Bridge" } 4174 }; 4175 4176 pcieadm_pci_cap_t pcieadm_pcie_caps[] = { 4177 { 0, "null", "NULL Capability", pcieadm_cap_info_fixed, 4178 { { 0, 0x4, pcieadm_cap_null } } }, 4179 { PCIE_EXT_CAP_ID_AER, "aer", "Advanced Error Reporting", 4180 pcieadm_cap_info_aer, { { 1, 0x38, pcieadm_cap_aer_v1 }, 4181 { 2, 0x48, pcieadm_cap_aer_v2 } } }, 4182 { PCIE_EXT_CAP_ID_VC, "vc", "Virtual Channel", pcieadm_cap_info_vers, 4183 { { 0x1, 0x1c, pcieadm_cap_vc } } }, 4184 { PCIE_EXT_CAP_ID_SER, "sn", "Serial Number", pcieadm_cap_info_vers, 4185 { { 1, 0xc, pcieadm_cap_sn } } }, 4186 { PCIE_EXT_CAP_ID_PWR_BUDGET, "powbudg", "Power Budgeting", 4187 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_powbudg } } }, 4188 { PCIE_EXT_CAP_ID_RC_LINK_DECL, "rcld", 4189 "Root Complex Link Declaration" }, 4190 { PCIE_EXT_CAP_ID_RC_INT_LINKCTRL, "rcilc", 4191 "Root Complex Internal Link Control" }, 4192 { PCIE_EXT_CAP_ID_RC_EVNT_CEA, "rcecea", 4193 "Root Complex Event Collector Endpoint Aggregation" }, 4194 { PCIE_EXT_CAP_ID_MFVC, "mfvc", "Multi-Function Virtual Channel" }, 4195 { PCIE_EXT_CAP_ID_VC_WITH_MFVC, "vcwmfvc", "Virtual Channel with MFVC", 4196 pcieadm_cap_info_vers, { { 0x1, 0x1c, pcieadm_cap_vc } } }, 4197 { PCIE_EXT_CAP_ID_RCRB, "rcrb", "Root Complex Register Block" }, 4198 { PCIE_EXT_CAP_ID_VS, "vsec", "Vendor Specific Extended Capability", 4199 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_vsec } } }, 4200 { PCIE_EXT_CAP_ID_CAC, "cac", "Configuration Access Correlation" }, 4201 { PCIE_EXT_CAP_ID_ACS, "acs", "Access Control Services", 4202 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_acs } } }, 4203 { PCIE_EXT_CAP_ID_ARI, "ari", "Alternative Routing-ID Interpretation", 4204 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_ari } } }, 4205 { PCIE_EXT_CAP_ID_ATS, "ats", "Access Translation Services", 4206 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_ats } } }, 4207 { PCIE_EXT_CAP_ID_SRIOV, "sriov", "Single Root I/O Virtualization", 4208 pcieadm_cap_info_vers, { { 1, 0x40, pcieadm_cap_sriov } } }, 4209 { PCIE_EXT_CAP_ID_MRIOV, "mriov", "Multi-Root I/O Virtualization" }, 4210 { PCIE_EXT_CAP_ID_MULTICAST, "mcast", "Multicast", 4211 pcieadm_cap_info_vers, { { 1, 0x30, pcieadm_cap_mcast } } }, 4212 { PCIE_EXT_CAP_ID_PGREQ, "pgreq", "Page Request", 4213 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_pgreq } } }, 4214 { PCIE_EXT_CAP_ID_EA, "ea", "Enhanced Allocation" }, 4215 { PCIE_EXT_CAP_ID_RESIZE_BAR, "rbar", "Resizable Bar" }, 4216 { PCIE_EXT_CAP_ID_DPA, "dpa", "Dynamic Power Allocation", 4217 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_dpa } } }, 4218 { PCIE_EXT_CAP_ID_TPH_REQ, "tph", "TPH Requester", 4219 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_tph } } }, 4220 { PCIE_EXT_CAP_ID_LTR, "ltr", "Latency Tolerance Reporting", 4221 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_ltr } } }, 4222 { PCIE_EXT_CAP_ID_PCIE2, "pcie2", "Secondary PCI Express", 4223 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_pcie2 } } }, 4224 { PCIE_EXT_CAP_ID_PASID, "pasid", "Process Address Space ID", 4225 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_pasid } } }, 4226 { PCIE_EXT_CAP_ID_LNR, "lnr", "LN Requester" }, 4227 { PCIE_EXT_CAP_ID_DPC, "dpc", "Downstream Port Containment", 4228 pcieadm_cap_info_vers, { { 1, 0x30, pcieadm_cap_dpc } } }, 4229 { PCIE_EXT_CAP_ID_L1PM, "l1pm", "L1 PM Substates", 4230 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_l1pm_v1 }, 4231 { 2, 0x14, pcieadm_cap_l1pm_v2 } } }, 4232 { PCIE_EXT_CAP_ID_PTM, "ptm", "Precision Time Management", 4233 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_info_ptm } } }, 4234 { PCIE_EXT_CAP_ID_FRS, "frs", "FRS Queueing" }, 4235 { PCIE_EXT_CAP_ID_RTR, "trt", "Readiness Time Reporting" }, 4236 /* 4237 * When we encounter a designated vendor specificaiton, in particular, 4238 * for CXL, we'll want to set ppc_subcap so we can use reasonable 4239 * filtering. 4240 */ 4241 { PCIE_EXT_CAP_ID_DVS, "dvsec", 4242 "Designated Vendor-Specific Extended Capability" }, 4243 { PCIE_EXT_CAP_ID_VFRBAR, "vfrbar", "Virtual Function Resizable BAR" }, 4244 { PCIE_EXT_CAP_ID_DLF, "dlf", "Data Link Feature", 4245 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_dlf } } }, 4246 { PCIE_EXT_CAP_ID_PL16GT, "pl16g", "Physical Layer 16.0 GT/s", 4247 pcieadm_cap_info_vers, { { 1, 0x22, pcieadm_cap_16g } } }, 4248 { PCIE_EXT_CAP_ID_LANE_MARGIN, "margin", 4249 "Lane Margining at the Receiver", pcieadm_cap_info_vers, 4250 { { 1, 0x8, pcieadm_cap_margin } } }, 4251 { PCIE_EXT_CAP_ID_HIEARCHY_ID, "hierid", "Hierarchy ID" }, 4252 { PCIE_EXT_CAP_ID_NPEM, "npem", "Native PCIe Enclosure Management" }, 4253 { PCIE_EXT_CAP_ID_PL32GT, "pl32g", "Physical Layer 32.0 GT/s" }, 4254 { PCIE_EXT_CAP_ID_AP, "ap", "Alternative Protocol" }, 4255 { PCIE_EXT_CAP_ID_SFI, "sfi", "System Firmware Intermediary" } 4256 }; 4257 4258 static const pcieadm_pci_cap_t * 4259 pcieadm_cfgspace_match_cap(uint32_t capid, boolean_t pcie) 4260 { 4261 uint_t ncaps; 4262 pcieadm_pci_cap_t *caps; 4263 4264 if (pcie) { 4265 ncaps = ARRAY_SIZE(pcieadm_pcie_caps); 4266 caps = pcieadm_pcie_caps; 4267 } else { 4268 ncaps = ARRAY_SIZE(pcieadm_pci_caps); 4269 caps = pcieadm_pci_caps; 4270 } 4271 4272 for (uint_t i = 0; i < ncaps; i++) { 4273 if (caps[i].ppc_id == capid) { 4274 return (&caps[i]); 4275 } 4276 } 4277 4278 return (NULL); 4279 } 4280 4281 static void 4282 pcieadm_cfgspace_print_cap(pcieadm_cfgspace_walk_t *walkp, uint_t capid, 4283 const pcieadm_pci_cap_t *cap_info, const pcieadm_cap_vers_t *vers_info, 4284 const pcieadm_subcap_t *subcap) 4285 { 4286 boolean_t filter = B_FALSE; 4287 4288 /* 4289 * If we don't recognize the capability, print out the ID if we're not 4290 * filtering and not in parsable mode. 4291 */ 4292 if (cap_info == NULL) { 4293 if (walkp->pcw_ofmt == NULL && 4294 pcieadm_cfgspace_filter(walkp, NULL)) { 4295 warnx("encountered unknown capability ID 0x%x " 4296 "unable to print or list", capid); 4297 pcieadm_print("Unknown Capability (0x%x)\n", capid); 4298 } 4299 return; 4300 } 4301 4302 /* 4303 * Check to see if we should print this and in particular, if there's 4304 * both a capability or subcapability, we need to try and match both. 4305 * The reason that the calls to check the filters are conditioned on 4306 * pcw_ofmt is that when we're in parsable mode, we cannot match a 4307 * top-level capability since it's an arbitrary number of fields. 4308 */ 4309 if (walkp->pcw_ofmt == NULL) { 4310 filter = pcieadm_cfgspace_filter(walkp, cap_info->ppc_short); 4311 } 4312 pcieadm_strfilt_push(walkp, cap_info->ppc_short); 4313 if (subcap != NULL) { 4314 if (walkp->pcw_ofmt == NULL) { 4315 boolean_t subfilt = pcieadm_cfgspace_filter(walkp, 4316 subcap->psub_short); 4317 filter = subfilt || filter; 4318 } 4319 pcieadm_strfilt_push(walkp, subcap->psub_short); 4320 } 4321 4322 4323 if (walkp->pcw_ofmt == NULL && filter) { 4324 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 4325 if (subcap != NULL) { 4326 pcieadm_print("%s Capability - %s (%s) " 4327 "(0x%x)\n", cap_info->ppc_human, 4328 subcap->psub_human, 4329 walkp->pcw_filt->pstr_curgen, capid); 4330 } else { 4331 pcieadm_print("%s Capability (%s) (0x%x)\n", 4332 cap_info->ppc_human, 4333 walkp->pcw_filt->pstr_curgen, capid); 4334 } 4335 } else { 4336 if (subcap != NULL) { 4337 pcieadm_print("%s Capability - %s (0x%x)\n", 4338 cap_info->ppc_human, subcap->psub_human, 4339 capid); 4340 } else { 4341 pcieadm_print("%s Capability (0x%x)\n", 4342 cap_info->ppc_human, capid); 4343 } 4344 } 4345 } 4346 4347 if (vers_info != NULL) { 4348 pcieadm_cfgspace_print_t *print; 4349 4350 pcieadm_indent(); 4351 for (print = vers_info->ppr_print; 4352 print->pcp_short != NULL; print++) { 4353 VERIFY3P(print->pcp_print, !=, NULL); 4354 print->pcp_print(walkp, print, 4355 print->pcp_arg); 4356 } 4357 pcieadm_deindent(); 4358 } else { 4359 if (subcap != NULL) { 4360 warnx("Unable to print or list %s - %s (no support or " 4361 "missing version info)", cap_info->ppc_human, 4362 subcap->psub_human); 4363 } else { 4364 warnx("Unable to print or list %s (no support or " 4365 "missing version info)", cap_info->ppc_human); 4366 } 4367 } 4368 4369 if (subcap != NULL) { 4370 pcieadm_strfilt_pop(walkp); 4371 } 4372 pcieadm_strfilt_pop(walkp); 4373 } 4374 4375 static void 4376 pcieadm_cfgspace_write(int fd, const uint8_t *source, size_t len) 4377 { 4378 size_t off = 0; 4379 4380 while (len > 0) { 4381 ssize_t ret = write(fd, source + off, len - off); 4382 if (ret < 0) { 4383 err(EXIT_FAILURE, "failed to write config space to " 4384 "output file"); 4385 } 4386 4387 off += ret; 4388 len -= ret; 4389 } 4390 } 4391 4392 void 4393 pcieadm_cfgspace(pcieadm_t *pcip, pcieadm_cfgspace_op_t op, 4394 pcieadm_cfgspace_f readf, int fd, void *readarg, uint_t nfilts, 4395 pcieadm_cfgspace_filter_t *filters, pcieadm_cfgspace_flags_t flags, 4396 ofmt_handle_t ofmt) 4397 { 4398 uint_t type; 4399 uint16_t cap; 4400 pcieadm_cfgspace_data_t data; 4401 pcieadm_cfgspace_walk_t walk; 4402 const char *headstr, *headshort; 4403 pcieadm_cfgspace_print_t *header; 4404 boolean_t capsup = B_FALSE, extcfg = B_FALSE; 4405 uint_t ncaps; 4406 4407 walk.pcw_pcieadm = pcip; 4408 walk.pcw_op = op; 4409 walk.pcw_data = &data; 4410 walk.pcw_outfd = fd; 4411 walk.pcw_capoff = 0; 4412 walk.pcw_nlanes = 0; 4413 walk.pcw_nfilters = nfilts; 4414 walk.pcw_filters = filters; 4415 walk.pcw_flags = flags; 4416 walk.pcw_ofmt = ofmt; 4417 walk.pcw_filt = NULL; 4418 4419 /* 4420 * Start by reading all of the basic 40-byte config space header in one 4421 * fell swoop. 4422 */ 4423 for (uint32_t i = 0; i < PCI_CAP_PTR_OFF / 4; i++) { 4424 if (!readf(i * 4, 4, &data.pcb_u32[i], readarg)) { 4425 errx(EXIT_FAILURE, "failed to read offset %u from " 4426 "configuration space", i * 4); 4427 } 4428 } 4429 walk.pcw_valid = PCI_CAP_PTR_OFF; 4430 walk.pcw_caplen = PCI_CAP_PTR_OFF; 4431 4432 /* 4433 * Grab the information from the header that we need to figure out what 4434 * kind of device this is, how to print it, if there are any 4435 * capabilities, and go from there. 4436 */ 4437 type = data.pcb_u8[PCI_CONF_HEADER] & PCI_HEADER_TYPE_M; 4438 switch (type) { 4439 case PCI_HEADER_ZERO: 4440 headstr = "Type 0 Header"; 4441 headshort = "header0"; 4442 header = pcieadm_cfgspace_type0; 4443 capsup = (data.pcb_u8[PCI_CONF_STAT] & PCI_STAT_CAP) != 0; 4444 break; 4445 case PCI_HEADER_ONE: 4446 headstr = "Type 1 Header"; 4447 headshort = "header1"; 4448 header = pcieadm_cfgspace_type1; 4449 capsup = (data.pcb_u8[PCI_CONF_STAT] & PCI_STAT_CAP) != 0; 4450 break; 4451 case PCI_HEADER_TWO: 4452 default: 4453 headstr = "Unknown Header"; 4454 headshort = "headerX"; 4455 header = pcieadm_cfgspace_unknown; 4456 warnx("unsupported PCI header type: 0x%x, output limited to " 4457 "data configuration space"); 4458 } 4459 4460 walk.pcw_dtype = type; 4461 4462 if (op == PCIEADM_CFGSPACE_OP_WRITE) { 4463 pcieadm_cfgspace_write(fd, &data.pcb_u8[0], PCI_CAP_PTR_OFF); 4464 } else if (op == PCIEADM_CFGSPACE_OP_PRINT) { 4465 pcieadm_cfgspace_print_t *print; 4466 4467 if (walk.pcw_ofmt == NULL && 4468 pcieadm_cfgspace_filter(&walk, headshort)) { 4469 if ((flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 4470 pcieadm_print("Device %s -- %s (%s)\n", 4471 pcip->pia_devstr, headstr, headshort); 4472 } else { 4473 pcieadm_print("Device %s -- %s\n", 4474 pcip->pia_devstr, headstr); 4475 } 4476 } 4477 4478 pcieadm_strfilt_push(&walk, headshort); 4479 pcieadm_indent(); 4480 for (print = header; print->pcp_short != NULL; print++) { 4481 print->pcp_print(&walk, print, print->pcp_arg); 4482 } 4483 pcieadm_deindent(); 4484 pcieadm_strfilt_pop(&walk); 4485 } 4486 4487 4488 if (!capsup) { 4489 return; 4490 } 4491 4492 for (uint32_t i = PCI_CAP_PTR_OFF / 4; i < PCI_CONF_HDR_SIZE / 4; i++) { 4493 if (!readf(i * 4, 4, &data.pcb_u32[i], readarg)) { 4494 errx(EXIT_FAILURE, "failed to read offset %u from " 4495 "configuration space", i * 4); 4496 } 4497 } 4498 walk.pcw_valid = PCIE_EXT_CAP; 4499 VERIFY3P(walk.pcw_filt, ==, NULL); 4500 4501 if (op == PCIEADM_CFGSPACE_OP_WRITE) { 4502 pcieadm_cfgspace_write(fd, &data.pcb_u8[PCI_CAP_PTR_OFF], 4503 PCI_CONF_HDR_SIZE - PCI_CAP_PTR_OFF); 4504 } 4505 4506 ncaps = 0; 4507 cap = data.pcb_u8[PCI_CONF_CAP_PTR]; 4508 while (cap != 0 && cap != PCI_EINVAL8) { 4509 const pcieadm_pci_cap_t *cap_info; 4510 const pcieadm_cap_vers_t *vers_info = NULL; 4511 const pcieadm_subcap_t *subcap = NULL; 4512 uint8_t cap_id, nextcap; 4513 uint32_t read_len = 0; 4514 4515 /* 4516 * The PCI specification requires that the caller mask off the 4517 * bottom two bits. Always check for an invalid value (all 1s) 4518 * before this. 4519 */ 4520 cap &= PCI_CAP_PTR_MASK; 4521 cap_id = data.pcb_u8[cap + PCI_CAP_ID]; 4522 nextcap = data.pcb_u8[cap + PCI_CAP_NEXT_PTR]; 4523 cap_info = pcieadm_cfgspace_match_cap(cap_id, B_FALSE); 4524 if (cap_info != NULL && cap_info->ppc_info != NULL) { 4525 cap_info->ppc_info(&walk, cap_info, cap, &vers_info, 4526 &read_len, &subcap); 4527 } 4528 4529 walk.pcw_caplen = read_len; 4530 walk.pcw_capoff = cap; 4531 4532 if (cap_id == PCI_CAP_ID_PCI_E) { 4533 extcfg = B_TRUE; 4534 if (walk.pcw_valid != 0) { 4535 walk.pcw_pcietype = data.pcb_u8[cap + 4536 PCIE_PCIECAP] & PCIE_PCIECAP_DEV_TYPE_MASK; 4537 walk.pcw_nlanes = (data.pcb_u8[cap + 4538 PCIE_LINKCAP] & 0xf0) >> 4; 4539 walk.pcw_nlanes |= (data.pcb_u8[cap + 4540 PCIE_LINKCAP + 1] & 0x01) << 4; 4541 } else { 4542 walk.pcw_pcietype = UINT_MAX; 4543 } 4544 } 4545 4546 if (op == PCIEADM_CFGSPACE_OP_PRINT) { 4547 pcieadm_cfgspace_print_cap(&walk, cap_id, cap_info, 4548 vers_info, subcap); 4549 } 4550 4551 cap = nextcap; 4552 ncaps++; 4553 if (ncaps >= PCI_CAP_MAX_PTR) { 4554 errx(EXIT_FAILURE, "encountered more PCI capabilities " 4555 "than fit in configuration space"); 4556 } 4557 } 4558 4559 if (!extcfg) { 4560 return; 4561 } 4562 4563 for (uint_t i = PCIE_EXT_CAP / 4; i < PCIE_CONF_HDR_SIZE / 4; i++) { 4564 if (!readf(i * 4, 4, &data.pcb_u32[i], readarg)) { 4565 errx(EXIT_FAILURE, "failed to read offset %u from " 4566 "configuration space", i * 4); 4567 } 4568 } 4569 walk.pcw_valid = PCIE_CONF_HDR_SIZE; 4570 4571 if (op == PCIEADM_CFGSPACE_OP_WRITE) { 4572 pcieadm_cfgspace_write(fd, &data.pcb_u8[PCIE_EXT_CAP], 4573 PCIE_CONF_HDR_SIZE - PCIE_EXT_CAP); 4574 return; 4575 } 4576 4577 cap = PCIE_EXT_CAP; 4578 ncaps = 0; 4579 while (cap != 0 && cap != PCI_EINVAL16) { 4580 uint16_t cap_id, nextcap; 4581 const pcieadm_pci_cap_t *cap_info; 4582 const pcieadm_cap_vers_t *vers_info = NULL; 4583 const pcieadm_subcap_t *subcap = NULL; 4584 uint32_t read_len = 0; 4585 4586 /* 4587 * PCIe has the same masking as PCI. Note, sys/pcie.h currently 4588 * has PCIE_EXT_CAP_NEXT_PTR_MASK as 0xfff, instead of the 4589 * below. This should be switched to PCIE_EXT_CAP_NEXT_PTR_MASK 4590 * when the kernel headers are fixed. 4591 */ 4592 cap &= 0xffc; 4593 4594 /* 4595 * While this seems duplicative of the loop condition, a device 4596 * without capabilities indicates it with a zero for the first 4597 * cap. 4598 */ 4599 if (data.pcb_u32[cap / 4] == 0 || 4600 data.pcb_u32[cap / 4] == PCI_EINVAL32) 4601 break; 4602 4603 cap_id = data.pcb_u32[cap / 4] & PCIE_EXT_CAP_ID_MASK; 4604 nextcap = (data.pcb_u32[cap / 4] >> 4605 PCIE_EXT_CAP_NEXT_PTR_SHIFT) & PCIE_EXT_CAP_NEXT_PTR_MASK; 4606 4607 cap_info = pcieadm_cfgspace_match_cap(cap_id, B_TRUE); 4608 if (cap_info != NULL && cap_info->ppc_info != NULL) { 4609 cap_info->ppc_info(&walk, cap_info, cap, &vers_info, 4610 &read_len, &subcap); 4611 } 4612 4613 walk.pcw_caplen = read_len; 4614 walk.pcw_capoff = cap; 4615 4616 if (op == PCIEADM_CFGSPACE_OP_PRINT) { 4617 pcieadm_cfgspace_print_cap(&walk, cap_id, cap_info, 4618 vers_info, subcap); 4619 } 4620 4621 cap = nextcap; 4622 ncaps++; 4623 if (ncaps >= PCIE_EXT_CAP_MAX_PTR) { 4624 errx(EXIT_FAILURE, "encountered more PCI capabilities " 4625 "than fit in configuration space"); 4626 } 4627 } 4628 } 4629 4630 void 4631 pcieadm_show_cfgspace_usage(FILE *f) 4632 { 4633 (void) fprintf(f, "\tshow-cfgspace\t[-L] [-n] [-H] -d device | -f file " 4634 "[filter...]\n"); 4635 (void) fprintf(f, "\tshow-cfgspace\t-p -o field[,...] [-H] -d device | " 4636 "-f file [filter...]\n"); 4637 } 4638 4639 static void 4640 pcieadm_show_cfgspace_help(const char *fmt, ...) 4641 { 4642 if (fmt != NULL) { 4643 va_list ap; 4644 4645 va_start(ap, fmt); 4646 vwarnx(fmt, ap); 4647 va_end(ap); 4648 (void) fprintf(stderr, "\n"); 4649 } 4650 4651 (void) fprintf(stderr, "Usage: %s show-cfgspace [-L] [-n] [-H] -d " 4652 "device | -f file [filter...]\n", pcieadm_progname); 4653 (void) fprintf(stderr, " %s show-cfgspace -p -o field[,...] " 4654 "[-H] -d device | -f file\n\t\t\t [filter...]\n", 4655 pcieadm_progname); 4656 4657 (void) fprintf(stderr, "\nPrint and decode PCI configuration space " 4658 "data from a device or file. Each\n<filter> selects a given " 4659 "capability, sub-capability, register, or field to print.\n\n" 4660 "\t-d device\tread data from the specified device (driver instance," 4661 "\n\t\t\t/devices path, or b/d/f)\n" 4662 "\t-f file\t\tread data from the specified file\n" 4663 "\t-L\t\tlist printable fields\n" 4664 "\t-n\t\tshow printable short names\n" 4665 "\t-H\t\tomit the column header (for -L and -p)\n" 4666 "\t-p\t\tparsable output (requires -o)\n" 4667 "\t-o field\toutput fields to print (required for -p)\n"); 4668 } 4669 4670 int 4671 pcieadm_show_cfgspace(pcieadm_t *pcip, int argc, char *argv[]) 4672 { 4673 int c, ret; 4674 pcieadm_cfgspace_f readf; 4675 void *readarg; 4676 boolean_t list = B_FALSE, parse = B_FALSE; 4677 const char *device = NULL, *file = NULL, *fields = NULL; 4678 uint_t nfilts = 0; 4679 pcieadm_cfgspace_filter_t *filts = NULL; 4680 pcieadm_cfgspace_flags_t flags = 0; 4681 uint_t oflags = 0; 4682 ofmt_handle_t ofmt = NULL; 4683 4684 while ((c = getopt(argc, argv, ":HLd:f:o:np")) != -1) { 4685 switch (c) { 4686 case 'd': 4687 device = optarg; 4688 break; 4689 case 'L': 4690 list = B_TRUE; 4691 break; 4692 case 'f': 4693 file = optarg; 4694 break; 4695 case 'p': 4696 parse = B_TRUE; 4697 flags |= PCIEADM_CFGSPACE_F_PARSE; 4698 oflags |= OFMT_PARSABLE; 4699 break; 4700 case 'n': 4701 flags |= PCIEADM_CFGSPACE_F_SHORT; 4702 break; 4703 case 'H': 4704 oflags |= OFMT_NOHEADER; 4705 break; 4706 case 'o': 4707 fields = optarg; 4708 break; 4709 case ':': 4710 pcieadm_show_cfgspace_help("Option -%c requires an " 4711 "argument", optopt); 4712 exit(EXIT_USAGE); 4713 case '?': 4714 default: 4715 pcieadm_show_cfgspace_help("unknown option: -%c", 4716 optopt); 4717 exit(EXIT_USAGE); 4718 } 4719 } 4720 4721 argc -= optind; 4722 argv += optind; 4723 4724 if (device == NULL && file == NULL) { 4725 pcieadm_show_cfgspace_help("one of -d or -f must be specified"); 4726 exit(EXIT_USAGE); 4727 } 4728 4729 if (device != NULL && file != NULL) { 4730 pcieadm_show_cfgspace_help("only one of -d and -f must be " 4731 "specified"); 4732 exit(EXIT_USAGE); 4733 } 4734 4735 if (parse && fields == NULL) { 4736 pcieadm_show_cfgspace_help("-p requires fields specified with " 4737 "-o"); 4738 exit(EXIT_USAGE); 4739 } 4740 4741 if (!parse && fields != NULL) { 4742 pcieadm_show_cfgspace_help("-o can only be used with -p"); 4743 exit(EXIT_USAGE); 4744 } 4745 4746 if ((oflags & OFMT_NOHEADER) && !(list || parse)) { 4747 pcieadm_show_cfgspace_help("-H must be used with either -L or " 4748 "-p"); 4749 exit(EXIT_USAGE); 4750 } 4751 4752 if ((flags & PCIEADM_CFGSPACE_F_SHORT) && (list || parse)) { 4753 pcieadm_show_cfgspace_help("-n cannot be used with either -L " 4754 "or -p"); 4755 exit(EXIT_USAGE); 4756 } 4757 4758 if (list && parse != 0) { 4759 pcieadm_show_cfgspace_help("-L and -p cannot be used together"); 4760 exit(EXIT_USAGE); 4761 } 4762 4763 if (list && fields != NULL) { 4764 pcieadm_show_cfgspace_help("-L and -o cannot be used together"); 4765 exit(EXIT_USAGE); 4766 } 4767 4768 if (list) { 4769 fields = "short,human"; 4770 } 4771 4772 if (argc > 0) { 4773 nfilts = argc; 4774 filts = calloc(nfilts, sizeof (pcieadm_cfgspace_filter_t)); 4775 4776 for (int i = 0; i < argc; i++) { 4777 filts[i].pcf_string = argv[i]; 4778 filts[i].pcf_len = strlen(argv[i]); 4779 } 4780 } 4781 4782 if (list || parse) { 4783 ofmt_status_t oferr; 4784 oferr = ofmt_open(fields, pcieadm_cfgspace_ofmt, oflags, 0, 4785 &ofmt); 4786 ofmt_check(oferr, parse, ofmt, pcieadm_ofmt_errx, warnx); 4787 } 4788 4789 /* 4790 * Initialize privileges that we require. For reading from the kernel 4791 * we require all privileges. For a file, we just intersect with things 4792 * that would allow someone to read from any file. 4793 */ 4794 if (device != NULL) { 4795 /* 4796 * We need full privileges if reading from a device, 4797 * unfortunately. 4798 */ 4799 priv_fillset(pcip->pia_priv_eff); 4800 } else { 4801 VERIFY0(priv_addset(pcip->pia_priv_eff, PRIV_FILE_DAC_READ)); 4802 VERIFY0(priv_addset(pcip->pia_priv_eff, PRIV_FILE_DAC_SEARCH)); 4803 } 4804 pcieadm_init_privs(pcip); 4805 4806 if (device != NULL) { 4807 pcieadm_find_dip(pcip, device); 4808 pcieadm_init_cfgspace_kernel(pcip, &readf, &readarg); 4809 } else { 4810 pcip->pia_devstr = file; 4811 pcieadm_init_cfgspace_file(pcip, file, &readf, &readarg); 4812 } 4813 pcieadm_cfgspace(pcip, PCIEADM_CFGSPACE_OP_PRINT, readf, -1, readarg, 4814 nfilts, filts, flags, ofmt); 4815 if (device != NULL) { 4816 pcieadm_fini_cfgspace_kernel(readarg); 4817 } else { 4818 pcieadm_fini_cfgspace_file(readarg); 4819 } 4820 4821 ofmt_close(ofmt); 4822 ret = EXIT_SUCCESS; 4823 for (uint_t i = 0; i < nfilts; i++) { 4824 if (!filts[i].pcf_used) { 4825 warnx("filter '%s' did not match any fields", 4826 filts[i].pcf_string); 4827 ret = EXIT_FAILURE; 4828 } 4829 } 4830 4831 return (ret); 4832 } 4833 4834 typedef struct pcieadm_save_cfgspace { 4835 pcieadm_t *psc_pci; 4836 int psc_dirfd; 4837 uint_t psc_nsaved; 4838 int psc_ret; 4839 } pcieadm_save_cfgspace_t; 4840 4841 static int 4842 pcieadm_save_cfgspace_cb(di_node_t devi, void *arg) 4843 { 4844 int fd, nregs, *regs; 4845 pcieadm_save_cfgspace_t *psc = arg; 4846 pcieadm_cfgspace_f readf; 4847 void *readarg; 4848 char fname[128]; 4849 4850 psc->psc_pci->pia_devstr = di_node_name(devi); 4851 psc->psc_pci->pia_devi = devi; 4852 psc->psc_pci->pia_nexus = DI_NODE_NIL; 4853 pcieadm_find_nexus(psc->psc_pci); 4854 if (psc->psc_pci->pia_nexus == DI_NODE_NIL) { 4855 warnx("failed to find nexus for %s", di_node_name(devi)); 4856 psc->psc_ret = EXIT_FAILURE; 4857 return (DI_WALK_CONTINUE); 4858 } 4859 4860 nregs = di_prop_lookup_ints(DDI_DEV_T_ANY, devi, "reg", ®s); 4861 if (nregs <= 0) { 4862 warnx("failed to lookup regs array for %s", 4863 psc->psc_pci->pia_devstr); 4864 psc->psc_ret = EXIT_FAILURE; 4865 return (DI_WALK_CONTINUE); 4866 } 4867 4868 (void) snprintf(fname, sizeof (fname), "%02x-%02x-%02x.pci", 4869 PCI_REG_BUS_G(regs[0]), PCI_REG_DEV_G(regs[0]), 4870 PCI_REG_FUNC_G(regs[0])); 4871 4872 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, psc->psc_pci->pia_priv_eff) != 4873 0) { 4874 err(EXIT_FAILURE, "failed to raise privileges"); 4875 } 4876 fd = openat(psc->psc_dirfd, fname, O_WRONLY | O_TRUNC | O_CREAT, 0666); 4877 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, psc->psc_pci->pia_priv_min) != 4878 0) { 4879 err(EXIT_FAILURE, "failed to reduce privileges"); 4880 } 4881 4882 if (fd < 0) { 4883 warn("failed to create output file %s", fname); 4884 psc->psc_ret = EXIT_FAILURE; 4885 return (DI_WALK_CONTINUE); 4886 } 4887 4888 pcieadm_init_cfgspace_kernel(psc->psc_pci, &readf, &readarg); 4889 pcieadm_cfgspace(psc->psc_pci, PCIEADM_CFGSPACE_OP_WRITE, readf, fd, 4890 readarg, 0, NULL, 0, NULL); 4891 pcieadm_fini_cfgspace_kernel(readarg); 4892 4893 if (close(fd) != 0) { 4894 warn("failed to close output fd for %s", fname); 4895 psc->psc_ret = EXIT_FAILURE; 4896 } else { 4897 psc->psc_nsaved++; 4898 } 4899 4900 return (DI_WALK_CONTINUE); 4901 } 4902 4903 void 4904 pcieadm_save_cfgspace_usage(FILE *f) 4905 { 4906 (void) fprintf(f, "\tsave-cfgspace\t-d device output-file\n"); 4907 (void) fprintf(f, "\tsave-cfgspace\t-a output-directory\n"); 4908 } 4909 4910 static void 4911 pcieadm_save_cfgspace_help(const char *fmt, ...) 4912 { 4913 if (fmt != NULL) { 4914 va_list ap; 4915 4916 va_start(ap, fmt); 4917 vwarnx(fmt, ap); 4918 va_end(ap); 4919 (void) fprintf(stderr, "\n"); 4920 } 4921 4922 (void) fprintf(stderr, "Usage: %s save-cfgspace -d device " 4923 "output-file\n", pcieadm_progname); 4924 (void) fprintf(stderr, " %s save-cfgspace -a " 4925 "output-directory\n", pcieadm_progname); 4926 4927 (void) fprintf(stderr, "\nSave PCI configuration space data from a " 4928 "device to a file or\nsave all devices to a specified directory." 4929 "\n\n" 4930 "\t-a\t\tsave data from all devices\n" 4931 "\t-d device\tread data from the specified device (driver instance," 4932 "\n\t\t\t/devices path, or b/d/f)\n"); 4933 } 4934 4935 int 4936 pcieadm_save_cfgspace(pcieadm_t *pcip, int argc, char *argv[]) 4937 { 4938 int c; 4939 pcieadm_cfgspace_f readf; 4940 void *readarg; 4941 const char *device = NULL; 4942 boolean_t do_all = B_FALSE; 4943 4944 while ((c = getopt(argc, argv, ":ad:")) != -1) { 4945 switch (c) { 4946 case 'a': 4947 do_all = B_TRUE; 4948 break; 4949 case 'd': 4950 device = optarg; 4951 break; 4952 case ':': 4953 pcieadm_save_cfgspace_help("Option -%c requires an " 4954 "argument", optopt); 4955 exit(EXIT_USAGE); 4956 case '?': 4957 default: 4958 pcieadm_save_cfgspace_help("unknown option: -%c", 4959 optopt); 4960 exit(EXIT_USAGE); 4961 } 4962 } 4963 4964 argc -= optind; 4965 argv += optind; 4966 4967 if (device == NULL && !do_all) { 4968 pcieadm_save_cfgspace_help("missing required -d option to " 4969 "indicate device to dump"); 4970 exit(EXIT_USAGE); 4971 } 4972 4973 if (argc != 1) { 4974 pcieadm_save_cfgspace_help("missing required output path"); 4975 exit(EXIT_USAGE); 4976 } 4977 4978 /* 4979 * For reading from devices, we need to full privileges, unfortunately. 4980 */ 4981 priv_fillset(pcip->pia_priv_eff); 4982 pcieadm_init_privs(pcip); 4983 4984 if (!do_all) { 4985 int fd; 4986 4987 pcieadm_find_dip(pcip, device); 4988 4989 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_eff) != 4990 0) { 4991 err(EXIT_FAILURE, "failed to raise privileges"); 4992 } 4993 4994 if ((fd = open(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 4995 0) { 4996 err(EXIT_FAILURE, "failed to open output file %s", 4997 argv[0]); 4998 } 4999 5000 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_min) != 5001 0) { 5002 err(EXIT_FAILURE, "failed to reduce privileges"); 5003 } 5004 5005 pcieadm_init_cfgspace_kernel(pcip, &readf, &readarg); 5006 pcieadm_cfgspace(pcip, PCIEADM_CFGSPACE_OP_WRITE, readf, fd, 5007 readarg, 0, NULL, 0, NULL); 5008 pcieadm_fini_cfgspace_kernel(readarg); 5009 5010 if (close(fd) != 0) { 5011 err(EXIT_FAILURE, "failed to close output file " 5012 "descriptor"); 5013 } 5014 5015 return (EXIT_SUCCESS); 5016 } else { 5017 pcieadm_save_cfgspace_t psc; 5018 pcieadm_di_walk_t walk; 5019 5020 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_eff) != 5021 0) { 5022 err(EXIT_FAILURE, "failed to raise privileges"); 5023 } 5024 5025 if ((psc.psc_dirfd = open(argv[0], O_RDONLY | O_DIRECTORY)) < 5026 0) { 5027 err(EXIT_FAILURE, "failed to open output directory %s", 5028 argv[0]); 5029 } 5030 5031 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_min) != 5032 0) { 5033 err(EXIT_FAILURE, "failed to reduce privileges"); 5034 } 5035 5036 psc.psc_nsaved = 0; 5037 psc.psc_ret = EXIT_SUCCESS; 5038 psc.psc_pci = pcip; 5039 5040 walk.pdw_arg = &psc; 5041 walk.pdw_func = pcieadm_save_cfgspace_cb; 5042 pcieadm_di_walk(pcip, &walk); 5043 5044 VERIFY0(close(psc.psc_dirfd)); 5045 5046 if (psc.psc_nsaved == 0) { 5047 warnx("failed to save any PCI devices"); 5048 return (EXIT_FAILURE); 5049 } 5050 5051 pcieadm_print("successfully saved %u devices to %s\n", 5052 psc.psc_nsaved, argv[0]); 5053 return (psc.psc_ret); 5054 } 5055 } 5056