Thank you Lazlo for a very detailed response. Based on your writeup, I think 1
b) will be the most suitable. I will post if I run into troubles.
Shubha Shubha D. [email protected]
[email protected]
On Tuesday, September 22, 2015 11:59 AM, Laszlo Ersek <[email protected]>
wrote:
On 09/22/15 20:02, Shubha Ramani wrote:
> Hi there. I have a need to read some PCI Space Registers with identified by a
> Bus, Device, Function and finally an Offset.Is there an EDK2 service or
> protocol for this ?
Depends on the kind of module you want to do this in:
1. In a UEFI driver or application, you should use the PciIo protocol.
1a. You can try to locate the right protocol instance via device path
search (ie. based on the device path protocol instance that is installed
on the same handle as the PciIo protocol instance). The most appropriate
boot service seems to be LocateDevicePath().
You'll get a handle. You should verify that the device path match is
exact. Then use OpenProtocol() with GET_PROTOCOL to grab the PciIo
interface on the same handle (without reference counting, ie. only
temporarily), then use PciIo->Pci.Read() to read the config space.
1b. You can also try to enumerate all PciIo protocol interfaces in the
system, with LocateHandleBuffer(). Then for each handle, use
OpenProtocol() with GET_PROTOCOL again, to arrive at the PciIo protocol
instance installed on the handle. In order to filter out each handle
that doesn't match your B/D/F requirement, call PciIo->GetLocation(),
and compare the returned B/D/F against your requirement.
One important difference between (1a) and (1b) is that handles
corresponding to PCI devices behind a bridge (or several bridges) will
have device paths installed on them that explains the "physical path" in
the system. They will reflect hierarchy. On the other hand, the B/D/F
triplet is flat (let's assume a single segment now), and is assigned by
the PCI Bus driver during enumeration. So you should decide if (1a) or
(1b) is more appropriate for you.
Here's an example: when someone uses libvirt to configure a Q35 machine
type for a QEMU virtual machine, libvirt inserts a DMI-to-PCI bridge
into the PCIe root controller, then a PCI-to-PCI bridge into that. (The
reasons exceed the scope of this email, but it's being done due to
hotplug restrictions.) So, for an example device behind these two
bridges, the device path you'd look for in (1a) is:
PciRoot(0x0)/Pci(0x1E,0x0)/Pci(0x1,0x0)/Pci(0x7,0x1)
whereas in (1b) you'd filter for the B/D/F triplet programmed by the PCI
Bus driver:
02:07.1
2. In a module that is supposed to run before DXE, or inside DXE but
without PciIo protocols anyway, you can use the PciLib edk2 library
class. The header file is "MdePkg/Include/Library/PciLib.h".
(
There's a bunch of library instances (library implementations) for that
interface; you can search for them with:
git grep 'LIBRARY_CLASS *= *PciLib\>' -- '*.inf'
)
For example, to read "an 8-bit PCI configuration register", you'd call
the PciRead8() function. This family of function takes device addresses
akin to (1b) above, but you need to use a macro to encode B/D/F first
into a flat UINTN address, and then pass that flat value to PciRead8().
The macro is PCI_LIB_ADDRESS(). It also takes the register offset as
(fourth) parameter; you can find macros for the standard registers in
the MdePkg/Include/IndustryStandard/Pci*.h files.
Of course this will only work if you either know the exact B/D/F you
need, or you are willing to probe the entire B/D/F space (eg. for vendor
/ device / subsystem IDs in the config header) in order to find your
device. And, I believe, if you do this without PCI bus enumeration /
assignment, then devices behind bridges won't respond.
> Please advise.
HTH,
Laszlo
> Thanks,
> Shubha Shubha D. [email protected]
> [email protected]
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel
>
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel