📄 callout_interrupt_gt64260.s
字号:
# # 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"## Interrupts are always off in this code.## Note that interrupt_id_* and interrupt_eoi_* are not actually# called by the kernel. For performance reasons, they are instead# copied into place and intermixed with other kernel code. As such,# they don't follow normal calling conventions. They should just fall out # their bottoms when done rather than attempting to do a return # instruction. The 'id' routine should return the interrupt level in# the r14 register. The 'eoi' routine will find it still there. # By turning on various INTR_GENFLAG_* bits in the intrinfo_entry,# the following values can be loaded before entry to this code.# # cpu number => r15# syspage_ptr => r16# intrinfo_entry => r17# intr mask count => r18 (only available in EOI routine)## If the INTR_FLAG_CPU_FAULT bit is on, the eoi routine should set# the A0 register to the following value to indicate the exception# that has occurred:# R3 = (fault_number << 16) | (signal_code << 8) | (signal_number)# Set R3 to zero if no exception has occured. If the exception is memory# related, set R4 to referenced address that caused the exception, zero# if there is no address.# .extern gt64260_ipi_in # R3: syspage paddr# R4: syspage vaddr# R5: rtn dst offset# R6: r/w offset# R7: patch data# R8: rtn srcpatcher: stwu %r1,-32(%r1) mflr %r0 stw %r31,28(%r1) stw %r0,36(%r1) add %r31,%r3,%r5 mr %r4,%r7 loadi %r3,0x30000 bl callout_io_map_indirect lhz %r4,6(%r31) lhz %r5,2(%r31) slwi %r5,%r5,16 or %r4,%r4,%r5 add %r3,%r3,%r4 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.set GT64260_CPU_CAUSE, 0xc70.set GT64260_CPUMASK_LO, 0xc1c.set GT64260_CPUMASK_HI, 0xc6c.set GT64260_PCI0_CAUSE, 0xc74.set GT64260_PCI0MASK_LO, 0xc24.set GT64260_PCI0MASK_HI, 0xc64.set GT64260_GPP_CAUSE, 0xf108.set GT64260_GPP_MASK, 0xf10c## int interrupt_unmask(struct syspage_entry *sysp, int intr)## Unmask the passed hardware interrupt number.#CALLOUT_START interrupt_unmask_gt64260, 0, patcher DEVBASE %r10,0 # What logical unit does it go to? cmplwi %r4,64 bge 1f cmplwi %r4,32 bge 2f # CAUSE low loadi %r5, GT64260_CPUMASK_LO b 3f2: # CAUSE high subi %r4,%r4,32 loadi %r5, GT64260_CPUMASK_HI b 3f1: # GPP interrupt subi %r4,%r4,64 loadi %r5,GT64260_GPP_MASK3: li %r6,1 slw %r6,%r6,%r4 lwbrx %r3,%r10,%r5 or %r3,%r3,%r6 stwbrx %r3,%r10,%r5 li %r3,0 blrCALLOUT_END interrupt_unmask_gt64260 ## void interrupt_mask(struct syspage_entry *sysp, int intr)## Mask the passed hardware interrupt number.#CALLOUT_START interrupt_mask_gt64260, 0, patcher DEVBASE %r10,0 # What logical unit does it go to? cmplwi %r4,64 bge 1f cmplwi %r4,32 bge 2f # CAUSE low subi %r4,%r4,32 loadi %r5, GT64260_CPUMASK_LO b 3f2: # CAUSE high subi %r4,%r4,32 loadi %r5, GT64260_CPUMASK_HI b 3f1: # GPP interrupt subi %r4,%r4,64 loadi %r5,GT64260_GPP_MASK3: li %r6,1 slw %r6,%r6,%r4 lwbrx %r3,%r10,%r5 andc %r3,%r3,%r6 stwbrx %r3,%r10,%r5 li %r3,0 blrCALLOUT_END interrupt_mask_gt64260 # # int interrupt_id(void)## Returns: interrupt level, masks it off#CALLOUT_START interrupt_id_gt64260, 0, patcher DEVBASE %r10,0 # use r14 temporarily to hold the zero-relative values of IPIs; # bits 0 - 15 == CPU 0->1 IPI, bits 16 - 31 == CPU 1->0 IPI lis %r14,gt64260_ipi_in@ha lwz %r14,gt64260_ipi_in@l(%r14) cmpwi %r15,0 # are we CPU 0 or 1? bne 10f loadi %r5, GT64260_CPU_CAUSE lwbrx %r3,%r10,%r5 # read cause# andis. %r0,%r3,0x8000# beq- 3f andis. %r0,%r3,0x4000 bne 1f # Low cause is set loadi %r5, GT64260_CPUMASK_LO lwbrx %r4,%r10,%r5 # read mask and %r4,%r3,%r4 rlwinm %r3,%r4,0,2,31 cntlzw %r7,%r3 cmpwi %r7,32 beq- 3f subfic %r8,%r7,31 # Vector in %r8; now mask li %r6,1 slw %r6,%r6,%r8 lwbrx %r3,%r10,%r5 andc %r3,%r3,%r6 stwbrx %r3,%r10,%r5 mr %r14,%r8 b 4f1: # High cause is set loadi %r5, GT64260_CPUMASK_HI lwbrx %r4,%r10,%r5 # read mask and %r4,%r3,%r4 rlwinm %r3,%r4,0,2,31 cntlzw %r7,%r3 cmpwi %r7,32 beq- 3f subfic %r8,%r7,31 rlwinm %r3,%r8,0,0,29 # r8 & 0xfffffffc -> r3: if r8 is 24, 25, 26, or 27, then 24 -> r3 cmpwi %r3,24 # GPP interrupt, don't mask beq 2f # Vector in %r8; now mask li %r6,1 slw %r6,%r6,%r8 lwbrx %r3,%r10,%r5 andc %r3,%r3,%r6 stwbrx %r3,%r10,%r5 addi %r14,%r8,32 b 4f2: # GPP pin active loadi %r5, GT64260_GPP_CAUSE lwbrx %r3,%r10,%r5 loadi %r5, GT64260_GPP_MASK lwbrx %r4,%r10,%r5 and %r3,%r4,%r3 # we know CPU 0->1 IPI, so determine the GPP group that contains that vector rlwinm %r7,%r14,16,16,31 # get CPU 0->1 IPI into r7 cmplwi %r7,8 bge 1f rlwinm %r3,%r3,0,0,23 # GPP 0 - 7 are for CPU 1 b 2f1: cmplwi %r7,16 bge 1f rlwinm %r3,%r3,0,16,7 # GPP 8 - 15 are for CPU 1 b 2f1: cmplwi %r7,24 bge 1f rlwinm %r3,%r3,0,24,15 # GPP 16 - 23 are for CPU 1 b 2f1: cmplwi %r7,32 bge 2f # if it's greater than 31, this must be a uni-processor system rlwinm %r3,%r3,0,8,31 # GPP 24 - 31 are for CPU 12: cntlzw %r7,%r3 cmpwi %r7,32 beq- 3f subfic %r8,%r7,31 # %r8 has the vector -- now mask GPP level li %r6,1 loadi %r5, GT64260_GPP_MASK slw %r6,%r6,%r8 lwbrx %r3,%r10,%r5 andc %r3,%r3,%r6 rlwinm %r7,%r14,0,16,31 # extract CPU 1->0 IPI vector cmpw %r8,%r7 # don't mask the IPI vector beq 22f stwbrx %r3,%r10,%r522: # And clear the cause register bit we're interested in not %r6,%r6 loadi %r5, GT64260_GPP_CAUSE stwbrx %r6,%r10,%r5 addi %r14,%r8,64 b 4f3: # Spurious int li %r14,-14: b 20f10: # CPU 1 - we're assuming that the only GPP in this group that is # configured as an interrupt is CPU 0 to 1 IPI - otherwise, non-IPI # interrupts won't be serviced if a uni-processor procnto is used... loadi %r5, GT64260_GPP_CAUSE rlwinm %r14,%r14,16,16,31 # get CPU 0->1 IPI into r14 li %r6, 1 slw %r6, %r6, %r14 not %r6,%r6 stwbrx %r6,%r10,%r5 # clear interrupt addi %r14,%r14,6420:CALLOUT_END interrupt_id_gt64260 # # void interrupt_eoi(struct syspage_entry *sysp, int intr)## Unmask the level (interrupt_id masked it)#CALLOUT_START interrupt_eoi_gt64260, 0, patcher DEVBASE %r10,0 # Unmask the level -- r14 still has the level cmplwi %r18,1 bge 3f # What logical unit does it go to? cmplwi %r14,64 bge 1f cmplwi %r14,32 bge 2f # CAUSE low loadi %r5, GT64260_CPUMASK_LO li %r6,1 slw %r6,%r6,%r14 lwbrx %r3,%r10,%r5 or %r3,%r3,%r6 stwbrx %r3,%r10,%r5 b 3f2: # CAUSE high subi %r4,%r14,32 loadi %r5, GT64260_CPUMASK_HI li %r6,1 slw %r6,%r6,%r4 lwbrx %r3,%r10,%r5 or %r3,%r3,%r6 stwbrx %r3,%r10,%r5 b 3f1: # GPP interrupt lis %r5,gt64260_ipi_in@ha lwz %r5,gt64260_ipi_in@l(%r5) # don't unmask IPIs - they should already be unmasked rlwinm %r6,%r5,16,16,31 # get CPU 0->1 IPI into r6 cmplw %r14,%r6 beq 3f rlwinm %r6,%r5,0,16,31 # get CPU 1->0 IPI into r6 cmplw %r14,%r6 beq 3f loadi %r5,GT64260_GPP_MASK subi %r4,%r14,64 li %r6,1 slw %r6,%r6,%r4 lwbrx %r0,%r10,%r5 or %r0,%r0,%r6 stwbrx %r0,%r10,%r53:CALLOUT_END interrupt_eoi_gt64260## Return special config for the passed hardware interrupt number.#CALLOUT_START interrupt_config_gt64260, 0, 0 lis %r14,gt64260_ipi_in@ha lwz %r14,gt64260_ipi_in@l(%r14) rlwinm %r6,%r14,16,16,31 # get CPU 0->1 IPI into r6 addi %r6,%r6,64 cmpw %r5,%r6 beq 1f rlwinm %r6,%r14,0,16,31 # get CPU 1->0 IPI into r6 addi %r6, %r6, 64 cmpw %r5,%r6 beq 1f li %r3,0 blr1: li %r3,INTR_CONFIG_FLAG_IPI|INTR_CONFIG_FLAG_DISALLOWED blrCALLOUT_END interrupt_config_gt64260
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -