]> git.ipfire.org Git - thirdparty/pciutils.git/blob - setpci.c
Intermediate version of pciutils.
[thirdparty/pciutils.git] / setpci.c
1 /*
2 * $Id: setpci.c,v 1.1 1998/03/31 21:02:20 mj Exp $
3 *
4 * Linux PCI Utilities -- Manipulate PCI Configuration Registers
5 *
6 * Copyright (c) 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16
17 #include "pciutils.h"
18
19 static int force; /* Don't complain if no devices match */
20 static int verbose; /* Verbosity level */
21
22 struct device {
23 struct device *next;
24 byte bus, devfn, mark;
25 word vendid, devid;
26 int fd;
27 };
28
29 static struct device *first_dev;
30
31 struct op {
32 struct op *next;
33 struct device **dev_vector;
34 unsigned int addr;
35 unsigned int width; /* Byte width of the access */
36 int num_values; /* Number of values to write; <0=read */
37 unsigned int values[0];
38 };
39
40 static struct op *first_op, **last_op = &first_op;
41
42 void *
43 xmalloc(unsigned int howmuch)
44 {
45 void *p = malloc(howmuch);
46 if (!p)
47 {
48 fprintf(stderr, "setpci: Unable to allocate %d bytes of memory\n", howmuch);
49 exit(1);
50 }
51 return p;
52 }
53
54 static void
55 scan_devices(void)
56 {
57 struct device **last = &first_dev;
58 byte line[256];
59 FILE *f;
60
61 if (!(f = fopen(PROC_BUS_PCI "/devices", "r")))
62 {
63 perror(PROC_BUS_PCI "/devices");
64 exit(1);
65 }
66 while (fgets(line, sizeof(line), f))
67 {
68 struct device *d = xmalloc(sizeof(struct device));
69 unsigned int dfn, vend;
70
71 sscanf(line, "%x %x", &dfn, &vend);
72 d->bus = dfn >> 8U;
73 d->devfn = dfn & 0xff;
74 d->vendid = vend >> 16U;
75 d->devid = vend & 0xffff;
76 d->fd = -1;
77 *last = d;
78 last = &d->next;
79 }
80 fclose(f);
81 *last = NULL;
82 }
83
84 static struct device **
85 select_devices(struct pci_filter *filt)
86 {
87 struct device *z, **a, **b;
88 int cnt = 1;
89
90 for(z=first_dev; z; z=z->next)
91 if (z->mark = filter_match(filt, z->bus, z->devfn, z->vendid, z->devid))
92 cnt++;
93 a = b = xmalloc(sizeof(struct device *) * cnt);
94 for(z=first_dev; z; z=z->next)
95 if (z->mark)
96 *a++ = z;
97 *a = NULL;
98 return b;
99 }
100
101 static void
102 exec_op(struct op *op, struct device *dev)
103 {
104 char *mm[] = { NULL, "%02x", "%04x", NULL, "%08x" };
105 char *m = mm[op->width];
106
107 if (dev->fd < 0)
108 {
109 char name[64];
110 sprintf(name, PROC_BUS_PCI "/%02x/%02x.%x", dev->bus, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
111 dev->fd = open(name, O_RDWR ????
112 }
113
114 if (verbose)
115 printf("%02x.%02x:%x.%c ", dev->bus, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
116 "?BW?L"[op->width]);
117 if (op->num_values > 0)
118 {
119 }
120 else
121 {
122 if (verbose)
123 printf("= ");
124 }
125 }
126
127 static void
128 execute(struct op *op)
129 {
130 struct device **vec = NULL;
131 struct device **pdev, *dev;
132 struct op *oops;
133
134 while (op)
135 {
136 pdev = vec = op->dev_vector;
137 while (dev = *pdev++)
138 for(oops=op; oops && oops->dev_vector == vec; oops=oops->next)
139 exec_op(oops, dev);
140 while (op && op->dev_vector == vec)
141 op = op->next;
142 }
143 }
144
145 static void usage(void) __attribute__((noreturn));
146
147 static void
148 usage(void)
149 {
150 fprintf(stderr,
151 "Usage: setpci [-f] [-v] (<device>+ <reg>[=<values>]*)*\n\
152 <device>: -s [[<bus>]:][<slot>][.[<func>]]\n\
153 \t| -d [<vendor>]:[<device>]\n\
154 <reg>: <number>[.(B|W|L)]\n\
155 <values>: <value>[,<value>...]\n\
156 ");
157 exit(1);
158 }
159
160 int
161 main(int argc, char **argv)
162 {
163 enum { STATE_INIT, STATE_GOT_FILTER, STATE_GOT_OP } state = STATE_INIT;
164 struct pci_filter filter;
165 struct device **selected_devices = NULL;
166
167 argc--;
168 argv++;
169 while (argc && argv[0][0] == '-')
170 {
171 char *c = argv[0]+1;
172 char *d = c;
173 while (*c)
174 switch (*c)
175 {
176 case 'v':
177 verbose++;
178 c++;
179 break;
180 case 'f':
181 force++;
182 c++;
183 break;
184 case 0:
185 break;
186 default:
187 if (c != d)
188 usage();
189 goto next;
190 }
191 argc--;
192 argv++;
193 }
194 next:
195
196 scan_devices();
197
198 while (argc)
199 {
200 char *c = argv[0];
201 char *d, *e, *f;
202 int n, i;
203 struct op *op;
204 unsigned long ll, lim;
205
206 if (*c == '-')
207 {
208 if (!c[1] || !strchr("sd", c[1]))
209 usage();
210 if (c[2])
211 d = (c[2] == '=') ? c+3 : c+2;
212 else if (argc)
213 {
214 argc--;
215 argv++;
216 d = argv[0];
217 }
218 else
219 usage();
220 if (state != STATE_GOT_FILTER)
221 {
222 filter_init(&filter);
223 state = STATE_GOT_FILTER;
224 }
225 switch (c[1])
226 {
227 case 's':
228 if (d = filter_parse_slot(&filter, d))
229 {
230 fprintf(stderr, "setpci: -s: %s\n", d);
231 return 1;
232 }
233 break;
234 case 'd':
235 if (d = filter_parse_id(&filter, d))
236 {
237 fprintf(stderr, "setpci: -d: %s\n", d);
238 return 1;
239 }
240 break;
241 default:
242 usage();
243 }
244 }
245 else if (state == STATE_INIT)
246 usage();
247 else
248 {
249 if (state == STATE_GOT_FILTER)
250 selected_devices = select_devices(&filter);
251 if (!selected_devices[0] && !force)
252 fprintf(stderr, "setpci: Warning: No devices selected for `%s'.\n", c);
253 state = STATE_GOT_OP;
254 d = strchr(c, '=');
255 if (d)
256 {
257 *d++ = 0;
258 for(e=d, n=1; *e; e++)
259 if (*e == ',')
260 n++;
261 op = xmalloc(sizeof(struct op) + n*sizeof(unsigned int));
262 }
263 else
264 {
265 n = -1;
266 op = xmalloc(sizeof(struct op));
267 }
268 op->dev_vector = selected_devices;
269 op->num_values = n;
270 e = strchr(c, '.');
271 if (e)
272 {
273 *e++ = 0;
274 if (e[1])
275 usage();
276 switch (*e & 0xdf)
277 {
278 case 'B':
279 op->width = 1; break;
280 case 'W':
281 op->width = 2; break;
282 case 'L':
283 op->width = 4; break;
284 default:
285 usage();
286 }
287 }
288 else
289 op->width = 1;
290 ll = strtol(c, &f, 16);
291 if (ll > 0x100 || ll + op->width*n > 0x100)
292 {
293 fprintf(stderr, "setpci: Register number out of range!\n");
294 return 1;
295 }
296 for(i=0; i<n; i++)
297 {
298 e = strchr(d, ',');
299 if (e)
300 *e++ = 0;
301 ll = strtoul(d, &f, 16);
302 lim = (2 << ((op->width << 3) - 1)) - 1;
303 if (f && *f ||
304 (ll > lim && ll < ~0UL - lim))
305 usage();
306 op->values[i] = ll;
307 d = e;
308 }
309 *last_op = op;
310 last_op = &op->next;
311 op->next = NULL;
312 }
313 argc--;
314 argv++;
315 }
316 if (state == STATE_INIT)
317 usage();
318
319 execute(first_op);
320
321 return 0;
322 }