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 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v1_dev[] = { 1753 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1754 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1755 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1756 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1757 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1758 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1759 { -1, -1, NULL } 1760 }; 1761 1762 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v1_link[] = { 1763 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1764 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1765 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1766 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1767 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1768 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1769 { PCIE_LINKCAP, 4, "linkcap", "Link Capabilities", 1770 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap }, 1771 { PCIE_LINKCTL, 2, "linkctl", "Link Control", 1772 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl }, 1773 { PCIE_LINKSTS, 2, "linksts", "Link Status", 1774 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts }, 1775 { -1, -1, NULL } 1776 }; 1777 1778 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v1_slot[] = { 1779 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1780 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1781 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1782 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1783 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1784 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1785 { PCIE_LINKCAP, 4, "linkcap", "Link Capabilities", 1786 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap }, 1787 { PCIE_LINKCTL, 2, "linkctl", "Link Control", 1788 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl }, 1789 { PCIE_LINKSTS, 2, "linksts", "Link Status", 1790 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts }, 1791 { PCIE_SLOTCAP, 4, "slotcap", "Slot Capabilities", 1792 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap }, 1793 { PCIE_SLOTCTL, 2, "slotctl", "Slot Control", 1794 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl }, 1795 { PCIE_SLOTSTS, 2, "slotsts", "Slot Status", 1796 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts }, 1797 { -1, -1, NULL } 1798 }; 1799 1800 1801 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v1_all[] = { 1802 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1803 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1804 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1805 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1806 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1807 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1808 { PCIE_LINKCAP, 4, "linkcap", "Link Capabilities", 1809 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap }, 1810 { PCIE_LINKCTL, 2, "linkctl", "Link Control", 1811 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl }, 1812 { PCIE_LINKSTS, 2, "linksts", "Link Status", 1813 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts }, 1814 { PCIE_SLOTCAP, 4, "slotcap", "Slot Capabilities", 1815 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap }, 1816 { PCIE_SLOTCTL, 2, "slotctl", "Slot Control", 1817 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl }, 1818 { PCIE_SLOTSTS, 2, "slotsts", "Slot Status", 1819 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts }, 1820 { PCIE_ROOTCTL, 2, "rootctl", "Root control", 1821 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootctl }, 1822 { PCIE_ROOTCAP, 2, "rootcap", "Root Capabilities", 1823 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootcap }, 1824 { PCIE_ROOTSTS, 4, "rootsts", "Root Status", 1825 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootsts }, 1826 { -1, -1, NULL } 1827 }; 1828 1829 static pcieadm_cfgspace_print_t pcieadm_cap_pcie_v2[] = { 1830 { PCIE_PCIECAP, 2, "cap", "Capability Register", 1831 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_cap }, 1832 { PCIE_DEVCAP, 4, "devcap", "Device Capabilities", 1833 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap }, 1834 { PCIE_DEVCTL, 2, "devctl", "Device Control", 1835 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devctl }, 1836 { PCIE_DEVSTS, 2, "devsts", "Device Status", 1837 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts }, 1838 { PCIE_LINKCAP, 4, "linkcap", "Link Capabilities", 1839 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap }, 1840 { PCIE_LINKCTL, 2, "linkctl", "Link Control", 1841 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl }, 1842 { PCIE_LINKSTS, 2, "linksts", "Link Status", 1843 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts }, 1844 { PCIE_SLOTCAP, 4, "slotcap", "Slot Capabilities", 1845 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap }, 1846 { PCIE_SLOTCTL, 2, "slotctl", "Slot Control", 1847 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl }, 1848 { PCIE_SLOTSTS, 2, "slotsts", "Slot Status", 1849 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts }, 1850 { PCIE_ROOTCTL, 2, "rootctl", "Root Control", 1851 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootctl }, 1852 { PCIE_ROOTCAP, 2, "rootcap", "Root Capabilities", 1853 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootcap }, 1854 { PCIE_ROOTSTS, 4, "rootsts", "Root Status", 1855 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_rootsts }, 1856 { PCIE_DEVCAP2, 4, "devcap2", "Device Capabilities 2", 1857 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devcap2 }, 1858 { PCIE_DEVCTL2, 2, "devctl2", "Device Control 2", 1859 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devctl2 }, 1860 { PCIE_DEVSTS2, 2, "devsts2", "Device Status 2", 1861 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_devsts2 }, 1862 { PCIE_LINKCAP2, 4, "linkcap2", "Link Capabilities 2", 1863 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkcap2 }, 1864 { PCIE_LINKCTL2, 2, "linkctl2", "Link Control 2", 1865 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linkctl2 }, 1866 { PCIE_LINKSTS2, 2, "linksts2", "Link Status 2", 1867 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_linksts2 }, 1868 { PCIE_SLOTCAP2, 4, "slotcap2", "Slot Capabilities 2", 1869 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotcap2 }, 1870 { PCIE_SLOTCTL2, 2, "slotctl2", "Slot Control 2", 1871 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotctl2 }, 1872 { PCIE_SLOTSTS2, 2, "slotsts2", "Slot Status 2", 1873 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_slotsts2 }, 1874 { -1, -1, NULL } 1875 }; 1876 1877 /* 1878 * PCIe Extended Capability Header 1879 */ 1880 static pcieadm_regdef_t pcieadm_regdef_pcie_caphdr[] = { 1881 { 0, 15, "capid", "Capability ID", PRDV_HEX }, 1882 { 16, 19, "version", "Capability Version", PRDV_HEX }, 1883 { 20, 32, "offset", "Next Capability Offset", PRDV_HEX }, 1884 { -1, -1, NULL } 1885 }; 1886 1887 /* 1888 * VPD Capability 1889 */ 1890 static pcieadm_regdef_t pcieadm_regdef_vpd_addr[] = { 1891 { 0, 14, "addr", "VPD Address", PRDV_HEX }, 1892 { 15, 15, "flag", "Flag", PRDV_HEX }, 1893 { -1, -1, NULL } 1894 }; 1895 1896 static pcieadm_cfgspace_print_t pcieadm_cap_vpd[] = { 1897 { 0x2, 2, "addr", "VPD Address Register", 1898 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vpd_addr }, 1899 { 0x4, 4, "data", "VPD Data", pcieadm_cfgspace_print_hex }, 1900 { -1, -1, NULL } 1901 }; 1902 1903 /* 1904 * SATA Capability per AHCI 1.3.1 1905 */ 1906 static pcieadm_regdef_t pcieadm_regdef_sata_cr0[] = { 1907 { 0, 3, "minrev", "Minor Revision", PRDV_HEX }, 1908 { 4, 7, "majrev", "Major Revision", PRDV_HEX }, 1909 { -1, -1, NULL } 1910 }; 1911 1912 static pcieadm_regdef_t pcieadm_regdef_sata_cr1[] = { 1913 { 0, 3, "bar", "BAR Location", PRDV_HEX, 1914 .prd_val = { .prdv_hex = { 2 } } }, 1915 { 4, 23, "offset", "BAR Offset", PRDV_HEX, 1916 .prd_val = { .prdv_hex = { 2 } } }, 1917 { -1, -1, NULL } 1918 }; 1919 1920 static pcieadm_cfgspace_print_t pcieadm_cap_sata[] = { 1921 { 0x2, 2, "satacr0", "SATA Capability Register 0", 1922 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sata_cr0 }, 1923 { 0x4, 4, "satacr1", "SATA Capability Register 1", 1924 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sata_cr1 }, 1925 { -1, -1, NULL } 1926 }; 1927 1928 /* 1929 * Debug Capability per EHCI 1930 */ 1931 static pcieadm_regdef_t pcieadm_regdef_debug[] = { 1932 { 0, 12, "offset", "BAR Offset", PRDV_HEX }, 1933 { 13, 15, "bar", "BAR Location ", PRDV_STRVAL, 1934 .prd_val = { .prdv_strval = { NULL, "BAR 0", "BAR 1", "BAR 2", 1935 "BAR 3", "BAR 4", "BAR 5" } } }, 1936 { -1, -1, NULL } 1937 }; 1938 1939 static pcieadm_cfgspace_print_t pcieadm_cap_debug[] = { 1940 { 0x2, 2, "port", "Debug Port", 1941 pcieadm_cfgspace_print_regdef, pcieadm_regdef_debug }, 1942 { -1, -1, NULL } 1943 }; 1944 1945 /* 1946 * AER Capability 1947 */ 1948 static pcieadm_regdef_t pcieadm_regdef_aer_ue[] = { 1949 { 4, 4, "dlp", "Data Link Protocol Error", PRDV_HEX }, 1950 { 5, 5, "sde", "Surprise Down Error", PRDV_HEX }, 1951 { 12, 12, "ptlp", "Poisoned TLP Received", PRDV_HEX }, 1952 { 13, 13, "fcp", "Flow Control Protocol Error", PRDV_HEX }, 1953 { 14, 14, "cto", "Completion Timeout", PRDV_HEX }, 1954 { 15, 15, "cab", "Completion Abort", PRDV_HEX }, 1955 { 16, 16, "unco", "Unexpected Completion", PRDV_HEX }, 1956 { 17, 17, "rxov", "Receiver Overflow", PRDV_HEX }, 1957 { 18, 18, "maltlp", "Malformed TLP", PRDV_HEX }, 1958 { 19, 19, "ecrc", "ECRC Error", PRDV_HEX }, 1959 { 20, 20, "usuprx", "Unsupported Request Error", PRDV_HEX }, 1960 { 21, 21, "acs", "ACS Violation", PRDV_HEX }, 1961 { 22, 22, "ueint", "Uncorrectable Internal Error", PRDV_HEX }, 1962 { 23, 23, "mcbtlp", "MC Blocked TLP", PRDV_HEX }, 1963 { 24, 24, "atoomeb", "AtomicOp Egress Blocked", PRDV_HEX }, 1964 { 25, 25, "tlppb", "TLP Prefix Blocked Error", PRDV_HEX }, 1965 { 26, 26, "ptlpeb", "Poisoned TLP Egress Blocked", PRDV_HEX }, 1966 { -1, -1, NULL } 1967 }; 1968 1969 static pcieadm_regdef_t pcieadm_regdef_aer_ce[] = { 1970 { 0, 0, "rxerr", "Receiver Error", PRDV_HEX }, 1971 { 6, 6, "badtlp", "Bad TLP", PRDV_HEX }, 1972 { 7, 7, "baddllp", "Bad DLLP", PRDV_HEX }, 1973 { 8, 8, "replayro", "REPLAY_NUM Rollover", PRDV_HEX }, 1974 { 12, 12, "rtto", "Replay timer Timeout", PRDV_HEX }, 1975 { 13, 13, "advnfe", "Advisory Non-Fatal Error", PRDV_HEX }, 1976 { 14, 14, "ceint", "Correctable Internal Error", PRDV_HEX }, 1977 { 15, 15, "headlov", "Header Log Overflow", PRDV_HEX }, 1978 { -1, -1, NULL } 1979 }; 1980 1981 static pcieadm_regdef_t pcieadm_regdef_aer_ctrl[] = { 1982 { 0, 4, "feptr", "First Error Pointer", PRDV_HEX }, 1983 { 5, 5, "ecgencap", "ECRC Generation Capable", PRDV_STRVAL, 1984 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1985 { 6, 6, "ecgenen", "ECRC Generation Enable", PRDV_STRVAL, 1986 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1987 { 7, 7, "ecchkcap", "ECRC Check Capable", PRDV_STRVAL, 1988 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 1989 { 8, 8, "ecchken", "ECRC Check Enable", PRDV_STRVAL, 1990 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1991 { -1, -1, NULL } 1992 }; 1993 1994 static pcieadm_regdef_t pcieadm_regdef_aer_rootcom[] = { 1995 { 0, 0, "corerr", "Correctable Error Reporting", PRDV_STRVAL, 1996 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1997 { 1, 1, "nferr", "Non-Fatal Error Reporting", PRDV_STRVAL, 1998 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 1999 { 2, 2, "faterr", "Fatal Error Reporting", PRDV_STRVAL, 2000 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2001 { -1, -1, NULL } 2002 }; 2003 2004 static pcieadm_regdef_t pcieadm_regdef_aer_rootsts[] = { 2005 { 0, 0, "errcor", "ERR_COR Received", PRDV_HEX }, 2006 { 1, 1, "merrcor", "Multiple ERR_COR Received", PRDV_HEX }, 2007 { 2, 2, "errfnf", "ERR_FATAL/NONFATAL Received", PRDV_HEX }, 2008 { 3, 3, "merrfnf", "Multiple ERR_FATAL/NONFATAL Received", PRDV_HEX }, 2009 { 4, 4, "fuefat", "First Uncorrectable Fatal", PRDV_HEX }, 2010 { 5, 5, "nferrrx", "Non-Fatal Error Messages Received", PRDV_HEX }, 2011 { 6, 6, "faterrx", "Fatal Error Messages Received", PRDV_HEX }, 2012 { 7, 8, "errcorsc", "ERR_COR Subclass", PRDV_STRVAL, 2013 .prd_val = { .prdv_strval = { "ECS Legacy", "ECS SIG_SFW", 2014 "ECS SIG_OS", "ECS Extended" } } }, 2015 { 27, 31, "inum", "Advanced Error Interrupt Message", PRDV_HEX }, 2016 { -1, -1, NULL } 2017 }; 2018 2019 static pcieadm_regdef_t pcieadm_regdef_aer_esi[] = { 2020 { 0, 15, "errcorr", "ERR_COR Source", PRDV_HEX }, 2021 { 16, 31, "errfnf", "ERR_FATAL/NONFATAL Source", PRDV_HEX }, 2022 { -1, -1, NULL } 2023 }; 2024 2025 static pcieadm_regdef_t pcieadm_regdef_aer_secue[] = { 2026 { 0, 0, "taosc", "Target-Abort on Split Completion", PRDV_HEX }, 2027 { 1, 1, "maosc", "Master-Abort on Split Completion", PRDV_HEX }, 2028 { 2, 2, "rxta", "Received Target-Abort", PRDV_HEX }, 2029 { 3, 3, "rxma", "Received Master-Abort", PRDV_HEX }, 2030 { 5, 5, "unsce", "Unexpected Split Completion Error", PRDV_HEX }, 2031 { 6, 6, "uescmd", "Uncorrectable Split Completion Message Data Error", 2032 PRDV_HEX }, 2033 { 7, 7, "uede", "Uncorrectable Data Error", PRDV_HEX }, 2034 { 8, 8, "ueattre", "Uncorrectable Attribute Error", PRDV_HEX }, 2035 { 9, 9, "ueaddre", "Uncorrectable Address Error", PRDV_HEX }, 2036 { 10, 10, "dtdte", "Delayed Transaction Discard Timer Expired", 2037 PRDV_HEX }, 2038 { 11, 11, "perr", "PERR# Assertion", PRDV_HEX }, 2039 { 12, 12, "serr", "SERR# Assertion", PRDV_HEX }, 2040 { 13, 13, "internal", "Internal Bridge Error", PRDV_HEX }, 2041 { -1, -1, NULL } 2042 }; 2043 2044 static pcieadm_regdef_t pcieadm_regdef_aer_secctl[] = { 2045 { 0, 4, "feptr", "Secondary Uncorrectable First Error Pointer", 2046 PRDV_HEX }, 2047 { -1, -1, NULL } 2048 }; 2049 2050 static pcieadm_cfgspace_print_t pcieadm_cap_aer_v1[] = { 2051 { PCIE_AER_CAP, 4, "caphdr", "Capability Header", 2052 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2053 { PCIE_AER_UCE_STS, 4, "uestatus", "Uncorrectable Error Status", 2054 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2055 { PCIE_AER_UCE_MASK, 4, "uemask", "Uncorrectable Error Mask", 2056 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2057 { PCIE_AER_UCE_SERV, 4, "ueserv", "Uncorrectable Error Severity", 2058 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2059 { PCIE_AER_CE_STS, 4, "cestatus", "Correctable Error Status", 2060 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2061 { PCIE_AER_CE_MASK, 4, "cemask", "Correctable Error Mask", 2062 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2063 { PCIE_AER_CTL, 4, "ctrl", "Advanced Error Capabilities and Control", 2064 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ctrl }, 2065 { PCIE_AER_HDR_LOG + 4, 4, "hl0", "Header Log 0", 2066 pcieadm_cfgspace_print_hex }, 2067 { PCIE_AER_HDR_LOG + 8, 4, "hl1", "Header Log 1", 2068 pcieadm_cfgspace_print_hex }, 2069 { PCIE_AER_HDR_LOG + 12, 4, "hl2", "Header Log 2", 2070 pcieadm_cfgspace_print_hex }, 2071 { PCIE_AER_HDR_LOG + 12, 4, "hl3", "Header Log 3", 2072 pcieadm_cfgspace_print_hex }, 2073 { PCIE_AER_CTL, 4, "rootcmd", "Root Error Command", 2074 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootcom }, 2075 { PCIE_AER_RE_STS, 4, "rootsts", "Root Error Status", 2076 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootsts }, 2077 { PCIE_AER_CE_SRC_ID, 4, "esi", "Error Source Identification", 2078 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_esi }, 2079 { -1, -1, NULL } 2080 }; 2081 2082 static pcieadm_cfgspace_print_t pcieadm_cap_aer_v2[] = { 2083 { PCIE_AER_CAP, 4, "caphdr", "Capability Header", 2084 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2085 { PCIE_AER_UCE_STS, 4, "uestatus", "Uncorrectable Error Status", 2086 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2087 { PCIE_AER_UCE_MASK, 4, "uemask", "Uncorrectable Error Mask", 2088 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2089 { PCIE_AER_UCE_SERV, 4, "ueserv", "Uncorrectable Error Severity", 2090 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2091 { PCIE_AER_CE_STS, 4, "cestatus", "Correctable Error Status", 2092 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2093 { PCIE_AER_CE_MASK, 4, "cemask", "Correctable Error Mask", 2094 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2095 { PCIE_AER_CTL, 4, "ctrl", "Advanced Error Capabilities and Control", 2096 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ctrl }, 2097 { PCIE_AER_HDR_LOG + 4, 4, "hl0", "Header Log 0", 2098 pcieadm_cfgspace_print_hex }, 2099 { PCIE_AER_HDR_LOG + 8, 4, "hl1", "Header Log 1", 2100 pcieadm_cfgspace_print_hex }, 2101 { PCIE_AER_HDR_LOG + 12, 4, "hl2", "Header Log 2", 2102 pcieadm_cfgspace_print_hex }, 2103 { PCIE_AER_HDR_LOG + 12, 4, "hl3", "Header Log 3", 2104 pcieadm_cfgspace_print_hex }, 2105 { PCIE_AER_CTL, 4, "rootcmd", "Root Error Command", 2106 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootcom }, 2107 { PCIE_AER_RE_STS, 4, "rootsts", "Root Error Status", 2108 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootsts }, 2109 { PCIE_AER_TLP_PRE_LOG, 4, "tlplog0", "TLP Prefix Log 0", 2110 pcieadm_cfgspace_print_hex }, 2111 { PCIE_AER_TLP_PRE_LOG + 4, 4, "tlplog1", "TLP Prefix Log 1", 2112 pcieadm_cfgspace_print_hex }, 2113 { PCIE_AER_TLP_PRE_LOG + 8, 4, "tlplog2", "TLP Prefix Log 2", 2114 pcieadm_cfgspace_print_hex }, 2115 { PCIE_AER_TLP_PRE_LOG + 12, 4, "tlplog3", "TLP Prefix Log 3", 2116 pcieadm_cfgspace_print_hex }, 2117 { -1, -1, NULL } 2118 }; 2119 2120 static pcieadm_cfgspace_print_t pcieadm_cap_aer_bridge[] = { 2121 { PCIE_AER_CAP, 4, "caphdr", "Capability Header", 2122 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2123 { PCIE_AER_UCE_STS, 4, "uestatus", "Uncorrectable Error Status", 2124 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2125 { PCIE_AER_UCE_MASK, 4, "uemask", "Uncorrectable Error Mask", 2126 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2127 { PCIE_AER_UCE_SERV, 4, "ueserv", "Uncorrectable Error Severity", 2128 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ue }, 2129 { PCIE_AER_CE_STS, 4, "cestatus", "Correctable Error Status", 2130 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2131 { PCIE_AER_CE_MASK, 4, "cemask", "Correctable Error Mask", 2132 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ce }, 2133 { PCIE_AER_CTL, 4, "ctrl", "Advanced Error Capabilities and Control", 2134 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_ctrl }, 2135 { PCIE_AER_HDR_LOG + 4, 4, "hl0", "Header Log 0", 2136 pcieadm_cfgspace_print_hex }, 2137 { PCIE_AER_HDR_LOG + 8, 4, "hl1", "Header Log 1", 2138 pcieadm_cfgspace_print_hex }, 2139 { PCIE_AER_HDR_LOG + 12, 4, "hl2", "Header Log 2", 2140 pcieadm_cfgspace_print_hex }, 2141 { PCIE_AER_HDR_LOG + 12, 4, "hl3", "Header Log 3", 2142 pcieadm_cfgspace_print_hex }, 2143 { PCIE_AER_CTL, 4, "rootcmd", "Root Error Command", 2144 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootcom }, 2145 { PCIE_AER_RE_STS, 4, "rootsts", "Root Error Status", 2146 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_rootsts }, 2147 { PCIE_AER_CE_SRC_ID, 4, "esi", "Error Source Identification", 2148 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_esi }, 2149 { PCIE_AER_SUCE_STS, 4, "secuests", 2150 "Secondary Uncorrectable Error Status", 2151 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secue }, 2152 { PCIE_AER_SUCE_MASK, 4, "secuests", 2153 "Secondary Uncorrectable Error Mask", 2154 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secue }, 2155 { PCIE_AER_SUCE_SERV, 4, "secuests", 2156 "Secondary Uncorrectable Error Severity", 2157 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secue }, 2158 { PCIE_AER_SCTL, 4, "secctrl", 2159 "Secondary Error Capabilityes and Control", 2160 pcieadm_cfgspace_print_regdef, pcieadm_regdef_aer_secctl }, 2161 { PCIE_AER_SHDR_LOG, 4, "shl0", "Secondary Header Log 0", 2162 pcieadm_cfgspace_print_hex }, 2163 { PCIE_AER_SHDR_LOG + 4, 4, "shl1", "Secondary Header Log 1", 2164 pcieadm_cfgspace_print_hex }, 2165 { PCIE_AER_SHDR_LOG + 8, 4, "shl1", "Secondary Header Log 2", 2166 pcieadm_cfgspace_print_hex }, 2167 { PCIE_AER_SHDR_LOG + 12, 4, "shl1", "Secondary Header Log 3", 2168 pcieadm_cfgspace_print_hex }, 2169 { -1, -1, NULL } 2170 }; 2171 2172 /* 2173 * Secondary PCI Express Extended Capability 2174 */ 2175 static pcieadm_regdef_t pcieadm_regdef_pcie2_linkctl3[] = { 2176 { 0, 0, "peq", "Perform Equalization", PRDV_HEX }, 2177 { 1, 1, "leqrie", "Link Equalization Request Interrupt Enable", 2178 PRDV_STRVAL, 2179 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2180 { 9, 15, "elskpos", "Enable Lower SKP OS Generation Vector", 2181 PRDV_BITFIELD, 2182 .prd_val = { .prdv_strval = { "2.5 GT/s", "5.0 GT/s", "8.0 GT/s", 2183 "16.0 GT/s", "32.0 GT/s" } } }, 2184 { -1, -1, NULL } 2185 }; 2186 2187 static pcieadm_regdef_t pcieadm_regdef_pcie2_linkeq[] = { 2188 { 0, 3, "dstxpre", "Downstream Port 8.0 GT/s Transmitter Preset", 2189 PRDV_HEX }, 2190 { 4, 6, "dstxhint", "Downstream Port 8.0 GT/s Receiver Hint", 2191 PRDV_HEX }, 2192 { 8, 11, "ustxpre", "Upstream Port 8.0 GT/s Transmitter Preset", 2193 PRDV_HEX }, 2194 { 12, 14, "ustxhint", "Upstream Port 8.0 GT/s Receiver Hint", 2195 PRDV_HEX }, 2196 { -1, -1, NULL } 2197 }; 2198 2199 static void 2200 pcieadm_cfgspace_print_laneq(pcieadm_cfgspace_walk_t *walkp, 2201 pcieadm_cfgspace_print_t *print, void *arg) 2202 { 2203 if (walkp->pcw_nlanes == 0) { 2204 warnx("failed to capture lane count, but somehow have " 2205 "secondary PCIe cap"); 2206 return; 2207 } 2208 2209 for (uint_t i = 0; i < walkp->pcw_nlanes; i++) { 2210 char eqshort[32], eqhuman[128]; 2211 pcieadm_cfgspace_print_t p; 2212 2213 (void) snprintf(eqshort, sizeof (eqshort), "lane%u", i); 2214 (void) snprintf(eqhuman, sizeof (eqhuman), "Lane %u EQ Control", 2215 i); 2216 p.pcp_off = print->pcp_off + i * 2; 2217 p.pcp_len = 2; 2218 p.pcp_short = eqshort; 2219 p.pcp_human = eqhuman; 2220 p.pcp_print = pcieadm_cfgspace_print_regdef; 2221 p.pcp_arg = pcieadm_regdef_pcie2_linkeq; 2222 2223 p.pcp_print(walkp, &p, p.pcp_arg); 2224 } 2225 } 2226 2227 static pcieadm_cfgspace_print_t pcieadm_cap_pcie2[] = { 2228 { 0x0, 4, "caphdr", "Capability Header", 2229 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2230 { 0x4, 4, "linkctl3", "Link Control 3", 2231 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie2_linkctl3 }, 2232 { 0x8, 4, "laneerr", "Lane Error Status", pcieadm_cfgspace_print_hex }, 2233 { 0xc, 2, "eqctl", "Lane Equalization Control", 2234 pcieadm_cfgspace_print_laneq }, 2235 { -1, -1, NULL } 2236 }; 2237 2238 /* 2239 * Access Control Services 2240 */ 2241 static pcieadm_regdef_t pcieadm_regdef_acs_cap[] = { 2242 { 0, 0, "srcvd", "ACS Source Validation", PRDV_STRVAL, 2243 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2244 { 1, 1, "tranblk", "ACS Transaction Blocking", PRDV_STRVAL, 2245 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2246 { 2, 2, "p2prr", "ACS P2P Request Redirect", PRDV_STRVAL, 2247 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2248 { 3, 3, "p2pcr", "ACS P2P Completion Redirect", PRDV_STRVAL, 2249 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2250 { 4, 4, "upfwd", "ACS Upstream Forwarding", PRDV_STRVAL, 2251 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2252 { 5, 5, "p2pegctl", "ACS P2P Egress Control", PRDV_STRVAL, 2253 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2254 { 6, 6, "dtp2p", "ACS Direct Translated P2P", PRDV_STRVAL, 2255 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2256 { 7, 7, "enhcap", "ACS Enhanced Capability", PRDV_STRVAL, 2257 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2258 { 8, 15, "ecvsz", "Egress Control Vector Size", PRDV_HEX }, 2259 { -1, -1, NULL } 2260 }; 2261 2262 static pcieadm_regdef_t pcieadm_regdef_acs_ctl[] = { 2263 { 0, 0, "srcvd", "ACS Source Validation", PRDV_STRVAL, 2264 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2265 { 1, 1, "tranblk", "ACS Transaction Blocking", PRDV_STRVAL, 2266 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2267 { 2, 2, "p2prr", "ACS P2P Request Redirect", PRDV_STRVAL, 2268 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2269 { 3, 3, "p2pcr", "ACS P2P Completion Redirect", PRDV_STRVAL, 2270 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2271 { 4, 4, "upfwd", "ACS Upstream Forwarding", PRDV_STRVAL, 2272 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2273 { 5, 5, "p2pegctl", "ACS P2P Egress Control", PRDV_STRVAL, 2274 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2275 { 6, 6, "dtp2p", "ACS Direct Translated P2P", PRDV_STRVAL, 2276 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2277 { 7, 7, "iorb", "ACS I/O Request Blocking", PRDV_STRVAL, 2278 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2279 { 8, 9, "dspmta", "ACS DSP Memory Target Access Control", PRDV_STRVAL, 2280 .prd_val = { .prdv_strval = { "Direct Request access", 2281 "Request blocking", "Request redirect" } } }, 2282 { 10, 11, "uspmta", "ACS USP Memory Target Access Control", PRDV_STRVAL, 2283 .prd_val = { .prdv_strval = { "Direct Request access", 2284 "Request blocking", "Request redirect" } } }, 2285 { -1, -1, NULL } 2286 }; 2287 2288 static pcieadm_cfgspace_print_t pcieadm_cap_acs[] = { 2289 { 0x0, 4, "caphdr", "Capability Header", 2290 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2291 { 0x4, 2, "cap", "ACS Capability", 2292 pcieadm_cfgspace_print_regdef, pcieadm_regdef_acs_cap }, 2293 { 0x6, 2, "ctl", "ACS Control", 2294 pcieadm_cfgspace_print_regdef, pcieadm_regdef_acs_ctl }, 2295 { 0x8, 4, "ecv", "Egress Control Vector", pcieadm_cfgspace_print_ecv }, 2296 { -1, -1, NULL } 2297 }; 2298 2299 /* 2300 * L1 PM Substates 2301 */ 2302 static pcieadm_regdef_t pcieadm_regdef_l1pm_cap[] = { 2303 { 0, 0, "pcil1.2", "PCI-PM L1.2", PRDV_STRVAL, 2304 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2305 { 1, 1, "pcil1.1", "PCI-PM L1.1", PRDV_STRVAL, 2306 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2307 { 2, 2, "aspml1.2", "ASPM L1.2", PRDV_STRVAL, 2308 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2309 { 3, 3, "aspml1.1", "ASPM L1.1", PRDV_STRVAL, 2310 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2311 { 4, 4, "l1pmsub", "L1 PM Substates", PRDV_STRVAL, 2312 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2313 { 5, 5, "linkact", "Link Activation", PRDV_STRVAL, 2314 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2315 { 8, 15, "pcmrt", "Port Common_Mode_Restore_Time", PRDV_HEX }, 2316 { 16, 17, "poscale", "Port T_POWER_ON Scale", PRDV_STRVAL, 2317 .prd_val = { .prdv_strval = { "2 us", "10 us", "100 us" } } }, 2318 { 19, 23, "portpo", "Port T_POWER_ON Value", PRDV_HEX }, 2319 { -1, -1, NULL } 2320 }; 2321 2322 static pcieadm_regdef_t pcieadm_regdef_l1pm_ctl1[] = { 2323 { 0, 0, "pcil1.2", "PCI-PM L1.2", PRDV_STRVAL, 2324 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2325 { 1, 1, "pcil1.1", "PCI-PM L1.1", PRDV_STRVAL, 2326 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2327 { 2, 2, "aspml1.2", "ASPM L1.2", PRDV_STRVAL, 2328 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2329 { 3, 3, "aspml1.1", "ASPM L1.1", PRDV_STRVAL, 2330 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2331 { 4, 4, "laie", "Link Activation Interrupt Enable", PRDV_STRVAL, 2332 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2333 { 5, 5, "lactl", "Link Activation Control", PRDV_STRVAL, 2334 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2335 { 8, 15, "cmrt", "Common_Mode_Restore_Time", PRDV_HEX }, 2336 { 16, 25, "ltrl1.2", "LTR L1.2 Threshold Value", PRDV_HEX }, 2337 { 29, 31, "ltrl1.2s", "LTR L1.2 Threshold Scale", PRDV_STRVAL, 2338 .prd_val = { .prdv_strval = { "1 ns", "32 ns", "1024 ns", 2339 "32,768 ns", "1,048,576 ns", "33,554,432 ns" } } }, 2340 { -1, -1, NULL } 2341 }; 2342 2343 static pcieadm_regdef_t pcieadm_regdef_l1pm_ctl2[] = { 2344 { 0, 1, "poscale", "T_POWER_ON Scale", PRDV_STRVAL, 2345 .prd_val = { .prdv_strval = { "2 us", "10 us", "100 us" } } }, 2346 { 3, 7, "portpo", "T_POWER_ON Value", PRDV_HEX }, 2347 { -1, -1, NULL } 2348 }; 2349 2350 static pcieadm_regdef_t pcieadm_regdef_l1pm_sts[] = { 2351 { 0, 0, "la", "Link Activation", PRDV_HEX }, 2352 { -1, -1, NULL } 2353 }; 2354 2355 2356 static pcieadm_cfgspace_print_t pcieadm_cap_l1pm_v1[] = { 2357 { 0x0, 4, "caphdr", "Capability Header", 2358 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2359 { 0x4, 4, "caps", "L1 PM Substates Capabilities", 2360 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_cap }, 2361 { 0x8, 4, "ctl1", "L1 PM Substates Control 1", 2362 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl1 }, 2363 { 0xc, 4, "ctl1", "L1 PM Substates Control 2", 2364 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl2 }, 2365 { -1, -1, NULL } 2366 }; 2367 2368 static pcieadm_cfgspace_print_t pcieadm_cap_l1pm_v2[] = { 2369 { 0x0, 4, "caphdr", "Capability Header", 2370 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2371 { 0x4, 4, "caps", "L1 PM Substates Capabilities", 2372 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_cap }, 2373 { 0x8, 4, "ctl1", "L1 PM Substates Control 1", 2374 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl1 }, 2375 { 0xc, 4, "ctl1", "L1 PM Substates Control 2", 2376 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_ctl2 }, 2377 { 0x10, 4, "sts", "L1 PM Substates Status", 2378 pcieadm_cfgspace_print_regdef, pcieadm_regdef_l1pm_sts }, 2379 { -1, -1, NULL } 2380 }; 2381 2382 /* 2383 * Latency Tolerance Reporting (LTR) 2384 */ 2385 static pcieadm_regdef_t pcieadm_regdef_ltr[] = { 2386 { 0, 9, "latval", "Latency Value", PRDV_HEX }, 2387 { 10, 12, "latscale", "Latency Scale", PRDV_STRVAL, 2388 .prd_val = { .prdv_strval = { "1 ns", "32 ns", "1024 ns", 2389 "32,768 ns", "1,048,576 ns", "33,554,432 ns" } } }, 2390 { -1, -1, NULL } 2391 }; 2392 2393 static pcieadm_cfgspace_print_t pcieadm_cap_ltr[] = { 2394 { 0x0, 4, "caphdr", "Capability Header", 2395 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2396 { 0x4, 2, "snoop", "Max Snoop Latency", 2397 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ltr }, 2398 { 0x6, 2, "snoop", "Max No-Snoop Latency", 2399 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ltr }, 2400 { -1, -1, NULL } 2401 }; 2402 2403 /* 2404 * Alternative Routing ID 2405 */ 2406 static pcieadm_regdef_t pcieadm_regdef_ari_cap[] = { 2407 { 0, 0, "mfvcfg", "MFVC Function Groups", PRDV_STRVAL, 2408 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2409 { 1, 1, "acsfg", "ACS Function Groups", PRDV_STRVAL, 2410 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2411 { 8, 15, "nfunc", "Next Function Number", PRDV_HEX }, 2412 { -1, -1, NULL } 2413 }; 2414 2415 static pcieadm_regdef_t pcieadm_regdef_ari_ctl[] = { 2416 { 0, 0, "mfvcfg", "MFVC Function Groups", PRDV_STRVAL, 2417 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2418 { 1, 1, "acsfg", "ACS Function Groups", PRDV_STRVAL, 2419 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2420 { 4, 6, "fgrp", "Function Group", PRDV_HEX }, 2421 { -1, -1, NULL } 2422 }; 2423 2424 static pcieadm_cfgspace_print_t pcieadm_cap_ari[] = { 2425 { 0x0, 4, "caphdr", "Capability Header", 2426 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2427 { 0x4, 2, "cap", "ARI Capability", 2428 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ari_cap }, 2429 { 0x6, 2, "ctl", "ARI Control", 2430 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ari_ctl }, 2431 { -1, -1, NULL } 2432 }; 2433 2434 /* 2435 * PASID 2436 */ 2437 static pcieadm_regdef_t pcieadm_regdef_pasid_cap[] = { 2438 { 1, 1, "exec", "Execution Permission", PRDV_STRVAL, 2439 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2440 { 2, 2, "priv", "Privileged Mode", PRDV_STRVAL, 2441 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2442 { 8, 12, "width", "Max PASID Width", PRDV_HEX }, 2443 { -1, -1, NULL } 2444 }; 2445 2446 static pcieadm_regdef_t pcieadm_regdef_pasid_ctl[] = { 2447 { 0, 0, "pasid", "PASID", PRDV_STRVAL, 2448 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2449 { 1, 1, "exec", "Execution Permission", PRDV_STRVAL, 2450 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2451 { 2, 2, "priv", "Privileged Mode", PRDV_STRVAL, 2452 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2453 { -1, -1, NULL } 2454 }; 2455 2456 2457 static pcieadm_cfgspace_print_t pcieadm_cap_pasid[] = { 2458 { 0x0, 4, "caphdr", "Capability Header", 2459 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2460 { 0x4, 2, "cap", "PASID Capability", 2461 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pasid_cap }, 2462 { 0x6, 2, "ctl", "PASID Control", 2463 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pasid_ctl }, 2464 { -1, -1, NULL } 2465 }; 2466 2467 /* 2468 * "Advanced Features" 2469 */ 2470 static pcieadm_regdef_t pcieadm_regdef_af_cap[] = { 2471 { 0, 0, "tp", "Transactions Pending", PRDV_STRVAL, 2472 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2473 { 1, 1, "flr", "Function Level Reset", PRDV_STRVAL, 2474 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2475 { -1, -1, NULL } 2476 }; 2477 2478 static pcieadm_regdef_t pcieadm_regdef_af_ctl[] = { 2479 { 0, 0, "flr", "Function Level Reset", PRDV_HEX }, 2480 { -1, -1, NULL } 2481 }; 2482 2483 static pcieadm_regdef_t pcieadm_regdef_af_sts[] = { 2484 { 0, 0, "tp", "Transactions Pending", PRDV_STRVAL, 2485 .prd_val = { .prdv_strval = { "none pending", "pending" } } }, 2486 { -1, -1, NULL } 2487 }; 2488 2489 static pcieadm_cfgspace_print_t pcieadm_cap_af[] = { 2490 { 0x2, 2, "cap", "AF Capabilities", 2491 pcieadm_cfgspace_print_regdef, pcieadm_regdef_af_cap }, 2492 { 0x4, 1, "ctl", "AF Control", 2493 pcieadm_cfgspace_print_regdef, pcieadm_regdef_af_ctl }, 2494 { 0x5, 1, "sts", "AF Status", 2495 pcieadm_cfgspace_print_regdef, pcieadm_regdef_af_sts }, 2496 { -1, -1, NULL } 2497 }; 2498 2499 /* 2500 * Multicast 2501 */ 2502 static pcieadm_regdef_t pcieadm_regdef_mcast_cap[] = { 2503 { 0, 5, "maxgrp", "Max Group", PRDV_HEX, 2504 .prd_val = { .prdv_hex = { 0, 1 } } }, 2505 { 8, 13, "winsize", "Window Size (raw)", PRDV_HEX }, 2506 { 15, 15, "ecrc", "ECRC Regeneration", PRDV_STRVAL, 2507 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2508 { -1, -1, NULL } 2509 }; 2510 2511 static pcieadm_regdef_t pcieadm_regdef_mcast_ctl[] = { 2512 { 0, 5, "numgrp", "Number of Groups", PRDV_HEX, 2513 .prd_val = { .prdv_hex = { 0, 1 } } }, 2514 { 15, 15, "enable", "Enable", PRDV_STRVAL, 2515 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2516 { -1, -1, NULL } 2517 }; 2518 2519 static pcieadm_regdef_t pcieadm_regdef_mcast_base[] = { 2520 { 0, 5, "index", "Multicast Index Position", PRDV_HEX }, 2521 { 12, 63, "addr", "Base Address", PRDV_HEX, 2522 .prd_val = { .prdv_hex = { 12 } } }, 2523 { -1, -1, NULL } 2524 }; 2525 2526 static pcieadm_regdef_t pcieadm_regdef_mcast_overlay[] = { 2527 { 0, 5, "size", "Overlay Size (raw)", PRDV_HEX }, 2528 { 6, 63, "addr", "Overlay Base Address", PRDV_HEX, 2529 .prd_val = { .prdv_hex = { 6 } } }, 2530 { -1, -1, NULL } 2531 }; 2532 2533 static pcieadm_cfgspace_print_t pcieadm_cap_mcast[] = { 2534 { 0x0, 4, "caphdr", "Capability Header", 2535 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2536 { 0x4, 2, "cap", "Multicast Capability", 2537 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_cap }, 2538 { 0x6, 2, "ctl", "Multicast Control", 2539 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_ctl }, 2540 { 0x8, 8, "base", "Multicast Base Address", 2541 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_base }, 2542 { 0x10, 8, "rx", "Multicast Receive", pcieadm_cfgspace_print_hex }, 2543 { 0x18, 8, "block", "Multicast Block All", pcieadm_cfgspace_print_hex }, 2544 { 0x20, 8, "blockun", "Multicast Block Untranslated", 2545 pcieadm_cfgspace_print_hex }, 2546 { 0x28, 8, "overlay", "Multicast Overlay BAR", 2547 pcieadm_cfgspace_print_regdef, pcieadm_regdef_mcast_overlay }, 2548 { -1, -1, NULL } 2549 }; 2550 2551 /* 2552 * Various vendor extensions 2553 */ 2554 static pcieadm_regdef_t pcieadm_regdef_vsec[] = { 2555 { 0, 15, "id", "ID", PRDV_HEX }, 2556 { 16, 19, "rev", "Revision", PRDV_HEX }, 2557 { 20, 31, "len", "Length", PRDV_HEX }, 2558 { -1, -1, NULL } 2559 }; 2560 2561 static pcieadm_cfgspace_print_t pcieadm_cap_vs[] = { 2562 { 0x2, 2, "length", "Length", pcieadm_cfgspace_print_hex }, 2563 { -1, -1, NULL } 2564 }; 2565 2566 static pcieadm_cfgspace_print_t pcieadm_cap_vsec[] = { 2567 { 0x0, 4, "caphdr", "Capability Header", 2568 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2569 { 0x4, 4, "header", "Vendor-Specific Header", 2570 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vsec }, 2571 { -1, -1, NULL } 2572 }; 2573 2574 /* 2575 * Data Link Feature 2576 */ 2577 static pcieadm_regdef_t pcieadm_regdef_dlf_cap[] = { 2578 { 0, 0, "lsfc", "Local Scaled Flow Control", PRDV_STRVAL, 2579 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2580 { 31, 31, "dlex", "Data Link Exchange", PRDV_STRVAL, 2581 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2582 { -1, -1, NULL } 2583 }; 2584 2585 static pcieadm_regdef_t pcieadm_regdef_dlf_sts[] = { 2586 { 0, 0, "rsfc", "Remote Scaled Flow Control", PRDV_STRVAL, 2587 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2588 { 31, 31, "valid", "Remote Data Link Feature Valid", PRDV_STRVAL, 2589 .prd_val = { .prdv_strval = { "invalid", "valid" } } }, 2590 { -1, -1, NULL } 2591 }; 2592 2593 static pcieadm_cfgspace_print_t pcieadm_cap_dlf[] = { 2594 { 0x0, 4, "caphdr", "Capability Header", 2595 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2596 { 0x4, 4, "cap", "Data Link Feature Capabilities", 2597 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dlf_cap }, 2598 { 0x8, 4, "sts", "Data Link Feature Status", 2599 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dlf_sts }, 2600 { -1, -1, NULL } 2601 }; 2602 2603 /* 2604 * 16.0 GT/s cap 2605 */ 2606 static pcieadm_regdef_t pcieadm_regdef_16g_cap[] = { 2607 { -1, -1, NULL } 2608 }; 2609 2610 static pcieadm_regdef_t pcieadm_regdef_16g_ctl[] = { 2611 { -1, -1, NULL } 2612 }; 2613 2614 static pcieadm_regdef_t pcieadm_regdef_16g_sts[] = { 2615 { 0, 0, "eqcomp", "Equalization 16.0 GT/s Complete", PRDV_STRVAL, 2616 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2617 { 1, 1, "eqp1", "Equalization 16.0 GT/s Phase 1", PRDV_STRVAL, 2618 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2619 { 2, 2, "eqp2", "Equalization 16.0 GT/s Phase 2", PRDV_STRVAL, 2620 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2621 { 3, 3, "eqp3", "Equalization 16.0 GT/s Phase 3", PRDV_STRVAL, 2622 .prd_val = { .prdv_strval = { "incomplete", "complete" } } }, 2623 { 4, 4, "req", "Link Equalization Request 16.0 GT/s", PRDV_HEX }, 2624 { -1, -1, NULL } 2625 }; 2626 2627 static pcieadm_regdef_t pcieadm_regdef_16g_eq[] = { 2628 { 0, 3, "dstxpre", "Downstream Port 16.0 GT/s Transmitter Preset", 2629 PRDV_HEX }, 2630 { 4, 7, "ustxpre", "Upstream Port 16.0 GT/s Transmitter Preset", 2631 PRDV_HEX }, 2632 { -1, -1, NULL } 2633 }; 2634 2635 static void 2636 pcieadm_cfgspace_print_16geq(pcieadm_cfgspace_walk_t *walkp, 2637 pcieadm_cfgspace_print_t *print, void *arg) 2638 { 2639 if (walkp->pcw_nlanes == 0) { 2640 warnx("failed to capture lane count, but somehow have " 2641 "secondary PCIe cap"); 2642 return; 2643 } 2644 2645 for (uint_t i = 0; i < walkp->pcw_nlanes; i++) { 2646 char eqshort[32], eqhuman[128]; 2647 pcieadm_cfgspace_print_t p; 2648 2649 (void) snprintf(eqshort, sizeof (eqshort), "lane%u", i); 2650 (void) snprintf(eqhuman, sizeof (eqhuman), "Lane %u EQ Control", 2651 i); 2652 p.pcp_off = print->pcp_off + i * 1; 2653 p.pcp_len = 1; 2654 p.pcp_short = eqshort; 2655 p.pcp_human = eqhuman; 2656 p.pcp_print = pcieadm_cfgspace_print_regdef; 2657 p.pcp_arg = pcieadm_regdef_16g_eq; 2658 2659 p.pcp_print(walkp, &p, p.pcp_arg); 2660 } 2661 } 2662 2663 static pcieadm_cfgspace_print_t pcieadm_cap_16g[] = { 2664 { 0x0, 4, "caphdr", "Capability Header", 2665 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2666 { 0x4, 4, "cap", "16.0 GT/s Capabilities", 2667 pcieadm_cfgspace_print_regdef, pcieadm_regdef_16g_cap }, 2668 { 0x8, 4, "ctl", "16.0 GT/s Control", 2669 pcieadm_cfgspace_print_regdef, pcieadm_regdef_16g_ctl }, 2670 { 0xc, 4, "sts", "16.0 GT/s Status", 2671 pcieadm_cfgspace_print_regdef, pcieadm_regdef_16g_sts }, 2672 { 0x10, 4, "ldpmis", "16.0 GT/s Local Data Parity Mismatch", 2673 pcieadm_cfgspace_print_hex }, 2674 { 0x14, 4, "frpmis", "16.0 GT/s First Retimer Data Parity Mismatch", 2675 pcieadm_cfgspace_print_hex }, 2676 { 0x18, 4, "srpmis", "16.0 GT/s Second Retimer Data Parity Mismatch", 2677 pcieadm_cfgspace_print_hex }, 2678 { 0x1c, 4, "rsvd", "16.0 GT/s Second Retimer Data Parity Mismatch", 2679 pcieadm_cfgspace_print_hex }, 2680 { 0x20, 1, "eqctl", "16.0 GT/s EQ Control", 2681 pcieadm_cfgspace_print_16geq }, 2682 { -1, -1, NULL } 2683 }; 2684 2685 /* 2686 * Receiver Margining 2687 */ 2688 static pcieadm_regdef_t pcieadm_regdef_margin_cap[] = { 2689 { 0, 0, "sw", "Margining uses Driver Software", PRDV_STRVAL, 2690 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2691 { -1, -1, NULL } 2692 }; 2693 2694 static pcieadm_regdef_t pcieadm_regdef_margin_sts[] = { 2695 { 0, 0, "ready", "Margining Ready", PRDV_STRVAL, 2696 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2697 { 1, 1, "sw", "Margining Software Ready", PRDV_STRVAL, 2698 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2699 { -1, -1, NULL } 2700 }; 2701 2702 static pcieadm_regdef_t pcieadm_regdef_margin_lane[] = { 2703 { 0, 2, "rxno", "Receiver Number", PRDV_HEX }, 2704 { 3, 5, "type", "Margin Type", PRDV_HEX }, 2705 { 6, 6, "model", "Usage Model", PRDV_HEX }, 2706 { 8, 15, "payload", "Margin Payload", PRDV_HEX }, 2707 { -1, -1, NULL } 2708 }; 2709 2710 static void 2711 pcieadm_cfgspace_print_margin(pcieadm_cfgspace_walk_t *walkp, 2712 pcieadm_cfgspace_print_t *print, void *arg) 2713 { 2714 if (walkp->pcw_nlanes == 0) { 2715 warnx("failed to capture lane count, but somehow have " 2716 "lane margining capability"); 2717 return; 2718 } 2719 2720 for (uint_t i = 0; i < walkp->pcw_nlanes; i++) { 2721 char mshort[32], mhuman[128]; 2722 pcieadm_cfgspace_print_t p; 2723 2724 (void) snprintf(mshort, sizeof (mshort), "lane%uctl", i); 2725 (void) snprintf(mhuman, sizeof (mhuman), "Lane %u Margining " 2726 "Control", i); 2727 p.pcp_off = print->pcp_off + i * 4; 2728 p.pcp_len = 2; 2729 p.pcp_short = mshort; 2730 p.pcp_human = mhuman; 2731 p.pcp_print = pcieadm_cfgspace_print_regdef; 2732 p.pcp_arg = pcieadm_regdef_margin_lane; 2733 2734 p.pcp_print(walkp, &p, p.pcp_arg); 2735 2736 (void) snprintf(mshort, sizeof (mshort), "lane%usts", i); 2737 (void) snprintf(mhuman, sizeof (mhuman), "Lane %u Margining " 2738 "Status", i); 2739 p.pcp_off = print->pcp_off + 2 + i * 4; 2740 p.pcp_len = 2; 2741 p.pcp_short = mshort; 2742 p.pcp_human = mhuman; 2743 p.pcp_print = pcieadm_cfgspace_print_regdef; 2744 p.pcp_arg = pcieadm_regdef_margin_lane; 2745 2746 p.pcp_print(walkp, &p, p.pcp_arg); 2747 } 2748 } 2749 2750 static pcieadm_cfgspace_print_t pcieadm_cap_margin[] = { 2751 { 0x0, 4, "caphdr", "Capability Header", 2752 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2753 { 0x4, 2, "cap", "Margining Port Capabilities", 2754 pcieadm_cfgspace_print_regdef, pcieadm_regdef_margin_cap }, 2755 { 0x6, 2, "sts", "Margining Port Status", 2756 pcieadm_cfgspace_print_regdef, pcieadm_regdef_margin_sts }, 2757 { 0x8, 4, "lane", "Margining Lane", pcieadm_cfgspace_print_margin }, 2758 { -1, -1, NULL } 2759 }; 2760 2761 /* 2762 * Serial Number Capability 2763 */ 2764 static void 2765 pcieadm_cfgspace_print_sn(pcieadm_cfgspace_walk_t *walkp, 2766 pcieadm_cfgspace_print_t *print, void *arg) 2767 { 2768 char sn[64]; 2769 uint16_t off = walkp->pcw_capoff + print->pcp_off; 2770 2771 (void) snprintf(sn, sizeof (sn), 2772 "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", 2773 walkp->pcw_data->pcb_u8[off + 7], walkp->pcw_data->pcb_u8[off + 6], 2774 walkp->pcw_data->pcb_u8[off + 5], walkp->pcw_data->pcb_u8[off + 4], 2775 walkp->pcw_data->pcb_u8[off + 3], walkp->pcw_data->pcb_u8[off + 2], 2776 walkp->pcw_data->pcb_u8[off + 1], walkp->pcw_data->pcb_u8[off]); 2777 2778 pcieadm_cfgspace_puts(walkp, print, sn); 2779 } 2780 2781 static pcieadm_cfgspace_print_t pcieadm_cap_sn[] = { 2782 { 0x0, 4, "caphdr", "Capability Header", 2783 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2784 { 0x4, 8, "sn", "Serial Number", pcieadm_cfgspace_print_sn }, 2785 { -1, -1, NULL } 2786 }; 2787 2788 /* 2789 * TLP Processing Hints (TPH) 2790 */ 2791 static pcieadm_regdef_t pcieadm_regdef_tph_cap[] = { 2792 { 0, 0, "nost", "No ST Mode", PRDV_STRVAL, 2793 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2794 { 1, 1, "ivec", "Interrupt Vector Mode", PRDV_STRVAL, 2795 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2796 { 2, 2, "dev", "Device Specific Mode", PRDV_STRVAL, 2797 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2798 { 8, 8, "exttph", "Extended TPH Requester", PRDV_STRVAL, 2799 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2800 { 9, 10, "loc", "ST Table Location", PRDV_STRVAL, 2801 .prd_val = { .prdv_strval = { "Not Present", 2802 "In Capability Structure", "MSI-X" } } }, 2803 { 16, 26, "size", "ST Table Size", PRDV_HEX, { .prdv_hex = { 0, 1 } } }, 2804 { -1, -1, NULL } 2805 }; 2806 2807 static pcieadm_regdef_t pcieadm_regdef_tph_ctl[] = { 2808 { 0, 2, "mode", "ST Mode Select", PRDV_STRVAL, 2809 .prd_val = { .prdv_strval = { "No ST", "Interrupt Vector", 2810 "Device Specific" } } }, 2811 { 8, 9, "en", "TPH Requester", PRDV_STRVAL, 2812 .prd_val = { .prdv_strval = { "Not Permitted", "TPH", NULL, 2813 "TPH and Extended TPH" } } }, 2814 { -1, -1, NULL } 2815 }; 2816 2817 static pcieadm_regdef_t pcieadm_regdef_tph_st[] = { 2818 { 0, 7, "low", "ST Lower", PRDV_HEX }, 2819 { 8, 15, "up", "ST Upper", PRDV_HEX }, 2820 { -1, -1, NULL } 2821 }; 2822 2823 /* 2824 * The TPH ST table is only conditionally present in the capability. So we need 2825 * to read the TPH capability register and then check if the table location and 2826 * size are set here. 2827 */ 2828 static void 2829 pcieadm_cfgspace_print_tphst(pcieadm_cfgspace_walk_t *walkp, 2830 pcieadm_cfgspace_print_t *print, void *arg) 2831 { 2832 uint_t nents; 2833 uint32_t tphcap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 2834 2835 if (BITX(tphcap, 10, 9) != 1) { 2836 return; 2837 } 2838 2839 nents = BITX(tphcap, 26, 16) + 1; 2840 for (uint_t i = 0; i < nents; i++) { 2841 char tshort[32], thuman[128]; 2842 pcieadm_cfgspace_print_t p; 2843 2844 (void) snprintf(tshort, sizeof (tshort), "st%u", i); 2845 (void) snprintf(thuman, sizeof (thuman), "ST Table %u", 2846 i); 2847 p.pcp_off = print->pcp_off + i * 2; 2848 p.pcp_len = 2; 2849 p.pcp_short = tshort; 2850 p.pcp_human = thuman; 2851 p.pcp_print = pcieadm_cfgspace_print_regdef; 2852 p.pcp_arg = pcieadm_regdef_tph_st; 2853 2854 p.pcp_print(walkp, &p, p.pcp_arg); 2855 } 2856 } 2857 2858 static pcieadm_cfgspace_print_t pcieadm_cap_tph[] = { 2859 { 0x0, 4, "caphdr", "Capability Header", 2860 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2861 { 0x4, 4, "cap", "TPH Requester Capability", 2862 pcieadm_cfgspace_print_regdef, pcieadm_regdef_tph_cap }, 2863 { 0x8, 4, "ctl", "TPH Requester Control", 2864 pcieadm_cfgspace_print_regdef, pcieadm_regdef_tph_ctl }, 2865 { 0xc, 2, "table", "ST Table", pcieadm_cfgspace_print_tphst }, 2866 { -1, -1, NULL } 2867 }; 2868 2869 /* 2870 * SR-IOV 2871 */ 2872 static pcieadm_regdef_t pcieadm_regdef_sriov_cap[] = { 2873 { 0, 0, "migration", "Migration", PRDV_STRVAL, 2874 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 2875 { 1, 1, "ari", "ARI Capable Hierarchy Preserved", PRDV_STRVAL, 2876 .prd_val = { .prdv_strval = { "unpreserved", "preserved" } } }, 2877 { 2, 2, "vf10b", "VF 10-bit Tag Requester", PRDV_STRVAL, 2878 .prd_val = { .prdv_strval = { "unpreserved", "preserved" } } }, 2879 { 21, 31, "inum", "VF Migration Interrupt Message Number", PRDV_HEX }, 2880 { -1, -1, NULL } 2881 }; 2882 2883 static pcieadm_regdef_t pcieadm_regdef_sriov_ctl[] = { 2884 { 0, 0, "vf", "VF", PRDV_STRVAL, 2885 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2886 { 1, 1, "vfm", "VF Migration", PRDV_STRVAL, 2887 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2888 { 2, 2, "vfmi", "VF Migration Interrupt", PRDV_STRVAL, 2889 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2890 { 3, 3, "ari", "ARI Capable Hierarchy", PRDV_STRVAL, 2891 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2892 { 4, 4, "vf10b", "VF 10-bit Tag Requester", PRDV_STRVAL, 2893 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2894 { -1, -1, NULL } 2895 }; 2896 2897 static pcieadm_regdef_t pcieadm_regdef_sriov_sts[] = { 2898 { 0, 0, "vfm", "VF Migration", PRDV_STRVAL, 2899 .prd_val = { .prdv_strval = { "none", "requested" } } }, 2900 { -1, -1, NULL } 2901 }; 2902 2903 static pcieadm_regdef_t pcieadm_regdef_sriov_pgsup[] = { 2904 { 0, 31, "pgsz", "Supported Page Sizes", PRDV_BITFIELD, 2905 .prd_val = { .prdv_strval = { "4 KB", "8 KB", "16 KB", "32 KB", 2906 "64 KB", "128 KB", "256 KB", "512 KB", "1 MB", "2 MB", "4 MB", 2907 "8 MB", "16 MB", "32 MB", "64 MB", "128 MB", "256 MB", "512 MB", 2908 "1 GB", "2 GB", "4 GB", "8 GB", "16 GB", "32 GB", "64 GB", 2909 "128 GB", "256 GB", "512 GB", "1 TB", "2 TB", "4 TB", "8 TB" } } }, 2910 { -1, -1, NULL } 2911 }; 2912 2913 static pcieadm_regdef_t pcieadm_regdef_sriov_pgen[] = { 2914 { 0, 31, "pgsz", "System Page Sizes", PRDV_BITFIELD, 2915 .prd_val = { .prdv_strval = { "4 KB", "8 KB", "16 KB", "32 KB", 2916 "64 KB", "128 KB", "256 KB", "512 KB", "1 MB", "2 MB", "4 MB", 2917 "8 MB", "16 MB", "32 MB", "64 MB", "128 MB", "256 MB", "512 MB", 2918 "1 GB", "2 GB", "4 GB", "8 GB", "16 GB", "32 GB", "64 GB", 2919 "128 GB", "256 GB", "512 GB", "1 TB", "2 TB", "4 TB", "8 TB" } } }, 2920 { -1, -1, NULL } 2921 }; 2922 2923 static pcieadm_regdef_t pcieadm_regdef_sriov_mig[] = { 2924 { 0, 2, "bir", "VF Migration State BIR", PRDV_STRVAL, 2925 .prd_val = { .prdv_strval = { "BAR 0", "BAR 1", "BAR 2", "BAR 3", 2926 "BAR 4", "BAR 5" } } }, 2927 { 3, 31, "offset", "VF Migration State Offset", PRDV_HEX, 2928 .prd_val = { .prdv_hex = { 3 } } }, 2929 { -1, -1, NULL } 2930 }; 2931 2932 static pcieadm_cfgspace_print_t pcieadm_cap_sriov[] = { 2933 { 0x0, 4, "caphdr", "Capability Header", 2934 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 2935 { 0x4, 4, "cap", "SR-IOV Capabilities", 2936 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_cap }, 2937 { 0x8, 2, "ctl", "SR-IOV Control", 2938 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_ctl }, 2939 { 0xa, 2, "sts", "SR-IOV Status", 2940 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_sts }, 2941 { 0xc, 2, "initvfs", "Initial VFs", pcieadm_cfgspace_print_hex }, 2942 { 0xe, 2, "totvfs", "Total VFs", pcieadm_cfgspace_print_hex }, 2943 { 0x10, 2, "numvfs", "Number VFs", pcieadm_cfgspace_print_hex }, 2944 { 0x12, 1, "dep", "Function Dependency Link", 2945 pcieadm_cfgspace_print_hex }, 2946 { 0x14, 2, "offset", "First VF Offset", pcieadm_cfgspace_print_hex }, 2947 { 0x16, 2, "stride", "VF Stride", pcieadm_cfgspace_print_hex }, 2948 { 0x1a, 2, "devid", "VF Device ID", pcieadm_cfgspace_print_hex }, 2949 { 0x1c, 4, "pgsz", "Supported Page Sizes", 2950 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_pgsup }, 2951 { 0x20, 4, "pgsz", "System Page Sizes", 2952 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_pgen }, 2953 { 0x24, 24, "vfbar", "Virtual Base Address Register", 2954 pcieadm_cfgspace_print_bars }, 2955 { 0x3c, 4, "migration", "VF Migration State Array", 2956 pcieadm_cfgspace_print_regdef, pcieadm_regdef_sriov_mig }, 2957 { -1, -1, NULL } 2958 }; 2959 2960 /* 2961 * PCI-X 2962 */ 2963 static pcieadm_regdef_t pcieadm_regdef_pcix_dev_ctl[] = { 2964 { 0, 0, "dper", "Data Parity Error Recovery", PRDV_STRVAL, 2965 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2966 { 1, 1, "ro", "Relaxed Ordering", PRDV_STRVAL, 2967 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 2968 { 2, 3, "maxread", "Maximum Memory Read Byte Count", PRDV_STRVAL, 2969 .prd_val = { .prdv_strval = { "512 bytes", "1024 bytes", 2970 "2048 byes", "4096 bytes" } } }, 2971 { 4, 6, "maxsplit", "Maximum Outstanding Split Transactions", 2972 PRDV_STRVAL, .prd_val = { .prdv_strval = { "1", "2", "3", "4", "8", 2973 "12", "16", "32" } } }, 2974 { -1, -1, NULL } 2975 }; 2976 2977 static pcieadm_regdef_t pcieadm_regdef_pcix_dev_sts[] = { 2978 { 0, 2, "func", "Function Number", PRDV_HEX }, 2979 { 3, 7, "dev", "Device Number", PRDV_HEX }, 2980 { 8, 15, "bus", "Bus Number", PRDV_HEX }, 2981 { 16, 16, "64bit", "64-bit Device", PRDV_STRVAL, 2982 .prd_val = { .prdv_strval = { "unsupported (32-bit)", 2983 "supported" } } }, 2984 { 17, 17, "133mhz", "133 MHz Capable", PRDV_STRVAL, 2985 .prd_val = { .prdv_strval = { "unsupported (66 MHz)", 2986 "supported" } } }, 2987 { 18, 18, "spcodis", "Split Completion Discarded", PRDV_STRVAL, 2988 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2989 { 19, 19, "unspco", "Unexpected Split Completion", PRDV_STRVAL, 2990 .prd_val = { .prdv_strval = { "no", "yes" } } }, 2991 { 20, 20, "complex", "Device Complexity", PRDV_STRVAL, 2992 .prd_val = { .prdv_strval = { "simple", "bridge" } } }, 2993 { 21, 22, "maxread", "Designed Maximum Memory Read Byte Count", 2994 PRDV_STRVAL, .prd_val = { .prdv_strval = { "512 bytes", 2995 "1024 bytes", "2048 byes", "4096 bytes" } } }, 2996 { 23, 25, "maxsplit", "Designed Maximum Outstanding Split Transactions", 2997 PRDV_STRVAL, .prd_val = { .prdv_strval = { "1", "2", "3", "4", "8", 2998 "12", "16", "32" } } }, 2999 { 26, 28, "maxcread", "Designed Maximum Cumulative Read Size", 3000 PRDV_STRVAL, .prd_val = { .prdv_strval = { "8/1KB", "16/2KB", 3001 "32/4KB", "64/8KB", "128/16KB", "256/32KB", "512/64KB", 3002 "1024/128KB" } } }, 3003 { 29, 29, "rxspcoer", "Received Split Completion Error Message", 3004 PRDV_STRVAL, .prd_val = { .prdv_strval = { "no", "yes" } } }, 3005 { -1, -1, NULL } 3006 }; 3007 3008 static pcieadm_regdef_t pcieadm_regdef_pcix_sec_sts[] = { 3009 { 0, 0, "64bit", "64-bit Device", PRDV_STRVAL, 3010 .prd_val = { .prdv_strval = { "unsupported (32-bit)", 3011 "supported" } } }, 3012 { 1, 1, "133mhz", "133 MHz Capable", PRDV_STRVAL, 3013 .prd_val = { .prdv_strval = { "unsupported (66 MHz)", 3014 "supported" } } }, 3015 { 2, 2, "spcodis", "Split Completion Discarded", PRDV_STRVAL, 3016 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3017 { 3, 3, "unspco", "Unexpected Split Completion", PRDV_STRVAL, 3018 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3019 { 4, 4, "spcoor", "Split Completion Overrun", PRDV_STRVAL, 3020 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3021 { 5, 5, "sprde", "Split Request Delayed", PRDV_STRVAL, 3022 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3023 { 6, 8, "freq", "Secondary Clock Frequency", PRDV_STRVAL, 3024 .prd_val = { .prdv_strval = { "conventional", "66 MHz", "100 Mhz", 3025 "133 MHz" } } }, 3026 { -1, -1, NULL } 3027 }; 3028 3029 static pcieadm_regdef_t pcieadm_regdef_pcix_bridge_sts[] = { 3030 { 0, 2, "func", "Function Number", PRDV_HEX }, 3031 { 3, 7, "dev", "Device Number", PRDV_HEX }, 3032 { 8, 15, "bus", "Bus Number", PRDV_HEX }, 3033 { 16, 16, "64bit", "64-bit Device", PRDV_STRVAL, 3034 .prd_val = { .prdv_strval = { "unsupported (32-bit)", 3035 "supported" } } }, 3036 { 17, 17, "133mhz", "133 MHz Capable", PRDV_STRVAL, 3037 .prd_val = { .prdv_strval = { "unsupported (66 MHz)", 3038 "supported" } } }, 3039 { 18, 18, "spcodis", "Split Completion Discarded", PRDV_STRVAL, 3040 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3041 { 19, 19, "unspco", "Unexpected Split Completion", PRDV_STRVAL, 3042 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3043 { 20, 20, "spcoor", "Split Completion Overrun", PRDV_STRVAL, 3044 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3045 { 21, 21, "sprde", "Split Request Delayed", PRDV_STRVAL, 3046 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3047 { -1, -1, NULL } 3048 }; 3049 3050 static pcieadm_regdef_t pcieadm_regdef_pcix_bridge_split[] = { 3051 { 0, 15, "cap", "Split Transaction Capacity", PRDV_HEX }, 3052 { 16, 31, "limit", "Split Transaction Commitment Limit", PRDV_HEX }, 3053 { -1, -1, NULL } 3054 }; 3055 3056 static pcieadm_cfgspace_print_t pcieadm_cap_pcix_dev[] = { 3057 { 0x2, 2, "ctl", "PCI-X Command", 3058 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_dev_ctl }, 3059 { 0x4, 4, "sts", "PCI-X Status", 3060 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_dev_sts }, 3061 { -1, -1, NULL } 3062 }; 3063 3064 static pcieadm_cfgspace_print_t pcieadm_cap_pcix_bridge[] = { 3065 { 0x2, 2, "secsts", "PCI-X Secondary Status", 3066 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_sec_sts }, 3067 { 0x4, 4, "sts", "PCI-X Bridge Status", 3068 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_bridge_sts }, 3069 { 0x8, 4, "ussplit", "Upstream Split Transaction", 3070 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_bridge_split }, 3071 { 0x8, 4, "dssplit", "Downstream Split Transaction", 3072 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcix_bridge_split }, 3073 { -1, -1, NULL } 3074 }; 3075 3076 /* 3077 * Dynamic Power Allocation 3078 */ 3079 static pcieadm_regdef_t pcieadm_regdef_dpa_cap[] = { 3080 { 0, 4, "substates", "Substate Max", PRDV_HEX, 3081 { .prdv_hex = { 0, 1 } } }, 3082 { 8, 9, "tlu", "Transition Latency Unit", PRDV_STRVAL, 3083 .prd_val = { .prdv_strval = { "1 ms", "10 ms", "100 ms" } } }, 3084 { 12, 13, "pas", "Power Allocation Scale", PRDV_STRVAL, 3085 .prd_val = { .prdv_strval = { "10.0x", "1.0x", "0.1x", 3086 "0.01x" } } }, 3087 { 16, 23, "tlv0", "Transition Latency Value 0", PRDV_HEX }, 3088 { 24, 31, "tlv0", "Transition Latency Value 1", PRDV_HEX }, 3089 { -1, -1, NULL } 3090 }; 3091 3092 static pcieadm_regdef_t pcieadm_regdef_dpa_sts[] = { 3093 { 0, 4, "substate", "Substate Status", PRDV_HEX }, 3094 { 8, 8, "ctlen", "Substate Control Enabled", PRDV_STRVAL, 3095 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3096 { -1, -1, NULL } 3097 }; 3098 3099 static pcieadm_regdef_t pcieadm_regdef_dpa_ctl[] = { 3100 { 0, 4, "substate", "Substate Control", PRDV_HEX }, 3101 { -1, -1, NULL } 3102 }; 3103 3104 static pcieadm_cfgspace_print_t pcieadm_cap_dpa[] = { 3105 { 0x0, 4, "caphdr", "Capability Header", 3106 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3107 { 0x4, 4, "cap", "DPA Capability", 3108 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpa_cap }, 3109 { 0x8, 4, "lat", "DPA Latency Indicator", pcieadm_cfgspace_print_hex }, 3110 { 0xc, 2, "sts", "DPA Status", 3111 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpa_sts }, 3112 { 0xe, 2, "sts", "DPA Control", 3113 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpa_ctl }, 3114 { 0x10, 1, "paa", "DPA Power Allocation Array", 3115 pcieadm_cfgspace_print_dpa_paa }, 3116 { -1, -1, NULL } 3117 }; 3118 3119 /* 3120 * Power Budgeting 3121 */ 3122 static pcieadm_regdef_t pcieadm_regdef_powbudg_data[] = { 3123 { 0, 7, "base", "Base Power", PRDV_HEX }, 3124 { 8, 9, "scale", "Data Scale", PRDV_STRVAL, 3125 .prd_val = { .prdv_strval = { "1.0x", "0.1x", "0.01x", 3126 "0.001x" } } }, 3127 { 10, 12, "pmsub", "PM Substate", PRDV_STRVAL, 3128 .prd_val = { .prdv_strval = { "Default", "Device Specific", 3129 "Device Specific", "Device Specific", "Device Specific", 3130 "Device Specific", "Device Specific", "Device Specific" } } }, 3131 { 13, 14, "pmstate", "PM State", PRDV_STRVAL, 3132 .prd_val = { .prdv_strval = { "D0", "D1", "D2", "D3" } } }, 3133 { 15, 17, "type", "Type", PRDV_STRVAL, 3134 .prd_val = { .prdv_strval = { "PME Aux", "Axiliary", "Idle", 3135 "Sustained", "Sustained - EPRS", "Maximum - EPRS", NULL, 3136 "Maximum" } } }, 3137 { 18, 20, "rail", "Power Rail", PRDV_STRVAL, 3138 .prd_val = { .prdv_strval = { "Power (12V)", "Power (3.3V)", 3139 "Power (1.5V or 1.8V)", NULL, NULL, NULL, NULL, "Thermal" } } }, 3140 { -1, -1, NULL } 3141 }; 3142 3143 static pcieadm_regdef_t pcieadm_regdef_powbudg_cap[] = { 3144 { 0, 0, "sa", "System Allocated", PRDV_STRVAL, 3145 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3146 { -1, -1, NULL } 3147 }; 3148 3149 3150 static pcieadm_cfgspace_print_t pcieadm_cap_powbudg[] = { 3151 { 0x0, 4, "caphdr", "Capability Header", 3152 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3153 { 0x4, 1, "sel", "Data Select", pcieadm_cfgspace_print_hex }, 3154 { 0x8, 4, "data", "Data Regiser", pcieadm_cfgspace_print_regdef, 3155 pcieadm_regdef_powbudg_data }, 3156 { 0xc, 0x1, "cap", "Power Budget Capability", 3157 pcieadm_cfgspace_print_regdef, pcieadm_regdef_powbudg_cap }, 3158 { -1, -1, NULL } 3159 }; 3160 3161 /* 3162 * Precision Time Management 3163 */ 3164 static pcieadm_regdef_t pcieadm_regdef_ptm_cap[] = { 3165 { 0, 0, "req", "PTM Requester", PRDV_STRVAL, 3166 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3167 { 1, 1, "resp", "PTM Responder", PRDV_STRVAL, 3168 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3169 { 2, 2, "root", "PTM Root", PRDV_STRVAL, 3170 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3171 { 3, 3, "eptm", "ePTM", PRDV_STRVAL, 3172 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3173 { 8, 15, "gran", "Local Clock Granularity", PRDV_HEX }, 3174 { -1, -1, NULL } 3175 }; 3176 3177 static pcieadm_regdef_t pcieadm_regdef_ptm_ctl[] = { 3178 { 0, 0, "en", "PTM Enable", PRDV_STRVAL, 3179 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3180 { 1, 1, "root", "Root Select", PRDV_STRVAL, 3181 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3182 { 8, 15, "gran", "Effective Granularity", PRDV_HEX }, 3183 { -1, -1, NULL } 3184 }; 3185 3186 static pcieadm_cfgspace_print_t pcieadm_cap_info_ptm[] = { 3187 { 0x0, 4, "caphdr", "Capability Header", 3188 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3189 { 0x4, 4, "cap", "PTM Capability", 3190 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ptm_cap }, 3191 { 0x8, 4, "cap", "PTM Control", 3192 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ptm_ctl }, 3193 { -1, -1, NULL } 3194 }; 3195 3196 /* 3197 * Address Translation Services (ATS) 3198 */ 3199 static pcieadm_regdef_t pcieadm_regdef_ats_cap[] = { 3200 { 0, 4, "invqd", "Invalidate Queue Depth", PRDV_HEX }, 3201 { 5, 5, "pgalign", "Page Aligned Request", PRDV_STRVAL, 3202 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3203 { 6, 6, "glbinv", "Global Invalidate", PRDV_STRVAL, 3204 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3205 { 7, 7, "relo", "Relaxed Ordering", PRDV_STRVAL, 3206 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3207 { -1, -1, NULL } 3208 }; 3209 3210 static pcieadm_regdef_t pcieadm_regdef_ats_ctl[] = { 3211 { 0, 4, "stu", "Smallest Translation Unit", PRDV_HEX }, 3212 { 15, 15, "en", "Enable", PRDV_STRVAL, 3213 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3214 { -1, -1, NULL } 3215 }; 3216 3217 static pcieadm_cfgspace_print_t pcieadm_cap_ats[] = { 3218 { 0x0, 4, "caphdr", "Capability Header", 3219 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3220 { 0x4, 2, "cap", "ATS Capability", 3221 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ats_cap }, 3222 { 0x6, 2, "cap", "ATS Control", 3223 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ats_ctl }, 3224 { -1, -1, NULL } 3225 }; 3226 3227 /* 3228 * Page Request 3229 */ 3230 static pcieadm_regdef_t pcieadm_regdef_pgreq_ctl[] = { 3231 { 0, 0, "en", "Enable", PRDV_STRVAL, 3232 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3233 { 1, 1, "reset", "Reset", PRDV_HEX }, 3234 { -1, -1, NULL } 3235 }; 3236 3237 static pcieadm_regdef_t pcieadm_regdef_pgreq_sts[] = { 3238 { 0, 0, "rf", "Response Failure", PRDV_STRVAL, 3239 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3240 { 1, 1, "uprgi", "Unexpected Page Request Group Index", PRDV_STRVAL, 3241 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3242 { 8, 8, "stopped", "Stopped", PRDV_STRVAL, 3243 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3244 { 15, 15, "prgrpreq", "PRG Response PASID", PRDV_STRVAL, 3245 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3246 { -1, -1, NULL } 3247 }; 3248 3249 static pcieadm_cfgspace_print_t pcieadm_cap_pgreq[] = { 3250 { 0x0, 4, "caphdr", "Capability Header", 3251 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3252 { 0x4, 2, "ctl", "Page Request Control", 3253 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pgreq_ctl }, 3254 { 0x6, 2, "ctl", "Page Request Status", 3255 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pgreq_sts }, 3256 { 0x8, 4, "cap", "Outstanding Page Request Capacity", 3257 pcieadm_cfgspace_print_hex }, 3258 { 0xc, 4, "alloc", "Outstanding Page Request Allocation", 3259 pcieadm_cfgspace_print_hex }, 3260 { -1, -1, NULL } 3261 }; 3262 3263 /* 3264 * NULL Capability 3265 */ 3266 static pcieadm_cfgspace_print_t pcieadm_cap_null[] = { 3267 { 0x0, 4, "caphdr", "Capability Header", 3268 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3269 { -1, -1, NULL } 3270 }; 3271 3272 /* 3273 * Downstream Port Containment 3274 */ 3275 static pcieadm_regdef_t pcieadm_regdef_dpc_cap[] = { 3276 { 0, 4, "inum", "DPC Interrupt Message Number", PRDV_HEX }, 3277 { 5, 5, "rpext", "Root Port Extensions", PRDV_STRVAL, 3278 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3279 { 6, 6, "ptlpeb", "Poisoned TLP Egress Blocking", PRDV_STRVAL, 3280 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3281 { 7, 7, "swtrig", "Software Triggering", PRDV_STRVAL, 3282 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3283 { 8, 11, "logsz", "RP PIO Log Size", PRDV_HEX }, 3284 { 12, 12, "errcorr", "DL_Active ERR_COR Signaling", PRDV_STRVAL, 3285 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3286 { -1, -1, NULL } 3287 }; 3288 3289 static pcieadm_regdef_t pcieadm_regdef_dpc_ctl[] = { 3290 { 0, 1, "trigger", "DPC Trigger", PRDV_STRVAL, 3291 .prd_val = { .prdv_strval = { "disabled", "enabled, fatal", 3292 "enabled, non-fatal" } } }, 3293 { 2, 2, "comp", "Completion Control", PRDV_STRVAL, 3294 .prd_val = { .prdv_strval = { "Completer Abort", 3295 "Unsupported Request" } } }, 3296 { 3, 3, "intr", "Interrupt", 3297 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3298 { 4, 4, "errcor", "ERR_COR", 3299 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3300 { 5, 5, "ptlpeb", "Poisoned TLP Egress Blocking", PRDV_STRVAL, 3301 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3302 { 6, 6, "swtrig", "Software Trigger", PRDV_HEX }, 3303 { 7, 7, "corerr", "DL_Active ERR_COR", 3304 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3305 { 8, 8, "sigsfw", "SIG_SFW", 3306 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3307 { -1, -1, NULL } 3308 }; 3309 3310 static pcieadm_regdef_t pcieadm_regdef_dpc_sts[] = { 3311 { 0, 0, "trigger", "Trigger Status", PRDV_STRVAL, 3312 .prd_val = { .prdv_strval = { "not triggered", "triggered" } } }, 3313 { 1, 2, "reason", "Trigger Reason", PRDV_STRVAL, 3314 .prd_val = { .prdv_strval = { "unmasked uncorrectable", 3315 "ERR_NONFATAL received", "ERR_FATAL received", 3316 "see extension" } } }, 3317 { 3, 3, "istatus", "Interrupt Status", PRDV_HEX }, 3318 { 4, 4, "rpbusy", "RP Busy", PRDV_STRVAL, 3319 .prd_val = { .prdv_strval = { "no", "yes" } } }, 3320 { 5, 6, "extreason", "Trigger Reason Extension", PRDV_STRVAL, 3321 .prd_val = { .prdv_strval = { "RP PIO", "Software Trigger" } } }, 3322 { 8, 12, "feptr", "RP PIO, First Error Pointer", PRDV_HEX }, 3323 { 13, 13, "sigsfw", "SIG_SFW Status", PRDV_HEX }, 3324 { -1, -1, NULL } 3325 }; 3326 3327 static pcieadm_regdef_t pcieadm_regdef_dpc_rppio_bits[] = { 3328 { 0, 0, "cfgur", "Configuration Request UR Completion", PRDV_HEX }, 3329 { 1, 1, "cfgca", "Configuration Request CA Completion", PRDV_HEX }, 3330 { 2, 2, "cfgcto", "Configuration Request Completion Timeout", 3331 PRDV_HEX }, 3332 { 8, 8, "iour", "I/O UR Completion", PRDV_HEX }, 3333 { 9, 9, "ioca", "I/O CA Completion", PRDV_HEX }, 3334 { 10, 10, "iocto", "I/O Completion Timeout", PRDV_HEX }, 3335 { 8, 8, "memur", "Memory UR Completion", PRDV_HEX }, 3336 { 9, 9, "memca", "Memory CA Completion", PRDV_HEX }, 3337 { 10, 10, "memcto", "Memory Completion Timeout", PRDV_HEX }, 3338 { -1, -1, NULL } 3339 }; 3340 3341 static void 3342 pcieadm_cfgspace_print_dpc_rppio(pcieadm_cfgspace_walk_t *walkp, 3343 pcieadm_cfgspace_print_t *print, void *arg) 3344 { 3345 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3346 3347 if (BITX(cap, 5, 5) == 0) { 3348 return; 3349 } 3350 3351 pcieadm_cfgspace_print_regdef(walkp, print, arg); 3352 } 3353 3354 static void 3355 pcieadm_cfgspace_print_dpc_piohead(pcieadm_cfgspace_walk_t *walkp, 3356 pcieadm_cfgspace_print_t *print, void *arg) 3357 { 3358 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3359 uint32_t nwords = BITX(cap, 11, 8); 3360 3361 if (BITX(cap, 5, 5) == 0 || nwords < 4) { 3362 return; 3363 } 3364 3365 pcieadm_cfgspace_print_hex(walkp, print, NULL); 3366 } 3367 3368 static void 3369 pcieadm_cfgspace_print_dpc_impspec(pcieadm_cfgspace_walk_t *walkp, 3370 pcieadm_cfgspace_print_t *print, void *arg) 3371 { 3372 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3373 uint32_t nwords = BITX(cap, 11, 8); 3374 3375 if (BITX(cap, 5, 5) == 0 || nwords < 5) { 3376 return; 3377 } 3378 3379 pcieadm_cfgspace_print_hex(walkp, print, NULL); 3380 } 3381 3382 static void 3383 pcieadm_cfgspace_print_dpc_tlplog(pcieadm_cfgspace_walk_t *walkp, 3384 pcieadm_cfgspace_print_t *print, void *arg) 3385 { 3386 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3387 int32_t nwords = BITX(cap, 11, 8); 3388 3389 if (nwords == 0 || BITX(cap, 5, 5) == 0) { 3390 return; 3391 } 3392 3393 if (nwords <= 9) { 3394 nwords -= 5; 3395 } else { 3396 nwords -= 4; 3397 } 3398 3399 for (int32_t i = 0; i < nwords; i++) { 3400 char tlpshort[32], tlphuman[128]; 3401 pcieadm_cfgspace_print_t p; 3402 3403 (void) snprintf(tlpshort, sizeof (tlpshort), "%s%u", 3404 print->pcp_short, i); 3405 (void) snprintf(tlphuman, sizeof (tlphuman), "%s %u", 3406 print->pcp_human, i); 3407 p.pcp_off = print->pcp_off + i * 4; 3408 p.pcp_len = 4; 3409 p.pcp_short = tlpshort; 3410 p.pcp_human = tlphuman; 3411 p.pcp_print = pcieadm_cfgspace_print_hex; 3412 p.pcp_arg = NULL; 3413 3414 p.pcp_print(walkp, &p, p.pcp_arg); 3415 } 3416 } 3417 3418 static pcieadm_cfgspace_print_t pcieadm_cap_dpc[] = { 3419 { 0x0, 4, "caphdr", "Capability Header", 3420 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3421 { 0x4, 2, "cap", "DPC Capability", 3422 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpc_cap }, 3423 { 0x6, 2, "ctl", "DPC Control", 3424 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpc_ctl }, 3425 { 0x8, 2, "sts", "DPC Status", 3426 pcieadm_cfgspace_print_regdef, pcieadm_regdef_dpc_sts }, 3427 { 0xa, 2, "srcid", "DPC Error Source ID", 3428 pcieadm_cfgspace_print_hex }, 3429 { 0x10, 4, "rppiosts", "RP PIO Status", 3430 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3431 { 0x14, 4, "rppiomask", "RP PIO Mask ID", 3432 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3433 { 0x14, 4, "rppiosev", "RP PIO Severity", 3434 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3435 { 0x18, 4, "rppiose", "RP PIO SysError", 3436 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3437 { 0x1c, 4, "rppioex", "RP PIO Exception", 3438 pcieadm_cfgspace_print_dpc_rppio, pcieadm_regdef_dpc_rppio_bits }, 3439 { 0x20, 4, "rppiohl0", "RP PIO Header Log 0", 3440 pcieadm_cfgspace_print_dpc_piohead }, 3441 { 0x24, 4, "rppiohl1", "RP PIO Header Log 1", 3442 pcieadm_cfgspace_print_dpc_piohead }, 3443 { 0x28, 4, "rppiohl2", "RP PIO Header Log 2", 3444 pcieadm_cfgspace_print_dpc_piohead }, 3445 { 0x2c, 4, "rppiohl3", "RP PIO Header Log 3", 3446 pcieadm_cfgspace_print_dpc_piohead }, 3447 { 0x30, 4, "impspec", "RP PIO ImpSpec Log", 3448 pcieadm_cfgspace_print_dpc_impspec }, 3449 { 0x34, 16, "tlplog", "RP PIO TLP Prefix Log", 3450 pcieadm_cfgspace_print_dpc_tlplog }, 3451 { -1, -1, NULL } 3452 }; 3453 3454 /* 3455 * Virtual Channel Capability 3456 */ 3457 static pcieadm_regdef_t pcieadm_regdef_vc_cap1[] = { 3458 { 0, 2, "count", "Extended VC Count", PRDV_HEX }, 3459 { 4, 6, "lpcount", "Low Priority Extended VC Count", PRDV_HEX }, 3460 { 8, 9, "refclk", "Reference Clock", PRDV_STRVAL, 3461 .prd_val = { .prdv_strval = { "100ns" } } }, 3462 { 10, 11, "patsz", "Port Arbitration Table Size", PRDV_STRVAL, 3463 .prd_val = { .prdv_strval = { "1 bit", "2 bits", "4 bits", 3464 "8 bits" } } }, 3465 { -1, -1, NULL } 3466 }; 3467 3468 static pcieadm_regdef_t pcieadm_regdef_vc_cap2[] = { 3469 { 0, 7, "arbcap", "VC Arbitration Capability", PRDV_BITFIELD, 3470 .prd_val = { .prdv_strval = { "hardware fixed", 3471 "32 phase weighted round robin", "64 phase weighted round robin", 3472 "128 phase weighted round robin" } } }, 3473 { 24, 31, "offset", "VC Arbitration Table Offset", PRDV_HEX }, 3474 { -1, -1, NULL } 3475 }; 3476 3477 static pcieadm_regdef_t pcieadm_regdef_vc_ctl[] = { 3478 { 0, 0, "loadtbl", "Load VC Arbitration Table", PRDV_HEX }, 3479 { 1, 3, "arbtype", "VC Arbitration Select", PRDV_STRVAL, 3480 .prd_val = { .prdv_strval = { "hardware fixed", 3481 "32 phase weighted round robin", "64 phase weighted round robin", 3482 "128 phase weighted round robin" } } }, 3483 { -1, -1, NULL } 3484 }; 3485 3486 static pcieadm_regdef_t pcieadm_regdef_vc_sts[] = { 3487 { 0, 0, "table", "VC Arbitration Table Status", PRDV_HEX }, 3488 { -1, -1, NULL } 3489 }; 3490 3491 static pcieadm_regdef_t pcieadm_regdef_vc_rsrccap[] = { 3492 { 0, 7, "arbcap", "Port Arbitration Capability", PRDV_BITFIELD, 3493 .prd_val = { .prdv_strval = { "hardware fixed", 3494 "32 phase weighted round robin", "64 phase weighted round robin", 3495 "128 phase weighted round robin", 3496 "128 phase time-based weighted round robin", 3497 "256 phase weighted round robin" } } }, 3498 { 14, 14, "aps", "Advanced Packet Switching", PRDV_STRVAL, 3499 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3500 { 15, 15, "rstx", "Reject Snoop Transactions", PRDV_STRVAL, 3501 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3502 { 16, 22, "nslots", "Maximum Time Slots", PRDV_HEX, 3503 { .prdv_hex = { 0, 1 } } }, 3504 { 24, 31, "offset", "VC Arbitration Table Offset", PRDV_HEX }, 3505 { -1, -1, NULL } 3506 }; 3507 3508 static pcieadm_regdef_t pcieadm_regdef_vc_rsrcctl[] = { 3509 { 0, 7, "tcmap", "TC/VC Map", PRDV_HEX }, 3510 { 16, 16, "loadtbl", "Load VC Arbitration Table", PRDV_HEX }, 3511 { 17, 19, "arbtype", "Port Arbitration Select", PRDV_STRVAL, 3512 .prd_val = { .prdv_strval = { "hardware fixed", 3513 "32 phase weighted round robin", "64 phase weighted round robin", 3514 "128 phase weighted round robin", 3515 "128 phase time-based weighted round robin", 3516 "256 phase weighted round robin" } } }, 3517 { 24, 26, "vcid", "VC ID", PRDV_HEX }, 3518 { 31, 31, "en", "VC Enable", 3519 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3520 { -1, -1, NULL } 3521 }; 3522 3523 static pcieadm_regdef_t pcieadm_regdef_vc_rsrcsts[] = { 3524 { 0, 0, "table", "Port Arbitration Table Status", PRDV_HEX }, 3525 { -1, -1, NULL } 3526 }; 3527 3528 static void 3529 pcieadm_cfgspace_print_vc_rsrc(pcieadm_cfgspace_walk_t *walkp, 3530 pcieadm_cfgspace_print_t *print, void *arg) 3531 { 3532 uint32_t cap = walkp->pcw_data->pcb_u32[(walkp->pcw_capoff + 4) / 4]; 3533 uint32_t nents = BITX(cap, 2, 0) + 1; 3534 3535 for (uint32_t i = 0; i < nents; i++) { 3536 char vcshort[32], vchuman[128]; 3537 pcieadm_cfgspace_print_t p; 3538 3539 (void) snprintf(vcshort, sizeof (vcshort), "rsrccap%u", i); 3540 (void) snprintf(vchuman, sizeof (vchuman), "VC Resource %u " 3541 "Capability", i); 3542 p.pcp_off = print->pcp_off + i * 0x10; 3543 p.pcp_len = 4; 3544 p.pcp_short = vcshort; 3545 p.pcp_human = vchuman; 3546 p.pcp_print = pcieadm_cfgspace_print_regdef; 3547 p.pcp_arg = pcieadm_regdef_vc_rsrccap; 3548 3549 p.pcp_print(walkp, &p, p.pcp_arg); 3550 3551 (void) snprintf(vcshort, sizeof (vcshort), "rsrcctl%u", i); 3552 (void) snprintf(vchuman, sizeof (vchuman), "VC Resource %u " 3553 "Control", i); 3554 p.pcp_off = print->pcp_off + i * 0x10 + 4; 3555 p.pcp_len = 4; 3556 p.pcp_short = vcshort; 3557 p.pcp_human = vchuman; 3558 p.pcp_print = pcieadm_cfgspace_print_regdef; 3559 p.pcp_arg = pcieadm_regdef_vc_rsrcctl; 3560 3561 p.pcp_print(walkp, &p, p.pcp_arg); 3562 3563 (void) snprintf(vcshort, sizeof (vcshort), "rsrcsts%u", i); 3564 (void) snprintf(vchuman, sizeof (vchuman), "VC Resource %u " 3565 "Status", i); 3566 p.pcp_off = print->pcp_off + i * 0x10 + 0xa; 3567 p.pcp_len = 2; 3568 p.pcp_short = vcshort; 3569 p.pcp_human = vchuman; 3570 p.pcp_print = pcieadm_cfgspace_print_regdef; 3571 p.pcp_arg = pcieadm_regdef_vc_rsrcsts; 3572 3573 p.pcp_print(walkp, &p, p.pcp_arg); 3574 } 3575 } 3576 3577 static pcieadm_cfgspace_print_t pcieadm_cap_vc[] = { 3578 { 0x0, 4, "caphdr", "Capability Header", 3579 pcieadm_cfgspace_print_regdef, pcieadm_regdef_pcie_caphdr }, 3580 { 0x4, 4, "cap1", "Port VC Capability 1", 3581 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_cap1 }, 3582 { 0x8, 4, "cap2", "Port VC Capability 2", 3583 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_cap2 }, 3584 { 0xc, 2, "ctl", "Port VC Control", 3585 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_ctl }, 3586 { 0xe, 2, "sts", "Port VC Status", 3587 pcieadm_cfgspace_print_regdef, pcieadm_regdef_vc_sts }, 3588 { 0x10, 12, "vcrec", "VC Resource", pcieadm_cfgspace_print_vc_rsrc }, 3589 { -1, -1, NULL } 3590 }; 3591 3592 /* 3593 * HyperTransport 3594 */ 3595 static pcieadm_cfgspace_print_t pcieadm_cap_ht_intr[] = { 3596 { 0x2, 1, "index", "Interrupt Discovery Index", 3597 pcieadm_cfgspace_print_hex }, 3598 { 0x4, 4, "dataport", "Interrupt Dataport", 3599 pcieadm_cfgspace_print_hex }, 3600 { -1, -1, NULL } 3601 }; 3602 3603 static pcieadm_regdef_t pcieadm_regdef_ht_command_pri[] = { 3604 { 0, 4, "unitid", "Base Unit ID", PRDV_HEX }, 3605 { 5, 9, "count", "Unit Count", PRDV_HEX }, 3606 { 10, 10, "host", "Master Host", PRDV_HEX }, 3607 { 11, 11, "dir", "Default Direction", PRDV_STRVAL, 3608 .prd_val = { .prdv_strval = { "towards host", 3609 "away from host" } } }, 3610 { 12, 12, "drop", "Drop on Uninitialized Link", PRDV_HEX }, 3611 { 13, 15, "cap", "Capability ID", PRDV_HEX }, 3612 { -1, -1, NULL } 3613 }; 3614 3615 static pcieadm_regdef_t pcieadm_regdef_ht_command_sec[] = { 3616 { 0, 0, "reset", "Warm Reset", PRDV_HEX }, 3617 { 1, 1, "de", "Double Ended", PRDV_HEX }, 3618 { 2, 6, "devno", "Device Number", PRDV_HEX }, 3619 { 7, 7, "chain", "Chain Side", PRDV_STRVAL, 3620 .prd_val = { .prdv_strval = { "from host", "from chain" } } }, 3621 { 8, 8, "hide", "Host Hide", PRDV_STRVAL, 3622 .prd_val = { .prdv_strval = { "visible", "hidden" } } }, 3623 { 10, 10, "target", "Act as Target", PRDV_HEX }, 3624 { 11, 11, "eocerr", "Host Inbound End of Chain Error", PRDV_HEX }, 3625 { 12, 12, "drop", "Drop on Uninitialized Link", PRDV_HEX }, 3626 { 13, 15, "cap", "Capability ID", PRDV_HEX }, 3627 { -1, -1, NULL } 3628 }; 3629 3630 static pcieadm_regdef_t pcieadm_regdef_ht_linkctl[] = { 3631 { 0, 0, "srcid", "Source ID", PRDV_STRVAL, 3632 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3633 { 1, 1, "cfl", "CRC Flood", PRDV_STRVAL, 3634 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3635 { 2, 2, "cst", "CRC Start Test", PRDV_HEX }, 3636 { 3, 3, "cfer", "CRC Force Error", PRDV_STRVAL, 3637 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3638 { 4, 4, "linkfail", "Link Failure", PRDV_HEX }, 3639 { 5, 5, "initcmp", "Initialization Complete", PRDV_HEX }, 3640 { 6, 6, "eoc", "End of Chain", PRDV_HEX }, 3641 { 7, 7, "txoff", "Transmitter Off", PRDV_STRVAL, 3642 .prd_val = { .prdv_strval = { "transmitter on", 3643 "transmitter off" } } }, 3644 { 8, 11, "crcerr", "CRC Error", PRDV_HEX }, 3645 { 12, 12, "isoc", "Isochronous Flow Control", PRDV_STRVAL, 3646 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3647 { 13, 13, "ls", "LDTSTOP# Tristate", PRDV_STRVAL, 3648 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3649 { 14, 14, "extctl", "Extended CTL Time", PRDV_HEX }, 3650 { 15, 15, "64b", "64-bit Addressing", PRDV_STRVAL, 3651 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3652 { -1, -1, NULL } 3653 }; 3654 3655 static pcieadm_regdef_t pcieadm_regdef_ht_linkcfg[] = { 3656 { 0, 2, "maxin", "Maximum Link Width In", PRDV_STRVAL, 3657 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3658 "2 bits", "4 bits", NULL, "not connected" } } }, 3659 { 3, 3, "dwfcinsup", "Doubleword Flow Control In", PRDV_STRVAL, 3660 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3661 { 4, 6, "maxout", "Maximum Link Width Out", PRDV_STRVAL, 3662 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3663 "2 bits", "4 bits", NULL, "not connected" } } }, 3664 { 7, 7, "dwfcoutsup", "Doubleword Flow Control Out", PRDV_STRVAL, 3665 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3666 { 8, 10, "linkin", "Link Width In", PRDV_STRVAL, 3667 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3668 "2 bits", "4 bits", NULL, "not connected" } } }, 3669 { 11, 11, "dwfcin", "Doubleword Flow Control In", PRDV_STRVAL, 3670 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3671 { 12, 14, "linkout", "Link Width Out", PRDV_STRVAL, 3672 .prd_val = { .prdv_strval = { "8 bits", "16 bits", NULL, "32 bits", 3673 "2 bits", "4 bits", NULL, "not connected" } } }, 3674 { 15, 15, "dwfcout", "Doubleword Flow Control Out", PRDV_STRVAL, 3675 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3676 { -1, -1, NULL } 3677 }; 3678 3679 static pcieadm_regdef_t pcieadm_regdef_ht_rev[] = { 3680 { 0, 4, "minor", "Minor Revision", PRDV_HEX }, 3681 { 5, 7, "major", "Major Revision", PRDV_HEX }, 3682 { -1, -1, NULL } 3683 }; 3684 3685 static pcieadm_regdef_t pcieadm_regdef_ht_linkfreq[] = { 3686 { 0, 4, "freq", "Link Frequency", PRDV_STRVAL, 3687 .prd_val = { .prdv_strval = { "200 MHz", "300 MHz", "400 MHz", 3688 "500 MHz", "600 MHz", "800 MHz", "1000 MHz", "1200 MHz", "1400 MHz", 3689 "1600 MHz", "1800 MHz", "2000 MHz", "2200 MHz", "2400 MHz", 3690 "2600 MHz", "Vendor Specfic" } } }, 3691 { -1, -1, NULL } 3692 }; 3693 3694 static pcieadm_regdef_t pcieadm_regdef_ht_linkerr[] = { 3695 { 4, 4, "prot", "Protocol Error", PRDV_HEX }, 3696 { 5, 5, "over", "Overflow Error", PRDV_HEX }, 3697 { 6, 6, "eoc", "End of Chain Error", PRDV_HEX }, 3698 { 7, 7, "ctl", "CTL Timeout", PRDV_HEX }, 3699 { -1, -1, NULL } 3700 }; 3701 3702 static pcieadm_regdef_t pcieadm_regdef_ht_linkcap[] = { 3703 { 0, 15, "freq", "Link Frequency", PRDV_BITFIELD, 3704 .prd_val = { .prdv_strval = { "200 MHz", "300 MHz", "400 MHz", 3705 "500 MHz", "600 MHz", "800 MHz", "1000 MHz", "1200 MHz", "1400 MHz", 3706 "1600 MHz", "1800 MHz", "2000 MHz", "2200 MHz", "2400 MHz", 3707 "2600 MHz", "Vendor Specfic" } } }, 3708 { -1, -1, NULL } 3709 }; 3710 3711 static pcieadm_regdef_t pcieadm_regdef_ht_feature[] = { 3712 { 0, 0, "isofc", "Isochronous Flow Control", PRDV_STRVAL, 3713 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3714 { 1, 1, "ls", "LDTSTOP#", PRDV_STRVAL, 3715 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3716 { 2, 2, "crct", "CRC Test Mode", PRDV_STRVAL, 3717 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3718 { 3, 3, "ectl", "Extended CTL Time", PRDV_STRVAL, 3719 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3720 { 4, 4, "64b", "64-bit Addressing", PRDV_STRVAL, 3721 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3722 { 5, 5, "unitid", "UnitID Reorder", PRDV_STRVAL, 3723 .prd_val = { .prdv_strval = { "enabled", "disabled" } } }, 3724 { 6, 6, "srcid", "Source Identification Extension", PRDV_STRVAL, 3725 .prd_val = { .prdv_strval = { "not required", "required" } } }, 3726 { 8, 8, "extreg", "Extended Register Set", PRDV_STRVAL, 3727 .prd_val = { .prdv_strval = { "unsupported", "supported" } } }, 3728 { 9, 9, "uscfg", "Upstream Configuration", PRDV_STRVAL, 3729 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3730 { -1, -1, NULL } 3731 }; 3732 3733 static pcieadm_regdef_t pcieadm_regdef_ht_error[] = { 3734 { 0, 0, "protfl", "Protocol Error Flood", PRDV_STRVAL, 3735 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3736 { 1, 1, "ovfl", "Overflow Error Flood", PRDV_STRVAL, 3737 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3738 { 2, 2, "protf", "Protocol Error Fatal", PRDV_STRVAL, 3739 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3740 { 3, 3, "ovf", "Overflow Error Fatal", PRDV_STRVAL, 3741 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3742 { 4, 4, "eocf", "End of Chain Fatal Error", PRDV_STRVAL, 3743 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3744 { 5, 5, "respf", "Response Error Fatal", PRDV_STRVAL, 3745 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3746 { 6, 6, "crcf", "CRC Error Fatal", PRDV_STRVAL, 3747 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3748 { 7, 7, "sysf", "System Error Fatal", PRDV_STRVAL, 3749 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3750 { 8, 8, "chain", "Chain Fail", PRDV_HEX }, 3751 { 9, 9, "resp", "Response Error", PRDV_HEX }, 3752 { 10, 10, "protnf", "Protocol Error Non-Fatal", PRDV_STRVAL, 3753 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3754 { 11, 11, "ovfnf", "Overflow Error Non-Fatal", PRDV_STRVAL, 3755 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3756 { 12, 12, "eocnf", "End of Chain Error Non-Fatal", PRDV_STRVAL, 3757 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3758 { 13, 13, "respnf", "Response Error Non-Fatal", PRDV_STRVAL, 3759 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3760 { 14, 14, "crcnf", "CRC Error Non-Fatal", PRDV_STRVAL, 3761 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3762 { 15, 15, "sysnf", "System Error Non-Fatal", PRDV_STRVAL, 3763 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3764 { -1, -1, NULL } 3765 }; 3766 3767 static pcieadm_regdef_t pcieadm_regdef_ht_memory[] = { 3768 { 0, 8, "base", "Memory Base Upper 8 Bits", PRDV_HEX, 3769 .prd_val = { .prdv_hex = { 32 } } }, 3770 { 9, 15, "limit", "Memory Limit Upper 8 Bits", PRDV_HEX, 3771 .prd_val = { .prdv_hex = { 32 } } }, 3772 { -1, -1, NULL } 3773 }; 3774 3775 static pcieadm_cfgspace_print_t pcieadm_cap_ht_pri[] = { 3776 { 0x2, 2, "command", "Command", 3777 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_command_pri }, 3778 { 0x4, 2, "linkctl0", "Link Control 0", 3779 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkctl }, 3780 { 0x6, 2, "linkcfg0", "Link Configuration 0", 3781 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcfg }, 3782 { 0x8, 2, "linkctl1", "Link Control 1", 3783 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkctl }, 3784 { 0xa, 2, "linkcfg1", "Link Configuration 1", 3785 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcfg }, 3786 { 0xc, 1, "rev", "Revision", 3787 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_rev }, 3788 { 0xd, 1, "linkfreq0", "Link Frequency 0", 3789 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkfreq }, 3790 { 0xd, 1, "linkerr0", "Link Error 0", 3791 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkerr }, 3792 { 0xe, 2, "linkfcap0", "Link Frequency Cap 0", 3793 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcap }, 3794 { 0x10, 1, "feature", "Feature Capability", 3795 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_feature }, 3796 { 0x11, 1, "linkfreq1", "Link Frequency 1", 3797 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkfreq }, 3798 { 0x11, 1, "linkerr1", "Link Error 1", 3799 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkerr }, 3800 { 0x12, 2, "linkfcap1", "Link Frequency Cap 1", 3801 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcap }, 3802 { 0x14, 2, "scratch", "Enumeration Scratchpad", 3803 pcieadm_cfgspace_print_hex }, 3804 { 0x16, 2, "error", "Error Handling", 3805 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_error }, 3806 { 0x18, 2, "memory", "Memory", 3807 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_memory }, 3808 { 0x1a, 1, "bus", "Bus Number", pcieadm_cfgspace_print_hex }, 3809 { -1, -1, NULL } 3810 }; 3811 3812 static pcieadm_cfgspace_print_t pcieadm_cap_ht_sec[] = { 3813 { 0x2, 2, "command", "Command", 3814 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_command_sec }, 3815 { 0x4, 2, "linkctl", "Link Control", 3816 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkctl }, 3817 { 0x6, 2, "linkcfg", "Link Configuration", 3818 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcfg }, 3819 { 0x8, 1, "rev", "Revision", 3820 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_rev }, 3821 { 0x9, 1, "linkfreq", "Link Frequency 0", 3822 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkfreq }, 3823 { 0x9, 1, "linkerr", "Link Error 0", 3824 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkerr }, 3825 { 0xa, 2, "linkfcap", "Link Frequency Cap 0", 3826 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_linkcap }, 3827 { 0xc, 2, "feature", "Feature Capability", 3828 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_feature }, 3829 { 0x10, 2, "scratch", "Enumeration Scratchpad", 3830 pcieadm_cfgspace_print_hex }, 3831 { 0x12, 2, "error", "Error Handling", 3832 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_error }, 3833 { 0x14, 2, "memory", "Memory", 3834 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_memory }, 3835 { -1, -1, NULL } 3836 }; 3837 3838 static pcieadm_regdef_t pcieadm_regdef_ht_msi[] = { 3839 { 0, 0, "en", "Enable", PRDV_STRVAL, 3840 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3841 { 1, 1, "fixed", "Fixed", PRDV_STRVAL, 3842 .prd_val = { .prdv_strval = { "disabled", "enabled" } } }, 3843 { -1, -1, NULL } 3844 }; 3845 3846 static void 3847 pcieadm_cfgspace_print_ht_msi_addr(pcieadm_cfgspace_walk_t *walkp, 3848 pcieadm_cfgspace_print_t *print, void *arg) 3849 { 3850 uint8_t fixed = walkp->pcw_data->pcb_u8[walkp->pcw_capoff + 2]; 3851 3852 if (BITX(fixed, 1, 1) != 0) 3853 return; 3854 3855 pcieadm_cfgspace_print_hex(walkp, print, arg); 3856 } 3857 3858 static pcieadm_cfgspace_print_t pcieadm_cap_ht_msi[] = { 3859 { 0x2, 2, "command", "Command", 3860 pcieadm_cfgspace_print_regdef, pcieadm_regdef_ht_msi }, 3861 { 0x4, 8, "address", "MSI Address", 3862 pcieadm_cfgspace_print_ht_msi_addr }, 3863 { -1, -1, NULL } 3864 }; 3865 3866 /* 3867 * Capability related tables 3868 */ 3869 typedef struct pcieadm_cap_vers { 3870 uint32_t ppr_vers; 3871 uint32_t ppr_len; 3872 pcieadm_cfgspace_print_t *ppr_print; 3873 } pcieadm_cap_vers_t; 3874 3875 typedef struct pcieadm_subcap { 3876 const char *psub_short; 3877 const char *psub_human; 3878 } pcieadm_subcap_t; 3879 3880 typedef struct pcieadm_pci_cap pcieadm_pci_cap_t; 3881 3882 typedef void (*pcieadm_cap_info_f)(pcieadm_cfgspace_walk_t *, 3883 const pcieadm_pci_cap_t *, uint32_t, const pcieadm_cap_vers_t **, 3884 uint32_t *, const pcieadm_subcap_t **); 3885 3886 struct pcieadm_pci_cap { 3887 uint32_t ppc_id; 3888 const char *ppc_short; 3889 const char *ppc_human; 3890 pcieadm_cap_info_f ppc_info; 3891 pcieadm_cap_vers_t ppc_vers[4]; 3892 }; 3893 3894 /* 3895 * Capability version determinations. 3896 */ 3897 3898 static void 3899 pcieadm_cap_info_fixed(pcieadm_cfgspace_walk_t *walkp, 3900 const pcieadm_pci_cap_t *cap, uint32_t off, 3901 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3902 const pcieadm_subcap_t **subcap) 3903 { 3904 *versp = &cap->ppc_vers[0]; 3905 *lenp = cap->ppc_vers[0].ppr_len; 3906 *subcap = NULL; 3907 } 3908 3909 static void 3910 pcieadm_cap_info_vers(pcieadm_cfgspace_walk_t *walkp, 3911 const pcieadm_pci_cap_t *cap, uint32_t off, 3912 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3913 const pcieadm_subcap_t **subcap) 3914 { 3915 uint8_t vers; 3916 3917 *subcap = NULL; 3918 vers = walkp->pcw_data->pcb_u8[off + 2] & 0xf; 3919 for (uint32_t i = 0; i < ARRAY_SIZE(cap->ppc_vers); i++) { 3920 if (vers == cap->ppc_vers[i].ppr_vers && 3921 cap->ppc_vers[i].ppr_vers != 0) { 3922 *versp = &cap->ppc_vers[i]; 3923 *lenp = cap->ppc_vers[i].ppr_len; 3924 return; 3925 } 3926 } 3927 3928 *versp = NULL; 3929 *lenp = 0; 3930 } 3931 3932 /* 3933 * The PCI Power Management capability uses a 3-bit version ID as opposed to the 3934 * standard 4-bit version. 3935 */ 3936 static void 3937 pcieadm_cap_info_pcipm(pcieadm_cfgspace_walk_t *walkp, 3938 const pcieadm_pci_cap_t *cap, uint32_t off, 3939 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3940 const pcieadm_subcap_t **subcap) 3941 { 3942 uint8_t vers; 3943 3944 *subcap = NULL; 3945 vers = walkp->pcw_data->pcb_u8[off + 2] & 0x7; 3946 for (uint32_t i = 0; i < ARRAY_SIZE(cap->ppc_vers); i++) { 3947 if (vers == cap->ppc_vers[i].ppr_vers) { 3948 *versp = &cap->ppc_vers[i]; 3949 *lenp = cap->ppc_vers[i].ppr_len; 3950 return; 3951 } 3952 } 3953 3954 *versp = NULL; 3955 *lenp = 0; 3956 } 3957 3958 /* 3959 * The PCIe capability underwent a few changes. In version 1 of the capability, 3960 * devices were not required to implement the entire capability. In particular, 3961 * endpoints did not need to implement anything more than the link status 3962 * register. In the v2 capability, this was changed such that all devices had to 3963 * implement the entire capbility, but otherwise hardcode registers to zero. As 3964 * such we get to play guess the length based on the device type. 3965 */ 3966 static pcieadm_cap_vers_t pcieadm_cap_vers_pcie_v1_dev = { 3967 1, 0x0c, pcieadm_cap_pcie_v1_dev 3968 }; 3969 3970 static pcieadm_cap_vers_t pcieadm_cap_vers_pcie_v1_link = { 3971 1, 0x14, pcieadm_cap_pcie_v1_link 3972 }; 3973 3974 static pcieadm_cap_vers_t pcieadm_cap_vers_pcie_v1_slot = { 3975 1, 0x1c, pcieadm_cap_pcie_v1_slot 3976 }; 3977 3978 static pcieadm_cap_vers_t pcieadm_cap_vers_pcie_v1_all = { 3979 1, 0x24, pcieadm_cap_pcie_v1_all 3980 }; 3981 3982 static pcieadm_cap_vers_t pcieadm_cap_vers_pcie_v2 = { 3983 2, 0x4c, pcieadm_cap_pcie_v2 3984 }; 3985 3986 static void 3987 pcieadm_cap_info_pcie(pcieadm_cfgspace_walk_t *walkp, 3988 const pcieadm_pci_cap_t *cap, uint32_t off, 3989 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 3990 const pcieadm_subcap_t **subcap) 3991 { 3992 uint8_t vers = walkp->pcw_data->pcb_u8[off + 2] & 0xf; 3993 uint16_t pcie = walkp->pcw_data->pcb_u8[off + 2] | 3994 (walkp->pcw_data->pcb_u8[off + 3] << 8); 3995 3996 /* 3997 * Version 2 is simple. There's only one thing to do, so we do it. For 3998 * version 1 we need to look at the device type. 3999 */ 4000 *subcap = NULL; 4001 if (vers == 2) { 4002 *versp = &pcieadm_cap_vers_pcie_v2; 4003 *lenp = (*versp)->ppr_len; 4004 return; 4005 } else if (vers != 1) { 4006 *versp = NULL; 4007 *lenp = 0; 4008 return; 4009 } 4010 4011 switch (pcie & PCIE_PCIECAP_DEV_TYPE_MASK) { 4012 case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV: 4013 case PCIE_PCIECAP_DEV_TYPE_PCI_DEV: 4014 *versp = &pcieadm_cap_vers_pcie_v1_link; 4015 break; 4016 case PCIE_PCIECAP_DEV_TYPE_RC_IEP: 4017 *versp = &pcieadm_cap_vers_pcie_v1_dev; 4018 break; 4019 case PCIE_PCIECAP_DEV_TYPE_UP: 4020 case PCIE_PCIECAP_DEV_TYPE_DOWN: 4021 case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI: 4022 case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE: 4023 if ((pcie & PCIE_PCIECAP_SLOT_IMPL) != 0) { 4024 *versp = &pcieadm_cap_vers_pcie_v1_slot; 4025 } else { 4026 *versp = &pcieadm_cap_vers_pcie_v1_link; 4027 } 4028 break; 4029 case PCIE_PCIECAP_DEV_TYPE_ROOT: 4030 case PCIE_PCIECAP_DEV_TYPE_RC_EC: 4031 *versp = &pcieadm_cap_vers_pcie_v1_all; 4032 break; 4033 default: 4034 *versp = NULL; 4035 *lenp = 0; 4036 return; 4037 } 4038 4039 *lenp = (*versp)->ppr_len; 4040 } 4041 4042 /* 4043 * The length of the MSI capability depends on bits in its control field. As 4044 * such we use a custom function to extract the length and treat each of these 4045 * variants as thought it were a different version. 4046 */ 4047 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_32 = { 4048 0, 0xa, pcieadm_cap_msi_32 4049 }; 4050 4051 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_32ext = { 4052 0, 0xc, pcieadm_cap_msi_32ext 4053 }; 4054 4055 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_64 = { 4056 0, 0xe, pcieadm_cap_msi_64 4057 }; 4058 4059 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_64ext = { 4060 0, 0x10, pcieadm_cap_msi_64ext 4061 }; 4062 4063 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_32pvm = { 4064 0, 0x14, pcieadm_cap_msi_32pvm 4065 }; 4066 4067 static pcieadm_cap_vers_t pcieadm_cap_vers_msi_64pvm = { 4068 0, 0x18, pcieadm_cap_msi_64pvm 4069 }; 4070 4071 static void 4072 pcieadm_cap_info_msi(pcieadm_cfgspace_walk_t *walkp, 4073 const pcieadm_pci_cap_t *cap, uint32_t off, 4074 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 4075 const pcieadm_subcap_t **subcap) 4076 { 4077 uint16_t ctrl; 4078 boolean_t addr64, pvm, ext; 4079 4080 *subcap = NULL; 4081 ctrl = walkp->pcw_data->pcb_u8[off + 2] | 4082 (walkp->pcw_data->pcb_u8[off + 3] << 8); 4083 if (ctrl == PCI_EINVAL16) { 4084 warnx("failed to read MSI Message Control register"); 4085 *lenp = 0; 4086 *versp = NULL; 4087 return; 4088 } 4089 4090 /* 4091 * The MSI capability has three main things that control its size. 4092 * 64-bit addressing adds 4 bytes. Per-Vector Masking adds 8 bytes and 4093 * causes the Extended data addressing piece to always be present. 4094 * Therefore we check first for pvm as it implies evt, effectively. 4095 */ 4096 addr64 = (ctrl & PCI_MSI_64BIT_MASK) != 0; 4097 pvm = (ctrl & PCI_MSI_PVM_MASK) != 0; 4098 ext = (ctrl & PCI_MSI_EMD_MASK) != 0; 4099 4100 if (pvm && addr64) { 4101 *versp = &pcieadm_cap_vers_msi_64pvm; 4102 } else if (pvm) { 4103 *versp = &pcieadm_cap_vers_msi_32pvm; 4104 } else if (addr64 && ext) { 4105 *versp = &pcieadm_cap_vers_msi_64ext; 4106 } else if (addr64) { 4107 *versp = &pcieadm_cap_vers_msi_64; 4108 } else if (ext) { 4109 *versp = &pcieadm_cap_vers_msi_32ext; 4110 } else { 4111 *versp = &pcieadm_cap_vers_msi_32; 4112 } 4113 4114 *lenp = (*versp)->ppr_len; 4115 } 4116 4117 /* 4118 * The AER Capability is technically different for PCIe-PCI bridges. If we find 4119 * that device type here, then we need to use a different version information 4120 * rather than the actual set defined with the device (which have changed over 4121 * time). 4122 */ 4123 static const pcieadm_cap_vers_t pcieadm_cap_vers_aer_bridge = { 4124 1, 0x4c, pcieadm_cap_aer_bridge 4125 }; 4126 4127 static void 4128 pcieadm_cap_info_aer(pcieadm_cfgspace_walk_t *walkp, 4129 const pcieadm_pci_cap_t *cap, uint32_t off, 4130 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 4131 const pcieadm_subcap_t **subcap) 4132 { 4133 if (walkp->pcw_pcietype == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) { 4134 uint8_t vers; 4135 4136 *subcap = NULL; 4137 vers = walkp->pcw_data->pcb_u8[off + 2] & 0xf; 4138 if (vers != pcieadm_cap_vers_aer_bridge.ppr_vers) { 4139 warnx("encountered PCIe to PCI bridge with unknown " 4140 "AER capability version: %u", vers); 4141 *lenp = 0; 4142 *versp = NULL; 4143 return; 4144 } 4145 *lenp = pcieadm_cap_vers_aer_bridge.ppr_len; 4146 *versp = &pcieadm_cap_vers_aer_bridge; 4147 } 4148 4149 return (pcieadm_cap_info_vers(walkp, cap, off, versp, lenp, subcap)); 4150 } 4151 4152 /* 4153 * The PCI-X capability varies depending on the header type of the device. 4154 * Therefore we simply use the device type to figure out what to do. 4155 */ 4156 static pcieadm_cap_vers_t pcieadm_cap_vers_pcix_dev = { 4157 0, 0x8, pcieadm_cap_pcix_dev 4158 }; 4159 4160 static pcieadm_cap_vers_t pcieadm_cap_vers_pcix_bridge = { 4161 0, 0x10, pcieadm_cap_pcix_bridge 4162 }; 4163 4164 static void 4165 pcieadm_cap_info_pcix(pcieadm_cfgspace_walk_t *walkp, 4166 const pcieadm_pci_cap_t *cap, uint32_t off, 4167 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 4168 const pcieadm_subcap_t **subcap) 4169 { 4170 4171 *subcap = NULL; 4172 switch (walkp->pcw_dtype) { 4173 case PCI_HEADER_ZERO: 4174 *versp = &pcieadm_cap_vers_pcix_dev; 4175 break; 4176 case PCI_HEADER_ONE: 4177 *versp = &pcieadm_cap_vers_pcix_bridge; 4178 break; 4179 default: 4180 warnx("encountered PCI-X capability with unsupported device " 4181 "type: 0x%x\n", walkp->pcw_dtype); 4182 *lenp = 0; 4183 *versp = NULL; 4184 return; 4185 } 4186 4187 *lenp = (*versp)->ppr_len; 4188 } 4189 4190 typedef struct pcieadm_cap_ht { 4191 uint32_t pch_capid; 4192 pcieadm_subcap_t pch_subcap; 4193 pcieadm_cap_vers_t pch_vers; 4194 } pcieadm_cap_ht_t; 4195 4196 static pcieadm_cap_ht_t pcieadm_ht_cap_pri = { 4197 0x00, { "pri", "Primary" }, { 0, 0x1c, pcieadm_cap_ht_pri } 4198 }; 4199 4200 static pcieadm_cap_ht_t pcieadm_ht_cap_sec = { 4201 0x01, { "sec", "Secondary" }, { 0, 0x18, pcieadm_cap_ht_sec } 4202 }; 4203 4204 static pcieadm_cap_ht_t pcieadm_ht_caps[] = { 4205 { 0x08, { "switch", "Switch" } }, 4206 { 0x10, { "intr", "Interrupt Discovery and Configuration" }, 4207 { 0, 8, pcieadm_cap_ht_intr } }, 4208 { 0x11, { "rev", "Revision ID" } }, 4209 { 0x12, { "unitid", "UnitID Clumping" } }, 4210 { 0x13, { "extcfg", "Extended Configuration Space Access" } }, 4211 { 0x14, { "addrmap", "Address Mapping" } }, 4212 { 0x15, { "msi", "MSI Mapping" }, 4213 { 0, 4, pcieadm_cap_ht_msi } }, 4214 { 0x16, { "dir", "DirectRoute" } }, 4215 { 0x17, { "vcset", "VCSet" } }, 4216 { 0x18, { "retry", "Retry Mode" } }, 4217 { 0x19, { "x86", "X86 Encoding" } }, 4218 { 0x1a, { "gen3", "Gen3" } }, 4219 { 0x1b, { "fle", "Function-Level Extension" } }, 4220 { 0x1c, { "pm", "Power Management" } }, 4221 { UINT32_MAX, NULL }, 4222 }; 4223 4224 static void 4225 pcieadm_cap_info_ht(pcieadm_cfgspace_walk_t *walkp, 4226 const pcieadm_pci_cap_t *cap, uint32_t off, 4227 const pcieadm_cap_vers_t **versp, uint32_t *lenp, 4228 const pcieadm_subcap_t **subcap) 4229 { 4230 uint32_t base = walkp->pcw_data->pcb_u32[off / 4]; 4231 uint32_t caplo = BITX(base, 31, 29); 4232 pcieadm_cap_ht_t *htcap = NULL; 4233 4234 *versp = NULL; 4235 *lenp = 0; 4236 *subcap = NULL; 4237 4238 if (caplo > 1) { 4239 uint32_t capid = BITX(base, 31, 27); 4240 4241 for (uint32_t i = 0; pcieadm_ht_caps[i].pch_capid != UINT32_MAX; 4242 i++) { 4243 if (capid == pcieadm_ht_caps[i].pch_capid) { 4244 htcap = &pcieadm_ht_caps[i]; 4245 break; 4246 } 4247 } 4248 } else if (caplo == 0) { 4249 htcap = &pcieadm_ht_cap_pri; 4250 } else if (caplo == 1) { 4251 htcap = &pcieadm_ht_cap_sec; 4252 } 4253 4254 if (htcap == NULL) { 4255 warnx("encountered unknown HyperTransport Capability 0x%x", 4256 BITX(base, 31, 27)); 4257 return; 4258 } 4259 4260 *subcap = &htcap->pch_subcap; 4261 if (htcap->pch_vers.ppr_print != NULL) { 4262 *versp = &htcap->pch_vers; 4263 *lenp = htcap->pch_vers.ppr_len; 4264 } 4265 } 4266 4267 pcieadm_pci_cap_t pcieadm_pci_caps[] = { 4268 { PCI_CAP_ID_PM, "pcipm", "PCI Power Management", 4269 pcieadm_cap_info_pcipm, { { 2, 8, pcieadm_cap_pcipm_v3 }, 4270 { 3, 8, pcieadm_cap_pcipm_v3 } } }, 4271 { PCI_CAP_ID_AGP, "agp", "Accelerated Graphics Port" }, 4272 { PCI_CAP_ID_VPD, "vpd", "Vital Product Data", pcieadm_cap_info_fixed, 4273 { { 0, 8, pcieadm_cap_vpd } } }, 4274 { PCI_CAP_ID_SLOT_ID, "slot", "Slot Identification" }, 4275 { PCI_CAP_ID_MSI, "msi", "Message Signaled Interrupts", 4276 pcieadm_cap_info_msi }, 4277 { PCI_CAP_ID_cPCI_HS, "cpci", "CompactPCI Hot Swap" }, 4278 { PCI_CAP_ID_PCIX, "pcix", "PCI-X", pcieadm_cap_info_pcix }, 4279 { PCI_CAP_ID_HT, "ht", "HyperTransport", pcieadm_cap_info_ht }, 4280 { PCI_CAP_ID_VS, "vs", "Vendor Specific", pcieadm_cap_info_fixed, 4281 { { 0, 3, pcieadm_cap_vs } } }, 4282 { PCI_CAP_ID_DEBUG_PORT, "dbg", "Debug Port", pcieadm_cap_info_fixed, 4283 { { 0, 4, pcieadm_cap_debug } } }, 4284 { PCI_CAP_ID_cPCI_CRC, "cpcicrc", 4285 "CompactPCI Central Resource Control" }, 4286 { PCI_CAP_ID_PCI_HOTPLUG, "pcihp", "PCI Hot-Plug" }, 4287 { PCI_CAP_ID_P2P_SUBSYS, "bdgsub", "PCI Bridge Subsystem Vendor ID", 4288 pcieadm_cap_info_fixed, { 0, 8, pcieadm_cap_bridge_subsys } }, 4289 { PCI_CAP_ID_AGP_8X, "agp8x", "AGP 8x" }, 4290 { PCI_CAP_ID_SECURE_DEV, "secdev", "Secure Device" }, 4291 { PCI_CAP_ID_PCI_E, "pcie", "PCI Express", pcieadm_cap_info_pcie }, 4292 { PCI_CAP_ID_MSI_X, "msix", "MSI-X", pcieadm_cap_info_fixed, 4293 { { 0, 12, pcieadm_cap_msix } } }, 4294 { PCI_CAP_ID_SATA, "sata", "Serial ATA Configuration", 4295 pcieadm_cap_info_fixed, { { 0, 8, pcieadm_cap_sata } } }, 4296 /* 4297 * Note, the AF feature doesn't have a version but encodes a length in 4298 * the version field, so we cheat and use that. 4299 */ 4300 { PCI_CAP_ID_FLR, "af", "Advanced Features", pcieadm_cap_info_vers, 4301 { { 6, 6, pcieadm_cap_af } } }, 4302 { PCI_CAP_ID_EA, "ea", "Enhanced Allocation" }, 4303 { PCI_CAP_ID_FPB, "fpb", "Flattening Portal Bridge" } 4304 }; 4305 4306 pcieadm_pci_cap_t pcieadm_pcie_caps[] = { 4307 { 0, "null", "NULL Capability", pcieadm_cap_info_fixed, 4308 { { 0, 0x4, pcieadm_cap_null } } }, 4309 { PCIE_EXT_CAP_ID_AER, "aer", "Advanced Error Reporting", 4310 pcieadm_cap_info_aer, { { 1, 0x38, pcieadm_cap_aer_v1 }, 4311 { 2, 0x48, pcieadm_cap_aer_v2 } } }, 4312 { PCIE_EXT_CAP_ID_VC, "vc", "Virtual Channel", pcieadm_cap_info_vers, 4313 { { 0x1, 0x1c, pcieadm_cap_vc } } }, 4314 { PCIE_EXT_CAP_ID_SER, "sn", "Serial Number", pcieadm_cap_info_vers, 4315 { { 1, 0xc, pcieadm_cap_sn } } }, 4316 { PCIE_EXT_CAP_ID_PWR_BUDGET, "powbudg", "Power Budgeting", 4317 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_powbudg } } }, 4318 { PCIE_EXT_CAP_ID_RC_LINK_DECL, "rcld", 4319 "Root Complex Link Declaration" }, 4320 { PCIE_EXT_CAP_ID_RC_INT_LINKCTRL, "rcilc", 4321 "Root Complex Internal Link Control" }, 4322 { PCIE_EXT_CAP_ID_RC_EVNT_CEA, "rcecea", 4323 "Root Complex Event Collector Endpoint Aggregation" }, 4324 { PCIE_EXT_CAP_ID_MFVC, "mfvc", "Multi-Function Virtual Channel" }, 4325 { PCIE_EXT_CAP_ID_VC_WITH_MFVC, "vcwmfvc", "Virtual Channel with MFVC", 4326 pcieadm_cap_info_vers, { { 0x1, 0x1c, pcieadm_cap_vc } } }, 4327 { PCIE_EXT_CAP_ID_RCRB, "rcrb", "Root Complex Register Block" }, 4328 { PCIE_EXT_CAP_ID_VS, "vsec", "Vendor Specific Extended Capability", 4329 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_vsec } } }, 4330 { PCIE_EXT_CAP_ID_CAC, "cac", "Configuration Access Correlation" }, 4331 { PCIE_EXT_CAP_ID_ACS, "acs", "Access Control Services", 4332 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_acs } } }, 4333 { PCIE_EXT_CAP_ID_ARI, "ari", "Alternative Routing-ID Interpretation", 4334 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_ari } } }, 4335 { PCIE_EXT_CAP_ID_ATS, "ats", "Access Translation Services", 4336 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_ats } } }, 4337 { PCIE_EXT_CAP_ID_SRIOV, "sriov", "Single Root I/O Virtualization", 4338 pcieadm_cap_info_vers, { { 1, 0x40, pcieadm_cap_sriov } } }, 4339 { PCIE_EXT_CAP_ID_MRIOV, "mriov", "Multi-Root I/O Virtualization" }, 4340 { PCIE_EXT_CAP_ID_MULTICAST, "mcast", "Multicast", 4341 pcieadm_cap_info_vers, { { 1, 0x30, pcieadm_cap_mcast } } }, 4342 { PCIE_EXT_CAP_ID_PGREQ, "pgreq", "Page Request", 4343 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_pgreq } } }, 4344 { PCIE_EXT_CAP_ID_EA, "ea", "Enhanced Allocation" }, 4345 { PCIE_EXT_CAP_ID_RESIZE_BAR, "rbar", "Resizable Bar" }, 4346 { PCIE_EXT_CAP_ID_DPA, "dpa", "Dynamic Power Allocation", 4347 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_dpa } } }, 4348 { PCIE_EXT_CAP_ID_TPH_REQ, "tph", "TPH Requester", 4349 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_tph } } }, 4350 { PCIE_EXT_CAP_ID_LTR, "ltr", "Latency Tolerance Reporting", 4351 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_ltr } } }, 4352 { PCIE_EXT_CAP_ID_PCIE2, "pcie2", "Secondary PCI Express", 4353 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_pcie2 } } }, 4354 { PCIE_EXT_CAP_ID_PASID, "pasid", "Process Address Space ID", 4355 pcieadm_cap_info_vers, { { 1, 0x8, pcieadm_cap_pasid } } }, 4356 { PCIE_EXT_CAP_ID_LNR, "lnr", "LN Requester" }, 4357 { PCIE_EXT_CAP_ID_DPC, "dpc", "Downstream Port Containment", 4358 pcieadm_cap_info_vers, { { 1, 0x30, pcieadm_cap_dpc } } }, 4359 { PCIE_EXT_CAP_ID_L1PM, "l1pm", "L1 PM Substates", 4360 pcieadm_cap_info_vers, { { 1, 0x10, pcieadm_cap_l1pm_v1 }, 4361 { 2, 0x14, pcieadm_cap_l1pm_v2 } } }, 4362 { PCIE_EXT_CAP_ID_PTM, "ptm", "Precision Time Management", 4363 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_info_ptm } } }, 4364 { PCIE_EXT_CAP_ID_FRS, "frs", "FRS Queueing" }, 4365 { PCIE_EXT_CAP_ID_RTR, "trt", "Readiness Time Reporting" }, 4366 /* 4367 * When we encounter a designated vendor specificaiton, in particular, 4368 * for CXL, we'll want to set ppc_subcap so we can use reasonable 4369 * filtering. 4370 */ 4371 { PCIE_EXT_CAP_ID_DVS, "dvsec", 4372 "Designated Vendor-Specific Extended Capability" }, 4373 { PCIE_EXT_CAP_ID_VFRBAR, "vfrbar", "Virtual Function Resizable BAR" }, 4374 { PCIE_EXT_CAP_ID_DLF, "dlf", "Data Link Feature", 4375 pcieadm_cap_info_vers, { { 1, 0xc, pcieadm_cap_dlf } } }, 4376 { PCIE_EXT_CAP_ID_PL16GT, "pl16g", "Physical Layer 16.0 GT/s", 4377 pcieadm_cap_info_vers, { { 1, 0x22, pcieadm_cap_16g } } }, 4378 { PCIE_EXT_CAP_ID_LANE_MARGIN, "margin", 4379 "Lane Margining at the Receiver", pcieadm_cap_info_vers, 4380 { { 1, 0x8, pcieadm_cap_margin } } }, 4381 { PCIE_EXT_CAP_ID_HIEARCHY_ID, "hierid", "Hierarchy ID" }, 4382 { PCIE_EXT_CAP_ID_NPEM, "npem", "Native PCIe Enclosure Management" }, 4383 { PCIE_EXT_CAP_ID_PL32GT, "pl32g", "Physical Layer 32.0 GT/s" }, 4384 { PCIE_EXT_CAP_ID_AP, "ap", "Alternative Protocol" }, 4385 { PCIE_EXT_CAP_ID_SFI, "sfi", "System Firmware Intermediary" } 4386 }; 4387 4388 static const pcieadm_pci_cap_t * 4389 pcieadm_cfgspace_match_cap(uint32_t capid, boolean_t pcie) 4390 { 4391 uint_t ncaps; 4392 pcieadm_pci_cap_t *caps; 4393 4394 if (pcie) { 4395 ncaps = ARRAY_SIZE(pcieadm_pcie_caps); 4396 caps = pcieadm_pcie_caps; 4397 } else { 4398 ncaps = ARRAY_SIZE(pcieadm_pci_caps); 4399 caps = pcieadm_pci_caps; 4400 } 4401 4402 for (uint_t i = 0; i < ncaps; i++) { 4403 if (caps[i].ppc_id == capid) { 4404 return (&caps[i]); 4405 } 4406 } 4407 4408 return (NULL); 4409 } 4410 4411 static void 4412 pcieadm_cfgspace_print_cap(pcieadm_cfgspace_walk_t *walkp, uint_t capid, 4413 const pcieadm_pci_cap_t *cap_info, const pcieadm_cap_vers_t *vers_info, 4414 const pcieadm_subcap_t *subcap) 4415 { 4416 boolean_t filter = B_FALSE; 4417 4418 /* 4419 * If we don't recognize the capability, print out the ID if we're not 4420 * filtering and not in parsable mode. 4421 */ 4422 if (cap_info == NULL) { 4423 if (walkp->pcw_ofmt == NULL && 4424 pcieadm_cfgspace_filter(walkp, NULL)) { 4425 warnx("encountered unknown capability ID 0x%x " 4426 "unable to print or list", capid); 4427 pcieadm_print("Unknown Capability (0x%x)\n", capid); 4428 } 4429 return; 4430 } 4431 4432 /* 4433 * Check to see if we should print this and in particular, if there's 4434 * both a capability or subcapability, we need to try and match both. 4435 * The reason that the calls to check the filters are conditioned on 4436 * pcw_ofmt is that when we're in parsable mode, we cannot match a 4437 * top-level capability since it's an arbitrary number of fields. 4438 */ 4439 if (walkp->pcw_ofmt == NULL) { 4440 filter = pcieadm_cfgspace_filter(walkp, cap_info->ppc_short); 4441 } 4442 pcieadm_strfilt_push(walkp, cap_info->ppc_short); 4443 if (subcap != NULL) { 4444 if (walkp->pcw_ofmt == NULL) { 4445 boolean_t subfilt = pcieadm_cfgspace_filter(walkp, 4446 subcap->psub_short); 4447 filter = subfilt || filter; 4448 } 4449 pcieadm_strfilt_push(walkp, subcap->psub_short); 4450 } 4451 4452 4453 if (walkp->pcw_ofmt == NULL && filter) { 4454 if ((walkp->pcw_flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 4455 if (subcap != NULL) { 4456 pcieadm_print("%s Capability - %s (%s) " 4457 "(0x%x)\n", cap_info->ppc_human, 4458 subcap->psub_human, 4459 walkp->pcw_filt->pstr_curgen, capid); 4460 } else { 4461 pcieadm_print("%s Capability (%s) (0x%x)\n", 4462 cap_info->ppc_human, 4463 walkp->pcw_filt->pstr_curgen, capid); 4464 } 4465 } else { 4466 if (subcap != NULL) { 4467 pcieadm_print("%s Capability - %s (0x%x)\n", 4468 cap_info->ppc_human, subcap->psub_human, 4469 capid); 4470 } else { 4471 pcieadm_print("%s Capability (0x%x)\n", 4472 cap_info->ppc_human, capid); 4473 } 4474 } 4475 } 4476 4477 if (vers_info != NULL) { 4478 pcieadm_cfgspace_print_t *print; 4479 4480 pcieadm_indent(); 4481 for (print = vers_info->ppr_print; 4482 print->pcp_short != NULL; print++) { 4483 VERIFY3P(print->pcp_print, !=, NULL); 4484 print->pcp_print(walkp, print, 4485 print->pcp_arg); 4486 } 4487 pcieadm_deindent(); 4488 } else { 4489 if (subcap != NULL) { 4490 warnx("Unable to print or list %s - %s (no support or " 4491 "missing version info)", cap_info->ppc_human, 4492 subcap->psub_human); 4493 } else { 4494 warnx("Unable to print or list %s (no support or " 4495 "missing version info)", cap_info->ppc_human); 4496 } 4497 } 4498 4499 if (subcap != NULL) { 4500 pcieadm_strfilt_pop(walkp); 4501 } 4502 pcieadm_strfilt_pop(walkp); 4503 } 4504 4505 static void 4506 pcieadm_cfgspace_write(int fd, const uint8_t *source, size_t len) 4507 { 4508 size_t off = 0; 4509 4510 while (len > 0) { 4511 ssize_t ret = write(fd, source + off, len - off); 4512 if (ret < 0) { 4513 err(EXIT_FAILURE, "failed to write config space to " 4514 "output file"); 4515 } 4516 4517 off += ret; 4518 len -= ret; 4519 } 4520 } 4521 4522 void 4523 pcieadm_cfgspace(pcieadm_t *pcip, pcieadm_cfgspace_op_t op, 4524 pcieadm_cfgspace_f readf, int fd, void *readarg, uint_t nfilts, 4525 pcieadm_cfgspace_filter_t *filters, pcieadm_cfgspace_flags_t flags, 4526 ofmt_handle_t ofmt) 4527 { 4528 uint_t type; 4529 uint16_t cap; 4530 pcieadm_cfgspace_data_t data; 4531 pcieadm_cfgspace_walk_t walk; 4532 const char *headstr, *headshort; 4533 pcieadm_cfgspace_print_t *header; 4534 boolean_t capsup = B_FALSE, extcfg = B_FALSE; 4535 uint_t ncaps; 4536 4537 walk.pcw_pcieadm = pcip; 4538 walk.pcw_op = op; 4539 walk.pcw_data = &data; 4540 walk.pcw_outfd = fd; 4541 walk.pcw_capoff = 0; 4542 walk.pcw_nlanes = 0; 4543 walk.pcw_nfilters = nfilts; 4544 walk.pcw_filters = filters; 4545 walk.pcw_flags = flags; 4546 walk.pcw_ofmt = ofmt; 4547 walk.pcw_filt = NULL; 4548 4549 /* 4550 * Start by reading all of the basic 40-byte config space header in one 4551 * fell swoop. 4552 */ 4553 for (uint32_t i = 0; i < PCI_CAP_PTR_OFF / 4; i++) { 4554 if (!readf(i * 4, 4, &data.pcb_u32[i], readarg)) { 4555 errx(EXIT_FAILURE, "failed to read offset %u from " 4556 "configuration space", i * 4); 4557 } 4558 } 4559 walk.pcw_valid = PCI_CAP_PTR_OFF; 4560 walk.pcw_caplen = PCI_CAP_PTR_OFF; 4561 4562 /* 4563 * Grab the information from the header that we need to figure out what 4564 * kind of device this is, how to print it, if there are any 4565 * capabilities, and go from there. 4566 */ 4567 type = data.pcb_u8[PCI_CONF_HEADER] & PCI_HEADER_TYPE_M; 4568 switch (type) { 4569 case PCI_HEADER_ZERO: 4570 headstr = "Type 0 Header"; 4571 headshort = "header0"; 4572 header = pcieadm_cfgspace_type0; 4573 capsup = (data.pcb_u8[PCI_CONF_STAT] & PCI_STAT_CAP) != 0; 4574 break; 4575 case PCI_HEADER_ONE: 4576 headstr = "Type 1 Header"; 4577 headshort = "header1"; 4578 header = pcieadm_cfgspace_type1; 4579 capsup = (data.pcb_u8[PCI_CONF_STAT] & PCI_STAT_CAP) != 0; 4580 break; 4581 case PCI_HEADER_TWO: 4582 default: 4583 headstr = "Unknown Header"; 4584 headshort = "headerX"; 4585 header = pcieadm_cfgspace_unknown; 4586 warnx("unsupported PCI header type: 0x%x, output limited to " 4587 "data configuration space"); 4588 } 4589 4590 walk.pcw_dtype = type; 4591 4592 if (op == PCIEADM_CFGSPACE_OP_WRITE) { 4593 pcieadm_cfgspace_write(fd, &data.pcb_u8[0], PCI_CAP_PTR_OFF); 4594 } else if (op == PCIEADM_CFGSPACE_OP_PRINT) { 4595 pcieadm_cfgspace_print_t *print; 4596 4597 if (walk.pcw_ofmt == NULL && 4598 pcieadm_cfgspace_filter(&walk, headshort)) { 4599 if ((flags & PCIEADM_CFGSPACE_F_SHORT) != 0) { 4600 pcieadm_print("Device %s -- %s (%s)\n", 4601 pcip->pia_devstr, headstr, headshort); 4602 } else { 4603 pcieadm_print("Device %s -- %s\n", 4604 pcip->pia_devstr, headstr); 4605 } 4606 } 4607 4608 pcieadm_strfilt_push(&walk, headshort); 4609 pcieadm_indent(); 4610 for (print = header; print->pcp_short != NULL; print++) { 4611 print->pcp_print(&walk, print, print->pcp_arg); 4612 } 4613 pcieadm_deindent(); 4614 pcieadm_strfilt_pop(&walk); 4615 } 4616 4617 4618 if (!capsup) { 4619 return; 4620 } 4621 4622 for (uint32_t i = PCI_CAP_PTR_OFF / 4; i < PCI_CONF_HDR_SIZE / 4; i++) { 4623 if (!readf(i * 4, 4, &data.pcb_u32[i], readarg)) { 4624 errx(EXIT_FAILURE, "failed to read offset %u from " 4625 "configuration space", i * 4); 4626 } 4627 } 4628 walk.pcw_valid = PCIE_EXT_CAP; 4629 VERIFY3P(walk.pcw_filt, ==, NULL); 4630 4631 if (op == PCIEADM_CFGSPACE_OP_WRITE) { 4632 pcieadm_cfgspace_write(fd, &data.pcb_u8[PCI_CAP_PTR_OFF], 4633 PCI_CONF_HDR_SIZE - PCI_CAP_PTR_OFF); 4634 } 4635 4636 ncaps = 0; 4637 cap = data.pcb_u8[PCI_CONF_CAP_PTR]; 4638 while (cap != 0 && cap != PCI_EINVAL8) { 4639 const pcieadm_pci_cap_t *cap_info; 4640 const pcieadm_cap_vers_t *vers_info = NULL; 4641 const pcieadm_subcap_t *subcap = NULL; 4642 uint8_t cap_id, nextcap; 4643 uint32_t read_len = 0; 4644 4645 /* 4646 * The PCI specification requires that the caller mask off the 4647 * bottom two bits. Always check for an invalid value (all 1s) 4648 * before this. 4649 */ 4650 cap &= PCI_CAP_PTR_MASK; 4651 cap_id = data.pcb_u8[cap + PCI_CAP_ID]; 4652 nextcap = data.pcb_u8[cap + PCI_CAP_NEXT_PTR]; 4653 cap_info = pcieadm_cfgspace_match_cap(cap_id, B_FALSE); 4654 if (cap_info != NULL && cap_info->ppc_info != NULL) { 4655 cap_info->ppc_info(&walk, cap_info, cap, &vers_info, 4656 &read_len, &subcap); 4657 } 4658 4659 walk.pcw_caplen = read_len; 4660 walk.pcw_capoff = cap; 4661 4662 if (cap_id == PCI_CAP_ID_PCI_E) { 4663 extcfg = B_TRUE; 4664 if (walk.pcw_valid != 0) { 4665 walk.pcw_pcietype = data.pcb_u8[cap + 4666 PCIE_PCIECAP] & PCIE_PCIECAP_DEV_TYPE_MASK; 4667 walk.pcw_nlanes = (data.pcb_u8[cap + 4668 PCIE_LINKCAP] & 0xf0) >> 4; 4669 walk.pcw_nlanes |= (data.pcb_u8[cap + 4670 PCIE_LINKCAP + 1] & 0x01) << 4; 4671 } else { 4672 walk.pcw_pcietype = UINT_MAX; 4673 } 4674 } 4675 4676 if (op == PCIEADM_CFGSPACE_OP_PRINT) { 4677 pcieadm_cfgspace_print_cap(&walk, cap_id, cap_info, 4678 vers_info, subcap); 4679 } 4680 4681 cap = nextcap; 4682 ncaps++; 4683 if (ncaps >= PCI_CAP_MAX_PTR) { 4684 errx(EXIT_FAILURE, "encountered more PCI capabilities " 4685 "than fit in configuration space"); 4686 } 4687 } 4688 4689 if (!extcfg) { 4690 return; 4691 } 4692 4693 for (uint_t i = PCIE_EXT_CAP / 4; i < PCIE_CONF_HDR_SIZE / 4; i++) { 4694 if (!readf(i * 4, 4, &data.pcb_u32[i], readarg)) { 4695 errx(EXIT_FAILURE, "failed to read offset %u from " 4696 "configuration space", i * 4); 4697 } 4698 } 4699 walk.pcw_valid = PCIE_CONF_HDR_SIZE; 4700 4701 if (op == PCIEADM_CFGSPACE_OP_WRITE) { 4702 pcieadm_cfgspace_write(fd, &data.pcb_u8[PCIE_EXT_CAP], 4703 PCIE_CONF_HDR_SIZE - PCIE_EXT_CAP); 4704 return; 4705 } 4706 4707 cap = PCIE_EXT_CAP; 4708 ncaps = 0; 4709 while (cap != 0 && cap != PCI_EINVAL16) { 4710 uint16_t cap_id, nextcap; 4711 const pcieadm_pci_cap_t *cap_info; 4712 const pcieadm_cap_vers_t *vers_info = NULL; 4713 const pcieadm_subcap_t *subcap = NULL; 4714 uint32_t read_len = 0; 4715 4716 /* 4717 * PCIe has the same masking as PCI. Note, sys/pcie.h currently 4718 * has PCIE_EXT_CAP_NEXT_PTR_MASK as 0xfff, instead of the 4719 * below. This should be switched to PCIE_EXT_CAP_NEXT_PTR_MASK 4720 * when the kernel headers are fixed. 4721 */ 4722 cap &= 0xffc; 4723 4724 /* 4725 * While this seems duplicative of the loop condition, a device 4726 * without capabilities indicates it with a zero for the first 4727 * cap. 4728 */ 4729 if (data.pcb_u32[cap / 4] == 0 || 4730 data.pcb_u32[cap / 4] == PCI_EINVAL32) 4731 break; 4732 4733 cap_id = data.pcb_u32[cap / 4] & PCIE_EXT_CAP_ID_MASK; 4734 nextcap = (data.pcb_u32[cap / 4] >> 4735 PCIE_EXT_CAP_NEXT_PTR_SHIFT) & PCIE_EXT_CAP_NEXT_PTR_MASK; 4736 4737 cap_info = pcieadm_cfgspace_match_cap(cap_id, B_TRUE); 4738 if (cap_info != NULL && cap_info->ppc_info != NULL) { 4739 cap_info->ppc_info(&walk, cap_info, cap, &vers_info, 4740 &read_len, &subcap); 4741 } 4742 4743 walk.pcw_caplen = read_len; 4744 walk.pcw_capoff = cap; 4745 4746 if (op == PCIEADM_CFGSPACE_OP_PRINT) { 4747 pcieadm_cfgspace_print_cap(&walk, cap_id, cap_info, 4748 vers_info, subcap); 4749 } 4750 4751 cap = nextcap; 4752 ncaps++; 4753 if (ncaps >= PCIE_EXT_CAP_MAX_PTR) { 4754 errx(EXIT_FAILURE, "encountered more PCI capabilities " 4755 "than fit in configuration space"); 4756 } 4757 } 4758 } 4759 4760 void 4761 pcieadm_show_cfgspace_usage(FILE *f) 4762 { 4763 (void) fprintf(f, "\tshow-cfgspace\t[-L] [-n] [-H] -d device | -f file " 4764 "[filter...]\n"); 4765 (void) fprintf(f, "\tshow-cfgspace\t-p -o field[,...] [-H] -d device | " 4766 "-f file [filter...]\n"); 4767 } 4768 4769 static void 4770 pcieadm_show_cfgspace_help(const char *fmt, ...) 4771 { 4772 if (fmt != NULL) { 4773 va_list ap; 4774 4775 va_start(ap, fmt); 4776 vwarnx(fmt, ap); 4777 va_end(ap); 4778 (void) fprintf(stderr, "\n"); 4779 } 4780 4781 (void) fprintf(stderr, "Usage: %s show-cfgspace [-L] [-n] [-H] -d " 4782 "device | -f file [filter...]\n", pcieadm_progname); 4783 (void) fprintf(stderr, " %s show-cfgspace -p -o field[,...] " 4784 "[-H] -d device | -f file\n\t\t\t [filter...]\n", 4785 pcieadm_progname); 4786 4787 (void) fprintf(stderr, "\nPrint and decode PCI configuration space " 4788 "data from a device or file. Each\n<filter> selects a given " 4789 "capability, sub-capability, register, or field to print.\n\n" 4790 "\t-d device\tread data from the specified device (driver instance," 4791 "\n\t\t\t/devices path, or b/d/f)\n" 4792 "\t-f file\t\tread data from the specified file\n" 4793 "\t-L\t\tlist printable fields\n" 4794 "\t-n\t\tshow printable short names\n" 4795 "\t-H\t\tomit the column header (for -L and -p)\n" 4796 "\t-p\t\tparsable output (requires -o)\n" 4797 "\t-o field\toutput fields to print (required for -p)\n"); 4798 } 4799 4800 int 4801 pcieadm_show_cfgspace(pcieadm_t *pcip, int argc, char *argv[]) 4802 { 4803 int c, ret; 4804 pcieadm_cfgspace_f readf; 4805 void *readarg; 4806 boolean_t list = B_FALSE, parse = B_FALSE; 4807 const char *device = NULL, *file = NULL, *fields = NULL; 4808 uint_t nfilts = 0; 4809 pcieadm_cfgspace_filter_t *filts = NULL; 4810 pcieadm_cfgspace_flags_t flags = 0; 4811 uint_t oflags = 0; 4812 ofmt_handle_t ofmt = NULL; 4813 4814 while ((c = getopt(argc, argv, ":HLd:f:o:np")) != -1) { 4815 switch (c) { 4816 case 'd': 4817 device = optarg; 4818 break; 4819 case 'L': 4820 list = B_TRUE; 4821 break; 4822 case 'f': 4823 file = optarg; 4824 break; 4825 case 'p': 4826 parse = B_TRUE; 4827 flags |= PCIEADM_CFGSPACE_F_PARSE; 4828 oflags |= OFMT_PARSABLE; 4829 break; 4830 case 'n': 4831 flags |= PCIEADM_CFGSPACE_F_SHORT; 4832 break; 4833 case 'H': 4834 oflags |= OFMT_NOHEADER; 4835 break; 4836 case 'o': 4837 fields = optarg; 4838 break; 4839 case ':': 4840 pcieadm_show_cfgspace_help("Option -%c requires an " 4841 "argument", optopt); 4842 exit(EXIT_USAGE); 4843 case '?': 4844 default: 4845 pcieadm_show_cfgspace_help("unknown option: -%c", 4846 optopt); 4847 exit(EXIT_USAGE); 4848 } 4849 } 4850 4851 argc -= optind; 4852 argv += optind; 4853 4854 if (device == NULL && file == NULL) { 4855 pcieadm_show_cfgspace_help("one of -d or -f must be specified"); 4856 exit(EXIT_USAGE); 4857 } 4858 4859 if (device != NULL && file != NULL) { 4860 pcieadm_show_cfgspace_help("only one of -d and -f must be " 4861 "specified"); 4862 exit(EXIT_USAGE); 4863 } 4864 4865 if (parse && fields == NULL) { 4866 pcieadm_show_cfgspace_help("-p requires fields specified with " 4867 "-o"); 4868 exit(EXIT_USAGE); 4869 } 4870 4871 if (!parse && fields != NULL) { 4872 pcieadm_show_cfgspace_help("-o can only be used with -p"); 4873 exit(EXIT_USAGE); 4874 } 4875 4876 if ((oflags & OFMT_NOHEADER) && !(list || parse)) { 4877 pcieadm_show_cfgspace_help("-H must be used with either -L or " 4878 "-p"); 4879 exit(EXIT_USAGE); 4880 } 4881 4882 if ((flags & PCIEADM_CFGSPACE_F_SHORT) && (list || parse)) { 4883 pcieadm_show_cfgspace_help("-n cannot be used with either -L " 4884 "or -p"); 4885 exit(EXIT_USAGE); 4886 } 4887 4888 if (list && parse != 0) { 4889 pcieadm_show_cfgspace_help("-L and -p cannot be used together"); 4890 exit(EXIT_USAGE); 4891 } 4892 4893 if (list && fields != NULL) { 4894 pcieadm_show_cfgspace_help("-L and -o cannot be used together"); 4895 exit(EXIT_USAGE); 4896 } 4897 4898 if (list) { 4899 fields = "short,human"; 4900 } 4901 4902 if (argc > 0) { 4903 nfilts = argc; 4904 filts = calloc(nfilts, sizeof (pcieadm_cfgspace_filter_t)); 4905 4906 for (int i = 0; i < argc; i++) { 4907 filts[i].pcf_string = argv[i]; 4908 filts[i].pcf_len = strlen(argv[i]); 4909 } 4910 } 4911 4912 if (list || parse) { 4913 ofmt_status_t oferr; 4914 oferr = ofmt_open(fields, pcieadm_cfgspace_ofmt, oflags, 0, 4915 &ofmt); 4916 ofmt_check(oferr, parse, ofmt, pcieadm_ofmt_errx, warnx); 4917 } 4918 4919 /* 4920 * Initialize privileges that we require. For reading from the kernel 4921 * we require all privileges. For a file, we just intersect with things 4922 * that would allow someone to read from any file. 4923 */ 4924 if (device != NULL) { 4925 /* 4926 * We need full privileges if reading from a device, 4927 * unfortunately. 4928 */ 4929 priv_fillset(pcip->pia_priv_eff); 4930 } else { 4931 VERIFY0(priv_addset(pcip->pia_priv_eff, PRIV_FILE_DAC_READ)); 4932 VERIFY0(priv_addset(pcip->pia_priv_eff, PRIV_FILE_DAC_SEARCH)); 4933 } 4934 pcieadm_init_privs(pcip); 4935 4936 if (device != NULL) { 4937 pcieadm_find_dip(pcip, device); 4938 pcieadm_init_cfgspace_kernel(pcip, &readf, &readarg); 4939 } else { 4940 pcip->pia_devstr = file; 4941 pcieadm_init_cfgspace_file(pcip, file, &readf, &readarg); 4942 } 4943 pcieadm_cfgspace(pcip, PCIEADM_CFGSPACE_OP_PRINT, readf, -1, readarg, 4944 nfilts, filts, flags, ofmt); 4945 if (device != NULL) { 4946 pcieadm_fini_cfgspace_kernel(readarg); 4947 } else { 4948 pcieadm_fini_cfgspace_file(readarg); 4949 } 4950 4951 ofmt_close(ofmt); 4952 ret = EXIT_SUCCESS; 4953 for (uint_t i = 0; i < nfilts; i++) { 4954 if (!filts[i].pcf_used) { 4955 warnx("filter '%s' did not match any fields", 4956 filts[i].pcf_string); 4957 ret = EXIT_FAILURE; 4958 } 4959 } 4960 4961 return (ret); 4962 } 4963 4964 typedef struct pcieadm_save_cfgspace { 4965 pcieadm_t *psc_pci; 4966 int psc_dirfd; 4967 uint_t psc_nsaved; 4968 int psc_ret; 4969 } pcieadm_save_cfgspace_t; 4970 4971 static int 4972 pcieadm_save_cfgspace_cb(di_node_t devi, void *arg) 4973 { 4974 int fd, nregs, *regs; 4975 pcieadm_save_cfgspace_t *psc = arg; 4976 pcieadm_cfgspace_f readf; 4977 void *readarg; 4978 char fname[128]; 4979 4980 psc->psc_pci->pia_devstr = di_node_name(devi); 4981 psc->psc_pci->pia_devi = devi; 4982 psc->psc_pci->pia_nexus = DI_NODE_NIL; 4983 pcieadm_find_nexus(psc->psc_pci); 4984 if (psc->psc_pci->pia_nexus == DI_NODE_NIL) { 4985 warnx("failed to find nexus for %s", di_node_name(devi)); 4986 psc->psc_ret = EXIT_FAILURE; 4987 return (DI_WALK_CONTINUE); 4988 } 4989 4990 nregs = di_prop_lookup_ints(DDI_DEV_T_ANY, devi, "reg", ®s); 4991 if (nregs <= 0) { 4992 warnx("failed to lookup regs array for %s", 4993 psc->psc_pci->pia_devstr); 4994 psc->psc_ret = EXIT_FAILURE; 4995 return (DI_WALK_CONTINUE); 4996 } 4997 4998 (void) snprintf(fname, sizeof (fname), "%02x-%02x-%02x.pci", 4999 PCI_REG_BUS_G(regs[0]), PCI_REG_DEV_G(regs[0]), 5000 PCI_REG_FUNC_G(regs[0])); 5001 5002 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, psc->psc_pci->pia_priv_eff) != 5003 0) { 5004 err(EXIT_FAILURE, "failed to raise privileges"); 5005 } 5006 fd = openat(psc->psc_dirfd, fname, O_WRONLY | O_TRUNC | O_CREAT, 0666); 5007 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, psc->psc_pci->pia_priv_min) != 5008 0) { 5009 err(EXIT_FAILURE, "failed to reduce privileges"); 5010 } 5011 5012 if (fd < 0) { 5013 warn("failed to create output file %s", fname); 5014 psc->psc_ret = EXIT_FAILURE; 5015 return (DI_WALK_CONTINUE); 5016 } 5017 5018 pcieadm_init_cfgspace_kernel(psc->psc_pci, &readf, &readarg); 5019 pcieadm_cfgspace(psc->psc_pci, PCIEADM_CFGSPACE_OP_WRITE, readf, fd, 5020 readarg, 0, NULL, 0, NULL); 5021 pcieadm_fini_cfgspace_kernel(readarg); 5022 5023 if (close(fd) != 0) { 5024 warn("failed to close output fd for %s", fname); 5025 psc->psc_ret = EXIT_FAILURE; 5026 } else { 5027 psc->psc_nsaved++; 5028 } 5029 5030 return (DI_WALK_CONTINUE); 5031 } 5032 5033 void 5034 pcieadm_save_cfgspace_usage(FILE *f) 5035 { 5036 (void) fprintf(f, "\tsave-cfgspace\t-d device output-file\n"); 5037 (void) fprintf(f, "\tsave-cfgspace\t-a output-directory\n"); 5038 } 5039 5040 static void 5041 pcieadm_save_cfgspace_help(const char *fmt, ...) 5042 { 5043 if (fmt != NULL) { 5044 va_list ap; 5045 5046 va_start(ap, fmt); 5047 vwarnx(fmt, ap); 5048 va_end(ap); 5049 (void) fprintf(stderr, "\n"); 5050 } 5051 5052 (void) fprintf(stderr, "Usage: %s save-cfgspace -d device " 5053 "output-file\n", pcieadm_progname); 5054 (void) fprintf(stderr, " %s save-cfgspace -a " 5055 "output-directory\n", pcieadm_progname); 5056 5057 (void) fprintf(stderr, "\nSave PCI configuration space data from a " 5058 "device to a file or\nsave all devices to a specified directory." 5059 "\n\n" 5060 "\t-a\t\tsave data from all devices\n" 5061 "\t-d device\tread data from the specified device (driver instance," 5062 "\n\t\t\t/devices path, or b/d/f)\n"); 5063 } 5064 5065 int 5066 pcieadm_save_cfgspace(pcieadm_t *pcip, int argc, char *argv[]) 5067 { 5068 int c; 5069 pcieadm_cfgspace_f readf; 5070 void *readarg; 5071 const char *device = NULL; 5072 boolean_t do_all = B_FALSE; 5073 5074 while ((c = getopt(argc, argv, ":ad:")) != -1) { 5075 switch (c) { 5076 case 'a': 5077 do_all = B_TRUE; 5078 break; 5079 case 'd': 5080 device = optarg; 5081 break; 5082 case ':': 5083 pcieadm_save_cfgspace_help("Option -%c requires an " 5084 "argument", optopt); 5085 exit(EXIT_USAGE); 5086 case '?': 5087 default: 5088 pcieadm_save_cfgspace_help("unknown option: -%c", 5089 optopt); 5090 exit(EXIT_USAGE); 5091 } 5092 } 5093 5094 argc -= optind; 5095 argv += optind; 5096 5097 if (device == NULL && !do_all) { 5098 pcieadm_save_cfgspace_help("missing required -d option to " 5099 "indicate device to dump"); 5100 exit(EXIT_USAGE); 5101 } 5102 5103 if (argc != 1) { 5104 pcieadm_save_cfgspace_help("missing required output path"); 5105 exit(EXIT_USAGE); 5106 } 5107 5108 /* 5109 * For reading from devices, we need to full privileges, unfortunately. 5110 */ 5111 priv_fillset(pcip->pia_priv_eff); 5112 pcieadm_init_privs(pcip); 5113 5114 if (!do_all) { 5115 int fd; 5116 5117 pcieadm_find_dip(pcip, device); 5118 5119 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_eff) != 5120 0) { 5121 err(EXIT_FAILURE, "failed to raise privileges"); 5122 } 5123 5124 if ((fd = open(argv[0], O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 5125 0) { 5126 err(EXIT_FAILURE, "failed to open output file %s", 5127 argv[0]); 5128 } 5129 5130 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_min) != 5131 0) { 5132 err(EXIT_FAILURE, "failed to reduce privileges"); 5133 } 5134 5135 pcieadm_init_cfgspace_kernel(pcip, &readf, &readarg); 5136 pcieadm_cfgspace(pcip, PCIEADM_CFGSPACE_OP_WRITE, readf, fd, 5137 readarg, 0, NULL, 0, NULL); 5138 pcieadm_fini_cfgspace_kernel(readarg); 5139 5140 if (close(fd) != 0) { 5141 err(EXIT_FAILURE, "failed to close output file " 5142 "descriptor"); 5143 } 5144 5145 return (EXIT_SUCCESS); 5146 } else { 5147 pcieadm_save_cfgspace_t psc; 5148 pcieadm_di_walk_t walk; 5149 5150 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_eff) != 5151 0) { 5152 err(EXIT_FAILURE, "failed to raise privileges"); 5153 } 5154 5155 if ((psc.psc_dirfd = open(argv[0], O_RDONLY | O_DIRECTORY)) < 5156 0) { 5157 err(EXIT_FAILURE, "failed to open output directory %s", 5158 argv[0]); 5159 } 5160 5161 if (setppriv(PRIV_SET, PRIV_EFFECTIVE, pcip->pia_priv_min) != 5162 0) { 5163 err(EXIT_FAILURE, "failed to reduce privileges"); 5164 } 5165 5166 psc.psc_nsaved = 0; 5167 psc.psc_ret = EXIT_SUCCESS; 5168 psc.psc_pci = pcip; 5169 5170 walk.pdw_arg = &psc; 5171 walk.pdw_func = pcieadm_save_cfgspace_cb; 5172 pcieadm_di_walk(pcip, &walk); 5173 5174 VERIFY0(close(psc.psc_dirfd)); 5175 5176 if (psc.psc_nsaved == 0) { 5177 warnx("failed to save any PCI devices"); 5178 return (EXIT_FAILURE); 5179 } 5180 5181 pcieadm_print("successfully saved %u devices to %s\n", 5182 psc.psc_nsaved, argv[0]); 5183 return (psc.psc_ret); 5184 } 5185 } 5186