📄 callout_interrupt_mgt5200.s
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ *//* * An entry point for a hardware kernel callout. * It may be called by an interrupt handler. * This code MUST be position independant. */.include "callout.ah"/* * int interrupt_unmask(struct syspage_entry *sysp, int intr) * * Unmask the passed hardware interrupt number. */.set MGT5200_PIMR, 0x0500.set MGT5200_PP_HLSR_1, 0x0504.set MGT5200_PP_HLSR_2, 0x0508.set MGT5200_PP_HLSR_3, 0x050C.set MGT5200_EE_ETR, 0x0510.set MGT5200_CP_MIMR, 0x0514.set MGT5200_MIP_SMI_1, 0x0518.set MGT5200_MIP_SMI_2, 0x051C.set MGT5200_ALL_STAT_ENC, 0x0524.set MGT5200_CISR, 0x0528.set MGT5200_MISR, 0x052C.set MGT5200_PISR, 0x0530.set MGT5200_GPIOSIE, 0x0B20.set MGT5200_GPIOSIIE, 0x0B30.set MGT5200_GPIOSSR, 0x0B3C.set MGT5200_GPIOWIE, 0x0C14.set MGT5200_GPIOWSR, 0x0C24.set MGT5200_SCIMR, 0x1218.set MGT5200_SCIPR, 0x1214.set MGT5200_SLC_0_TERM, 0x0700.set MGT5200_SLC_0_CTRL, 0x0704.set MGT5200_SLC_0_STAT, 0x070c.set MGT5200_SCTMR, 0x0400.set MGT5200_SCTSR, 0x0400patcher: # R3: syspage paddr # R4: syspage vaddr # R5: rtn dst offset # R6: r/w offset # R7: patch data # R8: rtn src stwu %r1,-32(%r1) mflr %r0 stw %r31,28(%r1) stw %r0,36(%r1) add %r31,%r3,%r5 mr %r4,%r7 li %r3, 0x08 bl callout_io_map_indirect sth %r3,6(%r31) srwi %r3,%r3,16 sth %r3,2(%r31) lwz %r0,36(%r1) mtlr %r0 lwz %r31,28(%r1) addi %r1,%r1,32 blr.macro DEVBASE reg,dev_reg_off# the instruction immediate values are patched by the above routine lis ®,(&dev_reg_off) >> 16 ori ®,®,(&dev_reg_off) & 0xffff.endm/*************************************************************************** * Callout : interrupt_id_mgt5200 * * Description: Determine critical or main interrupt level and mask it off * (if appropriate) * * On Entry: Nothing * * On Exit: r14 = interrupt level * * Notes: * * Test for core critical interrupts first: * If the interrupt is 0, (UART1_4), mask it by clearing bit 20 of EE_ETR. * If the interrupt is 1 (slice timer 0), then we mask it by clearing the * interrupt enable bit of Slice Timer 0 Control Register. If it's 2, it's * a cascade from some peripheral that's programmed to generate a HI int, * and we can't mask it directly, but it'll be taken care of by the * peripheral callouts. * **************************************************************************/CALLOUT_START interrupt_id_mgt5200, 0, patcher DEVBASE %r6, 0x12345678 li %r14,0 /* get all interrupt status, encoded */ lwz %r5,MGT5200_ALL_STAT_ENC(%r6) li %r0, 0x0400 /* Critical Status flag */ and %r0, %r0, %r5 /* clear all bits except status */ cmplwi %r0,0 beq 4f /* no critical interrupt, proceed to main interrupt id */ /* bits 22 and 23 represent the level. Load it into r14. */ srawi %r14, %r5, 8 andi. %r14, %r14, 3 cmplwi %r14,0 bgt 1f /* interrupt is 0, clear bit 20 of EE_ETR */ lwz %r5,MGT5200_EE_ETR(%r6) li %r4,0x800 /* bit 20 is IRQ 0 enable bit */ andc %r5,%r5,%r4 /* mask (clear) bit by ANDing with one's compliment of r4 */ stw %r5, MGT5200_EE_ETR(%r6) /* store new value */ b 6f /* done */1: cmplwi %r14,1 bgt 3f /* interrupt is 1, mask slice timer 0 interrupts */ lwz %r5,MGT5200_SLC_0_CTRL(%r6) lis %r0,0x0200 andc %r5, %r5, %r0 stw %r5,MGT5200_SLC_0_CTRL(%r6) lwz %r5,MGT5200_SLC_0_STAT(%r6) b 6f /* done */2: cmplwi %r14,2 bgt 3f /* For now, we'll pretend that this is a LO peripheral interrupt, since there seems to * be a problem cascading from the HI source. */ li %r14,4 /* LO int is main level 4 (QNX vector 8) */ b 5f 3: b 6f /* placeholder for CCS module wakeup from sleep. */4: /* main interrupt ID - r5 still contains Interrupt Status Register (encoded) */ /* bits 15 - 11 represent the level. Load it into r14. */ li %r14, -1 srawi %r8, %r5, 16 andi. %r8, %r8, 0x3f cmplwi %r8,0 beq 6f andi. %r14, %r8, 0x1f 5: /* * now, load the main interrupt mask register, and set the appropriate bit * to mask the interrupt * * Note: May want to prevent LO-int from being masked here and leave it to the peripheral * handler to mask only the peripheral causing the LO-int. */ lwz %r5,MGT5200_CP_MIMR(%r6) lis %r4, 1 /* puts 0x00010000 into r4 (bit 15) */ srw %r4, %r4, %r14 /* shift the bit to the proper position */ or %r5, %r5, %r4 stw %r5, MGT5200_CP_MIMR(%r6) /* write new mask value */ /* * Master interrupts start at offset 4 from the base of the critical interrupts, but * the value in r14 represents the relative master interrupt, so we need to compensate */ addi %r14, %r14, 4 /* done */6:CALLOUT_END interrupt_id_mgt5200/*************************************************************************** * Callout : interrupt_eoi_mgt5200 * * Description: Clear the interrupt, then unmask the level (it was masked in * interrupt_id) * * On Entry: r14 = interrupt level * * On Exit: Nothing * * Notes: * **************************************************************************/CALLOUT_START interrupt_eoi_mgt5200, 0, patcher/* * r14 = 0 - write a 1 to bit 20 of EE_ETR, to unmask * r14 = 1 - write a 1 to slice timer 0 status bit to clear, and enable timer interrupts * r14 = 2 or 3 - do nothing for now * r14 = 4 - 20 - unmask the appropriate main interrupt */ DEVBASE %r6, 0x12345678 cmplwi %r18,0 bgt 3f cmplwi %r14,0 bgt 1f /* UART 1_4 interrupt */ lwz %r5,MGT5200_EE_ETR(%r6) ori %r5, %r5, 0x800 /* unmask interrupt 0 (bit 20) */ stw %r5,MGT5200_EE_ETR(%r6) b 3f /* done */1: cmplwi %r14, 1 bgt 2f /* slice timer 0 interrupt */ lwz %r5,MGT5200_SLC_0_STAT(%r6)/* clear int */ lis %r0,0x0100 stw %r0,MGT5200_SLC_0_STAT(%r6)/* unmask the interrupt */ lis %r0,0x0700 stw %r0,MGT5200_SLC_0_CTRL(%r6) b 3f /* done */2: cmplwi %r14,3 ble 3f /* if it's 2 or 3, do nothing */ /* main interrupt */ cmplwi %r14, 20 bgt 3f lwz %r5,MGT5200_CP_MIMR(%r6) lis %r4, 0x10 /* int 4 == main interrupt 0, this is so srw by r14 puts bit in proper position */ srw %r4, %r4, %r14 /* r14 will be 4 or greater */ andc %r5, %r5, %r4 /* clear bit to unmask */ stw %r5, MGT5200_CP_MIMR(%r6)3:/* done */CALLOUT_END interrupt_eoi_mgt5200/*************************************************************************** * Callout : interrupt_mask_mgt5200 * * Description: Mask the given interrupt level * * On Entry: r4 = interrupt level * * On Exit: Nothing * * Notes: * **************************************************************************/CALLOUT_START interrupt_mask_mgt5200, 0, patcher/* * If the level passed here in r4 is 0, unmask external INT 0 by setting bit 20 * of the External Enable and External Types register. * If it's 1, enable slice timer 0 interrupts. * Otherwise, load the Critical Priority and Main Interrupt Mask register, * and clear the appropriate bit for the level to be unmasked. */ DEVBASE %r6, 0x12345678 cmplwi %r4, 0 bgt 1f lwz %r5, MGT5200_EE_ETR(%r6) /* load contents of EE_ETR into r5 */ li %r8,0x800 /* bit 20 is IRQ 0 enable bit */ andc %r5,%r5,%r8 /* mask (clear) bit by ANDing with one's compliment of r6 */ stw %r5, MGT5200_EE_ETR(%r6) /* store new value */ b 3f1: cmplwi %r4,1 bgt 2f /* interrupt is 1, mask slice timer 0 interrupts */ lwz %r5,MGT5200_SLC_0_CTRL(%r6) lis %r0,0x0200 andc %r5, %r5, %r0 stw %r5,MGT5200_SLC_0_CTRL(%r6) b 3f2: cmplwi %r4, 3 /* check for level 2 or 3 */ ble 3f /* can't mask */ /* set bit to mask in MIMR */ lwz %r5, MGT5200_CP_MIMR(%r6) /* load contents of CP_MIMR into r5 */ /* bits 15 - 31 represent interrupt levels 4 - 20, respectively */ lis %r8, 0x10 /* bit 11 */ srw %r8,%r8,%r4 /* shift mask bit to proper position in r6 */ or %r5,%r5,%r8 eieio stw %r5, MGT5200_CP_MIMR(%r6) /* load new interrupt mask */3: sync blrCALLOUT_END interrupt_mask_mgt5200 /*************************************************************************** * Callout : interrupt_unmask_mgt5200 * * Description: Unmask the given interrupt level * * On Entry: r4 = interrupt level * * On Exit: Nothing * * Notes: * **************************************************************************/CALLOUT_START interrupt_unmask_mgt5200, 0, patcher/* * If the level passed here is 0, unmask external INT 0 by setting bit 20 * of the External Enable and External Types register. * If it's 1, enable slice timer 0 interrupts. * Otherwise, load the Critical Priority and Main Interrupt Mask register, * and clear the appropriate bit for the level to be unmasked. */ DEVBASE %r6, 0x12345678 cmplwi %r4, 0 bgt 1f lwz %r5, MGT5200_EE_ETR(%r6) /* load contents of EE_ETR into r5 */ li %r8,0x800 /* bit 20 is IRQ 0 enable bit */ or %r5,%r5,%r8 /* unmask bit */ stw %r5, MGT5200_EE_ETR(%r6) /* store new value */ b 3f1: cmplwi %r4, 1 bgt 2f/* unmask slice timer 0 interrupt */ lis %r0,0x0700 stw %r0,MGT5200_SLC_0_CTRL(%r6) b 3f2: cmplwi %r4, 3 /* check for level 2 or 3 */ ble 3f /* can't unmask */ /* unmask a main interrupt - clear bit to unmask in MIMR */ lwz %r5, MGT5200_CP_MIMR(%r6) /* load contents of CP_MIMR into r5 */ /* bits 15 - 31 represent interrupt levels 4 - 20, respectively */ lis %r8, 0x10 /* bit 11 */ srw %r8,%r8,%r4 /* shift mask bit to proper position in r6 */ andc %r5,%r5,%r8 /* and r5 with one's compliment of r6 to unmask interrupt */ eieio stw %r5, MGT5200_CP_MIMR(%r6) /* load new interrupt mask */3: sync blrCALLOUT_END interrupt_unmask_mgt5200/*************************************************************************** * * Peripheral Interrupt Callouts * ***************************************************************************//*************************************************************************** * Callout : interrupt_unmask_mgt5200_per_hi * * Description: Unmask the given peripheral interrupt level for interrupts * configured as HI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -