PCI Clarification

Hey Guys

My company sort of threw im in on the deepside a while ago.
Im tasked with writing a PCI driver for one of the projects.
All I need to be able to do is allocate a block of memory and be able to read and write to and from it.
But its really not that simple…or at least its not that simple to me.
Were using the PLX 9054 chip to transfer data between an FPGA and the rest of the system.

Im having a couple of problems with the PCI driver including not fully understanding how it works.Ive slaved over the Data sheets and PLX book but the water still seems murky especially for the little R&D time I have been given.
There is really little resources and support from official QNX side unfortunately and if im going to have to figure this out on my own (which ive done a great deal of so far)…its going to take me way to long.

What im trying to do here is just open up the PLX chip with its VendorId and DeviceId. But 2 thing happen that I dont fully understand.
After calling pci_attach(0) I assign the Vendor ID and Device ID of the device I want the handler to be attached to .
Then I run the pci_attach_device() and in there I add the handler I want it to be connected to which after doing so seems to return a legit Address that the handler points to.
Then after that I try and read all the address registers to see if its the right card im trying to READ/ACCESS.
First problem I run into is that it ISNT the right card… The card that however does come up is an existing card. WHY did it attach that card instead of the one I assigned to it?
Also… if I try and read config registers for that card using handler or Device Function/BUS the one Fails and the other one succeeds(There’s more specific info in the comments about this problem).
The other problem is that it doesn’t seem to fill the array up with the information completely because when I try and read " info.BaseAddressSize[i] " it just comes back as 0x00.

Now I have done this one before and it did do the right thing by actually assigning the cards that I have saved into the DeviceID etc BUT I just cant seem to find what I am doing wrong here.

I would also like to know whats the difference between the 2 functions Im using.
Will I be able to write to the BAR Registers using pci_write_config() or pci_write_config32()?
In the picture that I uploaded I circled an Area.

In that red area I would like to know… That means that in ADDRESS 0xb0341ea008047cd0 a number of 134511852 bytes have been assigned as MEMORY bytes? How do I access them … Simply via pointer? No special DMA functions etc needed?

My problematic programs OUTPUT will be pasted below the code.

#include <stdio.h>
#include <stdlib.h>
#include <hw/pci.h>
#include <sys/mman.h>

void sCheck(int r);

int NumberOfPciCards = 1; //Only have 1
struct pci_dev_info info; //Defined PCI info structs found in hw/pci.h
info.VendorId = 0x10b5; //Fill info[0] with the PCI9054 VendorID details.
info.DeviceId = 0x9054; //Fill info[0] with PCI9054 DeviceID details
//I defined my pointers like this to make sure I allocate memory for them…its not
// neat practice but Ill make it look nicer later.
void *PciDevHand0;//Handler for my only device
uint32_t *Buffer; Buffer = (uint32_t *)malloc(sizeof(uint32_t)); //This buffer will be used to read out of the PCI Config Regsiters
int BusNumb; BusNumb = (int)malloc(sizeof(int));
*BusNumb =0;
int r,i,y;

memset(&info, 0, sizeof(info));

printf("pci_attach(0) returned address = 0x%x",pci_attach(0)); //This just prints the address assigned to index 0;

PciDevHand0 = pci_attach_device(0,PCI_SHARE|PCI_INIT_ALL, 0, &info); //Assigns address to the PCI0 device handler
if( PciDevHand0 == NULL ) {fprintf( stderr, "Unable to locate adapter\n" );}
else {printf("\n PciDevHand0 address = 0x%x",PciDevHand0);} 


for (r=0x00;r<0x3c;r=r+0x04)

