1 /* $NetBSD: pcictl.c,v 1.15 2009/07/04 13:54:14 cegger Exp $ */
4 * Copyright 2001 Wasabi Systems, Inc.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * pcictl(8) -- a program to manipulate the PCI bus
42 #include <sys/param.h>
43 #include <sys/ioctl.h>
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pcidevs.h>
57 #include <dev/pci/pciio.h>
61 const char *arg_names
;
62 void (*cmd_func
)(int, char *[]);
66 static void usage(void);
70 struct pciio_businfo pci_businfo
;
73 char dvname_store
[MAXPATHLEN
];
75 int print_numbers
= 0;
77 static void cmd_list(int, char *[]);
78 static void cmd_dump(int, char *[]);
80 const struct command commands
[] = {
82 "[-n] [-b bus] [-d device] [-f function]",
87 "[-b bus] -d device [-f function]",
94 static int parse_bdf(const char *);
96 static void scan_pci(int, int, int, void (*)(u_int
, u_int
, u_int
));
98 static void scan_pci_list(u_int
, u_int
, u_int
);
99 static void scan_pci_dump(u_int
, u_int
, u_int
);
102 main(int argc
, char *argv
[])
106 /* Must have at least: device command */
110 /* Skip program name, get and skip device name, get command. */
116 /* Look up and call the command. */
117 for (i
= 0; commands
[i
].cmd_name
!= NULL
; i
++)
118 if (strcmp(cmdname
, commands
[i
].cmd_name
) == 0)
120 if (commands
[i
].cmd_name
== NULL
)
121 errx(EXIT_FAILURE
, "unknown command: %s", cmdname
);
123 /* Open the device. */
124 if ((strchr(dvname
, '/') == NULL
) &&
125 (snprintf(dvname_store
, sizeof(dvname_store
), _PATH_DEV
"%s",
126 dvname
) < (int)sizeof(dvname_store
)))
127 dvname
= dvname_store
;
128 pcifd
= open(dvname
, commands
[i
].open_flags
);
130 err(EXIT_FAILURE
, "%s", dvname
);
132 /* Make sure the device is a PCI bus. */
133 if (ioctl(pcifd
, PCI_IOC_BUSINFO
, &pci_businfo
) != 0)
134 errx(EXIT_FAILURE
, "%s: not a PCI bus device", dvname
);
136 (*commands
[i
].cmd_func
)(argc
, argv
);
145 fprintf(stderr
, "usage: %s device command [arg [...]]\n",
148 fprintf(stderr
, " Available commands:\n");
149 for (i
= 0; commands
[i
].cmd_name
!= NULL
; i
++)
150 fprintf(stderr
, "\t%s %s\n", commands
[i
].cmd_name
,
151 commands
[i
].arg_names
);
157 cmd_list(int argc
, char *argv
[])
162 bus
= pci_businfo
.busno
;
165 while ((ch
= getopt(argc
, argv
, "nb:d:f:")) != -1) {
168 bus
= parse_bdf(optarg
);
171 dev
= parse_bdf(optarg
);
174 func
= parse_bdf(optarg
);
189 scan_pci(bus
, dev
, func
, scan_pci_list
);
193 cmd_dump(int argc
, char *argv
[])
198 bus
= pci_businfo
.busno
;
202 while ((ch
= getopt(argc
, argv
, "b:d:f:")) != -1) {
205 bus
= parse_bdf(optarg
);
208 dev
= parse_bdf(optarg
);
211 func
= parse_bdf(optarg
);
224 errx(EXIT_FAILURE
, "dump: wildcard bus number not permitted");
226 errx(EXIT_FAILURE
, "dump: must specify a device number");
228 errx(EXIT_FAILURE
, "dump: wildcard function number not permitted");
230 scan_pci(bus
, dev
, func
, scan_pci_dump
);
234 parse_bdf(const char *str
)
239 if (strcmp(str
, "all") == 0 ||
240 strcmp(str
, "any") == 0)
243 value
= strtol(str
, &end
, 0);
245 errx(EXIT_FAILURE
, "\"%s\" is not a number", str
);
251 scan_pci(int busarg
, int devarg
, int funcarg
, void (*cb
)(u_int
, u_int
, u_int
))
253 u_int busmin
, busmax
;
254 u_int devmin
, devmax
;
255 u_int funcmin
, funcmax
;
256 u_int bus
, dev
, func
;
263 busmin
= busmax
= busarg
;
267 if (pci_businfo
.maxdevs
<= 0)
270 devmax
= pci_businfo
.maxdevs
- 1;
272 devmin
= devmax
= devarg
;
274 for (bus
= busmin
; bus
<= busmax
; bus
++) {
275 for (dev
= devmin
; dev
<= devmax
; dev
++) {
276 if (pcibus_conf_read(pcifd
, bus
, dev
, 0,
277 PCI_BHLC_REG
, &bhlcr
) != 0)
281 if (PCI_HDRTYPE_MULTIFN(bhlcr
))
286 funcmin
= funcmax
= funcarg
;
287 for (func
= funcmin
; func
<= funcmax
; func
++) {
288 if (pcibus_conf_read(pcifd
, bus
, dev
,
289 func
, PCI_ID_REG
, &id
) != 0)
292 /* Invalid vendor ID value? */
293 if (PCI_VENDOR(id
) == PCI_VENDOR_INVALID
)
296 * XXX Not invalid, but we've done this
299 if (PCI_VENDOR(id
) == 0)
302 (*cb
)(bus
, dev
, func
);
309 scan_pci_list(u_int bus
, u_int dev
, u_int func
)
314 if (pcibus_conf_read(pcifd
, bus
, dev
, func
, PCI_ID_REG
, &id
) != 0)
316 if (pcibus_conf_read(pcifd
, bus
, dev
, func
, PCI_CLASS_REG
, &class) != 0)
319 printf("%03u:%02u:%01u: ", bus
, dev
, func
);
321 printf("0x%08x (0x%08x)\n", id
, class);
323 pci_devinfo(id
, class, 1, devinfo
, sizeof(devinfo
));
324 printf("%s\n", devinfo
);
329 scan_pci_dump(u_int bus
, u_int dev
, u_int func
)
332 pci_conf_print(pcifd
, bus
, dev
, func
);