📄 xp_osi_filte.c
字号:
/*----------------------------------------------------------------------------+| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1998| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Author : Ian Govett| Component : xp0| File : xp0_filte.c| Purpose : Section filter management| Changes :|| Date By Comments| --------- --- ------------------------------------------------------| 15-Jan-98 IG Created| 04-May-01 IG Updated for Pallas| 30-Sep-01 LGH Ported to Linux, combined codes 0f 3 devices| 29-Oct-02 LGH Add negative filter support for VESTA+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Section Filter Management+-----------------------------------------------------------------------------+|| The following functions provide section filter management for the demux| driver. Section filters are allocated for a user-specified number of| bytes using the xp0_filter_allocate() function. The caller is returned| a unique filter_id which is used with subsequent operations on the| filter. Section filters are defined or modified using the| xp0_filter_set() function. This function uses the data, mask, and| polarity fields to define the filter characteristics. The caller| provides an array of bytes to specify each of the data, mask, and| polarity fields. These fields are mapped to hardware registers (bytes| 2 & 3 are skipped by the hardware).|| It is possible for section filters to be longer than the table section| present in the stream. The function xp0_filter_short(), can be used to| define the match characteristic (hit, or miss) when the section filter| length exceeds the section length. By default, short filters are| considered a filter match.|| Section filters are added to a channel using| xp0_filter_add_to_channel(). function which returns a unique match_id| number. Multiple filters may be assigned to the same channel (max of| 32 filters per channel), each with a unique match_id. The match_id is| a component of the match word discussed in the next section. The| hardware link registers are automatically updated by this function when| filters are added.|| The xp0_filter_delete_from_channel() removes the filter from the channel.| As each filter is removed, the hardware links are automatically updated| by the function. The channel is disabled if the last filter is removed| from a channel defined with section filtering.|| Table sections are processed and delivered by the transport demux| driver. The application registers a callback function using the| xp0_channel_set_notification_fn(). This callback function is provided| the location (address in memory) of the table section, length of the| data, wChannelId, and a match word. The match word is a 32-bit| unsigned value whose bit positions indicate which filters matched. The| match_id value (returned from xp0_filter_add_to_channel()) described| above is a bit position in the match word. Using the match word, an| application can quickly determine which filters matched the table| section. Note: the bit positions in the match word are number 0..31| where bit 0 is the most significant (left-most) bit, and bit 31 is the| least significant bit.|| For example, suppose three filters are allocated (xp0_filter_allocate),| defined (xp0_filter_set), and added (xp0_filter_add_to_channel) to a| channel. The filter id's returned from xp0_filter_allocate(), and the| match id's returned from xp0_filter_add_to_channel() could be:|| filter_id match_id| -----------------------| 23 0| 18 2| 36 8|| The application may need to maintain a relationship between the filter| id's and match id's for each channel.|| Now suppose a table section is delivered to the application with a| match word of 0x80800000, then filter id number 23, and 36 were a "hit".| Or suppose the match word as 0xA0000000, then filter id's 23, and 18| were a "hit".|+----------------------------------------------------------------------------*//* The necessary header files */#if 0#include <linux/config.h>#include <linux/version.h>#ifdef MODVERSIONS#include <linux/modversions.h>#endif#define __NO_VERSION__#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/interrupt.h>#endif#include "xp_osi_global.h"#include "xp_atom_reg.h"/*----------------------------------------------------------------------------+| Local Defines+----------------------------------------------------------------------------*/#define FILTER_ID_UNUSED XP_FILTER_MAX_BLOCKS#define PSI_HEADER_LENGTH 3/*----------------------------------------------------------------------------+| Local Type Declarations+----------------------------------------------------------------------------*/typedef struct psi_header_type { unsigned table_id:8; /* table type */ unsigned syntax_ind:1; /* section syntax indicator */ unsigned private_ind:1; /* private indicator on type private */ unsigned reserved_1:2; /* */ unsigned sectionLength:12; /* length of the remaining data */ unsigned reserved_2:8;} PSI_HEADER_TYPE, *PSI_HEADER_PTR;//Internalstatic SHORT reserve_hw_blocks(GLOBAL_RESOURCES *pGlobal, USHORT uwBlockCount, UCHAR *pBlocks);static void clear_hw_block(GLOBAL_RESOURCES *pGlobal,SHORT wIndex);static void init_filter_links(GLOBAL_RESOURCES *pGlobal,FILTER_TYPE *pFilter);static void update_links(GLOBAL_RESOURCES *pGlobal, SHORT wId1, SHORT wId2);static void write_dram_filter(GLOBAL_RESOURCES *pGlobal, FILTER_TYPE *pFilter, USHORT uwCount, ULONG ulData, ULONG ulMask, ULONG ulControl, ULONG ulPolarity);static SHORT filter_match(GLOBAL_RESOURCES *pGlobal,FILTER_PTR pFilter, XP_CHANNEL_NOTIFY_DATA *pInfo,UCHAR *plBQueue, UCHAR *plEQueue);static void hw_filter_set(GLOBAL_RESOURCES *pGlobal,FILTER_TYPE *pFilter);static short hw_filter_add(GLOBAL_RESOURCES *pGlobal, FILTER_CHANNEL_PTR pChannel, SHORT wChannelId, FILTER_PTR pF2);static short hw_filter_delete(GLOBAL_RESOURCES *pGlobal,SHORT wChannelId,FILTER_PTR pF2);static void free_filter(GLOBAL_RESOURCES *pGlobal, SHORT wFilterId);static SHORT find_filter(GLOBAL_RESOURCES *pGlobal,SHORT wChannelId,SHORT wFilterId, SHORT *pId);static void delete_filter(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, SHORT wFilterId,short i);static void process_section_change(GLOBAL_RESOURCES *pGlobal);static SHORT filter_get_pending(GLOBAL_RESOURCES *pGlobal,SHORT wFilterId, XP_FILTER_PENDING *pPending);//External/*----------------------------------------------------------------------------+| XXXX XX XX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX| XX XXX XX X XX X XX X XX XX XXX XX XXXX XX| XX XXXX XX XX XX X XX XX XXXX XX XX XX XX| XX XX XXXX XX XXXX XXXXX XX XXXX XX XX XX| XX XX XXX XX XX X XX XX XX XXX XXXXXX XX| XX XX XX XX XX X XX XX XX XX XX XX XX XX| XXXX XX XX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| reserve_hw_blocks+----------------------------------------------------------------------------*/static SHORT reserve_hw_blocks(GLOBAL_RESOURCES *pGlobal, USHORT uwBlockCount, /* number of blocks requested */ UCHAR *pBlocks) /* array of block id's returned */{ unsigned short i; USHORT uwCount; /* number of blocks reserved */ /*------------------------------------------------------------------------+ | Find one of the words with a bit available +------------------------------------------------------------------------*/ for(i=0, uwCount=0; (i < XP_FILTER_MAX_BLOCKS) && (uwCount < uwBlockCount); i++) { if(pGlobal->FilterInfo.XpFilterHwData[i].inuse == 0) { pGlobal->FilterInfo.XpFilterHwData[i].inuse = 1; pBlocks[uwCount] = i; uwCount++; } } /*------------------------------------------------------------------------+ | Free the reserved bits which were allocated +------------------------------------------------------------------------*/ if (uwCount < uwBlockCount) { for(i=0; i<uwCount; i++) { pGlobal->FilterInfo.XpFilterHwData[pBlocks[i]].inuse = 0; } return(XP_ERROR_FILTER_UNAVAILABLE); } return(0);}/*----------------------------------------------------------------------------+| clear_hw_block+----------------------------------------------------------------------------*/static void clear_hw_block(GLOBAL_RESOURCES *pGlobal,SHORT wIndex){ if((wIndex >= 0) && (wIndex < XP_FILTER_MAX_BLOCKS)) { pGlobal->FilterInfo.XpFilterHwData[wIndex].inuse = 0; }}/*----------------------------------------------------------------------------+| init_filter_links+----------------------------------------------------------------------------*/static void init_filter_links(GLOBAL_RESOURCES *pGlobal,FILTER_TYPE *pFilter){ unsigned short i; unsigned b1, b2; /* block numbers in the link */ /*------------------------------------------------------------------------+ | Update the link chains +------------------------------------------------------------------------*/ b1 = pFilter->cHwBlockId[0]; pGlobal->FilterInfo.XpFilterHwData[b1].prev = b1; for(i=0; i<pFilter->uwHwBlockCount-1; i++) { b2 = pFilter->cHwBlockId[i+1]; pGlobal->FilterInfo.XpFilterHwData[b1].next = b2; pGlobal->FilterInfo.XpFilterHwData[b2].prev = b1; pGlobal->FilterInfo.XpFilterHwData[b1].endOfColumn = 1; b1 = b2; } pGlobal->FilterInfo.XpFilterHwData[b1].next = b1; pGlobal->FilterInfo.XpFilterHwData[b1].endOfColumn = 1;}/*----------------------------------------------------------------------------+| update_links+----------------------------------------------------------------------------*/static void update_links(GLOBAL_RESOURCES *pGlobal, SHORT wId1, SHORT wId2){ short next; UINT32 flag; next = pGlobal->FilterInfo.XpFilterHwData[wId1].next; /*------------------------------------------------------------------------+ | If the last node hasn't been reached, then copy the forward chain | (id1.next) to id2.next. Update the hardware +------------------------------------------------------------------------*/ if(next != wId1) { pGlobal->FilterInfo.XpFilterHwData[wId2].next = next; pGlobal->FilterInfo.XpFilterHwData[next].prev = wId2; flag = os_enter_critical_section(); xp_atom_dcr_write_filter_link(pGlobal->uDeviceIndex, wId2, pGlobal->FilterInfo.XpFilterHwData[wId2].next, pGlobal->FilterInfo.XpFilterHwData[wId2].endOfColumn); os_leave_critical_section(flag); } /*------------------------------------------------------------------------+ | Now update id1.next to point to id2. Update the hardware +------------------------------------------------------------------------*/ pGlobal->FilterInfo.XpFilterHwData[wId1].next = wId2; pGlobal->FilterInfo.XpFilterHwData[wId2].prev = wId1; pGlobal->FilterInfo.XpFilterHwData[wId1].endOfColumn = 0; flag = os_enter_critical_section(); xp_atom_dcr_write_filter_link(pGlobal->uDeviceIndex, wId1, pGlobal->FilterInfo.XpFilterHwData[wId1].next, pGlobal->FilterInfo.XpFilterHwData[wId1].endOfColumn); os_leave_critical_section(flag);}/*----------------------------------------------------------------------------+| write_dram_filter+----------------------------------------------------------------------------*/static void write_dram_filter(GLOBAL_RESOURCES *pGlobal, FILTER_TYPE *pFilter, /* filter information */ USHORT uwCount, /* filter block index */ ULONG ulData, ULONG ulMask, ULONG ulControl, ULONG ulPolarity){ short filterId; /* filter block number in hardware */ XP_FILTER_CONTROL_REG *pControl; UINT32 flag; pControl = (XP_FILTER_CONTROL_REG *)(void *) &ulControl; /*------------------------------------------------------------------------+ | Determine the next filter block number to setup the links in hardware | Preserve the enabled state if we're already enabled or we're not | in the first filter block +------------------------------------------------------------------------*/ filterId = pFilter->cHwBlockId[uwCount]; if((pFilter->state == XP_FILTER_ENABLED) || (uwCount > 0)) { pControl->enbl = 1; } else { pControl->enbl = 0; } /*------------------------------------------------------------------------+ | Retain current value of endOfColumn during a "Live" filter_set | operation old: pControl->ncol = 1; | Write the filter block +------------------------------------------------------------------------*/ pControl->sfid = pFilter->wMatchId; pControl->ncol = pGlobal->FilterInfo.XpFilterHwData[filterId].endOfColumn; pControl->nfilt = pGlobal->FilterInfo.XpFilterHwData[filterId].next; flag = os_enter_critical_section(); xp_atom_dcr_write_dram_filter(pGlobal->uDeviceIndex,filterId,ulData,ulMask,ulControl,ulPolarity); os_leave_critical_section(flag);}/*----------------------------------------------------------------------------+| filter_match+----------------------------------------------------------------------------*/static SHORT filter_match(GLOBAL_RESOURCES *pGlobal,FILTER_PTR pFilter, XP_CHANNEL_NOTIFY_DATA *pInfo,UCHAR *plBQueue, UCHAR *plEQueue){ short match; unsigned long i; unsigned long length; unsigned char *s; length = (pInfo->ulLength < pFilter->uwLength) ? pInfo->ulLength : pFilter->uwLength; for(i=0, s=pInfo->plData, match=1; i<length && match; i++, s++) { if(s == plEQueue) { s = plBQueue; } if((i != 1) && (i != 2)) { match = ((*s ^ pFilter->cData[i]) & pFilter->cMask[i]) ? 0 : 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -