vt82c686pciibc.c

来自「cpc-1631的BSP包for VxWorks操作系统」· C语言 代码 · 共 669 行 · 第 1/2 页

C
669
字号
    (
    int intNum	/*  interrupt level to disable  */
    )
    {

    if (intNum < VT_MAX_IRQS)
        {
        if (intNum < 8)
            {
            sysPicMask1 |= (1 << intNum);
            PIC_BYTE_OUT (PIC1_OCW1, sysPicMask1 | sysPicLevel1 );
            }
        else
            {
            sysPicMask2 |= (1 << (intNum - 8));
            PIC_BYTE_OUT (PIC2_OCW1, sysPicMask2 | sysPicLevel2);
            }

        if ((sysPicMask1 == 0xfb) && (sysPicMask2 == 0xff))
            return (OK);
        else
            return (sysPicMask1 | sysPicMask2);
        }
    else
        {
        return ERROR;
        }
    }

 
/*******************************************************************************
*
* pciIbcIntHandler - handle a vt82c686 interrupt
*
*
* This routine handles an interrupt which may have originated from the
* vt82c686 chip's 8259 controllers. Since we support sharing, it is not
* known whether the interrupt really came from the vt82c686 or was
* actually generated by another device which shares the same IRQ level
* as the vt82c686 chip on the EPIC. So first, the IRR is checked to
* see if an interrupt was pending, and if not the handler is not invoked.
*
* NOMANUAL
*
* RETURNS: N/A
*/

void pciIbcIntHandler
    (
    int arg
    )
    {
    UCHAR 	irrVal1;
    UCHAR 	irrVal2;
    UCHAR 	intVec;
    UCHAR 	winbIntNum;
    int		oldLevel;
    static int  lvl7Int = 0;
    static int  lvl15Int = 0;
	char IMR2=0;
	char IRR2=0;
	char ISR2=0;
INT32 oldLock;
    /*
     * read the IRR and check if the interrupt came from the vt82c686
     * This is beause we allow sharing of interrupt vectors between the
     * devices attached directly to the EPIC and the ones controlled by
     * the vt82c686 chip.
     */
#if 0
     	    PIC_BYTE_IN (0xa1, &IMR2);		
		logMsg("8259 IMR2 = %d\n",IMR2,0,0,0,0,0);
	    /* check cascaded 8259 */
	    PIC_BYTE_OUT (0xa0, 0x08+0x02);
	    PIC_BYTE_IN (0xa0, &IRR2);		
		logMsg("8259 IRR2 = %d\n",IRR2,0,0,0,0,0);
	    PIC_BYTE_OUT (0xa0, 0x08+0x03);
	    PIC_BYTE_IN (0xa0, &ISR2);		
		logMsg("8259 ISR2 = %d\n",ISR2,0,0,0,0,0);
#endif
    /*读取中断请求寄存器(IRR)*/
    PIC_BYTE_OUT (PIC1_OCW3, 0x08+0x02);

    PIC_BYTE_IN (PIC1_OCW3, &irrVal1);
	
	/*logMsg("8259 irrVal1 = %d\n",irrVal1,0,0,0,0,0);*/

    /* check cascaded 8259 */
    PIC_BYTE_OUT (PIC2_OCW3, 0x08+0x02);
    PIC_BYTE_IN (PIC2_OCW3, &irrVal2);
	
	/*logMsg("8259 irrVal2 = %d\n",irrVal2,0,0,0,0,0);*/
	
	/*如果没有中断请求,
	表明vt82c686使用中断被EPIC其他设备复用
	,在此不用处理*/
    if ((irrVal1 == 0)&&(irrVal2 == 0))
        {
        return;
        }
    oldLock = intLock ();		/* LOCK INTERRUPT */

    /*
     * reading ISA_INTR_ACK_REG generates PCI IACK cycles on the PCI bus
     * which will cause the PIC to put out the vector on the bus.
     * This occurs because Bit 5 of the PCI control reg in the PIC is 
     * programmed to 1 by default.
     */

    MEM_READ(PCI_MSTR_IACK_LOCAL, &intVec); 	/* read the vector */

	/*logMsg("8259 intVec = %d\n",intVec,0,0,0,0,0);*/

    if ((intVec == 0xff) || (intVec > INT_NUM_IRQ0 +VT_MAX_IRQS))
        {
        /* bogus vector value on bus i.e. interrupt not meant for vt82c686 */
        return;
        }

    winbIntNum = intVec - INT_VEC_IRQ0;

    /* 
     * In both edge and level triggered modes, the IR inputs must
     * remain high until until after the falling edge of the first
     * !INTA. If the IR input goes low before this time a DEFAULT
     * IR7 will occur when the CPU acknowleges the interrupt. This
     * can be a useful safeguard for detecting interrupts caused by
     * spurious noise glitches on the IR inputs.  (sic) 
     */

    if ((winbIntNum & 7) == 7)   /* Special check for phantom interrupts */
        {
        if (sysPicPhantomInt (&winbIntNum, lvl7Int, lvl15Int) == TRUE)
            {
            return;             /* It's phantom so just return. */
            }
        }
      
    /* Keep track of level 7 & 15 nesting for phantom interrupt handling */

    if (winbIntNum == 7)
        {
        lvl7Int++;
        }
    else if (winbIntNum == 15) /* yellowknife code has a bug here */
        {
        lvl15Int++;
        }
 
    /* mask this interrupt level and lower priority interrupt levels */

    oldLevel = sysPicLevelCur;

    sysPicIntLevelSet (winbIntNum); 

    /* Re-arm (enable) the interrupt chip */


    sysEpicIntHandlerExec (intVec);
	
        WRS_ASM ("sync");

	    sysPicEndOfInt (winbIntNum);
        WRS_ASM ("sync");


    if (winbIntNum == 7)
        {
        lvl7Int--;
        }
    else if (winbIntNum == 15)
        {
        lvl15Int--;
        }
      
    /*  set the original interrupt mask back the way it was */
   sysPicIntLevelSet (oldLevel);

    intUnlock (oldLock);				/* UNLOCK INTERRUPT */

    }

