📄 universedmavme_dy4.c
字号:
*/ sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaLock: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } return( status );}/****************************************************************************** sysVmeDmaUnlock - unlock VME DMA transfer operation** This routine unlocks the VME DMA operation, if the calling task* has the lock. If <forceUnlock> is true, an unlock can be forced even* if the calling task does not possess the lock.** RETURNS: OK, or ERROR if unlock failed.** SEE ALSO: sysVmeDmaLock(), sysVmeDmaCopy(), sysVmeDmaSet(), sysVmeDmaClr()*/STATUS sysVmeDmaUnlock ( BOOL forceUnlock ){ STATUS status = ERROR; STATUS sem_result; /* * Check if the driver is initialised. */ if( !vmeDmaInitialised ) { if( universeDmaDebug ) { logMsg( "VMEBus DMA not initialized!\n", 0, 0, 0, 0, 0, 0 ); } return( ERROR ); } /* * Ensure that only one task is in this critical section at * any one time. */ sem_result = semTake( vmeDmaMutexSem, WAIT_FOREVER ); if( sem_result != OK ) { logMsg ("sysVmeDmaUnlock: Cannot take Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } /* * If either we own the lock (via the ID) or we are asking the lock to * be forced, unlock the DMA. */ if( forceUnlock || (vmeDmaLockId == taskIdSelf()) ) { vmeDmaLockId = 0; status = OK; } /* * Give back the mutex to release other tasks to enter these critical * sections. */ sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaUnlock: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } return( status );}/****************************************************************************** sysVmeDmaCopy - copy blocks across the VMEbus using the DMA** This routine is used to copy blocks to or from VMEbus using the DMA. This* is a blocking DMA copy which waits for the DMA copy to complete before* returning to the calling task.** RETURNS: ERROR, or OK if data is transferred correctly.** SEE ALSO: sysVmeDmaSet(), sysVmeDmaGet(), sysVmeDmaLock()*/STATUS sysVmeDmaCopy ( char * local_addr, /* Local Address */ char * vme_addr, /* VMEbus Address */ UINT32 xfer_size, /* transfersize in bytes */ BOOL to_vme /* direction */ ){ STATUS status = ERROR; STATUS sem_result; UINT32 temp; /* * Check if the driver is initialised. */ if( !vmeDmaInitialised ) { if( universeDmaDebug ) logMsg( "VMEBus DMA not initialized!\n", 0, 0, 0, 0, 0, 0 ); return( ERROR ); } /* * Ensure that only one task is in this critical section at * any one time. */ sem_result = semTake( vmeDmaMutexSem, WAIT_FOREVER ); if( sem_result != OK ) { logMsg ("sysVmeDmaCopy: Cannot take Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } /* * Ensure that the calling task owns the lock or there is no lock in * place before continuing. An unowned lock is signified by the ID * being 0. */ if( (vmeDmaLockId != taskIdSelf()) && (vmeDmaLockId != 0) ) { if( universeDmaDebug ) logMsg( "VMEBus DMA locked by another task!\n", 0, 0, 0, 0, 0, 0 ); sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaCopy: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); } return( ERROR ); } /* * Check to see if the size requested is within range. */ if( xfer_size > 0x1000000 ) { if( universeDmaDebug ) logMsg( "Requested VMEbus DMA transfer size too large!\n", 0, 0, 0, 0, 0, 0 ); sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaCopy: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); } return( ERROR ); } /* * Check the source and destination addresses are aligned to the same * oct-byte boundary. */ if( ((UINT32)local_addr & 0x7) != ((UINT32)vme_addr & 0x7) ) { if( universeDmaDebug ) logMsg( "Src/Dest VMEbus DMA oct-byte boundaries not equal!\n", 0, 0, 0, 0, 0, 0); sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaCopy: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); } return( ERROR ); } /* * Set local (PCI) Address. */ *UNIVERSE_DLA = LONGSWAP( (UINT32)local_addr ); /* * Set VME Address. */ *UNIVERSE_DVA = LONGSWAP( (UINT32)vme_addr ); /* * Set transfer size. */ *UNIVERSE_DTBC = LONGSWAP( xfer_size ); /* * Set transfer direction. */ temp = LONGSWAP( *UNIVERSE_DCTL ); temp = (temp & ~DCTL_L2V) | ((to_vme ? 1 : 0) << 31); *UNIVERSE_DCTL = LONGSWAP( temp ); /* * If debug is enabled, tell the world what we are doing. */ if( universeDmaDebug ) { logMsg( "VMEBus DMA started\n", 0, 0, 0, 0, 0, 0 ); logMsg( "Local address : %08x\n", (UINT32)local_addr, 0, 0, 0, 0, 0 ); logMsg( "VMEBus address : %08x\n", (UINT32)vme_addr, 0, 0, 0, 0, 0 ); logMsg( "Transfer length : %08x\n", xfer_size, 0, 0, 0, 0, 0 ); } /* * Clear all status bits and start transfer. */ temp = LONGSWAP( *UNIVERSE_DGCS ); temp = ( temp | DGCS_GO | DGCS_STOP | DGCS_HALT | DGCS_DONE | DGCS_LERR | DGCS_VERR | DGCS_P_ERR ); *UNIVERSE_DGCS = LONGSWAP( temp ); /* * The ISR reports the DMA interrupt has fired by returning this * semaphore. If we get the semaphore back in time, it means that * some portion of the DMA triggered an interrupt (good or bad). */ if( semTake( vmeDmaSyncSem, (MAX_SECONDS_FOR_DMA_COMPLETION * sysClkRateGet())) == ERROR ) { /* * Whoops!! There was no response from the DMA interrupt. We * have timeout out! Kill the DMA transaction by setting the * STOP_REQ bit. */ temp = LONGSWAP( *UNIVERSE_DGCS ); temp = (temp | DGCS_STOP_REQ); *UNIVERSE_DGCS = LONGSWAP( temp ); if( universeDmaDebug ) { logMsg( "VMEBus DMA aborted due to timeout!\n", 0, 0, 0, 0, 0, 0 ); } status = ERROR; } /* * We got a DMA interrupt and now we must process the DMA status * register for the results. */ else { temp = LONGSWAP( *UNIVERSE_DGCS ); /* * See if the DMA DONE bit is set. This indicates that a * successfull transaction occured. */ if( (temp & DGCS_DONE) == DGCS_DONE ) { if( universeDmaDebug ) { logMsg( "VMEBus DMA termination ok!\n", 0, 0, 0, 0, 0, 0 ); } status = OK; } /* * See if the LERR bit is set indicating a local (PCI) bus error. */ if( (temp & DGCS_LERR) == DGCS_LERR ) { if( universeDmaDebug ) { logMsg( "VMEBus DMA error on PCI!\n", 0, 0, 0, 0, 0, 0 ); } status = ERROR; } /* * See if the VERR bit is set indicating a VMEbus error. */ if( (temp & DGCS_VERR) == DGCS_VERR ) { if( universeDmaDebug ) { logMsg( "VMEBus DMA error on VME!\n", 0, 0, 0, 0, 0, 0 ); } status = ERROR; } /* * Check if DMA P_ERR bit is set indicating a ??? error. */ if( (temp & DGCS_P_ERR) == DGCS_P_ERR ) { if( universeDmaDebug ) { logMsg( "VMEBus DMA error, misaligned transfer!\n", 0, 0, 0, 0, 0, 0 ); } status = ERROR; } } /* * Give back the mutex to release other tasks to enter these critical * sections. */ sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaCopy: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } return( status );}/****************************************************************************** sysVmeDmaConnect - connect a function to the DMA interrupt rountine.** The routine installs a terminal interrupt routine to the DMA interrupt* service routine. This is intended for use with the asynchronous DMA* function async_sysVmeDmaCopy().*** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!* NOTE NOTE NOTE: The mixed use of blocking and non-blocking* DMA functions is NOT RECOMMENDED. If this is required, the* task using non-block calls MUST DISCONNECT the sysVmeDmaRoutine* after DMA use by connecting a NULL vector using the* sysVmeDmaConnect() function. This MUST be done BEFORE a* blocking call is used.* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!* NOTE NOTE NOTE: Since the user function is executing at* interrupt level, the user should be aware that this function* might have a significant impact on interrupt performance. It* is advisable to execute as little as possible in the user* function.* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!** RETURNS: OK** SEE ALSO: async_sysVmeDmaCopy(), async_sysVmeDmaExampleISR()*/STATUS sysVmeDmaConnect ( FUNCPTR routine ){ STATUS sem_result; /* * Check if the driver is initialised. */ if( !vmeDmaInitialised ) { if( universeDmaDebug ) logMsg( "VMEBus DMA not initialized!\n", 0, 0, 0, 0, 0, 0 ); return( ERROR ); } /* * Ensure that only one task is in this critical section at * any one time. */ sem_result = semTake( vmeDmaMutexSem, WAIT_FOREVER ); if( sem_result != OK ) { logMsg ("sysVmeDmaConnect: Cannot take Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } /* * Ensure that the calling task owns the lock or there is no lock in * place before continuing. An unowned lock is signified by the ID * being 0. */ if( (vmeDmaLockId != taskIdSelf()) && (vmeDmaLockId != 0) ) { if( universeDmaDebug ) logMsg( "VMEBus DMA locked by another task!\n", 0, 0, 0, 0, 0, 0 ); sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaConnect: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); } return( ERROR ); } /* * Set the user defined ISR routine address. */ sysVmeDmaRoutine = routine; /* * Give back the mutex to release other tasks to enter these critical * sections. */ sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaConnect: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } return (OK);}/****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -