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

📄 drive42.cpp

📁 The Lite Evaluation/Demonstration Kit is intended to illustrate use of the AN3042. The AN3042 is c
💻 CPP
📖 第 1 页 / 共 3 页
字号:


DWORD boundary  = 0x80;	  // A byte offset.
DWORD blockSize = 0x4;    // DWORDs

// int guardbandSize = 0;  // DWORDs  // In this test, we put the guardband (if any) on the Local side.

//
// testSMguardband_PL
//
//
// P over L  (PCI-side block is higher in mem than Local side block)
//
DWORD testSMguardband_PL (DWORD comemID)
{
	DWORD reportBase, base, i, dRead1, dRead2, dRead3, dRead4, dWrote;

	base = getlinBAR0(comemID) + (SMbase + boundary);  // Compute a byte address
	reportBase = (SMbase + boundary);

	//  DWORD WRWR...
	for (i = 0 ; i < blockSize ; i++)
	{
		dWrote = 0x22222220 | i ;
		((long *) base)[i] = dWrote;

		if ( (dRead1 = ((long *) base)[i]) != dWrote)
		{
			dRead2 = ((long *) base)[i];				// Unconditionally read again and call the error handler.
			globalErrorCnt++;
			errorHandler (reportBase + i*4, dRead1, dRead2, dWrote);
			
			for (DWORD j = 0 ; j < 1000000 ; j++)	// We want totally different circumstances when we do the next read.
				;
			
			dRead3 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			dRead4 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			errorHandler (reportBase + i*4, dRead3, dRead4, dWrote); 
		}

		dWrote = 0xddddddd0 | i ;
		((long *) base)[i] = dWrote;

		if ( (dRead1 = ((long *) base)[i]) != dWrote)
		{
			dRead2 = ((long *) base)[i];				// Unconditionally read again and call the error handler.
			globalErrorCnt++;
			errorHandler (reportBase + i*4, dRead1, dRead2, dWrote);
			
			for (DWORD j = 0 ; j < 1000000 ; j++)	// We want totally different circumstances when we do the next read.
				;
			
			dRead3 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			dRead4 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			errorHandler (reportBase + i*4, dRead3, dRead4, dWrote); 
		}
	}


	// DWORD Block (!!!) WRWR...
	for (i = 0 ; i < blockSize ; i++)
	{
		dWrote = 0x22222220 | i ;
		((long *) base)[i] = dWrote;
	}

	for (i = 0 ; i < blockSize ; i++)
	{
		dWrote = 0x22222220 | i ;
		if ( (dRead1 = ((long *) base)[i]) != dWrote)
		{
			dRead2 = ((long *) base)[i];				// Unconditionally read again and call the error handler.
			globalErrorCnt++;
			errorHandler (reportBase + i*4, dRead1, dRead2, dWrote);
			
			for (DWORD j = 0 ; j < 1000000 ; j++)	// We want totally different circumstances when we do the next read.
				;
			
			dRead3 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			dRead4 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			errorHandler (reportBase + i*4, dRead3, dRead4, dWrote); 
		}
	}

	// DWORD Block (!!!) WRWR...
	for (i = 0 ; i < blockSize ; i++)
	{
		dWrote = 0xddddddd0 | i ;
		((long *) base)[i] = dWrote;
	}

	for (i = 0 ; i < blockSize ; i++)
	{
		dWrote = 0xddddddd0 | i ;
		if ( (dRead1 = ((long *) base)[i]) != dWrote)
		{
			dRead2 = ((long *) base)[i];				// Unconditionally read again and call the error handler.
			globalErrorCnt++;
			errorHandler (reportBase + i*4, dRead1, dRead2, dWrote);
			
			for (DWORD j = 0 ; j < 1000000 ; j++)	// We want totally different circumstances when we do the next read.
				;
			
			dRead3 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			dRead4 = ((long *) base)[i];	// Unconditionally read again and call the error handler.
			errorHandler (reportBase + i*4, dRead3, dRead4, dWrote); 
		}
	}

	return (0);

}  // end testSMguardband_PL

*/


