mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
bd7d7eb52b
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).
395 lines
9.0 KiB
ArmAsm
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)
|