source: rtems/bsps/powerpc/gen5200/bestcomm/bestcomm_api.c @ a0f04d6

5
Last change on this file since a0f04d6 was a0f04d6, checked in by Sebastian Huber <sebastian.huber@…>, on 04/22/18 at 13:32:38

bsp/gen5200: Move bestcomm to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 13.9 KB
Line 
1/******************************************************************************
2*
3* Copyright (c) 2004 Freescale Semiconductor, Inc.
4*
5* Permission is hereby granted, free of charge, to any person obtaining a
6* copy of this software and associated documentation files (the "Software"),
7* to deal in the Software without restriction, including without limitation
8* the rights to use, copy, modify, merge, publish, distribute, sublicense,
9* and/or sell copies of the Software, and to permit persons to whom the
10* Software is furnished to do so, subject to the following conditions:
11*
12* The above copyright notice and this permission notice shall be included
13* in all copies or substantial portions of the Software.
14*
15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21* OTHER DEALINGS IN THE SOFTWARE.
22*
23******************************************************************************/
24
25/*!
26 * \mainpage    Introduction
27 *
28 * \author      Motorola Semiconductor Products Sector
29 * \date        2 Apr 2004
30 */
31
32/*!
33 * \file        bestcomm_api.c
34 *
35 * Bestcomm_api.c implements most of the BestComm C API. The
36 * TaskSetup() function is generated by the BestComm Task API tools
37 * in capi/task_api/tasksetup_general.h as configured and included by
38 * code_dma/image_rtos?/task_capi/(*).c. Other functions are defined as
39 * inline in capi/bestcomm_api.h.
40 */
41
42#include <bsp/bestcomm/include/ppctypes.h>
43#include <bsp/bestcomm/bestcomm_api.h>
44#include <bsp/bestcomm/task_api/bestcomm_cntrl.h>
45#include <bsp/bestcomm/task_api/bestcomm_api_mem.h>
46#include <bsp/bestcomm/task_api/tasksetup_bdtable.h>
47
48/***********************************************************************
49 */
50static const char* const TaskVersionString = "BestComm API v2.2 20041209";
51
52/*
53 * Hidden API data per task.
54 */
55
56static BDIdx BDHead[MAX_TASKS];
57static BDIdx BDTail[MAX_TASKS];
58
59/*
60 * Virtual memory location of the MBAR. System registers and SRAM are
61 * offset from this address.
62 */
63uint8 *MBarGlobal;
64
65/*
66 * Offset from MBarGlobal to get the physical memory address of the
67 * MBAR. This will be zero for systems that do not use virtual memory in
68 * their device driver model.
69 */
70sint64 MBarPhysOffsetGlobal;
71
72/*
73 * This flag is false when TaskStart() has not yet been called on a
74 * task newly configured by TaskSetup() or TaskStop() has been called.
75 * Otherwise it is true.  It is possible that a task disabled itself
76 * (transfer complete or BD ring empty) which will not show up in this
77 * flag.
78 *
79 * It is really only useful for BD tasks that assign buffers (via
80 * TaskBDAssign()) before TaskStart() or after TaskStop() are called.
81 */
82int TaskRunning[MAX_TASKS];
83
84/*!
85 * \brief       Get a string containing API version information.
86 * \returns     Pointer to the API version string
87 */
88const char *TaskVersion(void)
89{
90        return TaskVersionString;
91}
92
93/*!
94 * \brief       Initialize the API.
95 * \param       MBarRef         Reference pointer to the device register memory
96 *                                              map.
97 *
98 * \returns     TASK_ERR_NO_ERR on successful initialization.
99 *                      or TASK_ERR_API_ALREADY_INITIALIZED.
100 *
101 * This function is only used with physical addresses.
102 *
103 * This function will also initialize API internal variables. The return
104 * value TASK_ERR_API_ALREADY_INITIALIZED is intended to help determine if
105 * another process has already instantiated a version of the API.
106 */
107int TasksInitAPI(uint8 *MBarRef)
108{
109        /*
110         * Copy pointer of register space to global variable.
111         * for use by other functions.
112         */
113        MBarGlobal = MBarRef;
114
115        /*
116         * The offset is 0 if physical and virtual are the same.
117         */
118        MBarPhysOffsetGlobal = 0;
119
120        /*
121         * IF API has not been initialized yet then...
122         * Make sure all BestComm interrupts are disabled and not pending.
123         * Make sure all tasks are disabled.
124         * This feature can only be put in after a way has been found to
125         * communicaticate with other processes.
126         */
127        return TASK_ERR_NO_ERR;
128}
129
130/*!
131 * \brief       Initialize the API when virtual memory is used.
132 * \param       MBarRef         Reference pointer to the device register memory
133 *                                              map.
134 * \param       MBarPhys        Actual physical location of MBAR device register
135 *                                              memory map.
136 *
137 * \returns     TASK_ERR_NO_ERR on successful initialization.
138 *                      or TASK_ERR_API_ALREADY_INITIALIZED.
139 *
140 * This function allows using virtual memory addresses as well as physical
141 * addresses. All device registers are offset to the address supplied here,
142 * so the virtual memory space should include enough space for the entire
143 * register set of the device to include the SRAM space.
144 *
145 * This function will also initialize API internal variables. The return
146 * value TASK_ERR_API_ALREADY_INITIALIZED is intended to help determine if
147 * another process has already instantiated a version of the API.
148 */
149int TasksInitAPI_VM(uint8 *MBarRef, uint8 *MBarPhys)
150{
151        /*
152         * Copy pointer of register space to global variable.
153         * for use by other functions.
154         */
155        MBarGlobal = MBarRef;
156        MBarPhysOffsetGlobal = MBarPhys - MBarRef;
157
158        /*
159         * If API has not been initialized yet then...
160         * Make sure all BestComm interrupts are disabled and not pending.
161         * Make sure all tasks are disabled.
162         * This feature can only be put in after a way has been found to
163         * communicaticate with other processes.
164         */
165        return TASK_ERR_NO_ERR;
166}
167
168/*!
169 * \brief       \em Deprecated
170 * \param       sdma Base address of the BestComm register set
171 *
172 * \returns TASK_ERR_NO_ERR
173 *
174 * Use of this function is no longer necessary. It is retained for
175 * compatibility with previous versions of the API.
176 */
177int TasksAttachImage(sdma_regs *sdma)
178{
179        return TASK_ERR_NO_ERR;
180}
181
182/*!
183 * \brief       Start an initialized task running.
184 * \param       taskId  Task handle passed back from a successful TaskSetup()
185 * \param       autoStartEnable Boolean for whether autostart bit is enabled.
186 *                                                      If this is set then the parameter autoStartTask
187 *                                                      defines the task to auto start.
188 * \param       autoStartTask   TaskId for task to autostart. If autoStartEnable
189 *                                                      is not set then this parameter is a don't care.
190 * \param       intrEnable              Boolean for interrupt enable for this task.
191 * \returns     TASK_ERR_NO_ERR on success or TASK_ERR_INVALID_ARG if taskId
192 *                      is invalid.
193 */
194int TaskStart(TaskId taskId, uint32 autoStartEnable, TaskId autoStartTask,
195                          uint32 intrEnable)
196{
197        if (intrEnable) {
198                SDMA_INT_ENABLE(SDMA_INT_MASK, taskId);
199        } else {
200                SDMA_INT_DISABLE(SDMA_INT_MASK, taskId);
201        }
202        SDMA_TASK_AUTO_START(SDMA_TCR, taskId, autoStartEnable, autoStartTask)
203        SDMA_TASK_ENABLE(SDMA_TCR, taskId);
204
205        TaskRunning[taskId] = 1;
206        return TASK_ERR_NO_ERR;
207}
208
209/*!
210 * \brief       Stop a running task.
211 * \param       taskId  Task handle passed back from a successful TaskSetup()
212 * \returns     TASK_ERR_NO_ERR on success or TASK_ERR_INVALID_ARG if taskId
213 *                      is invalid.
214 *
215 * \em Note: Stopping a polling buffer descriptor task is a catastrophic
216 * operation. It does not merely pause execution. Context is not
217 * saved. The task's pointer into the BD ring is reset back to the
218 * beginning.
219 *
220 * \em Note: This is not the case for the new "fall-through" BD tasks.
221 * They save the BD ring pointer across stop/start boundaries. The
222 * previous polling tasks are considered deprecated.
223 */
224int TaskStop(TaskId taskId)
225{
226        SDMA_INT_DISABLE(SDMA_INT_MASK, taskId);
227        SDMA_TASK_DISABLE(SDMA_TCR, taskId);
228
229        TaskRunning[taskId] = 0;
230        return TASK_ERR_NO_ERR;
231}
232
233/*!
234 * \brief Assign a buffer to a buffer descriptor.
235 * \param taskId        Task handle passed back from a successful TaskSetup()
236 * \param buffer0       A buffer to send data from or receive data into a device
237 * \param buffer1       A second buffer to send data from or receive data into
238 *                                      a device for use with double-buffer tasks.
239 * \param size          Size of the buffer in bytes.
240 * \param bdFlags       Buffer descriptor flags to set. Used by ethernet BD tasks.
241 * \returns Handle to the buffer descriptor used by this DMA transfer.
242 *                      Error is indicated by a negative return value (see TaskErr_t).
243 *
244 * This function is used for both transmit and receive buffer descriptor
245 * tasks. The buffer may be freed by the TaskBDRelease() function.
246 * In the case of tasks with a buffer descriptor with two buffer pointers
247 * this function uses both buffer0 and buffer1 where buffer0 is a source
248 * and buffer1 is a destination. When the buffer descriptor is a single
249 * pointer type, the buffer0 is the only pointer used and buffer1 is ignored.
250 *
251 * Using this function on non-buffer descriptor tasks will produce
252 * unpredictable results.
253 */
254BDIdx TaskBDAssign(TaskId taskId, void *buffer0, void *buffer1, int size, uint32 bdFlags)
255{
256        BDIdx           *bdHead;
257        TaskBD_t        *bd;
258        BDIdx           r = TASK_ERR_NO_ERR;
259
260        if (TaskBDIdxTable[taskId].currBDInUse == TaskBDIdxTable[taskId].numBD) {
261                /*
262                 * The buffer ring is full.
263                 */
264                r = TASK_ERR_BD_RING_FULL;
265
266        } else if (   (TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG)
267                           && ((uint32)size & (uint32)(~SDMA_DRD_MASK_LENGTH))) {
268                r = TASK_ERR_SIZE_TOO_LARGE;
269
270        } else if (   !(TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG)
271                           && ((uint32)size & (uint32)(0xffffffff<<SDMA_BD_BIT_READY))) {
272                r = TASK_ERR_SIZE_TOO_LARGE;
273
274        } else {
275                bdHead = &BDHead[taskId];
276
277                /*
278                 * Increase Buffer Descriptor in-use variable.
279                 */
280                ++TaskBDIdxTable[taskId].currBDInUse;
281
282                /*
283                 * Get a generic TaskBD_t pointer to the BD to be assigned.
284                 * Assign the buffer pointers.
285                 */
286                bd = TaskBDIdxTable[taskId].BDTablePtr;
287                if (TaskBDIdxTable[taskId].numPtr == 1) {
288                        bd = (TaskBD_t *)&(((TaskBD1_t *)bd)[*bdHead]);
289
290                        ((TaskBD1_t *)bd)->DataPtr[0] = (uint32)buffer0;
291                } else {
292                        bd = (TaskBD_t *)&(((TaskBD2_t *)bd)[*bdHead]);
293
294                        ((TaskBD2_t *)bd)->DataPtr[0] = (uint32)buffer0;
295                        ((TaskBD2_t *)bd)->DataPtr[1] = (uint32)buffer1;
296                }
297
298
299                if (bd->Status & SDMA_BD_MASK_READY) {
300                        /*
301                         * This BD is in use.
302                         */
303                        r = TASK_ERR_BD_BUSY;
304
305                } else {
306
307                        /*
308                         * Set status bits and length. As soon as Status is written, the
309                         * BestComm may perform the transfer.
310                         */
311                        if (TaskBDIdxTable[taskId].apiConfig & API_CONFIG_BD_FLAG) {
312                                bd->Status = ( ((uint32)SDMA_DRD_MASK_FLAGS  & bdFlags)
313                                                         | ((uint32)SDMA_DRD_MASK_LENGTH & (uint32)size)
314                                                         | ((uint32)SDMA_BD_MASK_READY));
315                        } else {
316                                bd->Status = ( ((uint32)SDMA_BD_MASK_SIGN    & (uint32)size)
317                                                         | ((uint32)SDMA_BD_MASK_READY));
318                        }
319
320                        /*
321                         * Return the current BD index and increment.
322                         */
323                        r = *bdHead;
324                        *bdHead = (BDIdx)((*bdHead + 1) % (BDIdx)TaskBDIdxTable[taskId].numBD);
325                }
326        }
327
328        /*
329         * Reenable a fall-through BD tasks that might have exited.
330         */
331        if (TaskRunning[taskId]) {
332                SDMA_TASK_ENABLE(SDMA_TCR, taskId);
333        }
334        return r;
335}
336
337/*!
338 * \brief Release last buffer in the buffer descriptor ring.
339 * \param taskId        Task handle passed back from a successful TaskSetup()
340 *
341 * \returns Buffer descriptor index of next buffer index that will be released
342 *                      by another call of this function.
343 *                      TASK_ERR_BD_RING_EMPTY is returned if the ring is already empty.
344 *
345 * This function allows the system to reallocate the memory used by
346 * the buffer. It also cleans up the structure in the BD ring by
347 * removing the tail buffer in the ring. The buffer descriptor tasks
348 * are designed around this. Non-BD tasks do not use this function.
349 *
350 * Using this function on non-buffer descriptor tasks will produce
351 * unpredictable results.
352 */
353BDIdx TaskBDRelease(TaskId taskId)
354{
355        BDIdx           *bdTail;
356        TaskBD_t        *bd;
357
358        bdTail = &BDTail[taskId];
359
360        if (TaskBDIdxTable[taskId].currBDInUse == 0) {
361                /*
362                 * Buffer Descriptor ring is empty, Can't Release!
363                 */
364                 return TASK_ERR_BD_RING_EMPTY;
365        }
366
367        /*
368         * Get a generic TaskBD_t pointer to the next BD to be released.
369         */
370        bd = TaskGetBD(taskId, *bdTail);
371
372        /*
373         * Verify the ready bit is clear.
374         */
375        if (bd->Status & SDMA_BD_MASK_READY) {
376                return TASK_ERR_BD_BUSY;
377        }
378
379        /*
380         * Increment the tail pointer around the ring, decrement in-use.
381         */
382        *bdTail = (BDIdx)((*bdTail + 1) % (BDIdx)TaskBDIdxTable[taskId].numBD);
383        --TaskBDIdxTable[taskId].currBDInUse;
384
385        return *bdTail;
386}
387
388
389/*!
390 * \brief Release all buffers.
391 * \param taskId        Task handle passed back from a successful TaskSetup()
392 *
393 * \returns Buffer descriptor index of next buffer that will be
394 *                      assigned by TaskBDAssign() which will also be the first
395 *                      released by the next call to TaskBDRelease() or
396 *                      TASK_ERR_TASK_RUNNING if the task has not been stopped.
397 *
398 * This function is similar to TaskBDRelease() except that it releases
399 * all assigned buffers including those not yet processed by the BestComm
400 * task; i.e. SDMA_BD_MASK_READY is set.
401 * Non-BD tasks do not use this
402 * function.
403 *
404 * The task should not be running. Call TaskStop() first.
405 *
406 * \em Note: Partially transmitted buffers are up to the user to handle.
407 *
408 * Using this function on non-buffer descriptor tasks will produce
409 * unpredictable results.
410 */
411BDIdx TaskBDReset(TaskId taskId)
412{
413        BDIdx           i;
414        TaskBD_t        *bd, *bdTab;
415
416        if (TaskRunning[taskId]) {
417                return TASK_ERR_TASK_RUNNING;
418        }
419
420        bdTab = TaskBDIdxTable[taskId].BDTablePtr;
421
422        for (i = (BDIdx)TaskBDIdxTable[taskId].numBD - 1; i >= 0; --i) {
423
424                if (TaskBDIdxTable[taskId].numPtr == 1) {
425                        bd = (TaskBD_t *)&(((TaskBD1_t *)bdTab)[i]);
426                } else {
427                        bd = (TaskBD_t *)&(((TaskBD2_t *)bdTab)[i]);
428                }
429
430                bd->Status = 0x0;
431        }
432
433        TaskBDIdxTable[taskId].currBDInUse = 0;
434        *TaskBDIdxTable[taskId].BDStartPtr =
435                (volatile uint32)((volatile uint32)TaskBDIdxTable[taskId].BDTablePtr
436                                                + MBarPhysOffsetGlobal);
437        return BDHead[taskId] = BDTail[taskId] = 0;
438}
439
440
441/*!
442 * \brief       Return BestComm debug information.
443 * \param       taskId  Task handle passed back from a successful TaskSetup()
444 * \param       paramSet        TBD
445 * \returns     TBD
446 *
447 * The implementation of this function is yet to be determined.
448 */
449int TaskDebug(TaskId taskId, TaskDebugParamSet_t *paramSet)
450{
451        if ((taskId < 0) || (taskId >= MAX_TASKS)) {
452                return TASK_ERR_INVALID_ARG;
453        }
454        if (paramSet == NULL) {
455                return TASK_ERR_INVALID_ARG;
456        }
457
458        return TASK_ERR_NO_ERR;
459}
Note: See TracBrowser for help on using the repository browser.