i have written to 0xcf8. After that tried to access (read) pci configuration space from location 0xcfc and got a garbage value. Please give me any suggestion or direction in this regard.
The code i have used.......(as follows):
#include<stdio.h>
#include<stdlib.h>
#include<linux/pci.h>
#include<sys/io.h>
#include<kernel/pci.h>
#define INDEX_PCI 0xCF8
#define DATA_PCI 0xCFC
long __read_PCI_config (long _devvid, int _offset); //Function prototype
void main (void)
{
unsigned int i;
printf("\n in main \n ");
printf("DVID: 0x20811022 offset 0x10 = 0x%08x",__read_PCI_config(0x3a30, 0x10));
printf("\n i= %d \n",i);
i=pci_read_word(0xCFC,0);
printf("\n i= %d\n",i);
}
long __read_PCI_config (long _devvid, int _offset)
// This function will return the data from the supplied offset into the PCI configuration
// space of the first device found that matches the supplied Device and Vendor ID or zero
// if no match is found.
{
long scankey;
int bus, device, function,i;
printf("\n in read pci");
fflush(stdout);
i=ioperm(3320,32,1);
printf("\n value of ioperm ret =%d",i);
//Search each bus, device, function...
for(bus = 0; bus < 256; bus++)
{
for(device = 0; device < 32; device++)
{
for(function = 0;function < 8; function++)
{
outl((8 << 28 | bus << 16 | device << 11 | function << 8 ),INDEX_PCI);
i=ioperm(3324,64,1);
scankey = inl(DATA_PCI);
//printf("\n scan key = %d ",scankey);
if (scankey == _devvid)
{
printf("\n in 2nd if");
outl(( (8 << 28 | bus << 16 | device << 11 | function << 8 ) + _offset),INDEX_PCI);
return inl_p( DATA_PCI );
}
}
}
}
printf("\n ioperm for CFC =%d",i);
printf("\n scan key= %u",scankey);
//No Match
return 0L;
}
unable to read pci config address(0xcfc) data;
Re: unable to read pci config address(0xcfc) data;
Firstly, I wouldn't suggest scanning the whole pci tree to find a vendor/device id each time..
I would have a read_pci function which takes (bus,device,function,ofs) and just reads that.
You'd enumerate the bus and store the relevant mapping so you know exactly which bus/dev/func corresponds to which device you want to read/write.
I'm not sure about this line:
printf("DVID: 0x20811022 offset 0x10 = 0x%08x",__read_PCI_config(0x3a30, 0x10));
you're passing in a long (assuming this is compiling as a dword(32bit))
that is support to contain both the vendor and device id .. 0x3a30 is a short so some part is implied to be 0000?
Hence why my above suggest about the function with separate parameters would make it easier to use and verify (as you can also ensure that each parameter is withing range including function (<0x3f) and ofs etc.
I would have a read_pci function which takes (bus,device,function,ofs) and just reads that.
You'd enumerate the bus and store the relevant mapping so you know exactly which bus/dev/func corresponds to which device you want to read/write.
I'm not sure about this line:
printf("DVID: 0x20811022 offset 0x10 = 0x%08x",__read_PCI_config(0x3a30, 0x10));
you're passing in a long (assuming this is compiling as a dword(32bit))
that is support to contain both the vendor and device id .. 0x3a30 is a short so some part is implied to be 0000?
Hence why my above suggest about the function with separate parameters would make it easier to use and verify (as you can also ensure that each parameter is withing range including function (<0x3f) and ofs etc.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: unable to read pci config address(0xcfc) data;
Why are you picking a fight with the linux kernel and not using lspci?nuralam89 wrote:#include<linux/pci.h>
how does pci device information is mapped or initialize.....
Hi,
Is the Configuration Mechanism described in the PCI spec for software
implementation(ie OS implementation). actually i am trying to
implement a tiny bootable piece of code(a kind of small Operating
system) through which(by writing code) i want to access data from hard
disk.
i have tried a bit to write pci CONFIG_ADDRESS and read data from config_DATA.
but it returned 0 each time( I gave different Device _ID from 'lspci' info) .
I have few queries in this regard.
1.Does pci bus and device needs insitalization(i mean to map specific bus and device) if so than how it works(is their any protocol??)??
2.if i try to access the CONFIG_ADDRESS & CONFIG_DATA in my piece of bootable code(where i just wrote a piece of nasm assembly code & linker to boot; printing a string on VGA-memory part after booting and it will hang there.i have not done any kind of mapping or initilization) what information it should provide??
3. in "pci.h" struct pci_dev{...} who initializes or maps the sub field of this struct data type.
4.specifically how does kernel initialize different device to different bus number so that we can access information about the device by reading CONFIG_ADDRESS & CONFIG_DATA by different predefined offset value(i.e. 0x0e for HEADER).
Is the Configuration Mechanism described in the PCI spec for software
implementation(ie OS implementation). actually i am trying to
implement a tiny bootable piece of code(a kind of small Operating
system) through which(by writing code) i want to access data from hard
disk.
i have tried a bit to write pci CONFIG_ADDRESS and read data from config_DATA.
but it returned 0 each time( I gave different Device _ID from 'lspci' info) .
I have few queries in this regard.
1.Does pci bus and device needs insitalization(i mean to map specific bus and device) if so than how it works(is their any protocol??)??
2.if i try to access the CONFIG_ADDRESS & CONFIG_DATA in my piece of bootable code(where i just wrote a piece of nasm assembly code & linker to boot; printing a string on VGA-memory part after booting and it will hang there.i have not done any kind of mapping or initilization) what information it should provide??
3. in "pci.h" struct pci_dev{...} who initializes or maps the sub field of this struct data type.
4.specifically how does kernel initialize different device to different bus number so that we can access information about the device by reading CONFIG_ADDRESS & CONFIG_DATA by different predefined offset value(i.e. 0x0e for HEADER).
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: unable to read pci config address(0xcfc) data;
Assuming you ran your bootloader on the same machine as where you ran lspci, and you didn't use an emulator or VM, post the following:but it returned 0 each time( I gave different Device _ID from 'lspci' info) .
- What value did you send to 0xcf8, what value did you read from 0xcfc, and what instructions did you use to do that?
- How did you, with explanations and citing sources, calculate the value you sent to port 0xcf8?
The BIOS configures the PCI bus and makes sure config space works. You don't need to initialize individual devices for what you want to do.1.Does pci bus and device needs insitalization
Any #include of linux code into your own bootloader is wrong. period.3. in "pci.h" struct pci_dev{...} who initializes or maps the sub field of this struct data type.
what type of information Base Address Register(BAR) provides
hi,
what type of information Base Address Register(BAR) provides??is it a Address range of a device? or Starting adress address?
actually i am trying to
implement a tiny bootable piece of code(a kind of small Operating
system) through which(by writing code) i want to access data from hard
disk.
If it(BAR) provides Address ranges of a device then what should be a starting address.
P.S.: using following code i have got a number other than zero from only BAR no-05 i.e. offset 0x24.
#include<stdio.h>
#include<stdlib.h>
//#include<linux/pci.h>
#include<sys/io.h>
//#include<kernel/pci.h>
#define INDEX_PCI 0xCF8
#define DATA_PCI 0xCFC
long __read_PCI_config (long _devvid, int _offset); //Function prototype
void value(long _devvid,int _offset);
void main (void)
{
unsigned int i;
printf("\n in main \n ");
printf("\n val= %x",__read_PCI_config(0x2363197b,0x00));//where 0x2363 & 197b is the deviceID and vendorID of my SATA Controller
printf("\n i= %d \n",i);
value(0x2363197b,0x24);
printf("\n i= %d\n",i);
}
long __read_PCI_config (long _devvid, int _offset)
// This function will return the data from the supplied offset into the PCI configuration
// space of the first device found that matches the supplied Device and Vendor ID or zero
// if no match is found.
{
long scankey;
int bus, device, function,i;
printf("\n in read pci");
fflush(stdout);
i=iopl(3);
//printf("\n value of ioperm ret =%d",i);
//Search each bus, device, function...
for(bus = 0; bus < 256; bus++)
{
for(device = 0; device < 32; device++)
{
for(function = 0;function < 8; function++)
{
outl((8 << 28 | bus << 16 | device << 11 | function << 8 ),INDEX_PCI);
i=iopl(3);
//printf("\n the value of iopl return in OUTL is= %d",i);
scankey = inl(0xCFC);
//printf("\n the valscan key = %x ",scankey);
if (scankey == _devvid)
{
printf("\n Device found");
// value(scankey,0x01);
outl(( (8 << 28 | bus << 16 | device << 11 | function << 8 ) + _offset),INDEX_PCI);
return inl( DATA_PCI );
}
}
}
}
//printf("\n ioperm for CFC =%d",i);
printf("\n scan key= %u",scankey);
//No Match
return 0L;
}
long read_PCI_config (long _devvid, int _offset)
// This function will return the data from the supplied offset into the PCI configuration
// space of the first device found that matches the supplied Device and Vendor ID or zero
// if no match is found.
{
long scankey;
int bus, device, function,i;
//printf("\n in read pci");
fflush(stdout);
i=iopl(3);
for(bus=0;bus<256;bus++)
{
for(device = 0; device < 32; device++)
{
for(function = 0;function < 8; function++)
{
outl((8 << 28 | bus << 16 | device << 11 | function << 8 ),INDEX_PCI);
i=iopl(3);
//printf("\n the value of iopl return in OUTL is= %d",i);
scankey = inl(0xCFC);
//printf("\n the valscan key = %x ",scankey);
if (scankey == _devvid)
{
printf("\n Device found");
outl(( (8 << 28 | bus << 16 | device << 11 | function << 8 ) +0x24),INDEX_PCI);
return inl( DATA_PCI );
}
}
}
}
//printf("\n ioperm for CFC =%d",i);
printf("\n scan key= %x",scankey);
//No Match
return 0L;
}
void value(long _devvid,int _offset)
{
int i;
i=iopl(3);
printf("\n ReturnValue in Value Function= %x",read_PCI_config(0x2363197b,0x24));
}
********************************************************************************************************************************************************
OUTPUT
********************************************************************************************************************************************************
in main
in read pci
Device found
val= 2363197b
i= 0
Device found
ReturnValue in Value Function= feafe000
i= 0
BEFORE WRITE INL VALUE IS:feafe000
AT=feafe000
The INL VALUE is:feafe000
Device found
After Write Return value is:=feafe000
**********************************************************************************************************************************************************
my query is what is the significance of this '0xfeafe000' which i have got from BAR 05 i.e. offset 0x24.
what type of information Base Address Register(BAR) provides??is it a Address range of a device? or Starting adress address?
actually i am trying to
implement a tiny bootable piece of code(a kind of small Operating
system) through which(by writing code) i want to access data from hard
disk.
If it(BAR) provides Address ranges of a device then what should be a starting address.
P.S.: using following code i have got a number other than zero from only BAR no-05 i.e. offset 0x24.
#include<stdio.h>
#include<stdlib.h>
//#include<linux/pci.h>
#include<sys/io.h>
//#include<kernel/pci.h>
#define INDEX_PCI 0xCF8
#define DATA_PCI 0xCFC
long __read_PCI_config (long _devvid, int _offset); //Function prototype
void value(long _devvid,int _offset);
void main (void)
{
unsigned int i;
printf("\n in main \n ");
printf("\n val= %x",__read_PCI_config(0x2363197b,0x00));//where 0x2363 & 197b is the deviceID and vendorID of my SATA Controller
printf("\n i= %d \n",i);
value(0x2363197b,0x24);
printf("\n i= %d\n",i);
}
long __read_PCI_config (long _devvid, int _offset)
// This function will return the data from the supplied offset into the PCI configuration
// space of the first device found that matches the supplied Device and Vendor ID or zero
// if no match is found.
{
long scankey;
int bus, device, function,i;
printf("\n in read pci");
fflush(stdout);
i=iopl(3);
//printf("\n value of ioperm ret =%d",i);
//Search each bus, device, function...
for(bus = 0; bus < 256; bus++)
{
for(device = 0; device < 32; device++)
{
for(function = 0;function < 8; function++)
{
outl((8 << 28 | bus << 16 | device << 11 | function << 8 ),INDEX_PCI);
i=iopl(3);
//printf("\n the value of iopl return in OUTL is= %d",i);
scankey = inl(0xCFC);
//printf("\n the valscan key = %x ",scankey);
if (scankey == _devvid)
{
printf("\n Device found");
// value(scankey,0x01);
outl(( (8 << 28 | bus << 16 | device << 11 | function << 8 ) + _offset),INDEX_PCI);
return inl( DATA_PCI );
}
}
}
}
//printf("\n ioperm for CFC =%d",i);
printf("\n scan key= %u",scankey);
//No Match
return 0L;
}
long read_PCI_config (long _devvid, int _offset)
// This function will return the data from the supplied offset into the PCI configuration
// space of the first device found that matches the supplied Device and Vendor ID or zero
// if no match is found.
{
long scankey;
int bus, device, function,i;
//printf("\n in read pci");
fflush(stdout);
i=iopl(3);
for(bus=0;bus<256;bus++)
{
for(device = 0; device < 32; device++)
{
for(function = 0;function < 8; function++)
{
outl((8 << 28 | bus << 16 | device << 11 | function << 8 ),INDEX_PCI);
i=iopl(3);
//printf("\n the value of iopl return in OUTL is= %d",i);
scankey = inl(0xCFC);
//printf("\n the valscan key = %x ",scankey);
if (scankey == _devvid)
{
printf("\n Device found");
outl(( (8 << 28 | bus << 16 | device << 11 | function << 8 ) +0x24),INDEX_PCI);
return inl( DATA_PCI );
}
}
}
}
//printf("\n ioperm for CFC =%d",i);
printf("\n scan key= %x",scankey);
//No Match
return 0L;
}
void value(long _devvid,int _offset)
{
int i;
i=iopl(3);
printf("\n ReturnValue in Value Function= %x",read_PCI_config(0x2363197b,0x24));
}
********************************************************************************************************************************************************
OUTPUT
********************************************************************************************************************************************************
in main
in read pci
Device found
val= 2363197b
i= 0
Device found
ReturnValue in Value Function= feafe000
i= 0
BEFORE WRITE INL VALUE IS:feafe000
AT=feafe000
The INL VALUE is:feafe000
Device found
After Write Return value is:=feafe000
**********************************************************************************************************************************************************
my query is what is the significance of this '0xfeafe000' which i have got from BAR 05 i.e. offset 0x24.
-
- Member
- Posts: 5588
- Joined: Mon Mar 25, 2013 7:01 pm
Re: unable to read pci config address(0xcfc) data;
Why are you still picking a fight with the linux kernel and not using lspci?nuralam89 wrote:iopl(3);
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: unable to read pci config address(0xcfc) data;
Please take in consideration the forum rules that ask you to search before posting: http://wiki.osdev.org/PCI#Base_Address_Registers, and to use tags
Code: Select all