home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mint104s.zoo / mint.src / syscall.spp < prev    next >
Text File  |  1993-03-08  |  13KB  |  458 lines

  1. ; Copyright 1992 Eric R. Smith
  2. ; Copyright 1992,1993 Atari Corporation
  3. ; All rights reserved.
  4.  
  5. %include "magic.i"
  6. ;
  7. ; syscall: interface for system calls. The following entry points are
  8. ;    defined:
  9. ; _mint_bios:  entry point for the BIOS calls (trap #13)
  10. ; _mint_xbios: entry point for XBIOS calls (trap #14)
  11. ; _mint_dos:   entry point for GEMDOS calls (trap #1)
  12. ; _sig_return: user signal handlers return to this routine (see signal.c)
  13. ;              it is responsible for restoring the kernel's old context
  14. ;              via the Psigreturn() system call
  15. ; _lineA0:     calls the line A initialize routine
  16. ; _call_aes:   calls the GEM AES
  17. ; _do_usrcall: calls a user supplied function (e.g. for Supexec), with
  18. ;           arguments supplied from global variables usrarg1, usrarg2, etc.
  19. ; _callout:    calls an external function, after first saving all registers,
  20. ;              and restores the registers afterward
  21. ;
  22. ; external variables referenced:
  23. ; _bios_tab, _bios_max:
  24. ;    table of entry points for BIOS routines, max # of routine
  25. ; _xbios_tab, _xbios_max:
  26. ;    ditto for XBIOS
  27. ; _dos_tab, _dos_max:
  28. ;    ditto for GEMDOS
  29. ; _curproc:
  30. ;    pointer to current process table entry, and hence to save area for
  31. ;    context (this is always the first entry in the PROC table).
  32. ; _valid_return:
  33. ;    used to indicate to the kernel that a valid return from user mode
  34. ;    is taking place
  35. ;
  36. ; _bconbuf, _bconbsiz, _bconbdev:
  37. ;    256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
  38. ;    there are that many bytes in _bconbuf waiting to be flushed. The
  39. ;    output is for device _bconbdev.
  40. ;
  41. ; The C function enter_kernel() is called on entry to the kernel, and the
  42. ; function leave_kernel() is called on exit. These functions are responsible
  43. ; for saving and restoring the various trap vectors, so that MiNT can trap
  44. ; out to TOS directly, but programs can only trap to MiNT.
  45. ;
  46. ; we also call certain BIOS functions directly if these are known not to
  47. ; require saving/restoring of context
  48. ;
  49.     TEXT
  50.     
  51.     XDEF    _mint_bios,_mint_xbios
  52.     XDEF    _mint_dos
  53.     XREF    _build_context
  54.     XREF    _restore_context
  55.     XREF    _proc_clock        ; controls process' allocation of CPU time
  56.     XREF    _enter_kernel
  57.     XREF    _leave_kernel
  58.     XREF    _preempt
  59.  
  60.     XREF    _curproc
  61.     XREF    _bios_tab,_bios_max
  62.     XREF    _xbios_tab,_xbios_max,_old_xbios
  63.     XREF    _dos_tab,_dos_max
  64.  
  65.     XREF    _bconbuf,_bconbsiz,_bconbdev
  66.     XREF    _bflush
  67.  
  68.     XREF    _ubconstat,_do_bconin,_ubcostat,_kbshift
  69.     
  70. _mint_dos:
  71.     clr.w    -(sp)            ; no frame format needed
  72.     move.l    _curproc,d0
  73.     addq.l    #4,d0
  74.     move.l    d0,-(sp)        ; push pointer to syscall context save
  75.     jsr    _build_context
  76.     move.l    #_dos_tab,a5        ; set syscall_tab
  77.     move.w    _dos_max,d5        ; set syscall_max
  78. ;
  79. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  80. ;
  81.  
  82.     move.l    _curproc,a0
  83.     move.l    (a0),sp            ; this puts us in our private stack
  84.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  85.     move.l    20(a1),-(sp)
  86.     move.l    16(a1),-(sp)
  87.     move.l    12(a1),-(sp)
  88.     move.l    8(a1),-(sp)
  89.     move.l    4(a1),-(sp)
  90.     move.l    (a1),-(sp)
  91.     jsr    _enter_kernel        ; set up vectors appropriately
  92.     bra    _syscall
  93.  
  94. _mint_xbios:
  95. ;
  96. ; Kludge for Setscreen: under Falcon TOS, this
  97. ; calls a GEMDOS function (Srealloc) and so
  98. ; we must *not* change any of the vectors!!
  99.  
  100.     btst    #13,(sp)        ; test for user/super mode
  101.     beq    LX_usr
  102. %ifdef ONLY030
  103.     lea    8(sp),a1
  104. %else
  105.     lea    6(sp),a1        ; supervisor mode: args on stack
  106.     tst.w    ($59e).w        ; test longframe
  107.     beq.s    LX_check
  108.     addq.l    #2,a1            ; stack is a bit bigger
  109. %endif
  110.     bra.s    LX_check
  111. LX_usr:
  112.     move.l    usp,a1            ; user mode: args on user stack
  113. LX_check:
  114.     move.w    (a1),d0            ; check command
  115.     cmp.w    #5,d0            ; Setscreen?
  116.     beq    LX_screen        ; no -- fall through
  117.  
  118.     clr.w    -(sp)            ; no frame format needed
  119.     move.l    _curproc,d0
  120.     addq.l    #4,d0
  121.     move.l    d0,-(sp)        ; push pointer to syscall context save
  122.     jsr    _build_context
  123.     move.l    #_xbios_tab,a5        ; set syscall_tab
  124.     move.w    _xbios_max,d5        ; set syscall_max
  125. ;
  126. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  127. ;
  128.  
  129.     move.l    _curproc,a0
  130.     move.l    (a0),sp            ; this puts us in our private stack
  131.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  132.     move.l    20(a1),-(sp)
  133.     move.l    16(a1),-(sp)
  134.     move.l    12(a1),-(sp)
  135.     move.l    8(a1),-(sp)
  136.     move.l    4(a1),-(sp)
  137.     move.l    (a1),-(sp)
  138.     jsr    _enter_kernel        ; set up vectors appropriately
  139.     bra    _syscall
  140. ;
  141. ; For setscreen, jump directly to the ROM vector --
  142. ; this avoids all hazards (like changing the vectors)
  143.  
  144. LX_screen:
  145.     move.l    _old_xbios+8,a0
  146.     jmp    (a0)
  147.  
  148.  
  149. _mint_bios:
  150. ;
  151. ; Entering the kernel can be very expensive; so, we take a short-cut
  152. ; if possible -- we try some BIOS functions out, and if they
  153. ; succeed without blocking then we're done; otherwise, we go
  154. ; through the long procedure for entering the kernel
  155. ;
  156. ; These shortcuts aren't done when we're called in supervisor mode,
  157. ; because TOS uses very tiny stacks (smaller than we want); the
  158. ; shortcuts operate on the user-supplied ssp, whereas the "full"
  159. ; BIOS code works on our (private) system stack
  160. ;
  161. ; the shortcuts are also turned off if BIOSBUF=n
  162. ;
  163.     jsr    _enter_kernel        ; set up BIOS vectors
  164.     tst.w    _bconbdev        ; is BIOS buffering on?
  165.     bmi    L_bios            ; no; skip all this
  166.  
  167.     btst    #5,(sp)            ; test for user/super mode
  168.     bne.s    L_bios            ; if super, goto L_bios
  169.     tst.w    _proc_clock        ; are we about to be preempted?
  170.     beq    L_bios
  171.  
  172.     move.l    usp,a1            ; user mode: args on user stack
  173. L_ubios:
  174.     move.w    (a1),d0            ; get command
  175.     cmp.w    #3,d0            ; Bconout?
  176.     beq    do_bconout        ; yes -- go do it
  177. ;
  178. ; most of the remaining functions require BIOS vectors to be properly
  179. ; set up
  180.     tst.w    _bconbsiz        ; is BIOS output waiting?
  181.     bne.s    L_bios            ; yes -- do regular code
  182.  
  183. ; test for various BIOS functions
  184.     cmp.w    #1,d0            ; Bconstat?
  185.     bne.s    L_00
  186.     move.w    2(a1),-(sp)        ; push arg
  187.     jsr    _ubconstat
  188. L_1out:
  189.     addq.l    #2,sp
  190. L_0out:
  191.     move.l    d0,-(sp)        ; save d0
  192.     ori.w    #$0700,sr        ; spl7()
  193.     jsr    _leave_kernel
  194.     move.l    (sp)+,d0        ; retrieve value to be returned
  195.     rte                ; return to user
  196. L_00:
  197.     cmp.w    #2,d0            ; Bconin?
  198.     bne.s    L_01
  199.     move.w    2(a1),-(sp)        ; yes; push argument
  200.     jsr    _do_bconin
  201.     addq.l    #2,sp
  202.     cmp.w    #$dead,d0        ; would Bconin block?
  203.     bne.s    L_0out            ; no -- we're done
  204.     bra.s    L_bios            ; yes -- do the long stuff
  205. L_01:
  206.     cmp.w    #8,d0            ; Bcostat?
  207.     bne.s    L_02
  208.     move.w    2(a1),-(sp)        ; push device
  209.     jsr    _ubcostat        ; get status
  210.     bra.s    L_1out
  211. L_02:
  212.     cmp.w    #11,d0            ; Kbshift?
  213.     bne.s    L_bios
  214.     move.w    2(a1),-(sp)        ; push arg
  215.     jsr    _kbshift
  216.     bra.s    L_1out
  217.  
  218. L_bios:
  219.     clr.w    -(sp)            ; no frame format needed
  220.     move.l    _curproc,d0
  221.     addq.l    #4,d0
  222.     move.l    d0,-(sp)        ; push pointer to syscall context save
  223.     jsr    _build_context
  224.     move.l    #_bios_tab,a5        ; set syscall_tab
  225.     move.w    _bios_max,d5        ; set syscall_max
  226. ;
  227. ; copy parameters onto process stack. a0 and a1 were set by _build_context
  228. ;
  229.  
  230.     move.l    _curproc,a0
  231.     move.l    (a0),sp            ; this puts us in our private stack
  232.     move.l    24(a1),-(sp)        ; a1 was set by build_context
  233.     move.l    20(a1),-(sp)
  234.     move.l    16(a1),-(sp)
  235.     move.l    12(a1),-(sp)
  236.     move.l    8(a1),-(sp)
  237.     move.l    4(a1),-(sp)
  238.     move.l    (a1),-(sp)
  239.  
  240. _syscall:
  241. ;
  242. ; check here to see if we need to flush the Bconout() buffer
  243. ;
  244.     tst.w    _bconbsiz        ; characters in buffer?
  245.     beq.s    L_noflush        ; no: OK to proceed
  246. ;
  247. ; watch out, this could cause a context switch
  248. ;
  249.     jsr    _bflush            ; flush the buffer
  250.  
  251. L_noflush:
  252. ;
  253. ; figure out which routine to call
  254. ;
  255.     move.w    (sp),d0
  256.     cmp.w    #-1,d0            ; trapping with -1 means return
  257.     bne.s    check_max        ; the corresponding system table
  258.     move.l    a5,d0
  259.     bra.s    out
  260. check_max:
  261.     cmp.w    d5,d0
  262.     bge.s    error
  263.     add.w    d0,d0
  264.     add.w    d0,d0            ; multiply by 4
  265.     move.l    0(a5,d0.w),d0        ; d0 = syscall_tab[d0]
  266.     beq.s    error            ; null entry means invalid call
  267.     addq.l    #2,sp            ; pop function number off stack
  268.     move.l    d0,a0
  269.     jsr    (a0)            ; go do the call
  270. out:
  271.     move.l    _curproc,a0
  272.     move.l    d0,P_SYSCTXT+C_D0(a0)    ; set d0 in the saved context
  273.     move.w    P_SYSCTXT+C_SR(a0),d0    ; get saved status register
  274.     
  275.     tst.l    P_PTRACER(a0)        ; check curproc->ptracer, if not set
  276.     beq.s    notrace            ; then no pending trace; this ensures
  277.     move.w    d0,d1            ; we work with non-MiNT debuggers
  278.     and.w    #$c000,d1        ; are either of the trace bits set
  279.     sne    P_SYSCTXT+C_PTRACE(a0)    ; mark as trace pending/not
  280. notrace:
  281.     tst.w    _proc_clock        ; has process exceeded time slice?
  282.     bne.s    nosleep            ; no -- continue
  283.     btst    #13,d0            ; caller in supervisor mode?
  284.     bne.s    nosleep            ; yes -- don't interrupt
  285.     tst.w    ($43e).w        ; test floppy disk lock variable
  286.     bne.s    nosleep            ; if locked, can't switch
  287. sleep:
  288.     jsr    _preempt        ; does a sleep(READY_Q)
  289. nosleep:
  290.     ori.w    #$0700,sr        ; spl7()
  291.     jsr    _leave_kernel        ; restore vectors
  292.     move.l    _curproc,a0
  293.     pea    4(a0)
  294.     jsr    _restore_context    ; never returns
  295.  
  296. ;
  297. ; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
  298. ; as appropriate, and letting them handle it -- that way, if the underlying
  299. ; system has functions we don't know about, they still work
  300. ; to figure out which trap we have to call, we use the system call
  301. ; table placed in a5 earlier
  302.  
  303. error:
  304.     cmp.l    #_xbios_tab,a5
  305.     bne.s    maybe_bios
  306.     trap    #14
  307.     bra.s    out
  308. maybe_bios:
  309.     cmp.l    #_dos_tab,a5
  310.     beq.s    trap_1
  311.     trap    #13
  312.     bra.s    out
  313. trap_1:
  314.     trap    #1
  315.     bra.s    out
  316.  
  317. ;
  318. ; sig_return: user signal handlers return to us. At that point, the
  319. ; stack looks like this:
  320. ;  -4(sp)      (long) sfmt
  321. ;    (sp)      (long) signal number -- was a parameter for user routine
  322. ;
  323.     XDEF    _sig_return
  324.     XREF    _valid_return
  325. _sig_return:
  326.     add.l    #8,sp            ; pop signal number and sfmt
  327.     move.w    #$11a,-(sp)        ; Psigreturn() system call
  328.     move.w    #1,_valid_return    ; tell kernel it's us!
  329.     trap    #1
  330. ; we had better not come back; if we did, something terrible
  331. ; happened, and we might as well terminate
  332.     move.w    #-998,-(sp)
  333.     move.w    #$4c,-(sp)        ; Pterm()
  334.     trap    #1
  335. ;
  336. ; bconout special code: on entry, a1 points to the stack the user
  337. ; was using. If possible, we just buffer the output until later.
  338. ;
  339.  
  340. do_bconout:
  341.     tst.w    _bconbdev        ; is BIOS buffering on?
  342.     bmi    L_bios            ; no buffering -- skip this code
  343.     move.w    2(a1),d0        ; what device is this for?
  344.     beq    L_bios            ; don't buffer the printer
  345.     cmp.w    _bconbdev,d0        ; same device as is buffered?
  346.     bne.s    new_dev            ; no -- maybe we can't do this
  347. put_buf:
  348.     move.w    4(a1),d0        ; get the character to output
  349.     move.w    _bconbsiz,d1        ; get index into buffer table
  350.     cmp.w    #255,d1            ; buffer full?
  351.     beq    L_bios            ; yes -- flush it out
  352.     lea    _bconbuf,a0
  353.     add.w    d1,a0
  354.     move.b    d0,(a0)            ; store the character
  355.     addq.w    #1,d1
  356.     move.w    d1,_bconbsiz
  357.     jsr    _leave_kernel        ; restore vectors
  358.     moveq.l    #-1,d0            ; return character output OK
  359.     rte
  360.  
  361. new_dev:
  362.     tst.w    _bconbsiz        ; characters already in buffer?
  363.     bne    L_bios            ; yes: we can't buffer this one
  364.     move.w    d0,_bconbdev        ; no: OK, we have a new device
  365.     bra.s    put_buf
  366.  
  367. ;
  368. ; _lineA0: MiNT calls this to get the address of the line A variables
  369. ;
  370.     XDEF    _lineA0
  371. _lineA0:
  372.     movem.l    d2/a2,-(sp)    ; save scratch registers
  373.     dc.w    $a000        ; call the line A initialization routine
  374.     movem.l    (sp)+,d2/a2
  375.     rts
  376.  
  377. ;
  378. ; _call_aes: calls the GEM AES, using the control block passed as
  379. ;            a parameter. Used only for doing appl_init(), to see
  380. ;         if the AES is active yet
  381. ;
  382.     XDEF    _call_aes
  383. _call_aes:
  384.     move.l    4(sp),d1    ; fetch pointer to parameter block
  385.     move.w    #$c8,d0        ; magic number for AES
  386.     movem.l    d2/a2,-(sp)    ; save scratch registers
  387.     trap    #2
  388.     movem.l    (sp)+,d2/a2
  389.     rts
  390.  
  391. ;
  392. ; _callout: Call an external function, passing <32 bytes of arguments,
  393. ; and return the value from the function. NOTE: we must be careful
  394. ; to save all registers here!
  395. ;
  396.     XDEF    _callout
  397.     XDEF    _callout1
  398.     XDEF    _callout2
  399. ;
  400. ; _callout is the general purpose one
  401. ;
  402. _callout:
  403.     lea    8(sp),a0        ; pointer to args
  404.     move.l    4(sp),a1        ; pointer to pointer to function
  405.     movem.l    d2-d7/a2-a6,-(sp)    ; save registers
  406.     movem.l    (a0),d0-d7        ; copy parameters
  407.     lea    -32(sp),sp        ; NOTE: movem.l auto-decrement
  408.     movem.l    d0-d7,(sp)        ;    changes the order of things
  409.     jsr    (a1)            ; go do it
  410.     lea    32(sp),sp
  411.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  412.     rts
  413. ;
  414. ; _callout2 and _callout1 are for functions with just 1 or
  415. ; 2 16 bit parameters. We cheat and use the same code for
  416. ; both, since passing 32 bits isn't much more expensive than
  417. ; passing 16 bits (and since the called function will just
  418. ; ignore any extra arg)
  419. ;
  420.  
  421. _callout1:
  422. _callout2:
  423.     movem.l    4(sp),a0/a1        ; get function ptr & args
  424.     movem.l    d2-d7/a2-a6,-(sp)    ; save reggies
  425.     move.l    a1,-(sp)        ; push args
  426.     jsr    (a0)            ; do function
  427.     addq.l    #4,sp
  428.     movem.l    (sp)+,d2-d7/a2-a6    ; restore reggies
  429.     rts
  430.  
  431. ;
  432. ; do_usrcall: call the user supplied function (*usrcall)(), with
  433. ; arguments given in the longwords usrarg1..usrarg5. Return value
  434. ; is placed in usrret. This function is used by the Supexec code
  435. ; in xbios.c.
  436.  
  437.     XDEF    _do_usrcall
  438.     XREF    _usrret
  439.     XREF    _usrcall
  440.     XREF    _usrarg1,_usrarg2,_usrarg3,_usrarg4,_usrarg5
  441.  
  442. _do_usrcall:
  443.     move.l    _usrarg5,-(sp)
  444.     move.l    _usrarg4,-(sp)
  445.     move.l    _usrarg3,-(sp)
  446.     move.l    _usrarg2,-(sp)
  447.     move.l    _usrarg1,-(sp)
  448.     move.l    _usrcall,-(sp)    ; the user expects to see this on the stack
  449.     pea    ucret        ; so rts puts us back here
  450.     move.l    _usrcall,-(sp)    ; this copy is for us to use
  451.     rts            ; to jump to (we don't want to use registers)
  452. ucret:
  453.     add.w    #24,sp        ; fix up stack
  454.     move.l    d0,_usrret    ; save returned value
  455.     rts            ; back to caller
  456.  
  457.     END
  458.