source: tools/oebuild/data/pti_np/pti_process.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.4 KB
Line 
1/*
2 * Data processing function.
3 *
4 */
5
6#include <linux/init.h>
7#include <linux/wait.h>
8#include <linux/module.h>
9
10#include <linux/version.h>
11
12#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
13#include <linux/semaphore.h>
14#else
15#include <asm/semaphore.h>
16#endif
17
18#include <asm/io.h>
19#include <asm/cacheflush.h>
20
21#include <dmxdev.h>
22#include <dvb_demux.h>
23#include <linux/dvb/dmx.h>
24
25#include "pti.h"
26#include "pti_main.h"
27#include "pti_hal.h"
28#include "ts_makros.h"
29
30#define U32 u32
31#define U16 u16
32#define U8 u8
33
34#ifdef WITH_CAMROUTING
35extern int camRouting;
36#endif
37extern int waitMS;
38#ifdef CONFIG_PRINTK
39extern int enableStatistic;
40#else
41extern int enableSysStatistic;
42#endif
43extern int max_pti_dma;
44extern struct TCDMAConfigExt_s *TCDMAConfigExt_t;
45
46static struct stpti *pti = NULL;
47extern void (*demultiplexDvbPackets)(struct dvb_demux *demux, const u8 *buf, int count);
48
49void setDmaThreshold(int a, int b)
50{
51}
52
53#ifdef CONFIG_PRINTK
54int pktCount;
55int prevPktCount;
56int maxDelta;
57int minDelta = 999999999;
58int loopCount = 0;
59int lastPktCount;
60#endif
61
62static wait_queue_head_t bufferHalfFull;
63
64void paceSwtsByPti(void)
65{
66        if (wait_event_interruptible(bufferHalfFull, 1))
67        {
68                printk("wait_event_interruptible failed\n");
69                return;
70        }
71}
72
73EXPORT_SYMBOL(paceSwtsByPti);
74
75#ifdef CONFIG_PRINTK
76struct pidStatistic_s
77{
78        int number;
79        unsigned long time;
80
81        unsigned long complete;
82        unsigned int rate;
83
84        unsigned int min_rate;
85        unsigned int max_rate;
86
87        u8 lastCC;
88        u8 ccError;
89};
90
91struct pidStatistic_s pidS[0xffff];
92
93void ptiStatistic(int num, u8 *pBuf)
94{
95        int i;
96        u8 cc;
97        /* walk over the packets, count each pid and remeber the current time */
98        for (i = 0; i < num; i++)
99        {
100                u16 pid = ts_pid(pBuf + (i * 188));
101                pidS[pid].number++;
102                pidS[pid].complete++;
103                if ((pidS[pid].time == 0) || (time_after(jiffies, pidS[pid].time + HZ /* 1 sekunde vorbei ? */)))
104                {
105                        pidS[pid].time = jiffies;
106                        pidS[pid].rate = pidS[pid].number;
107                        pidS[pid].number = 0;
108                        if ((pidS[pid].rate > pidS[pid].max_rate) || (pidS[pid].max_rate == 0))
109                                pidS[pid].max_rate = pidS[pid].rate;
110                        if ((pidS[pid].rate < pidS[pid].min_rate) || (pidS[pid].min_rate == 0))
111                                pidS[pid].min_rate = pidS[pid].rate;
112                }
113                cc = ts_cc(pBuf + (i * 188));
114                if (pidS[pid].lastCC != 255)
115                {
116                        if ((pidS[pid].lastCC + 1) % 0x10 != cc)
117                        {
118                                pidS[pid].ccError++;
119                                printk("cc error last %d exp %d got %d\n", pidS[pid].lastCC, (pidS[pid].lastCC + 1) % 0x10, cc);
120                        }
121                }
122                pidS[pid].lastCC = cc;
123        }
124}
125
126void ptiStatisticClean(void)
127{
128        int i;
129        for (i = 0; i < 0xffff; i++)
130        {
131                if ((time_after(jiffies, pidS[i].time + (HZ * 5) /* 5 sekunde vorbei ? */)))
132                {
133                        pidS[i].rate = 0;
134                        pidS[i].min_rate = 0;
135                        pidS[i].max_rate = 0;
136                        pidS[i].complete = 0;
137                        pidS[i].number = 0;
138                        pidS[i].time = 0;
139                        pidS[i].lastCC = 255;
140                        pidS[i].ccError = 0;
141                }
142        }
143}
144
145void ptiStatisticOut(void)
146{
147        int i;
148        for (i = 0; i < 0xffff; i++)
149        {
150                if (pidS[i].rate != 0)
151                        printk("pidstatistic: pid 0x%x, rate = %d packets/s (complete %lu) %d Mbps/s, min %d/s - max %d/s, CC error %d\n", i,
152                               pidS[i].rate, pidS[i].complete, (pidS[i].rate * 188 * 8) / (1024 * 1024), pidS[i].min_rate, pidS[i].max_rate, pidS[i].ccError);
153        }
154}
155#else
156extern unsigned long pti_last_time;
157extern unsigned long pti_count;
158
159void ptiStatistic(int num)
160{
161        pti_last_time = jiffies;
162        pti_count += num;
163}
164#endif
165
166#define TSM_STREAM_CONF(n) (n * 0x20)
167#define TSM_SERIAL_NOT_PARALLEL (1 << 0)
168#define TSM_SYNC_NOT_ASYNC (1 << 1)
169#define TSM_ALIGN_BYTE_SOP (1 << 2)
170#define TSM_ASYNC_SOP_TOKEN (1 << 3)
171#define TSM_INVERT_BYTECLK (1 << 4)
172#define TSM_ADD_TAG_BYTES (1 << 5)
173#define TSM_REPLACE_ID_TAG (1 << 6)
174#define TSM_STREAM_ON (1 << 7)
175#define TSM_RAM_ALLOC_START(size) ((size & 0xff) << 8)
176#define TSM_PRIORITY(priority) ((priority & 0xf) << 16)
177
178#define TSM_STREAM_STATUS(n) ((n * 0x20) + 0x10)
179#define TSM_STREAM_LOCK (1 << 0)
180#define TSM_INPUTFIFO_OVERFLOW (1 << 1)
181#define TSM_RAM_OVERFLOW (1 << 2)
182#define TSM_ERRONEOUS_PACKETS(value) ((value >> 3) & 0x1f)
183#define TSM_STRAM_COUNTER_VALUE(value) ((value >> 8) & 0xffffff)
184
185#define TSM_STREAM_CONF2(n) ((n * 0x20) + 0x18)
186#define TSM_CHANNEL_RESET (1 << 0)
187#define TSM_DISABLE_MID_PACKET_ERROR (1 << 1)
188#define TSM_DISABLE_START_PACKET_ERROR (1 << 2)
189#define TSM_SHORT_PACKET_COUNT (value) ((value >> 27) & 0x3f)
190
191unsigned long reg_tsm_config = 0;
192
193void stm_tsm_interrupt(void)
194{
195        int n;
196        for (n = 0; n < 5; n++)
197        {
198                int status = readl(reg_tsm_config + TSM_STREAM_STATUS(n));
199                int on = readl(reg_tsm_config + TSM_STREAM_CONF(n)) & TSM_STREAM_ON;
200                if (!on)
201                        continue;
202                if (status & TSM_RAM_OVERFLOW)
203                {
204                        /* ack the overflow */
205                        writel(status & ~TSM_RAM_OVERFLOW, reg_tsm_config + TSM_STREAM_STATUS(n));
206                        /* printk("%s: TSMerger RAM Overflow on channel %d(%x), deploying work around\n",__FUNCTION__,n,status); */
207                        printk("OFLOW(%d) ", n);
208                }
209                else if (status & TSM_INPUTFIFO_OVERFLOW)
210                {
211                        /* ack the overflow */
212                        writel(status & ~TSM_INPUTFIFO_OVERFLOW, reg_tsm_config + TSM_STREAM_STATUS(n));
213                        printk("I-OFLOW(%d) ", n);
214                }
215        }
216}
217
218inline static void processDmaChannel(int tc_dma_index,
219                                     U32 ReadPtr_physical,
220                                     U32 WritePtr_physical,
221                                     TCDMAConfig_t *DMAConfig_p)
222{
223        struct dvb_demux *demux = pti_hal_get_demux_from_dma_index(tc_dma_index);
224        /* calculate the write index in the buffer */
225        U32 WriteInd = (WritePtr_physical - TCDMAConfigExt_t[tc_dma_index].BasePtr_physical);
226        /* calculate the read index in the buffer */
227        U32 ReadInd = (ReadPtr_physical - TCDMAConfigExt_t[tc_dma_index].BasePtr_physical);
228        /* calculate the read pointer */
229        U8 *pBuf_add_ReadInd = (TCDMAConfigExt_t[tc_dma_index].pBuf + ReadInd);
230        /* decrease the index by one packet because it might be rolled back or
231         * be incomplete
232
233         * ***: laut meinen debugs sind nie unvollstaendige Pakete gekommen.
234         * Ausserdem wuerde dem demuxer nicht vollstaendige Pakete uebergeben werden,
235         * was dieser dann verwirft, daher auf 188 ausrichten.
236         */
237        if (WriteInd >= 188)
238                WriteInd -= 188; // normal case
239        else
240                WriteInd = TCDMAConfigExt_t[tc_dma_index].bufSize_sub_188; //after a wraparound (e.g. WriteInd = 0)
241        // align to 188
242        WriteInd = (WriteInd / 188) * 188;
243#ifdef CONFIG_PRINTK
244        prevPktCount = pktCount;
245#endif
246        /* validate pointers, even if they are invalid we want to process
247         status blocks */
248        if ((TCDMAConfigExt_t[tc_dma_index].pBuf != NULL) && (demux != NULL))
249        {
250                struct DeviceContext_s *pContext = (struct DeviceContext_s *)demux->priv;
251                int num = 0;
252                if (WriteInd < ReadInd)
253                {
254                        int bytenum = (TCDMAConfigExt_t[tc_dma_index].bufSize - ReadInd);
255                        int num1 = bytenum / 188;
256                        int num2 = WriteInd / 188;
257                        num = num1 + num2;
258#ifdef CONFIG_PRINTK
259                        pktCount += num;
260#endif
261                        if (demultiplexDvbPackets != NULL)
262                        {
263#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
264//                              __flush_invalidate_region(pBuf_add_ReadInd, bytenum);
265                                invalidate_ioremap_region(0, pBuf_add_ReadInd, 0, bytenum);
266#else
267                                dma_cache_inv(pBuf_add_ReadInd, bytenum);
268#endif
269                                demultiplexDvbPackets(demux, pBuf_add_ReadInd, num1); // process packets before wraparound
270#ifdef CONFIG_PRINTK
271                                if (enableStatistic)
272                                        ptiStatistic(num1, pBuf_add_ReadInd);
273#else
274                                if (enableSysStatistic)
275                                        ptiStatistic(num1);
276#endif
277#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
278//                              __flush_invalidate_region(TCDMAConfigExt_t[tc_dma_index].pBuf, WriteInd);
279                                invalidate_ioremap_region(0, TCDMAConfigExt_t[tc_dma_index].pBuf, 0, WriteInd);
280#else
281                                dma_cache_inv(TCDMAConfigExt_t[tc_dma_index].pBuf, WriteInd);
282#endif
283                                demultiplexDvbPackets(demux, TCDMAConfigExt_t[tc_dma_index].pBuf, num2); // process packets after wraparound
284#ifdef CONFIG_PRINTK
285                                if (enableStatistic)
286                                        ptiStatistic(num2, TCDMAConfigExt_t[tc_dma_index].pBuf);
287#else
288                                if (enableSysStatistic)
289                                        ptiStatistic(num2);
290#endif
291                        }
292                        //printk("+");
293                }
294                else
295                {
296                        int bytenum = (WriteInd - ReadInd);
297                        num = bytenum / 188;
298#ifdef CONFIG_PRINTK
299                        pktCount += num;
300#endif
301                        if (demultiplexDvbPackets != NULL)
302                        {
303#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
304//                              __flush_invalidate_region(pBuf_add_ReadInd, bytenum);
305                                invalidate_ioremap_region(0, pBuf_add_ReadInd, 0, bytenum);
306#else
307                                dma_cache_inv(pBuf_add_ReadInd, bytenum);
308#endif
309                                demultiplexDvbPackets(demux, pBuf_add_ReadInd, num);
310#ifdef CONFIG_PRINTK
311                                if (enableStatistic)
312                                        ptiStatistic(num, pBuf_add_ReadInd);
313#else
314                                if (enableSysStatistic)
315                                        ptiStatistic(num);
316#endif
317                        }
318                        //printk(".");
319                }
320                /* if the input is the DVR device the data is played
321                 back via SWTS to enable passing the playback data
322                 though the hardware descrambler */
323                if (pContext->pPtiSession->source == DMX_SOURCE_DVR0)
324                {
325                        if (num < TCDMAConfigExt_t[tc_dma_index].bufSize_div_188_div_2)
326                        {
327                                /* Buffer is less than half-empty, enable the semaphore.
328                                 Enforce binary semaphore behavior, otherwise the caller
329                                 wouldn't block when necessary. */
330                                wake_up_interruptible(&bufferHalfFull);
331                        }
332                        //printk("pti_task: %d\n", num);
333                }
334        }
335        //printk("pti_task: RI %d, BA %x\n", ReadInd, DMAConfig_p->BasePtr_physical);
336#ifdef CONFIG_PRINTK
337        if ((pktCount - prevPktCount) > maxDelta)
338        {
339                maxDelta = pktCount - prevPktCount;
340        }
341        if ((pktCount - prevPktCount) < minDelta)
342        {
343                minDelta = pktCount - prevPktCount;
344        }
345        loopCount++;
346        if (!(loopCount % 50) && (enableStatistic))
347        {
348                printk("statistic: pktCount %d last packets %d minDelta %d maxDelta %d\n", pktCount, pktCount - lastPktCount, minDelta, maxDelta);
349                ptiStatisticOut();
350                ptiStatisticClean();
351                lastPktCount = pktCount;
352                minDelta = 999999999;
353                maxDelta = 0;
354        }
355#endif
356        /*
357         * acknowledge all packets in the block
358
359         * ***: wird das abschneiden und ausrichten des WriteInd deaktiviert,
360         * so kann WritePtr_physical verwendet werden.
361         */
362        writel(TCDMAConfigExt_t[tc_dma_index].BasePtr_physical + WriteInd, (void *) &DMAConfig_p->DMARead_p);
363}
364
365#define SysConfigBaseAddress 0x19001000
366#define SYS_CFG0 0x100
367#define SYS_CFG1 0x104
368
369#if defined(CONFIG_CPU_SUBTYPE_STX7111) || defined(CONFIG_CPU_SUBTYPE_STX7105)
370#define TSMergerBaseAddress 0xFE242000
371#else
372#define TSMergerBaseAddress 0x19242000
373#endif
374
375#define TSM_1394_CFG 0x0810
376#define TSM_PTI_SEL 0x0200
377#define TSM_1394_DEST 0x0210
378
379unsigned long reg_sys_config = 0;
380
381int pti_task(void *data)
382{
383        TCDMAConfig_t *DMAConfig_p;
384        int vLoopDMAs;
385        U32 WritePtr_physical;
386        U32 ReadPtr_physical;
387        int time_to_wait = msecs_to_jiffies(waitMS);
388#ifdef CONFIG_PRINTK
389        int count = 0;
390#endif
391        pti = (struct stpti *) data;
392        daemonize("pti_task");
393        //set highest prio
394        set_user_nice(current, -20);
395        printk("pti_task: using %d dma channel\n", max_pti_dma);
396        init_waitqueue_head(&pti->queue);
397        init_waitqueue_head(&bufferHalfFull);
398        while (1)
399        {
400                wait_event_timeout(pti->queue, 0, time_to_wait);
401#ifndef CONFIG_PRINTK
402                //update pti time
403                if (enableSysStatistic)
404                        ptiStatistic(0);
405#endif
406#ifdef CONFIG_PRINTK
407                count++;
408                if (count > 500)
409                {
410                        printk("\n");
411                        count = 0;
412                        pti_hal_output_slot_state();
413                }
414#endif
415                /* pti_hal_output_slot_state(); */
416                /* Dagobert: configure the stream routing in accordance to
417                 * the scrambled state. route stream only through cimax
418                 * if screem is scrambled, otherwise directly to pti
419                 */
420                reg_tsm_config = (unsigned long) ioremap(TSMergerBaseAddress, 0x0900);
421#ifdef CONFIG_PRINTK
422                stm_tsm_interrupt();
423#endif
424#ifdef WITH_CAMROUTING
425                if (camRouting == 1)
426                {
427                        int state;
428                        if ((state = pti_hal_get_scrambled()) != -1)
429                        {
430                                u32 reg;
431                                if (reg_sys_config == 0)
432                                {
433                                        reg_sys_config = (unsigned long) ioremap(SysConfigBaseAddress, 0x0900);
434                                }
435                                reg = ctrl_inl(reg_tsm_config + TSM_1394_CFG);
436                                if (state == 1)
437                                {
438                                        ctrl_outl(0x6, reg_sys_config + SYS_CFG0);
439                                        ctrl_outl(reg | 0x20000 , reg_tsm_config + TSM_1394_CFG);
440                                        ctrl_outl(0xe , reg_tsm_config + TSM_PTI_SEL);
441                                        ctrl_outl(0x1 , reg_tsm_config + TSM_1394_DEST);
442                                }
443                                else
444                                {
445                                        ctrl_outl(0x2, reg_sys_config + SYS_CFG0);
446                                        ctrl_outl(reg & ~ 0x20000 , reg_tsm_config + TSM_1394_CFG);
447                                        ctrl_outl(0xf , reg_tsm_config + TSM_PTI_SEL);
448                                        ctrl_outl(0x0 , reg_tsm_config + TSM_1394_DEST);
449                                }
450                        }
451                }
452#endif
453                for (vLoopDMAs = 0; vLoopDMAs < /* TC_Params_p->TC_NumberDMAs*/ max_pti_dma; vLoopDMAs++)
454                {
455                        DMAConfig_p = &((TCDMAConfig_t *)tc_params.TC_DMAConfigStart)[vLoopDMAs];
456                        ReadPtr_physical = readl((void *) &DMAConfig_p->DMARead_p);
457                        WritePtr_physical = readl((void *) &DMAConfig_p->DMAWrite_p);
458#if 0
459                        if (vLoopDMAs == 1)
460                                printk("r%x w%x ", ReadPtr_physical, WritePtr_physical);
461#endif
462                        if (ReadPtr_physical != WritePtr_physical)
463                        {
464                                processDmaChannel(vLoopDMAs, ReadPtr_physical, WritePtr_physical, DMAConfig_p);
465                        }
466                }
467        } /* while true */
468        printk("######## PTI task terminated\n");
469        // TODO: stop dma
470}
471
Note: See TracBrowser for help on using the repository browser.