/*Here I use 2 different functions to read the same address... The one returns Failure but still reads the value and the
 * config32 function returns with success and also writes out the register which seems to be a whole lot of ones(0xffffffff).
 *Also the pci_read_config function has a SIZE parameter...the web site gives it this description "The number of 32-bit values to read."
 *But when I change this to either 0 or 32 it returns failure... However when it is 2 it works for some reason?
 *Another thing that I have noticed is that in both cases it doesnt get the VendorID or DeviceID that I supplied to it...It gets something else.
 *Even if I do pass in the handler that I have assigned to that VendorID.If this is right then whats the use of supplying the
 *vendor and device info?

if((i=pci_read_config32(2,0,r,32,Buffer))==0) //
{printf("\nConfig32 : 0x%x : 0x%x\n",r,*Buffer);sCheck(i);}
*Buffer = 0xdeadbeef; // I reset the value to something that Id know so that I can see if it is altered or not.
if((i=(pci_read_config(PciDevHand0,r,32,2,Buffer)))>-5)//I want it to print with errors hench -5
{printf("\nConfig : 0x%x : 0x%x\n",r,*Buffer);sCheck(i);}


//This part of the code doesnt seem to run since I cant get the right BaseAddressSize to write into the array from the pci_attach_device().
for (i = 0; i < 6; i++)
		if (info.BaseAddressSize[i] > 0)
			printf("Aperture %d: ""Base 0x%llx Length %d bytes Type %s\n", i,
					PCI_IS_MEM(info.CpuBaseAddress[i]) ?
					PCI_MEM_ADDR(info.CpuBaseAddress[i]) :
					PCI_IS_MEM(info.CpuBaseAddress[i]) ? "MEM" : "IO");


void sCheck(int r)
if (r==0x00)
else if(r==0x87)
else if(r==0x89)
else if (r=0x86)


pci_attach(0) returned address = 0x3
 PciDevHand0 address = 0x8070700

Config32 : 0x0 : 0xffffffff

Config : 0x0 : 0x35808086

Config32 : 0x4 : 0xffffffff

Config : 0x4 : 0x20900106

Config32 : 0x8 : 0xffffffff

Config : 0x8 : 0x6000002

Config32 : 0xc : 0xffffffff

Config : 0xc : 0x800000

Config32 : 0x10 : 0xffffffff

Config : 0x10 : 0x8

Config32 : 0x14 : 0xffffffff

Config : 0x14 : 0x0

Config32 : 0x18 : 0xffffffff

Config : 0x18 : 0x0

Config32 : 0x1c : 0xffffffff

Config : 0x1c : 0x0

Config32 : 0x20 : 0xffffffff

Config : 0x20 : 0x0

Config32 : 0x24 : 0xffffffff

Config : 0x24 : 0x0

Config32 : 0x28 : 0xffffffff

Config : 0x28 : 0x0

Config32 : 0x2c : 0xffffffff

Config : 0x2c : 0x40021059

Config32 : 0x30 : 0xffffffff

Config : 0x30 : 0x0

Config32 : 0x34 : 0xffffffff

Config : 0x34 : 0x40

Config32 : 0x38 : 0xffffffff

Config : 0x38 : 0x0

Just a quick glace at your code:

PciDevHand0 = pci_attach_device(0,PCI_SHARE|PCI_INIT_ALL, 0, &info); //Assigns address to the PCI0 device handler

I think you want to add PCI_SEARCH_VENDEV to your flags field to find just the vendor/device you specified in your info structure. Otherwise it’s probably just attaching to the first thing it sees.


You are right Tim.
However now that I do have that flag set it doesnt find any card at all even though I know for a fact that its in there and registered when I run " PCI -vvv | less " .

Also… in the function pci_read_config();
The two parameters are a bit cryptic and doesn’t seem to do anything when I change them accept totally corrupt the data in the buffer im saving too mostly with " 0xffffffff "!

They say:

count - > The number of objects that you want to read. // Ok but what determines an object? The subsections in the registers for instance in 0x00 it would be DeviceID and VendorID?


size - > The size of each object. //In bits or bytes?Using it as either of them doesn’t seem to make a difference though :confused:

WIll this be a legit call of the function → pci_read_config(PciDeviceHandler2,0x48,1,8,Buffer); ?