📄 pciconfigration.cpp
字号:
//把数据从PCI的配置空间上读取出来。
ULONG PciReadConfig( UCHAR bus, UCHAR dev, UCHAR func, OFFSET offset, SIZE size )
{
RESULT value = 0;
ULONG callfun;
switch ( size ) {
case 1:
callfun = PCIBIOS_READ_CONFIG_BYTE;
break;
case 2:
callfun = PCIBIOS_READ_CONFIG_WORD;
break;
case 4:
callfun = PCIBIOS_READ_CONFIG_DWORD;
break;
default:
Die("PciReadConfig: bad input\n");
};
ULONG ret;
ULONG bx = ( bus << 8 ) | (dev<<3) | func;
/*BL = device/function number (bits 7-3 device, bits 2-0 function)
BH = bus number
*/
__asm__("lcall *(%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
:"=c"( value ),
"=a"( ret )
:"1"( callfun ),
"b"( bx ),
"D"( (ULONG) offset ), //offset form 0~FFh
"S"( &PciEntry ) );
if( (ret>>8)&0xFF )
{
DbgPrintf("Read Config error. status=%d\n", ret );
return 0;
}
return value;
} //function
//把数据写进PCI的配置空间
RESULT PciWriteConfig( UCHAR bus, UCHAR dev, UCHAR func, OFFSET offset, SIZE size, ULONG value )
{
ULONG callfun;
switch ( size ) {
case 1:
callfun = PCIBIOS_WRITE_CONFIG_BYTE;
break;
case 2:
callfun = PCIBIOS_WRITE_CONFIG_WORD;
break;
case 4:
callfun = PCIBIOS_WRITE_CONFIG_DWORD;
break;
default:
Die("PciReadConfig: bad input\n");
};
ULONG ret;
ULONG bx = ( bus << 8 ) | (dev<<3) | func;
__asm__("lcall *(%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
:"=a"( ret )
:"a"( callfun ),
"b"( bx ),
"c"( value ),
"D"( (ULONG) offset ), //offset form 0~FFh
"S"( &PciEntry ) );
if( (ret>>8)&0xFF )
{
DbgPrintf("Read Config error. status=%d\n", ret );
return FALSE;
}
} //function
//读PCI配置空间, without bios
ULONG PciIoReadConfig( UCHAR bus, UCHAR dev, UCHAR func, OFFSET offset, SIZE size )
{
t_32 address;
/*
31 30 - 24 23 - 16 15 - 11 10 - 8 7 - 2 1 - 0
Enable Bit Reserved Bus Number Device Number Function Number Register Number 00
*/
address = (t_32)((bus << 16) | (dev << 11) |
(func << 8) | (offset & 0xfc) | ((t_32)0x80000000));
OutDWord (0xCF8, address);
t_16 tmp = 0;
/* read in the data */
tmp = (t_16)((InDWord (0xCFC) >> ((offset & 2) * 8)) & 0xffff);
switch ( size ) {
case 1:
return (tmp&0xFF);
break;
case 2:
return (tmp);
break;
default:
Die("PciReadConfig: bad input\n");
};
}
RESULT GetBiosService( t_32 srvSign, MEMADDR *SrvAddr ) {
UCHAR ret;
MEMADDR addr, entry;
SIZE len;
__asm__("lcall *(%%edi)"
:"=a" (ret),
"=b" (addr),
"=c" (len),
"=d" (entry)
:"0" (srvSign),
"1" (0),
"D" (&Bios32Entry));
switch ( ret ){
case 0:
*SrvAddr=addr+entry;
return TRUE;
case 0x80:
DbgPrintf("BIOS32 Service (0x%X) not present!\n", srvSign );
return FALSE;
}
DbgPrintf("BIOS32 Error: x%X\n", ret);
return FALSE;
}
RESULT PciReadHeader( PPciUnit pPci, UCHAR bus, UCHAR dev, UCHAR func )
{
t_16 temp2;
pPci->Bus = bus;
pPci->Driver = dev;
pPci->Function = func;
pPci->VendorID = PciReadConfig( bus, dev, func, PCI_VENDOR_ID, 2 );
pPci->DeviceID = PciReadConfig( bus, dev, func, PCI_DEVICE_ID, 2 );
//DbgPrintf( "vendor %x, device %x\n", pPci->VendorID, pPci->DeviceID );
pPci->Command = PciReadConfig( bus, dev, func, PCI_COMMAND, 2 );
pPci->Status = PciReadConfig( bus, dev, func, PCI_STATUS, 2 );
pPci->RevisionID = PciReadConfig( bus, dev, func, PCI_REVISION, 2 );
pPci->Interface = PciReadConfig( bus, dev, func, PCI_INTERFACE, 1 );
pPci->ClassCode = PciReadConfig( bus, dev, func, PCI_CLASS_CODE, 1 );
pPci->SubClass = PciReadConfig( bus, dev, func, PCI_SUB_CLASS, 1 );
//下面读取了基址之后,还要解码,取得存储大小。
//之后记得恢复原来的基址值,Over! huang 2007-2-7 11:57
pPci->u.NonBridge.BaseAddress0 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 0, 4 );
if ( pPci->u.NonBridge.BaseAddress0 ) {
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 0, 4, 0xFFFFFFFF );
temp2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 0, 4 ) & 0xFFFFFFF0;
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 0, 4, pPci->u.NonBridge.BaseAddress0 );
temp2 = 1 + ~temp2;
//DbgPrintf( "0: %x -> %x\n", pPci->u.NonBridge.BaseAddress0, temp2 );
pPci->u.NonBridge.BaseAddressSize0 = temp2;
}
pPci->u.NonBridge.BaseAddress1 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 4, 4 );
if ( pPci->u.NonBridge.BaseAddress1 ) {
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 4, 4, 0xFFFFFFFF );
temp2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 4, 4 ) & 0xFFFFFFF0;
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 4, 4, pPci->u.NonBridge.BaseAddress1 );
temp2 = 1 + ~temp2;
//DbgPrintf( "%x -> %x\n", pPci->u.NonBridge.BaseAddress1, temp2 );
pPci->u.NonBridge.BaseAddressSize1 = temp2;
}
pPci->u.NonBridge.BaseAddress2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 8, 4 );
if ( pPci->u.NonBridge.BaseAddress2 ) {
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 8, 4, 0xFFFFFFFF );
temp2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 8, 4 ) & 0xFFFFFFF0;
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 8, 4, pPci->u.NonBridge.BaseAddress2 );
temp2 = 1 + ~temp2;
//DbgPrintf( "%x -> %x\n", pPci->u.NonBridge.BaseAddress2, temp2 );
pPci->u.NonBridge.BaseAddressSize2 = temp2;
}
pPci->u.NonBridge.BaseAddress3 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 12, 4 );
if( pPci->u.NonBridge.BaseAddress3 ) {
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 12, 4, 0xFFFFFFFF );
temp2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 12, 4 ) & 0xFFFFFFF0;
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 12, 4, pPci->u.NonBridge.BaseAddress3 );
temp2 = 1 + ~temp2;
//DbgPrintf( "%x -> %x\n", pPci->u.NonBridge.BaseAddress3, temp2 );
pPci->u.NonBridge.BaseAddressSize3 = temp2;
}
pPci->u.NonBridge.BaseAddress4 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 16, 4 );
if ( pPci->u.NonBridge.BaseAddress4 ) {
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 16, 4, 0xFFFFFFFF );
temp2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 16, 4 ) & 0xFFFFFFF0;
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 16, 4, pPci->u.NonBridge.BaseAddress4 );
temp2 = 1 + ~temp2;
//DbgPrintf( "%x -> %x\n", pPci->u.NonBridge.BaseAddress4, temp2 );
pPci->u.NonBridge.BaseAddressSize4 = temp2;
}
pPci->u.NonBridge.BaseAddress5 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 20, 4 );
if ( pPci->u.NonBridge.BaseAddress5 ) {
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 20, 4, 0xFFFFFFFF );
temp2 = PciReadConfig( bus, dev, func, PCI_BASE_REGISTERS + 20, 4 ) & 0xFFFFFFF0;
PciWriteConfig( bus, dev, func, PCI_BASE_REGISTERS + 20, 4, pPci->u.NonBridge.BaseAddress5 );
temp2 = 1 + ~temp2;
//DbgPrintf( "%x -> %x\n", pPci->u.NonBridge.BaseAddress5, temp2 );
pPci->u.NonBridge.BaseAddressSize5 = temp2;
}
pPci->u.NonBridge.InterruptLine = PciReadConfig( bus, dev, func, PCI_INTERRUPT_LINE, 1 );
pPci->u.NonBridge.InterruptPIN = PciReadConfig( bus, dev, func, PCI_INTERRUPT_PIN, 1 );
pPci->u.NonBridge.MinDMATime = PciReadConfig( bus, dev, func, PCI_MIN_GRANT, 1 );
pPci->u.NonBridge.MaxDMALatency = PciReadConfig( bus, dev, func, PCI_MAX_LATENCY, 1 );
return TRUE;
}
//深度优先搜索算法,有点像Linux那个,呵呵!
RESULT ScanBus(NUMBER bus)
{
PPciUnit pPci;
UCHAR dev, func, headerType;
PciBusses ++;
t_16 vendorID, deviceID;
for( dev=0; dev<32; dev++ )
{
for( func=0; func<8; func++ )
{
vendorID = PciReadConfig( bus, dev, func, PCI_VENDOR_ID, 2 );
if( vendorID!=0xFFFF && vendorID != 0x0000 ){
if( func == 0 ){
headerType = PciReadConfig( bus, dev, func, PCI_HEADER_TYPE, 1 );
}else{
if ((headerType&PCI_MULTIFUNCTION) == 0 ) {
continue;
}
}
pPci = KMalloc( sizeof(PciUnit) );
if ( pPci ){
PciReadHeader( pPci, bus, dev, func );
DbgPrintf("Pci found. Type:%s %s\n", GetPciType(pPci->ClassCode),
GetPciName( pPci->ClassCode, pPci->SubClass, pPci->Interface ) );
//DbgPrintf("PciReadHeader( 0x%X, %d, %d, %d );\n", pPci, bus, dev, func );
if( DeviceNum<MAX_PCI_DEVICES ) {
PciDevices[ DeviceNum++ ] = pPci;
}else{
DbgPrintf( "[%s]: To many PCI devices!\n", __FUNCTION__ );
}
}
if ( headerType & PCI_HEADER_BRIDGE ) {
PciWriteConfig( bus, dev, func, PCI_COMMAND, 2,
PciReadConfig( bus, dev, func, PCI_COMMAND, 2 )
& ~( PCI_COMMAND_IO | PCI_COMMAND_MEMORY ) ); //禁止io和内存操作
PciWriteConfig( bus, dev, func, PCI_BUS_PRIMARY, 1, bus );
PciWriteConfig( bus, dev, func, PCI_BUS_SECONDARY, 1, PciBusses );
PciWriteConfig( bus, dev, func, PCI_BUS_SUBORDINATE, 1, 0xFF );
ScanBus( PciBusses );
PciWriteConfig( bus, dev, func, PCI_BUS_SUBORDINATE, 1, PciBusses - 1 );
PciWriteConfig( bus, dev, func, PCI_COMMAND, 2,
PciReadConfig( bus, dev, func, PCI_COMMAND, 2 ) |
( PCI_COMMAND_IO | PCI_COMMAND_MEMORY ) ); //允许io和内存操作
}
}
}
}
}
RESULT PciOpen()
{
/* Searching for "_32_" from 0xE0000 to 0xFFFF0 */
//MapPage( Me->PageDir, 0x0, 0x0, 256 );
ULONG *p = (ULONG*)0x800E0000;
for( ;*p!=0x5F32335F && p<(ULONG*)0x800FFFF0;p++ )
;
if( *p==0x5F32335F )
DbgPrintf("Find BIOS32 Service Directory at memaddr: 0x%X\n", p);
else{
DbgPrintf("No BIOS32 Service Directory!\n");
return FALSE;
}
pBios32Srv = (PBIOS32ServiceData)p;
if( pBios32Srv->LenghOfThis!=sizeof(BIOS32ServiceData)/16 && pBios32Srv->Checksum!=0 )
DbgPrintf("Bad BIOS32 Service Directory!\n");
//DbgPrintf("Entry: 0x%X\n", pBios32Srv->EntryPoint);
Bios32Entry.Offset = pBios32Srv->EntryPoint;
if(!GetBiosService(0x49435024, &PciEntry.Offset )) //0x49435024: "$PCI"
return FALSE;
DbgPrintf("GetEntryPointOf PCI: 0x%X\n", PciEntry.Offset );
//Check PCI Installation
RESULT ret;
t_32 ebx, ecx ,edx;
ret = PciBiosCall( PCIBIOS_INSTALL_CHECK, &ebx, &ecx, &edx );
if( (ret>>8&0xFF)!=0 || edx != 0x20494350 ) //edx should == "PCI "
{
DbgPrintf("PCI not present. ret=%x\n", ret);
return FALSE;
}
PciChar = ret&0xFF;
PciVersion = ebx&0xFFFF;
LastPci = ecx&0xFF;
DbgPrintf("PciChar: %x PciVer: %d.%d LastPci: %d \n", PciChar, PciVersion>>8, PciVersion&0xFF, LastPci );
PciBusses = 0;
DeviceNum = 0;
//Check Ok.
ScanBus(0);
DbgPrintf("Detected %d devices.\n", DeviceNum);
//for(;;);
}
RESULT PciControl(UINT dev, UINT cmd, ULONG arg)
{
PPciUnit pPci;
switch(cmd){
case PCI_GETPCILIST:
*((PPciUnit**)arg) = PciDevices;
return TRUE;
case PCI_READCONFIGSPACE:
{
PciRWConfigSpace *p = (PciRWConfigSpace*)arg;
if(!p||!p->pci)return FALSE;
pPci = p->pci;
p->value = PciReadConfig( pPci->Bus, pPci->Driver, pPci->Function, p->pos, p->size );
}
return TRUE;
case PCI_WRITECONFIGSPACE:
{
PciRWConfigSpace *p = (PciRWConfigSpace*)arg;
if(!p||!p->pci)return FALSE;
pPci = p->pci;
PciWriteConfig( pPci->Bus, pPci->Driver, pPci->Function, p->pos, p->size, p->value );
}
return TRUE;
break;
}
return FALSE;
}
Driver devPci = {
"Pci Driver",
0x0001,
0x0,
0,
{ PciOpen, NULL, NULL, NULL, PciControl }
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -