sdbtest.c

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

C
1,249
字号
			/*	of the i960 restrictions.							*/
			if (TestRAMRegion( pRIO, bRAMTestPhase, bRAMAccessWidth,
				dwPCISharedRAMBase1, 4096, dwRIOContigRAMSize/2 - 4096 )) {
				DbgPrintf( "TestMemory() - ERROR: Bank 1 Call To TestRAMRegion() Failed\n" );
				return 1;
			}
			/* Rotate through the 8, 16 and 32-bit access widths	*/
			bRAMAccessWidth <<= 1;
			bRAMAccessWidth = (bRAMAccessWidth & 0x38) ? bRAMAccessWidth : 8;
			/* Do this phase on the second half of the shared RAM	*/
			/*	using the second base address.						*/
			if (TestRAMRegion( pRIO, bRAMTestPhase, bRAMAccessWidth,
				dwPCISharedRAMBase2, dwRIOContigRAMSize/2, dwRIOContigRAMSize/2 )) {
				DbgPrintf( "TestMemory() - ERROR: Bank 2 Call To TestRAMRegion() Failed\n" );
				return 1;
			}
			/* Rotate through the 8, 16 and 32-bit access widths	*/
			bRAMAccessWidth <<= 1;
			bRAMAccessWidth = (bRAMAccessWidth & 0x38) ? bRAMAccessWidth : 8;
		}
	}

	/* Now I'll test the upper bits of the host bridge memory		*/
	/*	window by inverting them in successive passes of the RAM	*/
	/*	test on two different regions that should fall within the	*/
	/*	same host bridge memory window.  Normally, the host	bridge	*/
	/*	memory window will be much larger than the size of the RIO	*/
	/*	shared RAM.													*/
	/* The first base address used will have an alternating bit		*/
	/*	pattern for all bits beyond those that fit inside the RIO	*/
	/*	memory window.												*/
	dwPCISharedRAMBase1 = 0;
	for( dwTemp = dwRIOContigRAMSize; dwTemp; dwTemp <<= 2 )
		dwPCISharedRAMBase1 |= dwTemp;
	/* The second base address will keep the upper most bits the	*/
	/*	same so that host bridge window doesn't move, but it will	*/
	/*	alternate bits below that so that we twiddle the upper bits	*/
	/*	in the host bridge memory window.							*/
	dwPCISharedRAMBase2 =
		(dwPCISharedRAMBase1 & ~(PCIHostBridgeWindowInfo.dwMemWinSize-1)) |
		(~dwPCISharedRAMBase1 & (PCIHostBridgeWindowInfo.dwMemWinSize-1) & ~(dwRIOContigRAMSize-1));

	/* Make sure that the first base address is less than the second*/
	/*	so that the overlap comparison will work.					*/
	if (dwPCISharedRAMBase1 > dwPCISharedRAMBase2) {
		dwTemp = dwPCISharedRAMBase1;
		dwPCISharedRAMBase1 = dwPCISharedRAMBase2;
		dwPCISharedRAMBase2 = dwTemp;
	}
	/* If the two memory ranges would overlap, then the host bridge	*/
	/*	window is not bigger than the RIO shared RAM window and so	*/
	/*	we should skip this test because all of the bits of the		*/
	/*	host bridge window have already been tested by the previous	*/
	/*	test passes.												*/
	if (dwPCISharedRAMBase1 + dwRIOContigRAMSize/2 > dwPCISharedRAMBase2)
		DbgPrintf( "Host Bridge Memory Limit Test Skipped Because Of Small Window Size\n" );
	else {
		DbgPrintf( "TestMemory() - Testing PCI Host Bridge Window Limits\n" );
		bRAMAccessWidth = 32;
		for( dwNumPasses = 0; dwNumPasses < 2; dwNumPasses++ ) {
			for( bRAMTestPhase = 1; bRAMTestPhase < 4; bRAMTestPhase++ ) {
				/* Do this phase on the first half of the shared RAM	*/
				/*	using the first base address.						*/
				/* Remember to stay out of the lower 4K of RAM because	*/
				/*	of the i960 restrictions.							*/
				if (TestRAMRegion( pRIO, bRAMTestPhase, bRAMAccessWidth,
					dwPCISharedRAMBase1, 4096, dwRIOContigRAMSize/2 - 4096 )) {
					DbgPrintf( "TestMemory() - ERROR: Bank 1 Call To TestRAMRegion() Failed\n" );
					return 1;
				}
				/* Rotate through the 8, 16 and 32-bit access widths	*/
				bRAMAccessWidth <<= 1;
				bRAMAccessWidth = (bRAMAccessWidth & 0x38) ? bRAMAccessWidth : 8;

				/* Do this phase on the second half of the shared RAM	*/
				/*	using the second base address.						*/
				if (TestRAMRegion( pRIO, bRAMTestPhase, bRAMAccessWidth,
					dwPCISharedRAMBase2, dwRIOContigRAMSize/2, dwRIOContigRAMSize/2 )) {
					DbgPrintf( "TestMemory() - ERROR: Bank 2 Call To TestRAMRegion() Failed\n" );
					return 1;
				}
				/* Rotate through the 8, 16 and 32-bit access widths	*/
				bRAMAccessWidth <<= 1;
				bRAMAccessWidth = (bRAMAccessWidth & 0x38) ? bRAMAccessWidth : 8;
			}
		}
	}

	DbgPrintf( "TestMemory() Successful\n" );

	return 0;

} /* TestMemory() */



