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