/*******************************************************************************
*
* sysPicEndOfInt - send EOI(end of interrupt) signal.
*
* NOTES
*
* This routine is called at the end of the interrupt handler to
* send a non-specific end of interrupt (EOI) signal.
*
* The second PIC is acked only if the interrupt came from that PIC.
* The first PIC is always acked.
*
* RETURNS: N/A
*/

LOCAL void  sysPicEndOfInt
    (
    int intNum
    )
    {
    if (intNum > 7)
	{
        PIC_BYTE_OUT (PIC2_OCW2, 0x20); /* 0010 0000*/
	}
    PIC_BYTE_OUT (PIC1_OCW2, 0x20); /* 0010 0000*/
    }  /* End of sysPicEndOfInt	 */

/*******************************************************************************
*
* sysPicIntLevelSet - set the interrupt priority level
*
* NOTES
*
* This routine masks interrupts with real priority equal to or lower than
* <intNum>.  The special
* value 16 indicates all interrupts are enabled. Individual interrupt
* numbers have to be specifically enabled by sysPicIntEnable() before they
* are ever enabled by setting the interrupt level value.
*
* Note because of the IBM cascade scheme, the actual priority order for
* interrupt numbers is (high to low) 0, 1, 8, 9, 10, 11, 12, 13, 14, 15,
* 3, 4, 5, 6, 7, 16 (all enabled)
*
* INTERNAL: It is possible that we need to determine if we are raising
* or lowering our priority level.  It may be that the order of loading the
* two mask registers is dependent upon raising or lowering the priority.
*
* RETURNS: N/A
*/

void  sysPicIntLevelSet
    (
    int intNum   /*  interrupt level to implement  */
    )
    {
    if (intNum > 16)
	intNum = 16;

    sysPicLevelCur = intNum;

    if (sysPicLevel2 != sysPicPriMask2[intNum])
	{
	sysPicLevel2 = sysPicPriMask2[intNum];
	PIC_BYTE_OUT (PIC2_OCW1, sysPicMask2 | sysPicLevel2);
	}

    if (sysPicLevel1 != sysPicPriMask1[intNum])
	{
	sysPicLevel1 = sysPicPriMask1[intNum];
	PIC_BYTE_OUT (PIC1_OCW1, sysPicMask1 | sysPicLevel1);
	}
    }  /*  end of sysPicIntLevelSet	*/

/*******************************************************************************
*
* sysPicPhantomInt - Determine if IRQ interrupt number 7 or 15 is "phantom".
*
* NOTES
*
* This routine determines if an IRQ number of 7 or 15 is a phantom
* interrupt.  According to Intel 82C59A-2 documentation, the IR (interrupt
* request) inputs must remain high until after the falling edge of the first
* INTA (interrupt acknowledge).  If the IR goes low before this, a DEFAULT
* (phantom) IRQ7 will occur when the CPU acknowledges the interrupt.  Note
* that if an IRQ7 is generated it may really be another interrupt, IRQ4 for
* example.  IRQ 7 is associated  with the master 8259, IRQ 15 is associated 
* with the slave 8259.  This function should only be called if the 
* acknowledged IRQ number is 7 or 15 but does behave sanely if called with
* other IRQ numbers.
*
* RETURNS: TRUE if phantom IRQ, *intNum unaltered.
*          FALSE if not phantom interrupt, *intNum is "real" IRQ number.
*/
        
LOCAL UCHAR sysPicPhantomInt
    (
    UCHAR *intNum,      /* interrupt number received on acknowledge */
    int   lvl7Int,      /* interrupt 7 nesting level */
    int   lvl15Int      /* interrupt 15 nesting level */
    )
    {
    UINT irqBit;
    UINT irqNum;
    switch (*intNum)
        {
        case 7:
        
            /* Read the in-service register (ISR) */
        
            PIC_BYTE_OUT (PIC1_OCW3, 0x08+0x03);
            PIC_BYTE_IN (PIC1_OCW3, &irqBit);
        
            if (irqBit == 0)
                return (TRUE);  /* No in-service int so it MUST be phantom */
            else
                {
                for (irqNum = 0; ((irqBit & 1) == 0) ; irqNum++, irqBit >>= 1)
                            ;
                if (irqNum == 7)
                    if (lvl7Int > 1)
                        return (TRUE); /* We're nested so it MUST be phantom */
                *intNum = irqNum;
                return (FALSE);
                }
            break;
        
        case 15:
        
            /* Read the in-service register (ISR) */
        
            PIC_BYTE_OUT (PIC2_OCW3, 0x08+0x03);
            PIC_BYTE_IN (PIC2_OCW3, &irqBit);
        
            if (irqBit == 0)
                return (TRUE);  /* No in-service int so it MUST be phantom */
            else
                {
                for (irqNum = 8; ((irqBit & 1) == 0) ; irqNum++, irqBit >>= 1)
                            ;
                if (irqNum == 15)
                    if (lvl15Int > 1)
                        return (TRUE);  /* Were nested so it MUST be phantom */
                *intNum = irqNum;
                return (FALSE);
                }
            break;
        
        default:
            return (FALSE);
        }
    }

⌨️ 快捷键说明

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