|
|
1.1.1.2 root 1: ; Copyright 1992 Eric R. Smith
2:
3: ; Copyright 1992,1993 Atari Corporation
4:
5: ; All rights reserved.
6:
7:
8:
1.1 root 9: %include "magic.i"
10:
11: ;
12:
13: ; syscall: interface for system calls. The following entry points are
14:
15: ; defined:
16:
17: ; _mint_bios: entry point for the BIOS calls (trap #13)
18:
19: ; _mint_xbios: entry point for XBIOS calls (trap #14)
20:
21: ; _mint_dos: entry point for GEMDOS calls (trap #1)
22:
23: ; _sig_return: user signal handlers return to this routine (see signal.c)
24:
25: ; it is responsible for restoring the kernel's old context
26:
27: ; via the Psigreturn() system call
28:
29: ; _lineA0: calls the line A initialize routine
30:
31: ; _call_aes: calls the GEM AES
32:
1.1.1.4 ! root 33: ; _call_dosound: calls the XBIOS Dosound() function
! 34:
1.1.1.2 root 35: ; _do_usrcall: calls a user supplied function (e.g. for Supexec), with
36:
37: ; arguments supplied from global variables usrarg1, usrarg2, etc.
38:
1.1 root 39: ; _callout: calls an external function, after first saving all registers,
40:
41: ; and restores the registers afterward
42:
43: ;
44:
45: ; external variables referenced:
46:
47: ; _bios_tab, _bios_max:
48:
49: ; table of entry points for BIOS routines, max # of routine
50:
51: ; _xbios_tab, _xbios_max:
52:
53: ; ditto for XBIOS
54:
55: ; _dos_tab, _dos_max:
56:
57: ; ditto for GEMDOS
58:
59: ; _curproc:
60:
61: ; pointer to current process table entry, and hence to save area for
62:
63: ; context (this is always the first entry in the PROC table).
64:
65: ; _valid_return:
66:
67: ; used to indicate to the kernel that a valid return from user mode
68:
69: ; is taking place
70:
71: ;
72:
73: ; _bconbuf, _bconbsiz, _bconbdev:
74:
75: ; 256 byte buffer for Bconout() output. If _bconbsiz is non-zero,
76:
77: ; there are that many bytes in _bconbuf waiting to be flushed. The
78:
79: ; output is for device _bconbdev.
80:
81: ;
82:
83: ; The C function enter_kernel() is called on entry to the kernel, and the
84:
85: ; function leave_kernel() is called on exit. These functions are responsible
86:
87: ; for saving and restoring the various trap vectors, so that MiNT can trap
88:
89: ; out to TOS directly, but programs can only trap to MiNT.
90:
91: ;
92:
93: ; we also call certain BIOS functions directly if these are known not to
94:
95: ; require saving/restoring of context
96:
97: ;
98:
99: TEXT
100:
101:
102:
103: XDEF _mint_bios,_mint_xbios
104:
105: XDEF _mint_dos
106:
107: XREF _build_context
108:
109: XREF _restore_context
110:
111: XREF _proc_clock ; controls process' allocation of CPU time
112:
113: XREF _enter_kernel
114:
115: XREF _leave_kernel
116:
117: XREF _preempt
118:
119:
120:
121: XREF _curproc
122:
123: XREF _bios_tab,_bios_max
124:
1.1.1.2 root 125: XREF _xbios_tab,_xbios_max,_old_xbios
1.1 root 126:
127: XREF _dos_tab,_dos_max
128:
129:
130:
131: XREF _bconbuf,_bconbsiz,_bconbdev
132:
133: XREF _bflush
134:
135:
136:
137: XREF _ubconstat,_do_bconin,_ubcostat,_kbshift
138:
139:
140:
141: _mint_dos:
142:
143: clr.w -(sp) ; no frame format needed
144:
1.1.1.3 root 145: ; NOTE: FOR NOW, WE PRESERVE A0 ACROSS GEMDOS CALLS. THIS WILL CHANGE
146:
147: ; SOMEDAY, DON'T RELY ON IT!!!
148:
149: move.l _curproc,d0 ; note: preserve all regs but d0
150:
151: addq.l #4,d0 ; for compatibility
152:
1.1 root 153:
154:
155: move.l d0,-(sp) ; push pointer to syscall context save
156:
157: jsr _build_context
158:
1.1.1.3 root 159: lea _dos_tab,a5 ; set syscall_tab
1.1 root 160:
161: move.w _dos_max,d5 ; set syscall_max
162:
163: ;
164:
165: ; copy parameters onto process stack. a0 and a1 were set by _build_context
166:
167: ;
168:
169:
170:
171: move.l _curproc,a0
172:
173: move.l (a0),sp ; this puts us in our private stack
174:
175: move.l 24(a1),-(sp) ; a1 was set by build_context
176:
177: move.l 20(a1),-(sp)
178:
179: move.l 16(a1),-(sp)
180:
181: move.l 12(a1),-(sp)
182:
183: move.l 8(a1),-(sp)
184:
185: move.l 4(a1),-(sp)
186:
187: move.l (a1),-(sp)
188:
1.1.1.4 ! root 189: move.w #1,-(sp) ; flag for in GEMDOS
! 190:
1.1 root 191: jsr _enter_kernel ; set up vectors appropriately
192:
1.1.1.4 ! root 193: addq.w #2,sp
! 194:
1.1 root 195: bra _syscall
196:
197:
198:
199: _mint_xbios:
200:
1.1.1.2 root 201: ;
202:
203: ; Kludge for Setscreen: under Falcon TOS, this
204:
205: ; calls a GEMDOS function (Srealloc) and so
206:
207: ; we must *not* change any of the vectors!!
208:
209:
210:
1.1.1.3 root 211: btst #5,(sp) ; test for user/super mode
1.1.1.2 root 212:
1.1.1.3 root 213: beq.s LX_usr
1.1.1.2 root 214:
215: %ifdef ONLY030
216:
217: lea 8(sp),a1
218:
219: %else
220:
221: lea 6(sp),a1 ; supervisor mode: args on stack
222:
223: tst.w ($59e).w ; test longframe
224:
225: beq.s LX_check
226:
1.1.1.3 root 227: addq.w #2,a1 ; stack is a bit bigger
1.1.1.2 root 228:
229: %endif
230:
231: bra.s LX_check
232:
233: LX_usr:
234:
235: move.l usp,a1 ; user mode: args on user stack
236:
237: LX_check:
238:
1.1.1.3 root 239: cmp.w #5,(a1) ; check for Setscreen command
1.1.1.2 root 240:
1.1.1.3 root 241: beq.s LX_screen ; no -- fall through
1.1.1.2 root 242:
243:
244:
1.1 root 245: clr.w -(sp) ; no frame format needed
246:
1.1.1.3 root 247: move.l _curproc,a0
1.1 root 248:
1.1.1.3 root 249: pea 4(a0) ; push pointer to syscall context save
1.1 root 250:
251: jsr _build_context
252:
1.1.1.3 root 253: lea _xbios_tab,a5 ; set syscall_tab
1.1 root 254:
255: move.w _xbios_max,d5 ; set syscall_max
256:
257: ;
258:
259: ; copy parameters onto process stack. a0 and a1 were set by _build_context
260:
261: ;
262:
263:
264:
265: move.l _curproc,a0
266:
267: move.l (a0),sp ; this puts us in our private stack
268:
269: move.l 24(a1),-(sp) ; a1 was set by build_context
270:
271: move.l 20(a1),-(sp)
272:
273: move.l 16(a1),-(sp)
274:
275: move.l 12(a1),-(sp)
276:
277: move.l 8(a1),-(sp)
278:
279: move.l 4(a1),-(sp)
280:
281: move.l (a1),-(sp)
282:
1.1.1.4 ! root 283: move.w #0,-(sp) ; flag: NOT GEMDOS
! 284:
1.1 root 285: jsr _enter_kernel ; set up vectors appropriately
286:
1.1.1.4 ! root 287: addq.w #2,sp
! 288:
1.1 root 289: bra _syscall
290:
1.1.1.2 root 291: ;
292:
293: ; For setscreen, jump directly to the ROM vector --
294:
295: ; this avoids all hazards (like changing the vectors)
296:
297:
298:
299: LX_screen:
300:
301: move.l _old_xbios+8,a0
302:
303: jmp (a0)
304:
305:
306:
1.1 root 307:
308:
309: _mint_bios:
310:
311: ;
312:
313: ; Entering the kernel can be very expensive; so, we take a short-cut
314:
315: ; if possible -- we try some BIOS functions out, and if they
316:
317: ; succeed without blocking then we're done; otherwise, we go
318:
319: ; through the long procedure for entering the kernel
320:
321: ;
322:
323: ; These shortcuts aren't done when we're called in supervisor mode,
324:
325: ; because TOS uses very tiny stacks (smaller than we want); the
326:
327: ; shortcuts operate on the user-supplied ssp, whereas the "full"
328:
329: ; BIOS code works on our (private) system stack
330:
331: ;
332:
1.1.1.2 root 333: ; the shortcuts are also turned off if BIOSBUF=n
334:
335: ;
336:
1.1.1.4 ! root 337: move.w #0,-(sp) ; flag: NOT a GEMDOS call
! 338:
1.1 root 339: jsr _enter_kernel ; set up BIOS vectors
340:
1.1.1.4 ! root 341: addq.w #2,sp
! 342:
1.1.1.2 root 343: tst.w _bconbdev ; is BIOS buffering on?
344:
345: bmi L_bios ; no; skip all this
346:
347:
348:
1.1 root 349: btst #5,(sp) ; test for user/super mode
350:
351: bne.s L_bios ; if super, goto L_bios
352:
353: tst.w _proc_clock ; are we about to be preempted?
354:
1.1.1.3 root 355: beq.s L_bios
1.1 root 356:
357:
358:
359: move.l usp,a1 ; user mode: args on user stack
360:
361: L_ubios:
362:
363: move.w (a1),d0 ; get command
364:
365: cmp.w #3,d0 ; Bconout?
366:
367: beq do_bconout ; yes -- go do it
368:
369: ;
370:
371: ; most of the remaining functions require BIOS vectors to be properly
372:
373: ; set up
374:
375: tst.w _bconbsiz ; is BIOS output waiting?
376:
377: bne.s L_bios ; yes -- do regular code
378:
379:
380:
381: ; test for various BIOS functions
382:
383: cmp.w #1,d0 ; Bconstat?
384:
385: bne.s L_00
386:
387: move.w 2(a1),-(sp) ; push arg
388:
389: jsr _ubconstat
390:
391: L_1out:
392:
393: addq.l #2,sp
394:
395: L_0out:
396:
397: move.l d0,-(sp) ; save d0
398:
399: ori.w #$0700,sr ; spl7()
400:
401: jsr _leave_kernel
402:
403: move.l (sp)+,d0 ; retrieve value to be returned
404:
405: rte ; return to user
406:
407: L_00:
408:
409: cmp.w #2,d0 ; Bconin?
410:
411: bne.s L_01
412:
413: move.w 2(a1),-(sp) ; yes; push argument
414:
415: jsr _do_bconin
416:
1.1.1.3 root 417: addq.w #2,sp
1.1 root 418:
419: cmp.w #$dead,d0 ; would Bconin block?
420:
421: bne.s L_0out ; no -- we're done
422:
423: bra.s L_bios ; yes -- do the long stuff
424:
425: L_01:
426:
427: cmp.w #8,d0 ; Bcostat?
428:
429: bne.s L_02
430:
431: move.w 2(a1),-(sp) ; push device
432:
433: jsr _ubcostat ; get status
434:
435: bra.s L_1out
436:
437: L_02:
438:
439: cmp.w #11,d0 ; Kbshift?
440:
441: bne.s L_bios
442:
443: move.w 2(a1),-(sp) ; push arg
444:
445: jsr _kbshift
446:
447: bra.s L_1out
448:
449:
450:
451: L_bios:
452:
453: clr.w -(sp) ; no frame format needed
454:
1.1.1.3 root 455: move.l _curproc,a0
1.1 root 456:
1.1.1.3 root 457: pea 4(a0) ; push pointer to syscall context save
1.1 root 458:
459: jsr _build_context
460:
1.1.1.3 root 461: lea _bios_tab,a5 ; set syscall_tab
1.1 root 462:
463: move.w _bios_max,d5 ; set syscall_max
464:
465: ;
466:
467: ; copy parameters onto process stack. a0 and a1 were set by _build_context
468:
469: ;
470:
471:
472:
473: move.l _curproc,a0
474:
475: move.l (a0),sp ; this puts us in our private stack
476:
477: move.l 24(a1),-(sp) ; a1 was set by build_context
478:
479: move.l 20(a1),-(sp)
480:
481: move.l 16(a1),-(sp)
482:
483: move.l 12(a1),-(sp)
484:
485: move.l 8(a1),-(sp)
486:
487: move.l 4(a1),-(sp)
488:
489: move.l (a1),-(sp)
490:
491:
492:
493: _syscall:
494:
495: ;
496:
497: ; check here to see if we need to flush the Bconout() buffer
498:
499: ;
500:
501: tst.w _bconbsiz ; characters in buffer?
502:
503: beq.s L_noflush ; no: OK to proceed
504:
505: ;
506:
507: ; watch out, this could cause a context switch
508:
509: ;
510:
511: jsr _bflush ; flush the buffer
512:
513:
514:
515: L_noflush:
516:
517: ;
518:
519: ; figure out which routine to call
520:
521: ;
522:
523: move.w (sp),d0
524:
525: cmp.w #-1,d0 ; trapping with -1 means return
526:
527: bne.s check_max ; the corresponding system table
528:
529: move.l a5,d0
530:
531: bra.s out
532:
533: check_max:
534:
535: cmp.w d5,d0
536:
1.1.1.4 ! root 537: bcc.s error
1.1 root 538:
539: add.w d0,d0
540:
541: add.w d0,d0 ; multiply by 4
542:
543: move.l 0(a5,d0.w),d0 ; d0 = syscall_tab[d0]
544:
545: beq.s error ; null entry means invalid call
546:
1.1.1.3 root 547: addq.w #2,sp ; pop function number off stack
1.1 root 548:
549: move.l d0,a0
550:
551: jsr (a0) ; go do the call
552:
553: out:
554:
555: move.l _curproc,a0
556:
557: move.l d0,P_SYSCTXT+C_D0(a0) ; set d0 in the saved context
558:
559: move.w P_SYSCTXT+C_SR(a0),d0 ; get saved status register
560:
561:
562:
563: tst.l P_PTRACER(a0) ; check curproc->ptracer, if not set
564:
565: beq.s notrace ; then no pending trace; this ensures
566:
567: move.w d0,d1 ; we work with non-MiNT debuggers
568:
569: and.w #$c000,d1 ; are either of the trace bits set
570:
571: sne P_SYSCTXT+C_PTRACE(a0) ; mark as trace pending/not
572:
573: notrace:
574:
575: tst.w _proc_clock ; has process exceeded time slice?
576:
577: bne.s nosleep ; no -- continue
578:
579: btst #13,d0 ; caller in supervisor mode?
580:
581: bne.s nosleep ; yes -- don't interrupt
582:
583: tst.w ($43e).w ; test floppy disk lock variable
584:
585: bne.s nosleep ; if locked, can't switch
586:
587: sleep:
588:
589: jsr _preempt ; does a sleep(READY_Q)
590:
591: nosleep:
592:
593: ori.w #$0700,sr ; spl7()
594:
595: jsr _leave_kernel ; restore vectors
596:
597: move.l _curproc,a0
598:
599: pea 4(a0)
600:
601: jsr _restore_context ; never returns
602:
603:
604:
605: ;
606:
607: ; we handle errors by calling through to GEMDOS or the BIOS/XBIOS,
608:
609: ; as appropriate, and letting them handle it -- that way, if the underlying
610:
611: ; system has functions we don't know about, they still work
612:
613: ; to figure out which trap we have to call, we use the system call
614:
615: ; table placed in a5 earlier
616:
617:
618:
619: error:
620:
621: cmp.l #_xbios_tab,a5
622:
623: bne.s maybe_bios
624:
625: trap #14
626:
627: bra.s out
628:
629: maybe_bios:
630:
631: cmp.l #_dos_tab,a5
632:
633: beq.s trap_1
634:
635: trap #13
636:
637: bra.s out
638:
639: trap_1:
640:
641: trap #1
642:
643: bra.s out
644:
645:
646:
647: ;
648:
649: ; sig_return: user signal handlers return to us. At that point, the
650:
651: ; stack looks like this:
652:
1.1.1.2 root 653: ; -4(sp) (long) sfmt
654:
1.1 root 655: ; (sp) (long) signal number -- was a parameter for user routine
656:
657: ;
658:
659: XDEF _sig_return
660:
661: XREF _valid_return
662:
663: _sig_return:
664:
1.1.1.3 root 665: addq.w #8,sp ; pop signal number and sfmt
1.1 root 666:
667: move.w #$11a,-(sp) ; Psigreturn() system call
668:
669: move.w #1,_valid_return ; tell kernel it's us!
670:
671: trap #1
672:
673: ; we had better not come back; if we did, something terrible
674:
675: ; happened, and we might as well terminate
676:
677: move.w #-998,-(sp)
678:
679: move.w #$4c,-(sp) ; Pterm()
680:
681: trap #1
682:
683: ;
684:
685: ; bconout special code: on entry, a1 points to the stack the user
686:
687: ; was using. If possible, we just buffer the output until later.
688:
689: ;
690:
691:
692:
693: do_bconout:
694:
695: tst.w _bconbdev ; is BIOS buffering on?
696:
697: bmi L_bios ; no buffering -- skip this code
698:
699: move.w 2(a1),d0 ; what device is this for?
700:
701: beq L_bios ; don't buffer the printer
702:
703: cmp.w _bconbdev,d0 ; same device as is buffered?
704:
705: bne.s new_dev ; no -- maybe we can't do this
706:
707: put_buf:
708:
709: move.w 4(a1),d0 ; get the character to output
710:
711: move.w _bconbsiz,d1 ; get index into buffer table
712:
713: cmp.w #255,d1 ; buffer full?
714:
715: beq L_bios ; yes -- flush it out
716:
717: lea _bconbuf,a0
718:
719: add.w d1,a0
720:
721: move.b d0,(a0) ; store the character
722:
723: addq.w #1,d1
724:
725: move.w d1,_bconbsiz
726:
727: jsr _leave_kernel ; restore vectors
728:
729: moveq.l #-1,d0 ; return character output OK
730:
731: rte
732:
733:
734:
735: new_dev:
736:
737: tst.w _bconbsiz ; characters already in buffer?
738:
739: bne L_bios ; yes: we can't buffer this one
740:
741: move.w d0,_bconbdev ; no: OK, we have a new device
742:
743: bra.s put_buf
744:
745:
746:
747: ;
748:
749: ; _lineA0: MiNT calls this to get the address of the line A variables
750:
751: ;
752:
753: XDEF _lineA0
754:
755: _lineA0:
756:
757: movem.l d2/a2,-(sp) ; save scratch registers
758:
759: dc.w $a000 ; call the line A initialization routine
760:
761: movem.l (sp)+,d2/a2
762:
763: rts
764:
765:
766:
767: ;
768:
769: ; _call_aes: calls the GEM AES, using the control block passed as
770:
771: ; a parameter. Used only for doing appl_init(), to see
772:
773: ; if the AES is active yet
774:
775: ;
776:
777: XDEF _call_aes
778:
779: _call_aes:
780:
781: move.l 4(sp),d1 ; fetch pointer to parameter block
782:
783: move.w #$c8,d0 ; magic number for AES
784:
785: movem.l d2/a2,-(sp) ; save scratch registers
786:
787: trap #2
788:
789: movem.l (sp)+,d2/a2
790:
791: rts
792:
1.1.1.4 ! root 793: ;
! 794:
! 795: ; _call_dosound:
! 796:
! 797: ;
! 798:
! 799: XDEF _call_dosound
! 800:
! 801: _call_dosound:
! 802:
! 803: move.l 4(sp),d0
! 804:
! 805: move.l d0,-(sp)
! 806:
! 807: move.w #32,-(sp)
! 808:
! 809: trap #14
! 810:
! 811: addq.w #6,sp
! 812:
! 813: rts
! 814:
1.1 root 815:
816:
817: ;
818:
819: ; _callout: Call an external function, passing <32 bytes of arguments,
820:
821: ; and return the value from the function. NOTE: we must be careful
822:
823: ; to save all registers here!
824:
825: ;
826:
827: XDEF _callout
828:
829: XDEF _callout1
830:
831: XDEF _callout2
832:
833: ;
834:
835: ; _callout is the general purpose one
836:
837: ;
838:
839: _callout:
840:
841: lea 8(sp),a0 ; pointer to args
842:
843: move.l 4(sp),a1 ; pointer to pointer to function
844:
845: movem.l d2-d7/a2-a6,-(sp) ; save registers
846:
847: movem.l (a0),d0-d7 ; copy parameters
848:
1.1.1.4 ! root 849: movem.l d0-d7,-(sp)
1.1 root 850:
1.1.1.4 ! root 851: suba.l a5,a5 ; the BIOS expects 0 in a5
1.1 root 852:
853: jsr (a1) ; go do it
854:
855: lea 32(sp),sp
856:
857: movem.l (sp)+,d2-d7/a2-a6 ; restore reggies
858:
859: rts
860:
861: ;
862:
863: ; _callout2 and _callout1 are for functions with just 1 or
864:
865: ; 2 16 bit parameters. We cheat and use the same code for
866:
867: ; both, since passing 32 bits isn't much more expensive than
868:
869: ; passing 16 bits (and since the called function will just
870:
871: ; ignore any extra arg)
872:
873: ;
874:
875:
876:
877: _callout1:
878:
879: _callout2:
880:
881: movem.l 4(sp),a0/a1 ; get function ptr & args
882:
883: movem.l d2-d7/a2-a6,-(sp) ; save reggies
884:
885: move.l a1,-(sp) ; push args
886:
1.1.1.4 ! root 887: suba.l a5,a5 ; the BIOS expects 0 in a5
! 888:
1.1 root 889: jsr (a0) ; do function
890:
1.1.1.3 root 891: addq.w #4,sp
1.1 root 892:
893: movem.l (sp)+,d2-d7/a2-a6 ; restore reggies
894:
895: rts
896:
897:
898:
1.1.1.2 root 899: ;
900:
901: ; do_usrcall: call the user supplied function (*usrcall)(), with
902:
903: ; arguments given in the longwords usrarg1..usrarg5. Return value
904:
905: ; is placed in usrret. This function is used by the Supexec code
906:
907: ; in xbios.c.
908:
909:
910:
911: XDEF _do_usrcall
912:
913: XREF _usrret
914:
915: XREF _usrcall
916:
917: XREF _usrarg1,_usrarg2,_usrarg3,_usrarg4,_usrarg5
918:
919:
920:
921: _do_usrcall:
922:
923: move.l _usrarg5,-(sp)
924:
925: move.l _usrarg4,-(sp)
926:
927: move.l _usrarg3,-(sp)
928:
929: move.l _usrarg2,-(sp)
930:
931: move.l _usrarg1,-(sp)
932:
933: move.l _usrcall,-(sp) ; the user expects to see this on the stack
934:
1.1.1.3 root 935: pea ucret(pc) ; so rts puts us back here
1.1.1.2 root 936:
937: move.l _usrcall,-(sp) ; this copy is for us to use
938:
939: rts ; to jump to (we don't want to use registers)
940:
941: ucret:
942:
1.1.1.3 root 943: lea 24(sp),sp ; fix up stack
1.1.1.2 root 944:
945: move.l d0,_usrret ; save returned value
946:
947: rts ; back to caller
948:
949:
950:
1.1 root 951: END
952:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.