oempci.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,258 行 · 第 1/4 页

C
1,258
字号
	if(!(V3_InternalRegBase = VirtualAddress(PHYSICAL_V3_INTERNAL_REG_BASE, 0x100))) {
		ERRORMSG(1, (TEXT("Could not Allocate VirtualAddress to V3 Internal BASE Register.\r\n")));
		retval = FALSE;
	}
	else if(!(PciConfigBase = VirtualAddress(PHYSICAL_PCI_CONFIG_BASE, PCI_CONFIG_SIZE))) {
		ERRORMSG(1, (TEXT("Could not Allocate VirtualAddress to PCI Config Register.\r\n")));
		retval = FALSE;
	}
	else if(!(PciIoBase = VirtualAddress(PHYSICAL_PCI_IO_BASE, PCI_IO_SIZE))) {
		ERRORMSG(1, (TEXT("Could not Allocate VirtualAddress to PCI IO Register.\r\n")));
		retval = FALSE;
	}

	// PCI Memory is not allocated any more in the pci driver. Any driver which
	// needs pci memory must map it on it's own. This helps in saving virtual
	// address space in the device drivers that don't need it.
	// ALLOCATE_PCI_MEM would not be defined in the final version.
#ifdef PCI_DRIVER_ALLOCATES_PCI_MEM
	else if(!(PciMemBase = VirtualAddress(PHYSICAL_PCI_MEM_BASE, PCI_MEM_SIZE))) {
		ERRORMSG(1, (TEXT("Could not Allocate VirtualAddress to PCI IO Register.\r\n")));
		retval = FALSE;
	}
#else
	PciMemBase = 0;
#endif

	if(retval) {
  		DEBUGMSG(DEB_PCI_INIT, (TEXT("PCI: MapRegisters: V3_InternalRegBase = 0x%x, PciConfigBase=0x%x, PciIoBase=0x%x\r\n"), V3_InternalRegBase, PciConfigBase, PciIoBase));
	
		// Fill in the members of PciBaseAddresses.
		PciBaseAddresses.PciIoBase = (ULONG)PciIoBase;
		PciBaseAddresses.PciMemBase = (ULONG)PciMemBase;
		PhysicalPciIoBase = PHYSICAL_PCI_IO_BASE;
		PhysicalPciMemBase = PHYSICAL_PCI_MEM_BASE;
	}
	else {
    	if ( PciMemBase )
      		VirtualFree((PVOID)PciMemBase, 0, MEM_RELEASE);
    	if ( PciIoBase )
      		VirtualFree((PVOID)PciIoBase, 0, MEM_RELEASE);
    	PciMemBase = 0;
    	PciIoBase = 0;
	}

#endif

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


