source: svn/newcon3bcm2_21bu/magnum/syslib/pvrlib/bpvrlib_feed.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 33.9 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2007 Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bpvrlib_feed.c $
11 * $brcm_Revision: Hydra_Software_Devel/32 $
12 * $brcm_Date: 9/2/11 3:01p $
13 *
14 * Module Description:
15 *
16 * PVR library, playback feeder module
17 * Revision History:
18 *
19 * $brcm_Log: /magnum/syslib/pvrlib/bpvrlib_feed.c $
20 *
21 * Hydra_Software_Devel/32   9/2/11 3:01p vsilyaev
22 * SW7425-433: Better account for reserved descriptor in returned status
23 *
24 * Hydra_Software_Devel/31   4/26/11 4:11p vsilyaev
25 * SW7425-433: Don't allow reuse of the 'reserved' playback HW descriptor
26 *
27 * Hydra_Software_Devel/30   4/25/11 1:34p vsilyaev
28 * SW7425-433: Demoted debug message
29 *
30 * Hydra_Software_Devel/29   4/5/11 4:20p vsilyaev
31 * SW7405-5216: Use XPT defined defint to tag specific workaround
32 *
33 * Hydra_Software_Devel/28   3/8/11 12:24p vsilyaev
34 * SW7425-93: Flush cache while saving data and use better offset->address
35 * conversion
36 *
37 * Hydra_Software_Devel/27   12/29/10 3:04p vsilyaev
38 * SW7425-39: Fixed BPVRlib_Feed_GetStatus with enabled extended
39 * descriptors
40 *
41 * Hydra_Software_Devel/26   12/13/10 6:59p vsilyaev
42 * SW7425-39: Added support for MUX input
43 *
44 * Hydra_Software_Devel/25   1/25/10 12:50p vsilyaev
45 * SW7405-3822: Updated to use right offset in the BPVRlib_Feed_AddEntries
46 *
47 * Hydra_Software_Devel/24   7/16/09 11:32a vsilyaev
48 * PR 55361: Fixed data capturing
49 *
50 * Hydra_Software_Devel/23   5/22/09 5:03p vsilyaev
51 * PR 51821 PR 54925 PR 55054: Detect and handle the 'false' finished
52 * state, allocate and hide one extra descriptor
53 *
54 * Hydra_Software_Devel/22   5/21/09 4:57p vsilyaev
55 * PR 51821 PR 54925 PR 55054: Don't reset descriptors FIFO when HW
56 * Playback is completed
57 *
58 * Hydra_Software_Devel/21   5/21/09 1:33p vsilyaev
59 * PR 55361: Added code to capture data after it was submitted to HW and
60 * after HW completed DMA
61 *
62 * Hydra_Software_Devel/20   2/9/09 5:36p vsilyaev
63 * PR50211 PR46250 PR45133 PR45435 PR44649: Relaxed condiitions to test
64 * for alligment with the playback descriptor
65 *
66 * Hydra_Software_Devel/19   1/26/09 11:12a vsilyaev
67 * PR50211 PR46250 PR45133 PR45435 PR44649: Fixed condition for the
68 * address match
69 *
70 * Hydra_Software_Devel/18   1/26/09 9:42a vsilyaev
71 * PR50211 PR46250 PR45133 PR45435 PR44649: Reduce cases where S/G
72 * descriptor is updated and when it's updated preserve payload wherever
73 * is possible
74 *
75 * Hydra_Software_Devel/17   1/23/09 9:01a gmohile
76 * PR 50211 : Revert small desc bug fix for 7405 B0
77 *
78 * Hydra_Software_Devel/16   1/22/09 4:23p gmohile
79 * PR 50211 : Disable use of small desc bug for 7405 B0
80 *
81 * Hydra_Software_Devel/15   10/28/08 1:15p vsilyaev
82 * PR 45490: Fixed use of B_PVRLIB_SMALL_DESC
83 *
84 * Hydra_Software_Devel/14   10/17/08 1:18p vsilyaev
85 * PR 45490: Fixed typo
86 *
87 * Hydra_Software_Devel/13   10/17/08 11:03a vsilyaev
88 * PR 45490: Removed B_PVRLIB_SMALL_DESC for 3548/3556 B0+
89 *
90 * Hydra_Software_Devel/12   9/3/08 6:20p vsilyaev
91 * PR46250 PR45133 PR45435 PR44649: Print a warning and substitute size of
92 * S/G entry not compatible with HW
93 *
94 * Hydra_Software_Devel/11   8/5/08 5:32p vsilyaev
95 * PR 45435: Print a warning of first or last descriptor has size of 0
96 *
97 * Hydra_Software_Devel/10   4/16/08 6:57p mward
98 * PR39994: Use BXPT_Playback_GetIntId().
99 *
100 * Hydra_Software_Devel/9   4/8/08 4:03p erickson
101 * PR39453: add 3548 & 3556
102 *
103 * Hydra_Software_Devel/8   12/5/07 10:33a katrep
104 * PR37217: Added support for 7335.
105 *
106 * Hydra_Software_Devel/7   11/1/07 9:40a erickson
107 * PR36570: added 3563
108 *
109 * Hydra_Software_Devel/6   10/31/07 4:44p jrubio
110 * PR35015: adding 7325 support
111 *
112 * Hydra_Software_Devel/5   8/17/07 10:19a vsilyaev
113 * PR 33751: Deallocate uncached address
114 *
115 * Hydra_Software_Devel/4   8/6/07 1:49p katrep
116 * PR27643: 7405 has 5 playback inputs.
117 *
118 * Hydra_Software_Devel/3   8/2/07 5:36p vsilyaev
119 * PR 33751: Improved documentation of bpvrlib_feed module
120 *
121 * Hydra_Software_Devel/2   8/2/07 4:49p vsilyaev
122 * PR 33751: Reduced stack use
123 *
124 * Hydra_Software_Devel/1   8/2/07 4:18p vsilyaev
125 * PR 33751:
126 *
127 * 
128 ***************************************************************************/
129#include "bstd.h"
130#include "bkni.h"
131#include "bpvrlib_feed.h"
132
133/* to import TRANS_DESC flags */
134#include "bxpt_priv.h"
135#if BXPT_HAS_TSMUX
136#include "bxpt_tsmux.h"
137#endif
138
139BDBG_MODULE(bpvrlib_feed);
140
141#define BDBG_MSG_TRACE(x)   /* BDBG_MSG(x) */
142
143/* save data prior to sending data into the XPT playback */
144#define B_PVR_LIB_FEED_SAVE_BEFORE 0
145/* save data after XPT playback completed transfer */
146#define B_PVR_LIB_FEED_SAVE_AFTER 0
147#define B_PVR_LIB_FEED_CONTEXT_NAME 0
148
149BDBG_OBJECT_ID(BPVRlib_Feed);
150
151#if B_PVR_LIB_FEED_SAVE_BEFORE || B_PVR_LIB_FEED_SAVE_AFTER
152#include <stdio.h>
153typedef struct b_pvr_feed_save{
154    FILE *fout;
155    unsigned no;
156    const char *name;
157} b_pvr_feed_save;
158
159static void b_pvr_feed_save_init(b_pvr_feed_save *save, const char *name)
160{
161    save->name = name;
162    save->fout = NULL;
163    save->no = 0;
164    return;
165}
166
167static void b_pvr_feed_save_open(b_pvr_feed_save *save)
168{
169    char name[64];
170    BKNI_Snprintf(name, sizeof(name), 
171#if B_PVR_LIB_FEED_CONTEXT_NAME
172  "videos/bpvrlib_feed_%#x_%s_%u.mpg", save,
173#else
174  "videos/bpvrlib_feed_%s_%u.mpg", 
175#endif
176    save->name, save->no);
177    save->fout = fopen(name, "w+b");
178    return;
179}
180
181static void b_pvr_feed_save_close(b_pvr_feed_save *save)
182{
183    if(save->fout) {
184        fclose(save->fout);
185        save->fout = NULL;
186        save->no++;
187    }
188    return;
189}
190
191static void b_pvr_feed_save_data(b_pvr_feed_save *save, const void *data, size_t len)
192{
193   if(save->fout) {
194       BDBG_MSG(("D: %-8s: %#x:%u", save->name, (unsigned)data, (unsigned)len)); 
195       fwrite(data, len, 1, save->fout);
196   }
197   return;
198}
199
200static void b_pvr_feed_save_data_offset(BMEM_Heap_Handle  heap, b_pvr_feed_save *save, uint32_t data, size_t len)
201{
202    void *addr;
203    void *cachedAddr;
204    BERR_Code rc;
205
206    rc = BMEM_Heap_ConvertOffsetToAddress(heap, data, &addr);
207    BDBG_ASSERT(rc==BERR_SUCCESS);
208    BDBG_ASSERT(addr!=0);
209    rc = BMEM_Heap_ConvertAddressToCached(heap, addr, &cachedAddr);   
210    BDBG_ASSERT(cachedAddr!=0);
211    BDBG_ASSERT(rc==BERR_SUCCESS);
212    BMEM_Heap_FlushCache(heap, cachedAddr, len);
213    b_pvr_feed_save_data(save, cachedAddr, len);
214}
215
216
217#endif /* B_PVR_LIB_FEED_SAVE_BEFORE || B_PVR_LIB_FEED_SAVE_AFTER */
218
219#define B_PVRLIB_SMALL_DESC_BUG   BXPT_2_BYTE_MINIMUM_PLAYBACK_BUFFER
220
221#define BFIFO_HEAD(name, type) struct name { type *bf_base; type *bf_last; type *bf_read; type *bf_write; int bf_wrap; }
222
223#define BFIFO_INIT(fifo, base, size) do {(fifo)->bf_wrap=0; \
224    (fifo)->bf_base=(fifo)->bf_read=(fifo)->bf_write=(base);\
225    (fifo)->bf_last=(fifo)->bf_base+(size);}while(0)
226
227#define BFIFO_WRITE(fifo) (fifo)->bf_write
228#define BFIFO_READ(fifo) (fifo)->bf_read
229
230#define BFIFO_WRITE_PEEK(fifo) \
231    /* |====W---R===| */ ((unsigned)(((fifo)->bf_write < (fifo)->bf_read) ? (fifo)->bf_read - (fifo)->bf_write : ( \
232    /* |---R===W---| */ ((fifo)->bf_write > (fifo)->bf_read) ? (fifo)->bf_last - (fifo)->bf_write  : ( \
233    /* |---RW---| */ (fifo)->bf_wrap ? 0 : (fifo)->bf_last - (fifo)->bf_write))))
234
235#define BFIFO_READ_PEEK(fifo) \
236    /* |====W---R===| */ ((unsigned)(((fifo)->bf_write < (fifo)->bf_read) ? (fifo)->bf_last - (fifo)->bf_read : ( \
237    /* |---R===W---| */ ((fifo)->bf_write > (fifo)->bf_read) ? (fifo)->bf_write - (fifo)->bf_read : ( \
238    /* |---RW---| */ (fifo)->bf_wrap ? (fifo)->bf_last - (fifo)->bf_read:0))))
239
240#define BFIFO_WRITE_COMMIT(fifo, size) do { \
241    BDBG_ASSERT((size)>0 && BFIFO_WRITE_PEEK(fifo) >= (size));  \
242    (fifo)->bf_write += (size); \
243    if ((fifo)->bf_write >= (fifo)->bf_last) {(fifo)->bf_write = (fifo)->bf_base;(fifo)->bf_wrap++;}  \
244    } while(0)
245
246#define BFIFO_READ_COMMIT(fifo, size) do { \
247    BDBG_ASSERT(BFIFO_READ_PEEK(fifo) >= (unsigned)(size)); \
248    (fifo)->bf_read += (size); \
249    if ((fifo)->bf_read >= (fifo)->bf_last) {(fifo)->bf_read = (fifo)->bf_base;(fifo)->bf_wrap--;}  \
250    } while(0)
251
252#define BFIFO_WRITE_LEFT(fifo)  \
253    /* |====W---R===| */ (((fifo)->bf_write < (fifo)->bf_read) ? (fifo)->bf_read - (fifo)->bf_write : ( \
254    /* |---R===W---| */ ((fifo)->bf_write > (fifo)->bf_read) ? ((fifo)->bf_read - (fifo)->bf_base) + ((fifo)->bf_last - (fifo)->bf_write)  : ( \
255    /* |---RW---| */ (fifo)->bf_wrap ? 0 : (fifo)->bf_last - (fifo)->bf_base)))
256
257#define BFIFO_READ_LEFT(fifo) \
258    /* |====W---R===| */ (((fifo)->bf_write < (fifo)->bf_read) ? ((fifo)->bf_write - (fifo)->bf_base) + (fifo)->bf_last - (fifo)->bf_read : ( \
259    /* |---R===W---| */ ((fifo)->bf_write > (fifo)->bf_read) ? (fifo)->bf_write - (fifo)->bf_read : ( \
260    /* |---RW---| */ (fifo)->bf_wrap ? (fifo)->bf_last - (fifo)->bf_base:0)))
261
262#define BFIFO_VALIDATE(fifo) do { \
263        BDBG_ASSERT((fifo)->bf_wrap==0 || (fifo)->bf_wrap==1); \
264        BDBG_ASSERT((fifo)->bf_read>=(fifo)->bf_base && (fifo)->bf_read<(fifo)->bf_last); \
265        BDBG_ASSERT((fifo)->bf_write>=(fifo)->bf_base && (fifo)->bf_write<(fifo)->bf_last); \
266    } while(0)
267
268#define BFIFO_STATUS(DBG, header,fifo)  DBG((header ":(%#lx:%#lx) write (%u/%u/%#lx), read (%u/%u/%#lx)", (unsigned long)(fifo)->bf_base, (unsigned long)(fifo)->bf_last, BFIFO_WRITE_PEEK(fifo), BFIFO_WRITE_LEFT(fifo), (unsigned long)BFIFO_WRITE(fifo), BFIFO_READ_PEEK(fifo), BFIFO_READ_LEFT(fifo), (unsigned long)BFIFO_READ(fifo)))
269
270BFIFO_HEAD(B_PVRlib_DescrFifo, BXPT_PvrDescriptor);
271
272
273/* nc_ stands for Non Cached address, all other pointers are cached */
274struct BPVRlib_Feed {
275    BDBG_OBJECT(BPVRlib_Feed)
276    bool active; /* set to true if hardware sending data */
277    bool finished; /* true if finished bit is set */
278    bool false_finished; /* true if finished bit is set and new descriptor was added, finished bit then might belong to the previous descriptor */
279    const BXPT_PvrDescriptor *prev_hw_finished_desc; /* previous descriptor that was active in the hardware */
280    const BXPT_PvrDescriptor *last_desc; /* last descriptor submitted to hardware */
281    struct B_PVRlib_DescrFifo descFifo;
282    size_t  ncompleted;
283    BXPT_PvrDescriptor *desc;
284    BXPT_PvrDescriptor *nc_desc;
285    uint32_t off_desc; /* device offset for the descriptor */
286    BPVRlib_Feed_Settings config;
287    BINT_CallbackHandle hPlayInt;   /* cb Handle for playback interrupt */
288    BXPT_PvrDescriptor dummy_descr;
289    unsigned descScale;
290#if B_PVRLIB_SMALL_DESC_BUG   
291#define B_PVRLIB_BOUNCE_BUF_SIZE    256
292#define B_PVRLIB_SMALL_ADDR_TEST(a1,a2) (((a1)&0x1F) == ((a2)&0x1F) || ((a2)&0xF)==0)
293    uint8_t *bounce_buffer;
294    uint32_t bounce_offset;
295    size_t bounce_ptr;
296    uint32_t last_data_addr;
297#else
298#define B_PVRLIB_BOUNCE_BUF_SIZE    0
299#endif
300    BPVRlib_Feed_OffsetEntry offset_entries[8];
301#if B_PVR_LIB_FEED_SAVE_BEFORE || B_PVR_LIB_FEED_SAVE_AFTER
302    struct {
303#if B_PVR_LIB_FEED_SAVE_BEFORE
304        b_pvr_feed_save before;
305#endif
306#if B_PVR_LIB_FEED_SAVE_AFTER
307        b_pvr_feed_save after;
308#endif
309    } save;
310#endif
311};
312
313static void BPVRlib_Feed_Priv_Update(BPVRlib_Feed_Handle feed);
314
315void 
316BPVRlib_Feed_GetDefaultSettings(BPVRlib_Feed_Settings *config)
317{
318    BKNI_Memset(config, 0, sizeof(*config));
319    return;
320}
321
322static void 
323BPVRlib_Feed_Priv_Reset(BPVRlib_Feed_Handle feed)
324{
325    feed->ncompleted = 0;
326    feed->active = false;
327    feed->false_finished = false;
328    feed->finished = false;
329    feed->last_desc = NULL;
330    feed->prev_hw_finished_desc = NULL;
331    BFIFO_INIT(&feed->descFifo, feed->desc, feed->config.numDesc*feed->descScale);
332#if B_PVRLIB_SMALL_DESC_BUG   
333    feed->bounce_buffer = (uint8_t *)feed->nc_desc + feed->descScale*sizeof(*feed->desc)*feed->config.numDesc;
334    feed->bounce_offset = feed->off_desc + feed->descScale*sizeof(*feed->desc)*feed->config.numDesc;
335    feed->bounce_ptr = 0;
336    feed->last_data_addr = 0;
337#endif
338    return;
339}
340
341BERR_Code
342BPVRlib_Feed_Open(BPVRlib_Feed_Handle *pfeed, const BPVRlib_Feed_Settings *config)
343{
344    BERR_Code rc;
345    BPVRlib_Feed_Handle feed;
346    void *cached;
347    BINT_Id playInt;
348
349    BDBG_ASSERT(pfeed);
350    *pfeed = NULL;
351    if(config == NULL) {
352        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
353        goto err_parameter;
354    }
355    if(config->xptHandle==NULL || config->xptPlayHandle==NULL) {
356        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
357        goto err_parameter;
358    }
359    if(config->heap==NULL || config->intHandle==NULL) {
360        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
361        goto err_parameter;
362    }
363    if( config->numDesc<2) {
364        rc = BERR_TRACE(BERR_INVALID_PARAMETER);
365        goto err_parameter;
366    }
367#if !BXPT_HAS_TSMUX
368    if(config->useExtndedDesc) {
369        rc = BERR_TRACE(BERR_NOT_SUPPORTED);
370        goto err_parameter;
371    }
372#endif
373
374    feed = BKNI_Malloc(sizeof(*feed));
375    if(!feed) {
376        rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
377        goto err_alloc;
378    }
379    BDBG_OBJECT_INIT(feed, BPVRlib_Feed);
380    feed->config = *config;
381    feed->descScale = config->useExtndedDesc ? 2: 1;
382    feed->config.numDesc += feed->descScale; /* increase number of descriptors, since last descriptor can't be always used */
383    feed->nc_desc = BMEM_Heap_AllocAligned(config->heap, sizeof(*feed->desc)*feed->descScale*feed->config.numDesc+B_PVRLIB_BOUNCE_BUF_SIZE, 4, 0);
384    if(!feed->nc_desc) {
385        rc = BERR_TRACE(BERR_OUT_OF_DEVICE_MEMORY);
386        goto err_desc;
387    }
388    rc = BMEM_Heap_ConvertAddressToOffset(config->heap, feed->nc_desc, &feed->off_desc);
389    if(rc!=BERR_SUCCESS) {
390        rc = BERR_TRACE(rc);
391        goto err_offset;
392    }
393    rc = BMEM_Heap_ConvertAddressToCached(config->heap, feed->nc_desc, &cached);
394    if(rc!=BERR_SUCCESS) {
395        rc = BERR_TRACE(rc);
396        goto err_cached;
397    }
398    feed->desc = cached;
399    BPVRlib_Feed_Priv_Reset(feed);
400        playInt = BXPT_Playback_GetIntId(config->xptPlayHandle,BXPT_PbInt_eDone);
401    feed->hPlayInt = NULL;
402    if(config->descAvaliable_isr) {
403        rc = BINT_CreateCallback(&feed->hPlayInt, feed->config.intHandle, playInt, config->descAvaliable_isr, config->applicationCnxt, config->applicationNumber);
404        if(rc!=BERR_SUCCESS) {
405            rc = BERR_TRACE(rc);
406            goto err_int_callback;
407        }
408    }
409#if B_PVR_LIB_FEED_SAVE_BEFORE
410    b_pvr_feed_save_init(&feed->save.before,"before");
411#endif
412#if B_PVR_LIB_FEED_SAVE_AFTER
413    b_pvr_feed_save_init(&feed->save.after,"after");
414#endif
415
416    *pfeed = feed;
417    return BERR_SUCCESS;
418
419err_int_callback:
420err_cached:
421err_offset:
422    BMEM_Heap_Free(feed->config.heap, feed->desc);
423err_desc:
424    BKNI_Free(feed);
425err_alloc:
426err_parameter:
427    return rc;
428}
429
430
431void 
432BPVRlib_Feed_Close(BPVRlib_Feed_Handle feed)
433{
434    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
435#if B_PVR_LIB_FEED_SAVE_BEFORE
436    b_pvr_feed_save_close(&feed->save.before);
437#endif
438#if B_PVR_LIB_FEED_SAVE_AFTER
439    b_pvr_feed_save_close(&feed->save.after);
440#endif
441    if(feed->hPlayInt) {
442        BINT_DestroyCallback(feed->hPlayInt);
443    }
444    BMEM_Heap_Free(feed->config.heap, feed->nc_desc);
445    BDBG_OBJECT_DESTROY(feed, BPVRlib_Feed);
446    BKNI_Free(feed);
447    return;
448}
449
450
451BERR_Code
452BPVRlib_Feed_Start(BPVRlib_Feed_Handle feed)
453{
454    BERR_Code rc;
455    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
456    rc = BXPT_Playback_StartChannel(feed->config.xptPlayHandle);
457    if(rc!=BERR_SUCCESS) {
458        rc = BERR_TRACE(rc);
459    }
460    if(feed->hPlayInt) {
461        BINT_EnableCallback(feed->hPlayInt);
462    }
463    BPVRlib_Feed_Priv_Reset(feed);
464#if B_PVR_LIB_FEED_SAVE_BEFORE
465    b_pvr_feed_save_open(&feed->save.before);
466#endif
467#if B_PVR_LIB_FEED_SAVE_AFTER
468    b_pvr_feed_save_open(&feed->save.after);
469#endif
470    return rc;
471}
472
473
474void 
475BPVRlib_Feed_Stop(BPVRlib_Feed_Handle feed)
476{
477    BERR_Code rc;
478    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
479#if B_PVR_LIB_FEED_SAVE_BEFORE
480    b_pvr_feed_save_close(&feed->save.before);
481#endif
482#if B_PVR_LIB_FEED_SAVE_AFTER
483    b_pvr_feed_save_close(&feed->save.after);
484#endif
485    rc = BXPT_Playback_StopChannel(feed->config.xptPlayHandle);
486    if(rc!=BERR_SUCCESS) {
487        rc = BERR_TRACE(rc);
488    }
489    if(feed->hPlayInt) {
490        BINT_DisableCallback(feed->hPlayInt);
491    }
492    return;
493}
494
495static unsigned 
496BPVRlib_Feed_Priv_AddOffsetEntries(BPVRlib_Feed_Handle feed, const BPVRlib_Feed_OffsetEntry *entries, size_t nentries, bool last, bool extended)
497{
498    unsigned entries_left;
499    unsigned entrySize;
500    BERR_Code rc;
501    BXPT_PvrDescriptor *prev_desc;
502    BXPT_PvrDescriptor *first_desc=NULL;
503    BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_AddOffsetEntries>: %#lx %#lx:%u %s", (unsigned long)feed, (unsigned long)entries, nentries, last?"LAST":""));
504
505    entrySize = extended ? sizeof(BPVRlib_Feed_ExtendedOffsetEntry) : sizeof(*entries);
506
507    for(prev_desc=&feed->dummy_descr, entries_left=nentries;entries_left>0;) {
508        unsigned i;
509        unsigned nwrite_desc = BFIFO_WRITE_PEEK(&feed->descFifo);
510        BXPT_PvrDescriptor *write_desc;
511        BXPT_PvrDescriptor *desc;
512   
513        if(nwrite_desc==0 || 
514                (nwrite_desc<=feed->descScale && BFIFO_WRITE_LEFT(&feed->descFifo)==(int)feed->descScale) /* we should always keep one entry in the FIFO empty since it's reserved for the 'last' dscriptor that is used for chaining */
515                ) { 
516            break;
517        }
518        if(nwrite_desc>entries_left*feed->descScale) {
519            nwrite_desc = entries_left*feed->descScale;
520        }
521        BDBG_ASSERT(nwrite_desc>0);
522        write_desc = BFIFO_WRITE(&feed->descFifo);
523        if(feed->finished) {
524            feed->finished = false;
525            feed->false_finished = true;
526        }
527        if(feed->false_finished && write_desc+(nwrite_desc-feed->descScale) == feed->prev_hw_finished_desc) {
528            BDBG_WRN(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx preventing use of the last_finished_desc %#lx:%u", (unsigned long)feed, (unsigned long)feed->prev_hw_finished_desc, nwrite_desc));
529            if(nwrite_desc==feed->descScale) {
530                unsigned i;
531                for(i=0;i<10;i++) {
532                    BPVRlib_Feed_Priv_Update(feed);
533                    if(!feed->false_finished) {
534                        break;
535                    }
536                    BDBG_WRN(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx wating(%u) to release last_finished_desc %#lx:%u", (unsigned long)feed, i, (unsigned long)feed->prev_hw_finished_desc));
537                    BKNI_Sleep(1);
538                } 
539                /* try to use it anyway */
540            } else {
541                nwrite_desc-=feed->descScale;
542            }
543        }
544        BDBG_ASSERT(write_desc);
545        BFIFO_WRITE_COMMIT(&feed->descFifo, nwrite_desc);
546        entries_left -= nwrite_desc/feed->descScale;
547        if(first_desc==NULL) {
548            first_desc = write_desc;
549        }
550        for( desc=write_desc, i=0; i<nwrite_desc; i+=feed->descScale, desc+=feed->descScale, entries=(void *)((uint8_t*)entries+entrySize) ) {
551#if BXPT_HAS_TSMUX
552            if(feed->config.useExtndedDesc) {
553                BXPT_PvrDescriptor8 *desc8 = (void *)desc;
554                if(entrySize==sizeof(*entries)) {
555                    desc8->Reserved0=0;
556                    desc8->MuxingFlags = 0;
557                    desc8->NextPacketPacingTimestamp = 0;
558                    desc8->Pkt2PktPacingTimestampDelta = 0;
559                } else {
560                    BXPT_Tsmux_ConfigDesc(desc8, &((BPVRlib_Feed_ExtendedOffsetEntry *)entries)->flags);
561                }
562            }
563#endif
564            desc->BufferStartAddr = entries->offset;
565            desc->BufferLength = entries->len;
566            desc->Flags = 0;
567            prev_desc->NextDescAddr = feed->off_desc + ((uint32_t)desc - (uint32_t)feed->desc);
568            prev_desc = desc;
569            BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx desc %u:%#lx %#lx(%#lx:%u)", (unsigned long)feed, i, desc, feed->off_desc + ((uint32_t)desc - (uint32_t)feed->desc), entries->offset, entries->len));
570#if B_PVRLIB_SMALL_DESC_BUG   
571            switch(entries->len) {
572            case 0:
573                desc->BufferLength = 2;
574                BDBG_WRN(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx not supported S/G entry %#lx:%u, replaced with %#lx:%u", (unsigned long)feed, (unsigned long)entries->offset, (unsigned)entries->len, (unsigned long)desc->BufferStartAddr, (unsigned)desc->BufferLength));
575                break;
576            case 1:
577                BDBG_WRN(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx S/G entry %#lx:%u(%#lx)", (unsigned long)feed, (unsigned long)entries->offset, (unsigned)entries->len, (unsigned long)feed->last_data_addr));
578                if(B_PVRLIB_SMALL_ADDR_TEST(feed->last_data_addr, entries->offset)) {
579                    void *addr;
580                    BERR_Code rc = BMEM_Heap_ConvertOffsetToAddress(feed->config.heap, entries->offset, &addr);
581                    if(rc==BERR_SUCCESS) {
582                        for(;B_PVRLIB_SMALL_ADDR_TEST(feed->last_data_addr, feed->bounce_offset+(feed->bounce_ptr%B_PVRLIB_BOUNCE_BUF_SIZE));feed->bounce_ptr++) { }
583                        feed->bounce_buffer[feed->bounce_ptr%B_PVRLIB_BOUNCE_BUF_SIZE]=*(uint8_t *)addr;
584                        desc->BufferStartAddr = feed->bounce_offset+(feed->bounce_ptr%B_PVRLIB_BOUNCE_BUF_SIZE);
585                        feed->bounce_ptr++;
586                    } else {
587                        rc=BERR_TRACE(rc);
588                        desc->BufferLength = 2;
589                    } 
590                    BDBG_WRN(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx not supported S/G entry %#lx:%u, replaced with %#lx:%u", (unsigned long)feed, (unsigned long)entries->offset, (unsigned)entries->len, (unsigned long)desc->BufferStartAddr, (unsigned)desc->BufferLength));
591                }
592                break;
593            default:
594                break;
595            }
596            feed->last_data_addr = entries->offset + entries->len + 1;
597#endif /* B_PVRLIB_SMALL_ADDR_TEST */
598#if B_PVR_LIB_FEED_SAVE_BEFORE
599            b_pvr_feed_save_data_offset(feed->config.heap, &feed->save.before, desc->BufferStartAddr, desc->BufferLength);
600#endif
601        }
602        prev_desc->NextDescAddr = TRANS_DESC_LAST_DESCR_IND;
603        rc = BMEM_Heap_FlushCache(feed->config.heap, write_desc, nwrite_desc*sizeof(*write_desc));
604        if(rc!=BERR_SUCCESS) {
605            rc = BERR_TRACE(rc);
606            break;
607        }
608        feed->last_desc = prev_desc;
609        /* prev_desc points to the last descriptor, convert it to uncached address */
610        prev_desc = feed->nc_desc + (prev_desc - feed->desc);
611    }
612    if(first_desc) {
613        BDBG_ASSERT(prev_desc!=&feed->dummy_descr);
614        /* convert first descriptor to uncached address */
615        feed->active = true;
616        first_desc = feed->nc_desc + (first_desc - feed->desc);
617        if(last || nentries!=entries_left ) {
618            prev_desc->Flags = TRANS_DESC_INT_FLAG;
619        }
620        BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_AddOffsetEntries: %#lx first:%#lx(%#lx) last:%#lx(%#lx)", (unsigned long)feed, (unsigned long)first_desc, feed->off_desc + ((uint32_t)first_desc - (uint32_t)feed->nc_desc), (unsigned long)prev_desc, feed->off_desc + ((uint32_t)prev_desc - (uint32_t)feed->nc_desc)));
621        rc = BXPT_Playback_AddDescriptors(feed->config.xptPlayHandle, prev_desc, first_desc); /* last descriptor goes as second argument and first descriptor goes as third argument */
622        if(rc!=BERR_SUCCESS) {
623            rc = BERR_TRACE(rc);
624        }
625    }
626    BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_AddOffsetEntries<: %#lx %#lx:%u ->%u", (unsigned long)feed, (unsigned long)entries, nentries, nentries-entries_left));
627    return nentries-entries_left;
628}
629
630static void 
631BPVRlib_Feed_Priv_Update(BPVRlib_Feed_Handle feed)
632{
633    BERR_Code rc;
634    BXPT_PvrDescriptor *nc_hw_desc;
635    BXPT_PvrDescriptor *hw_desc;
636    unsigned hw_complete;
637    unsigned nread_desc;
638
639    BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update>: %#lx ncompleted:%u", (unsigned long)feed, feed->ncompleted));
640    if(!feed->active) {
641        goto done;
642    }
643    rc = BXPT_Playback_GetCurrentDescriptorAddress(feed->config.xptPlayHandle, &nc_hw_desc);
644    if(rc!=BERR_SUCCESS) {
645        rc = BERR_TRACE(rc);
646        goto error;
647    }
648    hw_desc = feed->desc + (nc_hw_desc - feed->nc_desc);  /* convert to cached address */
649    if(hw_desc != feed->prev_hw_finished_desc) {
650        feed->false_finished = false;
651        feed->finished = false;
652    }
653    BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx hw_desc:%#lx last_desc:%#lx %u", (unsigned long)feed, (unsigned long)hw_desc, (unsigned long)feed->last_desc, BFIFO_READ_LEFT(&feed->descFifo)));
654    BFIFO_STATUS(BDBG_MSG_TRACE,"BPVRlib_Feed_Priv_Update: fifo", &feed->descFifo);
655    if(feed->false_finished) {
656        BDBG_MSG(("BPVRlib_Feed_Priv_Update: %#lx false finished desc:%#lx .. %#lx (%u)", (unsigned long)feed, (unsigned long)hw_desc, BFIFO_READ(&feed->descFifo), BFIFO_READ_PEEK(&feed->descFifo)));
657        goto done;
658    }
659    if(hw_desc==feed->last_desc) { /* if we completed last descriptor test whether playback completed */
660        BXPT_Playback_ChannelStatus status;
661        rc = BXPT_Playback_GetChannelStatus(feed->config.xptPlayHandle, &status);
662        if(rc!=BERR_SUCCESS) {
663            rc=BERR_TRACE(rc);
664        } 
665        BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx last_desc:%#lx %s", (unsigned long)feed, (unsigned long)hw_desc, status.Finished?"FINISHED":""));
666        if(status.Finished) { /* last descriptor was completed */
667            feed->finished = true;
668            feed->prev_hw_finished_desc = hw_desc;
669            hw_complete = BFIFO_READ_LEFT(&feed->descFifo);
670#if B_PVR_LIB_FEED_SAVE_AFTER
671            {
672                unsigned i;
673                struct B_PVRlib_DescrFifo descFifo = feed->descFifo; /* do a copy, so we don't interfere with actual FIFO */
674                for(i=0; BFIFO_READ_PEEK(&descFifo)!=0;i++) {
675                    const BXPT_PvrDescriptor *desc = BFIFO_READ(&descFifo);
676                    b_pvr_feed_save_data_offset(feed->config.heap, &feed->save.after, desc->BufferStartAddr, desc->BufferLength);
677                    BFIFO_READ_COMMIT(&descFifo, feed->descScale);
678                }
679                BDBG_ASSERT(i==hw_complete/feed->descScale);
680            }
681#endif /* B_PVR_LIB_FEED_SAVE_AFTER */
682            BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx recycle all(%u) data from FIFO", (unsigned long)feed, hw_complete));
683            feed->ncompleted += hw_complete/feed->descScale;
684            /* update read pointer to walk through all descriptors */
685            nread_desc = BFIFO_READ_PEEK(&feed->descFifo);
686            if(nread_desc) {
687                BDBG_ASSERT(nread_desc <= hw_complete);
688                hw_complete -= nread_desc;
689                BFIFO_READ_COMMIT(&feed->descFifo, nread_desc);
690            } /* we could have a wrap */
691            nread_desc = BFIFO_READ_PEEK(&feed->descFifo);
692            if(nread_desc) {
693                BFIFO_READ_COMMIT(&feed->descFifo, nread_desc);
694            }
695            BDBG_ASSERT(nread_desc == hw_complete); /* number of reclaimed descriptors shoild be the same as number of queued descriptors */
696            feed->active = false;
697            goto done;
698        }
699        /* last descriptor still in use, proceed as usual */
700    }
701    if(hw_desc >= feed->desc && hw_desc < (feed->desc + feed->descScale * feed->config.numDesc)) {
702        const BXPT_PvrDescriptor *desc;
703
704        desc = BFIFO_READ(&feed->descFifo);
705        nread_desc = BFIFO_READ_PEEK(&feed->descFifo);
706
707        if(hw_desc < desc) { /* |===H---R===| HW descriptor is after wraparound, consume all 'peek'ed data */
708            BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx [wrap] hw_desc:%#lx desc:%#lx nread_desc:%d", (unsigned long)feed, (unsigned long)hw_desc, (unsigned long)desc, nread_desc));
709#if B_PVR_LIB_FEED_SAVE_AFTER
710            {
711                unsigned i;
712                for(i=0;i<nread_desc;i++) {
713                    b_pvr_feed_save_data_offset(feed->config.heap, &feed->save.after, desc[i].BufferStartAddr, desc[i].BufferLength);
714                }
715            }
716#endif /* B_PVR_LIB_FEED_SAVE_AFTER */
717            feed->ncompleted += nread_desc/feed->descScale;
718            BFIFO_READ_COMMIT(&feed->descFifo, nread_desc);
719            nread_desc = BFIFO_READ_PEEK(&feed->descFifo);
720            desc = BFIFO_READ(&feed->descFifo);
721        }
722        BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx hw_desc:%#lx desc:%#lx nread_desc:%d", (unsigned long)feed, (unsigned long)hw_desc, (unsigned long)desc, nread_desc));
723        if(hw_desc>=desc) { /* |-R===H-----| */
724            hw_complete = hw_desc - desc;
725            BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx off:%d nread_desc:%d", (unsigned long)feed, hw_complete, nread_desc));
726            if(hw_complete<=nread_desc) {
727                BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update: %#lx completed:%u", (unsigned long)feed, (unsigned)hw_complete));
728#if B_PVR_LIB_FEED_SAVE_AFTER
729                {
730                    unsigned i;
731                    for(i=0;i<hw_complete;i++) {
732                        b_pvr_feed_save_data_offset(feed->config.heap, &feed->save.after, desc[i].BufferStartAddr, desc[i].BufferLength);
733                    }
734                }
735#endif /* B_PVR_LIB_FEED_SAVE_AFTER */
736                feed->ncompleted += hw_complete/feed->descScale;
737                BFIFO_READ_COMMIT(&feed->descFifo, hw_complete);
738            } else {
739                BDBG_ERR(("BPVRlib_Feed_Priv_Update: %#lx underflow %u .. %u(%#lx..%#lx[%#lx..%#lx])", (unsigned long)feed, (unsigned long)hw_complete, (unsigned long)nread_desc, (unsigned long)desc, (unsigned long)hw_desc, (unsigned long)feed->desc, (unsigned long)(feed->desc+feed->config.numDesc*feed->descScale)));
740                goto error;
741            }
742        } else {
743            BDBG_ERR(("BPVRlib_Feed_Priv_Update: %#lx descriptor out of sequence %#lx .. %#lx [%#lx..%#lx]", (unsigned long)feed, (unsigned long)desc, (unsigned long)hw_desc, (unsigned long)feed->desc, (unsigned long)(feed->desc+feed->config.numDesc*feed->descScale)));
744            goto error;
745        }
746    } else {
747        BDBG_ERR(("BPVRlib_Feed_Priv_Update: %#lx descriptor out of range %#lx .. %#lx .. %#lx", (unsigned long)feed, (unsigned long)feed->desc, (unsigned long)hw_desc, (unsigned long)(feed->desc+feed->config.numDesc*feed->descScale)));
748        goto error;
749    }
750
751error:
752done:
753    BFIFO_STATUS(BDBG_MSG_TRACE,"BPVRlib_Feed_Priv_Update: fifo", &feed->descFifo);
754    BDBG_MSG_TRACE(("BPVRlib_Feed_Priv_Update<: %#lx ncompleted:%u", (unsigned long)feed, feed->ncompleted));
755    return;
756}
757
758BERR_Code
759BPVRlib_Feed_AddOffsetEntries(BPVRlib_Feed_Handle feed, const BPVRlib_Feed_OffsetEntry *entries, size_t count, size_t *nconsumed)
760{
761    BDBG_MSG_TRACE(("BPVRlib_Feed_AddOffsetEntries: %#lx entries %#lx:%u", (unsigned long)feed, (unsigned long)entries, count));
762    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
763
764    BDBG_ASSERT(entries);
765    BDBG_ASSERT(nconsumed);
766
767    BPVRlib_Feed_Priv_Update(feed);
768    *nconsumed = BPVRlib_Feed_Priv_AddOffsetEntries(feed, entries, count, true, false);
769    return BERR_SUCCESS;
770}
771
772BERR_Code
773BPVRlib_Feed_AddExtendedOffsetEntries(BPVRlib_Feed_Handle feed, const BPVRlib_Feed_ExtendedOffsetEntry *entries, size_t count, size_t *nconsumed)
774{
775    BDBG_MSG_TRACE(("BPVRlib_Feed_AddExtendedOffsetEntries: %#lx entries %#lx:%u", (unsigned long)feed, (unsigned long)entries, count));
776    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
777
778    BDBG_ASSERT(entries);
779    BDBG_ASSERT(nconsumed);
780    if(!feed->config.useExtndedDesc) {
781        return BERR_TRACE(BERR_NOT_SUPPORTED);
782    }
783
784    BPVRlib_Feed_Priv_Update(feed);
785    *nconsumed = BPVRlib_Feed_Priv_AddOffsetEntries(feed, (void*)entries, count, true, true);
786    return BERR_SUCCESS;
787}
788
789BERR_Code
790BPVRlib_Feed_AddEntries(BPVRlib_Feed_Handle feed, BMEM_Heap_Handle heap, const BPVRlib_Feed_Entry *entries /* pointer to array of entries */ , size_t nentries /* number of entries in the array */ , size_t *nconsumed)
791{
792    unsigned off;
793    BPVRlib_Feed_OffsetEntry *offset_entries = feed->offset_entries;
794    BERR_Code rc = BERR_SUCCESS;
795
796    BDBG_MSG_TRACE(("BPVRlib_Feed_AddEntries>: %#lx entries %#lx:%u", (unsigned long)feed, (unsigned long)entries, nentries));
797    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
798    BDBG_ASSERT(heap);
799    BDBG_ASSERT(entries);
800    BDBG_ASSERT(nconsumed);
801
802    *nconsumed=0;
803    BPVRlib_Feed_Priv_Update(feed);
804
805    for(off=0;;) {
806        unsigned i;
807        unsigned added;
808        for(i=0;i<sizeof(feed->offset_entries)/sizeof(*feed->offset_entries) && off<nentries;off++,i++) {
809            offset_entries[i].len = entries[off].len;
810            rc = BMEM_Heap_ConvertAddressToOffset(heap, entries[off].addr, &offset_entries[i].offset);
811            if(rc!=BERR_SUCCESS) {
812                rc = BERR_TRACE(rc);
813                goto err_offset;
814            }
815        }
816        if(i==0) {
817            break;
818        }
819        added = BPVRlib_Feed_Priv_AddOffsetEntries(feed, offset_entries, i, off==nentries, false);
820        *nconsumed+=added;
821        if(added!=i) {
822            break;
823        }
824    }
825err_offset:
826    BDBG_MSG_TRACE(("BPVRlib_Feed_AddEntries<: %#lx entries %#lx:%u -> %u", (unsigned long)feed, (unsigned long)entries, nentries, *nconsumed));
827    return rc;
828}
829
830BERR_Code
831BPVRlib_Feed_GetCompleted(BPVRlib_Feed_Handle feed, size_t *ncompleted)
832{
833    BDBG_MSG_TRACE(("BPVRlib_Feed_GetCompleted>: %#lx", (unsigned long)feed));
834
835    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
836    BDBG_ASSERT(ncompleted);
837    BPVRlib_Feed_Priv_Update(feed);
838    *ncompleted = feed->ncompleted;
839    feed->ncompleted = 0;
840
841    BDBG_MSG_TRACE(("BPVRlib_Feed_GetCompleted<: %#lx -> %u", (unsigned long)feed, *ncompleted));
842    return BERR_SUCCESS;
843}
844
845void 
846BPVRlib_Feed_GetStatus(BPVRlib_Feed_Handle feed, BPVRlib_Feed_Status *status)
847{
848    size_t freeDesc;
849    BDBG_OBJECT_ASSERT(feed, BPVRlib_Feed);
850    BDBG_ASSERT(status);
851
852    BPVRlib_Feed_Priv_Update(feed);
853    freeDesc =  BFIFO_WRITE_LEFT(&feed->descFifo);
854    freeDesc /= feed->descScale;
855    if(feed->false_finished) {
856        if(freeDesc>0) {
857            BDBG_MSG(("BPVRlib_Feed_GetStatus: %#lx correcting number of avaliable descriptors %u", (unsigned long)feed, freeDesc));
858            freeDesc --;
859        }
860    }
861    if(freeDesc>0) {
862        freeDesc --;
863    }
864    status->freeDesc = freeDesc;
865    BDBG_MSG_TRACE(("BPVRlib_Feed_GetStatus: %#lx freeDesc:%u", (unsigned long)feed, freeDesc));
866    return;
867}
Note: See TracBrowser for help on using the repository browser.