//
// doDMA
//
// Transfer up to 16KB via the 3042's DMA controller.
//
// Although in this example, we transfer between Host Mem and the 3042's Shared Mem, we could 
// use doDMA *unchanged* to do peer-to-peer transfers between devices on the PCI bus.
// 
DWORD doDMA (DWORD * PCIphysMem, // The PCI (physical) Memory space address (as opposed to I/O or Config space addresses).
                                 // The 3042 needs this because it knows nothing (directly) about linear addresses.
            DWORD SMstart,       // Shared Mem start.  Is 0 to point to the zeroth DWORD of 3042 Shared Mem.
            DWORD length,        // Length in bytes.  Gets converted to DWORDs below.
            DWORD direction,     // To or From Host Mem.
            DWORD comemID)       // Which 3042 we're driving.
{
    DWORD errorCnt = 0;

    // Set the starting Shared Mem address in DMALBASE register. 
    g_regp->dmalbase = SMstart;     // Give it a byte address, but since DMALBASE bits 0 and 1 are dead,
                                    // this loads a DWORD address.  The L in DMALBASE means Local, as in the
                                    // Local-side interface.

    // Set the DMASIZE.
    g_regp->dmasize = length - 4;   // Give it a byte size, but since DMASIZE bits 0 and 1 are dead,
                                    // actually loads a DWORD size.  Also, the value written to the DMASIZE register
                                    // must be reduced by one DWORD (4 bytes).

    // Set the DMAHBASE to the PCI (physical) Memory address
    g_regp->dmahbase = (DWORD) PCIphysMem;  // Once again, we give it a byte address, but because bits 0 and 1 are dead
                                            // loads a DWORD address.

    //  Clear the DMA complete bit.
    g_regp->hint &= DMA_COMPLETE_BIT;

    // Write low-order byte of DMACTL to set the direction, and to KICK OFF the DMA.
    // The only operations that MUST be done on each DMA transfer are the kick off and the wait for DMA_COMPLETE_BIT.
    g_regp->dmactl_v.dmactl_bytes[0] = (unsigned char) direction;        
    
    // Now the 3042 DMA masters the PCI bus and moves the data.
    // Looking at the PCI bus, you'd see mostly bursts of data moved by the DMA, with occasional polls of HINT.
    // The length of the bursts is determined by the value in the 3042's Latency Timer,
    // and other PCI bus activity (including our HINT polling).
    
    // Wait for the DMA complete bit to be set.
    //
    // We also want to check for a timeout here, because we don't want our thread to hang with no notification 
    // if something goes wrong.
    const DWORD loopsPerByte = 0x100;        // Number of times through this 'while' loop per byte of DMA.
    int timeout = length * loopsPerByte;    // Give lots of time to complete.
    while ( ((g_regp->hint & DMA_COMPLETE_BIT) != DMA_COMPLETE_BIT) 
            && timeout
          )
    {
        // Reduce the frequency of HINT polling to improve performance, but poll often enough 
        // that a poll occurs soon after the end of the DMA transfer (ideally just after the end).
        //
        // The optimal delay to be inserted here is dependent on:
        //   - your processor speed
        //   - the length of DMA transfer
        //   - characteristics of the PCI bus arbiter, the Latency Timer setting, and other PCI bus traffic
        //   - etc., etc.
        // A loop count of 150 works well for the 16 KB blocks, 200 MHz Pentium Pro and 440FX Chipset used to tune this example.
        for (volatile DWORD i = 0 ; i < 150 ; i++)
            ;

        timeout--;
    }

    if (timeout <= 0)
    {
        errorCnt++;
        printf ("Error: timed out before DMA_COMPLETE_BIT set. errorCnt=%d\n", errorCnt);
    }

    return (errorCnt);
}   // end doDMA



//
// Send a WORD to the designated 3042 via the HL mailbox (HLDATA).
// Assumes that the Local processor has been started earlier, and that it is waiting (intently) for
//   this WORD to be sent from the host.
//
//  theWORD may be any value *except* the following:
// #define GOT_IT 0xFEDC	  // Some data pattern that is not likely to occur at random.  Must be the same as in 860 code.	

DWORD putWORD (DWORD theWORD, DWORD comemID)
{
	int timeout = 1000000;  // Give mucho time to complete.

	g_regp->hldata = theWORD & 0x0000ffff;

	while ( (g_regp->hldata == theWORD) && timeout)
			timeout--;

	if (timeout <= 0)
	{
		printf ("Timed out waiting for Local.  Is probably dead.\n");
		return LOCALDEAD;
	}
	else
		return NO_ERROR;

}  // putWORD


/*
//
//  Wait for theWORD to be stuffed into the HLDATA register by the 860.
//	
DWORD waitWORD (DWORD theWORD, DWORD comemID)
{
	int timeout = 10000000;  // Give mucho time to complete.

	theWORD &= 0x0000ffff;  // Mask in the lower-order word.

	while ( (g_regp->hldata != theWORD) && timeout)
			timeout--;

	if (timeout <= 0)
	{
		printf ("Timed out waiting for Local.  Is probably dead.\n");
		return LOCALDEAD;
	}
	else
	{
		return NO_ERROR;
	}

}  // waitWORD
*/



int init3042(int comemID)
{
    blockT map[MAX_BLOCK] = {0};  // Initialize this to all zeroes in case there is an incomplete .ini file
    DWORD returnCode;
    const int endianFlag = 3;       // Use 0 for little endian
//     char * iniFileName = ".\\3042\\map42.ini" ;
//     char * logFileBase = ".\\debug\\log" ;

    // char * hexFileName = argv[2];


    //////////////////////////////////////////////////////////////////////
    // Contact the driver
    //////////////////////////////////////////////////////////////////////
 
	returnCode = comemOpenDriverL(comemID);

    if (returnCode != NO_ERROR)
        {
        reportErrorCode(returnCode, "   opening driver");
        return(1);
        }


    // Get the linear BAR0 and BAR1 pointers (we only use BAR0 here) so we can access the 3042's registers.
    // You may want to move this out of testDMA, doing it only once at the start of your application.
    //
    // Throughout this code, 'L' at the end of function names means Lite, as in CO-MEM Lite.
    returnCode = comemCopyBarPtrL(g_linBAR, comemID);
    if (returnCode != NO_ERROR)
    {
        reportErrorCode(returnCode, "creating BAR pointers.");
        // errorCnt++;
    }

    // Setup the structure template we use to access the 3042 op regs.

    // Note well: For the 3042 structure used in this drive42.cpp module, we must NOT
    //  add in the 0x460 offset.
    g_regp = (struct op_regs_struct_42_zerobased_t *) (g_linBAR[0]);


    // Allocate 4 Pages (4 KB each, 16 KB total = size of 3042 Shared Mem) which are (must be!) 
    // contiguous in Physical (and Linear) memory space.
    //
    // We pass the Physical address to the 3042's DMA controller DMAHBASE register.
    // We need the Linear address to reference the Pages from this program, which runs on the 'Linear side' of
    // the x86's MMU (Memory Management Unit).
    //
    // This allocation may be done once when the application is launched.  However, here we chose to
    // allocate and deallocate for each invocation of testDMA.  Remember to pair allocations with
    // deallocations.
    //
    returnCode = comemAllocContigMemL (4,        // In:  Number of pages.  Can be 1 to 4. Must be 4 for this test.
                                       &g_lin,     // Out: Returns the Linear address of the allocated Pages.
                                       &g_phys,    // Out: Returns the Physical address of the allocated Pages. 
                                       comemID); // In:  The 3042 that 'owns' the pages.
    if (returnCode != NO_ERROR)
    {
        printf("Error in comemAllocContigMemL.");
        // return (++errorCnt);
    }

    g_hostLin  = (DWORD *) g_lin;
    g_hostPhys = (DWORD *) g_phys;

	g_regp->i2ohimr = 0x8;		// Turn off the I2O interrupt for safety.

    // ********* The following line must be removed for end-to-end tests !!!   ************
    g_regp->hctl    = 0x1;      // Hold the 860 in reset (S=0, R=1) while running this Application.

    PCI_CONFIG_HEADER_0  temp;
    returnCode = comemGetPCIInfoL(&temp, comemID);
	temp.LatencyTimer = 0xff;						// Set Latency Timer to the max
    returnCode = comemSetPCIInfoL(&temp, comemID);
 
    //	tortureMem(comemID); // Torture the shared memory (what's the emoticon for a sadistic laugh?).

	return (NO_ERROR);
}


// Kick off and complete a DMA transfer.
//  Called only from the demo app idle loop.
int run3042(int direction, int DMAsize, int endToEnd, int comemID)
{
    DWORD SMstart = 0;
				
    // Note: 'Host Mem' can be PCI Memory (physical) addresses other than those assigned to Host Memory.
    // In this example, we use Host Mem as the source and destination.  But the 3042 does 
    // support peer-to-peer DMA transfers.  Get the physical addresses of the peer PCI devices from their BARs.

    // We don't handle the error return from doDMA for speed, but this is not,
    // in general, recommended practice.

    if (endToEnd)
	{
		doDMA ( g_hostPhys,       // host-side physical address
                SMstart,        // Shared Mem start (first byte of shared mem = address 0)
                DMAsize,        // size of DMA transfer (in bytes)
                direction,      // the direction of the transfer
                comemID);       // which 3042 are we driving

		putWORD  (111, comemID);	// Tell the 860 to copy the data to its local mem.
		// waitWORD (444, comemID);	// Wait for the 860 to complete its copy.
	}
	else
	{
		doDMA ( g_hostPhys,       // host-side physical address
                SMstart,        // Shared Mem start (first byte of shared mem = address 0)
                DMAsize,        // size of DMA transfer (in bytes)
                direction,      // the direction of the transfer
                comemID);       // which 3042 are we driving
	}

	return (NO_ERROR);
}


DWORD closeDriver(DWORD comemID)
{
	DWORD returnCode = NO_ERROR;

    // Deallocate the 4 Pages we allocated above.
    comemDeAllocContigMemL(&g_lin, &g_phys, comemID);

    comemCloseDriverL(comemID);

	return (returnCode);
}


int close3042(int comemID)
{
	return (closeDriver(comemID));	// Frees memory, closes driver.
}




⌨️ 快捷键说明

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