/* The shared RAM on RIO is organized as up to 4 banks of up to 64 Megabytes	*/
/*	each.  When RIO comes out of reset, it detects the number of banks and size	*/
/*	of each bank installed and then sets the Primary Inbound ATU Limit Register	*/
/*	so that the requested memory window is large enough to encompass all of it.	*/
/*	This may result in address fragmentation in the space between banks,		*/
/*	depending on the organization of the installed SIMMs.						*/
/* This routine will read the size of the memory overall window required in		*/
/*	terms of PCI address space.  It will then determine the size of the first	*/
/*	contiguous piece of RAM starting from the base address.						*/
int DetectRIORAM( PCIDevAddrRec *pRIO, DWORD *pdwRIORAMWindowSize, DWORD *pdwContigRAMSize ) {

	PCIHostBridgeWindowInfoRec PCIHostBridgeWindowInfo;
	PCIMapInfoRec PCIMapInfo;
	PCIDevAddrRec PCIStartDev;
	DWORD dwPCISharedRAMBase;
	volatile DWORD *pdwData;
	DWORD dwOffset;
	WORD wPCIStatus;

#if 1
		ClearPCIBridgeStatus( pRIO );
#endif 1
	
	DbgPrintf( "+DetectRIORAM()\n" );

	/* Get the size of the shared RAM on RIO	*/
	OEM_WriteConfigDword( pRIO->bBusNo, pRIO->bDevNo, 1, 0x10, 0xFFFFFFFF );
	if ((wPCIStatus = GetPCIBridgeStatus( pRIO )) != 0) {
		DbgPrintf( "DetectRIORAM() - ERROR: Can't Write Primary Inbound ATU Limit Register\n" );
		ClearPCIBridgeStatus( pRIO );
		PrintPCIError( wPCIStatus );
		return 1;
	}
	OEM_ReadConfigDword( pRIO->bBusNo, pRIO->bDevNo, 1, 0x10, pdwRIORAMWindowSize );
	if ((wPCIStatus = GetPCIBridgeStatus( pRIO )) != 0) {
		DbgPrintf( "DetectRIORAM() - ERROR: Can't Read Primary Inbound ATU Limit Register\n" );
		ClearPCIBridgeStatus( pRIO );
		PrintPCIError( wPCIStatus );
		return 1;
	}
	*pdwRIORAMWindowSize = ~(*pdwRIORAMWindowSize & 0xFFFFF000) + 1;

	DbgPrintf( "DetectRIORAM: *pdwRIORAMWindowSize=0x%x\n", *pdwRIORAMWindowSize);

	/* Get the size and starting address for the Host Bridge PCI memory window we have to work in.	*/
	OEM_GetPCIHostBridgeWindowInfo( &PCIHostBridgeWindowInfo );

	/* First I'll pick a safe base address for the RIO shared RAM	*/
	dwPCISharedRAMBase = 0x80000000;

	/* Set the base address for the shared RAM, and close all other accesses	*/
	/*	through the bridge.														*/
	if (InitI960( pRIO, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
		0xFFFFFFFF, 0x00000000, dwPCISharedRAMBase )) {
		DbgPrintf( "DetectRIORAM() - ERROR: Call To InitI960() Failed\n" );
		return 1;
	}

	/* The i960 shared RAM controller will not allow me to access the lowest 4K of RAM	*/
	/*	so I need to start testing for RAM beyond that point.  I'll just test every		*/
	/*	256K after offset 0.															*/

	/* First, put the offset value into each address of the memory	*/
	dwOffset = 4096;
	while( dwOffset < *pdwRIORAMWindowSize ) {
		/* Set the new base address for the memory window from the host bridge		*/
		/*	through all the PCI bridges.  Note that there are 1 Meg minimum windows	*/
		/*	for PCI bridges, so that the lower bits in dwOffset will be clipped the	*/
		/*	first time through.														*/
		PCIMapInfo.dwPCIMemBase = dwPCISharedRAMBase + dwOffset;
		PCIMapInfo.dwPCIMemLimit = PCIMapInfo.dwPCIMemBase + PCIHostBridgeWindowInfo.dwMemWinSize;
		PCIMapInfo.dwPCIIOBase = 0xFFFFFFFF;
		PCIMapInfo.dwPCIIOLimit = 0;
		PCIStartDev.bParentDevNo = PCIStartDev.bDevNo = 0xFF;
		if (MapPCIWindows( &PCIMapInfo, &PCIStartDev, pRIO )) {
			DbgPrintf( "DetectRIORAM() - ERROR: MapPCIWindows() Failed\n" );
			return 1;
		}

		/* Write out a 0 to clear possible transient bus values, then write the offset	*/
		/*	that we are at.																*/
		pdwData = (volatile DWORD *)
			(PCIHostBridgeWindowInfo.dwMemWinBase + (dwOffset % PCIHostBridgeWindowInfo.dwMemWinSize));
		*pdwData = 0;
		*pdwData = dwOffset;
		dwOffset <<= 1;
	}

	/* Now read back the offset values until we get one that doesn't match	*/
	dwOffset = 4096;
	while( dwOffset < *pdwRIORAMWindowSize ) {
		/* Set the new base address for the memory window from the host bridge		*/
		/*	through all the PCI bridges.  Note that there are 1 Meg minimum windows	*/
		/*	for PCI bridges, so that the lower bits in dwOffset will be clipped the	*/
		/*	first time through.														*/
		PCIMapInfo.dwPCIMemBase = dwPCISharedRAMBase + dwOffset;
		PCIMapInfo.dwPCIMemLimit = PCIMapInfo.dwPCIMemBase + PCIHostBridgeWindowInfo.dwMemWinSize;
		PCIMapInfo.dwPCIIOBase = 0xFFFFFFFF;
		PCIMapInfo.dwPCIIOLimit = 0;
		PCIStartDev.bParentDevNo = PCIStartDev.bDevNo = 0xFF;
		if (MapPCIWindows( &PCIMapInfo, &PCIStartDev, pRIO )) {
			DbgPrintf( "DetectRIORAM() - ERROR: MapPCIWindows() Failed\n" );
			return 1;
		}

		/* Read back the value and see if it matches	*/
		pdwData = (volatile DWORD *)
			(PCIHostBridgeWindowInfo.dwMemWinBase + (dwOffset % PCIHostBridgeWindowInfo.dwMemWinSize));
		if (*pdwData != dwOffset)
			break;
		dwOffset <<= 1;
	}

	*pdwContigRAMSize = dwOffset;

	return 0;

} /* DetectRIORAM() */



/* This routine will perform a memory test on the RIO shared RAM.  It does this in		*/
/*	three phases that should be done in sequence.  The bTestPhase variable indicates	*/
/*	which phase to perform.  The dwPCISharedRAMBase is PCI memory base address to be	*/
/*	used for the RIO shared RAM during the test.  The dwStartingOffset is the offset	*/
/*	from the base address to begin testing, and the dwMemSize is the amount of RAM to	*/
/*	be tested beyond that offset.  The bAccessWidth allows the caller to do byte lane	*/
/*	testing, by setting the data width used to: 8, 16 or 32 bits wide.					*/
/* It is assumed that the specified address ranges will fit within the RIO PCI memory	*/
/*	window and that there is actual RAM at those addresses.  The host bridge window and	*/
/*	intervening PCI-PCI bridge windows will be moved as needed.							*/
int TestRAMRegion( PCIDevAddrRec *pRIO, BYTE bTestPhase, BYTE bAccessWidth,
			DWORD dwPCISharedRAMBase, DWORD dwStartingOffset, DWORD dwMemSize ) {

	PCIHostBridgeWindowInfoRec PCIHostBridgeWindowInfo;
	PCIMapInfoRec PCIMapInfo;
	PCIDevAddrRec PCIStartDev;
	DWORD dwCurPCIAddr, dwNextHostWindowBoundary, dwLastPCIAddr;
	volatile DWORD *pvdwData;
	volatile WORD *pvwData;
	volatile BYTE *pvbData;
	DWORD dwVerificationData, dwWriteData;
	BYTE fDoVerification;
	BYTE bReadData;
	WORD wReadData;
	DWORD dwReadData;

DbgPrintf("+TRR(bTestPhase=%d, bAccessWidth=%d, dwPCISharedRAMBase=0x%x, dwStartingOffset=0x%x, dwMemsize=0x%x)\n", 
bTestPhase, bAccessWidth, dwPCISharedRAMBase, dwStartingOffset, dwMemSize);

	/* Set the base address for the shared RAM, and close all other accesses	*/
	/*	through the bridge.														*/
	if (InitI960( pRIO, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000,
		0xFFFFFFFF, 0x00000000, dwPCISharedRAMBase )) {
		DbgPrintf( "TestRAMRegion() - ERROR: Call To InitI960() Failed\n" );
		return 1;
	}

	/* Get the size and starting address for the Host Bridge PCI memory window we have to work in.	*/
	OEM_GetPCIHostBridgeWindowInfo( &PCIHostBridgeWindowInfo );

	dwCurPCIAddr = dwPCISharedRAMBase + dwStartingOffset;
	dwLastPCIAddr = dwCurPCIAddr + dwMemSize;

	DbgPrintf( "TestRAMRegion(%d) - PCI Base Addr 0x%08lX, Size 0x%08lX\n", bTestPhase, dwCurPCIAddr, dwMemSize );
	fDoVerification = (bTestPhase != 1);

#if 0
	// Decrease the dwLastPCIAddr
bAccessWidth = 32;
#endif 1

	while( dwCurPCIAddr < dwLastPCIAddr ) {
		/* Open the memory windows for all bridges, including the host bridge	*/
		PCIMapInfo.dwPCIMemBase = PCIMapInfo.dwPCIMemLimit =
			dwCurPCIAddr & ~(PCIHostBridgeWindowInfo.dwMemWinSize-1);
		PCIMapInfo.dwPCIIOBase = 0xFFFFFFFF;
		PCIMapInfo.dwPCIIOLimit = 0;
		PCIStartDev.bParentDevNo = PCIStartDev.bDevNo = 0xFF;
		if (MapPCIWindows( &PCIMapInfo, &PCIStartDev, pRIO )) {
			DbgPrintf( "TestRAMRegion(3) - ERROR: MapPCIWindows() Failed\n" );
			return 1;
		}
		/* Calculate the next address at which we will cross the host bridge	*/
		/*	memory window boundary and have to move the host bridge window again*/
		dwNextHostWindowBoundary =
			(dwCurPCIAddr & ~(PCIHostBridgeWindowInfo.dwMemWinSize-1)) + PCIHostBridgeWindowInfo.dwMemWinSize;
		pvbData = (volatile BYTE *)
			(PCIHostBridgeWindowInfo.dwMemWinBase + (dwCurPCIAddr & (PCIHostBridgeWindowInfo.dwMemWinSize-1)));
		pvdwData = (volatile DWORD *)pvwData = (volatile WORD *)pvbData;
 

#ifdef PUT_PCI_DELAY
{
	int length;
	if(StopNext) {
		DbgPrintf("\nTestPhase = %d, AccessWidth = %d\n", bTestPhase, bAccessWidth);
		DbgPrintf("Enter Buffer (fifo) size at 0x8c000000, wait loops at 0x8c000004 &\n"); 
		DbgPrintf("length of test area at 0x8c400008, Stop next time (0/1) at 8c00000C\n");

		ProcessCommands();

		my_buffer_size = *(volatile unsigned *)0x8c000000;
		my_wait = *(volatile unsigned *)0x8c000004;
		length = *(volatile unsigned *)0x8c000008;
		StopNext = *(volatile unsigned *)0x8c00000C;
		dwLastPCIAddr = dwCurPCIAddr + length;
		DbgPrintf("Decreased dwLastPCIAddr to 0x%x, my_wait = 0x%x\n", dwLastPCIAddr, my_wait);
	}
}
#endif PUT_PCI_DELAY

#if 1
DbgPrintf("TRR: MWS=0x%x", PCIHostBridgeWindowInfo.dwMemWinSize);
DbgPrintf("TRR: dwCurPCIAddr=0x%x, dNHWB=0x%x, dLastPCA: 0x%x, pvbData=0x%x, pvdwData=0x%x, bTestPhase=%d, bAccessWidth=%d\n", 
dwCurPCIAddr, dwNextHostWindowBoundary, dwLastPCIAddr, pvbData, pvdwData, bTestPhase, bAccessWidth);

⌨️ 快捷键说明

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