⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xp_osi_filte.c

📁 IBM source for pallas/vulcan/vesta
💻 C
📖 第 1 页 / 共 5 页
字号:
/*----------------------------------------------------------------------------+|   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 + -