pciconf.c revision 19817
1/*
2 * Copyright 1996 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all
9 * supporting documentation, and that the name of M.I.T. not be used
10 * in advertising or publicity pertaining to distribution of the
11 * software without specific, written prior permission.  M.I.T. makes
12 * no representations about the suitability of this software for any
13 * purpose.  It is provided "as is" without express or implied
14 * warranty.
15 *
16 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	$ANA: pciconf.c,v 1.1.1.1 1996/09/25 21:12:57 wollman Exp $
30 */
31
32#include <sys/types.h>
33#include <sys/fcntl.h>
34
35#include <err.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <string.h>
39#include <unistd.h>
40
41#include <pci/pcivar.h>
42#include <pci/pci_ioctl.h>
43
44#include "pathnames.h"
45
46static void list_devs(void);
47static void readit(const char *, const char *, int);
48static void writeit(const char *, const char *, const char *, int);
49
50
51static void
52usage(const char *argv0) {
53	fprintf(stderr, "usage:\n\t%s -l\n"
54		"\t%s [-r|-w] [-bh] sel addr [value]\n",
55		argv0, argv0);
56	exit (1);
57}
58
59int
60main(int argc, char **argv)
61{
62	int c;
63	int listmode, readmode, writemode;
64	int byte, isshort;
65
66	listmode = readmode = writemode = byte = isshort = 0;
67
68	while ((c = getopt(argc, argv, "lrwbh")) != EOF) {
69		switch(c) {
70		case 'l':
71			listmode = 1;
72			break;
73
74		case 'r':
75			readmode = 1;
76			break;
77
78		case 'w':
79			writemode = 1;
80			break;
81
82		case 'b':
83			byte = 1;
84			break;
85
86		case 'h':
87			isshort = 1;
88			break;
89
90		default:
91			usage(argv[0]);
92		}
93	}
94
95	if ((listmode && optind != argc)
96	    || (writemode && optind + 3 != argc)
97	    || (readmode && optind + 2 != argc))
98		usage(argv[0]);
99
100	if (listmode) {
101		list_devs();
102	} else if(readmode) {
103		readit(argv[optind], argv[optind + 1],
104		       byte ? 1 : isshort ? 2 : 4);
105	} else if(writemode) {
106		writeit(argv[optind], argv[optind + 1], argv[optind + 2],
107		       byte ? 1 : isshort ? 2 : 4);
108	} else {
109 		usage(argv[0]);
110	}
111
112	return 0;
113}
114
115static void
116list_devs(void)
117{
118	int fd;
119	struct pci_conf_io pc;
120	struct pci_conf conf[255], *p;
121
122	fd = open(_PATH_DEVPCI, O_RDONLY, 0);
123	if (fd < 0)
124		err(1, "%s", _PATH_DEVPCI);
125
126	pc.pci_len = sizeof(conf);
127	pc.pci_buf = conf;
128
129	if (ioctl(fd, PCIOCGETCONF, &pc) < 0)
130		err(1, "ioctl(PCIOCGETCONF)");
131
132	close(fd);
133
134	for (p = conf; p < &conf[pc.pci_len / sizeof conf[0]]; p++) {
135	    printf("pci%d:%d:%d:\tclass=0x%06x card=0x%08lx chip=0x%08lx rev=0x%02x hdr=0x%02x\n",
136		   p->pc_sel.pc_bus, p->pc_sel.pc_dev, p->pc_sel.pc_func,
137		   p->pc_class >> 8, p->pc_subid,
138		   p->pc_devid, p->pc_class & 0xff, p->pc_hdr);
139	}
140}
141
142static struct pcisel
143getsel(const char *str)
144{
145	char *ep = (char*) str;
146	struct pcisel sel;
147
148	if (strncmp(ep, "pci", 3) == 0) {
149		ep += 3;
150		sel.pc_bus = strtoul(ep, &ep, 0);
151		if (!ep || *ep++ != ':')
152			errx(1, "cannot parse selector %s", str);
153		sel.pc_dev = strtoul(ep, &ep, 0);
154		if (!ep || *ep != ':') {
155			sel.pc_func = 0;
156		} else {
157			ep++;
158			sel.pc_func = strtoul(ep, &ep, 0);
159		}
160	}
161	if (*ep == ':')
162		ep++;
163	if (*ep || ep == str)
164		errx(1, "cannot parse selector %s", str);
165	return sel;
166}
167
168static void
169readit(const char *name, const char *reg, int width)
170{
171	int fd;
172	struct pci_io pi;
173
174	pi.pi_sel = getsel(name);
175	pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */
176	pi.pi_width = width;
177
178	fd = open(_PATH_DEVPCI, O_RDWR, 0);
179	if (fd < 0)
180		err(1, "%s", _PATH_DEVPCI);
181
182	if (ioctl(fd, PCIOCREAD, &pi) < 0)
183		err(1, "ioctl(PCIOCREAD)");
184
185	printf("0x%08x\n", pi.pi_data);
186}
187
188static void
189writeit(const char *name, const char *reg, const char *data, int width)
190{
191	int fd;
192	struct pci_io pi;
193
194	pi.pi_sel = getsel(name);
195	pi.pi_reg = strtoul(reg, (char **)0, 0); /* XXX error check */
196	pi.pi_width = width;
197	pi.pi_data = strtoul(data, (char **)0, 0); /* XXX error check */
198
199	fd = open(_PATH_DEVPCI, O_RDWR, 0);
200	if (fd < 0)
201		err(1, "%s", _PATH_DEVPCI);
202
203	if (ioctl(fd, PCIOCWRITE, &pi) < 0)
204		err(1, "ioctl(PCIOCWRITE)");
205}
206