2 * $Id: setpci.c,v 1.1 1998/03/31 21:02:20 mj Exp $
4 * Linux PCI Utilities -- Manipulate PCI Configuration Registers
6 * Copyright (c) 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
8 * Can be freely distributed and used under the terms of the GNU GPL.
19 static int force; /* Don't complain if no devices match */
20 static int verbose; /* Verbosity level */
24 byte bus, devfn, mark;
29 static struct device *first_dev;
33 struct device **dev_vector;
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];
40 static struct op *first_op, **last_op = &first_op;
43 xmalloc(unsigned int howmuch)
45 void *p = malloc(howmuch);
48 fprintf(stderr, "setpci: Unable to allocate %d bytes of memory\n", howmuch);
57 struct device **last = &first_dev;
61 if (!(f = fopen(PROC_BUS_PCI "/devices", "r")))
63 perror(PROC_BUS_PCI "/devices");
66 while (fgets(line, sizeof(line), f))
68 struct device *d = xmalloc(sizeof(struct device));
69 unsigned int dfn, vend;
71 sscanf(line, "%x %x", &dfn, &vend);
73 d->devfn = dfn & 0xff;
74 d->vendid = vend >> 16U;
75 d->devid = vend & 0xffff;
84 static struct device **
85 select_devices(struct pci_filter *filt)
87 struct device *z, **a, **b;
90 for(z=first_dev; z; z=z->next)
91 if (z->mark = filter_match(filt, z->bus, z->devfn, z->vendid, z->devid))
93 a = b = xmalloc(sizeof(struct device *) * cnt);
94 for(z=first_dev; z; z=z->next)
102 exec_op(struct op *op, struct device *dev)
104 char *mm[] = { NULL, "%02x", "%04x", NULL, "%08x" };
105 char *m = mm[op->width];
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 ????
115 printf("%02x.%02x:%x.%c ", dev->bus, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
117 if (op->num_values > 0)
128 execute(struct op *op)
130 struct device **vec = NULL;
131 struct device **pdev, *dev;
136 pdev = vec = op->dev_vector;
137 while (dev = *pdev++)
138 for(oops=op; oops && oops->dev_vector == vec; oops=oops->next)
140 while (op && op->dev_vector == vec)
145 static void usage(void) __attribute__((noreturn));
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\
161 main(int argc, char **argv)
163 enum { STATE_INIT, STATE_GOT_FILTER, STATE_GOT_OP } state = STATE_INIT;
164 struct pci_filter filter;
165 struct device **selected_devices = NULL;
169 while (argc && argv[0][0] == '-')
204 unsigned long ll, lim;
208 if (!c[1] || !strchr("sd", c[1]))
211 d = (c[2] == '=') ? c+3 : c+2;
220 if (state != STATE_GOT_FILTER)
222 filter_init(&filter);
223 state = STATE_GOT_FILTER;
228 if (d = filter_parse_slot(&filter, d))
230 fprintf(stderr, "setpci: -s: %s\n", d);
235 if (d = filter_parse_id(&filter, d))
237 fprintf(stderr, "setpci: -d: %s\n", d);
245 else if (state == STATE_INIT)
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;
258 for(e=d, n=1; *e; e++)
261 op = xmalloc(sizeof(struct op) + n*sizeof(unsigned int));
266 op = xmalloc(sizeof(struct op));
268 op->dev_vector = selected_devices;
279 op->width = 1; break;
281 op->width = 2; break;
283 op->width = 4; break;
290 ll = strtol(c, &f, 16);
291 if (ll > 0x100 || ll + op->width*n > 0x100)
293 fprintf(stderr, "setpci: Register number out of range!\n");
301 ll = strtoul(d, &f, 16);
302 lim = (2 << ((op->width << 3) - 1)) - 1;
304 (ll > lim && ll < ~0UL - lim))
316 if (state == STATE_INIT)