⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciconfigration.cpp

📁 pci配置
💻 CPP
📖 第 1 页 / 共 2 页
字号:

//把数据从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 + -