GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/pcidump/pcidump.c Lines: 0 430 0.0 %
Date: 2017-11-07 Branches: 0 265 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pcidump.c,v 1.46 2017/08/31 12:03:02 otto Exp $	*/
2
3
/*
4
 * Copyright (c) 2006, 2007 David Gwynne <loki@animata.net>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/ioctl.h>
21
#include <sys/pciio.h>
22
23
#include <stdio.h>	/* need NULL for dev/pci/ headers */
24
25
#include <dev/pci/pcireg.h>
26
#include <dev/pci/pcidevs.h>
27
#include <dev/pci/pcidevs_data.h>
28
29
#include <err.h>
30
#include <errno.h>
31
#include <fcntl.h>
32
#include <paths.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <unistd.h>
36
#include <limits.h>
37
38
#define PCIDEV	"/dev/pci"
39
40
#ifndef nitems
41
#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
42
#endif
43
44
__dead void usage(void);
45
void scanpcidomain(void);
46
int probe(int, int, int);
47
void dump(int, int, int);
48
void hexdump(int, int, int, int);
49
const char *str2busdevfunc(const char *, int *, int *, int *);
50
int pci_nfuncs(int, int);
51
int pci_read(int, int, int, u_int32_t, u_int32_t *);
52
int pci_readmask(int, int, int, u_int32_t, u_int32_t *);
53
void dump_caplist(int, int, int, u_int8_t);
54
void dump_pci_powerstate(int, int, int, uint8_t);
55
void dump_pcie_linkspeed(int, int, int, uint8_t);
56
void print_pcie_ls(uint8_t);
57
int dump_rom(int, int, int);
58
int dump_vga_bios(void);
59
60
void	dump_type0(int bus, int dev, int func);
61
void	dump_type1(int bus, int dev, int func);
62
void	dump_type2(int bus, int dev, int func);
63
64
__dead void
65
usage(void)
66
{
67
	extern char *__progname;
68
69
	fprintf(stderr,
70
	    "usage: %s [-v] [-x | -xx | -xxx] [-d pcidev] [bus:dev:func]\n"
71
	    "       %s -r file [-d pcidev] bus:dev:func\n",
72
	    __progname, __progname);
73
	exit(1);
74
}
75
76
int pcifd;
77
int romfd;
78
int verbose = 0;
79
int hex = 0;
80
int size = 64;
81
82
const char *pci_capnames[] = {
83
	"Reserved",
84
	"Power Management",
85
	"AGP",
86
	"Vital Product Data (VPD)",
87
	"Slot Identification",
88
	"Message Signalled Interrupts (MSI)",
89
	"CompactPCI Hot Swap",
90
	"PCI-X",
91
	"AMD LDT/HT",
92
	"Vendor Specific",
93
	"Debug Port",
94
	"CompactPCI Central Resource Control",
95
	"PCI Hot-Plug",
96
	"PCI-PCI",
97
	"AGP8",
98
	"Secure",
99
	"PCI Express",
100
	"Extended Message Signalled Interrupts (MSI-X)",
101
	"SATA",
102
	"PCI Advanced Features"
103
};
104
105
const char *pci_enhanced_capnames[] = {
106
	"Unknown",
107
	"Advanced Error Reporting",
108
	"Virtual Channel Capability",
109
	"Device Serial Number",
110
	"Power Budgeting",
111
	"Root Complex Link Declaration",
112
	"Root Complex Internal Link Control",
113
	"Root Complex Event Collector",
114
	"Multi-Function VC Capability",
115
	"Virtual Channel Capability",
116
	"Root Complex/Root Bridge",
117
	"Vendor-Specific",
118
	"Config Access",
119
	"Access Control Services",
120
	"Alternate Routing ID",
121
	"Address Translation Services",
122
	"Single Root I/O Virtualization",
123
	"Multi Root I/O Virtualization",
124
	"Multicast",
125
	"Page Request Interface",
126
	"Reserved for AMD",
127
	"Resizable BAR",
128
	"Dynamic Power Allocation",
129
	"TPH Requester",
130
	"Latency Tolerance Reporting",
131
	"Secondary PCIe Capability",
132
	"Protocol Multiplexing",
133
	"Process Address Space ID",
134
	"LN Requester",
135
	"Downstream Port Containment",
136
	"L1 PM",
137
	"Precision Time Measurement",
138
};
139
140
int
141
main(int argc, char *argv[])
142
{
143
	int nfuncs;
144
	int bus, dev, func;
145
	char pcidev[PATH_MAX] = PCIDEV;
146
	char *romfile = NULL;
147
	const char *errstr;
148
	int c, error = 0, dumpall = 1, domid = 0;
149
150
	while ((c = getopt(argc, argv, "d:r:vx")) != -1) {
151
		switch (c) {
152
		case 'd':
153
			strlcpy(pcidev, optarg, sizeof(pcidev));
154
			dumpall = 0;
155
			break;
156
		case 'r':
157
			romfile = optarg;
158
			dumpall = 0;
159
			break;
160
		case 'v':
161
			verbose = 1;
162
			break;
163
		case 'x':
164
			hex++;
165
			break;
166
		default:
167
			usage();
168
		}
169
	}
170
	argc -= optind;
171
	argv += optind;
172
173
	if (argc > 1 || (romfile && argc != 1))
174
		usage();
175
176
	if (romfile) {
177
		romfd = open(romfile, O_WRONLY|O_CREAT|O_TRUNC, 0777);
178
		if (romfd == -1)
179
			err(1, "%s", romfile);
180
	}
181
182
	if (hex > 1)
183
		size = 256;
184
	if (hex > 2)
185
		size = 4096;
186
187
	if (argc == 1)
188
		dumpall = 0;
189
190
	if (dumpall == 0) {
191
		pcifd = open(pcidev, O_RDONLY, 0777);
192
		if (pcifd == -1)
193
			err(1, "%s", pcidev);
194
	} else {
195
		for (;;) {
196
			snprintf(pcidev, 16, "/dev/pci%d", domid++);
197
			pcifd = open(pcidev, O_RDONLY, 0777);
198
			if (pcifd == -1) {
199
				if (errno == ENXIO || errno == ENOENT) {
200
					return 0;
201
				} else {
202
					err(1, "%s", pcidev);
203
				}
204
			}
205
			printf("Domain %s:\n", pcidev);
206
			scanpcidomain();
207
			close(pcifd);
208
		}
209
	}
210
211
	if (argc == 1) {
212
		errstr = str2busdevfunc(argv[0], &bus, &dev, &func);
213
		if (errstr != NULL)
214
			errx(1, "\"%s\": %s", argv[0], errstr);
215
216
		nfuncs = pci_nfuncs(bus, dev);
217
		if (nfuncs == -1 || func > nfuncs)
218
			error = ENXIO;
219
		else if (romfile)
220
			error = dump_rom(bus, dev, func);
221
		else
222
			error = probe(bus, dev, func);
223
224
		if (error != 0)
225
			errc(1, error, "\"%s\"", argv[0]);
226
	} else {
227
		printf("Domain %s:\n", pcidev);
228
		scanpcidomain();
229
	}
230
231
	return (0);
232
}
233
234
void
235
scanpcidomain(void)
236
{
237
	int nfuncs;
238
	int bus, dev, func;
239
240
	for (bus = 0; bus < 256; bus++) {
241
		for (dev = 0; dev < 32; dev++) {
242
			nfuncs = pci_nfuncs(bus, dev);
243
			for (func = 0; func < nfuncs; func++) {
244
				probe(bus, dev, func);
245
			}
246
		}
247
	}
248
}
249
250
const char *
251
str2busdevfunc(const char *string, int *bus, int *dev, int *func)
252
{
253
	const char *errstr;
254
	char b[80], *d, *f;
255
256
	strlcpy(b, string, sizeof(b));
257
258
	d = strchr(b, ':');
259
	if (d == NULL)
260
		return("device not specified");
261
	*d++ = '\0';
262
263
	f = strchr(d, ':');
264
	if (f == NULL)
265
		return("function not specified");
266
	*f++ = '\0';
267
268
	*bus = strtonum(b, 0, 255, &errstr);
269
	if (errstr != NULL)
270
		return (errstr);
271
	*dev = strtonum(d, 0, 31, &errstr);
272
	if (errstr != NULL)
273
		return (errstr);
274
	*func = strtonum(f, 0, 7, &errstr);
275
	if (errstr != NULL)
276
		return (errstr);
277
278
	return (NULL);
279
}
280
281
int
282
probe(int bus, int dev, int func)
283
{
284
	u_int32_t id_reg;
285
	const struct pci_known_vendor *pkv;
286
	const struct pci_known_product *pkp;
287
	const char *vendor = NULL, *product = NULL;
288
289
	if (pci_read(bus, dev, func, PCI_ID_REG, &id_reg) != 0)
290
		return (errno);
291
292
	if (PCI_VENDOR(id_reg) == PCI_VENDOR_INVALID ||
293
	    PCI_VENDOR(id_reg) == 0)
294
		return (ENXIO);
295
296
	for (pkv = pci_known_vendors; pkv->vendorname != NULL; pkv++) {
297
		if (pkv->vendor == PCI_VENDOR(id_reg)) {
298
			vendor = pkv->vendorname;
299
			break;
300
		}
301
	}
302
303
	if (vendor != NULL) {
304
		for (pkp = pci_known_products; pkp->productname != NULL; pkp++)
305
		if (pkp->vendor == PCI_VENDOR(id_reg) &&
306
		    pkp->product == PCI_PRODUCT(id_reg)) {
307
			product = pkp->productname;
308
			break;
309
		}
310
	}
311
312
	printf(" %d:%d:%d: %s %s\n", bus, dev, func,
313
	    (vendor == NULL) ? "unknown" : vendor,
314
	    (product == NULL) ? "unknown" : product);
315
316
	if (verbose)
317
		dump(bus, dev, func);
318
	if (hex > 0)
319
		hexdump(bus, dev, func, size);
320
321
	return (0);
322
}
323
324
void
325
dump_pci_powerstate(int bus, int dev, int func, uint8_t ptr)
326
{
327
	u_int32_t pmcsr;
328
329
	if (pci_read(bus, dev, func, ptr + PCI_PMCSR, &pmcsr) != 0)
330
		return;
331
332
	printf("\t	State: D%d", pmcsr & PCI_PMCSR_STATE_MASK);
333
	if (pmcsr & PCI_PMCSR_PME_EN)
334
		printf(" PME# enabled");
335
	if (pmcsr & PCI_PMCSR_PME_STATUS)
336
		printf(" PME# asserted");
337
	printf("\n");
338
}
339
340
void
341
print_pcie_ls(uint8_t speed)
342
{
343
	if (speed & 4)
344
		printf("8.0");
345
	else if (speed & 2)
346
		printf("5.0");
347
	else if (speed & 1)
348
		printf("2.5");
349
	else
350
		printf("unknown (%d)", speed);
351
}
352
353
void
354
dump_pcie_linkspeed(int bus, int dev, int func, uint8_t ptr)
355
{
356
	u_int32_t lcap, sreg, lcap2 = 0, xcap;
357
	u_int8_t cwidth, cspeed, swidth, sspeed;
358
359
	if (pci_read(bus, dev, func, ptr + PCI_PCIE_XCAP, &xcap) != 0)
360
		return;
361
362
	if (PCI_PCIE_XCAP_VER(xcap) >= 2) {
363
		if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP2, &lcap2) != 0)
