BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / i386 / isa / icu.s
/*-
* 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
*/
/*
* AT/386
* Vector interrupt control section
*/
.data
.globl _imen
.globl _cpl
_cpl: .long 0xffff # current priority level (all off)
_imen: .long 0xffff # interrupt mask enable (all off)
.globl _highmask
_highmask: .long 0xffff
.globl _ttymask
_ttymask: .long 0
.globl _biomask
_biomask: .long 0
.globl _netmask
_netmask: .long 0
.globl _isa_intr
_isa_intr: .space 16*4
.text
/*
* Handle return from interrupt after device handler finishes
*/
doreti:
cli
popl %ebx # remove intr number
popl %eax # get previous priority
# now interrupt frame is a trap frame!
movw %ax,%cx
movw %ax,_cpl
orw _imen,%ax
NOP
outb %al,$ IO_ICU1+1 # re-enable intr?
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
andw $0xffff,%cx
cmpw $0,%cx # returning to zero?
je 1f
pop %es # nope, going to non-zero level
pop %ds
popa
addl $8,%esp
iret
1: cmpl $0,_netisr # check for softint s/traps
jne 1f
pop %es # none, going back to base pri
pop %ds
popa
addl $8,%esp
iret
#include "../net/netisr.h"
1:
#define DONET(s, c) ; \
.globl c ; \
movl $ s ,%eax ; \
btrl %eax,_netisr ; \
jnb 1f ; \
call c ; \
1:
call _splnet
pushl %eax
DONET(NETISR_RAW,_rawintr)
#ifdef INET
DONET(NETISR_IP,_ipintr)
#endif
#ifdef IMP
DONET(NETISR_IMP,_impintr)
#endif
#ifdef NS
DONET(NETISR_NS,_nsintr)
#endif
popl %eax
movw %ax,_cpl
orw _imen,%ax
NOP
outb %al,$ IO_ICU1+1 # re-enable intr?
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
# btrl $ NETISR_SCLK,_netisr
movl $ NETISR_SCLK,%eax # stupid assembler, as usual
btrl %eax,_netisr
jnb 1f
# back to an interrupt frame for a moment
call _splsoftclock
pushl %eax
pushl $0xff # dummy intr
call _softclock
popl %eax
call _splx
popl %eax
jmp 2f
/* 1: btrl $NETISR_AST,_netisr*/
1:
cmpw $0x1f,13*4(%esp) # to user?
jne 2f # nope, leave
movl $ NETISR_AST,%eax # stupid assembler, as usual
btrl %eax,_netisr
jnb 2f
call _trap
2: pop %es
pop %ds
popal
addl $8,%esp
iret
/*
* Interrupt priority mechanism
*
* Two flavors -- imlXX masks relative to ISA noemenclature (for PC compat sw)
* -- splXX masks with group mechanism for BSD purposes
*/
.globl _splhigh
.globl _splclock
_splhigh:
_splclock:
cli # disable interrupts
movw $0xffff,%ax # set new priority level
movw %ax,%dx
# orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _spltty # block clists
_spltty:
cli # disable interrupts
movw _cpl,%ax
orw _ttymask,%ax
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _splimp
.globl _splnet
_splimp:
_splnet:
cli # disable interrupts
movw _cpl,%ax
orw _netmask,%ax
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _splbio
_splbio:
cli # disable interrupts
movw _cpl,%ax
orw _biomask,%ax
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _splsoftclock
_splsoftclock:
cli # disable interrupts
movw _cpl,%ax
orw $0x8000,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _splnone
.globl _spl0
_splnone:
_spl0:
cli # disable interrupts
pushl _cpl # save old priority
movw _cpl,%ax
orw _netmask,%ax # mask off those network devices
movw %ax,_cpl # set new priority level
orw _imen,%ax # mask off those not enabled yet
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
sti # enable interrupts
DONET(NETISR_RAW,_rawintr)
#ifdef INET
DONET(NETISR_IP,_ipintr)
#endif
cli # disable interrupts
popl _cpl # save old priority
movw $0,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _splx
_splx:
cli # disable interrupts
movw 4(%esp),%ax # new priority level
movw %ax,%dx
cmpw $0,%dx
je _spl0 # going to "zero level" is special
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
inb $0x84,%al
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
#ifdef notyet
.globl _iml8 # mask off all but irq0-1
_iml8:
cli # disable interrupts
movw $0xfffc,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml10 # mask off all but irq0-1,8-9
_iml10:
cli # disable interrupts
movw $0xfcf8,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml11 # mask off all but irq0-1,8-10
_iml11:
cli # disable interrupts
movw $0xf8f8,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml12 # mask off all but irq0-1,8-11
_iml12:
cli # disable interrupts
movw $0xf0f8,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml13 # mask off all but irq0-1,8-12
_iml13:
cli # disable interrupts
movw $0xe0f8,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml15 # mask off all but irq0-1,8-14
_iml15:
cli # disable interrupts
movw $0x80f8,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml3 # mask off all but irq0-1,8-15
_iml3:
cli # disable interrupts
movw $0x00f8,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml4 # mask off all but irq0-1,8-15,3
_iml4:
cli # disable interrupts
movw $0x00f0,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml5 # mask off all but irq0-1,8-15,3-4
_iml5:
cli # disable interrupts
movw $0x00e0,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
.globl _iml6 # mask off all but irq0-1,8-15,3-5
_iml6:
cli # disable interrupts
movw $0x00c0,%ax # set new priority level
movw %ax,%dx
orw _imen,%ax # mask off those not enabled yet
movw %ax,%cx
NOP
outb %al,$ IO_ICU1+1 /* update icu's */
NOP
movb %ah,%al
NOP
outb %al,$ IO_ICU2+1
NOP
movzwl _cpl,%eax # return old priority
movw %dx,_cpl # set new priority level
sti # enable interrupts
ret
#endif notyet
/* hardware interrupt catcher (IDT 32 - 47) */
.globl _isa_strayintr
IDTVEC(intr0)
INTR(0, _highmask, 0) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr1)
INTR(1, _highmask, 1) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr2)
INTR(2, _highmask, 2) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr3)
INTR(3, _highmask, 3) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr4)
INTR(4, _highmask, 4) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr5)
INTR(5, _highmask, 5) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr6)
INTR(6, _highmask, 6) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr7)
INTR(7, _highmask, 7) ; call _isa_strayintr ; INTREXIT1
IDTVEC(intr8)
INTR(8, _highmask, 8) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr9)
INTR(9, _highmask, 9) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr10)
INTR(10, _highmask, 10) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr11)
INTR(11, _highmask, 11) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr12)
INTR(12, _highmask, 12) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr13)
INTR(13, _highmask, 13) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr14)
INTR(14, _highmask, 14) ; call _isa_strayintr ; INTREXIT2
IDTVEC(intr15)
INTR(15, _highmask, 15) ; call _isa_strayintr ; INTREXIT2