/*---------------------------------------------------------------------------* Project: DMAEngine library File: dmae.h Copyright (C) 2011 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ #ifndef __DMAE_H__ #define __DMAE_H__ #ifdef __cplusplus extern "C" { #endif /// @defgroup DMAE DMAE /// @defgroup DMAEConstants Constants /// @ingroup DMAE /// @addtogroup DMAEConstants /// @{ #define DMAE_INLINE inline /// \brief DMAE data buffers must be aligned by this many bytes. /// \note Semaphores must be aligned by sizeof(u64) = 8 bytes. #define DMAE_DATA_ALIGNMENT 4 /// \brief Default timeout for \ref DMAEWaitDone in milliseconds. /// This timeout value can be set via \ref DMAESetTimeout API #define DMAE_DEFAULT_TIMEOUT_IN_MILLISEC (30 * 1000) /// \brief Type used for DMA Engine time stamps /// /// Time stamps are used to check when DMA commands complete. /// typedef u64 DMAETimeStamp; /// @} /// @defgroup DMAEEnums Enums /// @ingroup DMAE /// @addtogroup DMAEEnums /// @{ /// \brief Type of endian swapping mode /// typedef enum DMAEEndian { DMAE_ENDIAN_NONE = 0x00000000, ///< do-nothing DMAE_ENDIAN_8IN16 = 0x00000001, ///< 8IN16 swapping mode. Endian swap in 16-bit int buffer. DMAE_ENDIAN_8IN32 = 0x00000002, ///< 8IN32 swapping mode. Endian swap in 32-bit int buffer. DMAE_ENDIAN_8IN64 = 0x00000003, ///< 8IN64 swapping mode. Endian swap in 64-bit int buffer. } DMAEEndian; /// \brief Type of DMA semaphore action /// typedef enum _DMAESemaphoreAction { DMAE_SEMAPHORE_WAIT = 0x00000000, ///< Wait before processing next command DMAE_SEMAPHORE_SIGNAL = 0x00000001, ///< Signal after all previous work is done } DMAESemaphoreAction; /// @} /// @defgroup DMAESynchronization Synchronization /// @ingroup DMAE /// @addtogroup DMAESynchronization /// @{ /// \brief Wait for a DMA command to complete. /// /// Returns false if a time-out occurs, true otherwise. /// A time-out should never occur in a correctly written program. /// The time-out value is set at 5 seconds. /// /// \param ts time stamp of command in question /// \return TRUE normally; FALSE if a time-out occurred /// /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall /// /// \writesdmae /// BOOL DMAEWaitDone(DMAETimeStamp ts); /// \brief Get time stamp of last submitted command. /// /// \donotcall \threadsafe \devonly \enddonotcall /// DMAETimeStamp DMAEGetLastSubmittedTimeStamp(void); /// \brief Indicate most recent time stamp completed (retired). /// /// When the value of this function matches or exceeds that of a specified command, /// then that command is completely finished. /// /// \return The value of the most recently completed time stamp /// /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall /// DMAETimeStamp DMAEGetRetiredTimeStamp(void); /// \brief Check if a command is done. /// /// A helper function to indicate if a specified command is completed. /// /// \param ts time stamp of command in question /// \return TRUE if the command is done, FALSE otherwise. /// /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall /// DMAE_INLINE BOOL DMAEIsDone(DMAETimeStamp ts) { return ts <= DMAEGetRetiredTimeStamp(); } /// \brief Initialize DMAE semaphore. /// /// This function is used to initialize the semaphore to syncronize DMA Engine /// with the GPU7. /// The semaphore value is kept in memory at the specified location. /// It is initialized to a specified count and flushed from the cache. /// This API has exactly the same functional capability as \ref GX2InitSemaphore. /// /// \param semaphoreAddr Location of semaphore data in memory /// \param semaphoreCount Initial semaphore count /// /// \donotcall \notthreadsafe \devonly \enddonotcall /// DMAE_INLINE void DMAEInitSemaphore(u64 *semaphoreAddr, u64 semaphoreCount) { // Store u64 byte-reversed (hardware requirement), so do lower half first: * (__bytereversed u32 *) semaphoreAddr = (u32) (semaphoreCount & 0xffffffff); * (((__bytereversed u32 *) semaphoreAddr)+1) = (u32) (semaphoreCount >> 32); DCFlushRange(semaphoreAddr, sizeof(u64)); } /// \brief Have DMA Engine wait on or signal a memory semaphore. /// /// This function is used to syncronize the DMA Engine with the GPU. /// The semaphore value is kept in memory at the specified location. /// It should be initialized and flushed from the cache before use. /// /// The command is put into the DMAEngine command queue immediately. /// /// \param semaphoreAddr Location of semaphore data in memory /// \param semaphoreAction Indicates whether to wait on or signal the semaphore /// \return time stamp for command submission /// /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall /// /// \writesdmae /// DMAETimeStamp DMAESemaphore(u64 *semaphoreAddr, DMAESemaphoreAction semaphoreAction); /// @} /// @defgroup DMAECopy Copy /// @ingroup DMAE /// @addtogroup DMAECopy /// @{ /// \brief Issue a DMA command to copy memory from one range to another. /// /// The command is put into the DMAEngine command queue immediately. /// However, this function does not wait for it to complete. /// Both ranges should be flushed or invalidated from the CPU cache /// prior to calling this function. /// /// \param dst Destination of data to copy (8B aligned) /// \param src Source of data to copy (8B aligned) /// \param sizeInU32s Size of data to copy (in u32 units) /// \param endian Endian mode for swapping destination data /// \return time stamp for command submission /// /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall /// /// \writesdmae /// DMAETimeStamp DMAECopyMem(void *dst, const void *src, u32 sizeInU32s, DMAEEndian endian); /// \brief Issue a DMA command to copy memory from one range to another. /// /// The command is put into the DMAEngine command queue immediately and waits for it to complete. /// Both ranges should be flushed or invalidated from the CPU cache /// prior to calling this function. /// /// \param dst Destination of data to copy (8B aligned) /// \param src Source of data to copy (8B aligned) /// \param sizeInU32s Size of data to copy (in u32 units) /// \param endian Endian mode for swapping destination data /// \return TRUE normally; FALSE if a time-out occurred /// /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall /// /// \writesdmae /// DMAE_INLINE BOOL DMAECopyMemWait(void *dst, const void *src, u32 sizeInU32s, DMAEEndian endian) { return DMAEWaitDone( DMAECopyMem(dst, src, sizeInU32s, endian) ); } /// @} /// @defgroup DMAEFill Fill /// @ingroup DMAE /// @addtogroup DMAEFill /// @{ /// \brief Issue a DMA command to fill a memory range with a specified value. /// /// The command is put into the DMAEngine command queue immediately. /// However, this function does not wait for it to complete. /// The range should be flushed or invalidated from the CPU cache /// prior to calling this function. /// /// \param dst Start of range to fill (8B aligned) /// \param fillData Value to fill range with (a u32) /// \param sizeInU32s Size of range to fill (in u32 units) /// \return time stamp for command submission /// /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall /// /// \writesdmae /// DMAETimeStamp DMAEFillMem(void *dst, u32 fillData, u32 sizeInU32s); /// \brief Issue a DMA command to fill a memory range with a specified value. /// /// The command is put into the DMAEngine command queue and waits for it to complete. /// The range should be flushed or invalidated from the CPU cache /// prior to calling this function. /// /// \param dst Start of range to fill (8B aligned) /// \param fillData Value to fill range with (a u32) /// \param sizeInU32s Size of range to fill (in u32 units) /// \return TRUE normally; FALSE if a time-out occurred /// /// \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall /// /// \writesdmae /// DMAE_INLINE BOOL DMAEFillMemWait(void *dst, u32 fillData, u32 sizeInU32s) { return DMAEWaitDone( DMAEFillMem(dst, fillData, sizeInU32s) ); } /// @} // For Nintendo use only // \brief Issue a DMA command to fill a physical memory range with a specified value. // // The range should be flushed or invalidated from the CPU cache // prior to calling this function. // // \param dst_pa Physical address of start of range to fill (8B aligned) // \param fillData Value to fill range with (a u32) // \param sizeInU32s Size of range to fill (in u32 units) // \return TRUE normally; FALSE if a time-out occurred // // \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall // // \writesdmae // DMAETimeStamp DMAEFillMemPhys(u32 dst_pa, u32 fillData, u32 sizeInU32s); // \brief Issue a DMA command to fill a physical memory range with a specified value. // // The command is put into the DMAEngine command queue and wait for it to complete. // The range should be flushed or invalidated from the CPU cache // prior to calling this function. // // \param dst_pa Physical address of start of range to fill (8B aligned) // \param fillData Value to fill range with (a u32) // \param sizeInU32s Size of range to fill (in u32 units) // \return TRUE normally; FALSE if a time-out occurred // // \donotcall \fgonly \threadsafe \notinterrupt \notexception \devonly \enddonotcall // // \writesdmae // DMAE_INLINE BOOL DMAEFillMemPhysWait(u32 dst_pa, u32 fillData, u32 sizeInU32s) { return DMAEWaitDone( DMAEFillMemPhys(dst_pa, fillData, sizeInU32s) ); } /// @defgroup DMAEMiscellaneous Miscellaneous /// @ingroup DMAE /// @addtogroup DMAEMiscellaneous /// @{ /// \brief This sets the millisecond timeout value used to determine whether /// the DMA Engine is hung when the app is doing a heavy workload. /// /// \param millisec set milli seconds that DMA Engine regards as hang /// /// \donotcall \fgonly \notthreadsafe \devonly \enddonotcall /// void DMAESetTimeout(u32 millisec); /// \brief This returns the timeout value in milliseconds used to /// determine whether the DMA Engine is hung when the app is doing a heavy workload. /// /// \donotcall \threadsafe \devonly \enddonotcall /// u32 DMAEGetTimeout(void); /// @} #ifdef __cplusplus } #endif #endif // __DMAE_H__