|
| interrupt wrapping routines; these should just save registers and call
| the appropriate C handlers, unless speed is a major problem
|

|
| first, utilities for setting processor status level
|
	.globl	_spl7, _spl
_spl7:
	movew	sr, d0
	oriw	#0x0700, sr
	rts
_spl:
	movew	sp@(4), d0
	movew	d0, sr
	rts

	.globl	_mint_5ms
	.globl	_mint_timer
	.globl	_mint_vbl
	.globl	_timeout	| C time routine
	.globl	_old_timer	| old GEMDOS time vector
	.globl	_old_vbl	| old GEMDOS vbl vector
	.globl	_old_5ms
	.globl	_build_context
	.globl	_restore_context
	.globl	_proc_clock		| controls process' allocation of CPU time
	.globl	_curproc
	.globl	_in_kernel

| AKP: this code is hit once every 5ms; it updates the time fields of curproc.
_mint_5ms:
	movel	a0,sp@-
	movel	_curproc,a0
	addw	#0x364,a0		| $364 is offset to curproc->systime;
	tstw	_in_kernel
	bne	L_5a			| usrtime is the branch-not-taken case
	addql	#4,a0
L_5a:	addql	#5,a0@
	movel	sp@+,a0
	movel	_old_5ms+8,sp@-
	rts

_mint_timer:
	moveml	d0-d2/a0-a2, sp@-	| save C registers
	jsr	_timeout
	moveml	sp@+, d0-d2/a0-a2
	movel	_old_timer+8, sp@-	| jump to GEMDOS time vector
	rts

_mint_vbl:
	tstw	0x59e			| test longframe (AKP)
	beq	L_short1
	clrw	sp@-			| yes, long frames: push a frame word
L_short1:
	pea	L_comeback		| push fake PC
	movew	sr, sp@-		| push status register
	movel	_old_vbl+8, sp@-	| go service the interrupt
	rts

L_comeback:
	tstw	_proc_clock		| has time expired yet?
	beq	L_expired		| yes -- maybe go switch processes
L_out:
	rte				| no -- just return

L_expired:
	btst	#13, sp@		| user mode?
	bne	L_out			| no -- switching is not possible
L_switch:
	movel	_curproc, sp@-
	addl	#4, sp@			| to get &curproc->ctxt[SYSCALL]
	jsr	_build_context		| build context
	movel	_curproc, a0
	movel	a0@, sp			| use curproc->sysstack
	jsr	_enter_kernel		| enter kernel
	jsr	_preempt		| yield processor
	oriw	#0x0700, sr		| spl7()
	jsr	_leave_kernel		| restore vectors
	movel	_curproc, a0
	pea	a0@(4)
	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
|
	.globl	_reset
	.globl	_tmpstack		| see main.c

_reset:
	movew	#0x2700, sr		| avoid interruption here
	movel	sp, _tmpstack		| save A7
	lea	_tmpstack, sp		| set up temporary stack
	lea	sp@(256), sp
	moveml	d0-d2/a0-a2, sp@-	| save C registers
	jsr	_restr_intr		| restore interrupts
	moveml	sp@+, d0-d2/a0-a2	| restore registers
	movel	_tmpstack, sp
	jmp	a6@			| reset again

|
| routine for doing a reboot
|
	.globl	_reboot
_reboot:
	movew	#0x2700, sr		| avoid interrupts
	movel	0x00, sp		| get sp after reboot
	movel	0x04, a6		| get new reboot address
	jmp	_reset

|
| routine for mouse packet handling
|
	.globl	_newmvec
_newmvec:
	movel	a0, sp@-
	jsr	_mouse_handler
	movel	sp@+, a0
	rts

|
| new ikbd keyboard interrupt vector
| kintr is a global variable that should be non-zero if a keyboard
| event occured
|
	.globl	_new_ikbd
_new_ikbd:
	movew	#1, _kintr
	movel	_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)
|
	.globl	_new_bus, _new_addr, _new_ill, _new_divzero, _new_priv
	.globl	_new_trace
	.globl	_in_kernel, _sig_routine
_new_bus:
	movel	#_sigbus, _sig_routine
Do_sig:
	tstw	_in_kernel		| are we already in the kernel?
	bne	Kernel			| yes
	movel	_curproc, sp@-
	addl	#4, sp@			| push offset of save area
	jsr	_build_context
	movel	_curproc, a4
	movel	a4@, sp			| put us in the system stack
	jsr	_enter_kernel		| set up kernel vectors
	movel	_sig_routine, a1	| get signal handling routine
	jsr	a1@			| go do it
	oriw	#0x0700, sr		| spl7()
	jsr	_leave_kernel		| leave kernel
	lea	a4@(4), a4		| get context save area address
	movel	a4, sp@-		| push it
	jsr	_restore_context	| restore the context
|
| here's what we do if we already were in the kernel
|
Kernel:
	moveml	d0-d2/a0-a2, sp@-	| save reggies
	movel	_sig_routine, a1	| get handler
	jsr	a1@			| go do it
	moveml	sp@+, d0-d2/a0-a2
	rte	
_new_addr:
	movel	#_sigaddr, _sig_routine
	bra	Do_sig
_new_ill:
	movel	#_sigill, _sig_routine
	bra	Do_sig
_new_divzero:
	movel	#_sigfpe, _sig_routine
	bra	Do_sig
_new_priv:
	movel	#_sigpriv, _sig_routine
	bra	Do_sig
_new_trace:
	movel	#_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
|
	.globl	_old_getbpb	| old Getbpb vector
	.globl	_old_mediach	| old Mediach vector
	.globl	_old_rwabs	| old Rwabs vector

	.globl	_new_getbpb
_new_getbpb:
	movew	sp@(4), d0	| check the drive
	cmpw	#0x10, d0	| drive Q:?
	beq	nobpb		| yes, no BPB available
	cmpw	#0x14, d0	| drive U:?
	beq	nobpb		| yes, no BPB available
	cmpw	#0x15, d0	| drive V:?
	beq	nobpb
	cmpw	#0x17, d0	| drive X:?
	beq	nobpb
	movel	_old_getbpb+8, a0	| not our drive
	jmp	a0@		| call the old vector for it
nobpb:
	moveql	#0, d0		| 0 means "no BPB read"
	rts

	.globl	_new_mediach
_new_mediach:
	movew	sp@(4), d0	| check the drive
	cmpw	#0x10, d0	| drive Q:?
	beq	nochng		| yes, no change
	cmpw	#0x14, d0	| drive U:?
	beq	nochng		| yes, no change
	cmpw	#0x15, d0	| drive V:?
	beq	nochng
	cmpw	#0x17, d0	| drive X:?
	beq	nochng
	movel	_old_mediach+8, a0	| not our drive
	jmp	a0@		| call the old vector for it
nochng:
	moveql	#0, d0		| 0 means "definitely no change"
	rts

	.globl	_new_rwabs
_new_rwabs:
	movew	sp@(0xe), d0	| check the drive
	cmpw	#0x10, d0	| drive Q:?
	beq	rwdone		| yes, fake a successful I/O operation
	cmpw	#0x14, d0	| drive U:?
	beq	rwdone		| yes, fake it
	cmpw	#0x15, d0	| drive V:?
	beq	rwdone
	cmpw	#0x17, d0	| drive X:?
	beq	rwdone
	movel	_old_rwabs+8, a0 | not our drive
	jmp	a0@		| call the old vector for it
rwdone:
	moveql	#0, d0		| 0 means "successful operation"
	rts
