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