📄 callout_interrupt_cpc700.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.# # 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 R3 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.#.set CPC700_UIC_SR, 0x00.set CPC700_UIC_SRS,0x04.set CPC700_UIC_ER, 0x08.set CPC700_UIC_CR, 0x0c.set CPC700_UIC_PR, 0x10.set CPC700_UIC_TR, 0x14.set CPC700_UIC_MSR,0x18.set CPC700_UIC_VR, 0x1c.set CPC700_UIC_VRC,0x20patcher: # 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 loadi %r3,0x24 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# # int interrupt_id(void)## Returns: interrupt level in r14, masks it off.#CALLOUT_START interrupt_id_cpc700, 0, patcher DEVBASE %r6, 0 li %r14,-1 # put 0x7fffffff into r14 lwz %r5,CPC700_UIC_MSR(%r6) # get masked status reg value cmplwi %r5,0 # if no interrupts, we're done beq- 1f lwz %r4,CPC700_UIC_ER(%r6) # get enable reg value cntlzw %r14,%r5 # count leading zeros in r5, place resulting interrupt value in r14 lis %r5,0x8000 srw %r5,%r5,%r14 # shift mask bit right to position of interrupt we wish to mask andc %r4,%r4,%r5 # and r4 with one's compliment of mask bit, clearing relevant bit eieio stw %r4,CPC700_UIC_ER(%r6) # set new enable reg value sync1:CALLOUT_END interrupt_id_cpc700# # void interrupt_eoi(struct syspage_entry *sysp, int intr)## Send an end-of-interrupt, then unmask the level (interrupt_id masked it).# For the UIC, eoi is indicated by clearing the appropriate bit in the# UIC status register, which is accomplished by writing a 1 to it. Unmasking# is done to the UIC enable register. r14 contains the interrupt value.#CALLOUT_START interrupt_eoi_cpc700, 0, patcher DEVBASE %r6, 0 lis %r5,0x8000 srw %r5,%r5,%r14 # shift unmask (enable) bit to proper position eieio stw %r5,CPC700_UIC_SR(%r6) # write 1 to appropriate bit in status reg to clear interrupt sync cmplwi %r18,0 # if intr mask count > 0, don't unmask int bgt 1f lwz %r7,CPC700_UIC_ER(%r6) # load value of enable register into r6 or %r7,%r5,%r7 # set enable bit eieio stw %r7,CPC700_UIC_ER(%r6) # store new value of enable register sync1:CALLOUT_END interrupt_eoi_cpc700## int interrupt_unmask(struct syspage_entry *sysp, int intr)## Unmask the passed hardware interrupt number. The interrupt gets# passed in r4. Unmask is performed by setting (enabling) the bit# in the UICER which corresponds to the value in r4.#CALLOUT_START interrupt_unmask_cpc700, 0, patcher DEVBASE %r7, 0 lwz %r5,CPC700_UIC_ER(%r7) # load contents of UICER into r5 lis %r6,0x8000 srw %r6,%r6,%r4 # shift enable bit to proper position or %r5,%r5,%r6 # unmask bit eieio stw %r5,CPC700_UIC_ER(%r7) # store new contents of UICER sync li %r3,0 blrCALLOUT_END interrupt_unmask_cpc700 ## void interrupt_mask(struct syspage_entry *sysp, int intr)## Mask the passed hardware interrupt number. Masking is performed by clearing# (disabling) the bit in the UICER which corresponds to the value passed in r4.#CALLOUT_START interrupt_mask_cpc700, 0, patcher DEVBASE %r7, 0 lwz %r5,CPC700_UIC_ER(%r7) # load contents of UICER into r5 lis %r6,0x8000 srw %r6,%r6,%r4 # shift mask bit to proper position in r6 andc %r5,%r5,%r6 # and r5 with one's compliment of r6 to mask interrupt eieio stw %r5,CPC700_UIC_ER(%r7) # store new contents of UICER sync li %r3,0 blrCALLOUT_END interrupt_mask_cpc700
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -