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