/*******************************************************************************
*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2014 QLogic Corporation
* The contents of this file are subject to the terms of the
* QLogic End User License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the License at
* http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
* QLogic_End_User_Software_License.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* Module Description:
*
*
* History:
* 02/05/07 Alon Elhanani Inception.
******************************************************************************/
/**@file hw_dmae.h
*
* A module encapsulating the DMAE HW block.
*
* Use cases for this module include:
*
* - 'Single-block' DMA operations
* Single-block DMA operations are composed of a single HW
* command that contains a GRC/PCI source, a GRC/PCI
* destination and length. Single-block DMA operations are
* locked from before writing the command to the HW registers,
* until after the DMAE writes the completion word to the
* appropriate location in host memory. Single-block DMA
* operations use a single DMAE channel.
*
* - SGL DMA operations
* SGL DMA operations use two DMAE channels - one called a
* 'loader' and one called an 'executer'. The operation is
* composed of a single HW command called a 'loader' that
* uses the loader channel, and multiple HW commands called
* 'executers' that use the executer channel. The loader
* command is configured so that whenever it is executed,
* it loads and executes the next pending executer command.
* Executer commands are configured so that whenever they
* complete they execute the loader command, except the last
* executer command that simply writes the completion word
* to the appropriate location in host memory.
* SGL DMA operations lock both channels from the time the
* loader first executes, until the last executer completes.
*
* - SGL DMA operations in asynchronous mode (a.k.a post/poll)
* SGL DMA operations in asynchronous mode only lock the
* context for the time required to load the loader command
* to the HW registers (called the 'post' stage). Afterwords
* they return immediately and unlock both channels. Then a
* DMAE user may query the context's state to check if the
* last executer command has already finished (the 'poll' stage).
* The context is locked only for the duration of a single
* query at a time. Note that a DMAE user may not use the
* context until the query returns with a code that indicates
* the context is available.
*/
#ifndef _LM_DMAE_H
#define _LM_DMAE_H
#include "mm.h"
// defines
#define DMAE_SGL_MAX_COMMANDS 5 // max number of commands in a DMAE SGL (just as a limit - can be defined other number)
#define DMAE_GO_VALUE 0x1 // DMAE spec
#define DMAE_SGL_COMPLETION_VAL 0xD0AE // local completion word value (for SGL)
#define DMAE_COMPLETION_VAL 0xD1AE // local completion word value with edianity mode 2 (for regular command)
#define DMAE_COMPLETION_VAL_SWAPPED 0xAED10000 // local completion word value with edianity mode 3
#define DMAE_CMD_SIZE 14 // size of DMAE command structure
#define DMAE_MAX_RW_SIZE_E1 0x0400 // maximun size (in DW) of read/write commands (HW limit) - for (chip id<=5710)
// up to 0xffff actually limit is 64KB-1 so 0x2000 dwords is 32KB
#define DMAE_MAX_RW_SIZE_NEW 0x2000 // maximun size of read/write commands (HW limit) - for E1.5 and above (chip id>5710)
#define DMAE_MAX_READ_SIZE 0x80 // due to a HW issue in E1, E1.5 A0, pci to pci and grc to pci operations are limited to 128 DWORDS
// max value for static allocations
#define DMAE_MAX_RW_SIZE_STATIC max(DMAE_MAX_RW_SIZE_E1,DMAE_MAX_RW_SIZE_NEW)
#define DMAE_MAX_RW_SIZE(pdev) (CHIP_IS_E1(pdev) ? DMAE_MAX_RW_SIZE_E1 : DMAE_MAX_RW_SIZE_NEW)
#define DMAE_STATS_GET_PORT_CMD_IDX(port_num,cmd_idx) DMAE_STATS_PORT_##port_num##_CMD_IDX_##cmd_idx
#define DMAE_STATS_PORT_0_CMD_IDX_0 DMAE_CMD_DRV_0
#define DMAE_STATS_PORT_0_CMD_IDX_1 DMAE_CMD_DRV_1
#define DMAE_STATS_PORT_1_CMD_IDX_0 DMAE_CMD_DRV_2
#define DMAE_STATS_PORT_1_CMD_IDX_1 DMAE_CMD_DRV_3
#define DMAE_WB_ACCESS_FUNCTION_CMD(_idx) DMAE_CMD_DRV_4+(_idx)
#define DMAE_COPY_PCI_PCI_PORT_0_CMD DMAE_CMD_DRV_12
#define DMAE_COPY_PCI_PCI_PORT_1_CMD DMAE_CMD_DRV_13
#define LM_DMAE_INTERMEDIATE_BUFFER_SIZE DMAE_MAX_RW_SIZE_NEW
#define LM_DMAE_NO_HWLOCK 0
typedef enum _lm_dmae_protected_resource_t
{
LM_PROTECTED_RESOURCE_DMAE_STATS = 0,
LM_PROTECTED_RESOURCE_DMAE_TOE,
LM_PROTECTED_RESOURCE_DMAE_DEFAULT,
LM_MAX_PROTECTED_RESOURCE
}lm_dmae_protected_resource_t;
typedef enum _lm_dmae_type_t
{
LM_DMAE_STATS,
LM_DMAE_TOE,
LM_DMAE_DEFAULT,
LM_DMAE_MAX_TYPE
}lm_dmae_type_t;
typedef enum _lm_dmae_address_type_t
{
LM_DMAE_ADDRESS_HOST_VIRT,
LM_DMAE_ADDRESS_HOST_PHYS,
LM_DMAE_ADDRESS_GRC
}lm_dmae_address_type_t;
typedef enum _lm_dmae_mode_t
{
LM_DMAE_MODE_SGL,
LM_DMAE_MODE_SINGLE_BLOCK
}lm_dmae_mode_t;
typedef enum _lm_dmae_locking_policy_type_t
{
LM_DMAE_LOCKING_POLICY_TYPE_NONE,
LM_DMAE_LOCKING_POLICY_TYPE_PER_PF,
LM_DMAE_LOCKING_POLICY_TYPE_INTER_PF
}lm_dmae_locking_policy_type_t;
/**
* An encapsulation of the synchronization method for resource.
* The type of locking policy depends on the synchronization
* requirements for the protected resource (in this design's
* case - the DMAE context)
*
* - No synchronization
* Use this type of policy when there is no contention on the
* protected resource. No locking will take place.
* - per-PF synchronization
* synchronizes access to the protected resource among users in
* the same PF, but not between multiple PFs. Use this type of
* policy when the protected resource is per-PF.
* - inter-PF synchronization
* synchronizes access to the protected resource among multiple
* users that may be running in the contexts of multiple PFs.
* Use this type of policy when the protected resource is
* shared among multiple PFs.
*
* @ingroup LockingPolicy
*/
typedef struct _lm_dmae_locking_policy_t
{
mm_spin_lock_t spinlock; /**< an opaque context for the spinlock that's used by this locking policy*/
u32_t hwlock; /**< the HW lock used by this locking policy*/
}lm_dmae_locking_policy_t;
/**
* A source/target address for a DMA operation.
*
* @ingroup DMAE_Address
*/
typedef struct _lm_dmae_address_t
{
/**The offset of this address (either a virtual address, a
physical address or a GRC offset) */
union {
u32_t grc_offset;
void* host_virt_address;
lm_address_t host_phys_address;
} u;
/**The type of this address*/
lm_dmae_address_type_t type;
}lm_dmae_address_t;
/**
* @ingroup DMAE_Operation
*/
typedef struct _lm_dmae_block_t
{
lm_dmae_address_t source;
lm_dmae_address_t dest;
u16_t length;
}lm_dmae_block_t;
/**
* An aggregation of one or more DMAE channels that are used by
* the driver for the same function with the same configuration.
* A context may be a non-SGL context (in which case it is
* associated with a single DMAE channel) or an SGL context (in
* which case it is associated with two DMAE channels). Every
* context may have one current operation.
*
* @ingroup DMAE_Context
*/
typedef struct _lm_dmae_context_t
{
/**The type of the context (SGL or single-block) */
lm_dmae_mode_t mode;
/** - single-block context: the index of the DMAE channel for
* this context
* - SGL context: the index of the loader DMAE channel for this
* context*/
u8_t main_channel;
/**SGL context: the index of the executer DMAE channel for this
* context.
* This field has no meaning for single-block contexts */
u8_t executer_channel;
u8_t change_endianity;
u32_t next_command_id;
lm_dmae_locking_policy_t* locking_policy;
/**This physical address of the field completion_word */
lm_address_t completion_word_paddr;
/**The memory location where the DMAE writes the completion
* value when an operation is finished on this context.*/
volatile u32_t completion_word;
/**The value that the DMAE writes to completion_word when an
* operation is finished on this context. Endianess note: The
* completion value that's written as part of the command is
* always the same, but the value that's later written to
* memory depends on the endianness mode of the command, so
* this value represents the value that's written by the DMAE
* and not the value that's used by the VBD. */
u32_t completion_value;
/**This physical address of the beginnning of
* intermediate_buffer*/
lm_address_t intermediate_buffer_paddr;
/**An intermediate buffer for DMAE operations that use virtual
* addresses - data is DMA'd to/from this buffer and then
* memcpy'd to/from the virtual address*/
u32_t intermediate_buffer[LM_DMAE_INTERMEDIATE_BUFFER_SIZE];
}lm_dmae_context_t;
/**
* A single logical DMAE transfer, which may be either a
* single-block transfer (in which case it has a single source
* and a single target) or an SGL transfer (in which case it is
* composed of multiple SGEs, each having a single source and a
* single target). An SGL operation may be synchronous or
* asynchronous - executing a synchronous DMAE operation results
* in a wait until the operation completes, while an
* asynchronous operation may be posted to the hardware without
* waiting for its completion.
*
* @ingroup DMAE_Operation
*/
typedef struct _lm_dmae_operation_t
{
/**The type of this operation (SGL or single-block)*/
lm_dmae_mode_t mode;
/**The context of this operation.*/
lm_dmae_context_t* context;
/**TRUE if the source is a block of length DMAE_MAX_RW_SIZE_E1 /
* DMAE_MAX_RW_SIZE_NEW and the destination is larger. In this
* case the source block will be duplicated as many times as
* required to fill the destination block.*/
u8_t b_replicate_source;
u8_t le32_swap;
/**SGL: TRUE if this operation is synchronous. This field has
* no meaning for single-block operations. */
u8_t b_sync;
u32_t command_id;
/**SGL: The loader command for this operation
*SINGLE_BLOCK: The command for this operation*/
struct dmae_cmd main_cmd;
/**The next available entry in blocks[] and executer_cmdp[] */
u8_t next_free_block;
/**The block/blocks of this operation*/
lm_dmae_block_t blocks[DMAE_SGL_MAX_COMMANDS];
/**SGL: The physical address of the beginning of executer_cmd.
* This field has no meaning for single-block operations. */
lm_address_t executer_paddr;
/**SGL: The executer HSI commands for this operation. This
* field has no meaning for single-block operations. */
struct dmae_cmd executer_cmd[DMAE_SGL_MAX_COMMANDS]; //these must be consecutive, so they can't be a part of the blocks[] array.
}lm_dmae_operation_t;
typedef struct _lm_dmae_context_info_t
{
lm_dmae_context_t* context;
lm_dmae_locking_policy_t locking_policy;
}lm_dmae_context_info_t ;
typedef struct _lm_dmae_info_t
{
lm_dmae_context_info_t ctx_arr[LM_DMAE_MAX_TYPE];
}lm_dmae_info_t;
//------------------ Locking Policy ------------------//
/**lm_dmae_locking_policy_create
* Create a locking policy
*
* @param resource The ID of the protected resource. This ID is
* used to determine which synchronization
* objects will be used by the policy.
* @param type the type of this locking policy
* @param policy the policy to initialize.
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure value on failure.
*/
lm_status_t lm_dmae_locking_policy_create( struct _lm_device_t* pdev,
IN const u32_t resource,
IN const lm_dmae_locking_policy_type_t type,
OUT lm_dmae_locking_policy_t* policy);
/**lm_dmae_locking_policy_lock
* Use a locking policy to lock a resource, acquiring whatever
* spinlock or hardware lock required.
*
* @param locking_policy the policy to use
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure code on failure.
*/
#ifdef _VBD_
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_at(locking_policy->spinlock.irql, __drv_savesIRQL)
__drv_setsIRQL(DISPATCH_LEVEL)
#endif
lm_status_t lm_dmae_locking_policy_lock(struct _lm_device_t* pdev, lm_dmae_locking_policy_t* locking_policy);
/**lm_dmae_locking_policy_unlock
* Use a locking policy to unlock a resource, releasing
* whatever spinlock or hardware lock required.
*
* @param locking_policy the policy to use
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure code on failure
*/
#ifdef _VBD_
#if defined(NTDDI_WIN8)
_IRQL_requires_(DISPATCH_LEVEL)
__drv_at(locking_policy->spinlock.irql, __drv_restoresIRQL )
#endif
#endif
lm_status_t lm_dmae_locking_policy_unlock(struct _lm_device_t* pdev, lm_dmae_locking_policy_t* locking_policy);
//------------------ DMAE Context ------------------//
/**lm_dmae_context_create
* Create a non-SGL DMA context, using the given policy for
* synchronization.
*
* @param channel_idx the DMAE channel index that is used by
* this context
* @param locking_policy the synchronization policy used by this
* context
* @param change_endianity
*
* @return lm_dmae_context_t* a single-block DMAE context
* configured according to the supplied
* parameters.
*/
lm_dmae_context_t* lm_dmae_context_create( struct _lm_device_t* pdev,
IN const u8_t channel_idx,
lm_dmae_locking_policy_t* locking_policy,
IN const u8_t change_endianity);
/**lm_dmae_context_create_sgl
* Create an SGL DMA context, using the given policy for
* synchronization.
*
* @param loader_channel_idx the 'loader' DMAE channel index
* that is used by this context
* @param executer_channel_idx the 'executer' DMAE channel index
* that is used by this context
* @param locking_policy the synchronization policy used by this
* context
* @param change_endianity
*
* @return lm_status_t an SGL DMAE context configured according
* to the supplied parameters.
*/
lm_dmae_context_t* lm_dmae_context_create_sgl( struct _lm_device_t* pdev,
IN const u8_t loader_channel_idx,
IN const u8_t executer_channel_idx,
lm_dmae_locking_policy_t* locking_policy,
IN const u8_t change_endianity);
/**lm_dmae_context_reset
* Bring a DMAE context to a known-good state. This function
* must be used on an acquired context. It should be used if for
* some reason the context is left in an invalid state (e.g an
* error occured during a DMAE transaction using this context).
*
* @param context the context to reset.
*
* @return lm_status LM_STATUS_SUCCESS on success, some other
* failure code on failure.
*/
lm_status_t lm_dmae_context_reset(lm_dmae_context_t *context);
/**lm_dmae_context_acquire
* Acquire the context, so that multiple DMAE operations may be
* executed on it without locking the context once for every
* operation. Only after calling this function can
* lm_dmae_context_execute_unsafe be used.
*
* @param context the context to acquire
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure value on failure
*/
#ifdef _VBD_
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_at(context->locking_policy->spinlock.irql, __drv_savesIRQL)
__drv_setsIRQL(DISPATCH_LEVEL)
#endif
lm_status_t lm_dmae_context_acquire(struct _lm_device_t* pdev, lm_dmae_context_t *context);
/**lm_dmae_context_release
* Release a context that was acquired with
* lm_dmae_context_release. After calling this function,
* lm_dmae_context_execute_unsafe may not be used on the
* context.
*
* @param context the context to release
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure value on failure
*/
#ifdef _VBD_
#if defined(NTDDI_WIN8)
_IRQL_requires_(DISPATCH_LEVEL)
__drv_at(context->locking_policy->spinlock.irql, __drv_restoresIRQL )
#endif
#endif
lm_status_t lm_dmae_context_release(struct _lm_device_t* pdev, lm_dmae_context_t *context);
/**lm_dmae_context_execute
* Execute a command in a context, using the context's locking
* policy
*
* @param context the context to use
* @param operation the operation to execute
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_PENDING if executing an asynchronous
* operation, LM_STATUS_BUSY if another asyncronous
* operation is in progress or some other failure code
* on failure.
*/
lm_status_t lm_dmae_context_execute(struct _lm_device_t* pdev, lm_dmae_context_t *context, lm_dmae_operation_t *operation);
/**lm_dmae_context_execute_unsafe
* Execute a command in a context, without locking. This
* function must be called between calls to
* lm_dmae_context_acquire and lm_dmae_context_release.
*
* @param context the context to use
* @param operation the operation to execute
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_PENDING if executing an asynchronous
* operation, LM_STATUS_BUSY if another asyncronous
* operation is in progress or some other failure code
* on failure.
*/
lm_status_t lm_dmae_context_execute_unsafe(struct _lm_device_t* pdev, lm_dmae_context_t *context, lm_dmae_operation_t *operation);
//------------------ DMAE Operation ------------------//
/**lm_dmae_operation_create
* Create a single-block DMAE operation and the DMAE command
* that it uses.
*
* @param source the source for this DMAE operation
* @param dest the destination for this DMAE operation
* @param length the length of the block to transfer
* @param replicate_source TRUE if the source is a block of
* length DMAE_MAX_RW_SIZE_E1/DMAE_MAX_RW_SIZE_NEW
* and the destination is larger. In
* this case the source block will be
* duplicated as many times as
* required to fill the destination
* block.
* @param le32_swap should byte-swapping occur before executing
* the operation.
* @param context the DMAE context for this operation
* @param operation the operation to initialize. If this function
* returns LM_STATUS_SUCCESS, the operation
* pointed to by this parameter is initialized
* to a single-block DMAE operation configured
* according to the supplied parameters.
*
* @return lm_status_t LM_STATUS_SUCCESS on success, some other
* failure value on failure.
*/
lm_status_t lm_dmae_operation_create( struct _lm_device_t* pdev,
IN const lm_dmae_address_t source,
IN const lm_dmae_address_t dest,
IN const u16_t length,
IN const u8_t replicate_source,
IN const u8_t le32_swap,
IN lm_dmae_context_t* context,
OUT lm_dmae_operation_t* operation);
/**lm_dmae_operation_create_sgl
* Create an SGL DMAE operation and the DMAE commands that it
* uses.
*
* @param b_sync TRUE if this operation is synchronous, FALSE
* otherwise.
* @param context the DMAE context for this operation
*
* @return lm_dmae_operation_t* An empty SGL DMAE operation
* based on the supplied parameters. Use
* lm_dmae_operation_add_sge to add SGEs to this
* operation. On failure the function returns NULL.
*/
lm_dmae_operation_t* lm_dmae_operation_create_sgl( struct _lm_device_t* pdev,
IN const u8_t b_sync,
IN lm_dmae_context_t* context);
/**lm_dmae_operation_add_sge
* Add an SGE to an SGL operation.
*
* @param operation the operation to add an SGE to.
* @param source the source for this SGE
* @param dest the destination for this SGE
* @param length the length of the block to transfer
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_INVALID_PARAMETER if the supplied operation
* is not an SGL operation, some other failure code on
* failure.
*/
lm_status_t lm_dmae_operation_add_sge( struct _lm_device_t* pdev,
lm_dmae_operation_t* operation,
IN const lm_dmae_address_t source,
IN const lm_dmae_address_t dest,
IN const u16_t length);
/**lm_dmae_operation_clear_all_sges
* Remove all SGEs from an SGL DMAE command.
*
* @param operation the operation to clear
*
*/
void lm_dmae_operation_clear_all_sges(lm_dmae_operation_t* operation);
/**lm_dmae_operation_is_complete
* check if an operation has finished
*
* @param operation the operation to check
*
* @return u8_t TRUE if the given operation is complete
*/
u8_t lm_dmae_operation_is_complete(IN lm_dmae_operation_t* operation);
//------------------ DMAE Address ------------------//
/**lm_dmae_address_native_offset
* Get a u64_t representation of the address's value which can
* be used as a source/destination address by DMAE hardware (i.e
* byte offset for host memory address, DWORD offset for GRC
* offsets)
*
* @param address the address to use
*
* @return u64_t see description
*/
u64_t lm_dmae_address_native_offset(IN const lm_dmae_address_t* address);
/**lm_dmae_address
* create a DMAE address
*
* @param offset the offset of the address (either
* physical/virtual address or GRC offset)
* @param type the type of the address
*
* @return lm_dmae_address_t a DMAE address initialized
* according to the supplied parameters
*/
lm_dmae_address_t lm_dmae_address(IN const u64_t offset, IN const lm_dmae_address_type_t type);
//------------------ DMAE users ------------------//
/**lm_dmae_get
* Return the context info for a given DMAE user.
*
* @param pdev the device to use
* @param type the dmae user
*
* @return lm_dmae_context_info_t* the context info for the given user, or NULL on error.
*/
lm_dmae_context_info_t* lm_dmae_get(struct _lm_device_t* pdev, IN const lm_dmae_type_t type);
/**lm_dmae_reg_wr
* Write a block of data from host memory (given as a virtual
* address) to GRC.
*
* @param pdev the device to use
* @param context the DMAE context to use
* @param source_vaddr the beginning of the source memory block
* @param dest_offset the GRC offset of the destination block
* @param length the length (in DWORDS) of the block
* @param b_replicate_source TRUE if the source is a block of
* length
* DMAE_MAX_RW_SIZE_E1/DMAE_MAX_RW_SIZE_NEW
* and the destination is larger. In
* this case the source block will be
* duplicated as many times as
* required to fill the destination
* block.
* @param le32_swap if TRUE, change all DWORDS in the source
* block to little-endian representation before
* executing the operation.
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_TIMEOUT if the operation did not finish in
* reasonable time, some other failure value on failure.
*/
lm_status_t lm_dmae_reg_wr(struct _lm_device_t* pdev, lm_dmae_context_t* context, void* source_vaddr, u32_t dest_offset, u16_t length, u8_t b_replicate_source, u8_t le32_swap);
/**lm_dmae_reg_wr_phys
* Write a block of data from host memory (given as a physical
* address) to GRC.
*
* @param pdev the device to use
* @param context the DMAE context to use
* @param source_paddr the beginning of the source memory block
* @param dest_offset the GRC offset of the destination block
* @param length the length (in DWORDS) of the block
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_TIMEOUT if the operation did not finish in
* reasonable time, some other failure value on failure.
*/
lm_status_t lm_dmae_reg_wr_phys(struct _lm_device_t* pdev, lm_dmae_context_t* context, lm_address_t source_paddr, u32_t dest_offset, u16_t length);
/**lm_dmae_reg_rd
* Read a block from GRC to host memory(given as a virtual
* address).
*
*
* @param pdev the device to use
* @param context the DMAE context to use
* @param source_offset the GRC offset of the source block
* @param dest_vaddr the beginning of the destination memory
* block
* @param length the length (in DWORDS) of the block
* @param le32_swap if TRUE, change all DWORDS in data to
* little-endian after it's read from GRC.
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_TIMEOUT if the operation did not finish in
* reasonable time, some other failure value on failure.
*/
lm_status_t lm_dmae_reg_rd(struct _lm_device_t* pdev, lm_dmae_context_t* context, u32_t source_offset, void* dest_vaddr, u16_t length, u8_t le32_swap);
/**lm_dmae_copy_phys_buffer_unsafe
* Copy a block from host memory to host memory, both addresses
* given as physical addresses.
*
*
* @param pdev the device to use
* @param context the DMAE context to use
* @param source_paddr the beginning of the source memory block
* @param dest_paddr the beginning of the destination memory
* block
* @param length the length (in DWORDS) of the block
*
* @return lm_status_t LM_STATUS_SUCCESS on success,
* LM_STATUS_TIMEOUT if the operation did not finish in
* reasonable time, some other failure value on failure.
*/
lm_status_t lm_dmae_copy_phys_buffer_unsafe(struct _lm_device_t* pdev, lm_dmae_context_t* context, lm_address_t source_paddr, lm_address_t dest_paddr, u16_t length);
#endif// _LM_DMAE_H