diff options
author | Ralf Corsepius <ralf.corsepius@rtems.org> | 2005-12-31 05:09:26 +0000 |
---|---|---|
committer | Ralf Corsepius <ralf.corsepius@rtems.org> | 2005-12-31 05:09:26 +0000 |
commit | ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36 (patch) | |
tree | 805a5ddce1250235d6133376ddabb5543eb2cf82 /c/src/lib/libbsp/powerpc/gen5200/bestcomm/bestcomm_api.c | |
parent | Add BuildRoot. (diff) | |
download | rtems-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.c | 512 |
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; +} |