|
|
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: 143: move.l _curproc,d0 144: 145: addq.l #4,d0 146: 147: move.l d0,-(sp) ; push pointer to syscall context save 148: 149: jsr _build_context 150: 151: move.l #_dos_tab,a5 ; set syscall_tab 152: 153: move.w _dos_max,d5 ; set syscall_max 154: 155: ; 156: 157: ; copy parameters onto process stack. a0 and a1 were set by _build_context 158: 159: ; 160: 161: 162: 163: move.l _curproc,a0 164: 165: move.l (a0),sp ; this puts us in our private stack 166: 167: move.l 24(a1),-(sp) ; a1 was set by build_context 168: 169: move.l 20(a1),-(sp) 170: 171: move.l 16(a1),-(sp) 172: 173: move.l 12(a1),-(sp) 174: 175: move.l 8(a1),-(sp) 176: 177: move.l 4(a1),-(sp) 178: 179: move.l (a1),-(sp) 180: 181: jsr _enter_kernel ; set up vectors appropriately 182: 183: bra _syscall 184: 185: 186: 187: _mint_xbios: 188: 1.1.1.2 ! root 189: ; ! 190: ! 191: ; Kludge for Setscreen: under Falcon TOS, this ! 192: ! 193: ; calls a GEMDOS function (Srealloc) and so ! 194: ! 195: ; we must *not* change any of the vectors!! ! 196: ! 197: ! 198: ! 199: btst #13,(sp) ; test for user/super mode ! 200: ! 201: beq LX_usr ! 202: ! 203: %ifdef ONLY030 ! 204: ! 205: lea 8(sp),a1 ! 206: ! 207: %else ! 208: ! 209: lea 6(sp),a1 ; supervisor mode: args on stack ! 210: ! 211: tst.w ($59e).w ; test longframe ! 212: ! 213: beq.s LX_check ! 214: ! 215: addq.l #2,a1 ; stack is a bit bigger ! 216: ! 217: %endif ! 218: ! 219: bra.s LX_check ! 220: ! 221: LX_usr: ! 222: ! 223: move.l usp,a1 ; user mode: args on user stack ! 224: ! 225: LX_check: ! 226: ! 227: move.w (a1),d0 ; check command ! 228: ! 229: cmp.w #5,d0 ; Setscreen? ! 230: ! 231: beq LX_screen ; no -- fall through ! 232: ! 233: ! 234: 1.1 root 235: clr.w -(sp) ; no frame format needed 236: 237: move.l _curproc,d0 238: 239: addq.l #4,d0 240: 241: move.l d0,-(sp) ; push pointer to syscall context save 242: 243: jsr _build_context 244: 245: move.l #_xbios_tab,a5 ; set syscall_tab 246: 247: move.w _xbios_max,d5 ; set syscall_max 248: 249: ; 250: 251: ; copy parameters onto process stack. a0 and a1 were set by _build_context 252: 253: ; 254: 255: 256: 257: move.l _curproc,a0 258: 259: move.l (a0),sp ; this puts us in our private stack 260: 261: move.l 24(a1),-(sp) ; a1 was set by build_context 262: 263: move.l 20(a1),-(sp) 264: 265: move.l 16(a1),-(sp) 266: 267: move.l 12(a1),-(sp) 268: 269: move.l 8(a1),-(sp) 270: 271: move.l 4(a1),-(sp) 272: 273: move.l (a1),-(sp) 274: 275: jsr _enter_kernel ; set up vectors appropriately 276: 277: bra _syscall 278: 1.1.1.2 ! root 279: ; ! 280: ! 281: ; For setscreen, jump directly to the ROM vector -- ! 282: ! 283: ; this avoids all hazards (like changing the vectors) ! 284: ! 285: ! 286: ! 287: LX_screen: ! 288: ! 289: move.l _old_xbios+8,a0 ! 290: ! 291: jmp (a0) ! 292: ! 293: ! 294: 1.1 root 295: 296: 297: _mint_bios: 298: 299: ; 300: 301: ; Entering the kernel can be very expensive; so, we take a short-cut 302: 303: ; if possible -- we try some BIOS functions out, and if they 304: 305: ; succeed without blocking then we're done; otherwise, we go 306: 307: ; through the long procedure for entering the kernel 308: 309: ; 310: 311: ; These shortcuts aren't done when we're called in supervisor mode, 312: 313: ; because TOS uses very tiny stacks (smaller than we want); the 314: 315: ; shortcuts operate on the user-supplied ssp, whereas the "full" 316: 317: ; BIOS code works on our (private) system stack 318: 319: ; 320: 1.1.1.2 ! root 321: ; the shortcuts are also turned off if BIOSBUF=n ! 322: ! 323: ; ! 324: 1.1 root 325: jsr _enter_kernel ; set up BIOS vectors 326: 1.1.1.2 ! root 327: tst.w _bconbdev ; is BIOS buffering on? ! 328: ! 329: bmi L_bios ; no; skip all this ! 330: ! 331: ! 332: 1.1 root 333: btst #5,(sp) ; test for user/super mode 334: 335: bne.s L_bios ; if super, goto L_bios 336: 337: tst.w _proc_clock ; are we about to be preempted? 338: 1.1.1.2 ! root 339: beq L_bios 1.1 root 340: 341: 342: 343: move.l usp,a1 ; user mode: args on user stack 344: 345: L_ubios: 346: 347: move.w (a1),d0 ; get command 348: 349: cmp.w #3,d0 ; Bconout? 350: 351: beq do_bconout ; yes -- go do it 352: 353: ; 354: 355: ; most of the remaining functions require BIOS vectors to be properly 356: 357: ; set up 358: 359: tst.w _bconbsiz ; is BIOS output waiting? 360: 361: bne.s L_bios ; yes -- do regular code 362: 363: 364: 365: ; test for various BIOS functions 366: 367: cmp.w #1,d0 ; Bconstat? 368: 369: bne.s L_00 370: 371: move.w 2(a1),-(sp) ; push arg 372: 373: jsr _ubconstat 374: 375: L_1out: 376: 377: addq.l #2,sp 378: 379: L_0out: 380: 381: move.l d0,-(sp) ; save d0 382: 383: ori.w #$0700,sr ; spl7() 384: 385: jsr _leave_kernel 386: 387: move.l (sp)+,d0 ; retrieve value to be returned 388: 389: rte ; return to user 390: 391: L_00: 392: 393: cmp.w #2,d0 ; Bconin? 394: 395: bne.s L_01 396: 397: move.w 2(a1),-(sp) ; yes; push argument 398: 399: jsr _do_bconin 400: 401: addq.l #2,sp 402: 403: cmp.w #$dead,d0 ; would Bconin block? 404: 405: bne.s L_0out ; no -- we're done 406: 407: bra.s L_bios ; yes -- do the long stuff 408: 409: L_01: 410: 411: cmp.w #8,d0 ; Bcostat? 412: 413: bne.s L_02 414: 415: move.w 2(a1),-(sp) ; push device 416: 417: jsr _ubcostat ; get status 418: 419: bra.s L_1out 420: 421: L_02: 422: 423: cmp.w #11,d0 ; Kbshift? 424: 425: bne.s L_bios 426: 427: move.w 2(a1),-(sp) ; push arg 428: 429: jsr _kbshift 430: 431: bra.s L_1out 432: 433: 434: 435: L_bios: 436: 437: clr.w -(sp) ; no frame format needed 438: 439: move.l _curproc,d0 440: 441: addq.l #4,d0 442: 443: move.l d0,-(sp) ; push pointer to syscall context save 444: 445: jsr _build_context 446: 447: move.l #_bios_tab,a5 ; set syscall_tab 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: 533: addq.l #2,sp ; pop function number off stack 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.2 ! root 651: add.l #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: 853: addq.l #4,sp 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: ! 897: pea ucret ; so rts puts us back here ! 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: ! 905: add.w #24,sp ; fix up stack ! 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.