|
|
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: 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.1.1.1 2018/04/24 17:55:36 root ; MiNT 0.95 pl13 ; ; 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.