cap.c revision 212749
1169691Skan/*- 2169691Skan * Copyright (c) 2007 Yahoo!, Inc. 3169691Skan * All rights reserved. 4169691Skan * Written by: John Baldwin <jhb@FreeBSD.org> 5169691Skan * 6169691Skan * Redistribution and use in source and binary forms, with or without 7169691Skan * modification, are permitted provided that the following conditions 8169691Skan * are met: 9169691Skan * 1. Redistributions of source code must retain the above copyright 10169691Skan * notice, this list of conditions and the following disclaimer. 11169691Skan * 2. Redistributions in binary form must reproduce the above copyright 12169691Skan * notice, this list of conditions and the following disclaimer in the 13169691Skan * documentation and/or other materials provided with the distribution. 14169691Skan * 3. Neither the name of the author nor the names of any co-contributors 15169691Skan * may be used to endorse or promote products derived from this software 16169691Skan * without specific prior written permission. 17169691Skan * 18169691Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19169691Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20169691Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21169691Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22169691Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24169691Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25169691Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26169691Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27169691Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28169691Skan * SUCH DAMAGE. 29169691Skan */ 30169691Skan 31169691Skan#ifndef lint 32169691Skanstatic const char rcsid[] = 33169691Skan "$FreeBSD: head/usr.sbin/pciconf/cap.c 212749 2010-09-16 16:03:12Z jhb $"; 34169691Skan#endif /* not lint */ 35169691Skan 36169691Skan#include <sys/types.h> 37169691Skan 38169691Skan#include <err.h> 39169691Skan#include <stdio.h> 40169691Skan#include <sys/agpio.h> 41169691Skan#include <sys/pciio.h> 42169691Skan 43169691Skan#include <dev/agp/agpreg.h> 44169691Skan#include <dev/pci/pcireg.h> 45169691Skan 46169691Skan#include "pciconf.h" 47169691Skan 48169691Skanstatic void list_ecaps(int fd, struct pci_conf *p); 49169691Skan 50169691Skanstatic void 51169691Skancap_power(int fd, struct pci_conf *p, uint8_t ptr) 52169691Skan{ 53169691Skan uint16_t cap, status; 54169691Skan 55169691Skan cap = read_config(fd, &p->pc_sel, ptr + PCIR_POWER_CAP, 2); 56169691Skan status = read_config(fd, &p->pc_sel, ptr + PCIR_POWER_STATUS, 2); 57169691Skan printf("powerspec %d supports D0%s%s D3 current D%d", 58169691Skan cap & PCIM_PCAP_SPEC, 59169691Skan cap & PCIM_PCAP_D1SUPP ? " D1" : "", 60169691Skan cap & PCIM_PCAP_D2SUPP ? " D2" : "", 61169691Skan status & PCIM_PSTAT_DMASK); 62169691Skan} 63169691Skan 64169691Skanstatic void 65169691Skancap_agp(int fd, struct pci_conf *p, uint8_t ptr) 66169691Skan{ 67169691Skan uint32_t status, command; 68169691Skan 69169691Skan status = read_config(fd, &p->pc_sel, ptr + AGP_STATUS, 4); 70169691Skan command = read_config(fd, &p->pc_sel, ptr + AGP_CAPID, 4); 71169691Skan printf("AGP "); 72169691Skan if (AGP_MODE_GET_MODE_3(status)) { 73169691Skan printf("v3 "); 74169691Skan if (AGP_MODE_GET_RATE(status) & AGP_MODE_V3_RATE_8x) 75169691Skan printf("8x "); 76169691Skan if (AGP_MODE_GET_RATE(status) & AGP_MODE_V3_RATE_4x) 77169691Skan printf("4x "); 78169691Skan } else { 79169691Skan if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_4x) 80169691Skan printf("4x "); 81169691Skan if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_2x) 82169691Skan printf("2x "); 83169691Skan if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_1x) 84169691Skan printf("1x "); 85169691Skan } 86169691Skan if (AGP_MODE_GET_SBA(status)) 87169691Skan printf("SBA "); 88169691Skan if (AGP_MODE_GET_AGP(command)) { 89169691Skan printf("enabled at "); 90169691Skan if (AGP_MODE_GET_MODE_3(command)) { 91169691Skan printf("v3 "); 92169691Skan switch (AGP_MODE_GET_RATE(command)) { 93169691Skan case AGP_MODE_V3_RATE_8x: 94169691Skan printf("8x "); 95169691Skan break; 96169691Skan case AGP_MODE_V3_RATE_4x: 97169691Skan printf("4x "); 98169691Skan break; 99169691Skan } 100169691Skan } else 101169691Skan switch (AGP_MODE_GET_RATE(command)) { 102169691Skan case AGP_MODE_V2_RATE_4x: 103169691Skan printf("4x "); 104169691Skan break; 105169691Skan case AGP_MODE_V2_RATE_2x: 106169691Skan printf("2x "); 107169691Skan break; 108169691Skan case AGP_MODE_V2_RATE_1x: 109169691Skan printf("1x "); 110169691Skan break; 111169691Skan } 112169691Skan if (AGP_MODE_GET_SBA(command)) 113169691Skan printf("SBA "); 114169691Skan } else 115169691Skan printf("disabled"); 116169691Skan} 117169691Skan 118169691Skanstatic void 119169691Skancap_vpd(int fd, struct pci_conf *p, uint8_t ptr) 120169691Skan{ 121169691Skan 122169691Skan printf("VPD"); 123169691Skan} 124169691Skan 125169691Skanstatic void 126169691Skancap_msi(int fd, struct pci_conf *p, uint8_t ptr) 127169691Skan{ 128169691Skan uint16_t ctrl; 129169691Skan int msgnum; 130169691Skan 131169691Skan ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSI_CTRL, 2); 132169691Skan msgnum = 1 << ((ctrl & PCIM_MSICTRL_MMC_MASK) >> 1); 133169691Skan printf("MSI supports %d message%s%s%s ", msgnum, 134169691Skan (msgnum == 1) ? "" : "s", 135169691Skan (ctrl & PCIM_MSICTRL_64BIT) ? ", 64 bit" : "", 136169691Skan (ctrl & PCIM_MSICTRL_VECTOR) ? ", vector masks" : ""); 137169691Skan if (ctrl & PCIM_MSICTRL_MSI_ENABLE) { 138169691Skan msgnum = 1 << ((ctrl & PCIM_MSICTRL_MME_MASK) >> 4); 139169691Skan printf("enabled with %d message%s", msgnum, 140169691Skan (msgnum == 1) ? "" : "s"); 141169691Skan } 142169691Skan} 143169691Skan 144169691Skanstatic void 145169691Skancap_pcix(int fd, struct pci_conf *p, uint8_t ptr) 146169691Skan{ 147169691Skan uint32_t status; 148169691Skan int comma, max_splits, max_burst_read; 149169691Skan 150169691Skan status = read_config(fd, &p->pc_sel, ptr + PCIXR_STATUS, 4); 151169691Skan printf("PCI-X "); 152169691Skan if (status & PCIXM_STATUS_64BIT) 153169691Skan printf("64-bit "); 154169691Skan if ((p->pc_hdr & PCIM_HDRTYPE) == 1) 155169691Skan printf("bridge "); 156169691Skan if ((p->pc_hdr & PCIM_HDRTYPE) != 1 || (status & (PCIXM_STATUS_133CAP | 157169691Skan PCIXM_STATUS_266CAP | PCIXM_STATUS_533CAP)) != 0) 158169691Skan printf("supports"); 159169691Skan comma = 0; 160169691Skan if (status & PCIXM_STATUS_133CAP) { 161169691Skan printf("%s 133MHz", comma ? "," : ""); 162169691Skan comma = 1; 163169691Skan } 164169691Skan if (status & PCIXM_STATUS_266CAP) { 165169691Skan printf("%s 266MHz", comma ? "," : ""); 166169691Skan comma = 1; 167169691Skan } 168169691Skan if (status & PCIXM_STATUS_533CAP) { 169169691Skan printf("%s 533MHz", comma ? "," : ""); 170169691Skan comma = 1; 171169691Skan } 172169691Skan if ((p->pc_hdr & PCIM_HDRTYPE) == 1) 173169691Skan return; 174169691Skan switch (status & PCIXM_STATUS_MAX_READ) { 175169691Skan case PCIXM_STATUS_MAX_READ_512: 176169691Skan max_burst_read = 512; 177169691Skan break; 178169691Skan case PCIXM_STATUS_MAX_READ_1024: 179169691Skan max_burst_read = 1024; 180169691Skan break; 181169691Skan case PCIXM_STATUS_MAX_READ_2048: 182169691Skan max_burst_read = 2048; 183169691Skan break; 184169691Skan case PCIXM_STATUS_MAX_READ_4096: 185169691Skan max_burst_read = 4096; 186169691Skan break; 187169691Skan } 188169691Skan switch (status & PCIXM_STATUS_MAX_SPLITS) { 189169691Skan case PCIXM_STATUS_MAX_SPLITS_1: 190169691Skan max_splits = 1; 191169691Skan break; 192169691Skan case PCIXM_STATUS_MAX_SPLITS_2: 193169691Skan max_splits = 2; 194169691Skan break; 195169691Skan case PCIXM_STATUS_MAX_SPLITS_3: 196169691Skan max_splits = 3; 197169691Skan break; 198169691Skan case PCIXM_STATUS_MAX_SPLITS_4: 199169691Skan max_splits = 4; 200169691Skan break; 201169691Skan case PCIXM_STATUS_MAX_SPLITS_8: 202169691Skan max_splits = 8; 203169691Skan break; 204169691Skan case PCIXM_STATUS_MAX_SPLITS_12: 205169691Skan max_splits = 12; 206169691Skan break; 207169691Skan case PCIXM_STATUS_MAX_SPLITS_16: 208169691Skan max_splits = 16; 209169691Skan break; 210169691Skan case PCIXM_STATUS_MAX_SPLITS_32: 211169691Skan max_splits = 32; 212169691Skan break; 213169691Skan } 214169691Skan printf("%s %d burst read, %d split transaction%s", comma ? "," : "", 215169691Skan max_burst_read, max_splits, max_splits == 1 ? "" : "s"); 216169691Skan} 217169691Skan 218169691Skanstatic void 219169691Skancap_ht(int fd, struct pci_conf *p, uint8_t ptr) 220169691Skan{ 221169691Skan uint32_t reg; 222169691Skan uint16_t command; 223169691Skan 224169691Skan command = read_config(fd, &p->pc_sel, ptr + PCIR_HT_COMMAND, 2); 225169691Skan printf("HT "); 226169691Skan if ((command & 0xe000) == PCIM_HTCAP_SLAVE) 227169691Skan printf("slave"); 228169691Skan else if ((command & 0xe000) == PCIM_HTCAP_HOST) 229169691Skan printf("host"); 230169691Skan else 231169691Skan switch (command & PCIM_HTCMD_CAP_MASK) { 232169691Skan case PCIM_HTCAP_SWITCH: 233169691Skan printf("switch"); 234169691Skan break; 235169691Skan case PCIM_HTCAP_INTERRUPT: 236169691Skan printf("interrupt"); 237169691Skan break; 238169691Skan case PCIM_HTCAP_REVISION_ID: 239169691Skan printf("revision ID"); 240169691Skan break; 241169691Skan case PCIM_HTCAP_UNITID_CLUMPING: 242169691Skan printf("unit ID clumping"); 243169691Skan break; 244169691Skan case PCIM_HTCAP_EXT_CONFIG_SPACE: 245169691Skan printf("extended config space"); 246169691Skan break; 247169691Skan case PCIM_HTCAP_ADDRESS_MAPPING: 248169691Skan printf("address mapping"); 249169691Skan break; 250169691Skan case PCIM_HTCAP_MSI_MAPPING: 251169691Skan printf("MSI %saddress window %s at 0x", 252169691Skan command & PCIM_HTCMD_MSI_FIXED ? "fixed " : "", 253169691Skan command & PCIM_HTCMD_MSI_ENABLE ? "enabled" : 254169691Skan "disabled"); 255169691Skan if (command & PCIM_HTCMD_MSI_FIXED) 256169691Skan printf("fee00000"); 257169691Skan else { 258169691Skan reg = read_config(fd, &p->pc_sel, 259169691Skan ptr + PCIR_HTMSI_ADDRESS_HI, 4); 260169691Skan if (reg != 0) 261169691Skan printf("%08x", reg); 262169691Skan reg = read_config(fd, &p->pc_sel, 263169691Skan ptr + PCIR_HTMSI_ADDRESS_LO, 4); 264169691Skan printf("%08x", reg); 265169691Skan } 266169691Skan break; 267169691Skan case PCIM_HTCAP_DIRECT_ROUTE: 268169691Skan printf("direct route"); 269169691Skan break; 270169691Skan case PCIM_HTCAP_VCSET: 271169691Skan printf("VC set"); 272169691Skan break; 273169691Skan case PCIM_HTCAP_RETRY_MODE: 274169691Skan printf("retry mode"); 275169691Skan break; 276169691Skan case PCIM_HTCAP_X86_ENCODING: 277169691Skan printf("X86 encoding"); 278169691Skan break; 279169691Skan default: 280169691Skan printf("unknown %02x", command); 281169691Skan break; 282169691Skan } 283169691Skan} 284169691Skan 285169691Skanstatic void 286169691Skancap_vendor(int fd, struct pci_conf *p, uint8_t ptr) 287169691Skan{ 288169691Skan uint8_t length; 289169691Skan 290169691Skan length = read_config(fd, &p->pc_sel, ptr + PCIR_VENDOR_LENGTH, 1); 291169691Skan printf("vendor (length %d)", length); 292169691Skan if (p->pc_vendor == 0x8086) { 293169691Skan /* Intel */ 294169691Skan uint8_t version; 295169691Skan 296169691Skan version = read_config(fd, &p->pc_sel, ptr + PCIR_VENDOR_DATA, 297169691Skan 1); 298169691Skan printf(" Intel cap %d version %d", version >> 4, version & 0xf); 299169691Skan if (version >> 4 == 1 && length == 12) { 300169691Skan /* Feature Detection */ 301169691Skan uint32_t fvec; 302169691Skan int comma; 303169691Skan 304169691Skan comma = 0; 305169691Skan fvec = read_config(fd, &p->pc_sel, ptr + 306169691Skan PCIR_VENDOR_DATA + 5, 4); 307169691Skan printf("\n\t\t features:"); 308169691Skan if (fvec & (1 << 0)) { 309169691Skan printf(" AMT"); 310169691Skan comma = 1; 311169691Skan } 312169691Skan fvec = read_config(fd, &p->pc_sel, ptr + 313169691Skan PCIR_VENDOR_DATA + 1, 4); 314169691Skan if (fvec & (1 << 21)) { 315169691Skan printf("%s Quick Resume", comma ? "," : ""); 316169691Skan comma = 1; 317169691Skan } 318169691Skan if (fvec & (1 << 18)) { 319169691Skan printf("%s SATA RAID-5", comma ? "," : ""); 320169691Skan comma = 1; 321169691Skan } 322169691Skan if (fvec & (1 << 9)) { 323169691Skan printf("%s Mobile", comma ? "," : ""); 324169691Skan comma = 1; 325169691Skan } 326169691Skan if (fvec & (1 << 7)) { 327169691Skan printf("%s 6 PCI-e x1 slots", comma ? "," : ""); 328169691Skan comma = 1; 329169691Skan } else { 330169691Skan printf("%s 4 PCI-e x1 slots", comma ? "," : ""); 331169691Skan comma = 1; 332169691Skan } 333169691Skan if (fvec & (1 << 5)) { 334169691Skan printf("%s SATA RAID-0/1/10", comma ? "," : ""); 335169691Skan comma = 1; 336169691Skan } 337169691Skan if (fvec & (1 << 3)) { 338169691Skan printf("%s SATA AHCI", comma ? "," : ""); 339169691Skan comma = 1; 340169691Skan } 341169691Skan } 342169691Skan } 343169691Skan} 344169691Skan 345169691Skanstatic void 346169691Skancap_debug(int fd, struct pci_conf *p, uint8_t ptr) 347169691Skan{ 348169691Skan uint16_t debug_port; 349169691Skan 350169691Skan debug_port = read_config(fd, &p->pc_sel, ptr + PCIR_DEBUG_PORT, 2); 351169691Skan printf("EHCI Debug Port at offset 0x%x in map 0x%x", debug_port & 352169691Skan PCIM_DEBUG_PORT_OFFSET, PCIR_BAR(debug_port >> 13)); 353169691Skan} 354169691Skan 355169691Skanstatic void 356169691Skancap_subvendor(int fd, struct pci_conf *p, uint8_t ptr) 357169691Skan{ 358169691Skan uint32_t id; 359169691Skan 360169691Skan id = read_config(fd, &p->pc_sel, ptr + PCIR_SUBVENDCAP_ID, 4); 361169691Skan printf("PCI Bridge card=0x%08x", id); 362169691Skan} 363169691Skan 364169691Skan#define MAX_PAYLOAD(field) (128 << (field)) 365169691Skan 366169691Skanstatic void 367169691Skancap_express(int fd, struct pci_conf *p, uint8_t ptr) 368169691Skan{ 369169691Skan uint32_t val; 370169691Skan uint16_t flags; 371169691Skan 372169691Skan flags = read_config(fd, &p->pc_sel, ptr + PCIR_EXPRESS_FLAGS, 2); 373169691Skan printf("PCI-Express %d ", flags & PCIM_EXP_FLAGS_VERSION); 374169691Skan switch (flags & PCIM_EXP_FLAGS_TYPE) { 375169691Skan case PCIM_EXP_TYPE_ENDPOINT: 376169691Skan printf("endpoint"); 377169691Skan break; 378169691Skan case PCIM_EXP_TYPE_LEGACY_ENDPOINT: 379169691Skan printf("legacy endpoint"); 380169691Skan break; 381169691Skan case PCIM_EXP_TYPE_ROOT_PORT: 382169691Skan printf("root port"); 383169691Skan break; 384169691Skan case PCIM_EXP_TYPE_UPSTREAM_PORT: 385169691Skan printf("upstream port"); 386169691Skan break; 387169691Skan case PCIM_EXP_TYPE_DOWNSTREAM_PORT: 388169691Skan printf("downstream port"); 389169691Skan break; 390169691Skan case PCIM_EXP_TYPE_PCI_BRIDGE: 391169691Skan printf("PCI bridge"); 392169691Skan break; 393169691Skan case PCIM_EXP_TYPE_PCIE_BRIDGE: 394169691Skan printf("PCI to PCIe bridge"); 395169691Skan break; 396169691Skan case PCIM_EXP_TYPE_ROOT_INT_EP: 397169691Skan printf("root endpoint"); 398169691Skan break; 399169691Skan case PCIM_EXP_TYPE_ROOT_EC: 400169691Skan printf("event collector"); 401169691Skan break; 402169691Skan default: 403169691Skan printf("type %d", (flags & PCIM_EXP_FLAGS_TYPE) >> 4); 404169691Skan break; 405169691Skan } 406169691Skan if (flags & PCIM_EXP_FLAGS_IRQ) 407169691Skan printf(" IRQ %d", (flags & PCIM_EXP_FLAGS_IRQ) >> 8); 408169691Skan val = read_config(fd, &p->pc_sel, ptr + PCIR_EXPRESS_DEVICE_CAP, 4); 409169691Skan flags = read_config(fd, &p->pc_sel, ptr + PCIR_EXPRESS_DEVICE_CTL, 2); 410169691Skan printf(" max data %d(%d)", 411169691Skan MAX_PAYLOAD((flags & PCIM_EXP_CTL_MAX_PAYLOAD) >> 5), 412169691Skan MAX_PAYLOAD(val & PCIM_EXP_CAP_MAX_PAYLOAD)); 413169691Skan val = read_config(fd, &p->pc_sel, ptr + PCIR_EXPRESS_LINK_CAP, 4); 414169691Skan flags = read_config(fd, &p->pc_sel, ptr+ PCIR_EXPRESS_LINK_STA, 2); 415169691Skan printf(" link x%d(x%d)", (flags & PCIM_LINK_STA_WIDTH) >> 4, 416169691Skan (val & PCIM_LINK_CAP_MAX_WIDTH) >> 4); 417169691Skan} 418169691Skan 419169691Skanstatic void 420169691Skancap_msix(int fd, struct pci_conf *p, uint8_t ptr) 421169691Skan{ 422169691Skan uint32_t val; 423169691Skan uint16_t ctrl; 424169691Skan int msgnum, table_bar, pba_bar; 425169691Skan 426169691Skan ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_CTRL, 2); 427169691Skan msgnum = (ctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1; 428169691Skan val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_TABLE, 4); 429169691Skan table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK); 430169691Skan val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_PBA, 4); 431169691Skan pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK); 432169691Skan printf("MSI-X supports %d message%s ", msgnum, 433169691Skan (msgnum == 1) ? "" : "s"); 434169691Skan if (table_bar == pba_bar) 435169691Skan printf("in map 0x%x", table_bar); 436169691Skan else 437169691Skan printf("in maps 0x%x and 0x%x", table_bar, pba_bar); 438169691Skan if (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE) 439169691Skan printf(" enabled"); 440169691Skan} 441169691Skan 442169691Skanstatic void 443169691Skancap_sata(int fd, struct pci_conf *p, uint8_t ptr) 444169691Skan{ 445169691Skan 446169691Skan printf("SATA Index-Data Pair"); 447169691Skan} 448169691Skan 449169691Skanstatic void 450169691Skancap_pciaf(int fd, struct pci_conf *p, uint8_t ptr) 451169691Skan{ 452169691Skan uint8_t cap; 453169691Skan 454169691Skan cap = read_config(fd, &p->pc_sel, ptr + PCIR_PCIAF_CAP, 1); 455169691Skan printf("PCI Advanced Features:%s%s", 456169691Skan cap & PCIM_PCIAFCAP_FLR ? " FLR" : "", 457169691Skan cap & PCIM_PCIAFCAP_TP ? " TP" : ""); 458169691Skan} 459169691Skan 460169691Skanvoid 461169691Skanlist_caps(int fd, struct pci_conf *p) 462169691Skan{ 463169691Skan int express; 464169691Skan uint16_t sta; 465169691Skan uint8_t ptr, cap; 466169691Skan 467169691Skan /* Are capabilities present for this device? */ 468169691Skan sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2); 469169691Skan if (!(sta & PCIM_STATUS_CAPPRESENT)) 470169691Skan return; 471169691Skan 472169691Skan switch (p->pc_hdr & PCIM_HDRTYPE) { 473169691Skan case PCIM_HDRTYPE_NORMAL: 474169691Skan case PCIM_HDRTYPE_BRIDGE: 475169691Skan ptr = PCIR_CAP_PTR; 476169691Skan break; 477169691Skan case PCIM_HDRTYPE_CARDBUS: 478169691Skan ptr = PCIR_CAP_PTR_2; 479169691Skan break; 480169691Skan default: 481169691Skan errx(1, "list_caps: bad header type"); 482169691Skan } 483169691Skan 484169691Skan /* Walk the capability list. */ 485169691Skan express = 0; 486169691Skan ptr = read_config(fd, &p->pc_sel, ptr, 1); 487169691Skan while (ptr != 0 && ptr != 0xff) { 488169691Skan cap = read_config(fd, &p->pc_sel, ptr + PCICAP_ID, 1); 489169691Skan printf(" cap %02x[%02x] = ", cap, ptr); 490169691Skan switch (cap) { 491169691Skan case PCIY_PMG: 492169691Skan cap_power(fd, p, ptr); 493169691Skan break; 494169691Skan case PCIY_AGP: 495169691Skan cap_agp(fd, p, ptr); 496169691Skan break; 497169691Skan case PCIY_VPD: 498169691Skan cap_vpd(fd, p, ptr); 499169691Skan break; 500169691Skan case PCIY_MSI: 501169691Skan cap_msi(fd, p, ptr); 502169691Skan break; 503169691Skan case PCIY_PCIX: 504169691Skan cap_pcix(fd, p, ptr); 505169691Skan break; 506169691Skan case PCIY_HT: 507169691Skan cap_ht(fd, p, ptr); 508169691Skan break; 509169691Skan case PCIY_VENDOR: 510169691Skan cap_vendor(fd, p, ptr); 511169691Skan break; 512169691Skan case PCIY_DEBUG: 513169691Skan cap_debug(fd, p, ptr); 514169691Skan break; 515169691Skan case PCIY_SUBVENDOR: 516169691Skan cap_subvendor(fd, p, ptr); 517169691Skan break; 518169691Skan case PCIY_EXPRESS: 519169691Skan express = 1; 520169691Skan cap_express(fd, p, ptr); 521169691Skan break; 522169691Skan case PCIY_MSIX: 523169691Skan cap_msix(fd, p, ptr); 524169691Skan break; 525169691Skan case PCIY_SATA: 526169691Skan cap_sata(fd, p, ptr); 527169691Skan break; 528169691Skan case PCIY_PCIAF: 529169691Skan cap_pciaf(fd, p, ptr); 530169691Skan break; 531169691Skan default: 532169691Skan printf("unknown"); 533169691Skan break; 534169691Skan } 535169691Skan printf("\n"); 536169691Skan ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1); 537169691Skan } 538169691Skan 539169691Skan if (express) 540169691Skan list_ecaps(fd, p); 541169691Skan} 542169691Skan 543169691Skan/* From <sys/systm.h>. */ 544169691Skanstatic __inline uint32_t 545169691Skanbitcount32(uint32_t x) 546169691Skan{ 547169691Skan 548169691Skan x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1); 549169691Skan x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2); 550169691Skan x = (x + (x >> 4)) & 0x0f0f0f0f; 551169691Skan x = (x + (x >> 8)); 552169691Skan x = (x + (x >> 16)) & 0x000000ff; 553169691Skan return (x); 554169691Skan} 555169691Skan 556169691Skanstatic void 557169691Skanecap_aer(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver) 558169691Skan{ 559169691Skan uint32_t sta, mask; 560169691Skan 561169691Skan printf("AER %d", ver); 562169691Skan if (ver != 1) 563169691Skan return; 564169691Skan sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_STATUS, 4); 565169691Skan mask = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_SEVERITY, 4); 566169691Skan printf(" %d fatal", bitcount32(sta & mask)); 567169691Skan printf(" %d non-fatal", bitcount32(sta & ~mask)); 568169691Skan sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_COR_STATUS, 4); 569169691Skan printf(" %d corrected", bitcount32(sta)); 570169691Skan} 571169691Skan 572169691Skanstatic void 573169691Skanecap_vc(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver) 574169691Skan{ 575169691Skan uint32_t cap1; 576169691Skan 577169691Skan printf("VC %d", ver); 578169691Skan if (ver != 1) 579169691Skan return; 580169691Skan cap1 = read_config(fd, &p->pc_sel, ptr + PCIR_VC_CAP1, 4); 581169691Skan printf(" max VC%d", cap1 & PCIM_VC_CAP1_EXT_COUNT); 582169691Skan if ((cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) != 0) 583169691Skan printf(" lowpri VC0-VC%d", 584169691Skan (cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) >> 4); 585169691Skan} 586169691Skan 587169691Skanstatic void 588169691Skanecap_sernum(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver) 589169691Skan{ 590169691Skan uint32_t high, low; 591169691Skan 592169691Skan printf("Serial %d", ver); 593169691Skan if (ver != 1) 594169691Skan return; 595169691Skan low = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_LOW, 4); 596169691Skan high = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_HIGH, 4); 597169691Skan printf(" %08x%08x", high, low); 598169691Skan} 599169691Skan 600169691Skanstatic void 601169691Skanlist_ecaps(int fd, struct pci_conf *p) 602169691Skan{ 603169691Skan uint32_t ecap; 604169691Skan uint16_t ptr; 605169691Skan 606169691Skan ptr = PCIR_EXTCAP; 607169691Skan ecap = read_config(fd, &p->pc_sel, ptr, 4); 608169691Skan if (ecap == 0xffffffff || ecap == 0) 609169691Skan return; 610169691Skan for (;;) { 611169691Skan printf("ecap %04x[%03x] = ", PCI_EXTCAP_ID(ecap), ptr); 612169691Skan switch (PCI_EXTCAP_ID(ecap)) { 613169691Skan case PCIZ_AER: 614169691Skan ecap_aer(fd, p, ptr, PCI_EXTCAP_VER(ecap)); 615169691Skan break; 616169691Skan case PCIZ_VC: 617169691Skan ecap_vc(fd, p, ptr, PCI_EXTCAP_VER(ecap)); 618169691Skan break; 619169691Skan case PCIZ_SERNUM: 620169691Skan ecap_sernum(fd, p, ptr, PCI_EXTCAP_VER(ecap)); 621169691Skan break; 622169691Skan default: 623169691Skan printf("unknown %d", PCI_EXTCAP_VER(ecap)); 624169691Skan break; 625169691Skan } 626169691Skan printf("\n"); 627169691Skan ptr = PCI_EXTCAP_NEXTPTR(ecap); 628169691Skan if (ptr == 0) 629169691Skan break; 630169691Skan ecap = read_config(fd, &p->pc_sel, ptr, 4); 631169691Skan } 632169691Skan} 633169691Skan