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

📄 pciext.c

📁 WinCE5.0BSP for Renesas SH7770
💻 C
📖 第 1 页 / 共 2 页
字号:
 *              nothing, but returning the actual PCI addresses.
 ****************************************************************************/
int MapRegisters(void)
{
	static int RegistersMapped = 0;
	int retval = TRUE;

  	DEBUGMSG(1, (TEXT("+PCI: MapRegisters\r\n")));

	// If the registers have already been mapped, just return.
	if(RegistersMapped) {
		return TRUE;
	}
	RegistersMapped = TRUE;

	PciConfigBase	 	= (DWORD)(PHYSICAL_PCI_CONFIG_BASE|UNCACHED_BASE);
//	V3_InternalRegBase 	= PHYSICAL_V3_INTERNAL_REG_BASE;

  	DEBUGMSG(1, (TEXT("PCI: -MapRegisters returning %d\r\n"), retval));
	return retval;
}




// PCI Bridge
int OEM_InitPCIHostBridge( void ) 
{
	unsigned tmp, i;

  	RETAILMSG(1, (TEXT("\r\n+InitPCIHostBridge\r\n")));

	/* Map Registers into your virtual address space. */
	MapRegisters();




	INIT_WAIT;
	RETAILMSG(1, (TEXT("PCI_INIT: Writing 0x%x to 0x%x\r\n"), (PHYSICAL_V3_INTERNAL_REG_BASE + 0x6c), &V360_LB_IO_BASE_RES));
	V360_LB_IO_BASE_RES	= (0x6c+PHYSICAL_V3_INTERNAL_REG_BASE);
	INIT_WAIT;

#if 0
	DbgPrintf("Set io base register. \r\n");
	{
		unsigned tmp;
		DbgPrintf("BCR1 = 0x%x\r\n", *(unsigned long *)0xFF800000);
		tmp = V3_PCI_DEV_VEN;
		DbgPrintf("tmp = %x\r\n", tmp);
	}
#endif 0

  	RETAILMSG(1, (TEXT("PCI_INIT: V3 device reads Vendor ID = %x, Device ID = %x\r\n"), 
			(V3_PCI_DEV_VEN & 0xFFFF), ((V3_PCI_DEV_VEN >> 16) & 0xFFFF)) );

	// Flush ALL FIFOs
	V360_LB_CFG_SYSTEM = 0x00008077; // 0x8000; // 0x00008077; // 0x63008077;
	V360_LB_CFG_SYSTEM = 0x00000000; // 0x63008077;
	V360_LB_CFG_SYSTEM = 0x63c08000; // 0x8000; // 0x63c08000; // 

	INIT_WAIT;

	V3_PCI_STAT_CMD =  0x00000246; // 0x00000246;
	V3_PCI_HDR_CFG = 0x0000F800; // 0x00000800;



	// Find out what to write in the BASE1 registers, Size bits.
	// The size bits contain the encoded value of the bits that is 1 above 1 Mb.
	i = 0;
	tmp = MB_1;
	// Possible values of ADR_SIZE are from 0 (1Mb) to 11 (2 Gb). Though SH4 will not support such big value
	// I still check for it.
	for(i = 0; i <= 11; i++) {
		if(tmp == PCI_MEM_SIZE)
			break;
		tmp <<= 1;
	}
	// At present i support only slots up to 64 Mb.
	if( i > 6) {
		ERRORMSG(1, (TEXT("Error: Got invalid size of PCI Memory Space (0x%x). Check PCI_MEM_SIZE in oempci.c\n"), PCI_MEM_SIZE));
		return -1;
	}
	tmp = PHYSICAL_PCI_MEM_BASE |UNCACHED_BASE | (i << 4) | 0x1;
	// DbgPrintf("Writing 0x%x to LB_BASE1\n", tmp);

	V360_LB_BASE0			 = PHYSICAL_PCI_IO_BASE |UNCACHED_BASE| 0x01;   // Enable.
	V360_LB_BASE1			 = tmp;
	V360_LB_MAP0_RES		 = 0x00020000; // Map PHYSICAL_PCI_IO_BASE to -> 0
	V360_LB_MAP1_RES		 = 0x00060000 | (tmp&0xfff00000L) ; // It is One to one MAP

	DEBUGMSG(1, (TEXT("LB_BASE0=0x%x, 1=0x%x, MAP0=0x%x, 1=0x%x, tmp=0x%x\r\n"), V360_LB_BASE0, V360_LB_BASE1, 
			V360_LB_MAP0_RES, V360_LB_MAP1_RES, tmp));

	// PCI to LOCAL map
	V360_PCI_BASE0           = ((DRAM_BASE | UNCACHED_BASE) & 0xfff00000);
	V360_PCI_MAP0			 = ((DRAM_BASE | UNCACHED_BASE ) & 0xfff00000) | 3 | (5<4); // 64 M uncached memory
	// PCI to LOCAL map
	V360_PCI_BASE1           = ((DRAM_BASE ) & 0xfff00000);
	V360_PCI_MAP1			 = ((DRAM_BASE ) & 0xfff00000) | 3 | (5<4); // 64 M cached memory

	V360_FIFO_PRIOR_CFG		 = 0x0f0f0000;

	// PCI Interrupt
	V360_PCI_INT_CFG         = 0x8421;
	V360_LB_ISTAT			= 0x1010;
#if 0
	WRITE_REGISTER_USHORT(V3_LB_MAP0, 0x000a);
	WRITE_REGISTER_USHORT(FPGA_PCI_CNT, 0xa0FF);
#endif

	CONFIG_WAIT;
	RETAILMSG(1, (TEXT("-InitPCIHostBridge\r\n")));

//	Command_Scan();
	return 0;

#if 0
	/* Enable Bus Mastering on the primary PCI segment for the ATU through the	*/
	/*	Primary ATU Command Register											*/
	*(volatile WORD *)0x00001204 = 0x0157;

	/* Set PCI Interrupt Routing Control so that it does not route CPU board	*/
	/*	secondary interrupts to primary PCI segment								*/
	*(volatile DWORD *)0x00001050 = 0x0000000F;

	/* Make sure that the internal bridge does not accept any accesses			*/
	*(volatile WORD *)0x00001004 = 0;

#endif
	return 0;
}

