mirror of https://github.com/dzavalishin/oskit/
305 lines
9.0 KiB
ArmAsm
Executable File
305 lines
9.0 KiB
ArmAsm
Executable File
/*
|
|
* Copyright (c) 1999, 2000 University of Utah and the Flux Group.
|
|
* All rights reserved.
|
|
*
|
|
* This file is part of the Flux OSKit. The OSKit is free software, also known
|
|
* as "open source;" you can redistribute it and/or modify it under the terms
|
|
* of the GNU General Public License (GPL), version 2, as published by the Free
|
|
* Software Foundation (FSF). To explore alternate licensing terms, contact
|
|
* the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
|
|
*
|
|
* The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
|
|
* received a copy of the GPL along with the OSKit; see the file COPYING. If
|
|
* not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/*
|
|
* Copyright 1997
|
|
* Digital Equipment Corporation. All rights reserved.
|
|
*
|
|
* This software is furnished under license and may be used and
|
|
* copied only in accordance with the following terms and conditions.
|
|
* Subject to these conditions, you may download, copy, install,
|
|
* use, modify and distribute this software in source and/or binary
|
|
* form. No title or ownership is transferred hereby.
|
|
*
|
|
* 1) Any source code used, modified or distributed must reproduce
|
|
* and retain this copyright notice and list of conditions as
|
|
* they appear in the source file.
|
|
*
|
|
* 2) No right is granted to use any trade name, trademark, or logo of
|
|
* Digital Equipment Corporation. Neither the "Digital Equipment
|
|
* Corporation" name nor any trademark or logo of Digital Equipment
|
|
* Corporation may be used to endorse or promote products derived
|
|
* from this software without the prior written permission of
|
|
* Digital Equipment Corporation.
|
|
*
|
|
* 3) This software is provided "AS-IS" and any express or implied
|
|
* warranties, including but not limited to, any implied warranties
|
|
* of merchantability, fitness for a particular purpose, or
|
|
* non-infringement are disclaimed. In no event shall DIGITAL be
|
|
* liable for any damages whatsoever, and in particular, DIGITAL
|
|
* shall not be liable for special, indirect, consequential, or
|
|
* incidental damages or damages for lost profits, loss of
|
|
* revenue or loss of use, whether such damages arise in contract,
|
|
* negligence, tort, under statute, in equity, at law or otherwise,
|
|
* even if advised of the possibility of such damage.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1994-1998 Mark Brinicombe.
|
|
* Copyright (c) 1994 Brini.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software written for Brini by Mark Brinicombe
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Mark Brinicombe
|
|
* for the NetBSD Project.
|
|
* 4. The name of the company nor the name of the author may be used to
|
|
* endorse or promote products derived from this software without specific
|
|
* prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* Interrupt handler. This operates by looping through the request register
|
|
* for each of the master and slaves (two loops). According to the NetBSD
|
|
* documentation, ISA bus access is terribly slow, and NetBSD goes to great
|
|
* pains to avoid it. I use a much simpler and slower approach, but this is
|
|
* intended to be a prototype ...
|
|
*/
|
|
|
|
#include <oskit/arm32/asm.h>
|
|
#include <oskit/arm32/base_trap.h>
|
|
|
|
#define IO_ICU1 0x20
|
|
#define IO_ICU2 0xa0
|
|
#define IO_ICU1_OCW 0x21
|
|
#define IO_ICU2_OCW 0xa1
|
|
#define ICU_EOI 0x20
|
|
#define SLAVE_ON_IR2 0x04
|
|
|
|
/*
|
|
* r4 - irq counter for master and slave loop
|
|
* r5 - slave imask
|
|
* r6 - master imask
|
|
* r7 - isa_iobus_address pointer
|
|
* r8 - master iir
|
|
* r9 - slave iir
|
|
* r10 - trap state pointer
|
|
*/
|
|
.text
|
|
|
|
ENTRY(base_irq_trap_handler)
|
|
stmfd sp!, {lr}
|
|
mov r10, r0
|
|
|
|
/*
|
|
* Adjust the PC in the trap frame for an IRQ.
|
|
*/
|
|
ldr r1, [r0, #(TRAP_STATE_PC)]
|
|
sub r1, r1, #0x00000004
|
|
str r1, [r0, #(TRAP_STATE_PC)]
|
|
|
|
/*
|
|
* Load the address of the ISA I/O bus, then indirect to read 8259
|
|
* interrupt request registers.
|
|
*/
|
|
ldr r7, Lisa_iobus_address
|
|
ldr r7, [r7]
|
|
ldrb r8, [r7, #IO_ICU1] /* ocw3 = irr */
|
|
ldrb r9, [r7, #IO_ICU2] /* ocw3 = irr */
|
|
bic r8, r8, #SLAVE_ON_IR2 /* always clear IRQ 2 (slave 8259) */
|
|
|
|
/*
|
|
* Increment the hardware interrupt nesting counter
|
|
*/
|
|
ldr r2, Lbase_irq_nest
|
|
ldr r3, [r2]
|
|
add r3, r3, #0x1
|
|
str r3, [r2]
|
|
|
|
cmp r8, #0
|
|
beq skipmpic
|
|
|
|
/* Save the current master PIC mask */
|
|
ldrb r6, [r7, #IO_ICU1_OCW]
|
|
|
|
/* Remove masked bits from the master iir. */
|
|
bic r8, r8, r6
|
|
cmp r8, #0
|
|
beq skipmpic
|
|
|
|
/* Mask out the interrupting IRQs on the master */
|
|
orr r3, r6, r8
|
|
strb r3, [r7, #IO_ICU1_OCW]
|
|
|
|
skipmpic:
|
|
cmp r9, #0
|
|
beq skipspic
|
|
|
|
/* Save the current slave PIC mask */
|
|
ldrb r5, [r7, #IO_ICU2_OCW]
|
|
|
|
/* Remove masked bits from the slave iir */
|
|
bic r9, r9, r5
|
|
cmp r9, #0
|
|
beq skipspic
|
|
|
|
/* Mask out the interrupting IRQs on the slave */
|
|
orr r3, r5, r9
|
|
strb r3, [r7, #IO_ICU2_OCW]
|
|
|
|
skipspic:
|
|
/*
|
|
* Now loop through and call the handler for each pending interrupt.
|
|
*/
|
|
cmp r8, #0
|
|
beq mskip
|
|
|
|
mov r4, #0
|
|
mloop:
|
|
mov r3, #1
|
|
mov r3, r3, lsl r4 /* Build the 1 bit mask */
|
|
tst r8, r3 /* Is a bit set? */
|
|
beq mnext /* No, then loop */
|
|
|
|
/*
|
|
* Call the interrupt handler. Be sure to stash the irq number
|
|
* in the trap frame, and pass the stack pointer as arg0.
|
|
*/
|
|
str r4, [r10, #(TRAP_STATE_INTNO)]
|
|
ldr r3, Lbase_irq_handlers
|
|
ldr r3, [r3, r4, asl #2] /* r3 = base_irq_handlers[irq] */
|
|
mov r0, r10
|
|
mov lr, pc
|
|
mov pc, r3
|
|
|
|
mnext:
|
|
add r4, r4, #1 /* move on to next bit */
|
|
cmp r4, #8 /* done the last bit ? */
|
|
bmi mloop /* no - loop back. */
|
|
|
|
/* Restore the interrupt mask */
|
|
strb r6, [r7, #IO_ICU1_OCW]
|
|
|
|
mskip:
|
|
/*
|
|
* Move to controller #2, and see what bits are set.
|
|
*/
|
|
cmp r9, #0
|
|
beq sskip
|
|
|
|
mov r4, #0
|
|
sloop:
|
|
mov r3, #1
|
|
mov r3, r3, lsl r4 /* Build the 1 bit mask */
|
|
tst r9, r3 /* Is a bit set? */
|
|
beq snext /* No, then loop */
|
|
|
|
/*
|
|
* Call the interrupt handler. Be sure to stash the irq number
|
|
* in the trap frame, and pass the frame pointer as arg0. Note
|
|
* that the irq numbering needs to be pushed up into 8-15.
|
|
*/
|
|
add r2, r4, #8
|
|
str r2, [r10, #(TRAP_STATE_INTNO)]
|
|
ldr r3, Lbase_irq_handlers
|
|
ldr r3, [r3, r2, asl #2] /* r3 = base_irq_handlers[irq] */
|
|
mov r0, r10
|
|
mov lr, pc
|
|
mov pc, r3
|
|
|
|
snext:
|
|
add r4, r4, #1 /* move on to next bit */
|
|
cmp r4, #8 /* done the last bit ? */
|
|
bmi sloop /* no - loop back. */
|
|
|
|
/* Restore the interrupt mask */
|
|
strb r5, [r7, #IO_ICU2_OCW]
|
|
|
|
sskip:
|
|
/*
|
|
* Decrement the hardware interrupt nesting counter
|
|
*/
|
|
ldr r2, Lbase_irq_nest
|
|
ldr r3, [r2]
|
|
subs r3, r3, #0x1
|
|
str r3, [r2]
|
|
|
|
/*
|
|
* Look for softints, base_irq_nest will be zero if one is pending.
|
|
*/
|
|
bne nosoft /* Result of sub above */
|
|
|
|
/*
|
|
* XXX There should be a test to see if BASE_IRQ_SKIP_SOFTINT is set,
|
|
* but since we run multiple handlers at once, kinda of a problem
|
|
* until I get more ambitious and fix up the code above.
|
|
*/
|
|
|
|
/*
|
|
* Clear the pending indicator, disable softints, reenable HW ints
|
|
* and call the softint handler.
|
|
*/
|
|
mov r3, #0xC0 /* SOFTINT_DISABLED|SOFTINT_CLEARED */
|
|
str r3, [r2]
|
|
mrs r3, cpsr_all
|
|
bic r3, r3, #0x80
|
|
msr cpsr_all, r3
|
|
mov r0, r10
|
|
ldr r3, Lbase_irq_softint_handler
|
|
ldr r3, [r3] /* r3 = *base_irq_softint_handler */
|
|
mov lr, pc
|
|
mov pc, r3
|
|
|
|
/*
|
|
* Reenable softints and disable HW interrupts
|
|
*/
|
|
ldr r2, Lbase_irq_nest
|
|
ldr r3, [r2]
|
|
bic r3, r3, #0x40 /* SOFTINT_CLEARED */
|
|
str r3, [r2]
|
|
mrs r3, cpsr_all
|
|
orr r3, r3, #0x80
|
|
msr cpsr_all, r3
|
|
|
|
nosoft:
|
|
mov r0, #0
|
|
ldmfd sp!, {pc}
|
|
mov r0, r0
|
|
|
|
Lisa_iobus_address:
|
|
.word EXT(isa_iobus_address)
|
|
|
|
Lbase_irq_nest:
|
|
.word EXT(base_irq_nest)
|
|
|
|
Lbase_irq_handlers:
|
|
.word EXT(base_irq_handlers)
|
|
|
|
Lbase_irq_softint_handler:
|
|
.word EXT(base_irq_softint_handler)
|