source: svn/newcon3bcm2_21bu/magnum/syslib/pvrlib/bpvrlib_p_ringmgr.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: 11.1 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2002, 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_p_ringmgr.c $
11 * $brcm_Revision: Hydra_Software_Devel/5 $
12 * $brcm_Date: 1/21/04 4:43p $
13 *
14 * Module Description:
15 *
16 * This module implements a generic ring buffer in software.
17 * It includes function that allow the user add and remove data
18 * from the ring buffer.  It supports notication of buffer
19 * full to not full, and buffer empty to not empty states through
20 * the use of callbacks.  It supports blocking function
21 * calls when requesting to add and requesting to remove data
22 * from the ring buffer.  It supports a programmable buffer
23 * address and size, and does not actually require accessing any
24 * memory inside the specified buffer.
25 *
26 * Revision History:
27 *
28 * $brcm_Log: /vobs/magnum/syslib/pvrlib/bpvrlib_p_ringmgr.c $
29 *
30 * Hydra_Software_Devel/5   1/21/04 4:43p marcusk
31 * PR8927: Fixed to work with latest version of XPT porting interface.
32 * Validate channel number.
33 *
34 * Hydra_Software_Devel/4   12/12/03 2:03p dlwin
35 * PR 8970: Change naming convention to conform to Magnum
36 *
37 * Hydra_Software_Devel/3   12/10/03 2:25p marcusk
38 * PR8927: Record syslib now compiles.
39 *
40 * Hydra_Software_Devel/2   12/10/03 11:07a marcusk
41 * PR 8927: Initial magnum version (not compiled yet)
42 *
43 * Irvine_HDDemo_Devel\26   6/25/02 12:57p marcusk
44 * Fixed detection of buffer full condition.
45 *
46 * Irvine_HDDemo_Devel\25   5/17/02 9:47a marcusk
47 * Added "" around BRCM_DBG_MODULE to support new debug routines.
48 *
49 ***************************************************************************/
50#include "bstd.h"
51#include "bkni.h"
52#include "bpvrlib_p_ringmgr.h"
53
54BDBG_MODULE(BPVRlib_RingMgr);
55
56BERR_Code BPVRlib_P_RingMgr_Open( 
57                                BPVRlib_P_RingMgr_Handle *rbmgr,                        /* [out] returns context */
58                                uint32_t channel,                                                       /* returned as parameter by callback functions */
59                                BPVRlib_P_RingMgrCb emptyToNotEmptyCb,  /* optional callback function to be called when the ring buffer transitions from empty to not empty */
60                                BPVRlib_P_RingMgrCb fullToNotFullCb,            /* optional callback function to be called when the ring buffer transitions from full to not full */
61                                uint8_t *p_bfr,                                                 /* pointer to the buffer that the ring buffer manager should use */
62                                size_t bfrSize                                                  /* the size of the buffer described by the p_bfr pointer */
63                                )
64{
65        BERR_Code err = BERR_SUCCESS;
66       
67        *rbmgr = BKNI_Malloc( sizeof( BPVRlib_P_RingMgr_Impl ) );
68        if( !*rbmgr )
69        {
70                err = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
71                BDBG_ERR(("Unable to allocate ring buffer manager."));
72                goto done;
73        }
74
75        /* This variable must be set to init the rpbmgr */
76        (*rbmgr)->channel                       = channel;
77        (*rbmgr)->emptyToNotEmptyCb= emptyToNotEmptyCb;
78        (*rbmgr)->fullToNotFullCb       = fullToNotFullCb;
79        (*rbmgr)->bufferSize            = bfrSize;
80        (*rbmgr)->p_bfr                         = p_bfr;
81
82        err = BKNI_CreateEvent(&((*rbmgr)->notifyEvent));
83        if( err != BERR_SUCCESS )
84        {
85                BKNI_Free( *rbmgr );
86                goto done;
87        }
88        BPVRlib_P_RingMgr_Reset( *rbmgr );
89
90done:
91        return err;
92}
93
94void BPVRlib_P_RingMgr_Reset( 
95                        BPVRlib_P_RingMgr_Handle rbmgr                          /* handle of ring buffer manager */
96                        )
97{
98        /* Assign the proper channel */
99        rbmgr->resetInProgress  = 1;
100        rbmgr->abortInProgress  = 0;
101        rbmgr->writeOffset              = 0;
102        rbmgr->writeWrapCount   = 0;
103        rbmgr->readOffset               = 0;
104        rbmgr->readWrapCount    = 0;
105        rbmgr->hwWriteOffset    = 0;
106        rbmgr->hwWriteWrapCount = 0;
107        BKNI_SetEvent(rbmgr->notifyEvent);
108}
109
110void BPVRlib_P_RingMgr_Close( 
111                        BPVRlib_P_RingMgr_Handle rbmgr                          /* handle of ring buffer manager */
112                        )
113{
114        BKNI_DestroyEvent(rbmgr->notifyEvent);
115        BKNI_Free( rbmgr );
116}
117
118BERR_Code BPVRlib_P_RingMgr_AddDataRequest( 
119                        BPVRlib_P_RingMgr_Handle rbmgr,         /* handle of ring buffer manager */
120                        uint8_t **pp_bfr,                                               /* returns pointer of starting buffer address of free space */
121                        size_t *p_count,                                        /* returns size of the free space (in bytes) */
122                        bool block,                                                     /* false (do not block), true (block until free space is available) */
123                        uint32_t timeout                                                /* max num of msec to block */
124                        )
125{
126        BERR_Code err = BERR_SUCCESS;
127
128        BDBG_MSG(("Request to add data to ring buffer with %s", block?"block":"no block"));
129
130        rbmgr->resetInProgress = 0;
131        *pp_bfr = (uint8_t *)rbmgr->p_bfr + rbmgr->writeOffset;
132
133        while( 1 )
134        {
135                if( rbmgr->writeOffset == rbmgr->readOffset )
136                {
137                        if( rbmgr->writeWrapCount == rbmgr->readWrapCount )
138                        {
139                                *p_count = rbmgr->bufferSize - rbmgr->writeOffset;
140                        }
141                        else
142                        {
143                                *p_count = 0;
144                        }
145                }
146                else if( rbmgr->writeOffset > rbmgr->readOffset )
147                {
148                        *p_count = rbmgr->bufferSize - rbmgr->writeOffset;
149                }
150                else if( rbmgr->writeOffset < rbmgr->readOffset )
151                {
152                        *p_count = rbmgr->readOffset - rbmgr->writeOffset;
153                }
154
155                if( *p_count == 0 && block )
156                {
157                        BDBG_MSG(("Ring buffer full.  Waiting %ld for read offset to be updated", timeout));
158                        err = BKNI_WaitForEvent( rbmgr->notifyEvent, timeout );
159
160                        if( err != BERR_SUCCESS || rbmgr->resetInProgress || rbmgr->abortInProgress )
161                        {
162                                err = BERR_TRACE(BERR_TIMEOUT);
163                                break;
164                        }
165                }
166                else
167                {
168                        break;
169                }
170        }
171
172        return err;
173}
174
175BERR_Code BPVRlib_P_RingMgr_UpdateWritePointer( 
176                        BPVRlib_P_RingMgr_Handle rbmgr,         /* handle of ring buffer manager */
177                        size_t count                                            /* number of bytes to increment the write pointer */
178                        )
179{
180        BERR_Code err = BERR_SUCCESS;
181        bool empty = false;
182
183        if( rbmgr->resetInProgress )
184        {
185                err = BERR_TRACE(BERR_UNKNOWN);
186                BDBG_WRN(("Reset or timeout occurred: rpbmgr_UpdateWritePointer"));
187                goto done;
188        }
189
190        BDBG_MSG(("Incrementing write pointer by %ld bytes", count));
191
192        if( (rbmgr->writeOffset == rbmgr->readOffset)
193                && (rbmgr->writeWrapCount == rbmgr->readWrapCount) )
194        {
195                empty = true;
196        }
197
198        if( (rbmgr->writeOffset+count) > rbmgr->bufferSize )
199        {
200                err = BERR_TRACE(BERR_INVALID_PARAMETER);
201                BDBG_ERR(("FATAL ERROR: Attempt to overflow ring buffer by %ld bytes!", (rbmgr->writeOffset+count)-rbmgr->bufferSize));
202                goto done;
203        }
204
205        rbmgr->writeOffset += count;
206        if( rbmgr->writeOffset >= rbmgr->bufferSize )
207        {
208                rbmgr->writeWrapCount++;
209                rbmgr->writeOffset -= rbmgr->bufferSize;
210        }
211               
212        BKNI_SetEvent( rbmgr->notifyEvent );
213
214        if( empty )
215        {
216                if( rbmgr->emptyToNotEmptyCb )
217                        (*rbmgr->emptyToNotEmptyCb)( rbmgr->channel );
218        }
219
220done:
221        return err;
222}
223
224BERR_Code BPVRlib_P_RingMgr_RemoveDataRequest( 
225                        BPVRlib_P_RingMgr_Handle rbmgr,                         /* handle of ring buffer manager */
226                        uint8_t **pp_bfr,                               /* returns pointer of starting buffer address of valid data */
227                        size_t *p_count,                        /* returns size of the valid data (in bytes) */
228                        bool block,                                     /* false (do not block), true (block until free space is available) */
229                        uint32_t timeout                                /* max num of msec to block */
230                        )
231
232{
233        BERR_Code err = BERR_SUCCESS;
234
235        BDBG_MSG(("Requesting to remove data from ring buffer with %s", block?"block":"no block"));
236
237        *pp_bfr = (uint8_t *)rbmgr->p_bfr + rbmgr->readOffset;
238
239        while( 1 )
240        {
241                if( rbmgr->writeOffset == rbmgr->readOffset )
242                {
243                        if( rbmgr->readWrapCount == rbmgr->writeWrapCount )
244                        {
245                                *p_count = 0;
246                        }
247                        else
248                        {
249                                *p_count = rbmgr->bufferSize - rbmgr->readOffset;
250                        }
251                }
252                else if( rbmgr->writeOffset > rbmgr->readOffset )
253                {
254                        *p_count = rbmgr->writeOffset - rbmgr->readOffset;
255                }
256                else if( rbmgr->writeOffset < rbmgr->readOffset )
257                {
258                        *p_count = rbmgr->bufferSize - rbmgr->readOffset;
259                }
260
261                if( *p_count == 0 && block )
262                {
263                        BDBG_MSG(("Ring buffer empty.  Waiting %ld for write offset to be updated", timeout));
264                        err = BKNI_WaitForEvent( rbmgr->notifyEvent, timeout);
265
266                        if( err != BERR_SUCCESS || rbmgr->resetInProgress || rbmgr->abortInProgress )
267                        {
268                                err = BERR_TRACE(BERR_TIMEOUT);
269                                break;
270                        }
271                }
272                else
273                {
274                        break;
275                }
276        }
277
278        return err;
279}
280
281BERR_Code BPVRlib_P_RingMgr_UpdateReadPointer( 
282                        BPVRlib_P_RingMgr_Handle rbmgr,         /* handle of ring buffer manager */
283                        size_t count                                            /* number of bytes to increment the read pointer */
284                        )
285{
286        BERR_Code err = BERR_SUCCESS;
287        bool full = false;
288
289        if( rbmgr->resetInProgress )
290        {
291                BDBG_WRN(("Reset or timeout occurred: rpbmgr_UpdateReadPointer"));
292                err = BERR_TRACE(BERR_UNKNOWN);
293                goto done;
294        }
295
296        BDBG_MSG(("Incrementing read pointer by %ld bytes", count));
297
298        if( (rbmgr->writeOffset == rbmgr->readOffset)
299                && (rbmgr->writeWrapCount != rbmgr->readWrapCount) )
300        {
301                full = true;
302        }
303
304        if( (rbmgr->readOffset+count) > rbmgr->bufferSize )
305        {
306                BDBG_ERR(("FATAL ERROR: Attempt to overflow ring buffer by %ld bytes!", (rbmgr->readOffset+count)-rbmgr->bufferSize));
307                err = BERR_TRACE(BERR_INVALID_PARAMETER);
308                goto done;
309        }
310
311        rbmgr->readOffset += count;
312        if( rbmgr->readOffset >= rbmgr->bufferSize )
313        {
314                rbmgr->readWrapCount++;
315                rbmgr->readOffset -= rbmgr->bufferSize;
316        }
317
318        BKNI_SetEvent( rbmgr->notifyEvent );
319
320        if( full )
321        {
322                if( rbmgr->fullToNotFullCb )
323                        (*rbmgr->fullToNotFullCb)( rbmgr->channel );
324        }
325
326done:
327        return err;
328}
329
330void BPVRlib_P_RingMgr_GetNumFreeBytes( 
331                        BPVRlib_P_RingMgr_Handle rbmgr,         /* handle of ring buffer manager */
332                        size_t *p_numFreeBytes                          /* returns number of bytes available in ring buffer */
333                        )
334{
335        if( rbmgr->writeOffset == rbmgr->readOffset )
336        {
337                if( rbmgr->readWrapCount == rbmgr->writeWrapCount )
338                {
339                        *p_numFreeBytes = rbmgr->bufferSize;
340                }
341                else
342                {
343                        *p_numFreeBytes = 0;
344                }
345        }
346        else if( rbmgr->writeOffset < rbmgr->readOffset )
347        {
348                *p_numFreeBytes = rbmgr->readOffset - rbmgr->writeOffset;
349        }
350        else if( rbmgr->writeOffset > rbmgr->readOffset )
351        {
352                *p_numFreeBytes = rbmgr->bufferSize - rbmgr->writeOffset;
353                *p_numFreeBytes += rbmgr->readOffset;
354        }
355        else
356        {
357                BDBG_ERR(("FATAL ERROR: This should not be possible!"));
358        }
359}
360
361void BPVRlib_P_RingMgr_Abort( 
362                        BPVRlib_P_RingMgr_Handle rbmgr                          /* handle of ring buffer manager */
363                        )
364{
365        /* This function differs from a reset only in that it
366         * doesn't reset any of the data pointers
367         */
368        rbmgr->abortInProgress = true;
369
370        BKNI_SetEvent(rbmgr->notifyEvent);
371}
372
373void BPVRlib_P_RingMgr_GetHwWriteDifference( 
374                        BPVRlib_P_RingMgr_Handle rbmgr,         /* handle of ring buffer manager */
375                        uint8_t **pp_bfr,                                               /* returns pointer of starting buffer address of data that needs to be added into hardware */
376                        size_t *p_count                                         /* returns size of the data that needs to be added into hardware */
377                        )
378{
379        *p_count = 0;
380
381        *pp_bfr = (uint8_t *)rbmgr->p_bfr + rbmgr->hwWriteOffset;
382
383        if( rbmgr->hwWriteOffset == rbmgr->writeOffset )
384        {
385                if( rbmgr->hwWriteWrapCount == rbmgr->writeWrapCount )
386                {
387                        *p_count = 0;
388                }
389                else
390                {
391                        *p_count = rbmgr->bufferSize - rbmgr->hwWriteOffset;
392                }
393        }
394        else
395        {
396                if( rbmgr->hwWriteOffset > rbmgr->writeOffset )
397                {
398                        *p_count = rbmgr->bufferSize - rbmgr->hwWriteOffset;
399                }
400                else
401                {
402                        *p_count = rbmgr->writeOffset - rbmgr->hwWriteOffset;
403                }
404        }
405}       
406
407void BPVRlib_P_RingMgr_UpdateHwWriteCount( 
408                        BPVRlib_P_RingMgr_Handle rbmgr, /* handle of ring buffer manager */
409                        size_t count                                    /* number of bytes to increment the hw write pointer */
410                        )
411{
412        rbmgr->hwWriteOffset += count;
413
414        if( rbmgr->hwWriteOffset >= rbmgr->bufferSize )
415        {
416                rbmgr->hwWriteWrapCount++;
417                rbmgr->hwWriteOffset -= rbmgr->bufferSize;
418        }
419}
420
Note: See TracBrowser for help on using the repository browser.