home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari FTP
/
ATARI_FTP_0693.zip
/
ATARI_FTP_0693
/
Mint
/
mint104s.zoo
/
mint.src
/
intr.spp
< prev
next >
Wrap
Text File
|
1993-03-08
|
13KB
|
477 lines
; Copyright 1992 Eric R. Smith
; All rights reserved.
%include "magic.i"
;
; interrupt wrapping routines; these should just save registers and call
; the appropriate C handlers, unless speed is a major problem
;
TEXT
;
; first, utilities for setting processor status level
;
XDEF _spl7,_spl
_spl7:
move.w sr,d0
ori.w #$0700,sr
rts
_spl:
move.w 4(sp),d0
move.w d0,sr
rts
XDEF _mint_5ms
XDEF _mint_timer
XDEF _mint_vbl
XREF _timeout ; C time routine
XREF _old_timer ; old GEMDOS time vector
XREF _old_vbl ; old GEMDOS vbl vector
XREF _old_5ms
XREF _build_context
XREF _restore_context
XREF _proc_clock ; controls process' allocation of CPU time
XREF _curproc
XREF _enter_kernel
XREF _leave_kernel
XREF _preempt
XREF _in_kernel
; AKP: this code is hit once every 5ms; it updates the time fields of curproc.
_mint_5ms:
move.l a0,-(sp)
move.l _curproc,a0
tst.w _in_kernel
bne.s L_systime
lea P_USRTIME(a0),a0 ; get offset to curproc->usrtime
addq.l #5,(a0) ; update the time
move.l (sp)+,a0
move.l _old_5ms+8,-(sp) ; branch to old vector
rts
L_systime:
lea P_SYSTIME(a0),a0 ; get offset to curproc->systime
addq.l #5,(a0)
move.l (sp)+,a0
move.l _old_5ms+8,-(sp)
rts
_mint_timer:
movem.l d0-d2/a0-a2,-(sp) ; save C registers
jsr _timeout
movem.l (sp)+,d0-d2/a0-a2
move.l _old_timer+8,-(sp) ; jump to GEMDOS time vector
rts
_mint_vbl:
%ifndef ONLY030
tst.w ($59e).w ; test longframe (AKP)
beq.s L_short1
%endif
clr.w -(sp) ; yes, long frames: push a frame word
L_short1:
pea L_comeback ; push fake PC
move.w sr,-(sp) ; push status register
move.l _old_vbl+8,-(sp) ; go service the interrupt
rts
L_comeback:
tst.w _proc_clock ; has time expired yet?
beq.s L_expired ; yes -- maybe go switch processes
L_out:
rte ; no -- just return
L_expired:
btst #5,(sp) ; user mode?
bne.s L_out ; no -- switching is not possible
tst.w ($43e).w ; test floppy disk lock variable
bne.s L_out ; if locked, can't switch
tst.w _in_kernel ; are we doing a kernel operation?
bne.s L_out
L_switch:
clr.w -(sp) ; no frame format needed
move.l _curproc,-(sp)
addq.l #P_CTXT0,(sp) ; to get &curproc->ctxt[SYSCALL]
jsr _build_context ; build context
move.l _curproc,a0
move.l (a0),sp ; use curproc->sysstack
jsr _enter_kernel ; enter kernel
jsr _preempt ; yield processor
ori.w #$700,sr ; spl7()
jsr _leave_kernel ; restore vectors
move.l _curproc,a0
pea 4(a0)
jsr _restore_context ; back to user
;
; reset routine -- called on a warm boot. Note that TOS sends the
; address to which we should return in register a6. Also note that
; the stack pointer is in an unknown state, so we set up our own
;
XDEF _reset
XREF _init_tail ; see main.c
XREF _restr_intr
_reset:
move.w #$2700,sr ; avoid interruption here
move.l sp,_init_tail ; save A7
lea _init_tail,sp ; set up temporary stack
lea 256(sp),sp
movem.l d0-d2/a0-a2,-(sp) ; save C registers
jsr _restr_intr ; restore interrupts
movem.l (sp)+,d0-d2/a0-a2 ; restore registers
move.l _init_tail,sp
jmp (a6) ; reset again
;
; routine for doing a reboot
;
XDEF _reboot
_reboot:
move.w #$2700,sr ; avoid interrupts
move.l (0).w,sp ; get sp after reboot
move.l (4).w,a6 ; get new reboot address
jmp _reset
;
; routine for mouse packet handling
;
XDEF _newmvec
XDEF _newjvec
XREF _mouse_handler
; Experimental three button mouse support (by jr@ms.maus.de,
; August 4, 1992
;
; Should work with the mice shipped with Atari's ASV or
; compatible ones (like Golden Image GI-6000). Might not work
; on ST/STE systems with older IKBD's or keyboards. The middle mouse
; button is wired to one of the joystick directions on joystick one.
;
; _newmvec is the same as before with two exceptions:
; 1. the first byte of the packet is saved for the joystick handler
; 2. the bit for the middle mouse button is ored in
;
; _newjvec hooks into the joystick vector and chains to the normal
; handler. The middle mouse button state is saved in a special
; register for _newmvec, and a 'fake' mouse packet is set up
; (by merging the last mouse packet header, or-ing in the
; middle button state and using 0/0 for the x/y increment).
;
; the faked_packet and third_button variables are declared at the
; end of this file
_newmvec:
move.l a0,-(sp)
move.b (a0),d0
move.b d0,faked_packet
or.b third_button,d0
move.b d0,(a0)
jsr _mouse_handler
move.l (sp)+,a0
rts
;
; routine for joystick packet handling (used for three button mice)
;
XDEF _newjvec
XREF _oldjvec
_newjvec:
move.l a0,-(sp) ; save a0 on the stack
move.b 2(a0),d0 ; joystick direction
and.b #1,d0 ; middle mouse button in lowest bit
add.b d0,d0 ; times 4
add.b d0,d0
move.b d0,third_button ; save it for use in newmvec
lea faked_packet,a0 ; 'our' faked mouse event
move.b (a0),d0
and.b #$3,d0 ; unmask our mouse button
or.b #$F8,d0 ; or in correct header
or.b third_button,d0 ; or in the current status
move.b d0,(a0) ; write it back
move.l a0,-(sp) ; pass pointer to fake packet
jsr _mouse_handler ; to \dev\mouse handler
addq.l #4,sp ; pop parameter
move.l (sp)+,a0 ; restore original a0 value
move.l _oldjvec,-(sp) ; jump to original joystick handler
rts
;
; new ikbd keyboard interrupt vector
; kintr is a global variable that should be non-zero if a keyboard
; event occured
;
XDEF _new_ikbd
XREF _old_ikbd
XREF _kintr
_new_ikbd:
move.w #1,_kintr
move.l _old_ikbd+8,-(sp)
rts ; jump to system interrupt routine
;
; simple signal handlers
; global variables referenced:
; in_kernel: (main.c): flag to indicate that we're in the MiNT kernel
; sig_routine: (signal.c): pointer to which signal catching routine to
; call (e.g. for SIGBUS, or whatever)
;
XDEF _new_bus,_new_addr,_new_ill,_new_divzero,_new_priv,_new_linef
XDEF _new_trace,_new_chk,_new_trapv,_new_fpcp,_new_mmu,_new_pmmuacc
XDEF _new_uninit,_new_spurious,_new_format,_new_cpv
XREF _in_kernel,_sig_routine
XREF _sigbus,_sigaddr,_sigill,_sigfpe,_sigpriv,_sigtrap
XREF _haltformat,_haltcpv
XREF _sig_exc
;
; New bus error handler for memory protection: get the ssp and
; put it in the proc structure before calling
; _sigbus. When the bus error happens in the kernel we don't save
; any contexts.
; We don't want to mess up any registers here because we might bring the
; page in and RTE.
;
_new_bus:
move.w #$8,_sig_exc
move.l #_mmu_sigbus,_sig_routine
Do_sig:
move.l a0,-(sp) ; save a0
move.l _curproc,a0
move.l sp,P_EXCSSP(a0)
addq.l #4,P_EXCSSP(a0)
move.l 6(sp),P_EXCPC(a0)
move.l (sp)+,a0
tst.w _in_kernel ; are we already in the kernel?
bne.s Kernel ; yes
move.w _sig_exc,-(sp)
move.l _curproc,-(sp)
addq.l #4,(sp) ; push offset of save area
jsr _build_context
move.l _curproc,a4
move.l (a4),sp ; put us in the system stack
jsr _enter_kernel ; set up kernel vectors
move.l _sig_routine,a1 ; get signal handling routine
jsr (a1) ; go do it
ori.w #$0700,sr ; spl7()
jsr _leave_kernel ; leave kernel
addq.w #4,a4 ; get context save area address
move.l a4,-(sp) ; push it
jsr _restore_context ; restore the context
;
; here's what we do if we already were in the kernel
;
Kernel:
movem.l d0-d2/a0-a2,-(sp) ; save reggies
move.l _sig_routine,a1 ; get handler
jsr (a1) ; go do it
movem.l (sp)+,d0-d2/a0-a2
rte
;
; _mmu_sigbus: a pre-handler for _sigbus. Check the reason for the bus
; error and report if it was a real access fault.
;
_mmu_sigbus:
move.l a2,-(sp)
move.l _curproc,a0
move.l P_EXCSSP(a0),a1 ; a1 is now exception_ssp
move.w $A(a1),d0 ; d0 is SSR
move.l $10(a1),a1 ; a1 is the access address
move.l a1,P_EXCADDR(a0) ; save the access address
ptestr d0,(a1),#7,a2 ; a2 is the table address
move.l a2,P_EXCTBL(a0) ; save table address in curproc
pmove mmusr,P_EXCMMUSR(a0) ; save resulting mmusr in curproc
move.l (sp)+,a2
jmp _sigbus ; chain to bus-error handler
_new_addr:
move.w #$c,_sig_exc
move.l #_sigaddr,_sig_routine
bra Do_sig
_new_ill:
move.w #$10,_sig_exc
move.l #_sigill,_sig_routine
bra Do_sig
_new_divzero:
move.w #$14,_sig_exc
move.l #_sigfpe,_sig_routine
bra Do_sig
_new_linef:
move.w #$2c,_sig_exc
move.l #_sigill,_sig_routine
bra Do_sig
_new_chk:
move.w #$18,_sig_exc
move.l #_sigfpe,_sig_routine
bra Do_sig
_new_trapv:
move.w #$1c,_sig_exc
move.l #_sigfpe,_sig_routine
bra Do_sig
_new_fpcp:
; don't set _sig_exc - only needed for 68000 vectors
move.l #_sigfpe,_sig_routine
bra Do_sig
_new_mmu:
; don't set _sig_exc - only needed for 68000 vectors
move.l #_sigill,_sig_routine
bra Do_sig
_new_pmmuacc:
; don't set _sig_exc - only needed for 68000 vectors
move.l #_sigbus,_sig_routine
bra Do_sig
_new_uninit:
move.w #$3c,_sig_exc
move.l #_sigbus,_sig_routine
bra Do_sig
_new_spurious:
move.w #$60,_sig_exc
move.l #_sigbus,_sig_routine
bra Do_sig
_new_format:
move.l #_haltformat,_sig_routine
bra Do_sig
_new_cpv:
move.l #_haltcpv,_sig_routine
bra Do_sig
XREF _old_priv ; old privilege violation vector
_new_priv:
move.w #$20,_sig_exc
move.l #_sigpriv,_sig_routine
%ifdef ONLY030
tst.w ($59e).w ; 68000s always get SIGPRIV
beq Do_sig
%endif
movem.l d0/a0,-(a7)
move.l 10(a7),a0 ; fetch exception address
move.w (a0),d0
and.w #$ffc0,d0 ; partially decode move sr,...
cmp.w #$40c0,d0 ; and test it
movem.l (a7)+,d0/a0 ; preserves the flags
bne Do_sig ; doesn't look like sr,...
move.l _old_priv+8,-(sp) ; let our parent handle it
rts
; XBRA vectors from main.c
XREF _old_dos,_old_bios,_old_xbios
XREF _old_divzero,_old_chk,_old_trapv
_new_trace:
btst #5,(a7) ; only check when called from supervisor mode
beq.s S_1
cmp.l #_old_dos+12,2(a7) ; lets not trace the kernel !
beq.s S_2
cmp.l #_old_xbios+12,2(a7)
beq.s S_2
cmp.l #_old_bios+12,2(a7)
beq.s S_2
cmp.l #_old_divzero+12,2(a7)
beq.s S_2
cmp.l #_old_trapv+12,2(a7)
beq.s S_2
cmp.l #_old_chk+12,2(a7)
beq.s S_2
; add any other non-traceable entities here...
S_1: move.w #$24,_sig_exc
move.l #_sigtrap,_sig_routine
bra Do_sig
S_2: and.w #$3fff,(a7) ; clear both trace bits
rte ; and re-start the handler
;
; BIOS disk vectors for pseudo-disks like U: and X:; these are present
; just in case some program (foolishly) attempts to access these drives
; directly and gets horribly confused
;
XREF _old_getbpb ; old Getbpb vector
XREF _old_mediach ; old Mediach vector
XREF _old_rwabs ; old Rwabs vector
XREF _aliasdrv ; array of drive aliases
XDEF _new_getbpb
XDEF _new_mediach
XDEF _new_rwabs
_new_getbpb:
move.w 4(sp),d0 ; check the drive
cmp.w #$1f,d0 ; legal drive?
bhi.s noalias0 ; no
move.w d0,d1 ; get index
add.w d0,d1 ; convert to index
lea _aliasdrv,a0
move.w 0(a0,d1.w),d1 ; alias drive?
beq.s noalias0
move.w d1,d0
subq.w #1,d0 ; adjust for aliasdrv base of '@'
cmp.w #$1f,d0 ; is this a legal drive?
bhi.s nobpb ; no -- ignore it
noalias0:
cmp.w #$14,d0 ; drive U:?
beq.s nobpb ; yes, no BPB available
move.l _old_getbpb+8,a0 ; not our drive
jmp (a0) ; call the old vector for it
nobpb:
moveq.l #0,d0 ; 0 means "no BPB read"
rts
_new_mediach:
move.w 4(sp),d0 ; check the drive
cmp.w #$1f,d0 ; legal drive?
bhi.s noalias1 ; no
move.w d0,d1 ; get index
add.w d0,d1 ; convert to index
lea _aliasdrv,a0
move.w 0(a0,d1.w),d1 ; alias drive?
beq.s noalias1
move.w d1,d0
subq.w #1,d0 ; adjust for aliasdrv base
cmp.w #$1f,d0 ; legal drive?
bhi.s nobpb ; no -- ignore it
noalias1:
cmp.w #$14,d0 ; drive U:?
beq.s nochng ; yes, no change
move.l _old_mediach+8,a0 ; not our drive
jmp (a0) ; call the old vector for it
nochng:
moveq.l #0,d0 ; 0 means "definitely no change"
rts
_new_rwabs:
move.w $e(sp),d0 ; check the drive
cmp.w #$1f,d0 ; legal drive?
bhi.s noalias2 ; no
move.w d0,d1 ; get index
add.w d0,d1 ; convert to index
lea _aliasdrv,a0
move.w 0(a0,d1.w),d1 ; alias drive?
beq.s noalias2
move.w d1,d0
subq.w #1,d0 ; adjust for aliasdrv base
cmp.w #$1f,d0 ; legal drive?
bhi.s nobpb ; no -- ignore it
noalias2:
cmp.w #$14,d0 ; drive U:?
beq.s rwdone ; yes, fake it
move.l _old_rwabs+8,a0 ; not our drive
jmp (a0) ; call the old vector for it
rwdone:
moveq.l #0,d0 ; 0 means "successful operation"
rts
DATA
; buffer for faked mouse packet (actually only 3 bytes)
faked_packet:
dc.l 0
; here we store the additional button state
third_button:
dc.w 0
END