Files
Arquivotheca.SunOS-4.1.4/sys/sparc/zs_asm.s
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

139 lines
3.5 KiB
ArmAsm

/*
* Copyright (c) 1987, 1988, 1989 by Sun Microsystems, Inc.
*/
#include "assym.s"
#include <machine/param.h>
#include <machine/asm_linkage.h>
#include <machine/mmu.h>
#include <machine/psl.h>
#include <sundev/zsreg.h>
#include <machine/intreg.h>
.seg "data"
.asciz "@(#)zs_asm.s 1.1 94/10/31"
.align 4
.seg "text"
#ifndef sun4c
/*
* UARTs require 1.6 usec recovery time
* note ZSRECOVER can't be used in a leaf routine
* this is overkill by .4 usec but it scales properly for all cpus
*/
#define ZSRECOVER() \
call _usec_delay; \
mov 2, %o0;
#else sun4c
/* SPARCstation 1 doesn't need a delay. */
#define ZSRECOVER()
#endif sun4c
/*
* We come here for auto-vectored interrupts
* We assume that the most recently interrupting
* chip is interrupting again and read the vector out of the
* chip and branch to the right routine. The "special receive"
* interrupt routine gets control if the assumption was wrong
* and performs the longer task of figuring out who is really interrupting
* and why.
*/
.global _zscurr
.global _zsNcurr
ENTRY(zslevel12)
save %sp, -SA(MINFRAME), %sp ! get a new window
set _zscurr, %g1 ! most active channel desc pointer
ld [%g1], %l0 ! read it
mov 2, %g2 ! register number 2 in channel B
ld [%l0 + ZS_ADDR], %l1 ! get address of hardware channel
stb %g2, [%l1] ! set register to read
ZSRECOVER();
ldub [%l1], %l2 ! get interrupt vector number
ZSRECOVER();
btst 8, %l2 ! channel A?
bnz,a 1f ! if not anull next instruction
sub %l0, ZSSIZE, %l0 ! point to channel A's descriptor
1:
set _zsNcurr, %g1 ! stash the [modified] channel
st %l0, [%g1] ! where it MIGHT be changed
and %l2, 6, %l2 ! get vetor bits
add %l2, %l2, %l2 ! get multiple of 4
ld [%l0 + %l2], %g1 ! get address of routine to call
call %g1 ! go to it
mov %l0, %o0 ! delay slot, fix argument
set _zsNcurr, %g1 ! restore the channel, since
ld [%g1], %l0 ! it might have been changed
ld [%l0 + ZS_ADDR], %l1 ! get address of hardware channel
mov ZSWR0_CLR_INTR, %g2 ! value to clear interrupt
stb %g2, [%l1] ! clear interrupt
ZSRECOVER();
ret
restore
/*
* Turn on a zs soft interrupt.
*/
ENTRY(setzssoft)
mov %psr, %g2
or %g2, PSR_PIL, %g1 ! spl hi to protect intreg update
mov %g1, %psr
nop; nop; ! psr delay
set INTREG_ADDR, %o0 ! set address of interrupt register
ldub [%o0], %o1 ! read it
bset IR_SOFT_INT6, %o1 ! set zs soft interrupt bit
stb %o1, [%o0] ! write it out
mov %g2, %psr ! restore psr
nop ! psr delay
retl ! leaf routine return
nop
/*
* Test and clear a zs soft interrupt.
*/
ENTRY(clrzssoft)
set INTREG_ADDR, %o1 ! set address of interrupt register
ldub [%o1], %o2 ! read it
btst IR_SOFT_INT6, %o2 ! was there an interrupt pending?
bz,a 1f ! no, simply return 0
mov 0, %o0 ! return value
mov %psr, %g2
or %g2, PSR_PIL, %g1 ! spl hi to protect intreg update
mov %g1, %psr
nop; nop; ! psr delay
mov 1, %o0 ! otherwise one was pending
ldub [%o1], %o2 ! read it
bclr IR_SOFT_INT6, %o2 ! clear zs soft int bit
stb %o2, [%o1] ! write interrupt register
mov %g2, %psr ! restore psr
nop ! psr delay
1:
retl
nop
/*
* Read a control register in the chip
*/
ENTRY(zszread)
save %sp, -SA(MINFRAME), %sp ! get a new window
stb %i1, [%i0] ! write register number
ZSRECOVER();
ldub [%i0], %i0 ! read register
ZSRECOVER();
ret
restore
/*
* Write a control register in the chip
*/
ENTRY(zszwrite)
save %sp, -SA(MINFRAME), %sp ! get a new window
stb %i1, [%i0] ! write register number
ZSRECOVER();
stb %i2, [%i0] ! write data
ZSRECOVER();
ret
restore