home *** CD-ROM | disk | FTP | other *** search
- ; 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),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
-
- XREF _kintr
- XREF _keyrec
-
- _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:
- move.w d0,-(sp) ; `repeated' keys don't generate
- move.w _keyrec+8,d0 ; interrupts... check buffer and
- cmp.w _keyrec+6,d0 ; set hi byte of kintr so that
- sne _kintr ; select can wake up before you
- move.w (sp)+,d0 ; release the key, etc.
- 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
- move.w #0,-(sp) ; not a system call
- jsr _enter_kernel ; enter kernel
- addq.w #2,sp
- 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
- XREF _mcpu
-
- ;
- ; 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:
- %ifndef ONLY030
- move.w #$8,_sig_exc
- cmp.l #30,_mcpu
- bne.s noMMU
- %endif
- move.l #_mmu_sigbus,_sig_routine
- %ifndef ONLY030
- bra.s Do_sig
- noMMU:
- move.l #_nommu_sigbus,_sig_routine
- %endif
- 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
- move.w #0,-(sp) ; not a GEMDOS call
- jsr _enter_kernel ; set up kernel vectors
- addq.w #2,sp
- 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
- %ifndef ONLY030
- ;
- ; _nommu_sigbus: handler for bus errors on machines without MMU
-
- _nommu_sigbus:
- move.l _curproc,a0
- move.l P_EXCSSP(a0),a1
- lea $10(a1),a1 ; point to access address
- tst.w ($59e).w ; test longframe
- beq.s NOMMU1
- addq.w #8,a1 ; on 68000, address is 8 bytes further
- NOMMU1:
- move.l (a1),P_EXCADDR(a0) ; save the access address
- jmp _sigbus
- %endif
-
- _new_addr:
- %ifndef ONLY030
- move.w #$c,_sig_exc
- %endif
- move.l #_sigaddr,_sig_routine
- bra Do_sig
- _new_ill:
- %ifndef ONLY030
- move.w #$10,_sig_exc
- %endif
- move.l #_sigill,_sig_routine
- bra Do_sig
- _new_divzero:
- %ifndef ONLY030
- move.w #$14,_sig_exc
- %endif
- move.l #_sigfpe,_sig_routine
- bra Do_sig
- _new_linef:
- %ifndef ONLY030
- move.w #$2c,_sig_exc
- %endif
- move.l #_sigill,_sig_routine
- bra Do_sig
- _new_chk:
- %ifndef ONLY030
- move.w #$18,_sig_exc
- %endif
- move.l #_sigfpe,_sig_routine
- bra Do_sig
- _new_trapv:
- %ifndef ONLY030
- move.w #$1c,_sig_exc
- %endif
- 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:
- %ifndef ONLY030
- move.w #$3c,_sig_exc
- %endif
- move.l #_sigbus,_sig_routine
- bra Do_sig
- _new_spurious:
- %ifndef ONLY030
- move.w #$60,_sig_exc
- %endif
- 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:
- %ifndef ONLY030
- move.w #$20,_sig_exc
- %endif
- move.l #_sigpriv,_sig_routine
- %ifndef 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
-