1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2007 Yahoo!, Inc.
5 * All rights reserved.
6 * Written by: John Baldwin <jhb@FreeBSD.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34
35#include <err.h>
36#include <stdio.h>
37#include <strings.h>
38#include <sys/agpio.h>
39#include <sys/pciio.h>
40
41#include <dev/agp/agpreg.h>
42#include <dev/pci/pcireg.h>
43
44#include "pciconf.h"
45
46static void	list_ecaps(int fd, struct pci_conf *p);
47
48static int cap_level;
49
50static void
51cap_power(int fd, struct pci_conf *p, uint8_t ptr)
52{
53	uint16_t cap, status;
54
55	cap = read_config(fd, &p->pc_sel, ptr + PCIR_POWER_CAP, 2);
56	status = read_config(fd, &p->pc_sel, ptr + PCIR_POWER_STATUS, 2);
57	printf("powerspec %d  supports D0%s%s D3  current D%d",
58	    cap & PCIM_PCAP_SPEC,
59	    cap & PCIM_PCAP_D1SUPP ? " D1" : "",
60	    cap & PCIM_PCAP_D2SUPP ? " D2" : "",
61	    status & PCIM_PSTAT_DMASK);
62}
63
64static void
65cap_agp(int fd, struct pci_conf *p, uint8_t ptr)
66{
67	uint32_t status, command;
68
69	status = read_config(fd, &p->pc_sel, ptr + AGP_STATUS, 4);
70	command = read_config(fd, &p->pc_sel, ptr + AGP_CAPID, 4);
71	printf("AGP ");
72	if (AGP_MODE_GET_MODE_3(status)) {
73		printf("v3 ");
74		if (AGP_MODE_GET_RATE(status) & AGP_MODE_V3_RATE_8x)
75			printf("8x ");
76		if (AGP_MODE_GET_RATE(status) & AGP_MODE_V3_RATE_4x)
77			printf("4x ");
78	} else {
79		if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_4x)
80			printf("4x ");
81		if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_2x)
82			printf("2x ");
83		if (AGP_MODE_GET_RATE(status) & AGP_MODE_V2_RATE_1x)
84			printf("1x ");
85	}
86	if (AGP_MODE_GET_SBA(status))
87		printf("SBA ");
88	if (AGP_MODE_GET_AGP(command)) {
89		printf("enabled at ");
90		if (AGP_MODE_GET_MODE_3(command)) {
91			printf("v3 ");
92			switch (AGP_MODE_GET_RATE(command)) {
93			case AGP_MODE_V3_RATE_8x:
94				printf("8x ");
95				break;
96			case AGP_MODE_V3_RATE_4x:
97				printf("4x ");
98				break;
99			}
100		} else
101			switch (AGP_MODE_GET_RATE(command)) {
102			case AGP_MODE_V2_RATE_4x:
103				printf("4x ");
104				break;
105			case AGP_MODE_V2_RATE_2x:
106				printf("2x ");
107				break;
108			case AGP_MODE_V2_RATE_1x:
109				printf("1x ");
110				break;
111			}
112		if (AGP_MODE_GET_SBA(command))
113			printf("SBA ");
114	} else
115		printf("disabled");
116}
117
118static void
119cap_vpd(int fd __unused, struct pci_conf *p __unused, uint8_t ptr __unused)
120{
121
122	printf("VPD");
123}
124
125static void
126cap_msi(int fd, struct pci_conf *p, uint8_t ptr)
127{
128	uint16_t ctrl;
129	int msgnum;
130
131	ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSI_CTRL, 2);
132	msgnum = 1 << ((ctrl & PCIM_MSICTRL_MMC_MASK) >> 1);
133	printf("MSI supports %d message%s%s%s ", msgnum,
134	    (msgnum == 1) ? "" : "s",
135	    (ctrl & PCIM_MSICTRL_64BIT) ? ", 64 bit" : "",
136	    (ctrl & PCIM_MSICTRL_VECTOR) ? ", vector masks" : "");
137	if (ctrl & PCIM_MSICTRL_MSI_ENABLE) {
138		msgnum = 1 << ((ctrl & PCIM_MSICTRL_MME_MASK) >> 4);
139		printf("enabled with %d message%s", msgnum,
140		    (msgnum == 1) ? "" : "s");
141	}
142}
143
144static void
145cap_pcix(int fd, struct pci_conf *p, uint8_t ptr)
146{
147	uint32_t status;
148	int comma, max_splits, max_burst_read;
149
150	status = read_config(fd, &p->pc_sel, ptr + PCIXR_STATUS, 4);
151	printf("PCI-X ");
152	if (status & PCIXM_STATUS_64BIT)
153		printf("64-bit ");
154	if ((p->pc_hdr & PCIM_HDRTYPE) == 1)
155		printf("bridge ");
156	if ((p->pc_hdr & PCIM_HDRTYPE) != 1 || (status & (PCIXM_STATUS_133CAP |
157	    PCIXM_STATUS_266CAP | PCIXM_STATUS_533CAP)) != 0)
158		printf("supports");
159	comma = 0;
160	if (status & PCIXM_STATUS_133CAP) {
161		printf(" 133MHz");
162		comma = 1;
163	}
164	if (status & PCIXM_STATUS_266CAP) {
165		printf("%s 266MHz", comma ? "," : "");
166		comma = 1;
167	}
168	if (status & PCIXM_STATUS_533CAP) {
169		printf("%s 533MHz", comma ? "," : "");
170		comma = 1;
171	}
172	if ((p->pc_hdr & PCIM_HDRTYPE) == 1)
173		return;
174	max_burst_read = 0;
175	switch (status & PCIXM_STATUS_MAX_READ) {
176	case PCIXM_STATUS_MAX_READ_512:
177		max_burst_read = 512;
178		break;
179	case PCIXM_STATUS_MAX_READ_1024:
180		max_burst_read = 1024;
181		break;
182	case PCIXM_STATUS_MAX_READ_2048:
183		max_burst_read = 2048;
184		break;
185	case PCIXM_STATUS_MAX_READ_4096:
186		max_burst_read = 4096;
187		break;
188	}
189	max_splits = 0;
190	switch (status & PCIXM_STATUS_MAX_SPLITS) {
191	case PCIXM_STATUS_MAX_SPLITS_1:
192		max_splits = 1;
193		break;
194	case PCIXM_STATUS_MAX_SPLITS_2:
195		max_splits = 2;
196		break;
197	case PCIXM_STATUS_MAX_SPLITS_3:
198		max_splits = 3;
199		break;
200	case PCIXM_STATUS_MAX_SPLITS_4:
201		max_splits = 4;
202		break;
203	case PCIXM_STATUS_MAX_SPLITS_8:
204		max_splits = 8;
205		break;
206	case PCIXM_STATUS_MAX_SPLITS_12:
207		max_splits = 12;
208		break;
209	case PCIXM_STATUS_MAX_SPLITS_16:
210		max_splits = 16;
211		break;
212	case PCIXM_STATUS_MAX_SPLITS_32:
213		max_splits = 32;
214		break;
215	}
216	printf("%s %d burst read, %d split transaction%s", comma ? "," : "",
217	    max_burst_read, max_splits, max_splits == 1 ? "" : "s");
218}
219
220static void
221cap_ht(int fd, struct pci_conf *p, uint8_t ptr)
222{
223	uint32_t reg;
224	uint16_t command;
225
226	command = read_config(fd, &p->pc_sel, ptr + PCIR_HT_COMMAND, 2);
227	printf("HT ");
228	if ((command & 0xe000) == PCIM_HTCAP_SLAVE)
229		printf("slave");
230	else if ((command & 0xe000) == PCIM_HTCAP_HOST)
231		printf("host");
232	else
233		switch (command & PCIM_HTCMD_CAP_MASK) {
234		case PCIM_HTCAP_SWITCH:
235			printf("switch");
236			break;
237		case PCIM_HTCAP_INTERRUPT:
238			printf("interrupt");
239			break;
240		case PCIM_HTCAP_REVISION_ID:
241			printf("revision ID");
242			break;
243		case PCIM_HTCAP_UNITID_CLUMPING:
244			printf("unit ID clumping");
245			break;
246		case PCIM_HTCAP_EXT_CONFIG_SPACE:
247			printf("extended config space");
248			break;
249		case PCIM_HTCAP_ADDRESS_MAPPING:
250			printf("address mapping");
251			break;
252		case PCIM_HTCAP_MSI_MAPPING:
253			printf("MSI %saddress window %s at 0x",
254			    command & PCIM_HTCMD_MSI_FIXED ? "fixed " : "",
255			    command & PCIM_HTCMD_MSI_ENABLE ? "enabled" :
256			    "disabled");
257			if (command & PCIM_HTCMD_MSI_FIXED)
258				printf("fee00000");
259			else {
260				reg = read_config(fd, &p->pc_sel,
261				    ptr + PCIR_HTMSI_ADDRESS_HI, 4);
262				if (reg != 0)
263					printf("%08x", reg);
264				reg = read_config(fd, &p->pc_sel,
265				    ptr + PCIR_HTMSI_ADDRESS_LO, 4);
266				printf("%08x", reg);
267			}
268			break;
269		case PCIM_HTCAP_DIRECT_ROUTE:
270			printf("direct route");
271			break;
272		case PCIM_HTCAP_VCSET:
273			printf("VC set");
274			break;
275		case PCIM_HTCAP_RETRY_MODE:
276			printf("retry mode");
277			break;
278		case PCIM_HTCAP_X86_ENCODING:
279			printf("X86 encoding");
280			break;
281		case PCIM_HTCAP_GEN3:
282			printf("Gen3");
283			break;
284		case PCIM_HTCAP_FLE:
285			printf("function-level extension");
286			break;
287		case PCIM_HTCAP_PM:
288			printf("power management");
289			break;
290		case PCIM_HTCAP_HIGH_NODE_COUNT:
291			printf("high node count");
292			break;
293		default:
294			printf("unknown %02x", command);
295			break;
296		}
297}
298
299static void
300cap_vendor(int fd, struct pci_conf *p, uint8_t ptr)
301{
302	uint8_t length;
303
304	length = read_config(fd, &p->pc_sel, ptr + PCIR_VENDOR_LENGTH, 1);
305	printf("vendor (length %d)", length);
306	if (p->pc_vendor == 0x8086) {
307		/* Intel */
308		uint8_t version;
309
310		version = read_config(fd, &p->pc_sel, ptr + PCIR_VENDOR_DATA,
311		    1);
312		printf(" Intel cap %d version %d", version >> 4, version & 0xf);
313		if (version >> 4 == 1 && length == 12) {
314			/* Feature Detection */
315			uint32_t fvec;
316			int comma;
317
318			comma = 0;
319			fvec = read_config(fd, &p->pc_sel, ptr +
320			    PCIR_VENDOR_DATA + 5, 4);
321			printf("\n\t\t features:");
322			if (fvec & (1 << 0)) {
323				printf(" AMT");
324				comma = 1;
325			}
326			fvec = read_config(fd, &p->pc_sel, ptr +
327			    PCIR_VENDOR_DATA + 1, 4);
328			if (fvec & (1 << 21)) {
329				printf("%s Quick Resume", comma ? "," : "");
330				comma = 1;
331			}
332			if (fvec & (1 << 18)) {
333				printf("%s SATA RAID-5", comma ? "," : "");
334				comma = 1;
335			}
336			if (fvec & (1 << 9)) {
337				printf("%s Mobile", comma ? "," : "");
338				comma = 1;
339			}
340			if (fvec & (1 << 7)) {
341				printf("%s 6 PCI-e x1 slots", comma ? "," : "");
342				comma = 1;
343			} else {
344				printf("%s 4 PCI-e x1 slots", comma ? "," : "");
345				comma = 1;
346			}
347			if (fvec & (1 << 5)) {
348				printf("%s SATA RAID-0/1/10", comma ? "," : "");
349				comma = 1;
350			}
351			if (fvec & (1 << 3))
352				printf(", SATA AHCI");
353		}
354	}
355}
356
357static void
358cap_debug(int fd, struct pci_conf *p, uint8_t ptr)
359{
360	uint16_t debug_port;
361
362	debug_port = read_config(fd, &p->pc_sel, ptr + PCIR_DEBUG_PORT, 2);
363	printf("EHCI Debug Port at offset 0x%x in map 0x%x", debug_port &
364	    PCIM_DEBUG_PORT_OFFSET, PCIR_BAR(debug_port >> 13));
365}
366
367static void
368cap_subvendor(int fd, struct pci_conf *p, uint8_t ptr)
369{
370	uint32_t id;
371	uint16_t ssid, ssvid;
372
373	id = read_config(fd, &p->pc_sel, ptr + PCIR_SUBVENDCAP_ID, 4);
374	ssid = id >> 16;
375	ssvid = id & 0xffff;
376	printf("PCI Bridge subvendor=0x%04x subdevice=0x%04x", ssvid, ssid);
377}
378
379static const char *
380cap_secdev_amdiommu_decode_vasize(uint32_t misc0)
381{
382	switch (misc0 & PCIM_AMDIOMMU_MISC0_VASIZE_MASK) {
383	case PCIM_AMDIOMMU_MISC0_VASIZE_32:
384		return ("32bit");
385	case PCIM_AMDIOMMU_MISC0_VASIZE_40:
386		return ("40bit");
387	case PCIM_AMDIOMMU_MISC0_VASIZE_48:
388		return ("48bit");
389	case PCIM_AMDIOMMU_MISC0_VASIZE_64:
390		return ("64bit");
391	default:
392		return ("unknown");
393	}
394}
395
396static const char *
397cap_secdev_amdiommu_decode_pasize(uint32_t misc0)
398{
399	switch (misc0 & PCIM_AMDIOMMU_MISC0_PASIZE_MASK) {
400	case PCIM_AMDIOMMU_MISC0_PASIZE_40:
401		return ("40bit");
402	case PCIM_AMDIOMMU_MISC0_PASIZE_48:
403		return ("48bit");
404	case PCIM_AMDIOMMU_MISC0_PASIZE_52:
405		return ("52bit");
406	default:
407		return ("unknown");
408	}
409}
410
411static const char *
412cap_secdev_amdiommu_decode_gvasize(uint32_t misc0)
413{
414	switch (misc0 & PCIM_AMDIOMMU_MISC0_GVASIZE_MASK) {
415	case PCIM_AMDIOMMU_MISC0_GVASIZE_48:
416		return ("48bit");
417	case PCIM_AMDIOMMU_MISC0_GVASIZE_57:
418		return ("57bit");
419	default:
420		return ("unknown");
421	}
422}
423
424static void
425cap_secdev(int fd, struct pci_conf *p, uint8_t ptr)
426{
427	uint32_t cap_h;
428	uint32_t cap_type, cap_rev;
429	uint32_t base_low, base_high;
430	uint32_t range;
431	uint32_t misc0, misc1;
432	const char *delim;
433
434	cap_h = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_CAP_HEADER, 4);
435	cap_type = cap_h & PCIM_AMDIOMMU_CAP_TYPE_MASK;
436	cap_rev = cap_h & PCIM_AMDIOMMU_CAP_REV_MASK;
437	if (cap_type != PCIM_AMDIOMMU_CAP_TYPE_VAL ||
438	    cap_rev != PCIM_AMDIOMMU_CAP_REV_VAL) {
439		printf("Secure Device Type=0x%1x Rev=0x%02x\n",
440		    cap_type >> 16, cap_rev >> 19);
441		return;
442	}
443	base_low = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_BASE_LOW,
444	    4);
445	base_high = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_BASE_HIGH,
446	    4);
447	printf("AMD IOMMU Base Capability Base=%#018jx/%sabled",
448	    (uintmax_t)(base_low & PCIM_AMDIOMMU_BASE_LOW_ADDRM) +
449	    ((uintmax_t)base_high << 32),
450	    (base_low & PCIM_AMDIOMMU_BASE_LOW_EN) != 0 ? "En" : "Dis");
451
452	delim = "\n\t\t";
453#define	PRINTCAP(bit, name)				\
454	if ((cap_h & PCIM_AMDIOMMU_CAP_ ##bit) != 0) {	\
455		printf("%s%s", delim, #name);		\
456		delim = ",";				\
457	}
458	PRINTCAP(CAPEXT, CapExt);
459	PRINTCAP(EFR, EFRSup);
460	PRINTCAP(NPCACHE, NpCache);
461	PRINTCAP(HTTUN, HtTunnel);
462	PRINTCAP(IOTLB, IotlbSup);
463#undef PRINTCAP
464
465	range = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_RANGE, 4);
466	printf("\n\t\tUnitId=%d", range & PCIM_AMDIOMMU_RANGE_UNITID_MASK);
467	if ((range & PCIM_AMDIOMMU_RANGE_RNGVALID) != 0) {
468		printf(" BusNum=%#06x FirstDev=%#06x LastDev=%#06x",
469		    (range & PCIM_AMDIOMMU_RANGE_BUSNUM_MASK) >> 8,
470		    (range & PCIM_AMDIOMMU_RANGE_FIRSTDEV_MASK) >> 16,
471		    (range & PCIM_AMDIOMMU_RANGE_LASTDEV_MASK) >> 24);
472	}
473
474	misc0 = read_config(fd, &p->pc_sel, ptr + PCIR_AMDIOMMU_MISC0, 4);
475	printf("\n\t\tMsiNum=%d MsiNumPPR=%d HtAtsResv=%d",
476	    misc0 & PCIM_AMDIOMMU_MISC0_MSINUM_MASK,
477	    (misc0 & PCIM_AMDIOMMU_MISC0_MSINUMPPR_MASK) >> 27,
478	    (misc0 & PCIM_AMDIOMMU_MISC0_HTATSRESV) != 0);
479	if ((cap_h & PCIM_AMDIOMMU_CAP_CAPEXT) != 0) {
480		misc1 = read_config(fd, &p->pc_sel,
481		    ptr + PCIR_AMDIOMMU_MISC1, 4);
482		printf(" MsiNumGA=%d",
483		    misc1 & PCIM_AMDIOMMU_MISC1_MSINUMGA_MASK);
484	}
485	printf("\n\t\tVAsize=%s PAsize=%s GVAsize=%s",
486	    cap_secdev_amdiommu_decode_vasize(misc0),
487	    cap_secdev_amdiommu_decode_pasize(misc0),
488	    cap_secdev_amdiommu_decode_gvasize(misc0));
489}
490
491#define	MAX_PAYLOAD(field)		(128 << (field))
492
493static const char *
494link_speed_string(uint8_t speed)
495{
496
497	switch (speed) {
498	case 1:
499		return ("2.5");
500	case 2:
501		return ("5.0");
502	case 3:
503		return ("8.0");
504	case 4:
505		return ("16.0");
506	case 5:
507		return ("32.0");
508	case 6:
509		return ("64.0");
510	default:
511		return ("undef");
512	}
513}
514
515static const char *
516max_read_string(u_int max_read)
517{
518
519	switch (max_read) {
520	case 0x0:
521		return ("128");
522	case 0x1:
523		return ("256");
524	case 0x2:
525		return ("512");
526	case 0x3:
527		return ("1024");
528	case 0x4:
529		return ("2048");
530	case 0x5:
531		return ("4096");
532	default:
533		return ("undef");
534	}
535}
536
537static const char *
538aspm_string(uint8_t aspm)
539{
540
541	switch (aspm) {
542	case 1:
543		return ("L0s");
544	case 2:
545		return ("L1");
546	case 3:
547		return ("L0s/L1");
548	default:
549		return ("disabled");
550	}
551}
552
553static int
554slot_power(uint32_t cap)
555{
556	int mwatts;
557
558	mwatts = (cap & PCIEM_SLOT_CAP_SPLV) >> 7;
559	switch (cap & PCIEM_SLOT_CAP_SPLS) {
560	case 0x0:
561		mwatts *= 1000;
562		break;
563	case 0x1:
564		mwatts *= 100;
565		break;
566	case 0x2:
567		mwatts *= 10;
568		break;
569	default:
570		break;
571	}
572	return (mwatts);
573}
574
575static void
576cap_express(int fd, struct pci_conf *p, uint8_t ptr)
577{
578	uint32_t cap;
579	uint16_t ctl, flags, sta;
580	unsigned int version;
581
582	flags = read_config(fd, &p->pc_sel, ptr + PCIER_FLAGS, 2);
583	version = flags & PCIEM_FLAGS_VERSION;
584	printf("PCI-Express %u ", version);
585	switch (flags & PCIEM_FLAGS_TYPE) {
586	case PCIEM_TYPE_ENDPOINT:
587		printf("endpoint");
588		break;
589	case PCIEM_TYPE_LEGACY_ENDPOINT:
590		printf("legacy endpoint");
591		break;
592	case PCIEM_TYPE_ROOT_PORT:
593		printf("root port");
594		break;
595	case PCIEM_TYPE_UPSTREAM_PORT:
596		printf("upstream port");
597		break;
598	case PCIEM_TYPE_DOWNSTREAM_PORT:
599		printf("downstream port");
600		break;
601	case PCIEM_TYPE_PCI_BRIDGE:
602		printf("PCI bridge");
603		break;
604	case PCIEM_TYPE_PCIE_BRIDGE:
605		printf("PCI to PCIe bridge");
606		break;
607	case PCIEM_TYPE_ROOT_INT_EP:
608		printf("root endpoint");
609		break;
610	case PCIEM_TYPE_ROOT_EC:
611		printf("event collector");
612		break;
613	default:
614		printf("type %d", (flags & PCIEM_FLAGS_TYPE) >> 4);
615		break;
616	}
617	if (flags & PCIEM_FLAGS_IRQ)
618		printf(" MSI %d", (flags & PCIEM_FLAGS_IRQ) >> 9);
619	cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP, 4);
620	ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL, 2);
621	printf(" max data %d(%d)",
622	    MAX_PAYLOAD((ctl & PCIEM_CTL_MAX_PAYLOAD) >> 5),
623	    MAX_PAYLOAD(cap & PCIEM_CAP_MAX_PAYLOAD));
624	if ((cap & PCIEM_CAP_FLR) != 0)
625		printf(" FLR");
626	if (ctl & PCIEM_CTL_RELAXED_ORD_ENABLE)
627		printf(" RO");
628	if (ctl & PCIEM_CTL_NOSNOOP_ENABLE)
629		printf(" NS");
630	if (version >= 2) {
631		cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP2, 4);
632		if ((cap & PCIEM_CAP2_ARI) != 0) {
633			ctl = read_config(fd, &p->pc_sel,
634			    ptr + PCIER_DEVICE_CTL2, 4);
635			printf(" ARI %s",
636			    (ctl & PCIEM_CTL2_ARI) ? "enabled" : "disabled");
637		}
638	}
639	printf("\n                 max read %s", max_read_string((ctl &
640	    PCIEM_CTL_MAX_READ_REQUEST) >> 12));
641	cap = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CAP, 4);
642	sta = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_STA, 2);
643	if (cap == 0 && sta == 0)
644		return;
645	printf("\n                ");
646	printf(" link x%d(x%d)", (sta & PCIEM_LINK_STA_WIDTH) >> 4,
647	    (cap & PCIEM_LINK_CAP_MAX_WIDTH) >> 4);
648	if ((cap & PCIEM_LINK_CAP_MAX_WIDTH) != 0) {
649		printf(" speed %s(%s)", (sta & PCIEM_LINK_STA_WIDTH) == 0 ?
650		    "0.0" : link_speed_string(sta & PCIEM_LINK_STA_SPEED),
651	    	    link_speed_string(cap & PCIEM_LINK_CAP_MAX_SPEED));
652	}
653	if ((cap & PCIEM_LINK_CAP_ASPM) != 0) {
654		ctl = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CTL, 2);
655		printf(" ASPM %s(%s)", aspm_string(ctl & PCIEM_LINK_CTL_ASPMC),
656		    aspm_string((cap & PCIEM_LINK_CAP_ASPM) >> 10));
657	}
658	if ((cap & PCIEM_LINK_CAP_CLOCK_PM) != 0) {
659		ctl = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CTL, 2);
660		printf(" ClockPM %s", (ctl & PCIEM_LINK_CTL_ECPM) ?
661		    "enabled" : "disabled");
662	}
663	if (!(flags & PCIEM_FLAGS_SLOT))
664		return;
665	cap = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_CAP, 4);
666	sta = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_STA, 2);
667	ctl = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_CTL, 2);
668	printf("\n                ");
669	printf(" slot %d", (cap & PCIEM_SLOT_CAP_PSN) >> 19);
670	printf(" power limit %d mW", slot_power(cap));
671	if (cap & PCIEM_SLOT_CAP_HPC)
672		printf(" HotPlug(%s)", sta & PCIEM_SLOT_STA_PDS ? "present" :
673		    "empty");
674	if (cap & PCIEM_SLOT_CAP_HPS)
675		printf(" surprise");
676	if (cap & PCIEM_SLOT_CAP_APB)
677		printf(" Attn Button");
678	if (cap & PCIEM_SLOT_CAP_PCP)
679		printf(" PC(%s)", ctl & PCIEM_SLOT_CTL_PCC ? "off" : "on");
680	if (cap & PCIEM_SLOT_CAP_MRLSP)
681		printf(" MRL(%s)", sta & PCIEM_SLOT_STA_MRLSS ? "open" :
682		    "closed");
683	if (cap & PCIEM_SLOT_CAP_EIP)
684		printf(" EI(%s)", sta & PCIEM_SLOT_STA_EIS ? "engaged" :
685		    "disengaged");
686}
687
688static void
689cap_msix(int fd, struct pci_conf *p, uint8_t ptr)
690{
691	uint32_t pba_offset, table_offset, val;
692	int msgnum, pba_bar, table_bar;
693	uint16_t ctrl;
694
695	ctrl = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_CTRL, 2);
696	msgnum = (ctrl & PCIM_MSIXCTRL_TABLE_SIZE) + 1;
697
698	val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_TABLE, 4);
699	table_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
700	table_offset = val & ~PCIM_MSIX_BIR_MASK;
701
702	val = read_config(fd, &p->pc_sel, ptr + PCIR_MSIX_PBA, 4);
703	pba_bar = PCIR_BAR(val & PCIM_MSIX_BIR_MASK);
704	pba_offset = val & ~PCIM_MSIX_BIR_MASK;
705
706	printf("MSI-X supports %d message%s%s\n", msgnum,
707	    (msgnum == 1) ? "" : "s",
708	    (ctrl & PCIM_MSIXCTRL_MSIX_ENABLE) ? ", enabled" : "");
709
710	printf("                 ");
711	printf("Table in map 0x%x[0x%x], PBA in map 0x%x[0x%x]",
712	    table_bar, table_offset, pba_bar, pba_offset);
713}
714
715static void
716cap_sata(int fd __unused, struct pci_conf *p __unused, uint8_t ptr __unused)
717{
718
719	printf("SATA Index-Data Pair");
720}
721
722static void
723cap_pciaf(int fd, struct pci_conf *p, uint8_t ptr)
724{
725	uint8_t cap;
726
727	cap = read_config(fd, &p->pc_sel, ptr + PCIR_PCIAF_CAP, 1);
728	printf("PCI Advanced Features:%s%s",
729	    cap & PCIM_PCIAFCAP_FLR ? " FLR" : "",
730	    cap & PCIM_PCIAFCAP_TP  ? " TP"  : "");
731}
732
733static const char *
734ea_bei_to_name(int bei)
735{
736	static const char *barstr[] = {
737		"BAR0", "BAR1", "BAR2", "BAR3", "BAR4", "BAR5"
738	};
739	static const char *vfbarstr[] = {
740		"VFBAR0", "VFBAR1", "VFBAR2", "VFBAR3", "VFBAR4", "VFBAR5"
741	};
742
743	if ((bei >= PCIM_EA_BEI_BAR_0) && (bei <= PCIM_EA_BEI_BAR_5))
744		return (barstr[bei - PCIM_EA_BEI_BAR_0]);
745	if ((bei >= PCIM_EA_BEI_VF_BAR_0) && (bei <= PCIM_EA_BEI_VF_BAR_5))
746		return (vfbarstr[bei - PCIM_EA_BEI_VF_BAR_0]);
747
748	switch (bei) {
749	case PCIM_EA_BEI_BRIDGE:
750		return "BRIDGE";
751	case PCIM_EA_BEI_ENI:
752		return "ENI";
753	case PCIM_EA_BEI_ROM:
754		return "ROM";
755	case PCIM_EA_BEI_RESERVED:
756	default:
757		return "RSVD";
758	}
759}
760
761static const char *
762ea_prop_to_name(uint8_t prop)
763{
764
765	switch (prop) {
766	case PCIM_EA_P_MEM:
767		return "Non-Prefetchable Memory";
768	case PCIM_EA_P_MEM_PREFETCH:
769		return "Prefetchable Memory";
770	case PCIM_EA_P_IO:
771		return "I/O Space";
772	case PCIM_EA_P_VF_MEM_PREFETCH:
773		return "VF Prefetchable Memory";
774	case PCIM_EA_P_VF_MEM:
775		return "VF Non-Prefetchable Memory";
776	case PCIM_EA_P_BRIDGE_MEM:
777		return "Bridge Non-Prefetchable Memory";
778	case PCIM_EA_P_BRIDGE_MEM_PREFETCH:
779		return "Bridge Prefetchable Memory";
780	case PCIM_EA_P_BRIDGE_IO:
781		return "Bridge I/O Space";
782	case PCIM_EA_P_MEM_RESERVED:
783		return "Reserved Memory";
784	case PCIM_EA_P_IO_RESERVED:
785		return "Reserved I/O Space";
786	case PCIM_EA_P_UNAVAILABLE:
787		return "Unavailable";
788	default:
789		return "Reserved";
790	}
791}
792
793static void
794cap_ea(int fd, struct pci_conf *p, uint8_t ptr)
795{
796	int num_ent;
797	int a, b;
798	uint32_t bei;
799	uint32_t val;
800	int ent_size;
801	uint32_t dw[4];
802	uint32_t flags, flags_pp, flags_sp;
803	uint64_t base, max_offset;
804	uint8_t fixed_sub_bus_nr, fixed_sec_bus_nr;
805
806	/* Determine the number of entries */
807	num_ent = read_config(fd, &p->pc_sel, ptr + PCIR_EA_NUM_ENT, 2);
808	num_ent &= PCIM_EA_NUM_ENT_MASK;
809
810	printf("PCI Enhanced Allocation (%d entries)", num_ent);
811
812	/* Find the first entry to care of */
813	ptr += PCIR_EA_FIRST_ENT;
814
815	/* Print BUS numbers for bridges */
816	if ((p->pc_hdr & PCIM_HDRTYPE) == PCIM_HDRTYPE_BRIDGE) {
817		val = read_config(fd, &p->pc_sel, ptr, 4);
818
819		fixed_sec_bus_nr = PCIM_EA_SEC_NR(val);
820		fixed_sub_bus_nr = PCIM_EA_SUB_NR(val);
821
822		printf("\n\t\t BRIDGE, sec bus [%d], sub bus [%d]",
823		    fixed_sec_bus_nr, fixed_sub_bus_nr);
824		ptr += 4;
825	}
826
827	for (a = 0; a < num_ent; a++) {
828		/* Read a number of dwords in the entry */
829		val = read_config(fd, &p->pc_sel, ptr, 4);
830		ptr += 4;
831		ent_size = (val & PCIM_EA_ES);
832
833		for (b = 0; b < ent_size; b++) {
834			dw[b] = read_config(fd, &p->pc_sel, ptr, 4);
835			ptr += 4;
836		}
837
838		flags = val;
839		flags_pp = (flags & PCIM_EA_PP) >> PCIM_EA_PP_OFFSET;
840		flags_sp = (flags & PCIM_EA_SP) >> PCIM_EA_SP_OFFSET;
841		bei = (PCIM_EA_BEI & val) >> PCIM_EA_BEI_OFFSET;
842
843		base = dw[0] & PCIM_EA_FIELD_MASK;
844		max_offset = dw[1] | ~PCIM_EA_FIELD_MASK;
845		b = 2;
846		if (((dw[0] & PCIM_EA_IS_64) != 0) && (b < ent_size)) {
847			base |= (uint64_t)dw[b] << 32UL;
848			b++;
849		}
850		if (((dw[1] & PCIM_EA_IS_64) != 0)
851			&& (b < ent_size)) {
852			max_offset |= (uint64_t)dw[b] << 32UL;
853			b++;
854		}
855
856		printf("\n\t\t [%d] %s, %s, %s, base [0x%jx], size [0x%jx]"
857		    "\n\t\t\tPrimary properties [0x%x] (%s)"
858		    "\n\t\t\tSecondary properties [0x%x] (%s)",
859		    bei, ea_bei_to_name(bei),
860		    (flags & PCIM_EA_ENABLE ? "Enabled" : "Disabled"),
861		    (flags & PCIM_EA_WRITABLE ? "Writable" : "Read-only"),
862		    (uintmax_t)base, (uintmax_t)(max_offset + 1),
863		    flags_pp, ea_prop_to_name(flags_pp),
864		    flags_sp, ea_prop_to_name(flags_sp));
865	}
866}
867
868void
869list_caps(int fd, struct pci_conf *p, int level)
870{
871	int express;
872	uint16_t sta;
873	uint8_t ptr, cap;
874
875	/* Are capabilities present for this device? */
876	sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2);
877	if (!(sta & PCIM_STATUS_CAPPRESENT))
878		return;
879
880	cap_level = level;
881
882	switch (p->pc_hdr & PCIM_HDRTYPE) {
883	case PCIM_HDRTYPE_NORMAL:
884	case PCIM_HDRTYPE_BRIDGE:
885		ptr = PCIR_CAP_PTR;
886		break;
887	case PCIM_HDRTYPE_CARDBUS:
888		ptr = PCIR_CAP_PTR_2;
889		break;
890	default:
891		errx(1, "list_caps: bad header type");
892	}
893
894	/* Walk the capability list. */
895	express = 0;
896	ptr = read_config(fd, &p->pc_sel, ptr, 1);
897	while (ptr != 0 && ptr != 0xff) {
898		cap = read_config(fd, &p->pc_sel, ptr + PCICAP_ID, 1);
899		printf("    cap %02x[%02x] = ", cap, ptr);
900		switch (cap) {
901		case PCIY_PMG:
902			cap_power(fd, p, ptr);
903			break;
904		case PCIY_AGP:
905			cap_agp(fd, p, ptr);
906			break;
907		case PCIY_VPD:
908			cap_vpd(fd, p, ptr);
909			break;
910		case PCIY_MSI:
911			cap_msi(fd, p, ptr);
912			break;
913		case PCIY_PCIX:
914			cap_pcix(fd, p, ptr);
915			break;
916		case PCIY_HT:
917			cap_ht(fd, p, ptr);
918			break;
919		case PCIY_VENDOR:
920			cap_vendor(fd, p, ptr);
921			break;
922		case PCIY_DEBUG:
923			cap_debug(fd, p, ptr);
924			break;
925		case PCIY_SUBVENDOR:
926			cap_subvendor(fd, p, ptr);
927			break;
928		case PCIY_SECDEV:
929			cap_secdev(fd, p, ptr);
930			break;
931		case PCIY_EXPRESS:
932			express = 1;
933			cap_express(fd, p, ptr);
934			break;
935		case PCIY_MSIX:
936			cap_msix(fd, p, ptr);
937			break;
938		case PCIY_SATA:
939			cap_sata(fd, p, ptr);
940			break;
941		case PCIY_PCIAF:
942			cap_pciaf(fd, p, ptr);
943			break;
944		case PCIY_EA:
945			cap_ea(fd, p, ptr);
946			break;
947		default:
948			printf("unknown");
949			break;
950		}
951		printf("\n");
952		ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1);
953	}
954
955	if (express)
956		list_ecaps(fd, p);
957}
958
959/* From <sys/systm.h>. */
960static __inline uint32_t
961bitcount32(uint32_t x)
962{
963
964	x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1);
965	x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2);
966	x = (x + (x >> 4)) & 0x0f0f0f0f;
967	x = (x + (x >> 8));
968	x = (x + (x >> 16)) & 0x000000ff;
969	return (x);
970}
971
972static void
973ecap_aer(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
974{
975	uint32_t sta, mask;
976
977	printf("AER %d", ver);
978	if (ver < 1) {
979		printf("\n");
980		return;
981	}
982	sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_STATUS, 4);
983	mask = read_config(fd, &p->pc_sel, ptr + PCIR_AER_UC_SEVERITY, 4);
984	printf(" %d fatal", bitcount32(sta & mask));
985	printf(" %d non-fatal", bitcount32(sta & ~mask));
986	sta = read_config(fd, &p->pc_sel, ptr + PCIR_AER_COR_STATUS, 4);
987	printf(" %d corrected\n", bitcount32(sta));
988}
989
990static void
991ecap_vc(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
992{
993	uint32_t cap1;
994
995	printf("VC %d", ver);
996	if (ver < 1) {
997		printf("\n");
998		return;
999	}
1000	cap1 = read_config(fd, &p->pc_sel, ptr + PCIR_VC_CAP1, 4);
1001	printf(" max VC%d", cap1 & PCIM_VC_CAP1_EXT_COUNT);
1002	if ((cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) != 0)
1003		printf(" lowpri VC0-VC%d",
1004		    (cap1 & PCIM_VC_CAP1_LOWPRI_EXT_COUNT) >> 4);
1005	printf("\n");
1006}
1007
1008static void
1009ecap_sernum(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1010{
1011	uint32_t high, low;
1012
1013	printf("Serial %d", ver);
1014	if (ver < 1) {
1015		printf("\n");
1016		return;
1017	}
1018	low = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_LOW, 4);
1019	high = read_config(fd, &p->pc_sel, ptr + PCIR_SERIAL_HIGH, 4);
1020	printf(" %08x%08x\n", high, low);
1021}
1022
1023static void
1024ecap_vendor(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1025{
1026	uint32_t val, hdr;
1027	uint16_t nextptr, len;
1028	int i;
1029
1030	val = read_config(fd, &p->pc_sel, ptr, 4);
1031	nextptr = PCI_EXTCAP_NEXTPTR(val);
1032	hdr = read_config(fd, &p->pc_sel, ptr + PCIR_VSEC_HEADER, 4);
1033	len = PCIR_VSEC_LENGTH(hdr);
1034	if (len == 0) {
1035		if (nextptr == 0)
1036			nextptr = 0x1000;
1037		len = nextptr - ptr;
1038	}
1039
1040	printf("Vendor [%d] ID %04x Rev %d Length %d\n", ver,
1041	    PCIR_VSEC_ID(hdr), PCIR_VSEC_REV(hdr), len);
1042	if ((ver < 1) || (cap_level <= 1))
1043		return;
1044	for (i = 0; i < len; i += 4) {
1045		val = read_config(fd, &p->pc_sel, ptr + i, 4);
1046		if ((i % 16) == 0)
1047			printf("                 ");
1048		printf("%02x %02x %02x %02x", val & 0xff, (val >> 8) & 0xff,
1049		    (val >> 16) & 0xff, (val >> 24) & 0xff);
1050		if ((((i + 4) % 16) == 0 ) || ((i + 4) >= len))
1051			printf("\n");
1052		else
1053			printf(" ");
1054	}
1055}
1056
1057static void
1058ecap_sec_pcie(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1059{
1060	uint32_t val;
1061
1062	printf("PCIe Sec %d", ver);
1063	if (ver < 1) {
1064		printf("\n");
1065		return;
1066	}
1067	val = read_config(fd, &p->pc_sel, ptr + 8, 4);
1068	printf(" lane errors %#x\n", val);
1069}
1070
1071static const char *
1072check_enabled(int value)
1073{
1074
1075	return (value ? "enabled" : "disabled");
1076}
1077
1078static void
1079ecap_sriov(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1080{
1081	const char *comma, *enabled;
1082	uint16_t iov_ctl, total_vfs, num_vfs, vf_offset, vf_stride, vf_did;
1083	uint32_t page_caps, page_size, page_shift, size;
1084	int i;
1085
1086	printf("SR-IOV %d ", ver);
1087
1088	iov_ctl = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_CTL, 2);
1089	printf("IOV %s, Memory Space %s, ARI %s\n",
1090	    check_enabled(iov_ctl & PCIM_SRIOV_VF_EN),
1091	    check_enabled(iov_ctl & PCIM_SRIOV_VF_MSE),
1092	    check_enabled(iov_ctl & PCIM_SRIOV_ARI_EN));
1093
1094	total_vfs = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_TOTAL_VFS, 2);
1095	num_vfs = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_NUM_VFS, 2);
1096	printf("                     ");
1097	printf("%d VFs configured out of %d supported\n", num_vfs, total_vfs);
1098
1099	vf_offset = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_VF_OFF, 2);
1100	vf_stride = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_VF_STRIDE, 2);
1101	printf("                     ");
1102	printf("First VF RID Offset 0x%04x, VF RID Stride 0x%04x\n", vf_offset,
1103	    vf_stride);
1104
1105	vf_did = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_VF_DID, 2);
1106	printf("                     VF Device ID 0x%04x\n", vf_did);
1107
1108	page_caps = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_PAGE_CAP, 4);
1109	page_size = read_config(fd, &p->pc_sel, ptr + PCIR_SRIOV_PAGE_SIZE, 4);
1110	printf("                     ");
1111	printf("Page Sizes: ");
1112	comma = "";
1113	while (page_caps != 0) {
1114		page_shift = ffs(page_caps) - 1;
1115
1116		if (page_caps & page_size)
1117			enabled = " (enabled)";
1118		else
1119			enabled = "";
1120
1121		size = (1 << (page_shift + PCI_SRIOV_BASE_PAGE_SHIFT));
1122		printf("%s%d%s", comma, size, enabled);
1123		comma = ", ";
1124
1125		page_caps &= ~(1 << page_shift);
1126	}
1127	printf("\n");
1128
1129	for (i = 0; i <= PCIR_MAX_BAR_0; i++)
1130		print_bar(fd, p, "iov bar  ", ptr + PCIR_SRIOV_BAR(i));
1131}
1132
1133static const char *
1134check_avail_and_state(u_int cap, u_int capbit, u_int ctl, u_int ctlbit)
1135{
1136
1137	if (cap & capbit)
1138		return (ctl & ctlbit ? "enabled" : "disabled");
1139	else
1140		return "unavailable";
1141}
1142
1143static void
1144ecap_acs(int fd, struct pci_conf *p, uint16_t ptr, uint8_t ver)
1145{
1146	uint16_t acs_cap, acs_ctl;
1147	static const char *const acc[] = { "access enabled", "blocking enabled",
1148		"redirect enabled", "reserved" };
1149
1150	printf("ACS %d ", ver);
1151	if (ver != 1) {
1152		printf("\n");
1153		return;
1154	}
1155
1156#define	CHECK_AVAIL_STATE(bit) \
1157	check_avail_and_state(acs_cap, bit, acs_ctl, bit##_ENABLE)
1158
1159	acs_cap = read_config(fd, &p->pc_sel, ptr + PCIR_ACS_CAP, 2);
1160	acs_ctl = read_config(fd, &p->pc_sel, ptr + PCIR_ACS_CTL, 2);
1161	printf("Source Validation %s, Translation Blocking %s\n",
1162	    CHECK_AVAIL_STATE(PCIM_ACS_SOURCE_VALIDATION),
1163	    CHECK_AVAIL_STATE(PCIM_ACS_TRANSLATION_BLOCKING));
1164
1165	printf("                     ");
1166	printf("P2P Req Redirect %s, P2P Cmpl Redirect %s\n",
1167	    CHECK_AVAIL_STATE(PCIM_ACS_P2P_REQ_REDIRECT),
1168	    CHECK_AVAIL_STATE(PCIM_ACS_P2P_CMP_REDIRECT));
1169	printf("                     ");
1170	printf("P2P Upstream Forwarding %s, P2P Egress Control %s\n",
1171	    CHECK_AVAIL_STATE(PCIM_ACS_P2P_UPSTREAM_FORWARDING),
1172	    CHECK_AVAIL_STATE(PCIM_ACS_P2P_EGRESS_CTL));
1173	printf("                     ");
1174	printf("P2P Direct Translated %s, Enhanced Capability %s\n",
1175	    CHECK_AVAIL_STATE(PCIM_ACS_P2P_DIRECT_TRANSLATED),
1176	    acs_ctl & PCIM_ACS_ENHANCED_CAP ? "available" : "unavailable");
1177#undef	CHECK_AVAIL_STATE
1178
1179	if (acs_cap & PCIM_ACS_ENHANCED_CAP) {
1180		printf("                     ");
1181		printf("I/O Req Blocking %s, Unclaimed Req Redirect Control %s\n",
1182		    check_enabled(acs_ctl & PCIM_ACS_IO_REQ_BLOCKING_ENABLE),
1183		    check_enabled(acs_ctl & PCIM_ACS_UNCLAIMED_REQ_REDIRECT_CTL));
1184		printf("                     ");
1185		printf("DSP BAR %s, USP BAR %s\n",
1186		    acc[(acs_cap & PCIM_ACS_DSP_MEM_TGT_ACC_CTL) >> 8],
1187		    acc[(acs_cap & PCIM_ACS_USP_MEM_TGT_ACC_CTL) >> 10]);
1188	}
1189}
1190
1191static struct {
1192	uint16_t id;
1193	const char *name;
1194} ecap_names[] = {
1195	{ PCIZ_AER, "AER" },
1196	{ PCIZ_VC, "Virtual Channel" },
1197	{ PCIZ_SERNUM, "Device Serial Number" },
1198	{ PCIZ_PWRBDGT, "Power Budgeting" },
1199	{ PCIZ_RCLINK_DCL, "Root Complex Link Declaration" },
1200	{ PCIZ_RCLINK_CTL, "Root Complex Internal Link Control" },
1201	{ PCIZ_RCEC_ASSOC, "Root Complex Event Collector ASsociation" },
1202	{ PCIZ_MFVC, "MFVC" },
1203	{ PCIZ_VC2, "Virtual Channel 2" },
1204	{ PCIZ_RCRB, "RCRB" },
1205	{ PCIZ_CAC, "Configuration Access Correction" },
1206	{ PCIZ_ACS, "ACS" },
1207	{ PCIZ_ARI, "ARI" },
1208	{ PCIZ_ATS, "ATS" },
1209	{ PCIZ_SRIOV, "SRIOV" },
1210	{ PCIZ_MRIOV, "MRIOV" },
1211	{ PCIZ_MULTICAST, "Multicast" },
1212	{ PCIZ_PAGE_REQ, "Page Page Request" },
1213	{ PCIZ_AMD, "AMD proprietary "},
1214	{ PCIZ_RESIZE_BAR, "Resizable BAR" },
1215	{ PCIZ_DPA, "DPA" },
1216	{ PCIZ_TPH_REQ, "TPH Requester" },
1217	{ PCIZ_LTR, "LTR" },
1218	{ PCIZ_SEC_PCIE, "Secondary PCI Express" },
1219	{ PCIZ_PMUX, "Protocol Multiplexing" },
1220	{ PCIZ_PASID, "Process Address Space ID" },
1221	{ PCIZ_LN_REQ, "LN Requester" },
1222	{ PCIZ_DPC, "Downstream Port Containment" },
1223	{ PCIZ_L1PM, "L1 PM Substates" },
1224	{ PCIZ_PTM, "Precision Time Measurement" },
1225	{ PCIZ_M_PCIE, "PCIe over M-PHY" },
1226	{ PCIZ_FRS, "FRS Queuing" },
1227	{ PCIZ_RTR, "Readiness Time Reporting" },
1228	{ PCIZ_DVSEC, "Designated Vendor-Specific" },
1229	{ PCIZ_VF_REBAR, "VF Resizable BAR" },
1230	{ PCIZ_DLNK, "Data Link Feature" },
1231	{ PCIZ_16GT, "Physical Layer 16.0 GT/s" },
1232	{ PCIZ_LMR, "Lane Margining at Receiver" },
1233	{ PCIZ_HIER_ID, "Hierarchy ID" },
1234	{ PCIZ_NPEM, "Native PCIe Enclosure Management" },
1235	{ PCIZ_PL32, "Physical Layer 32.0 GT/s" },
1236	{ PCIZ_AP, "Alternate Protocol" },
1237	{ PCIZ_SFI, "System Firmware Intermediary" },
1238	{ 0, NULL }
1239};
1240
1241static void
1242list_ecaps(int fd, struct pci_conf *p)
1243{
1244	const char *name;
1245	uint32_t ecap;
1246	uint16_t ptr;
1247	int i;
1248
1249	ptr = PCIR_EXTCAP;
1250	ecap = read_config(fd, &p->pc_sel, ptr, 4);
1251	if (ecap == 0xffffffff || ecap == 0)
1252		return;
1253	for (;;) {
1254		printf("    ecap %04x[%03x] = ", PCI_EXTCAP_ID(ecap), ptr);
1255		switch (PCI_EXTCAP_ID(ecap)) {
1256		case PCIZ_AER:
1257			ecap_aer(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1258			break;
1259		case PCIZ_VC:
1260			ecap_vc(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1261			break;
1262		case PCIZ_SERNUM:
1263			ecap_sernum(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1264			break;
1265		case PCIZ_VENDOR:
1266			ecap_vendor(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1267			break;
1268		case PCIZ_SEC_PCIE:
1269			ecap_sec_pcie(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1270			break;
1271		case PCIZ_SRIOV:
1272			ecap_sriov(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1273			break;
1274		case PCIZ_ACS:
1275			ecap_acs(fd, p, ptr, PCI_EXTCAP_VER(ecap));
1276			break;
1277		default:
1278			name = "unknown";
1279			for (i = 0; ecap_names[i].name != NULL; i++)
1280				if (ecap_names[i].id == PCI_EXTCAP_ID(ecap)) {
1281					name = ecap_names[i].name;
1282					break;
1283				}
1284			printf("%s %d\n", name, PCI_EXTCAP_VER(ecap));
1285			break;
1286		}
1287		ptr = PCI_EXTCAP_NEXTPTR(ecap);
1288		if (ptr == 0)
1289			break;
1290		ecap = read_config(fd, &p->pc_sel, ptr, 4);
1291	}
1292}
1293
1294/* Find offset of a specific capability.  Returns 0 on failure. */
1295uint8_t
1296pci_find_cap(int fd, struct pci_conf *p, uint8_t id)
1297{
1298	uint16_t sta;
1299	uint8_t ptr, cap;
1300
1301	/* Are capabilities present for this device? */
1302	sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2);
1303	if (!(sta & PCIM_STATUS_CAPPRESENT))
1304		return (0);
1305
1306	switch (p->pc_hdr & PCIM_HDRTYPE) {
1307	case PCIM_HDRTYPE_NORMAL:
1308	case PCIM_HDRTYPE_BRIDGE:
1309		ptr = PCIR_CAP_PTR;
1310		break;
1311	case PCIM_HDRTYPE_CARDBUS:
1312		ptr = PCIR_CAP_PTR_2;
1313		break;
1314	default:
1315		return (0);
1316	}
1317
1318	ptr = read_config(fd, &p->pc_sel, ptr, 1);
1319	while (ptr != 0 && ptr != 0xff) {
1320		cap = read_config(fd, &p->pc_sel, ptr + PCICAP_ID, 1);
1321		if (cap == id)
1322			return (ptr);
1323		ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1);
1324	}
1325	return (0);
1326}
1327
1328/* Find offset of a specific extended capability.  Returns 0 on failure. */
1329uint16_t
1330pcie_find_cap(int fd, struct pci_conf *p, uint16_t id)
1331{
1332	uint32_t ecap;
1333	uint16_t ptr;
1334
1335	ptr = PCIR_EXTCAP;
1336	ecap = read_config(fd, &p->pc_sel, ptr, 4);
1337	if (ecap == 0xffffffff || ecap == 0)
1338		return (0);
1339	for (;;) {
1340		if (PCI_EXTCAP_ID(ecap) == id)
1341			return (ptr);
1342		ptr = PCI_EXTCAP_NEXTPTR(ecap);
1343		if (ptr == 0)
1344			break;
1345		ecap = read_config(fd, &p->pc_sel, ptr, 4);
1346	}
1347	return (0);
1348}
1349