home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
No Fragments Archive 10: Diskmags
/
nf_archive_10.iso
/
MAGS
/
PURE_B
/
PBMAG22A.MSA
/
MINT095S.ZIP
/
SRC
/
ASM
/
SYSCALL.S
< prev
Wrap
Text File
|
1987-04-22
|
9KB
|
295 lines
;
; syscall: interface for system calls. The following entry points are
; defined:
; _mint_bios: entry point for the BIOS calls (trap #13)
; _mint_xbios: entry point for XBIOS calls (trap #14)
; _mint_dos: entry point for GEMDOS calls (trap #1)
; _sig_return: user signal handlers return to this routine (see signal.c)
; it is responsible for restoring the kernel's old context
; via the Psigreturn() system call
; _lineA0: calls the line A initialize routine
; _call_aes: calls the GEM AES
; _callout: calls an external function, after first saving all registers,
; and restores the registers afterward
;
; external variables referenced:
; _bios_tab, _bios_max:
; table of entry points for BIOS routines, max # of routine
; _xbios_tab, _xbios_max:
; ditto for XBIOS
; _dos_tab, _dos_max:
; ditto for GEMDOS
; _curproc:
; pointer to current process table entry, and hence to save area for
; context (this is always the first entry in the PROC table).
; _valid_return:
; used to indicate to the kernel that a valid return from user mode
; is taking place
;
; _bconbuf, _bconbsiz, _bconbdev:
; 256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
; there are that many bytes in _bconbuf waiting to be flushed. The
; output is for device _bconbdev.
;
; The C function enter_kernel() is called on entry to the kernel, and the
; function leave_kernel() is called on exit. These functions are responsible
; for saving and restoring the various trap vectors, so that MiNT can trap
; out to TOS directly, but programs can only trap to MiNT.
;
; $Log: syscall.s,v $
; 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:24:16 AGK
; Initial revision
;
SECTION TEXT
XDEF _mint_bios,_mint_xbios
XDEF _mint_dos
XREF _build_context
XREF _restore_context
XREF _proc_clock ; controls process' allocation of CPU time
XREF _enter_kernel
XREF _leave_kernel
XREF _preempt
XREF _curproc
XREF _bios_tab,_bios_max
XREF _xbios_tab,_xbios_max
XREF _dos_tab,_dos_max
XREF _bconbuf,_bconbsiz,_bconbdev
XREF _bflush
_mint_dos:
move.l #_dos_tab,syscall_tab
move.w _dos_max,syscall_max
bra.s _syscall
_mint_xbios:
move.l #_xbios_tab,syscall_tab
move.w _xbios_max,syscall_max
bra.s _syscall
_mint_bios:
;
; Bconout() is noticeably slower under MiNT, so we do a bit of a kludge
; and special case Bconout() so that it doesn't take so long. We
; do this by buffering Bconout calls until either another kind of
; system call or a context switch happens.
;
tst.w _bconbdev ; buffering on?
bmi.s L_bios ; if bconbdev < 0, no buffering
btst #13,(sp) ; test for user/super mode
beq.s L_usr ;
lea 6(sp),a1 ; supervisor mode: args on stack
tst.w $59e ; test longframe
beq.s L_check
addq.l #2,a1 ; stack is a bit bigger
bra.s L_check
L_usr:
move.l usp,a1 ; user mode: args on user stack
L_check:
move.w (a1),d0 ; check command
cmp.w #3,d0 ; Bconout?
beq do_bconout ; yes -- take some shortcuts
; no -- fall through to the normal code
L_bios:
move.l #_bios_tab,syscall_tab
move.w _bios_max,syscall_max
_syscall:
move.l _curproc,d0
addq.l #4,d0
move.l d0,-(sp) ; push pointer to syscall context save
jsr _build_context
;
; copy parameters onto process stack. a1 was set by _build_context
;
L_copy:
move.l _curproc,a0
move.l (a0),sp ; this puts us in our private stack
move.l 24(a1),-(sp) ; a1 was set by build_context
move.l 20(a1),-(sp)
move.l 16(a1),-(sp)
move.l 12(a1),-(sp)
move.l 8(a1),-(sp)
move.l 4(a1),-(sp)
move.l (a1),-(sp)
;
jsr _enter_kernel ; set up vectors appropriately
;
; check here to see if we need to flush the Bconout() buffer
;
tst.w _bconbsiz ; characters in buffer?
beq.s L_noflush ; no: OK to proceed
;
; make sure we save syscall_tab and syscall_max
;
move.l syscall_tab,-(sp)
move.w syscall_max,-(sp)
jsr _bflush ; flush the buffer
move.w (sp)+,syscall_max
move.l (sp)+,syscall_tab
L_noflush:
;
; figure out which routine to call
;
clr.l d0
move.w (sp),d0
cmp.w #-1,d0 ; trapping with -1 means return
bne.s check_max ; the corresponding system table
move.l syscall_tab,d0
bra.s out
check_max:
cmp.w syscall_max,d0
bge.s error
add.l d0,d0
add.l d0,d0 ; multiply by 4
move.l syscall_tab,a0
add.l d0,a0
move.l (a0),a0
cmp.l #0,a0 ; null entry means invalid call
beq.s error
addq.l #2,sp ; pop function number off stack
jsr (a0) ; go do the call
out:
move.l _curproc,a0
move.l d0,4(a0) ; set d0 in the saved context
tst.w _proc_clock ; has process exceeded time slice?
bne.s nosleep ; no -- continue
move.w 68(a0),d0 ; get saved status register
btst #13,d0 ; caller in supervisor mode?
bne nosleep ; yes -- don't interrupt
sleep:
jsr _preempt ; does a sleep(READY_Q)
nosleep:
ori.w #$0700,sr ; spl7()
jsr _leave_kernel ; restore vectors
move.l _curproc,a0
pea 4(a0)
jsr _restore_context ; never returns
;
; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
; as appropriate, and letting them handle it -- that way, if the underlying
; system has functions we don't know about, they still work
;
error:
move.l syscall_tab,a0
cmp.l #_xbios_tab,a0
bne.s maybe_dos
trap #14
bra.s out
maybe_dos:
cmp.l #_dos_tab,a0
beq.s trap_1
trap #13
bra.s out
trap_1:
trap #1
bra.s out
;
; sig_return: user signal handlers return to us. At that point, the
; stack looks like this:
; (sp) (long) signal number -- was a parameter for user routine
;
XDEF _sig_return
XREF _valid_return
_sig_return:
addq.l #4,sp ; pop signal number
move.w #$11a,-(sp) ; Psigreturn() system call
move.w #1,_valid_return ; tell kernel it's us!
trap #1
; we had better not come back; if we did, something terrible
; happened, and we might as well terminate
move.w #-998,-(sp)
move.w #$4c,-(sp) ; Pterm()
trap #1
;
; bconout special code: on entry, a1 points to the stack the user
; was using. If possible, we just buffer the output until later.
;
do_bconout:
move.w 2(a1),d0 ; what device is this for?
beq L_bios ; don't buffer the printer
cmp.w _bconbdev,d0 ; same device as is buffered?
bne.s new_dev ; no -- maybe we can't do this
put_buf:
move.w 4(a1),d0 ; get the character to output
move.w _bconbsiz,d1 ; get index into buffer table
cmp.w #255,d1 ; buffer full?
beq L_bios ; yes -- flush it out
lea _bconbuf,a0
add.w d1,a0
move.b d0,(a0) ; store the character
addq.w #1,d1
move.w d1,_bconbsiz
moveq.l #-1,d0 ; return character output OK
rte
new_dev:
tst.w _bconbsiz ; characters already in buffer?
bne L_bios ; yes: we can't buffer this one
move.w d0,_bconbdev ; no: OK, we have a new device
bra.s put_buf
;
; _lineA0: MiNT calls this to get the address of the line A variables
;
XDEF _lineA0
_lineA0:
movem.l d2/a2,-(sp) ; save scratch registers
dc.w $a000 ; call the line A initialization routine
movem.l (sp)+,d2/a2
rts
;
; _call_aes: calls the GEM AES, using the control block passed as
; a parameter. Used only for doing appl_init(), to see
; if the AES is active yet
;
XDEF _call_aes
_call_aes:
move.l 4(sp),d1 ; fetch pointer to parameter block
move.w #$c8,d0 ; magic number for AES
movem.l d2/a2,-(sp) ; save scratch registers
trap #2
movem.l (sp)+,d2/a2
rts
;
; _callout: Call an external function, passing <32 bytes of arguments,
; and return the value from the function. NOTE: we must be careful
; to save all registers here!
;
XDEF _callout
_callout:
lea 8(sp),a0 ; pointer to args
move.l 4(sp),a1 ; pointer to function
movem.l d2-d7/a2-a6,-(sp) ; save registers
movem.l (a0),d0-d7 ; copy parameters
lea -32(sp),sp ; NOTE: movem.l auto-decrement
movem.l d0-d7,(sp) ; changes the order of things
move.l (a1),a0 ; get function address
jsr (a0) ; go do it
add.l #32,sp
movem.l (sp)+,d2-d7/a2-a6 ; restore reggies
rts
SECTION BSS
XDEF syscall_tab,syscall_max
syscall_tab ds.l 1 ; set to which table to use for the call
syscall_max ds.l 1 ; maximum valid number for this call
END