/* This function will encode a Type 0 or Type 1 configuration address based on	*/
/*	the parameters passed in.													*/
void OEM_EncodeConfigAddress( DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo, DWORD dwOffset, DWORD *pdwAddress ) {

	/* Assume that we need to generate Type 0 bus cycles for Bus 0, based on	*/
	/*	the assumption that bus 0 is the one connected to the PCI host bridge.	*/
	if (dwBusNo == 0) {
		*pdwAddress = (0x00000800 << dwDevNo) | (dwFuncNo << 8) | (dwOffset & 0xFC);
	}
	else {
		/* Generate a Type 1 address for everything not on Bus 0.	*/
		*pdwAddress = (dwBusNo << 16) | (dwDevNo << 11) | (dwFuncNo << 8) | (dwOffset & 0xFC) | 1;
	}

} /* OEM_EncodeConfigAddress */

DWORD OEM_ReadConfigDword(IN ULONG BusNumber, IN ULONG DeviceNumber, IN ULONG FunctionNumber,
                            IN ULONG Offset)
{

	// This routine would check out the entire range of idsels by asserting
	// bits 11 - 31, one bit at a time.
	// If some of the bits are don't care, it would not make any difference.

	// So the configuration addresses generated would be of the form :-
	//	      dwDevNo == 0, idSel = 0x00000800
	//        dwDevNo == 1, idSel = 0x00001000

	//        dwDevNo == 21, idSel = 0x8000000
	// This way a max. of 21 devices are supported.


	DWORD dwConfigAddress;
	DWORD dwReturn;
	unsigned addr;
	unsigned old_val;

//	DEBUGMSG(0, (TEXT("RCD: dwBusNo = 0x%x, dwDevNo = 0x%x, dwFuncNo = 0x%x, dwOffset = 0x%x\r\n"), BusNumber, DeviceNumber, FunctionNumber,Offset));
//	CONFIG_WAIT;

	// Get the address in the PCI configuration space for the requested register
	OEM_EncodeConfigAddress( BusNumber, DeviceNumber, FunctionNumber, Offset, &dwConfigAddress );

	// Save OLD Value of LB_MAP1 so that you can restore it after the access
	old_val = V360_LB_MAP1_RES;

//	DEBUGMSG(0, (TEXT("Encoded Address = 0x%x\r\n"), dwConfigAddress));

	// Now is the address bigger than PCI memory size that you mapped ?
	if(dwConfigAddress >= PCI_CONFIG_SIZE) {
//		DEBUGMSG(1, (TEXT("Writing to LB_MAP1_RES1 0x%x\n"), ((dwConfigAddress & 0xFFF00000) | (TYPE_CONFIG << 16)) ));

		// Split dwConfigAddress into two parts. The upper part gets written
		// to MAP1 register and the lower part is the address that gets accessed.
		V360_LB_MAP1_RES = ((dwConfigAddress & 0xFFF00000) | (TYPE_CONFIG << 16));
	}
	else {
//		DEBUGMSG(0, (TEXT("Writing to LB_MAP1_RES2 0x%x\r\n"), (TYPE_CONFIG) << 16) );
		V360_LB_MAP1_RES =  (TYPE_CONFIG) << 16 ;
	}

	addr = PciConfigBase + (dwConfigAddress & (PCI_CONFIG_SIZE - 1));
//	DEBUGMSG(1, (TEXT("addr = 0x%x\r\n"), addr));

	//  If type is 1, that is address bits 0,1 are 01, Then you need to 
	// program AD_LOW_ENABLE in LB_MAP1_RES and AD_LOW=01 in PCI_CFG
	if(addr & 3) {
		volatile unsigned long *tmp_addr = (unsigned *) (addr & 0xFFFFFFFC);

//		CONFIG_WAIT;
		// Set bits 8,9 of PCI_CFG register to the override value of address.
		V360_PCI_CFG = ( V360_PCI_CFG & ~(0x300) ) | ( (addr & 3) << 8);
		V360_LB_MAP1_RES =  (V360_LB_MAP1_RES | 0x10000);
//		DEBUGMSG(1, (TEXT("RCD: addr = 0x%x, V360_PCI_CFG = 0x%x, V360_LB_MAP1_RES = 0x%x\n"), tmp_addr, V360_PCI_CFG, V360_LB_MAP1_RES));
		dwReturn = *tmp_addr;
	}
	else {
//		CONFIG_WAIT;
//		DEBUGMSG(1, (TEXT("About to read location 0x%x, \r\n"), addr));
		dwReturn = *(volatile unsigned long *)(addr);
//		DEBUGMSG(1, (TEXT("read data %x\r\n"), dwReturn));
	}

//	DEBUGMSG(1, (TEXT("RCD(BDFO)=(%d:%d:%d:0x%x),A=%x,*D=%x,M1=%x,CA=%x\r\n"), BusNumber, DeviceNumber, FunctionNumber, Offset, addr, dwReturn, V360_LB_MAP1_RES, dwConfigAddress));

	// Switch back the area to old mode
	V360_LB_MAP1_RES 	= old_val;

	// No need to reset PCI_CFG AD_LOW bits since they would not be used.

	return dwReturn;
} 
int glbl_wait = 1000;
/* Junk global variable to make sure it does not get removed while optimization */
int my_wait=0;

