summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c
diff options
context:
space:
mode:
authorRalf Corsepius <ralf.corsepius@rtems.org>2005-12-31 05:09:26 +0000
committerRalf Corsepius <ralf.corsepius@rtems.org>2005-12-31 05:09:26 +0000
commitca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36 (patch)
tree805a5ddce1250235d6133376ddabb5543eb2cf82 /c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c
parentAdd BuildRoot. (diff)
downloadrtems-ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36.tar.bz2
New (CVS import Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>'s
submission).
Diffstat (limited to 'c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c')
-rw-r--r--c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c512
1 files changed, 512 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c b/c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c
new file mode 100644
index 0000000000..ad7471cdbb
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c
@@ -0,0 +1,512 @@
+/******************************************************************************
+*
+* 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.
+*
+* Filename: $Source$
+* Author: $Author$
+* Locker: $Locker$
+* State: $State$
+* Revision: $Revision$
+*
+******************************************************************************/
+
+/*!
+ * \mainpage Introduction
+ *
+ * \author Motorola Semiconductor Products Sector
+ * \date 2 Apr 2004
+ */
+
+/*!
+ * \file bestcomm_api.c
+ *
+ * Bestcomm_api.c implements most of the BestComm C API. The
+ * TaskSetup() function is generated by the BestComm Task API tools
+ * in capi/task_api/tasksetup_general.h as configured and included by
+ * code_dma/image_rtos?/task_capi/(*).c. Other functions are defined as
+ * inline in capi/bestcomm_api.h.
+ */
+
+#include "../bestcomm/include/ppctypes.h"
+#include "../bestcomm/bestcomm_api.h"
+#include "../bestcomm/task_api/bestcomm_cntrl.h"
+#include "../bestcomm/task_api/bestcomm_api_mem.h"
+#include "../bestcomm/task_api/tasksetup_bdtable.h"
+
+/***********************************************************************
+ */
+static const char* const TaskVersionString = "BestComm API v2.2 20041209";
+
+/*
+ * Hidden API data per task.
+ */
+
+static BDIdx BDHead[MAX_TASKS];
+static BDIdx BDTail[MAX_TASKS];
+
+/*
+ * Virtual memory location of the MBAR. System registers and SRAM are
+ * offset from this address.
+ */
+uint8 *MBarGlobal;
+
+/*
+ * Offset from MBarGlobal to get the physical memory address of the
+ * MBAR. This will be zero for systems that do not use virtual memory in
+ * their device driver model.
+ */
+sint64 MBarPhysOffsetGlobal;
+
+/*
+ * Offset to free space in SRAM after task code and buffer descriptors.
+ */
+uint32 SramOffsetGlobal = 0;
+
+/*
+ * This flag is false when TaskStart() has not yet been called on a
+ * task newly configured by TaskSetup() or TaskStop() has been called.
+ * Otherwise it is true. It is possible that a task disabled itself
+ * (transfer complete or BD ring empty) which will not show up in this
+ * flag.
+ *
+ * It is really only useful for BD tasks that assign buffers (via
+ * TaskBDAssign()) before TaskStart() or after TaskStop() are called.
+ */
+int TaskRunning[MAX_TASKS];
+
+/*!
+ * \brief Get a string containing API version information.
+ * \returns Pointer to the API version string
+ */
+const char *TaskVersion(void)
+{
+ return TaskVersionString;
+}
+
+/*!
+ * \brief Initialize the API.
+ * \param MBarRef Reference pointer to the device register memory
+ * map.
+ *
+ * \returns TASK_ERR_NO_ERR on successful initialization.
+ * or TASK_ERR_API_ALREADY_INITIALIZED.
+ *
+ * This function is only used with physical addresses.
+ *
+ * This function will also initialize API internal variables. The return
+ * value TASK_ERR_API_ALREADY_INITIALIZED is intended to help determine if
+ * another process has already instantiated a version of the API.
+ */
+int TasksInitAPI(uint8 *MBarRef)
+{
+ /*
+ * Copy pointer of register space to global variable.
+ * for use by other functions.
+ */
+ MBarGlobal = MBarRef;
+
+ /*
+ * The offset is 0 if physical and virtual are the same.
+ */
+ MBarPhysOffsetGlobal = 0;
+
+ /*
+ * IF API has not been initialized yet then...
+ * Make sure all BestComm interrupts are disabled and not pending.
+ * Make sure all tasks are disabled.
+ * This feature can only be put in after a way has been found to
+ * communicaticate with other processes.
+ */
+ return TASK_ERR_NO_ERR;
+}
+
+/*!
+ * \brief Initialize the API when virtual memory is used.
+ * \param MBarRef Reference pointer to the device register memory
+ * map.
+ * \param MBarPhys Actual physical location of MBAR device register
+ * memory map.
+ *
+ * \returns TASK_ERR_NO_ERR on successful initialization.
+ * or TASK_ERR_API_ALREADY_INITIALIZED.
+ *
+ * This function allows using virtual memory addresses as well as physical
+ * addresses. All device registers are offset to the address supplied here,
+ * so the virtual memory space should include enough space for the entire
+ * register set of the device to include the SRAM space.
+ *
+ * This function will also initialize API internal variables. The return
+ * value TASK_ERR_API_ALREADY_INITIALIZED is intended to help determine if
+ * another process has already instantiated a version of the API.
+ */
+int TasksInitAPI_VM(uint8 *MBarRef, uint8 *MBarPhys)
+{
+ /*
+ * Copy pointer of register space to global variable.
+ * for use by other functions.
+ */
+ MBarGlobal = MBarRef;
+ MBarPhysOffsetGlobal = MBarPhys - MBarRef;
+
+ /*
+ * If API has not been initialized yet then...
+ * Make sure all BestComm interrupts are disabled and not pending.
+ * Make sure all tasks are disabled.
+ * This feature can only be put in after a way has been found to
+ * communicaticate with other processes.
+ */
+ return TASK_ERR_NO_ERR;
+}
+
+/*!
+ * \brief \em Deprecated
+ * \param sdma Base address of the BestComm register set
+ *
+ * \returns TASK_ERR_NO_ERR
+ *
+ * Use of this function is no longer necessary. It is retained for
+ * compatibility with previous versions of the API.
+ */
+int TasksAttachImage(sdma_regs *sdma)
+{
+ return TASK_ERR_NO_ERR;
+}
+
+/*!
+ * \brief This function returns the value of the internal variable
+ * used to keep track of used space in SRAM.
+ *
+ * \returns The number of bytes from the beginning of SRAM to the end
+ * used space in the SRAM.
+ *
+ * This function will return the offset to free space in the SRAM
+ * not used by the CAPI. \b Note: The returned value is based
+ * on what is in TasksSetSramOffset. This function can
+ * not determine what SRAM space was used by another process. There must
+ * be some way external to the CAPI to keep track of SRAM space. This
+ * function only returns the internal variable used to keep track of buffer
+ * descriptors.
+ */
+uint32 TasksGetSramOffset(void)
+{
+ return SramOffsetGlobal;
+}
+
+/*!
+ * \brief This function stores the number of bytes from the
+ * beginning of SRAM to the end of the used space.
+ *
+ * \param sram_offset Number of bytes until the beginning of
+ * free space in the SRAM.
+ *
+ * This function sets the free space offset in SRAM. It must be called
+ * before setup in multi-task environments. It is the application's
+ * job to determine where the free space in SRAM is. This sets the
+ * base offset for the buffer descriptor variables during setup, so to
+ * deallocate buffers that have already been set this function should be
+ * called with a new offset.
+ */
+void TasksSetSramOffset(uint32 sram_offset)
+{
+ /*
+ * Set the SramOffsetGlobal variable to be used by TaskSetup_BDTable
+ */
+ SramOffsetGlobal = sram_offset;
+}
+
+/*!
+ * \brief Start an initialized task running.
+ * \param taskId Task handle passed back from a successful TaskSetup()
+ * \param autoStartEnable Boolean for whether autostart bit is enabled.
+ * If this is set then the parameter autoStartTask
+ * defines the task to auto start.
+ * \param autoStartTask TaskId for task to autostart. If autoStartEnable
+ * is not set then this parameter is a don't care.
+ * \param intrEnable Boolean for interrupt enable for this task.
+ * \returns TASK_ERR_NO_ERR on success or TASK_ERR_INVALID_ARG if taskId
+ * is invalid.
+ */
+int TaskStart(TaskId taskId, uint32 autoStartEnable, TaskId autoStartTask,
+ uint32 intrEnable)
+{
+ if (intrEnable) {
+ SDMA_INT_ENABLE(SDMA_INT_MASK, taskId);
+ } else {
+ SDMA_INT_DISABLE(SDMA_INT_MASK, taskId);
+ }
+ SDMA_TASK_AUTO_START(SDMA_TCR, taskId, autoStartEnable, autoStartTask)
+ SDMA_TASK_ENABLE(SDMA_TCR, taskId);
+
+ TaskRunning[taskId] = 1;
+ return TASK_ERR_NO_ERR;
+}
+
+/*!
+ * \brief Stop a running task.
+ * \param taskId Task handle passed back from a successful TaskSetup()
+ * \returns TASK_ERR_NO_ERR on success or TASK_ERR_INVALID_ARG if taskId
+ * is invalid.
+ *
+ * \em Note: Stopping a polling buffer descriptor task is a catastrophic
+ * operation. It does not merely pause execution. Context is not
+ * saved. The task's pointer into the BD ring is reset back to the
+ * beginning.
+ *
+ * \em Note: This is not the case for the new "fall-through" BD tasks.
+ * They save the BD ring pointer across stop/start boundaries. The
+ * previous polling tasks are considered deprecated.
+ */
+int TaskStop(TaskId taskId)
+{
+ SDMA_INT_DISABLE(SDMA_INT_MASK, taskId);
+ SDMA_TASK_DISABLE(SDMA_TCR, taskId);
+
+ TaskRunning[taskId] = 0;
+ return TASK_ERR_NO_ERR;
+}
+
+/*!
+ * \brief Assign a buffer to a buffer descriptor.
+ * \param taskId Task handle passed back from a successful TaskSetup()
+ * \param buffer0 A buffer to send data from or receive data into a device
+ * \param buffer1 A second buffer to send data from or receive data into
+ * a device for use with double-buffer tasks.
+ * \param size Size of the buffer in bytes.
+ * \param bdFlags Buffer descriptor flags to set. Used by ethernet BD tasks.
+ * \returns Handle to the buffer descriptor used by this DMA transfer.
+ * Error is indicated by a negative return value (see TaskErr_t).
+ *
+ * This function is used for both transmit and receive buffer descriptor
+ * tasks. The buffer may be freed by the TaskBDRelease() function.
+ * In the case of tasks with a buffer descriptor with two buffer pointers
+ * this function uses both buffer0 and buffer1 where buffer0 is a source
+ * and buffer1 is a destination. When the buffer descriptor is a single
+ * pointer type, the buffer0 is the only pointer used and buffer1 is ignored.
+ *
+ * Using this function on non-buffer descriptor tasks will produce
+ * unpredictable results.
+ */
+BDIdx TaskBDAssign(TaskId taskId, void *buffer0, void *buffer1, int size, uint32 bdFlags)
+{
+ BDIdx *bdHead;
+ TaskBD_t *bd;
+ BDIdx r = TASK_ERR_NO_ERR;
+
+ if (TaskBDIdxTable[taskId].currBDInUse == TaskBDIdxTable[taskId].numBD) {
+ /*
+ * The buffer ring is full.
+ */
+ r = TASK_ERR_BD_RING_FULL;
+
+ } else if ( (TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG)
+ && ((uint32)size & (uint32)(~SDMA_DRD_MASK_LENGTH))) {
+ r = TASK_ERR_SIZE_TOO_LARGE;
+
+ } else if ( !(TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG)
+ && ((uint32)size & (uint32)(0xffffffff<<SDMA_BD_BIT_READY))) {
+ r = TASK_ERR_SIZE_TOO_LARGE;
+
+ } else {
+ bdHead = &BDHead[taskId];
+
+ /*
+ * Increase Buffer Descriptor in-use variable.
+ */
+ ++TaskBDIdxTable[taskId].currBDInUse;
+
+ /*
+ * Get a generic TaskBD_t pointer to the BD to be assigned.
+ * Assign the buffer pointers.
+ */
+ bd = TaskBDIdxTable[taskId].BDTablePtr;
+ if (TaskBDIdxTable[taskId].numPtr == 1) {
+ bd = (TaskBD_t *)&(((TaskBD1_t *)bd)[*bdHead]);
+
+ ((TaskBD1_t *)bd)->DataPtr[0] = (uint32)buffer0;
+ } else {
+ bd = (TaskBD_t *)&(((TaskBD2_t *)bd)[*bdHead]);
+
+ ((TaskBD2_t *)bd)->DataPtr[0] = (uint32)buffer0;
+ ((TaskBD2_t *)bd)->DataPtr[1] = (uint32)buffer1;
+ }
+
+
+ if (bd->Status & SDMA_BD_MASK_READY) {
+ /*
+ * This BD is in use.
+ */
+ r = TASK_ERR_BD_BUSY;
+
+ } else {
+
+ /*
+ * Set status bits and length. As soon as Status is written, the
+ * BestComm may perform the transfer.
+ */
+ if (TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG) {
+ bd->Status = ( ((uint32)SDMA_DRD_MASK_FLAGS & bdFlags)
+ | ((uint32)SDMA_DRD_MASK_LENGTH & (uint32)size)
+ | ((uint32)SDMA_BD_MASK_READY));
+ } else {
+ bd->Status = ( ((uint32)SDMA_BD_MASK_SIGN & (uint32)size)
+ | ((uint32)SDMA_BD_MASK_READY));
+ }
+
+ /*
+ * Return the current BD index and increment.
+ */
+ r = *bdHead;
+ *bdHead = (BDIdx)((*bdHead + 1) % (BDIdx)TaskBDIdxTable[taskId].numBD);
+ }
+ }
+
+ /*
+ * Reenable a fall-through BD tasks that might have exited.
+ */
+ if (TaskRunning[taskId]) {
+ SDMA_TASK_ENABLE(SDMA_TCR, taskId);
+ }
+ return r;
+}
+
+/*!
+ * \brief Release last buffer in the buffer descriptor ring.
+ * \param taskId Task handle passed back from a successful TaskSetup()
+ *
+ * \returns Buffer descriptor index of next buffer index that will be released
+ * by another call of this function.
+ * TASK_ERR_BD_RING_EMPTY is returned if the ring is already empty.
+ *
+ * This function allows the system to reallocate the memory used by
+ * the buffer. It also cleans up the structure in the BD ring by
+ * removing the tail buffer in the ring. The buffer descriptor tasks
+ * are designed around this. Non-BD tasks do not use this function.
+ *
+ * Using this function on non-buffer descriptor tasks will produce
+ * unpredictable results.
+ */
+BDIdx TaskBDRelease(TaskId taskId)
+{
+ BDIdx *bdTail;
+ TaskBD_t *bd;
+
+ bdTail = &BDTail[taskId];
+
+ if (TaskBDIdxTable[taskId].currBDInUse == 0) {
+ /*
+ * Buffer Descriptor ring is empty, Can't Release!
+ */
+ return TASK_ERR_BD_RING_EMPTY;
+ }
+
+ /*
+ * Get a generic TaskBD_t pointer to the next BD to be released.
+ */
+ bd = TaskGetBD(taskId, *bdTail);
+
+ /*
+ * Verify the ready bit is clear.
+ */
+ if (bd->Status & SDMA_BD_MASK_READY) {
+ return TASK_ERR_BD_BUSY;
+ }
+
+ /*
+ * Increment the tail pointer around the ring, decrement in-use.
+ */
+ *bdTail = (BDIdx)((*bdTail + 1) % (BDIdx)TaskBDIdxTable[taskId].numBD);
+ --TaskBDIdxTable[taskId].currBDInUse;
+
+ return *bdTail;
+}
+
+
+/*!
+ * \brief Release all buffers.
+ * \param taskId Task handle passed back from a successful TaskSetup()
+ *
+ * \returns Buffer descriptor index of next buffer that will be
+ * assigned by TaskBDAssign() which will also be the first
+ * released by the next call to TaskBDRelease() or
+ * TASK_ERR_TASK_RUNNING if the task has not been stopped.
+ *
+ * This function is similar to TaskBDRelease() except that it releases
+ * all assigned buffers including those not yet processed by the BestComm
+ * task; i.e. SDMA_BD_MASK_READY is set.
+ * Non-BD tasks do not use this
+ * function.
+ *
+ * The task should not be running. Call TaskStop() first.
+ *
+ * \em Note: Partially transmitted buffers are up to the user to handle.
+ *
+ * Using this function on non-buffer descriptor tasks will produce
+ * unpredictable results.
+ */
+BDIdx TaskBDReset(TaskId taskId)
+{
+ BDIdx i;
+ TaskBD_t *bd, *bdTab;
+
+ if (TaskRunning[taskId]) {
+ return TASK_ERR_TASK_RUNNING;
+ }
+
+ bdTab = TaskBDIdxTable[taskId].BDTablePtr;
+
+ for (i = (BDIdx)TaskBDIdxTable[taskId].numBD - 1; i >= 0; --i) {
+
+ if (TaskBDIdxTable[taskId].numPtr == 1) {
+ bd = (TaskBD_t *)&(((TaskBD1_t *)bdTab)[i]);
+ } else {
+ bd = (TaskBD_t *)&(((TaskBD2_t *)bdTab)[i]);
+ }
+
+ bd->Status = 0x0;
+ }
+
+ TaskBDIdxTable[taskId].currBDInUse = 0;
+ *TaskBDIdxTable[taskId].BDStartPtr =
+ (volatile uint32)((volatile uint32)TaskBDIdxTable[taskId].BDTablePtr
+ + MBarPhysOffsetGlobal);
+ return BDHead[taskId] = BDTail[taskId] = 0;
+}
+
+
+/*!
+ * \brief Return BestComm debug information.
+ * \param taskId Task handle passed back from a successful TaskSetup()
+ * \param paramSet TBD
+ * \returns TBD
+ *
+ * The implementation of this function is yet to be determined.
+ */
+int TaskDebug(TaskId taskId, TaskDebugParamSet_t *paramSet)
+{
+ if ((taskId < 0) || (taskId >= MAX_TASKS)) {
+ return TASK_ERR_INVALID_ARG;
+ }
+ if (paramSet == NULL) {
+ return TASK_ERR_INVALID_ARG;
+ }
+
+ return TASK_ERR_NO_ERR;
+}