Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:52

0001 /******************************************************************************
0002 *
0003 * Copyright (c) 2004 Freescale Semiconductor, Inc.
0004 *
0005 * Permission is hereby granted, free of charge, to any person obtaining a
0006 * copy of this software and associated documentation files (the "Software"),
0007 * to deal in the Software without restriction, including without limitation
0008 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0009 * and/or sell copies of the Software, and to permit persons to whom the
0010 * Software is furnished to do so, subject to the following conditions:
0011 *
0012 * The above copyright notice and this permission notice shall be included
0013 * in all copies or substantial portions of the Software.
0014 *
0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
0018 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0019 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0020 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0021 * OTHER DEALINGS IN THE SOFTWARE.
0022 *
0023 ******************************************************************************/
0024 
0025 /*!
0026  * \file    bestcomm_api.c
0027  *
0028  * Bestcomm_api.c implements most of the BestComm C API. The
0029  * TaskSetup() function is generated by the BestComm Task API tools
0030  * in capi/task_api/tasksetup_general.h as configured and included by
0031  * code_dma/image_rtos?/task_capi/(*).c. Other functions are defined as
0032  * inline in capi/bestcomm_api.h.
0033  */
0034 
0035 #include <bsp/bestcomm/include/ppctypes.h>
0036 #include <bsp/bestcomm/bestcomm_api.h>
0037 #include <bsp/bestcomm/task_api/bestcomm_cntrl.h>
0038 #include <bsp/bestcomm/task_api/bestcomm_api_mem.h>
0039 #include <bsp/bestcomm/task_api/tasksetup_bdtable.h>
0040 
0041 /***********************************************************************
0042  */
0043 static const char* const TaskVersionString = "BestComm API v2.2 20041209";
0044 
0045 /*
0046  * Hidden API data per task.
0047  */
0048 
0049 static BDIdx BDHead[MAX_TASKS];
0050 static BDIdx BDTail[MAX_TASKS];
0051 
0052 /*
0053  * Virtual memory location of the MBAR. System registers and SRAM are
0054  * offset from this address.
0055  */
0056 uint8 *MBarGlobal;
0057 
0058 /*
0059  * Offset from MBarGlobal to get the physical memory address of the
0060  * MBAR. This will be zero for systems that do not use virtual memory in
0061  * their device driver model.
0062  */
0063 sint64 MBarPhysOffsetGlobal;
0064 
0065 /*
0066  * This flag is false when TaskStart() has not yet been called on a
0067  * task newly configured by TaskSetup() or TaskStop() has been called.
0068  * Otherwise it is true.  It is possible that a task disabled itself
0069  * (transfer complete or BD ring empty) which will not show up in this
0070  * flag.
0071  *
0072  * It is really only useful for BD tasks that assign buffers (via
0073  * TaskBDAssign()) before TaskStart() or after TaskStop() are called.
0074  */
0075 int TaskRunning[MAX_TASKS];
0076 
0077 /*!
0078  * \brief   Get a string containing API version information.
0079  * \returns Pointer to the API version string
0080  */
0081 const char *TaskVersion(void)
0082 {
0083     return TaskVersionString;
0084 }
0085 
0086 /*!
0087  * \brief   Initialize the API.
0088  * \param   MBarRef     Reference pointer to the device register memory
0089  *                      map.
0090  *
0091  * \returns TASK_ERR_NO_ERR on successful initialization.
0092  *          or TASK_ERR_API_ALREADY_INITIALIZED.
0093  *
0094  * This function is only used with physical addresses.
0095  *
0096  * This function will also initialize API internal variables. The return
0097  * value TASK_ERR_API_ALREADY_INITIALIZED is intended to help determine if
0098  * another process has already instantiated a version of the API.
0099  */
0100 int TasksInitAPI(uint8 *MBarRef)
0101 {
0102     /*
0103      * Copy pointer of register space to global variable.
0104      * for use by other functions.
0105      */
0106     MBarGlobal = MBarRef;
0107 
0108     /*
0109      * The offset is 0 if physical and virtual are the same.
0110      */
0111     MBarPhysOffsetGlobal = 0;
0112 
0113     /*
0114      * IF API has not been initialized yet then...
0115      * Make sure all BestComm interrupts are disabled and not pending.
0116      * Make sure all tasks are disabled.
0117      * This feature can only be put in after a way has been found to
0118      * communicaticate with other processes.
0119      */
0120     return TASK_ERR_NO_ERR;
0121 }
0122 
0123 /*!
0124  * \brief   Initialize the API when virtual memory is used.
0125  * \param   MBarRef     Reference pointer to the device register memory
0126  *                      map.
0127  * \param   MBarPhys    Actual physical location of MBAR device register
0128  *                      memory map.
0129  *
0130  * \returns TASK_ERR_NO_ERR on successful initialization.
0131  *          or TASK_ERR_API_ALREADY_INITIALIZED.
0132  *
0133  * This function allows using virtual memory addresses as well as physical
0134  * addresses. All device registers are offset to the address supplied here,
0135  * so the virtual memory space should include enough space for the entire
0136  * register set of the device to include the SRAM space.
0137  *
0138  * This function will also initialize API internal variables. The return
0139  * value TASK_ERR_API_ALREADY_INITIALIZED is intended to help determine if
0140  * another process has already instantiated a version of the API.
0141  */
0142 int TasksInitAPI_VM(uint8 *MBarRef, uint8 *MBarPhys)
0143 {
0144     /*
0145      * Copy pointer of register space to global variable.
0146      * for use by other functions.
0147      */
0148     MBarGlobal = MBarRef;
0149     MBarPhysOffsetGlobal = MBarPhys - MBarRef;
0150 
0151     /*
0152      * If API has not been initialized yet then...
0153      * Make sure all BestComm interrupts are disabled and not pending.
0154      * Make sure all tasks are disabled.
0155      * This feature can only be put in after a way has been found to
0156      * communicaticate with other processes.
0157      */
0158     return TASK_ERR_NO_ERR;
0159 }
0160 
0161 /*!
0162  * \brief   \em Deprecated
0163  * \param   sdma Base address of the BestComm register set
0164  *
0165  * \returns TASK_ERR_NO_ERR
0166  *
0167  * Use of this function is no longer necessary. It is retained for
0168  * compatibility with previous versions of the API.
0169  */
0170 int TasksAttachImage(sdma_regs *sdma)
0171 {
0172     return TASK_ERR_NO_ERR;
0173 }
0174 
0175 /*!
0176  * \brief   Start an initialized task running.
0177  * \param   taskId  Task handle passed back from a successful TaskSetup()
0178  * \param   autoStartEnable Boolean for whether autostart bit is enabled.
0179  *                          If this is set then the parameter autoStartTask
0180  *                          defines the task to auto start.
0181  * \param   autoStartTask   TaskId for task to autostart. If autoStartEnable
0182  *                          is not set then this parameter is a don't care.
0183  * \param   intrEnable      Boolean for interrupt enable for this task.
0184  * \returns TASK_ERR_NO_ERR on success or TASK_ERR_INVALID_ARG if taskId
0185  *          is invalid.
0186  */
0187 int TaskStart(TaskId taskId, uint32 autoStartEnable, TaskId autoStartTask,
0188               uint32 intrEnable)
0189 {
0190     if (intrEnable) {
0191         SDMA_INT_ENABLE(SDMA_INT_MASK, taskId);
0192     } else {
0193         SDMA_INT_DISABLE(SDMA_INT_MASK, taskId);
0194     }
0195     SDMA_TASK_AUTO_START(SDMA_TCR, taskId, autoStartEnable, autoStartTask)
0196     SDMA_TASK_ENABLE(SDMA_TCR, taskId);
0197 
0198     TaskRunning[taskId] = 1;
0199     return TASK_ERR_NO_ERR;
0200 }
0201 
0202 /*!
0203  * \brief   Stop a running task.
0204  * \param   taskId  Task handle passed back from a successful TaskSetup()
0205  * \returns TASK_ERR_NO_ERR on success or TASK_ERR_INVALID_ARG if taskId
0206  *          is invalid.
0207  *
0208  * \em Note: Stopping a polling buffer descriptor task is a catastrophic
0209  * operation. It does not merely pause execution. Context is not
0210  * saved. The task's pointer into the BD ring is reset back to the
0211  * beginning.
0212  *
0213  * \em Note: This is not the case for the new "fall-through" BD tasks.
0214  * They save the BD ring pointer across stop/start boundaries. The
0215  * previous polling tasks are considered deprecated.
0216  */
0217 int TaskStop(TaskId taskId)
0218 {
0219     SDMA_INT_DISABLE(SDMA_INT_MASK, taskId);
0220     SDMA_TASK_DISABLE(SDMA_TCR, taskId);
0221 
0222     TaskRunning[taskId] = 0;
0223     return TASK_ERR_NO_ERR;
0224 }
0225 
0226 /*!
0227  * \brief Assign a buffer to a buffer descriptor.
0228  * \param taskId    Task handle passed back from a successful TaskSetup()
0229  * \param buffer0   A buffer to send data from or receive data into a device
0230  * \param buffer1   A second buffer to send data from or receive data into
0231  *                  a device for use with double-buffer tasks.
0232  * \param size      Size of the buffer in bytes.
0233  * \param bdFlags   Buffer descriptor flags to set. Used by ethernet BD tasks.
0234  * \returns Handle to the buffer descriptor used by this DMA transfer.
0235  *          Error is indicated by a negative return value (see TaskErr_t).
0236  *
0237  * This function is used for both transmit and receive buffer descriptor
0238  * tasks. The buffer may be freed by the TaskBDRelease() function.
0239  * In the case of tasks with a buffer descriptor with two buffer pointers
0240  * this function uses both buffer0 and buffer1 where buffer0 is a source
0241  * and buffer1 is a destination. When the buffer descriptor is a single
0242  * pointer type, the buffer0 is the only pointer used and buffer1 is ignored.
0243  *
0244  * Using this function on non-buffer descriptor tasks will produce
0245  * unpredictable results.
0246  */
0247 BDIdx TaskBDAssign(TaskId taskId, void *buffer0, void *buffer1, int size, uint32 bdFlags)
0248 {
0249     BDIdx       *bdHead;
0250     TaskBD_t    *bd;
0251     BDIdx       r = TASK_ERR_NO_ERR;
0252 
0253     if (TaskBDIdxTable[taskId].currBDInUse == TaskBDIdxTable[taskId].numBD) {
0254         /*
0255          * The buffer ring is full.
0256          */
0257         r = TASK_ERR_BD_RING_FULL;
0258 
0259     } else if (   (TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG)
0260                && ((uint32)size & (uint32)(~SDMA_DRD_MASK_LENGTH))) {
0261         r = TASK_ERR_SIZE_TOO_LARGE;
0262 
0263     } else if (   !(TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG)
0264                && ((uint32)size & (uint32)(0xffffffff<<SDMA_BD_BIT_READY))) {
0265         r = TASK_ERR_SIZE_TOO_LARGE;
0266 
0267     } else {
0268         bdHead = &BDHead[taskId];
0269 
0270         /*
0271          * Increase Buffer Descriptor in-use variable.
0272          */
0273         ++TaskBDIdxTable[taskId].currBDInUse;
0274 
0275         /*
0276          * Get a generic TaskBD_t pointer to the BD to be assigned.
0277          * Assign the buffer pointers.
0278          */
0279         bd = TaskBDIdxTable[taskId].BDTablePtr;
0280         if (TaskBDIdxTable[taskId].numPtr == 1) {
0281             bd = (TaskBD_t *)&(((TaskBD1_t *)bd)[*bdHead]);
0282 
0283             ((TaskBD1_t *)bd)->DataPtr[0] = (uint32)buffer0;
0284         } else {
0285             bd = (TaskBD_t *)&(((TaskBD2_t *)bd)[*bdHead]);
0286 
0287             ((TaskBD2_t *)bd)->DataPtr[0] = (uint32)buffer0;
0288             ((TaskBD2_t *)bd)->DataPtr[1] = (uint32)buffer1;
0289         }
0290 
0291 
0292         if (bd->Status & SDMA_BD_MASK_READY) {
0293             /*
0294              * This BD is in use.
0295              */
0296             r = TASK_ERR_BD_BUSY;
0297 
0298         } else {
0299 
0300             /*
0301              * Set status bits and length. As soon as Status is written, the
0302              * BestComm may perform the transfer.
0303              */
0304             if (TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG) {
0305                 bd->Status = ( ((uint32)SDMA_DRD_MASK_FLAGS  & bdFlags)
0306                              | ((uint32)SDMA_DRD_MASK_LENGTH & (uint32)size)
0307                              | ((uint32)SDMA_BD_MASK_READY));
0308             } else {
0309                 bd->Status = ( ((uint32)SDMA_BD_MASK_SIGN    & (uint32)size)
0310                              | ((uint32)SDMA_BD_MASK_READY));
0311             }
0312 
0313             /*
0314              * Return the current BD index and increment.
0315              */
0316             r = *bdHead;
0317             *bdHead = (BDIdx)((*bdHead + 1) % (BDIdx)TaskBDIdxTable[taskId].numBD);
0318         }
0319     }
0320 
0321     /*
0322      * Reenable a fall-through BD tasks that might have exited.
0323      */
0324     if (TaskRunning[taskId]) {
0325         SDMA_TASK_ENABLE(SDMA_TCR, taskId);
0326     }
0327     return r;
0328 }
0329 
0330 /*!
0331  * \brief Release last buffer in the buffer descriptor ring.
0332  * \param taskId    Task handle passed back from a successful TaskSetup()
0333  *
0334  * \returns Buffer descriptor index of next buffer index that will be released
0335  *          by another call of this function.
0336  *          TASK_ERR_BD_RING_EMPTY is returned if the ring is already empty.
0337  *
0338  * This function allows the system to reallocate the memory used by
0339  * the buffer. It also cleans up the structure in the BD ring by
0340  * removing the tail buffer in the ring. The buffer descriptor tasks
0341  * are designed around this. Non-BD tasks do not use this function.
0342  *
0343  * Using this function on non-buffer descriptor tasks will produce
0344  * unpredictable results.
0345  */
0346 BDIdx TaskBDRelease(TaskId taskId)
0347 {
0348     BDIdx       *bdTail;
0349     TaskBD_t    *bd;
0350 
0351     bdTail = &BDTail[taskId];
0352 
0353     if (TaskBDIdxTable[taskId].currBDInUse == 0) {
0354         /*
0355          * Buffer Descriptor ring is empty, Can't Release!
0356          */
0357          return TASK_ERR_BD_RING_EMPTY;
0358     }
0359 
0360     /*
0361      * Get a generic TaskBD_t pointer to the next BD to be released.
0362      */
0363     bd = TaskGetBD(taskId, *bdTail);
0364 
0365     /*
0366      * Verify the ready bit is clear.
0367      */
0368     if (bd->Status & SDMA_BD_MASK_READY) {
0369         return TASK_ERR_BD_BUSY;
0370     }
0371 
0372     /*
0373      * Increment the tail pointer around the ring, decrement in-use.
0374      */
0375     *bdTail = (BDIdx)((*bdTail + 1) % (BDIdx)TaskBDIdxTable[taskId].numBD);
0376     --TaskBDIdxTable[taskId].currBDInUse;
0377 
0378     return *bdTail;
0379 }
0380 
0381 
0382 /*!
0383  * \brief Release all buffers.
0384  * \param taskId    Task handle passed back from a successful TaskSetup()
0385  *
0386  * \returns Buffer descriptor index of next buffer that will be
0387  *          assigned by TaskBDAssign() which will also be the first
0388  *          released by the next call to TaskBDRelease() or
0389  *          TASK_ERR_TASK_RUNNING if the task has not been stopped.
0390  *
0391  * This function is similar to TaskBDRelease() except that it releases
0392  * all assigned buffers including those not yet processed by the BestComm
0393  * task; i.e. SDMA_BD_MASK_READY is set.
0394  * Non-BD tasks do not use this
0395  * function.
0396  *
0397  * The task should not be running. Call TaskStop() first.
0398  *
0399  * \em Note: Partially transmitted buffers are up to the user to handle.
0400  *
0401  * Using this function on non-buffer descriptor tasks will produce
0402  * unpredictable results.
0403  */
0404 BDIdx TaskBDReset(TaskId taskId)
0405 {
0406     BDIdx       i;
0407     TaskBD_t    *bd, *bdTab;
0408 
0409     if (TaskRunning[taskId]) {
0410         return TASK_ERR_TASK_RUNNING;
0411     }
0412 
0413     bdTab = TaskBDIdxTable[taskId].BDTablePtr;
0414 
0415     for (i = (BDIdx)TaskBDIdxTable[taskId].numBD - 1; i >= 0; --i) {
0416 
0417         if (TaskBDIdxTable[taskId].numPtr == 1) {
0418             bd = (TaskBD_t *)&(((TaskBD1_t *)bdTab)[i]);
0419         } else {
0420             bd = (TaskBD_t *)&(((TaskBD2_t *)bdTab)[i]);
0421         }
0422 
0423         bd->Status = 0x0;
0424     }
0425 
0426     TaskBDIdxTable[taskId].currBDInUse = 0;
0427     *TaskBDIdxTable[taskId].BDStartPtr =
0428         (volatile uint32)((volatile uint32)TaskBDIdxTable[taskId].BDTablePtr
0429                         + MBarPhysOffsetGlobal);
0430     return BDHead[taskId] = BDTail[taskId] = 0;
0431 }
0432 
0433 
0434 /*!
0435  * \brief   Return BestComm debug information.
0436  * \param   taskId  Task handle passed back from a successful TaskSetup()
0437  * \param   paramSet    TBD
0438  * \returns TBD
0439  *
0440  * The implementation of this function is yet to be determined.
0441  */
0442 int TaskDebug(TaskId taskId, TaskDebugParamSet_t *paramSet)
0443 {
0444     if ((taskId < 0) || (taskId >= MAX_TASKS)) {
0445         return TASK_ERR_INVALID_ARG;
0446     }
0447     if (paramSet == NULL) {
0448         return TASK_ERR_INVALID_ARG;
0449     }
0450 
0451     return TASK_ERR_NO_ERR;
0452 }