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 + -
显示快捷键?