home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
mint
/
mint095s
/
syscall.s
< prev
next >
Wrap
Text File
|
1993-08-03
|
8KB
|
275 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: call an external function, after first making sure that all
| registers are saved
|
| 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.
|
.globl _mint_bios, _mint_xbios
.globl _mint_dos
.globl _build_context
.globl _restore_context
.globl _curproc
.globl _bios_tab, _bios_max
.globl _xbios_tab, _xbios_max
.globl _dos_tab, _dos_max
.globl _bconbuf, _bconbsiz, _bconbdev
.globl _bflush
.data
.comm syscall_tab, 4 | set to which table to use for the call
.comm syscall_max, 4 | maximum valid number for this call
.text
.even
_mint_dos:
movel #_dos_tab, syscall_tab
movew _dos_max, syscall_max
bra _syscall
_mint_xbios:
movel #_xbios_tab, syscall_tab
movew _xbios_max, syscall_max
bra _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.
|
tstw _bconbdev | buffering on?
bmi L_bios | if bconbdev < 0, no buffering
btst #13, sp@ | test for user/super mode
beq L_usr |
lea sp@(6), a1 | supervisor mode: args on stack
tstw 0x59e | test longframe
beq L_check
addql #2, a1 | stack is a bit bigger
bra L_check
L_usr:
movel usp, a1 | user mode: args on user stack
L_check:
movew a1@, d0 | check command
cmpw #3, d0 | Bconout?
beq do_bconout | yes -- take some shortcuts
| no -- fall through to the normal code
L_bios:
movel #_bios_tab, syscall_tab
movew _bios_max, syscall_max
_syscall:
movel _curproc, d0
addql #4, d0
movel d0, sp@- | push pointer to syscall context save
jsr _build_context
|
| copy parameters onto process stack. a1 was set by _build_context
|
L_copy:
movel _curproc, a0
movel a0@, a0 | fetch system call stack pointer
lea a0@(-28), sp | this puts us in our private stack
moveml a1@, d1-d7 | copy parameters from user stack
moveml d1-d7, sp@ | to ours (build_context set a1)
|
jsr _enter_kernel | set up vectors appropriately
|
| check here to see if we need to flush the Bconout() buffers
|
tstw _bconbsiz | characters in buffer?
beq L_noflush | nope: OK to proceed
|
| make sure we save syscall_tab and syscall_max
|
movel syscall_tab, sp@-
movew syscall_max, sp@-
jsr _bflush | flush the buffer
movew sp@+, syscall_max
movel sp@+, syscall_tab
L_noflush:
|
| figure out which routine to call
|
clrl d0
movew sp@, d0
cmpw #-1, d0 | trapping with -1 means return
bne check_max | the corresponding system table
movel syscall_tab, d0
bra out
check_max:
cmpw syscall_max, d0
bge error
addl d0,d0
addl d0,d0 | multiply by 4
movel syscall_tab, a0
addl d0, a0
movel a0@, a0
cmpl #0, a0 | null entry means invalid call
beq error
addql #2, sp | pop function number off stack
jsr a0@ | go do the call
out:
movel _curproc, a0
movel d0, a0@(4) | set d0 in the saved context
tstw _proc_clock | has process exceeded time slice?
bne nosleep | no -- continue
movew a0@(68), 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:
oriw #0x0700, sr | spl7()
jsr _leave_kernel | restore vectors
movel _curproc, a0
pea a0@(4)
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:
movel syscall_tab, a0
cmpl #_xbios_tab, a0
bne maybe_dos
trap #14
bra out
maybe_dos:
cmpl #_dos_tab, a0
beq trap_1
trap #13
bra out
trap_1:
trap #1
bra 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
|
.globl _sig_return
.globl _valid_return
_sig_return:
addql #4, sp | pop signal number
movew #0x11a, sp@- | Psigreturn() system call
movew #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
movew #-998, sp@-
movew #0x4c, 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:
movew a1@(2), d0 | what device is this for?
beq L_bios | don't buffer the printer
cmpw _bconbdev, d0 | same device as is buffered?
bne new_dev | no -- maybe we can't do this
put_buf:
movew a1@(4), d0 | get the character to output
movew _bconbsiz, d1 | get index into buffer table
cmpw #255, d1 | buffer full?
beq L_bios | yes -- flush it out
lea _bconbuf, a0
addw d1, a0
moveb d0, a0@ | store the character
addqw #1, d1
movew d1, _bconbsiz
moveql #-1, d0 | return character output OK
rte
new_dev:
tstw _bconbsiz | characters already in buffer?
bne L_bios | yes: we can't buffer this one
movew d0, _bconbdev | no: OK, we have a new device
bra put_buf
|
|
| _lineA0: MiNT calls this to get the address of the line A variables
|
.globl _lineA0
_lineA0:
moveml d2/a2, sp@- | save scratch registers
.word 0xa000 | call the line A initialization routine
moveml 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
|
.globl _call_aes
_call_aes:
movel sp@(4), d1 | fetch pointer to parameter block
movew #0xc8, d0 | magic number for AES
moveml d2/a2, sp@- | save scratch registers
trap #2
moveml 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!
|
.globl _callout
_callout:
lea sp@(8), a0 | pointer to args
movel sp@(4), a1 | pointer to function
moveml d2-d7/a2-a6, sp@- | save registers
moveml a0@, d0-d7 | copy parameters
lea sp@(-32), sp | NOTE: moveml auto-decrement
moveml d0-d7, sp@ | changes the order of things
movel a1@, a0 | get function address
jsr a0@ | go do it
addl #32, sp
moveml sp@+, d2-d7/a2-a6 | restore reggies
rts