]>
git.ipfire.org Git - thirdparty/pciutils.git/blob - setpci.c
2 * Linux PCI Utilities -- Manipulate PCI Configuration Registers
4 * Copyright (c) 1998--2003 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
17 static int force
; /* Don't complain if no devices match */
18 static int verbose
; /* Verbosity level */
19 static int demo_mode
; /* Only show */
21 static struct pci_access
*pacc
;
30 struct pci_dev
**dev_vector
;
32 unsigned int width
; /* Byte width of the access */
33 int num_values
; /* Number of values to write; <0=read */
34 struct value values
[0];
37 static struct op
*first_op
, **last_op
= &first_op
;
38 static unsigned int max_values
[] = { 0, 0xff, 0xffff, 0, 0xffffffff };
40 static struct pci_dev
**
41 select_devices(struct pci_filter
*filt
)
43 struct pci_dev
*z
, **a
, **b
;
46 for(z
=pacc
->devices
; z
; z
=z
->next
)
47 if (pci_filter_match(filt
, z
))
49 a
= b
= xmalloc(sizeof(struct device
*) * cnt
);
50 for(z
=pacc
->devices
; z
; z
=z
->next
)
51 if (pci_filter_match(filt
, z
))
58 exec_op(struct op
*op
, struct pci_dev
*dev
)
60 char *formats
[] = { NULL
, "%02x", "%04x", NULL
, "%08x" };
61 char *mask_formats
[] = { NULL
, "%02x->(%02x:%02x)->%02x", "%04x->(%04x:%04x)->%04x", NULL
, "%08x->(%08x:%08x)->%08x" };
64 int width
= op
->width
;
67 printf("%02x:%02x.%x:%02x", dev
->bus
, dev
->dev
, dev
->func
, op
->addr
);
69 if (op
->num_values
>= 0)
71 for(i
=0; i
<op
->num_values
; i
++)
73 if ((op
->values
[i
].mask
& max_values
[width
]) == max_values
[width
])
75 x
= op
->values
[i
].value
;
79 printf(formats
[width
], op
->values
[i
].value
);
87 y
= pci_read_byte(dev
, addr
);
90 y
= pci_read_word(dev
, addr
);
93 y
= pci_read_long(dev
, addr
);
96 x
= (y
& ~op
->values
[i
].mask
) | op
->values
[i
].value
;
100 printf(mask_formats
[width
], y
, op
->values
[i
].value
, op
->values
[i
].mask
, x
);
108 pci_write_byte(dev
, addr
, x
);
111 pci_write_word(dev
, addr
, x
);
114 pci_write_long(dev
, addr
, x
);
132 x
= pci_read_byte(dev
, addr
);
135 x
= pci_read_word(dev
, addr
);
138 x
= pci_read_long(dev
, addr
);
141 printf(formats
[width
], x
);
150 execute(struct op
*op
)
152 struct pci_dev
**vec
= NULL
;
153 struct pci_dev
**pdev
, *dev
;
158 pdev
= vec
= op
->dev_vector
;
159 while (dev
= *pdev
++)
160 for(oops
=op
; oops
&& oops
->dev_vector
== vec
; oops
=oops
->next
)
162 while (op
&& op
->dev_vector
== vec
)
168 scan_ops(struct op
*op
)
172 if (op
->num_values
>= 0)
184 static const struct reg_name pci_reg_names
[] = {
185 { 0x00, 2, "VENDOR_ID", },
186 { 0x02, 2, "DEVICE_ID", },
187 { 0x04, 2, "COMMAND", },
188 { 0x06, 2, "STATUS", },
189 { 0x08, 1, "REVISION", },
190 { 0x09, 1, "CLASS_PROG", },
191 { 0x0a, 2, "CLASS_DEVICE", },
192 { 0x0c, 1, "CACHE_LINE_SIZE", },
193 { 0x0d, 1, "LATENCY_TIMER", },
194 { 0x0e, 1, "HEADER_TYPE", },
195 { 0x0f, 1, "BIST", },
196 { 0x10, 4, "BASE_ADDRESS_0", },
197 { 0x14, 4, "BASE_ADDRESS_1", },
198 { 0x18, 4, "BASE_ADDRESS_2", },
199 { 0x1c, 4, "BASE_ADDRESS_3", },
200 { 0x20, 4, "BASE_ADDRESS_4", },
201 { 0x24, 4, "BASE_ADDRESS_5", },
202 { 0x28, 4, "CARDBUS_CIS", },
203 { 0x2c, 4, "SUBSYSTEM_VENDOR_ID", },
204 { 0x2e, 2, "SUBSYSTEM_ID", },
205 { 0x30, 4, "ROM_ADDRESS", },
206 { 0x3c, 1, "INTERRUPT_LINE", },
207 { 0x3d, 1, "INTERRUPT_PIN", },
208 { 0x3e, 1, "MIN_GNT", },
209 { 0x3f, 1, "MAX_LAT", },
210 { 0x18, 1, "PRIMARY_BUS", },
211 { 0x19, 1, "SECONDARY_BUS", },
212 { 0x1a, 1, "SUBORDINATE_BUS", },
213 { 0x1b, 1, "SEC_LATENCY_TIMER", },
214 { 0x1c, 1, "IO_BASE", },
215 { 0x1d, 1, "IO_LIMIT", },
216 { 0x1e, 2, "SEC_STATUS", },
217 { 0x20, 2, "MEMORY_BASE", },
218 { 0x22, 2, "MEMORY_LIMIT", },
219 { 0x24, 2, "PREF_MEMORY_BASE", },
220 { 0x26, 2, "PREF_MEMORY_LIMIT", },
221 { 0x28, 4, "PREF_BASE_UPPER32", },
222 { 0x2c, 4, "PREF_LIMIT_UPPER32", },
223 { 0x30, 2, "IO_BASE_UPPER16", },
224 { 0x32, 2, "IO_LIMIT_UPPER16", },
225 { 0x38, 4, "BRIDGE_ROM_ADDRESS", },
226 { 0x3e, 2, "BRIDGE_CONTROL", },
227 { 0x10, 4, "CB_CARDBUS_BASE", },
228 { 0x14, 2, "CB_CAPABILITIES", },
229 { 0x16, 2, "CB_SEC_STATUS", },
230 { 0x18, 1, "CB_BUS_NUMBER", },
231 { 0x19, 1, "CB_CARDBUS_NUMBER", },
232 { 0x1a, 1, "CB_SUBORDINATE_BUS", },
233 { 0x1b, 1, "CB_CARDBUS_LATENCY", },
234 { 0x1c, 4, "CB_MEMORY_BASE_0", },
235 { 0x20, 4, "CB_MEMORY_LIMIT_0", },
236 { 0x24, 4, "CB_MEMORY_BASE_1", },
237 { 0x28, 4, "CB_MEMORY_LIMIT_1", },
238 { 0x2c, 2, "CB_IO_BASE_0", },
239 { 0x2e, 2, "CB_IO_BASE_0_HI", },
240 { 0x30, 2, "CB_IO_LIMIT_0", },
241 { 0x32, 2, "CB_IO_LIMIT_0_HI", },
242 { 0x34, 2, "CB_IO_BASE_1", },
243 { 0x36, 2, "CB_IO_BASE_1_HI", },
244 { 0x38, 2, "CB_IO_LIMIT_1", },
245 { 0x3a, 2, "CB_IO_LIMIT_1_HI", },
246 { 0x40, 2, "CB_SUBSYSTEM_VENDOR_ID", },
247 { 0x42, 2, "CB_SUBSYSTEM_ID", },
248 { 0x44, 4, "CB_LEGACY_MODE_BASE", },
252 static void usage(void) __attribute__((noreturn
));
258 "Usage: setpci [<options>] (<device>+ <reg>[=<values>]*)*\n\
259 -f\t\tDon't complain if there's nothing to do\n\
261 -D\t\tList changes, don't commit them\n"
263 "<device>:\t-s [[<bus>]:][<slot>][.[<func>]]\n"
264 "\t|\t-d [<vendor>]:[<device>]\n"
265 "<reg>:\t\t<number>[.(B|W|L)]\n"
267 "<values>:\t<value>[,<value>...]\n"
269 " |\t<hex>:<mask>\n");
274 main(int argc
, char **argv
)
276 enum { STATE_INIT
, STATE_GOT_FILTER
, STATE_GOT_OP
} state
= STATE_INIT
;
277 struct pci_filter filter
;
278 struct pci_dev
**selected_devices
= NULL
;
279 char *opts
= GENERIC_OPTIONS
;
281 if (argc
== 2 && !strcmp(argv
[1], "--version"))
283 puts("setpci version " PCIUTILS_VERSION
);
292 while (argc
&& argv
[0][0] == '-')
315 if (e
= strchr(opts
, *c
))
334 if (!parse_generic_option(*e
, pacc
, arg
))
363 if (!c
[1] || !strchr("sd", c
[1]))
366 d
= (c
[2] == '=') ? c
+3 : c
+2;
375 if (state
!= STATE_GOT_FILTER
)
377 pci_filter_init(pacc
, &filter
);
378 state
= STATE_GOT_FILTER
;
383 if (d
= pci_filter_parse_slot(&filter
, d
))
387 if (d
= pci_filter_parse_id(&filter
, d
))
394 else if (state
== STATE_INIT
)
398 if (state
== STATE_GOT_FILTER
)
399 selected_devices
= select_devices(&filter
);
400 if (!selected_devices
[0] && !force
)
401 fprintf(stderr
, "setpci: Warning: No devices selected for `%s'.\n", c
);
402 state
= STATE_GOT_OP
;
403 /* look for setting of values and count how many */
410 for(e
=d
, n
=1; *e
; e
++)
413 op
= xmalloc(sizeof(struct op
) + n
*sizeof(struct value
));
418 op
= xmalloc(sizeof(struct op
));
420 op
->dev_vector
= selected_devices
;
431 op
->width
= 1; break;
433 op
->width
= 2; break;
435 op
->width
= 4; break;
442 ll
= strtol(c
, &f
, 16);
445 const struct reg_name
*r
;
446 for(r
= pci_reg_names
; r
->name
; r
++)
447 if (!strcasecmp(r
->name
, c
))
452 op
->width
= r
->width
;
454 if (ll
> 0x100 || ll
+ op
->width
*((n
< 0) ? 1 : n
) > 0x100)
455 die("Register number out of range!");
456 if (ll
& (op
->width
- 1))
457 die("Unaligned register address!");
459 /* read in all the values to be set */
465 ll
= strtoul(d
, &f
, 16);
466 lim
= max_values
[op
->width
];
467 if (f
&& *f
&& (*f
!= ':') ||
468 (ll
> lim
&& ll
< ~0UL - lim
))
470 fprintf(stderr
, "bad value \"%s\"\n\n", d
);
475 op
->values
[i
].value
= ll
;
477 ll
= strtoul(d
, &f
, 16);
479 (ll
> lim
&& ll
< ~0UL - lim
))
481 fprintf(stderr
, "bad value:mask pair \"%s\"\n\n", d
);
484 op
->values
[i
].mask
= ll
;
485 op
->values
[i
].value
&= op
->values
[i
].mask
;
489 op
->values
[i
].value
= ll
;
490 op
->values
[i
].mask
= ~0U;
501 if (state
== STATE_INIT
)