412 lines
13 KiB
C
Executable File
412 lines
13 KiB
C
Executable File
/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved.
|
|
*
|
|
* NVIDIA Corporation and its licensors retain all intellectual property
|
|
* and proprietary rights in and to this software, related documentation
|
|
* and any modifications thereto. Any use, reproduction, disclosure or
|
|
* distribution of this software and related documentation without an
|
|
* express license agreement from NVIDIA Corporation is strictly prohibited.
|
|
*/
|
|
|
|
/** @File: GFRmRDMA.h
|
|
GFSDK Read DMA memmory manager.
|
|
|
|
*/
|
|
|
|
#ifndef __GFRMRDMA_H__
|
|
#define __GFRMRDMA_H__
|
|
|
|
#include "GF.h"
|
|
|
|
/** @addtogroup groupRDMA RDMA ReadDMA API
|
|
<ul>
|
|
<li> @ref pageRDMAAppNotes
|
|
</ul>
|
|
*/
|
|
|
|
/*@{*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
|
|
/** eGFRmRDMAClientID: Enumeration of client id's. SC15 has 4
|
|
RDMA (Read DMA) FIFO's. Modules specified below can be
|
|
attached to the RDMA FIFO's. See @
|
|
*/
|
|
typedef enum
|
|
{
|
|
RDMA_CLID_CPU = 0,
|
|
RDMA_CLID_DSP,
|
|
RDMA_CLID_I2S,
|
|
RDMA_CLID_SD,
|
|
RDMA_CLID_MPEGE,
|
|
RDMA_CLID_JPEGE,
|
|
RDMA_CLID_EPP,
|
|
RDMA_CLID_VI,
|
|
RDMA_CLIDS
|
|
} eGFRmRDMAClientID;
|
|
|
|
/** RDMA buffer header.
|
|
|
|
For non-rectangular (or linear) reads
|
|
RDMA expects a header in the memory. The header formart is as specified
|
|
below. GFRmRDMAReadHeader function returns the header in this format.
|
|
|
|
@See GFRmRDMAReadHeader()
|
|
*/
|
|
|
|
typedef struct _RDMA_BUF_HEADER
|
|
{
|
|
NvU32 bufferSize;
|
|
NvU32 raiseVector;
|
|
NvU32 channel;
|
|
NvU8 raiseEnable;
|
|
NvU8 frameStart;
|
|
NvU8 frameEnd;
|
|
NvU8 largeHdr;
|
|
NvU32 extHeader;
|
|
|
|
} RDMA_BUFFER_HEADER, *pRDMA_BUFFER_HEADER;
|
|
|
|
|
|
/* RDMA flags */
|
|
|
|
/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit:
|
|
No byte swap.
|
|
*/
|
|
#define GF_RDMA_FLAGS_SWAP_NONE 0x00000000
|
|
|
|
/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit:
|
|
Swap bytes in a word. example: 0xaabbccdd to 0xbbaaddcc.
|
|
*/
|
|
#define GF_RDMA_FLAGS_SWAP_BYTE_IN_WORD 0x00000001
|
|
|
|
/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit:
|
|
Swap bytes in dword: 0xaabbccdd to 0xddccbbaa.
|
|
*/
|
|
#define GF_RDMA_FLAGS_SWAP_BYTE_IN_DWORD 0x00000002
|
|
|
|
/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit:
|
|
Swap word in dword example: 0xaabbccdd to 0xccddaabb.
|
|
*/
|
|
#define GF_RDMA_FLAGS_SWAP_WORD_IN_DWORD 0x00000003
|
|
|
|
/** RDMA_NONRECT::flags and RDMA_RECT::flags bitmask:
|
|
mask out byte swap options GF_RDMA_FLAGS_SWAP_*.
|
|
*/
|
|
#define GF_RDMA_FLAGS_SWAP_MASK 0x00000003
|
|
|
|
/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit:
|
|
Tells the RDMA engine to output header. Will output a header into the data stream,
|
|
which has to be read with GFRmRDMAReadHeader() before calling GFRmRDMARead().
|
|
This flag is relevant only in non-rectangular reads.
|
|
*/
|
|
#define GF_RDMA_FLAGS_STR_HEADER 0x00010000
|
|
|
|
/** RDMA_RECT
|
|
Setup information for the RDMA.
|
|
*/
|
|
typedef struct _RDMA_RECT
|
|
{
|
|
/** physical addess of the buffer in the SC15 Memory view. 32-bit alignment
|
|
* required. */
|
|
NvU32 baseOffset;
|
|
|
|
/** client id. See @eGFRmRDMAClientID */
|
|
eGFRmRDMAClientID clid;
|
|
|
|
/** buffers/stride/width/lines of the rectangular buffer.
|
|
|
|
Need to comply with the following constraints provided
|
|
by the hardware
|
|
- if width is not a multiple of 4 bytes (one word):
|
|
- stride equals width, stride should be the exact stride in bytes (eg. line_stride[1:0] not equal to 0)
|
|
- if stride is bigger than width, stride should be rounded down to the nearest word
|
|
(eg. line_stride[1:0] should be zero)
|
|
|
|
For example: width = 42 bytes, stride = 82 -> stride should be programmed to 80
|
|
width = 42 bytes, stride = 42 -> stride should be programmed to 42
|
|
*/
|
|
NvU32 buffers;
|
|
NvU32 stride;
|
|
NvU32 width;
|
|
NvU32 lines;
|
|
|
|
/* use the RDMA flags defined above as GF_RDMS_FLAGS_* */
|
|
NvU32 flags; //!< Flagbits, see GF_RDMA_FLAGS_*
|
|
|
|
/* Timeout in msec. If <=0, then no timeout */
|
|
NvU32 timeout;
|
|
|
|
} RDMA_RECT, *pRDMA_RECT;
|
|
|
|
/** RDMA_NONRECT
|
|
|
|
Setup structure for non-rectangular reads.
|
|
|
|
*/
|
|
typedef struct _RDMA_NONRECT
|
|
{
|
|
/** Physical addess of the buffer in the GPU address space. Needs to be
|
|
* 32-bit aligned. */
|
|
NvU32 baseOffset;
|
|
|
|
/** client id. See @eGFRmRDMAClientID */
|
|
eGFRmRDMAClientID clid;
|
|
|
|
NvU32 buffers;
|
|
NvU32 stride;
|
|
|
|
/* use the RDMA flags defined above as GF_RDMS_FLAGS_* */
|
|
NvU32 flags; //!< Flagbits, see GF_RDMA_FLAGS_*
|
|
|
|
/* Timeout in msec. If =0, then no timeout */
|
|
NvU32 timeout;
|
|
|
|
} RDMA_NONRECT, *pRDMA_NONRECT;
|
|
|
|
|
|
/** There are four read dma channels, the RM manages the allocation/
|
|
freeing of these channels. This function allocates a channel.
|
|
|
|
@param RmHandle Handle to the Rm allocated via call to GFRmOpen.
|
|
@param DmaHandle Pointer to an allocated handle.
|
|
|
|
@retval GF_SUCCESS if a RDMA channel is available, and returns
|
|
RDMA handle on allocation.
|
|
|
|
The release function will return GF_ERROR
|
|
if the read dma is already released.
|
|
*/
|
|
|
|
GF_RETTYPE
|
|
GFRmRDMAAlloc(GFRmHandle RmHandle, GFRmRdmaHandle *DmaHandle);
|
|
|
|
/** There are four read dma channels, the RM manages the allocation/
|
|
freeing of these channels. This function frees an allocated
|
|
channel.
|
|
|
|
@param hRm Handle to the Rm allocated via call to GFRmOpen.
|
|
@param phDma Pointer to the DMA handle to be released.
|
|
*/
|
|
void
|
|
GFRmRDMARelease(GFRmHandle hRm, GFRmRdmaHandle *phDma);
|
|
|
|
/** Setup non-rectangular RDMA.
|
|
|
|
When the flag GF_RDMA_FLAGS_STR_HEADER is set, buffer header is written to the
|
|
memory by the RDMA client. So, when the cpu reads the data, buffer
|
|
header comes first and then the data. Buffer header has the information
|
|
of buffer, like its size etc.
|
|
|
|
|
|
So, an example sequence would be
|
|
- Call setup with GF_RDMA_FLAGS_STR_HEADER flag set.
|
|
- Read header with the GFRmRDMAReadHeader(...)
|
|
- Read buffer size of data with GFRmRDMARead() funtion.
|
|
Buffer size is in the buffer header.
|
|
|
|
If this flag is not set, then the there is no buffer header.
|
|
In this case it is assumed that the the size of the buffer is prefixed
|
|
and known to the module API writers.
|
|
|
|
So, an example sequence would be
|
|
- Call setup GF_RDMA_FLAGS_STR_HEADER flag not set.
|
|
- Read buffer size of data with GFRmRDMARead() funtion.
|
|
Buffer size is known to the callers.
|
|
|
|
baseOffset of pReq structure needs to be 32-bit aligned.
|
|
|
|
@param DmaHandle Handle returned by @GFRmRDMAAlloc function.
|
|
@param pReq Populated RDMA req structure. See @RDMA_NONRECT
|
|
*/
|
|
|
|
GF_RETTYPE
|
|
GFRmRDMASetupNONRect(GFRmRdmaHandle DmaHandle, pRDMA_NONRECT pReq);
|
|
|
|
/** Setup RDMA for rectangular read.
|
|
|
|
Requirement:
|
|
baseOffset of pReq structure needs to be 32-bit aligned.
|
|
|
|
@param DmaHandle Handle returned by @GFRmRDMAAlloc function.
|
|
@param pReq Populated RDMA req structure. See @RDMA_RECT
|
|
*/
|
|
GF_RETTYPE
|
|
GFRmRDMASetupRect(GFRmRdmaHandle DmaHandle, pRDMA_RECT pReq);
|
|
|
|
/** Reads the RDMA FIFO status register and returns the
|
|
available number of FIFO slots. A slot is 32-bit.
|
|
|
|
@param DmaHandle Handle returned by @GFRmRDMAAlloc function.
|
|
*/
|
|
NvU32 GFRmRDMAFIFOAvailIn32Bits(GFRmRdmaHandle DmaHandle);
|
|
|
|
/** Reads memory from SC15 internal/external
|
|
memory to the system memory pointed by the dstAddr. Need
|
|
to pass the same rectangular attributes passed, when the
|
|
RDMA is setup.
|
|
|
|
@param DmaHandle Handle returned by @GFRmRDMAAlloc function.
|
|
@param dstAddr aligned or non-aligned dest pointer. Aligned
|
|
pointer results in faster reads.
|
|
@param width Width in bytes to read.
|
|
@param height Height of the rectangular region.
|
|
|
|
@retval Returns GF_SUCCESS or GF_ERROR.
|
|
*/
|
|
|
|
GF_RETTYPE
|
|
GFRmRDMARectRead(GFRmRdmaHandle DmaHandle, void *dstAddr, NvU32 width, NvU32 height);
|
|
|
|
|
|
/** Reads memory from SC15 internal/external
|
|
memory to the system memory pointed by the dstAddr.
|
|
|
|
@param DmaHandle Handle returned by @GFRmRDMAAlloc function.
|
|
@param dstAddr aligned or non-aligned dest pointer. Aligned
|
|
pointer results in faster reads.
|
|
@param sizeInBytes Number of bytes to read.
|
|
|
|
@retval Returns GF_SUCCESS or GF_ERROR.
|
|
*/
|
|
|
|
GF_RETTYPE
|
|
GFRmRDMARead(GFRmRdmaHandle DmaHandle, void *dstAddr, NvU32 sizeInBytes);
|
|
|
|
/** Reads buffer header. Once this info is read
|
|
API's will know how much data to read or expect.
|
|
|
|
@param DmaHandle Handle returned by @GFRmRDMAAlloc function.
|
|
@param header Pointer to RDMA header structure. See @RDMA_BUFFER_HEADER
|
|
*/
|
|
GF_RETTYPE
|
|
GFRmRDMAReadHeader(GFRmRdmaHandle DmaHandle, pRDMA_BUFFER_HEADER header);
|
|
|
|
|
|
/** Cleanup the RDMA FIFO, by reading out any extra DOWRDS
|
|
GFRmRDMARead might not have read.
|
|
|
|
In general this function need not be used.
|
|
*/
|
|
|
|
GF_RETTYPE
|
|
GFRmRDMACleanup(GFRmRdmaHandle DmaHandle);
|
|
|
|
|
|
/** Gets the actual RDMA channel number from the DMA handle. This is
|
|
usefull for DSP development. Host code allocates the DMAHandle
|
|
gets the DMA number from that and creates the DMA handle on the
|
|
DSP side using GFXRmRDMAAlloc function. GFXRmRDMAAlloc needs to
|
|
know what DMA channel to use.
|
|
|
|
@param DmaHandle RDMA handle.
|
|
@param dmaNumber RDMA channel number used the handle.
|
|
|
|
*/
|
|
|
|
void
|
|
GFRmRDMAGetPortNumber(GFRmRdmaHandle DmaHandle, NvU32 *portNumber);
|
|
|
|
#if NVCPU_IS_XTENSA
|
|
|
|
// In XRM, it is expected that the dma handle is allocated on
|
|
// the Host side, and just the dma number is passed into code
|
|
// running on the Xtensa. These functions will setup a
|
|
// DMA handle that can used in the XRM.
|
|
|
|
|
|
GF_RETTYPE
|
|
GFXRmRDMAAlloc(NvU32 dmaNumber, GFRmRdmaHandle *DmaHandle);
|
|
|
|
|
|
GF_RETTYPE
|
|
GFXRmRDMARelease(GFRmRdmaHandle *DmaHandle);
|
|
|
|
#endif // NVCPU_IS_XTENSA
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
/*@}*/
|
|
|
|
/** @page pageRDMAAppNotes RDMA Application Notes
|
|
|
|
General information about RDMA - RDMA is read DMA hw block. Unlike
|
|
traditional DMA, sw reads the data from the FIFO to system memory. This is
|
|
becasuse SC15 cannot bus master and write directly to the system memory.
|
|
RDMA will be faster becasue the data is buffered by the HOST1x Block and sw
|
|
reads back data in a tight loop.
|
|
|
|
SC15 RDMA supports 2 modes - Linear(AKA NON-Rect) and Rect mode.
|
|
In both modes the sequence of programming same - setup and then read the data.
|
|
|
|
RDMA setup is 2 step process.
|
|
- RDMA need to know which client will trigger the RDMA. It also need to other
|
|
parameters like which varies for linear and RECT modes.
|
|
In rect reads software has to setup the stride/width/number of lines.
|
|
This information is needed to describe a buffer. In case of non-rect
|
|
read a buffer header is expected, which describes the buffer. In both
|
|
cases one need to specify the number of buffers.
|
|
|
|
- Client module also need to be setup, as it notifies the RDMA hw block when
|
|
the data is ready. This step is not needed for CPU triggered case, as the
|
|
data is already available in the memory.
|
|
|
|
Sample program sequence:
|
|
|
|
Setup RDMA
|
|
Setup Client side register (example - vi, SD etc...). Not needed when
|
|
setup for CLID CPU.
|
|
|
|
wait till the data is available ()
|
|
{
|
|
Read the data(..)
|
|
}
|
|
|
|
Amount of data to read is either known a-priori (RECT mode) or read from
|
|
the header (linear mode).
|
|
|
|
|
|
As described ealier RDMA supports 2 modes
|
|
|
|
Linear RDMA - RDMA expects a header in the memory right before the data, when
|
|
it is triggered. That header describes the length and the attributes of the
|
|
buffer.
|
|
|
|
Depending on how the RDMA is setup, buffer header will be/will not be
|
|
(i.e RDMA_BUFFER_HEADER struct) readout. see #GF_RDMA_FLAGS_STR_HEADER
|
|
|
|
When the header is returned the usage looks like
|
|
|
|
RDMA_BUFFER_HEADER header;
|
|
GFRmRDMAReadHeader(...,&header);
|
|
While (header->bufferSize)
|
|
{
|
|
...
|
|
GFRmReadRDMA(...)
|
|
}
|
|
|
|
In this mode, it is important is to note that RDMA expect the buffer header
|
|
in the memory. So, this is not good for CPU triggerd case, as in that case
|
|
CPU should somehow write the buffer header to read the data already present
|
|
in the embedded memory.
|
|
|
|
Rect RDMA - In this mode, there is no concept of buffer header. Exact size
|
|
should be programmed in the RDMA registers when the Setup is done. So, sw
|
|
should know how much data to pull out. Requests for data more than available
|
|
will result in timeout errors.
|
|
|
|
A guideline: if an engine already generated the buffer for you, then use
|
|
non-rectangular read. Otherwise, use rect read.
|
|
|
|
*/
|
|
|
|
#endif /* __GFRMRDMA_H__ */
|