|
|
MiNT 0.95 pl13
| | 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.