📄 ioapicintr.c
字号:
return (OK); }/********************************************************************************* ioApicIntLock - lock out all IO APIC interrupts** This routine saves the mask and locks out all IO APIC interrupts.* It should be called in the interrupt disable state(IF bit is 0).** RETURNS: N/A ** SEE ALSO: ioApicIntUnlock()** ARGSUSED0*/LOCAL VOID ioApicIntLock (void) { INT32 ix; INT32 upper32; INT32 lower32; for (ix = 0; ix < ioApicRedEntries; ix++) { ioApicRedGet (ix, &upper32, &lower32); /* lock if the destination is my Local APIC and unlocked */ if ((((upper32 & IOAPIC_DESTINATION) >> 24) == loApicId) && ((lower32 & IOAPIC_INT_MASK) == 0)) { ioApicSet (ioApicBase, ioApicData, IOAPIC_REDTBL + (ix *2), lower32 | IOAPIC_INT_MASK); *(ioApicIntTable + ix) = lower32; /* save the old state */ } } }/********************************************************************************* ioApicIntUnlock - unlock the IO APIC interrupts** This routine restores the mask and unlocks the IO APIC interrupts* It should be called in the interrupt disable state(IF bit is 0).** RETURNS: N/A ** SEE ALSO: ioApicIntLock()** ARGSUSED0*/LOCAL VOID ioApicIntUnlock (void) { INT32 ix; INT32 upper32; INT32 lower32; for (ix = 0; ix < ioApicRedEntries; ix++) { ioApicRedGet (ix, &upper32, &lower32); /* unlock if the destination is my Local APIC and unlocked */ if ((((upper32 & IOAPIC_DESTINATION) >> 24) == loApicId) && ((*(ioApicIntTable + ix) & IOAPIC_INT_MASK) == 0)) { ioApicSet (ioApicBase, ioApicData, IOAPIC_REDTBL + (ix *2), lower32 & ~IOAPIC_INT_MASK); } } }/********************************************************************************* ioApicGet - get a value from the IO APIC register.** This routine gets a value from the IO APIC register.** RETURNS: A value of the IO APIC register.*/INT32 ioApicGet ( UINT32 index, /* IO register select (index) */ UINT32 data, /* IO window (data) */ INT32 offset /* offset to the register */ ) { INT32 value; INT32 oldLevel; oldLevel = intLock (); /* LOCK INTERRUPT */ *(char *)index = (char)offset; /* select the register */ value = *(int *)data; /* must be a 32bit read */ intUnlock (oldLevel); /* UNLOCK */ return (value); }/********************************************************************************* ioApicSet - set a value into the IO APIC register.** This routine sets a value into the IO APIC register.** RETURNS: N/A*/void ioApicSet ( UINT32 index, /* IO register select (index) */ UINT32 data, /* IO window (data) */ INT32 offset, /* offset to the register */ INT32 value /* value to set the register */ ) { INT32 oldLevel; oldLevel = intLock (); /* LOCK INTERRUPT */ *(char *)index = (char)offset; /* select the register */ *(int *)data = value; /* must be a 32bit write */ intUnlock (oldLevel); /* UNLOCK */ }/********************************************************************************* ioApicRedGet - get a specified entry in the Redirection Table** This routine gets a specified entry in the Redirection Table** RETURNS: OK, or ERROR if intNum is out of range*/STATUS ioApicRedGet ( INT32 irq, /* index of the table */ INT32 * pUpper32, /* upper 32 bit (MS LONG) */ INT32 * pLower32 /* lower 32 bit (LS LONG) */ ) { INT32 offset = IOAPIC_REDTBL + (irq * 2); if (irq >= ioApicRedEntries) return (ERROR); *pLower32 = ioApicGet (ioApicBase, ioApicData, offset); *pUpper32 = ioApicGet (ioApicBase, ioApicData, offset + 1); return (OK); }/********************************************************************************* ioApicRedSet - set a specified entry in the Redirection Table** This routine sets a specified entry in the Redirection Table** RETURNS: OK, or ERROR if intNum is out of range*/STATUS ioApicRedSet ( INT32 irq, /* index of the table */ INT32 upper32, /* upper 32 bit (MS LONG) */ INT32 lower32 /* lower 32 bit (LS LONG) */ ) { INT32 offset = IOAPIC_REDTBL + (irq * 2); if (irq >= ioApicRedEntries) return (ERROR); ioApicSet (ioApicBase, ioApicData, offset, lower32); ioApicSet (ioApicBase, ioApicData, offset + 1, upper32); return (OK); }/********************************************************************************* ioApicIrqMove - move interrupt handler from source IRQ to destination IRQ** This routine moves the interrupt handler from the source IRQ to the * destination IRQ. If the source IRQ's interrupt handler is the default * handler, it just returns. Otherwise it is moved and the destination IRQ's * vector table entry will be overridden. This routine is for the chipset* that have programmable IRQ capability. This routine should be called at* the initialization time, otherwise there are no guarantee for losing * interrupts. The polarity and the trigger mode of the IRQ is not changed.** RETURNS: OK, or ERROR if the source intHandler is the default handler.*/STATUS ioApicIrqMove ( INT32 srcIrq, /* source IRQ moving from */ INT32 dstIrq /* destination IRQ moving to */ ) { FUNCPTR intHandler; /* interrupt handler */ INT32 idtType; /* IDT type */ INT32 selector; /* code selector */ INT32 srcInum = INT_NUM_GET (srcIrq); INT32 dstInum = INT_NUM_GET (dstIrq); INT8 * pCode; /* pointer to intConnect code */ INT32 oldLevel; /* lock interrupts */ oldLevel = intLock (); /* LOCK INTERRUPTS */ ioApicIntDisable (srcIrq); ioApicIntDisable (dstIrq); /* get the info from the source IRQ vector table entry */ intVecGet2 ((FUNCPTR *)INUM_TO_IVEC (srcInum), &intHandler, &idtType, &selector); /* return if the intHandler is the default handler */ if (intHandler == (FUNCPTR)&excCallTbl[srcInum * 5]) return (ERROR); /* set the info to the destination IRQ vector table entry */ intVecSet2 ((FUNCPTR *)INUM_TO_IVEC (dstInum), intHandler, idtType, selector); /* update the IRQ (parameter of EOI routine) in the intConnect code */ if (intEoiGet != NULL) { pCode = (INT8 *)intHandler; *(INT32 *)(pCode + ICC_EOI_PARAM) = dstIrq; } /* set the default interrupt handler to the source IRQ */ intVecSet2 ((FUNCPTR *)INUM_TO_IVEC (srcInum), (FUNCPTR)&excCallTbl[srcInum * 5], sysIntIdtType, sysCsInt); /* unlock interrupts */ intUnlock (oldLevel); /* UNLOCK INTERRUPTS */ ioApicIntEnable (dstIrq); return (OK); } /********************************************************************************* ioApicIrqSet - set the Local APIC ID of the specified IRQ** This routine sets the Local APIC ID of the specified IRQ in the IO APIC* Redirection Table.** RETURNS: OK, or ERROR if the IRQ is out of bound*/STATUS ioApicIrqSet ( INT32 irq, /* IRQ */ INT32 apicId /* Local APIC ID */ ) { INT32 upper32; INT32 oldLevel; INT32 offset = IOAPIC_REDTBL + (irq * 2); if (irq >= ioApicRedEntries) return (ERROR); /* lock interrupts */ oldLevel = intLock (); /* LOCK INTERRUPTS */ ioApicIntDisable (irq); /* set the loApicId */ upper32 = ioApicGet (ioApicBase, ioApicData, offset + 1); upper32 = (upper32 & ~IOAPIC_DESTINATION) | (apicId << 24); ioApicSet (ioApicBase, ioApicData, offset + 1, upper32); /* unlock interrupts */ intUnlock (oldLevel); /* UNLOCK INTERRUPTS */ ioApicIntEnable (irq); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -