|
|
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.