364
			lcap2 = 0;
365
		else
366
			cspeed = (lcap2 & 0x0e) >> 1;
367
	}
368
369
	if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCAP, &lcap) != 0)
370
		return;
371
	if (lcap2 == 0)
372
		cspeed = lcap & 0x0f;
373
374
	if (pci_read(bus, dev, func, ptr + PCI_PCIE_LCSR, &sreg) != 0)
375
		return;
376
	sreg = sreg >> 16;
377
378
	cwidth = (lcap >> 4) & 0x3f;
379
	if (cwidth == 0)
380
		return;
381
382
	swidth = (sreg >> 4) & 0x3f;
383
	sspeed = sreg & 0x0f;
384
385
	printf("\t        Link Speed: ");
386
	print_pcie_ls(sspeed);
387
	printf(" / ");
388
	print_pcie_ls(cspeed);
389
390
	printf(" GT/s Link Width: x%d / x%d\n", swidth, cwidth);
391
}
392
393
void
394
dump_pcie_enhanced_caplist(int bus, int dev, int func)
395
{
396
	u_int32_t reg;
397
	u_int32_t capidx;
398
	u_int16_t ptr;
399
	u_int16_t ecap;
400
401
	ptr = PCI_PCIE_ECAP;
402
403
	do {
404
		if (pci_read(bus, dev, func, ptr, &reg) != 0)
405
			return;
406
407
		if (PCI_PCIE_ECAP_ID(reg) == 0xffff &&
408
		    PCI_PCIE_ECAP_NEXT(reg) == PCI_PCIE_ECAP_LAST)
409
			return;
410
411
		ecap = PCI_PCIE_ECAP_ID(reg);
412
		if (ecap >= nitems(pci_enhanced_capnames))
413
			capidx = 0;
414
		else
415
			capidx = ecap;
416
417
		printf("\t0x%04x: Enhanced Capability 0x%02x: ", ptr, ecap);
418
		printf("%s\n", pci_enhanced_capnames[capidx]);
419
420
		ptr = PCI_PCIE_ECAP_NEXT(reg);
421
422
	} while (ptr != PCI_PCIE_ECAP_LAST);
423
}
424
425
void
426
dump_caplist(int bus, int dev, int func, u_int8_t ptr)
427
{
428
	u_int32_t reg;
429
	u_int8_t cap;
430
431
	if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, &reg) != 0)
