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

📄 testutil.cpp

📁 The Lite Evaluation/Demonstration Kit is intended to illustrate use of the AN3042. The AN3042 is c
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				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 + -