?? universe.c
字號:
* The DMA engine will also be permanently configured so that the PCI Bus* will perform 64-bit transactions.* * NOTE: This low-level driver is strictly non-sharable; however,* it contains no guards to prevent multiple tasks from calling* it simultaneously. It assumes that the application layer will* provide atomic access to this driver through the use of a* semaphore or similar guards.** In addition, the internals of this driver only operates in a* non-interrupt (polled) mode; it uses a busy loop to sample the* DMA transfer status. This implies that the calling task will* wait until the DMA transfer has terminated. As a precaution,* it is recommended by the Tundra User's Manual that the calling* task set up a background timer to prevent an infinite wait* caused by a system problem. Also, tasks transferring large* blocks of data should lower their priority level to allow other* tasks to run, and tasks transferring small blocks of data* should use bcopy() instead of calling this driver.** RETURNS: OK*/STATUS sysVmeDmaInit ( void ) { /* Configure the DMA Transfer Control register */ UNIV_OUT_LONG(UNIVERSE_DCTL, (VME_DMA_XFER_TYPE | VME_DMA_ADDR_SPACE | VME_DMA_DATA_TYPE | VME_DMA_USER_TYPE | DCTL_LD64EN )); sysVmeDmaReady = TRUE; return (OK); }/******************************************************************************** sysVmeDmaCnfgGet - Get DMA transfer configuration parameters** This routine will get the DMA transfer parameters.** RETURNS: OK or ERROR*/STATUS sysVmeDmaCnfgGet ( UINT32 *xferType, /* output: Ptr to VMEbus data transfer type */ /* Valid range: */ /* (DCTL_VDW_8 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_16 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_32 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_64 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_32 | DCTL_VCT_BLK) ** BLT */ /* (DCTL_VDW_64 | DCTL_VCT_BLK) ** MBLT */ UINT32 *addrSpace, /* output: Ptr to VMEbus Address Space type */ /* Valid range: */ /* DCTL_VAS_A16 */ /* DCTL_VAS_A24 */ /* DCTL_VAS_A32 */ UINT32 *dataType, /* output: Ptr to Program/Data AM Code */ /* Valid range: */ /* DCTL_PGM_DATA */ /* DCTL_PGM_PRGM */ UINT32 *userType /* output: Ptr to Supervisor/User AM Code */ /* Valid range: */ /* DCTL_SUPER_USER */ /* DCTL_SUPER_SUP */ ) { UINT32 dctlReg; if (!sysVmeDmaReady) { return (ERROR); } /* Get contents of DMA Transfer Control register */ UNIV_IN_LONG(UNIVERSE_DCTL, &dctlReg); /* Extract the VMEbus data transfer type */ *xferType = (dctlReg & (DCTL_VDW_MSK | DCTL_VCT_MSK)); /* Extract the VMEbus Address Space type */ *addrSpace = (dctlReg & DCTL_VAS_MSK); /* Extract the Program/Data AM Code */ *dataType = (dctlReg & DCTL_PGM_MSK); /* Extract the Supervisor/User AM Code */ *userType = (dctlReg & DCTL_SUPER_MSK); return (OK); }/******************************************************************************** sysVmeDmaCnfgSet - Set DMA transfer configuration parameters** This routine will configure the DMA transfer parameters.** RETURNS: OK or ERROR*/STATUS sysVmeDmaCnfgSet ( UINT32 xferType, /* input: VMEbus data transfer type */ /* Valid range: */ /* (DCTL_VDW_8 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_16 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_32 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_64 | DCTL_VCT_SINGLE) */ /* (DCTL_VDW_32 | DCTL_VCT_BLK) ** BLT */ /* (DCTL_VDW_64 | DCTL_VCT_BLK) ** MBLT */ UINT32 addrSpace, /* input: VMEbus Address Space type */ /* Valid range: */ /* DCTL_VAS_A16 */ /* DCTL_VAS_A24 */ /* DCTL_VAS_A32 */ UINT32 dataType, /* imput: Ptr to Program/Data AM Code */ /* Valid range: */ /* DCTL_PGM_DATA */ /* DCTL_PGM_PRGM */ UINT32 userType /* input: Supervisor/User AM Code */ /* Valid range: */ /* DCTL_SUPER_USER */ /* DCTL_SUPER_SUP */ ) { UINT32 dctlReg; if (!sysVmeDmaReady) { return (ERROR); } /* Get contents of DMA Transfer Control register */ UNIV_IN_LONG(UNIVERSE_DCTL, &dctlReg); /* Setup the VMEbus data transfer type */ dctlReg &= ~(DCTL_VDW_MSK | DCTL_VCT_MSK); dctlReg |= (xferType & (DCTL_VDW_MSK | DCTL_VCT_MSK)); /* Setup the VMEbus Address Space type */ dctlReg &= ~(DCTL_VAS_MSK); dctlReg |= (addrSpace & DCTL_VAS_MSK); /* Setup the Program/Data AM Code */ dctlReg &= ~(DCTL_PGM_MSK); dctlReg |= (dataType & DCTL_PGM_MSK); /* Setup the Supervisor/User AM Code */ dctlReg &= ~(DCTL_SUPER_MSK); dctlReg |= (userType & DCTL_SUPER_MSK); /* Update contents of DMA Transfer Control register */ UNIV_OUT_LONG(UNIVERSE_DCTL, dctlReg); return (OK); }/******************************************************************************** sysVmeDmaStatusGet - Get DMA transfer Status** This routine will return the status of the DMA transfer.** RETURNS: OK or ERROR*/STATUS sysVmeDmaStatusGet ( UINT32 *transferStatus /* State of DMA transfer defined as */ /* DGCS register status bits */ /* DGCS_ACT | DGCS_STOP | DGCS_HALT | */ /* DGCS_DONE | DGCS_LERR | DGCS_VERR | */ /* DGCS_P_ERR */ ) { UINT32 dgcsReg; if (!sysVmeDmaReady) { return (ERROR); } /* Get contents of DMA General Control/Status register */ UNIV_IN_LONG(UNIVERSE_DGCS, &dgcsReg); /* Return the status of the DMA transfer */ *transferStatus = (dgcsReg & DGCS_STATUS_MSK); return (OK); }/******************************************************************************** sysVmeDmaL2VCopy - Copy data from local memory to VMEbus memory** This routine copies data from local memory to VMEbus memory using* the Universe's DMA engine.** NOTE: This routine assumes that the DMA transfer configuration* parameters have been previously set up either at driver init time* (sysVmeDmaInit()) with the default parameters in config.h or* dynamically by calling sysVmeDmaCnfgSet().** .CS* RETURNS: OK,* ERROR - driver not initialized or invalid argument,* DGCS_LERR - PCI Bus Error,* DGCS_VERR - VMEbus Error,* or* DGCS_P_ERR - Protocol Error* .CE*/STATUS sysVmeDmaL2VCopy ( UCHAR *localAddr, /* Local Address as seen by the CPU */ UCHAR *localVmeAddr, /* VMEbus Address as seen by the CPU */ UINT32 nbytes ) { return (sysVmeDmaCopy(localAddr, localVmeAddr, nbytes, (UINT32)DCTL_L2V_PCI_VME)); }/******************************************************************************** sysVmeDmaV2LCopy - Copy data from VMEbus memory to local memory** This routine copies data from VMEbus memory to local memory using* the Universe's DMA engine.** NOTE: This routine assumes that the DMA transfer configuration* parameters have been previously set up either at driver init time* (sysVmeDmaInit()) with the default parameters in config.h or* dynamically by calling sysVmeDmaCnfgSet().** .CS* RETURNS: OK,* ERROR - driver not initialized or invalid argument,* DGCS_LERR - PCI Bus Error,* DGCS_VERR - VMEbus Error,* or* DGCS_P_ERR - Protocol Error* .CE*/STATUS sysVmeDmaV2LCopy ( UCHAR *localVmeAddr, /* VMEbus Address as seen by the CPU */ UCHAR *localAddr, /* Local Address as seen by the CPU */ UINT32 nbytes ) { return (sysVmeDmaCopy(localAddr, localVmeAddr, nbytes, (UINT32)DCTL_L2V_VME_PCI)); }/******************************************************************************** sysVmeDmaCopy - Copy data between local and VMEbus memory** This routine copies data between local and VMEbus memory using* the Universe's DMA engine. In addition to the parameters passed in,* this routine uses the macros VME_DMA_MAX_BURST and VME_DMA_MIN_TIME_OFF_BUS* defined in config.h to set up VON and VOFF, respectfully.** NOTE: This routine assumes that the DMA transfer configuration* parameters have been previously set up either at driver init time* (sysVmeDmaInit()) with the default parameters in config.h or* dynamically by calling sysVmeDmaCnfgSet().** The sampling rate to determine the DMA transfer status* will directly affect the throughput of the DMA transfer.** .CS* RETURNS: OK,* ERROR - driver not initialized or invalid argument,* DGCS_LERR - PCI Bus Error,* DGCS_VERR - VMEbus Error,* or* DGCS_P_ERR - Protocol Error* .CE*/LOCAL STATUS sysVmeDmaCopy ( UCHAR *localAddr, /* Local Address as seen by the CPU */ UCHAR *localVmeAddr, /* VMEbus Address as seen by the CPU */ UINT32 nbytes, /* number of bytes to copy: */ /* max = DTBC_VALID_BITS_MASK */ UINT32 direction /* Copy direction: DCTL_L2V_PCI_VME, DCTL_L2V_VME_PCI */ ) { UCHAR *pciAddr; UCHAR *vmeAddr; UINT32 dctlReg; UINT32 dgcsReg; if (!sysVmeDmaReady) { return (ERROR); } /* Check addresses for 8-byte alignment to each other */ if (((UINT32)localAddr & 0x7) != ((UINT32)localVmeAddr & 0x7)) { return (ERROR); } /* Check for too large a transfer byte count */ if (nbytes > DTBC_VALID_BITS_MASK) { return (ERROR); } /* * Clearing the chain bit and setting the GO bit at the same time * does not work. So, clearing the chain bit and setting up VON * and VOFF is done before setting up the source and destination * register as called out in the Universe manual. */ UNIV_IN_LONG(UNIVERSE_DGCS, &dgcsReg); dgcsReg &= ~(DGCS_CHAIN_MSK | DGCS_VON_MSK | DGCS_VOFF_MSK); dgcsReg |= (VME_DMA_MAX_BURST | VME_DMA_MIN_TIME_OFF_BUS); UNIV_OUT_LONG(UNIVERSE_DGCS, dgcsReg); /* Setup transfer direction */ UNIV_IN_LONG(UNIVERSE_DCTL, &dctlReg); dctlReg &= ~(DCTL_L2V_MSK); dctlReg |= (direction & DCTL_L2V_MSK); UNIV_OUT_LONG(UNIVERSE_DCTL, dctlReg); /* * Convert the VME address as seen by the CPU to a * VMEbus address as seen on the VMEbus, and store * it in the DMA engine's VMEbus address register. */ switch (dctlReg & DCTL_VAS_MSK) { case DCTL_VAS_A32: vmeAddr = (UCHAR *)((UINT32)localVmeAddr - (UINT32)VME_A32_MSTR_LOCAL + (UINT32)VME_A32_MSTR_BUS); UNIV_OUT_LONG(UNIVERSE_DVA, vmeAddr); break; case DCTL_VAS_A24: vmeAddr = (UCHAR *)((UINT32)localVmeAddr - (UINT32)VME_A24_MSTR_LOCAL + (UINT32)VME_A24_MSTR_BUS); UNIV_OUT_LONG(UNIVERSE_DVA, vmeAddr); break; case DCTL_VAS_A16: vmeAddr = (UCHAR *)((UINT32)localVmeAddr - (UINT32)VME_A16_MSTR_LOCAL + (UINT32)VME_A16_MSTR_BUS); UNIV_OUT_LONG(UNIVERSE_DVA, vmeAddr); break; default: return (ERROR); } /* * Convert the local address to a PCI address as seen * on the PCI Bus, and store it in the DMA engine's * PCI Bus address register. */ pciAddr = (UCHAR *)((UINT32)localAddr + (UINT32)PCI2DRAM_BASE_ADRS); UNIV_OUT_LONG(UNIVERSE_DLA, pciAddr); /* Configure DMA engine's byte count */ UNIV_OUT_LONG(UNIVERSE_DTBC, nbytes); /* Start transfer by clearing status and setting GO bit */ dgcsReg &= ~(DGCS_STATUS_MSK); dgcsReg |= DGCS_GO; UNIV_OUT_LONG(UNIVERSE_DGCS, dgcsReg); /* Wait for transfer to terminate */ UNIV_IN_LONG(UNIVERSE_DGCS, &dgcsReg); while (dgcsReg & DGCS_ACT) { sysUsDelay(25); UNIV_IN_LONG(UNIVERSE_DGCS, &dgcsReg); } if (dgcsReg & DGCS_DONE) { return (OK); } else { return (dgcsReg & (DGCS_LERR | DGCS_VERR | DGCS_P_ERR)); } }#endif /* INCLUDE_VME_DMA */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -