Products > Embedded Computing

Is it possible to read AHCI registers using setpci on Linux?


Can anyone tell me if it's possible to use the Linux setpci utility to read values from AHCI registers for a PCIe bus SATA controller?

I'm trying to definitively determine if a SATA controller is running in legacy IDE emulation mode or AHCI mode.

Apparently, according to the AHCI specification, there is an HBA Capabilities ('CAP') register that contains a Supports AHCI Mode Only ('SAM') bit flag, and there is also a Global HBA Control ('GHC') register that contains an AHCI Enable ('AE') bit flag. If the former is '1', then the controller only does AHCI and doesn't support IDE emulation. If it is '0', then you need to check the latter GHC.AE flag to see if it is currently '1' for AHCI or '0' for IDE mode.

From the spec document, I know what the register address offsets are, but I've no idea how to translate that to arguments for setpci. I think AHCI registers are accessed via some kind of PCI MMIO scheme, so it's probably not 1:1 mapping.

I don't know to answer the question, but the Linux kernel should have a Device Tree (DT).  The DT is telling the kernel (at boot), what driver to load for each device, and any specific parameters the driver might need.  Later, that DT is mapped into a directory tree (in Linux, everything is a file), here mapped at /proc/.

For example, if I search for PCI in /proc/ of my desktop PC, there is a /proc/bus/pci/ directory, and a /proc/bus/pci/devices file.  Inside that file there is a line contaning the text ahci, and some addresses/registers.

See if you can make use of any of that info, in order to find the address you are interested in, though never tried that myself.

No idea if this could help changing the settings you are after, if it applies to your OS flavor, or if it brings anything extra other than setpci can already do/show (I don't know much about setpci).  But if it does, then it should be possible to decompile the (binary) device tree that is in use, edit the decompiled DT to add your changes in the DT sources, then recompile the DT (the decompiler/compiler is called dtc), so to make your changes persistent after a reboot.

AFAIK setpci only access the configuration address space of PCI. If the registers you are looking for are there then you are set. If they are in some MMIO region, I don't see a way of reading them with setpci.

However, the related lspci (with -v flag) will tell you where the MMIO registers are mapped in the CPU physical address space. Knowing this, you could presumably read them by means of /dev/mem or something like that (note: in recent times there were some attempts to restrict or completely remove this mechanism on security grounds and I'm not sure how it works in mainstream distributions these days).

I did actually find a way to do it in the end. I meant to come back here and post an update but it slipped my mind.

The AHCI register contents memory region is actually exposed in sysfs, in /sys/bus/pci/devices/<device id>/resource5. It is the same "Resource 5" (aka "Region 5", "BAR5") mentioned in lspci verbose output. But you can't just read that file - oh, no, that would be too easy! :P It has to be accessed using mmap IO. I found a utility on GitHub that will do so:

--- Code: ---$ sudo ./pcimem /sys/bus/pci/devices/0000:01:00.0/resource5 0 w*128
/sys/bus/pci/devices/0000:01:00.0/resource5 opened.
Target offset is 0x0, page size is 16384
mmap(0, 4096, 0x3, 0x1, 3, 0x0)
PCI Memory mapped to address 0x7fffa9fbc000.
0x0000: 0xEB32FFA1
0x0004: 0x80000002
0x0008: 0x00000000
0x000C: 0x00000003
0x0010: 0x00010200
0x0014: 0x00000010
0x0018: 0x00000000

--- End code ---

The arguments to the command tell it to read 128 32-bit words starting from offset zero. The AHCI register space on my particular SATA controller is 512 bytes, because it only features 2 ports. With more ports the register space will be larger.

The GHC.AE (AHCI mode enabled) register flag is bit 31 of the word at offset 0x0004. You can see here that it is set. :D


[0] Message Index

There was an error while thanking
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod