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