432
		return;
433
	if (!(reg & PCI_STATUS_CAPLIST_SUPPORT))
434
		return;
435
436
	if (pci_read(bus, dev, func, ptr, &reg) != 0)
437
		return;
438
	ptr = PCI_CAPLIST_PTR(reg);
439
	while (ptr != 0) {
440
		if (pci_read(bus, dev, func, ptr, &reg) != 0)
441
			return;
442
		cap = PCI_CAPLIST_CAP(reg);
443
		printf("\t0x%04x: Capability 0x%02x: ", ptr, cap);
444
		if (cap >= nitems(pci_capnames))
445
			cap = 0;
446
		printf("%s\n", pci_capnames[cap]);
447
		if (cap == PCI_CAP_PWRMGMT)
448
			dump_pci_powerstate(bus, dev, func, ptr);
449
		if (cap == PCI_CAP_PCIEXPRESS) {
450
			dump_pcie_linkspeed(bus, dev, func, ptr);
451
			dump_pcie_enhanced_caplist(bus, dev, func);
452
		}
453
		ptr = PCI_CAPLIST_NEXT(reg);
454
	}
455
}
456
457
void
458
dump_type0(int bus, int dev, int func)
459
{
460
	const char *memtype;
461
	u_int64_t mem;
462
	u_int64_t mask;
463
	u_int32_t reg, reg1;
464
	int bar;
465
466
	for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 0x4) {
467
		if (pci_read(bus, dev, func, bar, &reg) != 0 ||
468
		    pci_readmask(bus, dev, func, bar, &reg1) != 0)
469
			warn("unable to read PCI_MAPREG 0x%02x", bar);
470
471
		printf("\t0x%04x: BAR ", bar);
472
473
		if (reg == 0 && reg1 == 0) {
474
			printf("empty (%08x)\n", reg);
475
			continue;
476
		}
477
478
		switch (PCI_MAPREG_TYPE(reg)) {
479
		case PCI_MAPREG_TYPE_MEM:
480
			printf("mem ");
481
			if (PCI_MAPREG_MEM_PREFETCHABLE(reg))
482
				printf("prefetchable ");
483
484
			memtype = "32bit 1m";
485
			switch (PCI_MAPREG_MEM_TYPE(reg)) {
486
			case PCI_MAPREG_MEM_TYPE_32BIT:
487
				memtype = "32bit";
488
			case PCI_MAPREG_MEM_TYPE_32BIT_1M:
489
				printf("%s ", memtype);
490
491
				printf("addr: 0x%08x/0x%08x\n",
492
				    PCI_MAPREG_MEM_ADDR(reg),
493
				    PCI_MAPREG_MEM_SIZE(reg1));
494
495
				break;
496
			case PCI_MAPREG_MEM_TYPE_64BIT:
497
				mem = reg;
498
				mask = reg1;
499
				bar += 0x04;
500
				if (pci_read(bus, dev, func, bar, &reg) != 0 ||
501
				    pci_readmask(bus, dev, func, bar, &reg1) != 0)
502
					warn("unable to read 0x%02x", bar);
503
504
				mem |= (u_int64_t)reg << 32;
505
				mask |= (u_int64_t)reg1 << 32;
506
507
				printf("64bit addr: 0x%016llx/0x%08llx\n",
508
				    PCI_MAPREG_MEM64_ADDR(mem),
509
				    PCI_MAPREG_MEM64_SIZE(mask));
510
511
				break;
512
			}
513
			break;
514
515
		case PCI_MAPREG_TYPE_IO:
516
			printf("io addr: 0x%08x/0x%04x\n",
517
			    PCI_MAPREG_IO_ADDR(reg),
518
			    PCI_MAPREG_IO_SIZE(reg1));
519
			break;
520
		}
521
	}
