#ifndef __BESTCOMM_API_H
#define __BESTCOMM_API_H 1
/******************************************************************************
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
******************************************************************************/
/*!
* \file bestcomm_api.h
*
* Bestcomm_api.h is the only header necessary for inclusion by user
* code. The include path the C compiler searches to find .h files
* should contain bestcomm/capi and one of bestcomm/code_dma/image_*.
* This second entry selects which set of BestComm tasks will be used.
* Of course the appropriate files in image_* must also be compiled and
* linked.
*/
#include "include/ppctypes.h"
#include "include/mgt5200/sdma.h"
#include "task_api/tasksetup_bdtable.h"
#include "task_api/bestcomm_cntrl.h"
#include "task_api/bestcomm_api_mem.h"
/*!
* \brief TaskSetup() debugging
*
* Define this macro as follows for debugging printf()s to see
* what the API receives and sets from the TaskSetupParamSet_t
* struct. Implemented in capi/task_api/tasksetup_general.h.
*
* \verbatim
* >0 : print basic debug messages
* >=10: also print C-API interface variables
* >=20: also print task API interface variables
* else: do nothing
* \endverbatim
*/
#define DEBUG_BESTCOMM_API 0
/*!
* \brief Maximum number of tasks in the system.
* This number is hardware-dependent and not user configuration.
*/
#define MAX_TASKS 16
/*
* This may need to be removed in certain implementations.
*/
#ifndef NULL
# define NULL ((void *)0)
#endif /* NULL */
typedef sint8 TaskId;
typedef sint32 BDIdx;
/*
* Special "task IDs" for interrupt handling API functions
*/
/*! \brief Debug interrupt "task ID" */
#define DEBUG_INTR_ID SDMA_INT_BIT_DBG
/*! \brief TEA interrupt "task ID" */
#define TEA_INTR_ID SDMA_INT_BIT_TEA
/*! \brief Task start autostart enable */
#define TASK_AUTOSTART_ENABLE 1
/*! \brief Task start autostart disable */
#define TASK_AUTOSTART_DISABLE 0
/*! \brief Task start interrupt enable */
#define TASK_INTERRUPT_ENABLE 1
/*! \brief Task start interrupt disable */
#define TASK_INTERRUPT_DISABLE 0
/*
* Buffer descriptor flags to pass to TaskBDAssign().
*/
/*! \brief Transmit frame done */
#define TASK_BD_TFD (1 << SDMA_DRD_BIT_TFD)
/*! \brief Interrupt on frame done */
#define TASK_BD_INT (1 << SDMA_DRD_BIT_INT)
/*!
* \brief Data transfer size
*/
typedef enum {
SZ_FLEX = 3, /*!< invalid for TaskSetupParamSet_t */
SZ_UINT8 = 1, /*!< 1-byte */
SZ_UINT16 = 2, /*!< 2-byte */
SZ_UINT32 = 4 /*!< 4-byte */
} Sz_t;
/*!
* \brief API error codes
*/
typedef enum {
TASK_ERR_NO_ERR = -1, /*!< No error */
TASK_ERR_NO_INTR = TASK_ERR_NO_ERR,
/*!< No interrupt */
TASK_ERR_INVALID_ARG = -2, /*!< Invalid function argument */
TASK_ERR_BD_RING_FULL = -3, /*!< Buffer descriptor ring full*/
TASK_ERR_API_ALREADY_INITIALIZED
= -4, /*!< API has already been initialized */
TASK_ERR_SIZE_TOO_LARGE = -5, /*!< Buffer descriptor cannot support size parameter */
TASK_ERR_BD_RING_EMPTY = -6, /*!< Buffer descriptor ring is empty*/
TASK_ERR_BD_BUSY = -7, /*!< The buffer descriptor is in use
by the BestComm */
TASK_ERR_TASK_RUNNING = -8 /*!< The task is running. */
} TaskErr_t;
/*!
* \brief BestComm initiators
*
* These are assigned by TaskSetup().
*/
typedef enum {
INITIATOR_ALWAYS = 0,
INITIATOR_SCTMR_0 = 1,
INITIATOR_SCTMR_1 = 2,
INITIATOR_FEC_RX = 3,
INITIATOR_FEC_TX = 4,
INITIATOR_ATA_RX = 5,
INITIATOR_ATA_TX = 6,
INITIATOR_SCPCI_RX = 7,
INITIATOR_SCPCI_TX = 8,
INITIATOR_PSC3_RX = 9,
INITIATOR_PSC3_TX = 10,
INITIATOR_PSC2_RX = 11,
INITIATOR_PSC2_TX = 12,
INITIATOR_PSC1_RX = 13,
INITIATOR_PSC1_TX = 14,
INITIATOR_SCTMR_2 = 15,
INITIATOR_SCLPC = 16,
INITIATOR_PSC5_RX = 17,
INITIATOR_PSC5_TX = 18,
INITIATOR_PSC4_RX = 19,
INITIATOR_PSC4_TX = 20,
INITIATOR_I2C2_RX = 21,
INITIATOR_I2C2_TX = 22,
INITIATOR_I2C1_RX = 23,
INITIATOR_I2C1_TX = 24,
INITIATOR_PSC6_RX = 25,
INITIATOR_PSC6_TX = 26,
INITIATOR_IRDA_RX = 25,
INITIATOR_IRDA_TX = 26,
INITIATOR_SCTMR_3 = 27,
INITIATOR_SCTMR_4 = 28,
INITIATOR_SCTMR_5 = 29,
INITIATOR_SCTMR_6 = 30,
INITIATOR_SCTMR_7 = 31
} MPC5200Initiator_t;
/*!
* \brief Parameters for TaskSetup()
*
* All parameters can be hard-coded by the task API. Hard-coded values
* will be changed in the struct passed to TaskSetup() for the user to
* examine later.
*/
typedef struct {
uint32 NumBD; /*!< Number of buffer descriptors */
union {
uint32 MaxBuf; /*!< Maximum buffer size */
uint32 NumBytes; /*!< Number of bytes to transfer */
} Size; /*!< Buffer size union for BD and non-BD tasks */
MPC5200Initiator_t
Initiator; /*!< BestComm initiator (ignored if hard-wired) */
uint32 StartAddrSrc; /*!< Address of the DMA source (e.g. a FIFO) */
sint16 IncrSrc; /*!< Amount to increment source pointer */
Sz_t SzSrc; /*!< Size of source data access */
uint32 StartAddrDst; /*!< Address of the DMA destination (e.g. a FIFO) */
sint16 IncrDst; /*!< Amount to increment data pointer */
Sz_t SzDst; /*!< Size of destination data access */
} TaskSetupParamSet_t;
/*!
* \brief Parameters for TaskDebug()
*
* TaskDebug() and the contents of this data structure are yet to be
* determined.
*/
typedef struct {
int dummy; /* Some compilers don't like empty struct typedefs */
} TaskDebugParamSet_t;
/*!
* \brief Generic buffer descriptor.
*
* It is generally used as a pointer which should be cast to one of the
* other BD types based on the number of buffers per descriptor.
*/
typedef struct {
uint32 Status; /*!< Status and length bits */
} TaskBD_t;
/*!
* \brief Single buffer descriptor.
*/
typedef struct {
uint32 Status; /*!< Status and length bits */
uint32 DataPtr[1]; /*!< Pointer to data buffer */
} TaskBD1_t;
/*!
* \brief Dual buffer descriptor.
*/
typedef struct {
uint32 Status; /*!< Status and length bits */
uint32 DataPtr[2]; /*!< Pointer to data buffers */
} TaskBD2_t;
/***************************
* Start of API Prototypes
***************************/
#include "bestcomm_priv.h"
#include "dma_image.capi.h"
/*!
* \brief Initialize a single task.
* \param TaskName Type of task to initialize. E.g. PCI transmit,
* ethernet receive, general purpose dual-pointer.
* Values expected can be found in the TaskName_t
* enum defined in dma_image.capi.h.
* \param TaskSetupParams Task-specific parameters. The user must fill out
* the pertinent parts of a TaskSetupParamSet_t
* data structure.
* \returns TaskId task identification token which is a required
* parameter for most other API functions.
*
* This function returns a task identification token which is a required
* parameter for most other API functions.
*
* Certain values of the structure pointed to by TaskParams are set
* as a side-effect based on task type. These may be examined after
* a successful call to TaskSetup(). User-specified values may be
* overridden.
*
* TaskId TaskSetup( TaskName_t TaskName,
* TaskSetupParamSet_t *TaskSetupParams );
*/
#define TaskSetup(TaskName, TaskSetupParams) \
TaskSetup_ ## TaskName (TaskName ## _api, TaskSetupParams)
const char *TaskVersion(void);
int TasksInitAPI(uint8 *MBarRef);
int TasksInitAPI_VM(uint8 *MBarRef, uint8 *MBarPhys);
void TasksLoadImage(sdma_regs *sdma);
int TasksAttachImage(sdma_regs *sdma);
uint32 TasksGetSramOffset(void);
void TasksSetSramOffset(uint32 sram_offset);
int TaskStart(TaskId taskId, uint32 autoStartEnable,
TaskId autoStartTask, uint32 intrEnable);
int TaskStop(TaskId taskId);
static int TaskStatus(TaskId taskId);
BDIdx TaskBDAssign(TaskId taskId, void *buffer0, void *buffer1,
int size, uint32 bdFlags);
BDIdx TaskBDRelease(TaskId taskId);
BDIdx TaskBDReset(TaskId taskId);
static TaskBD_t *TaskGetBD(TaskId taskId, BDIdx bd);
static TaskBD_t *TaskGetBDRing(TaskId taskId);
int TaskDebug(TaskId taskId, TaskDebugParamSet_t *paramSet);
static int TaskIntClear(TaskId taskId);
static TaskId TaskIntStatus(TaskId taskId);
static int TaskIntPending(TaskId taskId);
static TaskId TaskIntSource(void);
static uint16 TaskBDInUse(TaskId taskId);
/*!
* \brief Get the enable/disable status of a task.
* \param taskId Task handle passed back from a successful TaskSetup()
* \returns Boolean true indicates enabled or false indicates disabled
* or invalid taskId.
*/
static inline int TaskStatus(TaskId taskId)
{
return SDMA_TASK_STATUS(SDMA_TCR, taskId) & 0x8000;
}
/*!
* \brief Return a pointer to a buffer descriptor at index BDIdx
* \param taskId Task handle passed back from a successful TaskSetup()
* \param bd Buffer descriptor handle returned by
* TaskBDAssign() or TaskBDRelease().
* \returns Pointer to the requested buffer descriptor or NULL on error.
*
* The returned pointer should be cast to the appropriate buffer
* descriptor type, TaskBD1_t or TaskBD2_t.
*/
static inline TaskBD_t *TaskGetBD(TaskId taskId, BDIdx bd)
{
TaskBD_t *bdTab;
bdTab = TaskBDIdxTable[taskId].BDTablePtr;
if (TaskBDIdxTable[taskId].numPtr == 1) {
return (TaskBD_t *)&(((TaskBD1_t *)bdTab)[bd]);
} else {
return (TaskBD_t *)&(((TaskBD2_t *)bdTab)[bd]);
}
}
/*!
* \brief Return a pointer to the first buffer descriptor in the ring.
* \param taskId Task handle passed back from a successful TaskSetup()
* \returns Pointer to the array of buffer descriptors making up the
* ring or NULL on error.
*
* A device driver author may choose to use this in lieu of
* TaskBDAssign()/TaskBDRelease() to get direct access to the
* BD ring with the warning that the underlying data structure may change.
* Use at one's own discretion.
*/
static inline TaskBD_t *TaskGetBDRing(TaskId taskId)
{
return TaskBDIdxTable[taskId].BDTablePtr;
}
/*!
* \brief Clear the interrupt for a given BestComm task.
* \param taskId Task handle passed back from a successful TaskSetup()
* \returns TASK_ERR_NO_ERR (which is not really an error) for success
*/
static inline int TaskIntClear(TaskId taskId)
{
SDMA_CLEAR_IEVENT(SDMA_INT_PEND, taskId);
return TASK_ERR_NO_ERR; /* success */
}
/*!
* \brief Get the interrupt status for a given task.
* \param taskId Task handle passed back from a successful TaskSetup()
* \returns TASK_ERR_NO_INTR (which is not really an error) for no interrupt
* pending, taskId for a regular interrupt, DEBUG_INTR_ID for
* a debug interrupt and TEA_INTR_ID for a TEA interrupt.
* \b Note: TaskIntStatus() may return 0, but this means that that
* taskId 0 is interrupt pending.
*/
static inline TaskId TaskIntStatus(TaskId taskId)
{
uint32 pending;
pending = SDMA_INT_PENDING(SDMA_INT_PEND, SDMA_INT_MASK);
if (SDMA_INT_TEST(pending, taskId)) {
return taskId;
} else if (SDMA_INT_TEST(pending, DEBUG_INTR_ID)) {
return DEBUG_INTR_ID;
} else if (SDMA_INT_TEST(pending, TEA_INTR_ID)) {
return TEA_INTR_ID;
}
return TASK_ERR_NO_INTR;
}
/*!
* \brief Get the interrupt pending status for a given task.
* \param taskId Task handle passed back from a successful TaskSetup()
* \returns 0 if task does not have a pending interrupt. 1 if the task
* has an interrupt pending.
*/
static inline int TaskIntPending(TaskId taskId)
{
uint32 pending;
pending = SDMA_INT_PENDING(SDMA_INT_PEND, SDMA_INT_MASK);
if (SDMA_INT_TEST(pending, taskId)) {
return 1;
} else {
return 0;
}
}
/*!
* \brief Returns the task ID of an interrupting BestComm task.
* \returns TASK_ERR_NO_INTR (which is not really an error) for no interrupt
* pending or the taskId of the interrupting task.
*
* The user must query TaskIntStatus() to discover if this is a debug
* or TEA interrupt. This function is designed for use by an operating
* system interrupt handler.
*/
static inline TaskId TaskIntSource(void)
{
uint32 pending;
uint32 mask = 1 << (MAX_TASKS - 1);
TaskId i;
pending = SDMA_INT_PENDING(SDMA_INT_PEND, SDMA_INT_MASK);
if (SDMA_INT_TEST(pending, SDMA_INT_BIT_TEA)) {
return (TaskId)SDMA_TEA_SOURCE(SDMA_INT_PEND);
}
for (i = (MAX_TASKS - 1); i >= 0; --i, mask >>= 1) {
if (pending & mask) {
return i;
}
}
return TASK_ERR_NO_INTR;
}
/*!
* \brief Get a count of in-use buffer descriptors.
* \param taskId Task handle passed back from a successful TaskSetup()
* \returns Count of the current number of BDs in use by the given task.
*/
static inline uint16 TaskBDInUse(TaskId taskId)
{
return TaskBDIdxTable[taskId].currBDInUse;
}
#endif /* __BESTCOMM_API_H */