int OEM_InitPCIHostBridge( void ) 
{
	unsigned tmp, i;

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

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

#if (SH_PLATFORM == PLATFORM_S1)	
	// Set the BCR2 and WCR2 registers to get correct Wait states.
	// This might be different in Aspen.
	WRITE_REGISTER_USHORT(BCR2, 0x2a3c);
	WRITE_REGISTER_ULONG(WCR2, 0xFFF666FB);
#endif (SH_PLATFORM == PLATFORM_S1)	


	// Initialization of the V3 chip.
		// Step 1: Set Base register for V3 Internal registers.
		// Step 1a: Assert and De-assert LRESET #
		// Step 1b: Write to V3_INITIAL_LB_IO_BASE_RES register.

#if (SH_PLATFORM == PLATFORM_S1)

	// The PBC is initialized by asserting LRESET# pin for more than 8 clock 
	// cycles (To initialize from the local bus). 
	// The FPGA should provide a register which can be used to assert this pin.
  	DEBUGMSG(DEB_PCI_INIT, (TEXT("\r\nAsserting and Deasserting the FPGA LRESET#...\r\n")));

	FPGA_PCI_CNT = 0x000000FF;
	INIT_WAIT;
	FPGA_PCI_CNT = 0x000080FF;

	// This is not a good idea. I should not generate any local bus writes
	// till i've successfully written to the LB_IO_BASE register.
	// But if i don't put this delay loop, i'm not able to write to successfully
	// to LB_IO_BASE register. These writes would also be captured by the V3
	// device.
	INIT_WAIT;

	// Now Set the V3 registers.
	// To initialize from the PCI bus, the first step is to set the Local
	// Bus to PCI Aperture. Once this is set, the rest of the registers can
	// be accessed from this aperture.

	// Set Local to Internal Register Map Base Address.

	// DbgPrintf("Setting V3 LB IOBASE at 0x%x...\r\n", (V3_INTERNAL_REG_OFFSET >> 16));
	V360_INITIAL_LB_IO_BASE_RES = 0x01800000; // ( (V3_INTERNAL_REG_BASE - V3_MEM_AREA) );

#endif (SH_PLATFORM == PLATFORM_S1)



#if ( (SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR) )
	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;

#endif (SH_PLATFORM == PLATFORM_ASPEN)



#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
#if ( (SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR) )
	V360_LB_CFG_SYSTEM = 0x00008077; // 0x8000; // 0x00008077; // 0x63008077;
	V360_LB_CFG_SYSTEM = 0x00000000; // 0x63008077;
	V360_LB_CFG_SYSTEM = 0x63c08000; // 0x8000; // 0x63c08000; // 

	INIT_WAIT;
#else (SH_PLATFORM == PLATFORM_ASPEN)
	V360_LB_CFG_SYSTEM = 0x00038077; // 0x63008077;
	V360_LB_CFG_SYSTEM = 0x03c08000; // 
#endif (SH_PLATFORM == PLATFORM_ASPEN)

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


#if ( (SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR) )

	// 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 | (i << 4) | 0x1;
	// DbgPrintf("Writing 0x%x to LB_BASE1\n", tmp);

	V360_LB_BASE0			 =PHYSICAL_PCI_IO_BASE | 0x01;   // Enable.
	V360_LB_BASE1			 = tmp;
	V360_LB_MAP0_RES		 = 0x00020000;
	V360_LB_MAP1_RES		 = 0x00060000;

	DEBUGMSG(DEB_PCI_INIT, (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));

#else (SH_PLATFORM == PLATFORM_ASPEN)
	V360_LB_BASE0			 = 0x00000041; // No prefetch
	V360_LB_BASE1			 = 0x01000001; // No prefetch
	V360_LB_MAP0_RES		 = 0x00060000;
	V360_LB_MAP1_RES		 = 0x00020000;
#endif (SH_PLATFORM == PLATFORM_ASPEN)

	
	V360_FIFO_PRIOR_CFG		 = 0x0f0f0000;

#if 0
	WRITE_REGISTER_USHORT(V3_LB_MAP0, 0x000a);
	WRITE_REGISTER_USHORT(FPGA_PCI_CNT, 0xa0FF);
#endif

	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 routine sets the PCI base address used to access shared RAM when the	*/
/*	CPU board is acting as a PCI memory target device.							*/
/* If operation succeeds, it returns 0.  If the operation fails, or this		*/
/*	capability is not supported, it returns non-zero.							*/
int OEM_SetSharedRAMBaseAddr( DWORD dwPCISharedRAMBase ) {
#if 0

	/* Set the primary inbound ATU base address to allow DMA onto the CPU card	*/
	*(volatile DWORD *)0x00001210 = dwPCISharedRAMBase;

#endif
	return 0;

} /* OEM_SetSharedRAMBaseAddr */



/* Function returning a record describing the base address and size for	*/
/*	the PCI memory and I/O space windows that pass through the PCI host	*/
/*	bridge for the processor.											*/
void OEM_GetPCIHostBridgeWindowInfo( PCIHostBridgeWindowInfoRec *pPCIHostBridgeWindowInfo ) {

#if ( (SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR) )
	/* Processor base address to access PCI memory window	*/
	pPCIHostBridgeWindowInfo->dwMemWinBase = PHYSICAL_PCI_MEM_BASE;
	/* Size of PCI memory window	*/
	pPCIHostBridgeWindowInfo->dwMemWinSize = PCI_MEM_SIZE;
	/* Processor base address to access PCI I/O window	*/
	pPCIHostBridgeWindowInfo->dwIOWinBase = PHYSICAL_PCI_IO_BASE;
	/* Size of PCI I/O window	*/
	pPCIHostBridgeWindowInfo->dwIOWinSize = PCI_IO_SIZE;
	/* Indicate that the board does support PCI memory target operation	*/
	pPCIHostBridgeWindowInfo->fPCIMemTargetSupported = 0;

#else (SH_PLATFORM == PLATFORM_ASPEN)
	/* Processor base address to access PCI memory window	*/
	pPCIHostBridgeWindowInfo->dwMemWinBase = 0xA4000000;
	/* Size of PCI memory window	*/
	pPCIHostBridgeWindowInfo->dwMemWinSize = 16*1024*1024;
	/* Processor base address to access PCI I/O window	*/
	pPCIHostBridgeWindowInfo->dwIOWinBase = 0xA5000000;
	/* Size of PCI I/O window	*/
	pPCIHostBridgeWindowInfo->dwIOWinSize = 1*1024*1024;
	/* Indicate that the board does support PCI memory target operation	*/
	pPCIHostBridgeWindowInfo->fPCIMemTargetSupported = 0;
#endif (SH_PLATFORM == PLATFORM_ASPEN)

} /* GetPCIWindowInfo() */



/* This function returns the extents of the range of PCI memory and I/O	*/
/*	addresses that the PCI host bridge can generate.  This is not just	*/
/*	the size of the host bridge windows, but also includes what can be	*/
/*	reached using the PCI paging registers.  The host bridge should		*/
/*	allow all of PCI address space to be addressed if the paging		*/
/*	registers are used; however, the test program itself may need to	*/
/*	map devices into certain ranges for use with the debug serial for	*/
/*	example.  This data returned from this function allows the			*/
/*	exclusion of some address ranges so that they will not be altered.	*/
void OEM_GetLegalPCIAddrRange( PCIMapInfoRec *pPCIMapInfo ) {
	/* For ASPEN, this is currently returning the same values as in the
	 * original code, though for this platform the whole PCI range from 0
	 * to 4GB can be accessed.
	 * I'll modify the code for that later.
	 */
#if ( (SH_PLATFORM == PLATFORM_ASPEN) || (SH_PLATFORM == PLATFORM_BIGSUR) )
	/* Processor base address to access PCI memory window	*/
	pPCIMapInfo->dwPCIMemBase = PHYSICAL_PCI_MEM_BASE; // 0x80000000; // PCI_MEM_AREA;
	/* Size of PCI memory window	*/
	pPCIMapInfo->dwPCIMemLimit = PCI_MEM_SIZE; // 64 * 1024 * 1024; // PCI_MEM_SIZE;
	/* Processor base address to access PCI I/O window	*/
	pPCIMapInfo->dwPCIIOBase = PHYSICAL_PCI_IO_BASE; // 0x90000000; // PCI_IO_AREA;
	/* Size of PCI I/O window	*/
	pPCIMapInfo->dwPCIIOLimit = PCI_IO_SIZE; // 64 * 1024; // PCI_IO_SIZE;
#else (SH_PLATFORM == PLATFORM_ASPEN)
#endif (SH_PLATFORM == PLATFORM_ASPEN)

} /* GetPCIWindowInfo() */



/* This routine will return the state of the PCI interrupt lines that	*/
/*	are directly connected to the host PCI bridge.						*/
/*	*pbInterrupts is interpretted as follows:							*/
/*		Bit 3 - INTA#													*/
/*		Bit 2 - INTB#													*/
/*		Bit 1 - INTC#													*/
/*		Bit 0 - INTD#													*/
/*	If a bit is a 0, then the interrupt is asserted. if a bit is a 1,	*/
/*	then the interrupt is not asserted.  Unassigned bits should be 0.	*/
/*	The routine will return 0 if there is no error or will return non-	*/
/*	zero if an error occurs.											*/
int OEM_GetPCIInterruptState( BYTE *pbInterrupts ) {
#if 0

	/* Unimplemented at this time	*/
	*pbInterrupts = 0x0F;
#endif

	return 0;

} /* OEM_GetPCIInterruptState() */

⌨️ 快捷键说明

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