📄 testutil.cpp
字号:
printf ("ERROR: PCIAddr=%08x LocalAddr=%08x Wrote=%08x Read=%08x\n",
(long *) SMtstBlkBase+SMoffset+i, i*4, i, dRead);
}
//else
//{
// printf ("PCIAddr=%08x LocalAddr=%08x Wrote=%08x Read=%08x\n",
// (long *) SMtstBlkBase+SMoffset+i, i*4, i, dRead);
//}
}
}
else //use FILL_PATTERN
{
int i;
for (i = 0; i < SMtstBlkSz/4; i++) // Write address pattern
((long *) linBAR[0] + SMoffset)[i] = 0xAA55AA55;
for (i = 0; i < SMtstBlkSz/4; i++) // Read and check address pattern
if (((long *) linBAR[0] + SMoffset)[i] != 0xAA55AA55)
errorCnt++;
}
return (errorCnt);
} // end initSharedMem
DWORD checkSharedMem (DWORD patternStart, DWORD patternLen, DWORD patternType, DWORD comemID)
{
int SMtstBlkSz;
DWORD SMoffset;
int errorCnt = 0;
if (chipType() == CHIP3041)
{
SMtstBlkSz = 512; // For 3041, in bytes.
SMoffset = 0x0; // Offset from BAR0 for 3041, in bytes.
}
else
{
if (patternLen == 0)
SMtstBlkSz = 0x4000; // If 0 bytes specified, use the whole Shared Mem.
else
SMtstBlkSz = patternLen; // else, use the size specified in the call.
SMoffset = SM_OFFSET + patternStart/4; // in DWORDS
}
// Get a pointer to the Shared Memory area (BAR 0)
DWORD linBAR[COMEM_MAX_BARS];
DWORD returnCode = comemCopyBarPtrL(linBAR, comemID);
if (returnCode != NO_ERROR)
{
printf("Error creating BAR pointers.");
errorCnt++;
}
volatile DWORD dRead;
volatile DWORD SMtstBlkBase = linBAR[0];
if(patternType == ADDR_PATTERN)
{
DWORD i;
for (i = 0; i < (DWORD)(SMtstBlkSz/4); i++) // Read and check address pattern
{
dRead = ((long *) SMtstBlkBase + SMoffset)[i];
if ( dRead != i)
{
if(errorCnt++ < 8) // only report first 8 errors
{
printf ("ERROR:: PCIAddr=%08x LocalAddr=%08x Wrote=%08x Read=%08x\n",
(long *) SMtstBlkBase+SMoffset+i, i*4, i, dRead);
}
}
}
}
else //use FILL_PATTERN
{
int i;
for (i = 0; i < SMtstBlkSz/4; i++) // Read and check address pattern
if (((long *) linBAR[0] + SMoffset)[i] != 0xAA55AA55)
errorCnt++;
}
return (errorCnt);
} // end checkSharedMem
//
// testOpRegs
// 1. Obtain pointers to the BARs (Base Address Registers).
// 2. Read the initial contents of thr Operation Registers.
// 3. Attempt to write all 1's to each register. Some bits, i.e. status, are cleared by writing 1.
// 4. Read register back to verify that all writable bits (as defined by mask) are set.
// 5. Write all zeroes to each register.
// 6. Read register back to verify that all writable bits are set to zero.
// 7. Write back the original contents of all registers.
// 8. Verify that writable bits (i.e. not status) have been restored.
// 9. See definition of opRegs3042 to view masks.
//
DWORD testOpRegs (DWORD comemID)
{
int errorCnt = 0;
printf ("Testing Op Regs...\n");
// Get the BARs.
DWORD linBAR[COMEM_MAX_BARS];
DWORD returnCode = comemCopyBarPtrL(linBAR, comemID);
if (returnCode != NO_ERROR)
{
printf("Error creating BAR pointers.");
errorCnt++;
}
printf("testOpRegs: linBAR[0]=%08x\n", linBAR[0]);
DWORD * regs = (DWORD *) linBAR[0]; // BAR 0 for OpRegs on 3042
for (DWORD i = 0 ; i < NUMopr3042 ; i++)
{
DWORD temp, orig;
volatile DWORD * theReg; // TPM: MUST make volitile for release version
DWORD theMask = opRegs3042[i].mask; // Do this to make the code more readable.
char * theText = opRegs3042[i].text;
theReg = regs + (opRegs3042[i].offset/4); // The /4 is to convert from byte offset
// (as coded in opRegs3042 table)
// to a DWORD offset.
orig = *theReg; // Get original.
printf ("Read original contents from: %s at:%08x = %08x\n", theText, theReg, orig);
*theReg = 0xFFFFFFFF; // Attempt to write all ones.
temp = *theReg; // Read it back.
if(!strcmp(theText, "hint ") || !strcmp(theText, "lint "))
temp &= theMask; //account for stat bits (can't set from host)
if (temp != theMask)
{
errorCnt++;
printf (" Bad %s: WR 0xFFFFFFFF RD %08x Should RD %08x Errs %d\n",
theText, temp, theMask, errorCnt);
}
*theReg = 0; // Attempt to write all zeros.
temp = *theReg; // Read it back.
temp &= theMask;
if (temp != 0)
{
errorCnt++;
printf (" Bad %s: WR 0x00000000 RD %08x Should RD 00000000 Errs %d\n",
theText, temp, errorCnt);
}
*theReg = orig; // Attempt to restore original.
temp = *theReg; // Read it back.
if(!strcmp(theText, "hint ") || !strcmp(theText, "lint "))
{
orig &= 0xFFFFFC00; //account for stat bits (which were cleared)
temp &= 0xFFFFFC00; //account for stat bits (which were cleared)
}
if (temp != orig)
{
errorCnt++;
printf (" Bad %s: WR %08x RD %08x Should RD %08x Errs %d\n",
theText, orig, temp, orig, errorCnt);
}
} // end for each record in opRegs3042 table
return (errorCnt);
}
DWORD closeDriver(DWORD comemID)
{
DWORD returnCode = comemDestroyBarPtrL(comemID);
if (returnCode != NO_ERROR)
reportErrorCode(returnCode, "destroying linear pointers to BARs.");
comemCloseDriverL(comemID);
return (returnCode);
}
//////////////////////////////////////////////////////////////////////
// In order for the co-mem device to operate properly, it must be
// configured correctly by the system BIOS. If it is not configured
// correctly, this routine attempts to reconfigure it.
//////////////////////////////////////////////////////////////////////
DWORD verifyComemConfig(DWORD comemID)
{
DWORD returnCode;
PCI_CONFIG_HEADER_0 pciCfg;
returnCode = comemGetPCIInfoL(&pciCfg, comemID);
if (returnCode != NO_ERROR)
{
reportErrorCodeL(returnCode, "while reading PCI configuration.");
return returnCode;
}
if (pciCfg.LatencyTimer < 0x10)
report_errorL("Warning: Latency Timer is less than 16!");
// If the PCI host has disabled our memory, we cannot perform any functions.
// This is not a recoverable error, since we have no idea where to locate
// ourselves in memory space if the BIOS doesn't do it for us.
if (!(pciCfg.Command & 0x2))
{
report_errorL("Memory is disabled!! Co-mem will not work.!");
exit(1);
}
if (!(pciCfg.Command & 0x8))
{
report_errorL("Bus mastering not enabled by BIOS. COMEM requires bus master capability, so is about to be enabled by driver.");
pciCfg.Command |= 0x8;
comemSetPCIInfoL(&(pciCfg), comemID);
}
// The SERR bit controls the reporting of parity errors by our device during
// other device's address cycles. Since we have seen some PCI devices generate
// incorrect parity, we disable this bit to prevent the co-mem from stopping
// the system on an address parity error.
while (pciCfg.Command & 0x100)
{
int old = pciCfg.Command;
pciCfg.Command &= ~0x100;
pciCfg.Status = 0;
comemSetPCIInfoL(&(pciCfg), comemID);
// Use the dialog box to ensure that we wait a while before reading the regs
comemGetPCIInfoL(&(pciCfg), comemID);
report_errorL("SERR was enabled. It has been disabled. (Command reg %04x, ==>%04x)", old, pciCfg.Command);
}
return NO_ERROR;
}
int InitDriver(DWORD comemID)
{
unsigned long returnCode;
//////////////////////////////////////////////////////////////////////
// Contact the driver
//////////////////////////////////////////////////////////////////////
returnCode = comemOpenDriverL(comemID);
if (returnCode != NO_ERROR)
{
reportErrorCodeL(returnCode, "opening driver: CoMem Lite card may not be present in your PC");
return(1);
}
return(0);
}
DWORD doDMA(DWORD hostPhys, // host-side physical address
DWORD SMstart, // shared mem start address
DWORD DMAlength, // DMA Length
DWORD DMAdir, // DMA Direction
DWORD comemID)
{
DWORD errorCnt = 0;
DWORD linBAR[COMEM_MAX_BARS];
DWORD returnCode = comemCopyBarPtrL(linBAR, comemID);
if (returnCode != NO_ERROR)
{
reportErrorCode(returnCode, "creating BAR pointers.");
errorCnt++;
}
// check arbitration bits. // TPM: MUST make volatile for release version
volatile struct op_regs_struct_42_t * regp = (struct op_regs_struct_42_t *) (linBAR[0] + OP_REGS_BASE_42);
char tempc;
// The L and P bits should both be zero (neither side claims the DMA resource)
//printf("Checking L and P bits: &(regp->dmactl_v.dmactl_bytes[1])=%08x\n", &(regp->dmactl_v.dmactl_bytes[1]));
if ((tempc = regp->dmactl_v.dmactl_bytes[1]) != 0)
{
errorCnt++;
printf (" dmactl LP bits - bad initial state. Read %02x. Should be 00. Errs=%d\n",
tempc, errorCnt);
}
// Write all ones to the LP byte. Only the P bit should set.
regp->dmactl_v.dmactl_bytes[1] = 0xFF;
if ((tempc = regp->dmactl_v.dmactl_bytes[1]) != 1)
{
errorCnt++;
printf (" dmactl LP bits - P bit should be set. Read %02x. Should be 01. Errs=%d\n",
tempc, errorCnt);
}
// Write all zeros to the LP byte. We should be able to reset the P bit.
regp->dmactl_v.dmactl_bytes[1] = 0;
if ((tempc = regp->dmactl_v.dmactl_bytes[1]) != 0)
{
errorCnt++;
printf (" dmactl LP bits - P bit should be reset. Read %02x. Should be 00. Errs=%d\n",
tempc, errorCnt);
}
regp->dmalbase = SMstart;
regp->dmasize = DMAlength - 4; // must be reduced by one DWORD
regp->dmahbase = hostPhys;
// Check to make sure that the DMA complete bit is not already set
// (not normally required, but part of a resonable test).
if (regp->hint & DMA_COMPLETE_BIT)
{ errorCnt++;
printf ("Error: DMA_COMPLETE_BIT should not be set. Errs=%d\n", errorCnt);
}
// Show the time in mSec for the DMA
LARGE_INTEGER llnHPTimerFreq; // High Performance Timer: Frequency
LARGE_INTEGER llnHPT1; // High Performance Timer: Time 1
LARGE_INTEGER llnHPT2; // High Performance Timer: Time 2
LARGE_INTEGER llnT_uSec; // Time in microseconds
QueryPerformanceFrequency(&llnHPTimerFreq);
QueryPerformanceCounter(&llnHPT1);
// Write low-order byte of DMACTL to KICK OFF the DMA.
regp->dmactl_v.dmactl_bytes[0] = (volatile unsigned char)DMAdir;
// Wait for the DMA complete bit to be set.
DWORD timeout = DMAlength * DMAlength; // Give mucho time to complete.
while ( ((regp->hint & DMA_COMPLETE_BIT) != DMA_COMPLETE_BIT) && timeout )
timeout--; // busy loop while doing DMA
if (timeout == 0)
{
errorCnt++;
printf ("Error: timed out before DMA_COMPLETE_BIT set (DMA completed). Errs=%d\n", errorCnt);
}
else
{
if(QueryPerformanceCounter(&llnHPT2))
{
llnT_uSec.QuadPart = ( (llnHPT2.QuadPart - llnHPT1.QuadPart) * // Time Delta
((LONGLONG)1E9/llnHPTimerFreq.QuadPart) ) /
(LONGLONG)1E3; // could divide by 1E9 for Time in Sec
//printf("DMA_COMPLETE_BIT set (DMA completed) in %3d Sec: %03d mSec: %03d uSec\n",
// llnT_uSec.LowPart/(LONG)1E6, (llnT_uSec.LowPart/(LONG)1E3)%(1000), (llnT_uSec.LowPart)%(1000));
printf("DMA completed in %3d Sec: %03d mSec: %03d uSec: DMA Rate = %d Mb/Sec\n",
llnT_uSec.LowPart/(LONG)1E6, (llnT_uSec.LowPart/(LONG)1E3)%(1000),
(llnT_uSec.LowPart)%(1000), (1000000/llnT_uSec.LowPart)/(1048576/DMAlength));
}
}
return (errorCnt);
} // end doDMA()
// testDMAtoTarg
// Test DMA functionality by performing a DMA operation from the Host to the 3042.
// Initialize source buffer.
// Write a pattern to destination (Shared Mem) so the HOST has to actually change it.
// Perform DMA operation using doDMA
// Check the destination buffer.
// Deallocate buffer in host memory.
//
DWORD testDMAtoTarg(DWORD comemID)
{
DWORD errorCnt = 0;
DWORD linPage;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -