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