346 lines
8.0 KiB
ArmAsm
346 lines
8.0 KiB
ArmAsm
/*-
|
|
* Copyright (c) 1993, 1994 Charles Hannum.
|
|
* Copyright (c) 1989, 1990 William F. Jolitz.
|
|
* Copyright (c) 1990 The Regents of the University of California.
|
|
* All rights reserved.
|
|
*
|
|
* This code is derived from software contributed to Berkeley by
|
|
* William Jolitz.
|
|
*
|
|
* 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 the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
|
*
|
|
* from: @(#)icu.s 7.2 (Berkeley) 5/21/91
|
|
* $Id: icu.s,v 1.25 1994/03/09 07:58:40 mycroft Exp $
|
|
*/
|
|
|
|
/*
|
|
* AT/386
|
|
* Vector interrupt control section
|
|
*/
|
|
|
|
#include <net/netisr.h>
|
|
|
|
/*
|
|
* All spl levels include astmask; this forces cpl to be non-zero when
|
|
* splx()ing from nested spl levels, and thus soft interrupts do not
|
|
* get executed. Logically, all spl levels are `above' soft interupts.
|
|
*/
|
|
|
|
#ifdef notyet
|
|
#include "sio.h"
|
|
#else
|
|
#define NSIO 0
|
|
#endif
|
|
|
|
.data
|
|
.globl _cpl
|
|
_cpl:
|
|
.long -1 # current priority (all off)
|
|
.globl _highmask
|
|
_highmask:
|
|
.long -1 # XXX needed for braindead config
|
|
.globl _ipending
|
|
_ipending:
|
|
.long 0
|
|
.globl _imen
|
|
_imen:
|
|
.long 0xffff # interrupt mask enable (all off)
|
|
.globl _clockmask
|
|
_clockmask:
|
|
.long 1
|
|
.globl _ttymask
|
|
_ttymask:
|
|
.long 0
|
|
.globl _biomask
|
|
_biomask:
|
|
.long 0
|
|
.globl _netmask
|
|
_netmask:
|
|
.long 0
|
|
.globl _impmask
|
|
_impmask:
|
|
.long 0
|
|
.globl _astmask
|
|
_astmask:
|
|
.long 0x80000000
|
|
|
|
vec:
|
|
.long INTRLOCAL(vec0), INTRLOCAL(vec1), INTRLOCAL(vec2)
|
|
.long INTRLOCAL(vec3), INTRLOCAL(vec4), INTRLOCAL(vec5)
|
|
.long INTRLOCAL(vec6), INTRLOCAL(vec7), INTRLOCAL(vec8)
|
|
.long INTRLOCAL(vec9), INTRLOCAL(vec10), INTRLOCAL(vec11)
|
|
.long INTRLOCAL(vec12), INTRLOCAL(vec13), INTRLOCAL(vec14)
|
|
.long INTRLOCAL(vec15)
|
|
|
|
#define GENSPL(name, mask, event) \
|
|
.globl _spl/**/name ; \
|
|
ALIGN_TEXT ; \
|
|
_spl/**/name: ; \
|
|
movl _cpl,%eax ; \
|
|
movl %eax,%edx ; \
|
|
orl mask,%edx ; \
|
|
movl %edx,_cpl ; \
|
|
ret
|
|
|
|
#define FASTSPL(mask) \
|
|
movl mask,_cpl
|
|
|
|
#define FASTSPL_VARMASK(varmask) \
|
|
movl varmask,%eax ; \
|
|
movl %eax,_cpl
|
|
|
|
.text
|
|
|
|
ALIGN_TEXT
|
|
INTRLOCAL(unpend_v):
|
|
bsfl %eax,%eax # slow, but not worth optimizing
|
|
btrl %eax,_ipending
|
|
jnc INTRLOCAL(unpend_v_next) # some intr cleared the in-memory bit
|
|
movl Vresume(,%eax,4),%eax
|
|
testl %eax,%eax
|
|
jz INTRLOCAL(noresume)
|
|
jmp %eax
|
|
|
|
ALIGN_TEXT
|
|
/*
|
|
* XXX - must be some fastintr, need to register those too.
|
|
*/
|
|
INTRLOCAL(noresume):
|
|
#if NSIO > 0
|
|
call _softsio1
|
|
#endif
|
|
INTRLOCAL(unpend_v_next):
|
|
movl _cpl,%eax
|
|
movl %eax,%edx
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jz INTRLOCAL(none_to_unpend)
|
|
jmp INTRLOCAL(unpend_v)
|
|
|
|
/*
|
|
* Handle return from interrupt after device handler finishes
|
|
*/
|
|
ALIGN_TEXT
|
|
doreti:
|
|
addl $4,%esp # discard unit arg
|
|
popl %eax # get previous priority
|
|
/*
|
|
* Now interrupt frame is a trap frame!
|
|
*
|
|
* XXX - setting up the interrupt frame to be almost a stack frame is mostly
|
|
* a waste of time.
|
|
*/
|
|
movl %eax,_cpl
|
|
movl %eax,%edx
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jnz INTRLOCAL(unpend_v)
|
|
INTRLOCAL(none_to_unpend):
|
|
testl %edx,%edx # returning to zero priority?
|
|
jz 2f
|
|
popl %es
|
|
popl %ds
|
|
popal
|
|
addl $8,%esp
|
|
iret
|
|
|
|
|
|
.globl _netisr,_sir
|
|
|
|
#define DONET(s, c, event) ; \
|
|
.globl c ; \
|
|
btrl $s,_netisr ; \
|
|
jnc 1f ; \
|
|
call c ; \
|
|
1:
|
|
|
|
ALIGN_TEXT
|
|
2:
|
|
/*
|
|
* XXX - might need extra locking while testing reg copy of netisr, but
|
|
* interrupt routines setting it would not cause any new problems (since we
|
|
* don't loop, fresh bits will not be processed until the next doreti or spl0)
|
|
*/
|
|
btrl $SIR_NET,_sir
|
|
jnc test_clock
|
|
FASTSPL_VARMASK(_netmask)
|
|
DONET(NETISR_RAW, _rawintr, 5)
|
|
#ifdef INET
|
|
DONET(NETISR_IP, _ipintr, 6)
|
|
#endif
|
|
#ifdef IMP
|
|
DONET(NETISR_IMP, _impintr, 7)
|
|
#endif
|
|
#ifdef NS
|
|
DONET(NETISR_NS, _nsintr, 8)
|
|
#endif
|
|
#ifdef ISO
|
|
DONET(NETISR_ISO, _clnlintr, 25)
|
|
#endif
|
|
FASTSPL($0)
|
|
test_clock:
|
|
btrl $SIR_CLOCK,_sir
|
|
jnc test_ast
|
|
FASTSPL_VARMASK(_astmask)
|
|
pushl $0 # XXX previous cpl (probably not used)
|
|
pushl $0x7f # XXX dummy unit number
|
|
pushl %esp
|
|
call _softclock
|
|
addl $12,%esp # XXX discard dummies
|
|
FASTSPL($0)
|
|
test_ast:
|
|
btrl $SIR_AST,_sir # signal handling, rescheduling, ...
|
|
jnc 2f
|
|
testb $SEL_RPL_MASK,TF_CS(%esp)
|
|
# to non-kernel (i.e., user)?
|
|
jz 2f # nope, leave
|
|
call _trap
|
|
2:
|
|
popl %es
|
|
popl %ds
|
|
popal
|
|
addl $8,%esp
|
|
iret
|
|
|
|
/*
|
|
* Interrupt priority mechanism
|
|
* -- soft splXX masks with group mechanism (cpl)
|
|
* -- h/w masks for currently active or unused interrupts (imen)
|
|
* -- ipending = active interrupts currently masked by cpl
|
|
*/
|
|
|
|
GENSPL(tty, _ttymask, 18)
|
|
GENSPL(bio, _biomask, 12)
|
|
GENSPL(net, _netmask, 16)
|
|
GENSPL(imp, _impmask, 15)
|
|
GENSPL(high, $-1, 14)
|
|
GENSPL(clock, _clockmask, 13)
|
|
GENSPL(softclock, _astmask, 17)
|
|
|
|
.globl _spl0
|
|
ALIGN_TEXT
|
|
_spl0:
|
|
in_spl0:
|
|
movl _cpl,%eax
|
|
pushl %eax # save old priority
|
|
btrl $SIR_NET,_sir
|
|
jnc INTRLOCAL(over_net_stuff_for_spl0)
|
|
FASTSPL_VARMASK(_netmask)
|
|
DONET(NETISR_RAW, _rawintr, 20)
|
|
#ifdef INET
|
|
DONET(NETISR_IP, _ipintr, 21)
|
|
#endif
|
|
#ifdef IMP
|
|
DONET(NETISR_IMP, _impintr, 26)
|
|
#endif
|
|
#ifdef NS
|
|
DONET(NETISR_NS, _nsintr, 27)
|
|
#endif
|
|
#ifdef ISO
|
|
DONET(NETISR_ISO, _clnlintr, 28)
|
|
#endif
|
|
INTRLOCAL(over_net_stuff_for_spl0):
|
|
FASTSPL($0)
|
|
movl _ipending,%eax
|
|
testl %eax,%eax
|
|
jnz INTRLOCAL(unpend_V)
|
|
popl %eax # return old priority
|
|
ret
|
|
|
|
.globl _splx
|
|
ALIGN_TEXT
|
|
_splx:
|
|
movl 4(%esp),%eax # new priority
|
|
testl %eax,%eax
|
|
jz in_spl0 # going to "zero level" is special
|
|
pushl _cpl # save old priority
|
|
movl %eax,_cpl # set new priority
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jnz INTRLOCAL(unpend_V)
|
|
popl %eax # return old priority
|
|
ret
|
|
|
|
ALIGN_TEXT
|
|
INTRLOCAL(unpend_V):
|
|
bsfl %eax,%eax
|
|
btrl %eax,_ipending
|
|
jnc INTRLOCAL(unpend_V_next)
|
|
movl Vresume(,%eax,4),%edx
|
|
testl %edx,%edx
|
|
jz INTRLOCAL(noresumeV)
|
|
/*
|
|
* We would prefer to call the intr handler directly here but that doesn't
|
|
* work for badly behaved handlers that want the interrupt frame. Also,
|
|
* there's a problem determining the unit number. We should change the
|
|
* interface so that the unit number is not determined at config time.
|
|
*/
|
|
jmp *vec(,%eax,4)
|
|
|
|
ALIGN_TEXT
|
|
/*
|
|
* XXX - must be some fastintr, need to register those too.
|
|
*/
|
|
INTRLOCAL(noresumeV):
|
|
#if NSIO > 0
|
|
call _softsio1
|
|
#endif
|
|
INTRLOCAL(unpend_V_next):
|
|
movl _cpl,%eax
|
|
notl %eax
|
|
andl _ipending,%eax
|
|
jnz INTRLOCAL(unpend_V)
|
|
popl %eax
|
|
ret
|
|
|
|
#define BUILD_VEC(irq_num) \
|
|
ALIGN_TEXT ; \
|
|
INTRLOCAL(vec/**/irq_num): ; \
|
|
int $(ICU_OFFSET + irq_num) ; \
|
|
popl %eax ; \
|
|
ret
|
|
|
|
BUILD_VEC(0)
|
|
BUILD_VEC(1)
|
|
BUILD_VEC(2)
|
|
BUILD_VEC(3)
|
|
BUILD_VEC(4)
|
|
BUILD_VEC(5)
|
|
BUILD_VEC(6)
|
|
BUILD_VEC(7)
|
|
BUILD_VEC(8)
|
|
BUILD_VEC(9)
|
|
BUILD_VEC(10)
|
|
BUILD_VEC(11)
|
|
BUILD_VEC(12)
|
|
BUILD_VEC(13)
|
|
BUILD_VEC(14)
|
|
BUILD_VEC(15)
|
|
|