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