522
523
	if (pci_read(bus, dev, func, PCI_CARDBUS_CIS_REG, &reg) != 0)
524
		warn("unable to read PCI_CARDBUS_CIS_REG");
525
	printf("\t0x%04x: Cardbus CIS: %08x\n", PCI_CARDBUS_CIS_REG, reg);
526
527
	if (pci_read(bus, dev, func, PCI_SUBSYS_ID_REG, &reg) != 0)
528
		warn("unable to read PCI_SUBSYS_ID_REG");
529
	printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n",
530
	    PCI_SUBSYS_ID_REG, PCI_VENDOR(reg), PCI_PRODUCT(reg));
531
532
	if (pci_read(bus, dev, func, PCI_ROM_REG, &reg) != 0)
533
		warn("unable to read PCI_ROM_REG");
534
	printf("\t0x%04x: Expansion ROM Base Address: %08x\n",
535
	    PCI_ROM_REG, reg);
536
537
	if (pci_read(bus, dev, func, 0x38, &reg) != 0)
538
		warn("unable to read 0x38 (reserved)");
539
	printf("\t0x%04x: %08x\n", 0x38, reg);
540
541
	if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, &reg) != 0)
542
		warn("unable to read PCI_INTERRUPT_REG");
543
	printf("\t0x%04x: Interrupt Pin: %02x Line: %02x Min Gnt: %02x"
544
	    " Max Lat: %02x\n", PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg),
