freebsd-dev/sys/i386/isa/icu.s
Garrett Wollman bd7d7eb52b Separated netisrs for pkintr() (X.25) and hdintr() (HDLC) so that someone
can actually write a sane netif device to support one of these.  Note that it
was necessary to steal a netisr bit from another protocol; I took the one for
PF_DATAKIT (no great loss).
1993-12-20 14:58:21 +00:00

395 lines
9.0 KiB
ArmAsm

/*-
* 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.
*
* @(#)icu.s 7.2 (Berkeley) 5/21/91
*
* $Id: icu.s,v 1.6 1993/12/19 00:50:35 wollman Exp $
*/
/*
* AT/386
* Vector interrupt control section
*/
/*
* XXX - this file is now misnamed. All spls are now soft and the only thing
* related to the hardware icu is that the bit numbering is the same in the
* soft priority masks as in the hard ones.
*/
#include "sio.h"
#define HIGHMASK 0xffff
#define SOFTCLOCKMASK 0x8000
.data
.globl _cpl
_cpl: .long 0xffff /* current priority (all off) */
.globl _imen
_imen: .long 0xffff /* interrupt mask enable (all off) */
/* .globl _highmask */
_highmask: .long HIGHMASK
.globl _ttymask, _biomask, _netmask
_ttymask: .long 0
_biomask: .long 0
_netmask: .long 0
.globl _ipending, _astpending
_ipending: .long 0
_astpending: .long 0 /* tells us an AST needs to be taken */
.globl _netisr
_netisr: .long 0 /* set with bits for which queue to service */
vec:
.long vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7
.long vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15
#define GENSPL(name, mask, event) \
.globl _spl/**/name ; \
ALIGN_TEXT ; \
_spl/**/name: ; \
COUNT_EVENT(_intrcnt_spl, event) ; \
movl _cpl,%eax ; \
movl %eax,%edx ; \
orl mask,%edx ; \
movl %edx,_cpl ; \
SHOW_CPL ; \
ret
#define FASTSPL(mask) \
movl mask,_cpl ; \
SHOW_CPL
#define FASTSPL_VARMASK(varmask) \
movl varmask,%eax ; \
movl %eax,_cpl ; \
SHOW_CPL
.text
ALIGN_TEXT
unpend_v:
COUNT_EVENT(_intrcnt_spl, 0)
bsfl %eax,%eax # slow, but not worth optimizing
btrl %eax,_ipending
jnc unpend_v_next # some intr cleared the in-memory bit
SHOW_IPENDING
movl Vresume(,%eax,4),%eax
testl %eax,%eax
je noresume
jmp %eax
ALIGN_TEXT
/*
* XXX - must be some fastintr, need to register those too.
*/
noresume:
#if NSIO > 0
call _softsio1
#endif
unpend_v_next:
movl _cpl,%eax
movl %eax,%edx
notl %eax
andl _ipending,%eax
je none_to_unpend
jmp unpend_v
/*
* Handle return from interrupt after device handler finishes
*/
ALIGN_TEXT
doreti:
COUNT_EVENT(_intrcnt_spl, 1)
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
SHOW_CPL
movl %eax,%edx
notl %eax
andl _ipending,%eax
jne unpend_v
none_to_unpend:
testl %edx,%edx # returning to zero priority?
jne 1f # nope, going to non-zero priority
movl _netisr,%eax
testl %eax,%eax # check for softint s/traps
jne 2f # there are some
jmp test_resched # XXX - schedule jumps better
COUNT_EVENT(_intrcnt_spl, 2) # XXX
ALIGN_TEXT # XXX
1: # XXX
COUNT_EVENT(_intrcnt_spl, 3)
popl %es
popl %ds
popal
addl $8,%esp
iret
#include "../net/netisr.h"
#define DONET(s, c, event) ; \
.globl c ; \
btrl $s,_netisr ; \
jnc 1f ; \
COUNT_EVENT(_intrcnt_spl, event) ; \
call c ; \
1:
ALIGN_TEXT
2:
COUNT_EVENT(_intrcnt_spl, 4)
/*
* 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).
*/
testl $~((1 << NETISR_SCLK) | (1 << NETISR_AST)),%eax
je test_ASTs # no net stuff, just temporary AST's
FASTSPL_VARMASK(_netmask)
#if 0
DONET(NETISR_RAW, _rawintr, 5)
#endif
#ifdef INET
DONET(NETISR_IP, _ipintr, 6)
#endif /* INET */
#ifdef IMP
DONET(NETISR_IMP, _impintr, 7)
#endif /* IMP */
#ifdef NS
DONET(NETISR_NS, _nsintr, 8)
#endif /* NS */
#ifdef ISO
DONET(NETISR_ISO, _clnlintr, 9)
#endif /* ISO */
#ifdef CCITT
DONET(NETISR_X25, _pkintr, 29)
DONET(NETISR_HDLC, _hdintr, 30)
#endif /* CCITT */
FASTSPL($0)
test_ASTs:
btrl $NETISR_SCLK,_netisr
jnc test_resched
COUNT_EVENT(_intrcnt_spl, 10)
FASTSPL($SOFTCLOCKMASK)
/*
* Back to an interrupt frame for a moment.
*/
pushl $0 # previous cpl (probably not used)
pushl $0x7f # dummy unit number
call _softclock
addl $8,%esp # discard dummies
FASTSPL($0)
test_resched:
#ifdef notused1
btrl $NETISR_AST,_netisr
jnc 2f
#endif
#ifdef notused2
cmpl $0,_want_resched
je 2f
#endif
cmpl $0,_astpending # XXX - put it back in netisr to
je 2f # reduce the number of tests
testb $SEL_RPL_MASK,TRAPF_CS_OFF(%esp)
# to non-kernel (i.e., user)?
je 2f # nope, leave
COUNT_EVENT(_intrcnt_spl, 11)
movl $0,_astpending
call _trap
2:
COUNT_EVENT(_intrcnt_spl, 12)
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(bio, _biomask, 13)
GENSPL(clock, $HIGHMASK, 14) /* splclock == splhigh ex for count */
GENSPL(high, $HIGHMASK, 15)
GENSPL(imp, _netmask, 16) /* splimp == splnet except for count */
GENSPL(net, _netmask, 17)
GENSPL(softclock, $SOFTCLOCKMASK, 18)
GENSPL(tty, _ttymask, 19)
.globl _splnone
.globl _spl0
ALIGN_TEXT
_splnone:
_spl0:
COUNT_EVENT(_intrcnt_spl, 20)
in_spl0:
movl _cpl,%eax
pushl %eax # save old priority
testl $(1 << NETISR_RAW) | (1 << NETISR_IP),_netisr
je over_net_stuff_for_spl0
movl _netmask,%eax # mask off those network devices
movl %eax,_cpl # set new priority
SHOW_CPL
/*
* XXX - what about other net intrs?
*/
#if 0
DONET(NETISR_RAW, _rawintr, 21)
#endif
#ifdef INET
DONET(NETISR_IP, _ipintr, 22)
#endif /* INET */
#ifdef IMP
DONET(NETISR_IMP, _impintr, 23)
#endif /* IMP */
#ifdef NS
DONET(NETISR_NS, _nsintr, 24)
#endif /* NS */
#ifdef ISO
DONET(NETISR_ISO, _clnlintr, 25)
#endif /* ISO */
over_net_stuff_for_spl0:
movl $0,_cpl # set new priority
SHOW_CPL
movl _ipending,%eax
testl %eax,%eax
jne unpend_V
popl %eax # return old priority
ret
.globl _splx
ALIGN_TEXT
_splx:
COUNT_EVENT(_intrcnt_spl, 26)
movl 4(%esp),%eax # new priority
testl %eax,%eax
je in_spl0 # going to "zero level" is special
COUNT_EVENT(_intrcnt_spl, 27)
movl _cpl,%edx # save old priority
movl %eax,_cpl # set new priority
SHOW_CPL
notl %eax
andl _ipending,%eax
jne unpend_V_result_edx
movl %edx,%eax # return old priority
ret
ALIGN_TEXT
unpend_V_result_edx:
pushl %edx
unpend_V:
COUNT_EVENT(_intrcnt_spl, 28)
bsfl %eax,%eax
btrl %eax,_ipending
jnc unpend_V_next
SHOW_IPENDING
movl Vresume(,%eax,4),%edx
testl %edx,%edx
je 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.
*/
noresumeV:
#if NSIO > 0
call _softsio1
#endif
unpend_V_next:
movl _cpl,%eax
notl %eax
andl _ipending,%eax
jne unpend_V
popl %eax
ret
#define BUILD_VEC(irq_num) \
ALIGN_TEXT ; \
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)