]> mj.ucw.cz Git - pciutils.git/blob - setpci.c
Intermediate version of pciutils.
[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 }