📄 universedmavme_dy4.c
字号:
** async_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 non-blocking DMA copy which does not wait for the DMA copy to complete* before returning to the calling task.*** !!! NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE !!!** The user MUST install a user defined DMA interrupt handler via the* sysVmeDmaConnect() function in order for this function to work* properly.** !!! NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE --- NOTE !!!** !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!* 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: ERROR, or OK if data is transferred correctly.** SEE ALSO: sysVmeDmaSet(), sysVmeDmaGet(), sysVmeDmaLock(),* sysVmeDmaConnect(), async_sysVmeDmaExampleISR()*/STATUS async_sysVmeDmaCopy ( char * local_addr, /* Local Address */ char * vme_addr, /* VMEbus Address */ UINT32 xfer_size, /* transfersize in bytes */ BOOL to_vme /* direction */ ){ UINT32 temp; 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 ); } /* * Check that the user has actually attached a return function. * If not, clear out with an error. */ if (sysVmeDmaRoutine == NULL) { if( universeDmaDebug ) logMsg ("No VMEbus DMA interrupt function connected\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 ("async_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 ("async_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 ("async_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 ("async_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 ); /* * DMA should be running. */ return (OK);}/****************************************************************************** async_sysVmeDmaExampleISR - default VMEbus DMA interrupt function for async** This function is an example of how an asynchronous DMA ISR function* might look. It uses the global variable sysVmeDmaLastAsyncStatus to record* the status of the last asynchronous transfer. This global status word can* be accessed using the sysVmeDmaGetLastAsyncStatus() function.** This routine may be connected to the async DMA function using the* sysVmeDmaConnect().*** RETURNS: none** SEE ALSO: async_sysVmeDmaCopy(), sysVmeDmaConnect(),* sysVmeDmaGetLastAsyncStatus()*/void async_sysVmeDmaExampleISR ( void ){ UINT32 temp; temp = LONGSWAP( *UNIVERSE_DGCS ); /* * See if the DMA DONE bit is set. This indicates that a * successfull transaction has occured. */ if( (temp & DGCS_DONE) == DGCS_DONE ) { if( universeDmaDebug ) { logMsg( "VMEBus DMA termination ok!\n", 0, 0, 0, 0, 0, 0 ); } sysVmeDmaSetLastAsyncStatus( 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 ); } sysVmeDmaSetLastAsyncStatus( 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 ); } sysVmeDmaSetLastAsyncStatus( 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 ); } sysVmeDmaSetLastAsyncStatus( ERROR ); }}/****************************************************************************** sysVmeDmaGetLastAsyncStatus - get the status of the last async DMA transfer*** RETURNS: STATUS of last async DMA transfer** NOMANUAL*/STATUS sysVmeDmaGetLastAsyncStatus ( void ){ return( sysVmeDmaLastAsyncStatus );}/****************************************************************************** sysVmeDmaSetLastAsyncStatus - set the status of the last async DMA transfer*** RETURNS: STATUS of last async DMA transfer** NOMANUAL*/STATUS sysVmeDmaSetLastAsyncStatus ( STATUS last_status ){ sysVmeDmaLastAsyncStatus = last_status; return( sysVmeDmaLastAsyncStatus );}/****************************************************************************** sysVmeDmaIsAsyncDone - check to see if an asynchronous DMA transfer has* completed.** Timeout value is in seconds.** If timeout is set to 0, the function tests the semaphore immediately* with no waiting. This can be used to poll the result.** RETURNS: OK or ERROR** NOMANUAL*/STATUS sysVmeDmaIsAsyncDone( UINT32 timeout ){ STATUS sem_result; UINT32 temp; /* * Wait for the DMA to finish. If timeout is set to 0, don't wait. * This is intended to be used as a poll operation. */ if( timeout == 0 ) sem_result = semTake( vmeDmaSyncSem, NO_WAIT ); else sem_result = semTake( vmeDmaSyncSem, (timeout * sysClkRateGet()) ); /* * Check on the results of trying to get the semaphore. It could be * either a timeout or a real error. */ if( sem_result != OK ) { /* * Check for a polled "not done" condition. Currently, don't do * anything when this is detected. */ if( errno == S_objLib_OBJ_UNAVAILABLE ) { /* logMsg ("sysVmeDmaIsAsyncDone: Polled 'not done'\n", 0, 0, 0, 0, 0, 0); */ } /* * We did not get an OK (indicating completion) and we did * not get S_objLib_OBJ_UNAVAILABLE (indicating not completed). * Therefore, something serious happened and we must see what. * We should release the mutex in this case. */ else { /* * Check for a time out. If so and the debug flag is active, print * a message. */ if( errno == S_objLib_OBJ_TIMEOUT ) { 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 ); } } /* * If it was not a timeout or a poll "not done", we must not have been * able to get the binary semaphore. Report this error. */ else { logMsg ("sysVmeDmaIsAsyncDone: Cannot take Binary semaphore\n", 0, 0, 0, 0, 0, 0); } /* * We have an irreconcilable problem. Give back the mutex to release * other tasks to enter these critical sections. */ sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaIsAsyncDone: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); } /* DEBUG */ /* logMsg ("sysVmeDmaIsAsyncDone: Released Mutex semaphore (error condition)\n", 0, 0, 0, 0, 0, 0); */ } return( ERROR ); } /* * If we got here, the DMA operation has finished. */ /* * Give back the mutex to release other tasks to enter these critical * sections. */ sem_result = semGive( vmeDmaMutexSem ); if( sem_result != OK ) { logMsg ("sysVmeDmaIsAsyncDone: Cannot give Mutex semaphore\n", 0, 0, 0, 0, 0, 0); return( ERROR ); } /* DEBUG */ /* logMsg ("sysVmeDmaIsAsyncDone: Released Mutex semaphore\n", 0, 0, 0, 0, 0, 0); */ return( OK );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -