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

📄 drive42.cpp

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			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).	//FXN
                                 // 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.
            HANDLE InterruptEvt  // Interrupt event flag to wait on	//FXN
){
    DWORD errorCnt = 0;
    DWORD WaitStatus;	//FXN
    int timeout;	//FXN

		// Check for valid mapping to DMA space.	//FXN
		if(PCIphysMem == 0) return (1);	//FXN

    // 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.
		// debug
    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 = PCIphysMem;  // Once again, we give it a byte address, but because bits 0 and 1 are dead	//FXN
                                            // loads a DWORD address.

    //  Clear the DMA complete bit.
    if(PollingOnly) g_regp->hint &= DMA_COMPLETE_BIT;	//FXN

    // 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 to complete via an interrupt.	//FXN
    if(PollingOnly == false){	//FXN
      WaitStatus = WaitForSingleObject(InterruptEvt, 100);	//FXN
      if(WaitStatus == WAIT_TIMEOUT){	//FXN
        timeout = 0;	//FXN
				PollingOnly = true;	//FXN
				AfxMessageBox(	//FXN
					"Timed out waiting for DMA COMPLETE\n"	//FXN
					"interrupt. Switching to polling method.",	//FXN
					MB_OK	//FXN
				);	//FXN
			}	//FXN
      else	//FXN
        timeout = 1;	//FXN
    }	//FXN

    // Wait for the DMA complete bit to be set (i.e., polling).
    else{	//FXN
      
      //
      // 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.
      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--;
      }
    }	//FXN

    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	//FXN
//     char * iniFileName = ".\\3042\\map42.ini" ;
//     char * logFileBase = ".\\debug\\log" ;

    // char * hexFileName = argv[2];
		unsigned long IOMemory;	//FXN
		unsigned long IOSpace;	//FXN
		unsigned long Length;	//FXN
		unsigned long Status;	//FXN


    //////////////////////////////////////////////////////////////////////
    // Contact the driver
    //////////////////////////////////////////////////////////////////////
 
    //returnCode = comemOpenDriverL(comemID);
    if(comemID < 8)	//FXN
      returnCode = OpenPCIDP(comemID, &PCIDPHandle[comemID]);	//FXN
    else
      returnCode = 87;	//FXN ERROR_INVALID_PARAMETER

    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++;
    //}

    Length = 0x8000;
    returnCode = MapBaseRegister(	//FXN
      PCIDPHandle[comemID],	//FXN
      0,	//FXN
      &Length,	//FXN
      &PCIDPMemory[comemID],	//FXN
      &IOMemory,	//FXN
      &IOSpace	//FXN
    );	//FXN

    if (returnCode != NO_ERROR){	//FXN
      reportErrorCode(returnCode, "mapping to board memory");	//FXN
      return(1);	//FXN
    }	//FXN
    g_linBAR[0] = (DWORD)PCIDPMemory[comemID];	//FXN

    // 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)	//FXN
    //{
    //    //printf("Error in comemAllocContigMemL.");	//FXN
    //    printf("Error Allocating Contiguous Memory\n");	//FXN
    //    // return (++errorCnt);	//FXN
    //}	//FXN

    // Maping to the DMA space should be moved to TestMenu.  It's not a good	//FXN
    // idea to leave this area continuously mapped.  If the application should	//FXN
    // fail and the DMA is still mapped, it will cause the entire system	//FXN
    // to crash.	//FXN
		Status = MapDMAMemory(	//FXN
			PCIDPHandle[comemID],	//FXN
			(unsigned long**)&DMALinAddress, 	//FXN
			&DMAPhyAddress	//FXN
		);	//FXN
		if(Status != ERROR_SUCCESS){
			char ErrorMsg[100];	//FXN
			DMAPhyAddress = 0;
			sprintf(	//FXN
				ErrorMsg,	//FXN
				"Error: Could not map to DMA space. Error code = %d.",	//FXN
				Status	//FXN
			);	//FXN
			AfxMessageBox(ErrorMsg, MB_ICONEXCLAMATION | MB_OK);	//FXN
		}

		// Register the DMA complete interrupt.	//FXN
		Status = RegisterInterrupt(	//FXN
			PCIDPHandle[comemID],	//FXN
			PCIDP_DMAComplete,	//FXN
			&InterruptID,	//FXN
			&InterruptEvt	//FXN
		);	//FXN
		if(Status != ERROR_SUCCESS){	//FXN
			char ErrorMsg[200];	//FXN
			PollingOnly = true;	//FXN
			sprintf(	//FXN
				ErrorMsg,	//FXN
				"Warning: Could not register DMA interrupt. Error code = %d.\n"	//FXN
				"Using polling to wait for DMA completion instead.",	//FXN
				Status	//FXN
			);	//FXN
			AfxMessageBox(ErrorMsg, MB_ICONEXCLAMATION | MB_OK);	//FXN
		}	//FXN
		else{	//FXN
			ResetEvent(InterruptEvt);	//FXN
			PollingOnly = false;
		}

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

    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;
    PCIDP_CONFIG PCIConfig;	//FXN
    //returnCode = comemGetPCIInfoL(&temp, comemID);	//FXN
    returnCode = GetPCIConfigurationSpace(PCIDPHandle[comemID], &PCIConfig);	//FXN
    //temp.LatencyTimer = 0xff;						// Set Latency Timer to the max	//FXN
    PCIConfig.LatencyTimer = 0xff;						// FXN
    //returnCode = comemSetPCIInfoL(&temp, comemID);	//FXN
    SetPCIConfigurationSpace(PCIDPHandle[comemID], &PCIConfig);	//FXN

    //	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(unsigned long PhyAddr, int direction, int DMAsize, int endToEnd, int comemID, HANDLE IntEvt)	//FXN
{
    DWORD SMstart = 0;
    int returncode;
				
    // 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)
	{
		returncode = doDMA ( PhyAddr,       // host-side physical address	//FXN
                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
                IntEvt);        // DMA complete event

		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
	{
		returncode = doDMA ( PhyAddr,       // host-side physical address	//FXN
                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
                IntEvt);        // DMA complete event
	}

	//return (NO_ERROR);	//FXN
	return returncode;
}


DWORD closeDriver(DWORD comemID)
{
	DWORD returnCode = NO_ERROR;
	unsigned long Status;

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

    // Unmapping the DMA space should be moved to TestMenu.	//FXN
		Status = UnRegisterInterrupt(	//FXN
			PCIDPHandle[comemID],	//FXN
			InterruptID	//FXN
		);	//FXN

		Status = UnMapDMAMemory(	//FXN
			PCIDPHandle[comemID], 	//FXN
			DMALinAddress	//FXN
		);	//FXN

    //comemCloseDriverL(comemID);	//FXN

	return (returnCode);
}


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




⌨️ 快捷键说明

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