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