File:  [Atari MiNT] / MiNT / src / asm / intr.s
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:55:36 2018 UTC (8 years, 1 month ago) by root
Branches: mint, MAIN
CVS tags: mint095, HEAD
MiNT 0.95 pl13

;

; interrupt wrapping routines; these should just save registers and call

; the appropriate C handlers, unless speed is a major problem

;

; $Log: intr.s,v $
; Revision 1.1.1.1  2018/04/24 17:55:36  root
; MiNT 0.95 pl13
;

; Revision 1.5  1992/04/18  10:57:18  AGK

; More +8s for 0.94

;

; Revision 1.4  1992/04/04  16:05:54  AGK

; Added some missing +8s in the vector pushes to allow for XBRA support

;

; Revision 1.3  1992/03/31  14:02:08  AGK

; Fixed for real Motorola syntax (many thanks to ERS for keeping these

; files in step with the GAS ones).

;

; Revision 1.2  1992/03/31  13:55:28  AGK

; Checked in MiNT 0.93 sources

;

; Revision 1.1  1991/05/30  17:22:18  AGK

; Initial revision

;

	SECTION	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

	add.w	#$364,a0		; $364 is offset to curproc->systime;

	tst.w	_in_kernel

	bne	L_5a			; usrtime is the branch-not-taken case

	addq.l	#4,a0

L_5a:	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:

	tst.w	($59e).w		; test longframe (AKP)

	beq.s	L_short1

	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	#13,(sp)		; user mode?

	bne.s	L_out			; no -- switching is not possible

L_switch:

	move.l	_curproc,-(sp)

	addq.l	#4,(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	_tmpstack		; see main.c

	XREF	_restr_intr



_reset:

	move.w	#$2700,sr		; avoid interruption here

	move.l	sp,_tmpstack		; save A7

	lea	_tmpstack,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	_tmpstack,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

	XREF	_mouse_handler



_newmvec:

	move.l	a0,-(sp)

	jsr	_mouse_handler

	move.l	(sp)+,a0

	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

	XDEF	_new_trace

	XREF	_in_kernel,_sig_routine

	XREF	_sigbus,_sigaddr,_sigill,_sigfpe,_sigpriv,_sigtrap



_new_bus:

	move.l	#_sigbus,_sig_routine

Do_sig:

	tst.w	_in_kernel		; are we already in the kernel?

	bne.s	Kernel			; yes

	move.l	_curproc,-(sp)

	add.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

	lea	4(a4),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	

_new_addr:

	move.l	#_sigaddr,_sig_routine

	bra.s	Do_sig

_new_ill:

	move.l	#_sigill,_sig_routine

	bra.s	Do_sig

_new_divzero:

	move.l	#_sigfpe,_sig_routine

	bra.s	Do_sig

_new_priv:

	move.l	#_sigpriv,_sig_routine

	bra	Do_sig

_new_trace:

	move.l	#_sigtrap,_sig_routine

	bra	Do_sig



;

; 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

	XDEF	_new_getbpb

	XDEF	_new_mediach

	XDEF	_new_rwabs



_new_getbpb:

	move.w	4(sp),d0	; check the drive

	cmp.w	#$10,d0		; drive Q:?

	beq.s	nobpb		; yes, no BPB available

	cmp.w	#$14,d0		; drive U:?

	beq.s	nobpb		; yes, no BPB available

	cmp.w	#$15,d0		; drive V:?

	beq.s	nobpb

	cmp.w	#$17,d0		; drive X:?

	beq.s	nobpb

	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	#$10,d0		; drive Q:?

	beq.s	nochng		; yes, no change

	cmp.w	#$14,d0		; drive U:?

	beq.s	nochng		; yes, no change

	cmp.w	#$15,d0		; drive V:?

	beq.s	nochng

	cmp.w	#$17,d0		; drive X:?

	beq.s	nochng

	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	#$10,d0		; drive Q:?

	beq.s	rwdone		; yes, fake a successful I/O operation

	cmp.w	#$14,d0		; drive U:?

	beq.s	rwdone		; yes, fake it

	cmp.w	#$15,d0		; drive V:?

	beq.s	rwdone

	cmp.w	#$17,d0		; drive X:?

	beq.s	rwdone

	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



	END


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.