545
	    PCI_INTERRUPT_LINE(reg), PCI_MIN_GNT(reg), PCI_MAX_LAT(reg));
546
}
547
548
void
549
dump_type1(int bus, int dev, int func)
550
{
551
	u_int32_t reg;
552
	int bar;
553
554
	for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_PPB_END; bar += 0x4) {
555
		if (pci_read(bus, dev, func, bar, &reg) != 0)
556
			warn("unable to read PCI_MAPREG 0x%02x", bar);
557
		printf("\t0x%04x: %08x\n", bar, reg);
558
	}
559
560
	if (pci_read(bus, dev, func, PCI_PRIBUS_1, &reg) != 0)
561
		warn("unable to read PCI_PRIBUS_1");
562
	printf("\t0x%04x: Primary Bus: %d Secondary Bus: %d "
563
	    "Subordinate Bus: %d \n\t        Secondary Latency Timer: %02x\n",
564
	    PCI_PRIBUS_1, (reg >> 0) & 0xff, (reg >> 8) & 0xff,
565
	    (reg >> 16) & 0xff, (reg >> 24) & 0xff);
566
567
	if (pci_read(bus, dev, func, PCI_IOBASEL_1, &reg) != 0)
568
		warn("unable to read PCI_IOBASEL_1");
569
	printf("\t0x%04x: I/O Base: %02x I/O Limit: %02x "
570
	    "Secondary Status: %04x\n", PCI_IOBASEL_1, (reg >> 0 ) & 0xff,
571
	    (reg >> 8) & 0xff, (reg >> 16) & 0xffff);
572
573
	if (pci_read(bus, dev, func, PCI_MEMBASE_1, &reg) != 0)
574
		warn("unable to read PCI_MEMBASE_1");