void OEM_WriteConfigDword(IN ULONG BusNumber, IN ULONG DeviceNumber, IN ULONG FunctionNumber,
                            IN ULONG Offset, IN ULONG dwData)
{
    
	DWORD dwConfigAddress;
	unsigned addr;
	unsigned old_val;

//	CONFIG_WAIT;
	// Get the address in the PCI configuration space for the requested register
	OEM_EncodeConfigAddress( BusNumber, DeviceNumber, FunctionNumber, Offset, &dwConfigAddress );
	// Save OLD Value of LB_MAP1 so that you can restore it after the access
	old_val = V360_LB_MAP1_RES;

	// Now is the address is bigger than PCI memory size that you mapped,
	if(dwConfigAddress >= PCI_CONFIG_SIZE) {
		// Split dwConfigAddress into two parts. The upper part gets written
		// to MAP1 register and the lower part is the address that gets accessed.
		V360_LB_MAP1_RES = ((dwConfigAddress & 0xFFF00000) | (TYPE_CONFIG << 16));
	}
	else {
		V360_LB_MAP1_RES =  (TYPE_CONFIG) << 16 ;
	}

	addr = PciConfigBase + (dwConfigAddress & (PCI_CONFIG_SIZE - 1));
//	DEBUGMSG(1, (TEXT("WCD: (B:D:F:O) = (%d:%d:%d:0x%x), *Data=%x, addr=%x, MAP1=%x\r\n"),  BusNumber, DeviceNumber, FunctionNumber,Offset, dwData, addr, V360_LB_MAP1_RES));

	//  If type is 1, that is address bits 0,1 are 01, Then you need to 
	// program AD_LOW_ENABLE in LB_MAP1_RES and AD_LOW=01 in PCI_CFG
	if(addr & 3) {

		volatile unsigned long *tmp_addr = (unsigned long *)(addr & 0xFFFFFFFC);

		// Set bits 8,9 of PCI_CFG register to the override value of address.
		V360_PCI_CFG = ( V360_PCI_CFG & ~(0x300) ) | ( (addr & 3) << 8);
		V360_LB_MAP1_RES =  (V360_LB_MAP1_RES | 0x10000);
//		DEBUGMSG(1, (TEXT("WCD: addr = 0x%x, V360_PCI_CFG = 0x%x, V360_LB_MAP1_RES = 0x%x "), tmp_addr, V360_PCI_CFG, V360_LB_MAP1_RES));

		// Presently i need to write to this register many times, since if i
		// write only once, it does not reliably get written to the register.
		// Either some timing problem or some wrongly set paramter.
		*tmp_addr = dwData;		// Write code

#if 1 // def PUT_PCI_DELAY
		{
			int i;
			for(i = 0; i < 1; i++)
				for(glbl_wait = 0; glbl_wait < my_wait; glbl_wait ++);	
				*tmp_addr = dwData;		// Write code
		}
		
//		DEBUGMSG(1, (TEXT("RB: 0x%x\n"), *(volatile unsigned long *)(tmp_addr)));
#endif PUT_PCI_DELAY
	}
	else {
		*(volatile unsigned long *)(addr) = dwData;		// Write code

//		DEBUGMSG(1, (TEXT("RB: 0x%x\n"), *(volatile unsigned long *)(addr)));
	}

//	DEBUGMSG(1, (TEXT("WCD: (B:D:F:O) = (%d:%d:%d:0x%x), *Data=%x, addr=%x, MAP1=%x, dwConfigAddress=%x\r\n"), BusNumber, DeviceNumber, FunctionNumber,Offset, dwData, addr, V360_LB_MAP1_RES, dwConfigAddress));

	// Switch back the area to old mode
	V360_LB_MAP1_RES 	= old_val;

	// No need to reset PCI_CFG AD_LOW bits since they would not be used.

	return;

} /* OEM_WriteConfigDword() */

ULONG PCI_Type1_Configuration(ULONG BusNumber, ULONG SlotNumber, PVOID Buffer,
                              ULONG Offset, ULONG Length, BOOL  fSet)
{
    PULONG   pBuffer;
    int      registerOffset, endOffset;
    ULONG    DeviceNumber, FunctionNumber;

    if (BusNumber >= PCI_MAX_BUS)
        return (0);

    DeviceNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.DeviceNumber;
    FunctionNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.FunctionNumber;

    if (DeviceNumber >= PCI_MAX_DEVICES)
        return (0);

    registerOffset = Offset / sizeof(ULONG);
    endOffset = registerOffset + (Length + sizeof(ULONG) - 1) / sizeof(ULONG);
    pBuffer = Buffer;

    for ( ; registerOffset < endOffset; ++registerOffset)
    {
        if (fSet)
            OEM_WriteConfigDword(BusNumber, DeviceNumber, FunctionNumber,
                                 registerOffset * 4, *pBuffer++);
        else
            *(pBuffer++) = OEM_ReadConfigDword(BusNumber, DeviceNumber,
                                               FunctionNumber,
                                               registerOffset * 4);
    }

    return (Length);
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -