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 + -
显示快捷键?