575
	printf("\t0x%04x: Memory Base: %04x Memory Limit: %04x\n",
576
	    PCI_MEMBASE_1, (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
577
578
	if (pci_read(bus, dev, func, PCI_PMBASEL_1, &reg) != 0)
579
		warn("unable to read PCI_PMBASEL_1");
580
	printf("\t0x%04x: Prefetch Memory Base: %04x "
581
	    "Prefetch Memory Limit: %04x\n", PCI_PMBASEL_1,
582
	    (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
583
584
#undef PCI_PMBASEH_1
585
#define PCI_PMBASEH_1	0x28
586
	if (pci_read(bus, dev, func, PCI_PMBASEH_1, &reg) != 0)
587
		warn("unable to read PCI_PMBASEH_1");
588
	printf("\t0x%04x: Prefetch Memory Base Upper 32 Bits: %08x\n",
589
	    PCI_PMBASEH_1, reg);
590
591
#undef PCI_PMLIMITH_1
592
#define PCI_PMLIMITH_1	0x2c
593
	if (pci_read(bus, dev, func, PCI_PMLIMITH_1, &reg) != 0)
594
		warn("unable to read PCI_PMLIMITH_1");
595
	printf("\t0x%04x: Prefetch Memory Limit Upper 32 Bits: %08x\n",
596
	    PCI_PMLIMITH_1, reg);
597
598
#undef PCI_IOBASEH_1
599
#define PCI_IOBASEH_1	0x30
600
	if (pci_read(bus, dev, func, PCI_IOBASEH_1, &reg) != 0)
601
		warn("unable to read PCI_IOBASEH_1");
602
	printf("\t0x%04x: I/O Base Upper 16 Bits: %04x "
603
	    "I/O Limit Upper 16 Bits: %04x\n", PCI_IOBASEH_1,
604
	    (reg >> 0) & 0xffff, (reg >> 16) & 0xffff);
605
606
#define PCI_PPB_ROM_REG		0x38
607
	if (pci_read(bus, dev, func, PCI_PPB_ROM_REG, &reg) != 0)
608
		warn("unable to read PCI_PPB_ROM_REG");
609
	printf("\t0x%04x: Expansion ROM Base Address: %08x\n",
610
	    PCI_PPB_ROM_REG, reg);
611
612
	if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, &reg) != 0)
613
		warn("unable to read PCI_INTERRUPT_REG");
614
	printf("\t0x%04x: Interrupt Pin: %02x Line: %02x "
615
	    "Bridge Control: %04x\n",
616
	    PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg),
617
	    PCI_INTERRUPT_LINE(reg), reg >> 16);
618
}
619
620
void
621
dump_type2(int bus, int dev, int func)
622
{
623
	u_int32_t reg;
624
625
	if (pci_read(bus, dev, func, PCI_MAPREG_START, &reg) != 0)
626
		warn("unable to read PCI_MAPREG\n");
627
	printf("\t0x%04x: Cardbus Control Registers Base Address: %08x\n",
628
	    PCI_MAPREG_START, reg);
629
630
	if (pci_read(bus, dev, func, PCI_PRIBUS_2, &reg) != 0)
631
		warn("unable to read PCI_PRIBUS_2");
632
	printf("\t0x%04x: Primary Bus: %d Cardbus Bus: %d "
633
	    "Subordinate Bus: %d \n\t        Cardbus Latency Timer: %02x\n",
634
	    PCI_PRIBUS_2, (reg >> 0) & 0xff, (reg >> 8) & 0xff,
635
	    (reg >> 16) & 0xff, (reg >> 24) & 0xff);
636
637
	if (pci_read(bus, dev, func, PCI_MEMBASE0_2, &reg) != 0)
638
		warn("unable to read PCI_MEMBASE0_2\n");
639
	printf("\t0x%04x: Memory Base 0: %08x\n", PCI_MEMBASE0_2, reg);
640
641
	if (pci_read(bus, dev, func, PCI_MEMLIMIT0_2, &reg) != 0)
642
		warn("unable to read PCI_MEMLIMIT0_2\n");
643
	printf("\t0x%04x: Memory Limit 0: %08x\n", PCI_MEMLIMIT0_2, reg);
644
645
	if (pci_read(bus, dev, func, PCI_MEMBASE1_2, &reg) != 0)
646
		warn("unable to read PCI_MEMBASE1_2\n");
647
	printf("\t0x%04x: Memory Base 1: %08x\n", PCI_MEMBASE1_2, reg);
648
649
	if (pci_read(bus, dev, func, PCI_MEMLIMIT1_2, &reg) != 0)
650
		warn("unable to read PCI_MEMLIMIT1_2\n");
651
	printf("\t0x%04x: Memory Limit 1: %08x\n", PCI_MEMLIMIT1_2, reg);
652
653
	if (pci_read(bus, dev, func, PCI_IOBASE0_2, &reg) != 0)
654
		warn("unable to read PCI_IOBASE0_2\n");
655
	printf("\t0x%04x: I/O Base 0: %08x\n", PCI_IOBASE0_2, reg);
656
657
	if (pci_read(bus, dev, func, PCI_IOLIMIT0_2, &reg) != 0)
658
		warn("unable to read PCI_IOLIMIT0_2\n");
659
	printf("\t0x%04x: I/O Limit 0: %08x\n", PCI_IOLIMIT0_2, reg);
660
661
	if (pci_read(bus, dev, func, PCI_IOBASE1_2, &reg) != 0)
662
		warn("unable to read PCI_IOBASE1_2\n");
663
	printf("\t0x%04x: I/O Base 1: %08x\n", PCI_IOBASE1_2, reg);
664
665
	if (pci_read(bus, dev, func, PCI_IOLIMIT1_2, &reg) != 0)
666
		warn("unable to read PCI_IOLIMIT1_2\n");
667
	printf("\t0x%04x: I/O Limit 1: %08x\n", PCI_IOLIMIT1_2, reg);
668
669
	if (pci_read(bus, dev, func, PCI_INTERRUPT_REG, &reg) != 0)
670
		warn("unable to read PCI_INTERRUPT_REG");
671
	printf("\t0x%04x: Interrupt Pin: %02x Line: %02x "
672
	    "Bridge Control: %04x\n",
673
	    PCI_INTERRUPT_REG, PCI_INTERRUPT_PIN(reg),
674
	    PCI_INTERRUPT_LINE(reg), reg >> 16);
675
676
	if (pci_read(bus, dev, func, PCI_SUBVEND_2, &reg) != 0)
677
		warn("unable to read PCI_SUBVEND_2");
678
	printf("\t0x%04x: Subsystem Vendor ID: %04x Product ID: %04x\n",
679
	    PCI_SUBVEND_2, PCI_VENDOR(reg), PCI_PRODUCT(reg));
680
681
	if (pci_read(bus, dev, func, PCI_PCCARDIF_2, &reg) != 0)
682
		warn("unable to read PCI_PCCARDIF_2\n");
683
	printf("\t0x%04x: 16-bit Legacy Mode Base Address: %08x\n",
684
	    PCI_PCCARDIF_2, reg);
685
}
686
687
void
688
dump(int bus, int dev, int func)
689
{
690
	u_int32_t reg;
691
	u_int8_t capptr = PCI_CAPLISTPTR_REG;
692
693
	if (pci_read(bus, dev, func, PCI_ID_REG, &reg) != 0)
694
		warn("unable to read PCI_ID_REG");
695
	printf("\t0x%04x: Vendor ID: %04x Product ID: %04x\n", PCI_ID_REG,
696
	    PCI_VENDOR(reg), PCI_PRODUCT(reg));
697
698
	if (pci_read(bus, dev, func, PCI_COMMAND_STATUS_REG, &reg) != 0)
699
		warn("unable to read PCI_COMMAND_STATUS_REG");
700
	printf("\t0x%04x: Command: %04x Status: %04x\n",
701
	    PCI_COMMAND_STATUS_REG, reg & 0xffff, (reg  >> 16) & 0xffff);
702
703
	if (pci_read(bus, dev, func, PCI_CLASS_REG, &reg) != 0)
704
		warn("unable to read PCI_CLASS_REG");
705
	printf("\t0x%04x: Class: %02x Subclass: %02x Interface: %02x "
706
	    "Revision: %02x\n", PCI_CLASS_REG, PCI_CLASS(reg),
707
	    PCI_SUBCLASS(reg), PCI_INTERFACE(reg), PCI_REVISION(reg));
708
709
	if (pci_read(bus, dev, func, PCI_BHLC_REG, &reg) != 0)
710
		warn("unable to read PCI_BHLC_REG");
711
	printf("\t0x%04x: BIST: %02x Header Type: %02x Latency Timer: %02x "
712
	    "Cache Line Size: %02x\n", PCI_BHLC_REG, PCI_BIST(reg),
713
	    PCI_HDRTYPE(reg), PCI_LATTIMER(reg), PCI_CACHELINE(reg));
714
715
	switch (PCI_HDRTYPE_TYPE(reg)) {
716
	case 2:
717
		dump_type2(bus, dev, func);
718
		capptr = PCI_CARDBUS_CAPLISTPTR_REG;
719
		break;
720
	case 1:
721
		dump_type1(bus, dev, func);
722
		break;
723
	case 0:
724
		dump_type0(bus, dev, func);
725
		break;
726
	default:
727
		break;
728
	}
729
	dump_caplist(bus, dev, func, capptr);
730
}
731
732
void
733
hexdump(int bus, int dev, int func, int size)
734
{
735
	u_int32_t reg;
736
	int i;
737
738
	for (i = 0; i < size; i += 4) {
739
		if (pci_read(bus, dev, func, i, &reg) != 0) {
740
			if (errno == EINVAL)
741
				return;
742
			warn("unable to read 0x%02x", i);
743
		}
744
745
		if ((i % 16) == 0)
746
			printf("\t0x%04x:", i);
747
		printf(" %08x", reg);
748
749
		if ((i % 16) == 12)
750
			printf("\n");
751
	}
752
}
753
754
int
755
pci_nfuncs(int bus, int dev)
756
{
757
	u_int32_t hdr;
758
759
	if (pci_read(bus, dev, 0, PCI_BHLC_REG, &hdr) != 0)
760
		return (-1);
761
762
	return (PCI_HDRTYPE_MULTIFN(hdr) ? 8 : 1);
763
}
764
765
int
766
pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
767
{
768
	struct pci_io io;
769
	int rv;
770
771
	bzero(&io, sizeof(io));
772
	io.pi_sel.pc_bus = bus;
773
	io.pi_sel.pc_dev = dev;
774
	io.pi_sel.pc_func = func;
775
	io.pi_reg = reg;
776
	io.pi_width = 4;
777
778
	rv = ioctl(pcifd, PCIOCREAD, &io);
779
	if (rv != 0)
780
		return (rv);
781
782
	*val = io.pi_data;
783
784
	return (0);
785
}
786
787
int
788
pci_readmask(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
789
{
790
	struct pci_io io;
791
	int rv;
792
793
	bzero(&io, sizeof(io));
794
	io.pi_sel.pc_bus = bus;
795
	io.pi_sel.pc_dev = dev;
796
	io.pi_sel.pc_func = func;
797
	io.pi_reg = reg;
798
	io.pi_width = 4;
799
800
	rv = ioctl(pcifd, PCIOCREADMASK, &io);
801
	if (rv != 0)
802
		return (rv);
803
804
	*val = io.pi_data;
805
806
	return (0);
807
}
808
809
int
810
dump_rom(int bus, int dev, int func)
811
{
812
	struct pci_rom rom;
813
	u_int32_t cr, addr;
814
815
	if (pci_read(bus, dev, func, PCI_ROM_REG, &addr) != 0 ||
816
	    pci_read(bus, dev, func, PCI_CLASS_REG, &cr) != 0)
817
		return (errno);
818
819
	if (addr == 0 && PCI_CLASS(cr) == PCI_CLASS_DISPLAY &&
820
	    PCI_SUBCLASS(cr) == PCI_SUBCLASS_DISPLAY_VGA)
821
		return dump_vga_bios();
822
823
	bzero(&rom, sizeof(rom));
824
	rom.pr_sel.pc_bus = bus;
825
	rom.pr_sel.pc_dev = dev;
826
	rom.pr_sel.pc_func = func;
827
	if (ioctl(pcifd, PCIOCGETROMLEN, &rom))
828
		return (errno);
829
830
	rom.pr_rom = malloc(rom.pr_romlen);
831
	if (rom.pr_rom == NULL)
832
		return (ENOMEM);
833
834
	if (ioctl(pcifd, PCIOCGETROM, &rom))
835
		return (errno);
836
837
	if (write(romfd, rom.pr_rom, rom.pr_romlen) == -1)
838
		return (errno);
839
840
	return (0);
841
}
842
843
#define VGA_BIOS_ADDR	0xc0000
844
#define VGA_BIOS_LEN	0x10000
845
846
int
847
dump_vga_bios(void)
848
{
849
#if defined(__amd64__) || defined(__i386__)
850
	void *bios;
851
	int fd;
852
853
	fd = open(_PATH_MEM, O_RDONLY, 0777);
854
	if (fd == -1)
855
		err(1, "%s", _PATH_MEM);
856
857
	bios = malloc(VGA_BIOS_LEN);
858
	if (bios == NULL)
859
		return (ENOMEM);
860
861
	if (pread(fd, bios, VGA_BIOS_LEN, VGA_BIOS_ADDR) == -1)
862
		err(1, "%s", _PATH_MEM);
863
864
	if (write(romfd, bios, VGA_BIOS_LEN) == -1) {
865
		free(bios);
866
		return (errno);
867
	}
868
869
	free(bios);
870
871
	return (0);
872
#else
873
	return (ENODEV);
874
#endif
875
}