📄 cpu.c
字号:
* * _CPU_ISR_install_raw_handler * * This routine installs the specified handler as a "raw" non-executive * supported trap handler (a.k.a. interrupt service routine). * * Input Parameters: * vector - trap table entry number plus synchronous * vs. asynchronous information * new_handler - address of the handler to be installed * old_handler - pointer to an address of the handler previously installed * * Output Parameters: NONE * *new_handler - address of the handler previously installed * * NOTE: * * This routine is based on the SPARC routine _CPU_ISR_install_raw_handler. * Install a software trap handler as an executive interrupt handler * (which is desirable since RTEMS takes care of window and register issues), * then the executive needs to know that the return address is to the trap * rather than the instruction following the trap. * */ void _CPU_ISR_install_raw_handler( unsigned32 vector, proc_ptr new_handler, proc_ptr *old_handler){ unsigned32 real_vector; CPU_Trap_table_entry *slot; unsigned32 u32_handler=0; /* * Get the "real" trap number for this vector ignoring the synchronous * versus asynchronous indicator included with our vector numbers. */ real_vector = vector; /* * Get the current base address of the trap table and calculate a pointer * to the slot we are interested in. */ slot = (CPU_Trap_table_entry *)ppc_exception_vector_addr( real_vector ); /* * Get the address of the old_handler from the trap table. * * NOTE: The old_handler returned will be bogus if it does not follow * the RTEMS model. */#define HIGH_BITS_MASK 0xFFFFFC00#define HIGH_BITS_SHIFT 10#define LOW_BITS_MASK 0x000003FF if (slot->stwu_r1 == _CPU_Trap_slot_template.stwu_r1) { /* * Set u32_handler = to target address */ u32_handler = slot->b_Handler & 0x03fffffc; /* IMD FIX: sign extend address fragment... */ if (u32_handler & 0x02000000) { u32_handler |= 0xfc000000; } *old_handler = (proc_ptr) u32_handler; } else/* There are two kinds of handlers for the MPC860. One is the 'standard' * one like above. The other is for the cascaded interrupts from the SIU * and CPM. Therefore we must check for the alternate one if the standard * one is not present */#if defined(mpc860) || defined(mpc821) if (slot->stwu_r1 == _CPU_Trap_slot_template_m860.stwu_r1) { /* * Set u32_handler = to target address */ u32_handler = slot->b_Handler & 0x03fffffc; *old_handler = (proc_ptr) u32_handler; } else#endif /* mpc860 */ *old_handler = 0; /* * Copy the template to the slot and then fix it. */#if defined(mpc860) || defined(mpc821) if (vector >= PPC_IRQ_IRQ0) *slot = _CPU_Trap_slot_template_m860; else#endif /* mpc860 */ *slot = _CPU_Trap_slot_template; u32_handler = (unsigned32) new_handler; /* * IMD FIX: insert address fragment only (bits 6..29) * therefore check for proper address range * and remove unwanted bits */ if ((u32_handler & 0xfc000000) == 0xfc000000) { u32_handler &= ~0xfc000000; } else if ((u32_handler & 0xfc000000) != 0x00000000) { _Internal_error_Occurred(INTERNAL_ERROR_CORE, TRUE, u32_handler); } slot->b_Handler |= u32_handler; slot->li_r0_IRQ |= vector; _CPU_Data_Cache_Block_Flush( slot );}unsigned32 ppc_exception_vector_addr( unsigned32 vector){#if (!PPC_HAS_EVPR) unsigned32 Msr;#endif unsigned32 Top = 0; unsigned32 Offset = 0x000;#if (PPC_HAS_EXCEPTION_PREFIX) _CPU_MSR_Value ( Msr ); if ( ( Msr & PPC_MSR_EP) != 0 ) /* Vectors at FFFx_xxxx */ Top = 0xfff00000;#elif (PPC_HAS_EVPR) asm volatile( "mfspr %0,0x3d6" : "=r" (Top)); /* EVPR */ Top = Top & 0xffff0000;#endif switch ( vector ) { case PPC_IRQ_SYSTEM_RESET: /* on 40x aka PPC_IRQ_CRIT */ Offset = 0x00100; break; case PPC_IRQ_MCHECK: Offset = 0x00200; break; case PPC_IRQ_PROTECT: Offset = 0x00300; break; case PPC_IRQ_ISI: Offset = 0x00400; break; case PPC_IRQ_EXTERNAL: Offset = 0x00500; break; case PPC_IRQ_ALIGNMENT: Offset = 0x00600; break; case PPC_IRQ_PROGRAM: Offset = 0x00700; break; case PPC_IRQ_NOFP: Offset = 0x00800; break; case PPC_IRQ_DECREMENTER: Offset = 0x00900; break; case PPC_IRQ_RESERVED_A: Offset = 0x00a00; break; case PPC_IRQ_RESERVED_B: Offset = 0x00b00; break; case PPC_IRQ_SCALL: Offset = 0x00c00; break; case PPC_IRQ_TRACE: Offset = 0x00d00; break; case PPC_IRQ_FP_ASST: Offset = 0x00e00; break;#if defined(ppc403) || defined(ppc405) /* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET case PPC_IRQ_CRIT: Offset = 0x00100; break;*/ case PPC_IRQ_PIT: Offset = 0x01000; break; case PPC_IRQ_FIT: Offset = 0x01010; break; case PPC_IRQ_WATCHDOG: Offset = 0x01020; break; case PPC_IRQ_DEBUG: Offset = 0x02000; break;#elif defined(ppc601) case PPC_IRQ_TRACE: Offset = 0x02000; break;#elif defined(ppc603) case PPC_IRQ_TRANS_MISS: Offset = 0x1000; break; case PPC_IRQ_DATA_LOAD: Offset = 0x1100; break; case PPC_IRQ_DATA_STORE: Offset = 0x1200; break; case PPC_IRQ_ADDR_BRK: Offset = 0x1300; break; case PPC_IRQ_SYS_MGT: Offset = 0x1400; break;#elif defined(ppc603e) case PPC_TLB_INST_MISS: Offset = 0x1000; break; case PPC_TLB_LOAD_MISS: Offset = 0x1100; break; case PPC_TLB_STORE_MISS: Offset = 0x1200; break; case PPC_IRQ_ADDRBRK: Offset = 0x1300; break; case PPC_IRQ_SYS_MGT: Offset = 0x1400; break;#elif defined(mpc604) case PPC_IRQ_ADDR_BRK: Offset = 0x1300; break; case PPC_IRQ_SYS_MGT: Offset = 0x1400; break;#elif defined(mpc860) || defined(mpc821) case PPC_IRQ_EMULATE: Offset = 0x1000; break; case PPC_IRQ_INST_MISS: Offset = 0x1100; break; case PPC_IRQ_DATA_MISS: Offset = 0x1200; break; case PPC_IRQ_INST_ERR: Offset = 0x1300; break; case PPC_IRQ_DATA_ERR: Offset = 0x1400; break; case PPC_IRQ_DATA_BPNT: Offset = 0x1c00; break; case PPC_IRQ_INST_BPNT: Offset = 0x1d00; break; case PPC_IRQ_IO_BPNT: Offset = 0x1e00; break; case PPC_IRQ_DEV_PORT: Offset = 0x1f00; break; case PPC_IRQ_IRQ0: Offset = 0x2000; break; case PPC_IRQ_LVL0: Offset = 0x2040; break; case PPC_IRQ_IRQ1: Offset = 0x2080; break; case PPC_IRQ_LVL1: Offset = 0x20c0; break; case PPC_IRQ_IRQ2: Offset = 0x2100; break; case PPC_IRQ_LVL2: Offset = 0x2140; break; case PPC_IRQ_IRQ3: Offset = 0x2180; break; case PPC_IRQ_LVL3: Offset = 0x21c0; break; case PPC_IRQ_IRQ4: Offset = 0x2200; break; case PPC_IRQ_LVL4: Offset = 0x2240; break; case PPC_IRQ_IRQ5: Offset = 0x2280; break; case PPC_IRQ_LVL5: Offset = 0x22c0; break; case PPC_IRQ_IRQ6: Offset = 0x2300; break; case PPC_IRQ_LVL6: Offset = 0x2340; break; case PPC_IRQ_IRQ7: Offset = 0x2380; break; case PPC_IRQ_LVL7: Offset = 0x23c0; break; case PPC_IRQ_CPM_ERROR: Offset = 0x2400; break; case PPC_IRQ_CPM_PC4: Offset = 0x2410; break; case PPC_IRQ_CPM_PC5: Offset = 0x2420; break; case PPC_IRQ_CPM_SMC2: Offset = 0x2430; break; case PPC_IRQ_CPM_SMC1: Offset = 0x2440; break; case PPC_IRQ_CPM_SPI: Offset = 0x2450; break; case PPC_IRQ_CPM_PC6: Offset = 0x2460; break; case PPC_IRQ_CPM_TIMER4: Offset = 0x2470; break; case PPC_IRQ_CPM_RESERVED_8: Offset = 0x2480; break; case PPC_IRQ_CPM_PC7: Offset = 0x2490; break; case PPC_IRQ_CPM_PC8: Offset = 0x24a0; break; case PPC_IRQ_CPM_PC9: Offset = 0x24b0; break; case PPC_IRQ_CPM_TIMER3: Offset = 0x24c0; break; case PPC_IRQ_CPM_RESERVED_D: Offset = 0x24d0; break; case PPC_IRQ_CPM_PC10: Offset = 0x24e0; break; case PPC_IRQ_CPM_PC11: Offset = 0x24f0; break; case PPC_IRQ_CPM_I2C: Offset = 0x2500; break; case PPC_IRQ_CPM_RISC_TIMER: Offset = 0x2510; break; case PPC_IRQ_CPM_TIMER2: Offset = 0x2520; break; case PPC_IRQ_CPM_RESERVED_13: Offset = 0x2530; break; case PPC_IRQ_CPM_IDMA2: Offset = 0x2540; break; case PPC_IRQ_CPM_IDMA1: Offset = 0x2550; break; case PPC_IRQ_CPM_SDMA_ERROR: Offset = 0x2560; break; case PPC_IRQ_CPM_PC12: Offset = 0x2570; break; case PPC_IRQ_CPM_PC13: Offset = 0x2580; break; case PPC_IRQ_CPM_TIMER1: Offset = 0x2590; break; case PPC_IRQ_CPM_PC14: Offset = 0x25a0; break; case PPC_IRQ_CPM_SCC4: Offset = 0x25b0; break; case PPC_IRQ_CPM_SCC3: Offset = 0x25c0; break; case PPC_IRQ_CPM_SCC2: Offset = 0x25d0; break; case PPC_IRQ_CPM_SCC1: Offset = 0x25e0; break; case PPC_IRQ_CPM_PC15: Offset = 0x25f0; break;#endif } Top += Offset; return Top;}/*PAGE * * This is the PowerPC specific implementation of the routine which * returns TRUE if an interrupt is in progress. * * NOTE: This is the same as the generic version. But since the * PowerPC is still supporting old and new exception processing * models and the new exception processing model has a hardware * way of doing this, we have to provide this capability here * for symmetry. */boolean _ISR_Is_in_progress( void ){ return (_ISR_Nest_level != 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -