source: tools/oebuild/data/pti_np/pti_buffer.c @ 45168

Last change on this file since 45168 was 45168, checked in by obi, 19 months ago

add oebuild building files

  • Property svn:executable set to *
File size: 12.2 KB
Line 
1/*
2 * Authors: Dagobert, Phantomias
3 * Buffer Pool Handling for the pti. We allocate two pools of buffer.
4 * One pool is for BIG buffersizes and one for SMALL (the amount is configurable).
5 *
6 * The buffer pools are located in the lim_sys.
7 *
8 * The Addreesing will be done by the constants PTI_POOL_BIG, PTI_POOL_SMALL.
9 * The buffer allocation whill be done in ts packet size (188 Bytes) and is
10 * alligned to the STPTI_BUFFER_SIZE_MULTIPLE (0x20).
11 */
12
13#include <asm/io.h>
14
15#include <linux/version.h>
16
17#if defined (CONFIG_KERNELVERSION) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
18#include <linux/bpa2.h>
19#else
20#include <linux/bigphysarea.h>
21#include <linux/bpa2.h>
22#endif
23
24#include "pti.h"
25#include "pti_buffer.h"
26#include "pti_main.h"
27
28static struct semaphore sem;
29static struct tBuffer *bufferArray;
30static int poolNumber;
31
32struct TCDMAConfigExt_s *TCDMAConfigExt_t;
33
34typedef struct
35{
36        int bufSize;
37        int freeBuffers;
38        struct tBuffer *pList;
39} tPool;
40
41static tPool *poolArray;
42
43static size_t adjustSize(size_t size)
44{
45        return ((size + STPTI_BUFFER_SIZE_MULTIPLE - 1) &
46                (~(STPTI_BUFFER_SIZE_MULTIPLE - 1)));
47}
48
49static void *alignAddress(void *pAddress)
50{
51        return (void *)(((u32) pAddress + STPTI_BUFFER_ALIGN_MULTIPLE - 1) &
52                        (~(STPTI_BUFFER_ALIGN_MULTIPLE - 1)));
53}
54
55// the function pushes the buffer on stack
56static void freeBuffer(tPool *pPool, struct tBuffer *pBuffer)
57{
58        if (pBuffer->inUse == 0)
59                printk("%s: FREEING UNUSED BUFFER\n", __func__);
60        if (down_interruptible(&sem))
61        {
62                printk("%s(): error taking semaphore\n", __func__);
63        }
64        pBuffer->inUse = 0;
65        pPool->freeBuffers++;
66        /* attach the buffer at the list head */
67        pBuffer->pNext = pPool->pList;
68        pPool->pList = pBuffer;
69        printk("%s(): free = %d\n", __func__, pPool->freeBuffers);
70        up(&sem);
71}
72
73// the function pops a buffer from stack
74static struct tBuffer *getBuffer(tPool *pPool)
75{
76        struct tBuffer *pBuffer;
77        if (down_interruptible(&sem))
78        {
79                printk("%s(): error taking semaphore\n", __func__);
80        }
81        printk("%s(): free = %d\n", __func__, pPool->freeBuffers);
82        /* get the pointer after locking the semaphore */
83        pBuffer = pPool->pList;
84        if (pPool->pList != NULL)
85        {
86                // update the buffer and the pool
87                if (pBuffer->inUse != 0)
88                        printk("%s: ALLOCATING USED BUFFER\n", __func__);
89                pBuffer->inUse = 1;
90                pPool->freeBuffers--;
91                pPool->pList = pBuffer->pNext;
92                /* invalidate the chain */
93                pBuffer->pNext = NULL;
94        }
95        up(&sem);
96        return pBuffer;
97}
98
99static void pti_init_dma(int tc_dma_index, u32 BufferPhys_p, int ActualSize)
100{
101        TCDMAConfig_t *DMAConfig_p = &((TCDMAConfig_t *)tc_params.TC_DMAConfigStart)[tc_dma_index];
102        u32 base = (u32)(BufferPhys_p);
103        u32 top = (u32)(base + ActualSize);
104        printk("DMA(%d) base = %x, top = %x, buffer = %x, size %d\n", tc_dma_index, base, top, BufferPhys_p, ActualSize);
105        TCDMAConfigExt_t[tc_dma_index].BasePtr_physical = base;
106        TCDMAConfigExt_t[tc_dma_index].TopPtr_physical = (top - 1) & ~0xf;
107        TCDMAConfigExt_t[tc_dma_index].pBuf = (u8 *) phys_to_virt(TCDMAConfigExt_t[tc_dma_index].BasePtr_physical);
108        TCDMAConfigExt_t[tc_dma_index].bufSize = (TCDMAConfigExt_t[tc_dma_index].TopPtr_physical - TCDMAConfigExt_t[tc_dma_index].BasePtr_physical) + 0x10;
109        TCDMAConfigExt_t[tc_dma_index].bufSize_sub_188 = TCDMAConfigExt_t[tc_dma_index].bufSize - 188;
110        TCDMAConfigExt_t[tc_dma_index].bufSize_div_188 = TCDMAConfigExt_t[tc_dma_index].bufSize / 188;
111        TCDMAConfigExt_t[tc_dma_index].bufSize_div_188_div_2 = TCDMAConfigExt_t[tc_dma_index].bufSize / 188 / 2;
112        writel(base, (void *)&DMAConfig_p->DMABase_p);
113        writel((top - 1) & ~0xf , (void *)&DMAConfig_p->DMATop_p);
114        writel(base, (void *)&DMAConfig_p->DMARead_p);
115        writel(base, (void *)&DMAConfig_p->DMAWrite_p);
116        writel(base, (void *)&DMAConfig_p->DMAQWrite_p);
117        writel(0 , (void *)&DMAConfig_p->BufferPacketCount);
118        /* Reset SignalModeFlags as this could have been a previously used DMA and the flags may be in an
119         * un-defined state
120         */
121        STSYS_ClearTCMask16LE((void *)&DMAConfig_p->SignalModeFlags, TC_DMA_CONFIG_SIGNAL_MODE_TYPE_MASK);
122        //TC_DMA_CONFIG_SIGNAL_MODE_TYPE_EVERY_TS, TC_DMA_CONFIG_SIGNAL_MODE_SWCDFIFO TC_DMA_CONFIG_SIGNAL_MODE_TYPE_QUANTISATION...
123        STSYS_SetTCMask16LE((void *)&DMAConfig_p->SignalModeFlags,
124                            TC_DMA_CONFIG_SIGNAL_MODE_TYPE_EVERY_TS |
125                            TC_DMA_CONFIG_OUTPUT_WITHOUT_META_DATA |
126                            TC_DMA_CONFIG_WINDBACK_ON_ERROR);
127        STSYS_WriteTCReg16LE((void *)&DMAConfig_p->Threshold, TC_DMA_THRESHOLD_LOW);
128        // disable signalling
129        STSYS_SetTCMask16LE((void *)&DMAConfig_p->SignalModeFlags, TC_DMA_CONFIG_SIGNAL_MODE_FLAGS_SIGNAL_DISABLE);
130}
131
132int pti_buffer_pool_init(int poolNum, int *pSizes, int *pCount)
133{
134        int i;
135        int bufSize;
136        u8 *pBuffer;
137        int pages;
138        int poolInd;
139        int totalBuffers = 0;
140        int offset = 0;
141        /* init the access semaphore */
142        sema_init(&sem, 1);
143        poolNumber = poolNum;
144        for (poolInd = 0; poolInd < poolNum; poolInd++)
145                totalBuffers += pCount[poolInd];
146        // allocate memory for all buffer control structures
147        // (avoids memory fragmentation)
148        bufferArray = kmalloc(sizeof(struct tBuffer) * totalBuffers, GFP_KERNEL);
149        memset(bufferArray, 0, sizeof(struct tBuffer) * totalBuffers);
150        // allocate memory for all pool control structures
151        // (avoids memory fragmentation)
152        poolArray = kmalloc(sizeof(tPool) * poolNum, GFP_KERNEL);
153        memset(poolArray, 0, sizeof(tPool) * poolNum);
154        // allocate memory for all Dma extra Bytes for speed up pti_task
155        TCDMAConfigExt_t = kmalloc(sizeof(struct TCDMAConfigExt_s) * totalBuffers, GFP_KERNEL);
156        memset(TCDMAConfigExt_t, 0, sizeof(struct TCDMAConfigExt_s) * totalBuffers);
157        for (poolInd = 0; poolInd < poolNum; poolInd++)
158        {
159                // init pool data
160                poolArray[poolInd].freeBuffers = 0;
161                poolArray[poolInd].bufSize = pSizes[poolInd];
162                poolArray[poolInd].pList = NULL;
163                // compute the buffer size including overhead and the corresponding
164                // number of pages
165                bufSize = adjustSize(pSizes[poolInd]);
166                pages = bufSize / PAGE_SIZE;
167                if (bufSize % PAGE_SIZE)
168                        pages++;
169                // initialize buffer control structures for this pool
170                for (i = 0; i < pCount[poolInd]; i++)
171                {
172                        int j = i + offset;
173                        // allocate big buffers at once
174                        pBuffer = bigphysarea_alloc_pages(pages, 0, GFP_KERNEL | __GFP_DMA);
175                        printk("pti: %s: allocate %d pages (%lu bytes)\n", __func__, pages, pages * PAGE_SIZE);
176                        if (pBuffer == NULL)
177                        {
178                                printk("%s(): failed to allocate buffer (%d, %d)\n",
179                                       __func__, bufSize, pages);
180                                break;
181                        }
182                        // store the requested buffer size
183                        bufferArray[j].bufSize = pSizes[poolInd];
184                        // partition the big buffer area
185                        bufferArray[j].pBuffer = pBuffer;
186#if defined (CONFIG_KERNELVERSION) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
187                        bufferArray[j].pAlignedBuffer = alignAddress((void *)virt_to_phys(pBuffer));
188#else
189                        bufferArray[j].pAlignedBuffer = alignAddress((void *)virt_to_bus(pBuffer));
190#endif
191                        bufferArray[j].pMappedBuffer = ioremap_nocache((int)bufferArray[j].pAlignedBuffer, bufSize);
192                        /* set the inUse flag before frreing the buffer */
193                        bufferArray[j].inUse = 1;
194                        // initialize DMA
195                        bufferArray[j].dmaIndex = j;
196                        bufferArray[j].threshold = TC_DMA_THRESHOLD_LOW;
197                        pti_init_dma(j, (u32) bufferArray[j].pAlignedBuffer, bufSize);
198                        // put into the pool
199                        printk("%s: put in pool dmaIndex %d\n", __func__, j);
200                        freeBuffer(&poolArray[poolInd], &bufferArray[j]);
201                }
202                // increment the offset within the buffer array
203                offset += i;
204        }
205        return 0;
206}
207
208struct tBuffer *pti_buffer_get(int size)
209{
210        int i;
211        struct tBuffer *pBuffer = NULL;
212        for (i = 0; i < poolNumber; i++)
213        {
214                if (poolArray != NULL)
215                {
216                        // check the buffer size
217                        if (poolArray[i].bufSize == size)
218                        {
219                                pBuffer = getBuffer(&poolArray[i]);
220                                break;
221                        }
222                }
223        }
224        printk("%s(%d) => %p\n", __func__, size, pBuffer);
225        if (pBuffer == NULL)
226        {
227                printk("%s(): NO FREE BUFFER (%d)\n", __func__, size);
228        }
229        else
230        {
231                TCDMAConfig_t *DMAConfig_p = &((TCDMAConfig_t *)tc_params.TC_DMAConfigStart)[pBuffer->dmaIndex];
232                u32 base = (u32)pBuffer->pAlignedBuffer;
233                u32 top = (u32)(base + pBuffer->bufSize);
234                if ((readl((void *)&DMAConfig_p->DMAWrite_p) != base) ||
235                                (readl((void *)&DMAConfig_p->BufferPacketCount) != 0))
236                {
237                        printk("\n%s(): inconsistent DMA settings %d\n\n", __func__, pBuffer->dmaIndex);
238                }
239                TCDMAConfigExt_t[pBuffer->dmaIndex].BasePtr_physical = base;
240                TCDMAConfigExt_t[pBuffer->dmaIndex].TopPtr_physical = (top - 1) & ~0xf;
241                TCDMAConfigExt_t[pBuffer->dmaIndex].pBuf = (u8 *) phys_to_virt(TCDMAConfigExt_t[pBuffer->dmaIndex].BasePtr_physical);
242                TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize = (TCDMAConfigExt_t[pBuffer->dmaIndex].TopPtr_physical - TCDMAConfigExt_t[pBuffer->dmaIndex].BasePtr_physical) + 0x10;
243                TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize_sub_188 = TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize - 188;
244                TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize_div_188 = TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize / 188;
245                TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize_div_188_div_2 = TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize / 188 / 2;
246                writel(base, (void *)&DMAConfig_p->DMABase_p);
247                writel((top - 1) & ~0xf , (void *)&DMAConfig_p->DMATop_p);
248                writel(base, (void *)&DMAConfig_p->DMARead_p);
249                writel(base, (void *)&DMAConfig_p->DMAWrite_p);
250                writel(base, (void *)&DMAConfig_p->DMAQWrite_p);
251                writel(0 , (void *)&DMAConfig_p->BufferPacketCount);
252                /* Reset SignalModeFlags as this could have been a previously used DMA and the flags may be in an
253                 * un-defined state
254                 */
255                STSYS_ClearTCMask16LE((void *)&DMAConfig_p->SignalModeFlags, TC_DMA_CONFIG_SIGNAL_MODE_TYPE_MASK);
256                //TC_DMA_CONFIG_SIGNAL_MODE_TYPE_EVERY_TS, TC_DMA_CONFIG_SIGNAL_MODE_SWCDFIFO TC_DMA_CONFIG_SIGNAL_MODE_TYPE_QUANTISATION...
257                STSYS_SetTCMask16LE((void *)&DMAConfig_p->SignalModeFlags,
258                                    TC_DMA_CONFIG_SIGNAL_MODE_TYPE_EVERY_TS |
259                                    TC_DMA_CONFIG_OUTPUT_WITHOUT_META_DATA |
260                                    TC_DMA_CONFIG_WINDBACK_ON_ERROR);
261                STSYS_WriteTCReg16LE((void *)&DMAConfig_p->Threshold, TC_DMA_THRESHOLD_LOW);
262                // disable signalling
263                STSYS_SetTCMask16LE((void *)&DMAConfig_p->SignalModeFlags, TC_DMA_CONFIG_SIGNAL_MODE_FLAGS_SIGNAL_DISABLE);
264        }
265        return pBuffer;
266}
267
268void pti_buffer_free(struct tBuffer *pBuffer)
269{
270        int i;
271        TCDMAConfig_t *DMAConfig_p = &((TCDMAConfig_t *)tc_params.TC_DMAConfigStart)[pBuffer->dmaIndex];
272#if defined (CONFIG_KERNELVERSION) /* ST Linux 2.3 */
273        printk("%s(%p, %d) - delta 0x%8x, thr 0x%x\n", __func__, pBuffer, pBuffer->bufSize,
274               readl((void *)&DMAConfig_p->DMAWrite_p) - readl((void *)&DMAConfig_p->DMABase_p), readw((void *)&DMAConfig_p->Threshold));
275#else
276        printk("%s(%p, %d) - delta 0x%8x, thr 0x%x\n", __func__, pBuffer, pBuffer->bufSize,
277               readl((void *)&DMAConfig_p->DMAWrite_p) - readl((void *)&DMAConfig_p->DMABase_p), readw((void *)&DMAConfig_p->Threshold));
278#endif
279        for (i = 0; i < poolNumber; i++)
280        {
281                if (poolArray[i].bufSize == pBuffer->bufSize)
282                {
283                        TCDMAConfig_t *DMAConfig_p = &((TCDMAConfig_t *)tc_params.TC_DMAConfigStart)[pBuffer->dmaIndex];
284                        u32 base = (u32)pBuffer->pAlignedBuffer;
285                        u32 top = (u32)(base + pBuffer->bufSize);
286                        STSYS_WriteTCReg16LE((void *)&DMAConfig_p->SignalModeFlags, TC_DMA_CONFIG_SIGNAL_MODE_FLAGS_SIGNAL_DISABLE);
287                        TCDMAConfigExt_t[pBuffer->dmaIndex].BasePtr_physical = base;
288                        TCDMAConfigExt_t[pBuffer->dmaIndex].TopPtr_physical = (top - 1) & ~0xf;
289                        TCDMAConfigExt_t[pBuffer->dmaIndex].pBuf = (u8 *) phys_to_virt(TCDMAConfigExt_t[pBuffer->dmaIndex].BasePtr_physical);
290                        TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize = (TCDMAConfigExt_t[pBuffer->dmaIndex].TopPtr_physical - TCDMAConfigExt_t[pBuffer->dmaIndex].BasePtr_physical) + 0x10;
291                        TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize_sub_188 = TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize - 188;
292                        TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize_div_188 = TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize / 188;
293                        TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize_div_188_div_2 = TCDMAConfigExt_t[pBuffer->dmaIndex].bufSize / 188 / 2;
294                        writel(base, (void *)&DMAConfig_p->DMABase_p);
295                        writel((top - 1) & ~0xf , (void *)&DMAConfig_p->DMATop_p);
296                        writel(base, (void *)&DMAConfig_p->DMARead_p);
297                        writel(base, (void *)&DMAConfig_p->DMAWrite_p);
298                        writel(base, (void *)&DMAConfig_p->DMAQWrite_p);
299                        writel(0 , (void *)&DMAConfig_p->BufferPacketCount);
300                        /* Reset SignalModeFlags as this could have been a previously used DMA and the flags may be in an
301                         * un-defined state
302                         */
303                        STSYS_WriteTCReg16LE((void *)&DMAConfig_p->Threshold, TC_DMA_THRESHOLD_LOW);
304                        freeBuffer(&poolArray[i], pBuffer);
305                        break;
306                }
307        }
308        if (i == poolNumber)
309                printk("%s(): NO POOL FOUND (%p, %d)\n", __func__, pBuffer, pBuffer->bufSize);
310}
311
Note: See TracBrowser for help on using the repository browser.