📄 loapicintr.c
字号:
#endif /* defined (SYMMETRIC_IO_MODE) */ /* if the original mode is PIC mode, disable the Local APIC */ if ((loApicOldSvr & LOAPIC_ENABLE) == 0) { *(int *)(loApicBase + LOAPIC_SVR) &= ~LOAPIC_ENABLE; } else { /* restore the original value */ *(int *)(loApicBase + LOAPIC_SVR) = loApicOldSvr; *(int *)(loApicBase + LOAPIC_LINT0) = loApicOldLint0; *(int *)(loApicBase + LOAPIC_LINT1) = loApicOldLint1; } } intUnlock (oldLevel); /* UNLOCK INTERRUPTS */ }/********************************************************************************* loApicIntLock - lock out all Local APIC interrupts** This routine locks out all Local APIC interrupts* It should be called in the interrupt disable state(IF bit is 0).** RETURNS: N/A** SEE ALSO: loApicIntUnlock()** ARGSUSED0*/LOCAL void loApicIntLock (void) { if (!(*(int *)(loApicBase + LOAPIC_TIMER) & LOAPIC_MASK)) { sysIntMaskLocalApic |= LOCKED_TIMER; *(int *)(loApicBase + LOAPIC_TIMER) |= LOAPIC_MASK; } if (!(*(int *)(loApicBase + LOAPIC_LINT0) & LOAPIC_MASK)) { sysIntMaskLocalApic |= LOCKED_LINT0; *(int *)(loApicBase + LOAPIC_LINT0) |= LOAPIC_MASK; } if (!(*(int *)(loApicBase + LOAPIC_LINT1) & LOAPIC_MASK)) { sysIntMaskLocalApic |= LOCKED_LINT1; *(int *)(loApicBase + LOAPIC_LINT1) |= LOAPIC_MASK; } if (!(*(int *)(loApicBase + LOAPIC_ERROR) & LOAPIC_MASK)) { sysIntMaskLocalApic |= LOCKED_ERROR; *(int *)(loApicBase + LOAPIC_ERROR) |= LOAPIC_MASK; } if ((loApicMaxLvt >= LOAPIC_LVT_P6) && (!(*(int *)(loApicBase + LOAPIC_PMC) & LOAPIC_MASK))) { sysIntMaskLocalApic |= LOCKED_PMC; *(int *)(loApicBase + LOAPIC_PMC) |= LOAPIC_MASK; } if ((loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) && (!(*(int *)(loApicBase + LOAPIC_THERMAL) & LOAPIC_MASK))) { sysIntMaskLocalApic |= LOCKED_THERMAL; *(int *)(loApicBase + LOAPIC_THERMAL) |= LOAPIC_MASK; } }/********************************************************************************* loApicIntUnlock - unlock the Local APIC interrupts** This routine unlocks the Local APIC interrupts* It should be called in the interrupt disable state(IF bit is 0).** RETURNS: N/A** SEE ALSO: loApicIntLock()** ARGSUSED0*/LOCAL void loApicIntUnlock (void) { if (sysIntMaskLocalApic & LOCKED_TIMER) *(int *)(loApicBase + LOAPIC_TIMER) &= ~LOAPIC_MASK; if (sysIntMaskLocalApic & LOCKED_LINT0) *(int *)(loApicBase + LOAPIC_LINT0) &= ~LOAPIC_MASK; if (sysIntMaskLocalApic & LOCKED_LINT1) *(int *)(loApicBase + LOAPIC_LINT1) &= ~LOAPIC_MASK; if (sysIntMaskLocalApic & LOCKED_ERROR) *(int *)(loApicBase + LOAPIC_ERROR) &= ~LOAPIC_MASK; if ((loApicMaxLvt >= LOAPIC_LVT_P6) && (sysIntMaskLocalApic & LOCKED_PMC)) *(int *)(loApicBase + LOAPIC_PMC) &= ~LOAPIC_MASK; if ((loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) && (sysIntMaskLocalApic & LOCKED_THERMAL)) *(int *)(loApicBase + LOAPIC_THERMAL) &= ~LOAPIC_MASK; sysIntMaskLocalApic = 0; /* reset the flags */ }/********************************************************************************* loApicIntEoi - send EOI (End Of Interrupt) signal to Local APIC** This routine sends an EOI signal to the Local APIC's interrupting source.** RETURNS: N/A*/LOCAL void loApicIntEoi ( INT32 irqNo /* INIIN number to send EOI */ ) {#ifdef SYS_INT_DEBUG extern UINT32 sysIntCount []; sysIntCount [irqNo]++;#endif /* SYS_INT_DEBUG */ *(int *)(loApicBase + LOAPIC_EOI) = 0; }/********************************************************************************* loApicMpConfigTableInit - initialize pointers to MP configuration table** This routine scans the memory areas specified in MP ver1.4, to find the* MP signature and initializes pointers to MP configuration tables. This* is not comprehensive and the only data used by VxWorks is the * APIC IDs and APIC base addresses.** RETURNS: OK, or ERROR if not MP compliant**/LOCAL STATUS loApicMpConfigTableInit (void) { MP_FPS * pFps = NULL; MP_HEADER * mpHdr; MP_CPU * mpCpu; MP_IOAPIC * mpIOApic; INT8 * p; INT32 ix; /* scan for the MP Floating Point Structure */ pFps = (MP_FPS *)loApicMpScan ((char *)EBDA_START, (char *)EBDA_END); if (pFps == NULL) pFps = (MP_FPS *)loApicMpScan ((char *)BIOS_ROM_START, (char *)BIOS_ROM_END); if (pFps == NULL) return (ERROR); /* * If featurebyte1 (array element 0) is non-zero, then we use * standard configuration return ERROR and let the error handle use * standard addresses and Local and IO APIC ID's. */ if ((pFps->featureByte[0] != 0) || (pFps->configTableAddr == 0)) return (ERROR); /* check if the IMCR exists or not */ loApicImcr = (pFps->featureByte[1] & 0x80) ? TRUE : FALSE; /* get MP header pointer */ mpHdr = (MP_HEADER *) pFps->configTableAddr; /* get Local APIC Base Address */ loApicBase = (UINT32)(mpHdr->localApicBaseAddr); /* We only need CPU and IO APIC entries, ignore the rest */ p = (char *)mpHdr + sizeof(MP_HEADER); for(ix = 0; ix < mpHdr->entryCount; ix++) { switch(*p) { case MP_ENTRY_CPU: /* Processor Configuration Entry */ mpCpu = (MP_CPU *)p; loApicNcpu++; /* increment the CPU counter */ p += sizeof (MP_CPU); break; case MP_ENTRY_IOAPIC: /* IO Apic Configuration Entry */ mpIOApic = (MP_IOAPIC *)p; loApicNioApic++; /* increment the IO APIC counter */ p += sizeof (MP_IOAPIC); break; default: /* Others..ignore, for now */ p += 8; /* wild guess */ } } return(OK); }/********************************************************************************* loApicMpScan - scans given memory range for the string "_MP_"** This routine scans the memory areas specified in its argument for the* Intel MP signature string "_MP_". ** RETURNS: pointer to "_MP_" in the range , or NULL**/LOCAL INT8 * loApicMpScan ( INT8 * start, /* start address to scan */ INT8 * end /* end address to scan */ ) { INT8 * p; for (p = start; (p+3) < end; p++) { if (strncmp (p, "_MP_", 4) == 0) return (p); } return (NULL); }/******************************************************************************** loApicIpi - generate a Inter Processor Interrupt** This routine delivers an Inter-Processor interrupt to the specified CPU* in the specified mode, with the specified vectorNo. Level should always* be 1 except INIT De-assert mode.** RETURNS: OK, or ERROR if the delivery status is not idle*/STATUS loApicIpi ( INT32 apicId, /* APIC ID number to send the interrupt */ INT32 shortHand, /* destination short hand */ INT32 trigger, /* trigger mode. 0: edge or 1: level */ INT32 level, /* level. 0: de-assert or 1: assert */ INT32 destMode, /* destination mode. 0: physical or 1: logical */ INT32 deliMode, /* delivery mode. 000: fixed ... 110: startup */ INT32 vectorNo /* vector number */ ) { UINT32 icrHi = (*(int *)(loApicBase + LOAPIC_ICRHI)) & 0xf0ffffff; UINT32 icrLo = (*(int *)(loApicBase + LOAPIC_ICRLO)) & 0xfff33000; /* ShortHand, Trigger, Level, DeliveryMode and Vector */ icrLo |= ((shortHand << 18) & 0xc0000) | ((trigger << 15) & 0x8000) | ((level << 14) & 0x4000) | ((destMode << 11) & 0x800) | ((deliMode << 8) & 0x700) | (vectorNo & 0xff); /* Destination Apic Id */ icrHi |= (apicId << 24) & 0xff000000; /* is the interrupt idle? */ if (*(int *)(loApicBase + LOAPIC_ICRLO) & STATUS_PEND) { loApicBusy++; LOAPIC_DBG_MSG ("ipi: LOAPIC busy 0x%x\n", *(int *)(loApicBase + LOAPIC_ESR)) return (ERROR); } /* reset the error status register */ *(int *)(loApicBase + LOAPIC_ESR) = 0; *(int *)(loApicBase + LOAPIC_ESR) = 0; if (*(int *)(loApicBase + LOAPIC_ESR) != 0) { LOAPIC_DBG_MSG ("ipi: 0. ESR=0x%x\n", *(int *)(loApicBase + LOAPIC_ESR)) return (ERROR); } /* Send it! */ *(int *)(loApicBase + LOAPIC_ICRHI) = icrHi; *(int *)(loApicBase + LOAPIC_ICRLO) = icrLo; /* Wait till interrupt is sent */ while (*(int *)(loApicBase + LOAPIC_ICRLO) & STATUS_PEND) if (*(int *)(loApicBase + LOAPIC_ESR) != 0) { LOAPIC_DBG_MSG ("ipi: 1. ESR=0x%x\n", *(int *)(loApicBase + LOAPIC_ESR)) return (ERROR); } return(OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -