How to read a specific PCI device register in Linux from the CLI?

4

1

In order to control my backlight, I need to do the following:

sudo setpci -s 00:02.1 F4.B=x

This could be read as:

For the PCI device with the ID 00:02.1, set the register F4 (byte only) to x.

To figure out a value I want for x, I'd like to read its current value (in a script I'm writing). How do I do this?

Early work:

This seems to be the domain of lspci. I tried

sudo lspci -x -s 00:02.1

but this doesn't give enough range (doesn't reach register/address F4). I can do it with the -xxx command line, however. This gives me a dump at which I can see the byte at F4, which I verified I can manipulate with the setpci command. However, the manual says:

  -xxx   Show hexadecimal dump of the whole PCI configuration space. It is  available  only  to  root  as  several  PCI
         devices  crash when you try to read some parts of the config space (this behavior probably doesn't violate the
         PCI standard, but it's at least very stupid). However, such devices are rare, so you needn't worry much.

So I'd rather not put that in a program that runs automatically as root. Any way to just read the value for register F4? A getpci program? A setpci flag? Some special lspci flag I missed?

(Environment is Ubuntu Netbook Remix 9.04 (karmic) (32-bit) on a Samsung N140 netbook)

Paul Biggar

Posted 2009-12-26T00:22:09.433

Reputation: 510

non pci superset: https://unix.stackexchange.com/questions/4948/shell-command-to-read-device-registers

– Ciro Santilli 新疆改造中心法轮功六四事件 – 2017-07-21T13:26:05.970

Answers

9

You want the program setpci. It looks like this format would do what you want:

setpci -s 00:02.1 F4.B

See man setpci: the only difference with your version is you're trying to set the register, so you name it and assign a value ("F4.B=x"). Here, just name it; don't assign a value.

From the manpage:

Operations

To query value of a configuration register, just name it (either by typing its name or by typing register address with optional .B, .W or .L suffix specifying register width as byte, word or longword).

To set a register, write reg=values where reg is the same as you would use to query the register and values is a comma-separated list of values you want to write starting with the given address. Each value to be written can be specified either as a hexadecimal number or as a bits:mask pair which causes the bits corresponding to binary ones in the mask to be changed to values of the corresponding bits in the bits

quack quixote

Posted 2009-12-26T00:22:09.433

Reputation: 37 382

List all regnames with setpci --dumpregs. Also possible to use device ID directly with -d 1234:5678. – Ciro Santilli 新疆改造中心法轮功六四事件 – 2017-08-05T19:22:09.577

If you add a one line awk, you can print the values of each dumpregs register: setpci --dumpregs | gawk '{if ($2 != 0){printf("setpci -s 2e:00.0 %s.%s\n",$3,$2);system("setpci -s 2e:00.0 " $3"."$2)}}'. Needs a little more work for CAP registers, but displaying pci registers and values for a device completes the answer. – rickfoosusa – 2019-08-12T21:10:50.820

How did I not think of this. Perfect, thanks. – Paul Biggar – 2009-12-26T00:56:31.547

i would've looked for a getpci first too... – quack quixote – 2009-12-26T01:11:08.713

1

Take into account that this will not work if your display uses the new intel_backlight interface (until this date only the gnome power manager can manage it).

Please read this: https://askubuntu.com/questions/57236/unable-to-change-brightness-in-a-lenovo-laptop/81389#81389 and the links listed Especially my post (under the name Álvaro)

Álvaro

Posted 2009-12-26T00:22:09.433

Reputation: 11