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

📄 xp_osi_inter.c

📁 IBM source for pallas/vulcan/vesta
💻 C
📖 第 1 页 / 共 3 页
字号:
/*----------------------------------------------------------------------------+|     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 :  xp|   File      :  xp0_inter.c|   Purpose   :  Interrupt Management|   Changes   :||   Date       By   Comments|   ---------  ---  ---------------------------------------------------------|   15-Jan-98  IG   Created|   22-Jun-99  PAG  Only clear unmasked status interrupt bits.|   30-Sep-01  LGH  Ported to Linux, combined codes of 3 devices|+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+|                   Interrupt processing & management+-----------------------------------------------------------------------------+||   The following functions provide interrupt services for the demux|   driver.  A large number of interrupts are available to the demux|   driver.  The hardware provides a set of interrupt registers which are|   organized in a hierarchical manner, with the primary interrupt register|   at the top of the hierarchy.  Status registers for audio, video, and|   channel registers provide the secondary interrupt layer.  See the demux|   specification for more detailed information.||   The demux driver processes all interrupts signaled by the transport|   hardware.  The primary interrupt register is read and cleared before|   executing any callback function which may have been registered.  This|   is done to minimize the loss of any future interrupts delivered by the|   hardware.  Information in the primary interrupt register indicates if|   there are any status, audio, video, or channel interrupts pending.|   Other primary interrupts such as clock recovery are processed first,|   followed by the secondary interrupts.||   The interface provided by the demux driver features the registration of|   callback functions for each type of interrupt in any of the interrupt|   registers.  Multiple functions may register their callback functions|   for the same or a different set of interrupts.  Callback functions are|   called in the order of their registration.||   There are three callback functions which process the primary, status,|   and channel interrupts.  The registration of callback functions require|   a bit mask (channel interrupts also require a channel_id). This bit|   mask indicates the interrupt types being registered for notification.|   Only one callback is made for each registration no matter how many bits|   may be set.||   To minimize the number of interrupts received from the hardware, the|   union of all the interrupt masks registered with callback functions is|   calculated.  This value is used to set the hardware masks.|+----------------------------------------------------------------------------*//* 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/slab.h>#include <linux/interrupt.h>#endif#include "hw/hardware.h"#include "xp_osi_global.h"#include "xp_atom_reg.h"/*----------------------------------------------------------------------------+| Local Defines+----------------------------------------------------------------------------*/#define QSTAT_INTERRUPT_MASK        0x0000FFFF  /* Valid Queue Status bits       */#define XP0_FESTAT_INTERRUPT_MASK   0x00007F3F  /* Valid Front-End Status bits   */#define XP0_PRIMARY_INTERRUPT_MASK  0xFFFE0003  /* Valid Primary Interrupt bits  */#define XP0_PRIMARY_SET_MASK        0xF0000000  /* Primary Ints auto enabled     */#define XP12_FESTAT_INTERRUPT_MASK   0x0000713F  /* Valid Front-End Status bits   */#define XP12_PRIMARY_INTERRUPT_MASK  0xC6CE0000  /* Valid Primary Interrupt bits  */#define XP12_PRIMARY_SET_MASK        0xC0000000  /* Primary Ints auto enabled     */#define QUEUE_SIZE  20typedef struct xp_os_msg_type{    GLOBAL_RESOURCES *pGlobal;    SHORT   wChannelId;                     /* channel id for the interrupt     */    ULONG   ulInterrupt;                    /* interrupt vector for channel     */    XP_INTERRUPT_CHANNEL_FN notify_fn;      /* callback function                */} XP_OS_MSG_TYPE, *XP_OS_MSG_PTR;/*----------------------------------------------------------------------------+| Static Variables+----------------------------------------------------------------------------*/static GLOBAL_RESOURCES *pXp0Global;static GLOBAL_RESOURCES *pXp1Global;static GLOBAL_RESOURCES *pXp2Global;/*----------------------------------------------------------------------------+| Local Prototype Definitions+----------------------------------------------------------------------------*///Internalstatic void process_channel_interrupt(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId);static void status_interrupt(GLOBAL_RESOURCES *pGlobal);static void audio_interrupt(GLOBAL_RESOURCES *pGlobal);static void video_interrupt(GLOBAL_RESOURCES *pGlobal);static void channel_interrupt(GLOBAL_RESOURCES *pGlobal);static SHORT add_mask(GLOBAL_RESOURCES *pGlobal,ULONG ulMask,PFS notify_fn,                      INTERRUPT_INFO_PTR pInfo);static SHORT del_mask(GLOBAL_RESOURCES * pGlobal,ULONG ulMask,PFS notify_fn,                      INTERRUPT_INFO_PTR pInfo);static void reset_mask(GLOBAL_RESOURCES *pGlobal,INTERRUPT_INFO_PTR pInfo);/*----------------------------------------------------------------------------+| 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+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+|  process_channel_interrupt+-----------------------------------------------------------------------------+||  FUNCTION    :  process_channel_interrupt||  DESCRIPTION :  process interrupts for audio, video, and system channels|+----------------------------------------------------------------------------*/static void process_channel_interrupt(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId){    short i, j;    unsigned long addr;    unsigned long interrupt;    XP_OS_MSG_TYPE msg;    switch(wChannelId)    {    case XP_INTERRUPT_VIDEO:        addr  = XP_DCR_ADDR_VSTATUS;        break;    case XP_INTERRUPT_AUDIO:        addr  = XP_DCR_ADDR_ASTATUS;        break;    default:        addr  = XP_DCR_ADDR_BASE_QSTAT + wChannelId;        break;    }    /*------------------------------------------------------------------------+    |  Read & clear the primary interrupts    +------------------------------------------------------------------------*///  flag = os_enter_critical_section();    interrupt = xp_atom_dcr_read(pGlobal->uDeviceIndex,addr);    xp_atom_dcr_write(pGlobal->uDeviceIndex, addr, interrupt);//  os_leave_critical_section(flag);    for(i=0, j=0; i<pGlobal->InterInfo.XpInterChanInt[wChannelId].wNotifyAlloc &&                  j<pGlobal->InterInfo.XpInterChanInt[wChannelId].wNotifyCount; i++)    {        if(interrupt & pGlobal->InterInfo.XpInterChanInt[wChannelId].pNotify[i].ulMask)        {            j++;            /*----------------------------------------------------------------+            |  Process the current interrupt by adding the work to the            |  Task queue. Note: direct call is            |  (*notify_fn)(channel_id, interrupt)            +----------------------------------------------------------------*/            if (pGlobal->InterInfo.XpInterChanInt[wChannelId].pNotify[i].notify_fn)            {                msg.pGlobal    = pGlobal;                msg.wChannelId = wChannelId;                msg.ulInterrupt  = interrupt;                msg.notify_fn  = (XP_INTERRUPT_CHANNEL_FN)                    pGlobal->InterInfo.XpInterChanInt[wChannelId].pNotify[i].notify_fn;                 if(os_call_irq_task(XP_IRQ,&msg))                 {                     ;                 }            }        }    }}/*----------------------------------------------------------------------------+|  status_interrupt+-----------------------------------------------------------------------------+||  FUNCTION    :  status_interrupt||  DESCRIPTION :  process all status interrupts|+----------------------------------------------------------------------------*/static void status_interrupt(GLOBAL_RESOURCES *pGlobal){    short i, j;    unsigned long interrupt;    /*------------------------------------------------------------------------+    |  Read & clear the primary interrupts    +------------------------------------------------------------------------*/    //flag = os_enter_critical_section();    interrupt = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_FESTAT) &                xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_FEIMASK);    xp_atom_dcr_write(pGlobal->uDeviceIndex, XP_DCR_ADDR_FESTAT, interrupt);    //os_leave_critical_section(flag);    for(i=0, j=0; i<pGlobal->InterInfo.XpInterStatInt.wNotifyAlloc &&                  j<pGlobal->InterInfo.XpInterStatInt.wNotifyCount; i++)    {        if(interrupt & pGlobal->InterInfo.XpInterStatInt.pNotify[i].ulMask)        {            j++;            if(pGlobal->InterInfo.XpInterStatInt.pNotify[i].notify_fn)            {              (*pGlobal->InterInfo.XpInterStatInt.pNotify[i].notify_fn)(pGlobal, interrupt);            }        }    }}/*----------------------------------------------------------------------------+|  audio_interrupt+-----------------------------------------------------------------------------+||  FUNCTION    :  audio_interrupt||  DESCRIPTION :  process all status interrupts|+----------------------------------------------------------------------------*/static void audio_interrupt(GLOBAL_RESOURCES *pGlobal){    process_channel_interrupt(pGlobal,XP_INTERRUPT_AUDIO);}/*----------------------------------------------------------------------------+|  video_interrupt+-----------------------------------------------------------------------------+||  FUNCTION    :  video_interrupt||  DESCRIPTION :  process all status interrupts|+----------------------------------------------------------------------------*/static void video_interrupt(GLOBAL_RESOURCES *pGlobal){    process_channel_interrupt(pGlobal,XP_INTERRUPT_VIDEO);}/*----------------------------------------------------------------------------+|  channel_interrupt+-----------------------------------------------------------------------------+||   FUNCTION    :  channel_interrupt||   DESCRIPTION :  process all the channel interrupts|+----------------------------------------------------------------------------*/static void channel_interrupt(GLOBAL_RESOURCES *pGlobal){    short i;    unsigned long k;    unsigned long ireq;    /*------------------------------------------------------------------------+    |  Get the interrupt vector which shows which channels have an    |  interrupt pending    +------------------------------------------------------------------------*///  flag = os_enter_critical_section();    ireq = xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_QINT) &           xp_atom_dcr_read(pGlobal->uDeviceIndex,XP_DCR_ADDR_QINTMSK);//  os_leave_critical_section(flag);    /*------------------------------------------------------------------------+    |  for each interrupt on a channel, process the interrupts    +------------------------------------------------------------------------*/    for(i=0, k=0x80000000; i<XP_CHANNEL_COUNT; i++, k>>=1) {        if(k & ireq) {            process_channel_interrupt(pGlobal,i);        }    }}/*----------------------------------------------------------------------------+|  add_mask+----------------------------------------------------------------------------*/static SHORT add_mask(GLOBAL_RESOURCES *pGlobal,ULONG ulMask,PFS notify_fn,                      INTERRUPT_INFO_PTR pInfo){    short i;    short index;                            /* array index available         */    INTERRUPT_NOTIFY_PTR pNotify;    /*------------------------------------------------------------------------+    |  Make sure this mask isn't already registered    +------------------------------------------------------------------------*/    for(i=0, index=-1; i<pInfo->wNotifyAlloc; i++)    {        if((ulMask == pInfo->pNotify[i].ulMask) &&           (notify_fn == pInfo->pNotify[i].notify_fn))        {            return(XP_ERROR_INTER_NOTIFY_DUP);        }        if(pInfo->pNotify[i].ulMask == 0)        {            index = i;        }    }    /*------------------------------------------------------------------------+    |  If there is no space, allocate more space    +------------------------------------------------------------------------*/    if (index < 0)    {        if (pInfo->wNotifyAlloc == 0)        {                               //added by lingh            index = pInfo->wNotifyAlloc;            pInfo->wNotifyAlloc += 10;            pNotify = (INTERRUPT_NOTIFY_PTR) MALLOC(pInfo->wNotifyAlloc * sizeof(XP_INTERRUPT_NOTIFY_TYPE));            if(pNotify == NULL)            {                return(XP_ERROR_INTERNAL);            }            pInfo->pNotify = pNotify;        /*------------------------------------------------------------------------+        |  Initialize the new space        +------------------------------------------------------------------------*/            for(i=index; i<pInfo->wNotifyAlloc; i++)            {                pInfo->pNotify[i].ulMask = 0;                pInfo->pNotify[i].notify_fn = NULL;            }        }        else        {             return (XP_ERROR_INTERNAL);    /* which should not happen */        }    }    pInfo->pNotify[index].ulMask      = ulMask;    pInfo->pNotify[index].notify_fn = notify_fn;    pInfo->wNotifyCount++;    return(0);}/*----------------------------------------------------------------------------+|  del_mask+----------------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -