35 #define TABLE_SIZE (1 << TABLE_BITS)
36 #define NUM_FILTERS 64
38 #define INVALID_VERSION 0xFF
39 #define STALE_VERSION 0xFE
40 #define STALE_BIT 0x80
41 #define REPORTING 0x40
43 #define ALLOCSIZE(s) ((s >> 1) & 7) + 1
47 typedef struct s_NodeBlock *H_NodeBlock;
48 typedef struct s_FiltBlock *H_FiltBlock;
50 typedef struct s_CacheNode
58 typedef struct s_CacheFilter
69 typedef struct s_CacheTable
71 H_CacheFilter filters[TABLE_SIZE];
72 U8BIT changed[TABLE_SIZE];
75 typedef struct s_NodeBlock
80 typedef struct s_FiltBlock
86 typedef struct s_SfmCache
91 H_FiltBlock memFilters;
93 H_CacheFilter filtHead;
94 H_CacheFilter filtTail;
117 static U16BIT HashIndex(U32BIT key, U16BIT bits)
119 key = (key << 15) - key - 1;
120 key = key ^ (key >> 12);
121 key = key + (key << 2);
122 key = key ^ (key >> 4);
123 key = (key + (key << 3)) + (key << 11);
124 key = key ^ (key >> 16);
125 return key & ((1 << bits) - 1);
128 static BOOLEAN AllocFiltBlock( H_SfmCache cache )
130 H_FiltBlock memFilters;
131 H_CacheFilter filter;
136 size =
sizeof(S_FiltBlock) + (NUM_FILTERS *
sizeof(S_CacheFilter));
137 memFilters = sfm->setup.memAlloc( size );
138 if (memFilters == NULL)
144 memset(memFilters, 0, size);
145 filter = (H_CacheFilter)(memFilters + 1);
146 if (cache->filtHead == NULL)
148 cache->filtHead = filter;
152 ASSERT( cache->filtTail != NULL )
153 cache->filtTail->next = filter;
155 for (size = NUM_FILTERS - 1; size--; filter++)
157 filter->next = (filter + 1);
160 cache->filtTail = filter;
161 memFilters->next = cache->memFilters;
162 cache->memFilters = memFilters;
168 static void FreeFiltBlocks(
H_SfmInstance sfm, H_FiltBlock memFilters )
171 while (memFilters != NULL)
173 memNext = memFilters->next;
174 sfm->setup.memFree( memFilters );
175 memFilters = memNext;
179 static BOOLEAN AllocNodeBlock( H_SfmCache cache )
181 H_NodeBlock memNodes;
187 size =
sizeof(S_NodeBlock) + (NUM_NODES *
sizeof(S_CacheNode));
188 memNodes = sfm->setup.memAlloc( size );
189 if (memNodes == NULL)
195 memset(memNodes, 0, size);
196 node = (H_CacheNode)(memNodes + 1);
197 if (cache->nodeHead == NULL)
199 cache->nodeHead = node;
203 ASSERT( cache->nodeTail != NULL )
204 cache->nodeTail->next = node;
206 for (size = NUM_NODES - 1; size--; node++)
208 node->next = (node + 1);
211 cache->nodeTail = node;
212 memNodes->next = cache->memNodes;
213 cache->memNodes = memNodes;
219 static void FreeNodeBlocks(
H_SfmInstance sfm, H_NodeBlock memNodes )
222 while (memNodes != NULL)
224 memNext = memNodes->next;
225 sfm->setup.memFree( memNodes );
230 static H_CacheNode AddCacheNode( H_SfmCache cache, H_CacheFilter cfilter, U8BIT *buff )
234 if (cache->nodeHead == NULL && !AllocNodeBlock( cache ))
240 cnode = cache->nodeHead;
241 cache->nodeHead = cache->nodeHead->next;
243 cnode->next = cfilter->node;
244 cfilter->node = cnode;
250 static void FreeCacheFilt( H_SfmCache cache, H_CacheFilter filter )
252 filter->vers = INVALID_VERSION;
253 if (cache->filtHead == NULL)
255 cache->filtHead = filter;
259 ASSERT( cache->filtTail != NULL )
260 cache->filtTail->next = filter;
263 cache->filtTail = filter;
266 static
void FreeCacheNode( H_SfmCache cache, H_CacheNode node )
269 U32BIT size = ALLOCSIZE(node->sbuf[1]);
270 if (cache->allocated >= size)
272 cache->allocated -= size;
276 if (cache->nodeHead == NULL)
278 cache->nodeHead = node;
282 ASSERT( cache->nodeTail != NULL )
283 cache->nodeTail->next = node;
286 cache->nodeTail = node;
296 static BOOLEAN CacheValidNode( H_SfmCache cache,
void *ptr )
298 H_NodeBlock memNodes;
305 size =
sizeof(S_NodeBlock) + (NUM_NODES *
sizeof(S_CacheNode));
306 memNodes = cache->memNodes;
307 while (memNodes != NULL)
309 mval = (PU8BIT)memNodes;
310 if (pval > mval && pval < mval + size)
315 memNodes = memNodes->next;
320 static void CacheClearNodes( H_SfmCache cache, H_CacheFilter cfilter )
322 H_CacheNode cnode, cnext;
323 if (cfilter->node != NULL)
325 cnode = cfilter->node;
329 FreeCacheNode( cache, cnode );
332 while (cnode != NULL);
334 cfilter->node = NULL;
338 static void CacheClearFilters( H_SfmCache cache, H_CacheTable ctable )
340 H_CacheFilter cfilter;
343 for (ndx = 0; ndx != TABLE_SIZE; ndx++)
345 cfilter = ctable->filters[ndx];
346 while (cfilter != NULL)
348 CacheClearNodes( cache, cfilter );
349 cfilter = cfilter->next;
354 static void CtablePurgeExpired( H_SfmCache cache, H_CacheTable ctable )
356 H_CacheFilter cfilter, *pCfilter;
360 for (ndx = TABLE_SIZE; ndx--; )
362 if (ctable->changed[ndx] & STALE_BIT)
364 ctable->changed[ndx] &= ~(STALE_BIT);
365 pCfilter = &(ctable->filters[ndx]);
366 while (*pCfilter != NULL)
369 if (cfilter->vers == STALE_VERSION)
371 CacheClearNodes( cache, cfilter );
372 *pCfilter = cfilter->next;
373 FreeCacheFilt( cache, cfilter );
377 pCfilter = &(cfilter->next);
392 ctable = cache->ctables;
394 DBGLOG(DF_CACHE,
"Purging stale nodes")
395 for (ndx = (sfm->setup.maxPidFilters << 1); ndx--; ctable++)
397 CtablePurgeExpired( cache, ctable );
410 static void ReportSections(
H_SfmInstance sfm, H_CacheFilter cfilter,
411 E_SFM_STATUS status )
414 cnode = cfilter->node;
415 while (cnode != NULL)
417 cnode->report = REPORTING;
418 DBGLOG(DF_CACHE,
"CACHE HIT: sz=0x%x t=0x%x e=0x%x, %d, %d status=%d",
419 (((
int)(cnode->sbuf[1] & 0x0f) << 8) | cnode->sbuf[2]) + 3, *cnode->sbuf,
420 ((cnode->sbuf[3] << 8) | cnode->sbuf[4]), cnode->sbuf[6] + 1, cnode->sbuf[7] + 1, status)
421 sfm->setup.cacheMatch( sfm, cnode->sbuf, cfilter, status );
432 static H_CacheFilter FindFilter(
H_SfmInstance sfm, H_CacheTable ctable, U16BIT tide )
434 H_CacheFilter cfilter;
436 index = HashIndex(tide, TABLE_BITS);
438 cfilter = ctable->filters[index];
439 while (cfilter != NULL)
441 if (cfilter->tide == tide &&
442 cfilter->vers != STALE_VERSION)
446 cfilter = cfilter->next;
452 void *hBuffer, E_SFM_STATUS status )
454 FUNCTION_START(CacheMatch)
456 FUNCTION_FINISH(CacheMatch)
468 setup.memAlloc = sfm->setup.memAlloc;
469 setup.memFree = sfm->setup.memFree;
470 setup.lock = sfm->setup.mutexLock;
471 setup.unlock = sfm->setup.mutexUnlock;
472 setup.mtx_sem = sfm->setup.bufferMutex;
473 setup.bufferSize = sfm->setup.sectionBuffCacheSize;
478 sfm->setup.sectionBuffCacheSize = 0;
483 size =
sizeof(S_SfmCache) +
484 (sfm->setup.maxPidFilters *
sizeof(S_CacheTable) * 2);
485 cache = sfm->setup.memAlloc( size );
489 sfm->setup.sectionBuffCacheSize = 0;
494 memset(cache, 0, size);
497 if (AllocNodeBlock( cache ))
499 cache->ctables = (H_CacheTable)(cache + 1);
500 if (sfm->setup.cacheMatch == NULL)
502 sfm->setup.cacheMatch = CacheMatch;
504 cache->counter = sfm->setup.maxPidFilters * 2;
506 cache->allocated = 0;
512 sfm->setup.memFree( cache );
528 FreeNodeBlocks( sfm, cache->memNodes );
529 FreeFiltBlocks( sfm, cache->memFilters );
531 sfm->setup.memFree( cache );
550 ctable = cache->ctables;
552 for (ndx = (sfm->setup.maxPidFilters << 1); ndx--; ctable++)
554 CacheClearFilters( cache, ctable );
559 H_CacheTable SFMCacheGetTable( H_SfmCache cache )
562 if (cache->counter == 0)
569 ctable = cache->ctables + cache->counter;
582 U16BIT teid, U8BIT vers )
584 H_SfmCache cache = sfm->cache;
585 H_CacheFilter cfilter, *pFilter;
587 index = HashIndex(teid, TABLE_BITS);
588 pFilter = ctable->filters + index;
591 while (cfilter != NULL)
593 if (cfilter->tide == teid)
595 if (cfilter->vers == vers)
599 DBGLOG(DF_CACHE,
"version changed TEid=0x%x old=%d new=%d", teid, cfilter->vers, vers)
601 cfilter->vers = STALE_VERSION;
602 ctable->changed[index] |= STALE_BIT;
604 cfilter = cfilter->next;
608 if (cache->filtHead != NULL || AllocFiltBlock( cache ))
610 cfilter = cache->filtHead;
611 cache->filtHead = cfilter->next;
612 cfilter->next = NULL;
613 cfilter->tide = teid;
614 cfilter->vers = vers;
615 cfilter->node = NULL;
616 cfilter->ctndx = ctable - cache->ctables;
617 cfilter->next = *pFilter;
640 H_SfmCache cache = sfm->cache;
641 H_CacheFilter cfilter;
649 for (cnode = cfilter->node; cnode; cnode = cnode->next)
651 if (cnode->bknum == bknum)
666 DBGLOG(DF_CACHE,
"Cache cannot store sz1=%d allocated=%d (512 byte blks)", ALLOCSIZE(size1), cache->allocated)
671 cnode = AddCacheNode( cache, cfilter, buff );
679 cnode->bknum = bknum;
682 cache->allocated += ALLOCSIZE(size1);
705 if (!CacheValidNode( sfm->cache, hBuffer ))
707 ERRLOG(
"Invalid pointer!")
712 buff = ((H_CacheNode)hBuffer)->sbuf;
727 H_CacheFilter cfilter = (H_CacheFilter)hBuffer;
728 H_CacheNode *ppNode, cnode;
729 ppNode = &cfilter->node;
730 while (*ppNode != NULL)
733 if (cnode->sbuf == pSection)
735 if (cnode->bknum != pSection[6])
737 ERRLOG(
"Mis-matched of buffer data with node (0x%x,0x%x)", cnode->bknum, pSection[6])
741 *ppNode = cnode->next;
742 FreeCacheNode( sfm->cache, cnode );
746 ppNode = &(cnode->next);
759 H_FiltBlock memFilters;
766 size =
sizeof(S_FiltBlock) + (NUM_FILTERS *
sizeof(S_CacheFilter));
767 memFilters = sfm->cache->memFilters;
768 while (memFilters != NULL)
770 mval = (PU8BIT)memFilters;
771 if (pval > mval && pval < mval + size)
776 memFilters = memFilters->next;
792 H_CacheNode *ppNode, cnode;
793 ppNode = &cfilter->node;
794 while (*ppNode != NULL)
797 if (cnode->sbuf == pSection)
799 if (cnode->bknum != pSection[6])
801 ERRLOG(
"Mis-matched of buffer data with node (0x%x,0x%x)", cnode->bknum, pSection[6])
806 *ppNode = cnode->next;
807 FreeCacheNode( sfm->cache, cnode );
811 ppNode = &(cnode->next);
823 U16BIT dsmref, E_SFM_STATUS status )
825 H_CacheFilter cfilter;
829 cfilter = FindFilter( sfm, ctable, tex.id ^ 0x0001 );
832 cfilter->dsmref = dsmref;
833 ReportSections( sfm, cfilter, status );
836 cfilter = FindFilter( sfm, ctable, tex.id );
839 cfilter->dsmref = dsmref;
840 ReportSections( sfm, cfilter, status );
850 for (ndx = 0; ndx != TABLE_SIZE; ndx++)
852 cfilter = ctable->filters[ndx];
853 while (cfilter != NULL)
855 if ((cfilter->tide & tex.mask) == tex.id &&
856 cfilter->vers != STALE_VERSION)
858 cfilter->dsmref = dsmref;
859 ReportSections( sfm, cfilter, status );
861 cfilter = cfilter->next;
867 CachePurgeExpired( sfm );
U8BIT * SFM_CacheBuffer(H_SfmInstance sfm, void *hBuffer)
Get section data buffer pointer in SFM's cache for the handle. This should only be called after SFM_R...
H_CacheFilter SFMCacheRetrieveFilter(H_SfmInstance sfm, H_CacheTable ctable, U16BIT teid, U8BIT vers)
Search cache for section data.
void SFMFilterProcessSection(H_SfmInstance sfm, U8BIT *pSection, H_DsmResource pDsmRes)
Get DSM-CC filter request and pass section buffer to DSM-CC with it's filter handle This should only ...
U8BIT * SBM_AllocateBuffer(H_SbmInstance sbm, U8BIT size1)
Allocate buffer for a DVB section.
void SFMCacheAddBlock(H_SfmInstance sfm, U8BIT size1, U8BIT bknum, void **phBuffer)
Allocates space in cache for section data If allocation is made, *phBuffer has holds cache location...
H_SbmInstance SBM_CreateInstance(S_SbmSetup *pSetup)
Create Section Buffer Manager instance, using setup structure.
Section Filter Manasger (SFM): cache definitions.
Section Filter Manager (SFM): filters.
void SFMCacheProcessSection(H_SfmInstance sfm, U8BIT *pSection, H_CacheFilter cfilter)
Tells SFM Cache to update DSM-CC with cached buffer (reported to F_CacheMatch callback funtion...
Section Filter Manager (SFM): main definitions.
void SBM_DestroyInstance(H_SbmInstance sbm, void **pBufMtx)
Destroy Section Filter Manager instance, and return mutexes so that they may be destroyed by client...
void SBM_ReleaseBuffer(H_SbmInstance sbm, U8BIT *buffer)
Release DVB section buffer allocated with SBM_AllocateBuffer.
void SFMCacheSearch(H_SfmInstance sfm, H_CacheTable ctable, S_TableExt tex, U16BIT dsmref, E_SFM_STATUS status)
Search cache for section data.
Section Buffer Manager (for use by Section Filter Manager and client) Provides mechanism to allocate ...
BOOLEAN SFMCacheValidHandle(H_SfmInstance sfm, void *ptr)
void SFM_CacheReleaseBuffer(H_SfmInstance sfm, U8BIT *pSection, void *hBuffer)
Release Cache buffer allocated by SFM_CacheBuffer.
void SFM_CacheClear(H_SfmInstance sfm)
Clear all SFM cached section data.