|
|
1.1 ! root 1: .unixorder ! 2: .llen 132 ! 3: .include as.inc ! 4: ! 5: IODELAY .macro ! 6: jmp .+2 / DELAY ! 7: jmp .+2 / DELAY ! 8: .endm ! 9: ! 10: / Most places where %cr3 is refreshed, it can be done through a Ring 0 gate. ! 11: MMUUPD .macro ! 12: pushfl ! 13: cli ! 14: lcall $SEG_MMUUPD,$0 / gate to mmuupdfR0 ! 15: popfl ! 16: .endm ! 17: ! 18: / ! 19: / USTART and ESP_START map kernel stack and u area within top 4k page ! 20: / of virtual space. ! 21: / NDP context starts 0x100 bytes below u area. ! 22: / See also U_OFFSET, NDP_OFFSET in uproc.h ! 23: / ! 24: .set USTART,0xFFFFFC00 ! 25: .set ESP0_START,0xFFFFF300 ! 26: .set ESP1_START,USTART ! 27: ! 28: .set u,USTART ! 29: .set PSW_VAL,0x1200 / set system IOPL to 1, enable IRQ ! 30: / .set PSW_VAL,0x3200 / set system IOPL to 3, enable IRQ ! 31: ! 32: / (lgl- ! 33: / The information contained herein is a trade secret of Mark Williams ! 34: / Company, and is confidential information. It is provided under a ! 35: / license agreement, and may be copied or disclosed only under the ! 36: / terms of that agreement. Any reproduction or disclosure of this ! 37: / material without the express written authorization of Mark Williams ! 38: / Company or persuant to the license agreement is unlawful. ! 39: ! 40: / Copyright (c) 1982, 1992. ! 41: / An unpublished work by Mark Williams Company, Chicago. ! 42: / All rights reserved. ! 43: ! 44: / Intel 386 port and extensions ! 45: / Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991 ! 46: / -lgl) ! 47: / ! 48: / $Log: as.s,v $ ! 49: /Revision 1.18 93/06/14 13:42:14 bin ! 50: /Hal: kernel 78 update ! 51: / ! 52: / Revision 1.17 92/12/08 16:43:10 root ! 53: / ker 70 ! 54: / ! 55: / Revision 1.16 92/11/12 10:04:31 root ! 56: / Ker #68 ! 57: / ! 58: / Revision 1.15 92/11/09 17:08:28 root ! 59: / Just before adding vio segs. ! 60: / ! 61: / Revision 1.13 92/10/06 23:47:48 root ! 62: / Ker #64 ! 63: / ! 64: / Revision 1.12 92/10/06 20:45:40 root ! 65: / Ker #63d ! 66: / ! 67: / Revision 1.10 92/07/27 18:15:43 hal ! 68: / Kernel #59 ! 69: / ! 70: / Revision 1.9 92/07/16 16:38:14 hal ! 71: / Kernel #58 ! 72: / ! 73: / Revision 1.8 92/07/15 13:50:55 root ! 74: / COH 4.0.0 ! 75: / ! 76: / Revision 1.6 92/04/03 11:05:28 hal ! 77: / Fix missed IRQ bug. ! 78: / Add read_t0(), read_psw(), getusd(), putusd(). ! 79: / ! 80: ! 81: /////// ! 82: / Machine language assist for ! 83: / Intel 80386/80486 Coherent. This contains the parts ! 84: / that are common to all machines as well as the machine-specific code ! 85: / for the IBM PC-386 ! 86: ! 87: ! 88: /////// ! 89: ! 90: / System entry point. ! 91: ! 92: / When this code is entered, the boot program has done the following: ! 93: / Relocate itself above where the kernel will be (e.g., 0x20600). ! 94: / Load as.s binary; text at 0x02000, data at next paragraph (16-byte) ! 95: / boundary at or beyond end of kernel text. ! 96: / CS = 0x02000 <- start of kernel text ("physical" stext) ! 97: / ES = 0x02xxx <- start of kernel data ! 98: / SS,DS = 0x20xxx <- ....some address in boot data space.... ! 99: ! 100: / Due to the way the kernel has been linked (see ld.master), symbol "stext" ! 101: / has a value of 0xFFC0_0000, which is the start of the last 4 meg segment. ! 102: / This value is the address in linear space once we have entered paging mode, ! 103: / but until that time relocation arithmetic is necessary: ! 104: / ! 105: / Before segmentation is turned on, symbols in kernel text or data space ! 106: / must be relocated by -SBASE<<BPCSHIFT for memory reference instructions ! 107: / to work. ! 108: ! 109: /////// ! 110: ! 111: stext: / kernel code starts at stext+0x100 ! 112: .org .+0x100 / reserve stack space ! 113: cli / No interrupts, please. ! 114: ! 115: / put up a debugging "!" on the screen. We can still use the BIOS. ! 116: push %si / Save registers. ! 117: push %di ! 118: ! 119: movb $'!', %al ! 120: ! 121: movw $0x0007, %bx / Page 0, white on black ! 122: movb $0x0E, %ah / Write TTY. ! 123: int $VIDEO / Call video I/O in ROM. ! 124: pop %di ! 125: pop %si ! 126: ! 127: / equipment status word to AX ! 128: int $0x11 / Obtain int 11 value before printf(). ! 129: movl %eax,%ecx / esw -> cx ! 130: ! 131: / val11 is a long, initially zero, in the CS. ! 132: / copy (long)esw to val11 ! 133: .byte PX_ADDR / 32-bit address ! 134: .byte PX_OPND / 32-bit operand ! 135: movl %ecx,%cs:[[-SBASE]<<BPCSHIFT]+val11 ! 136: ! 137: / last use of boot block's stack ! 138: .byte PX_ADDR / 32-bit address ! 139: .byte PX_OPND / 32-bit operand ! 140: lgdtl %cs:[[-SBASE]<<BPCSHIFT]+gdtinit ! 141: ! 142: / turn on lsbit of cr0 - Protection Enable ! 143: mov %cr0,%eax ! 144: orb $1,%al ! 145: mov %eax,%cr0 ! 146: ! 147: / intersegment jump (48-bit address) ! 148: / jumping flushes the cache... ! 149: / ! 150: .byte PX_OPND ! 151: ljmp $SEG_386_II, $next ! 152: ! 153: next: ! 154: mov $SEG_386_ID,%eax ! 155: movw %ax,%ds ! 156: movw %ax,%ss ! 157: mov $SEG_386_UD|R_USR,%eax ! 158: movw %ax,%es ! 159: mov $stext+0x100,%eax / 256 byte stack for initialization ! 160: mov %eax,%esp ! 161: ! 162: push $'@' / Debugging checkpoint: ! 163: call chirp / protected mode is on ! 164: pop %ecx ! 165: ! 166: / Enable the A20 address line, which is normally disabled by the ROM BIOS. ! 167: / This line is under the control of the 8042 keyboard interface controller. ! 168: ! 169: sub %ecx, %ecx ! 170: loc0: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 171: testb $2,%al ! 172: loopne loc0 ! 173: IODELAY ! 174: ! 175: movb $0xD1, %al / Request next output byte to be ! 176: outb $KBCTRL / sent to the 8042 output port. ! 177: IODELAY ! 178: ! 179: sub %ecx, %ecx ! 180: loc1: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 181: testb $2, %al ! 182: loopne loc1 ! 183: IODELAY ! 184: ! 185: movb $0xDF,%al / Enable A20 address line. ! 186: outb $KBDATA / See Page 1-44, IBM-AT Tech Ref. ! 187: IODELAY ! 188: ! 189: sub %ecx, %ecx ! 190: loc2: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 191: testb $2,%al / NOTE: A20 not enabled for up to 20 us. ! 192: loopne loc2 ! 193: ! 194: ! 195: / Reprogram the 8253 timer so that channel 0, ! 196: / which is used as the clock, interrupts at exactly ! 197: / 100 HZ, instead of 18.2 HZ. ! 198: ! 199: movb $0x36,%al / Timer 0, LSB, MSB, mode 3 ! 200: outb $PIT+3 ! 201: IODELAY ! 202: movb $0x9C,%al / Lsb of 59659/5 = 11932 ! 203: outb $PIT ! 204: IODELAY ! 205: movb $0x2E,%al / Msb of 59659/5 = 11932 ! 206: outb $PIT ! 207: IODELAY ! 208: ! 209: / Reprogram the 1st programmable interrupt controller. ! 210: / Its default vector table collides with iAPX 286 protection vectors. ! 211: movb $0x11,%al / ICW1 - edge, ICW4 ! 212: outb $PIC ! 213: IODELAY ! 214: movb $0x20,%al / ICW2 - Reserve 1st 32 vectors for 286 ! 215: outb $PICM ! 216: IODELAY ! 217: movb $0x04,%al / ICW3 - master level 2 ! 218: outb $PICM ! 219: IODELAY ! 220: movb $0x01,%al / ICW4 - 8086 mode, master. ! 221: outb $PICM ! 222: IODELAY ! 223: ! 224: / NIGEL: The original code here (and related code in "i386/md.c") turned off ! 225: / the chain bit in the first PIC by default (and at every subsequent ! 226: / opportunity) even though all the mask bits in the slave PIC are set to off. ! 227: / In order to support an enhanced interrupt architecture for the STREAMS and ! 228: / DDI/DDK subsystems I want to remove the state knowledge from the code in ! 229: / "i386/md.c" so that the chain bit is always left on. ! 230: / In order to do this, I have modified the startup code below so that the ! 231: / system by default allows the slave PIC to interrupt (of course, it still ! 232: / won't interrupt unless it is enabled to; the masking I have removed was ! 233: / totally redundant). ! 234: ! 235: movb $0xFA,%al / Disable interrupts from master PIC. ! 236: outb $PICM / (except for clock and slave PIC interrupt). ! 237: ! 238: movb $0x11,%al / ICW1 - edge, ICW4 ! 239: outb $SPIC ! 240: IODELAY ! 241: movb $0x70,%al / ICW2 - slave starts at 0x70th interrupt ! 242: outb $SPICM ! 243: IODELAY ! 244: movb $0x02,%al / ICW3 - master level 2 ! 245: outb $SPICM ! 246: IODELAY ! 247: movb $0x01,%al / ICW4 - 8086 mode. ! 248: outb $SPICM ! 249: IODELAY ! 250: movb $0xFF,%al ! 251: outb $SPICM / Disable interrupts from slave PIC. ! 252: /DEBUG ! 253: cli ! 254: call __cinit ! 255: call mchinit / C initialization ! 256: mov %cr0,%eax / Turn on paging ! 257: / use 80000001 to allow FP ! 258: / or $0x80000001,%eax ! 259: / use 80000005 to disallow FP ! 260: or $0x80000005,%eax ! 261: mov %eax,%cr0 ! 262: ljmp $SEG_RNG0_TXT,$loc3 / clear pipeline; jump far, direct ! 263: ! 264: / ! 265: / Ring 0 startup code ! 266: / ! 267: loc3: ! 268: movw $SEG_386_KD,%ax ! 269: movw %ax,%ds ! 270: movw $SEG_RNG0_STK,%ax ! 271: movw %ax,%ss ! 272: movl $ESP0_START,%esp / Stack pointer for init ! 273: clts / Clear task switched flag. ! 274: ! 275: / Call the machine setup code. ! 276: / Call Coherent main. ! 277: / On return, send control off to the user ! 278: / at its entry point. ! 279: ! 280: sub %eax, %eax / Load local descriptor table register. ! 281: lldt %ax ! 282: ! 283: / movw $tss,%ax / Fix low 16 bits of tss base in gdt ! 284: / movw %ax,gdt+SEG_TSS+2 ! 285: ! 286: / Fix tss base in gdt ! 287: movl $tss,%eax ! 288: movw %ax,gdt+SEG_TSS+2 / Fix bits 0..15 ! 289: rorl $16,%eax / Get tss bits 16..31 ! 290: movb %al,gdt+SEG_TSS+4 / Fix bits 16..23 ! 291: movb %ah,gdt+SEG_TSS+7 / Fix bits 24..31 ! 292: ! 293: movw $SEG_TSS,%ax / Load task state segment register. ! 294: ltr %ax ! 295: lidt idtmap / Load interrupt descriptor table ! 296: lgdt gdtmap ! 297: ! 298: / movw $ldt,%ax / Relocate ldt in gdt ! 299: / movw %ax,gdt+SEG_LDT+2 ! 300: ! 301: / Fix ldt base in gdt ! 302: movl $ldt,%eax ! 303: movw %ax,gdt+SEG_LDT+2 / Fix bits 0..15 ! 304: rorl $16,%eax / Get ldt bits 16..31 ! 305: movb %al,gdt+SEG_LDT+4 / Fix bits 16..23 ! 306: movb %ah,gdt+SEG_LDT+7 / Fix bits 24..31 ! 307: ! 308: movw $SEG_LDT,%ax ! 309: lldt %ax ! 310: ! 311: call i8086 / i8086() does fixup of tss_sp0 ! 312: ! 313: / ! 314: / Enter Ring 1 kernel from Ring 0 ! 315: / ! 316: push $SEG_RNG1_STK / SS ! 317: push $ESP1_START / ESP ! 318: push $PSW_VAL / PSW ! 319: push $SEG_RNG1_TXT / CS ! 320: push $__xmain__ / IP ! 321: movw $SEG_386_KD,%ax / DS, ES ! 322: movw %ax, %ds / Map data segment ! 323: movw %ax, %es / Map extra segment ! 324: iret / Go to user state. ! 325: ! 326: / ! 327: / Start of Ring 1 kernel. ! 328: / Need Ring 1 because interrupts are about to turn on, and all irpt gates ! 329: / have DPL (descriptor privilege level) 1. ! 330: / ! 331: __xmain__: ! 332: sti / Interrupts on, and ! 333: call main / call Coherent mainline. ! 334: cli / Interrupts off. ! 335: ! 336: / ! 337: / Enter User mode from Ring 1 kernel ! 338: / ! 339: push $SEG_386_UD|R_USR / SS ! 340: push $NBPC / ESP ! 341: push $PSW_VAL / PSW ! 342: push $SEG_386_UI|R_USR / CS ! 343: push $0 / IP ! 344: movw $SEG_386_UD|R_USR,%ax / DS, ES ! 345: movw %ax, %ds / Map data segment ! 346: movw %ax, %es / Map extra segment ! 347: iret / Go to user state. ! 348: ! 349: /////// ! 350: / ! 351: / Trap and interrupt save. ! 352: / ! 353: / This version of tsave runs from Ring 1 trap/irpt gates. ! 354: / ! 355: /////// ! 356: .globl disflag ! 357: ! 358: tsave: / What level of interrupt ? ! 359: pusha ! 360: push %ds / Save current state ! 361: push %es ! 362: push %fs ! 363: push %gs ! 364: ! 365: mov $SEG_386_KD,%eax / Map ds ! 366: movw %ax,%ds ! 367: mov $SEG_386_UD|R_USR,%eax / Map es ! 368: movw %ax,%es / to system ds ! 369: ! 370: sti ! 371: icall X_TRAPNO(%esp) / and call the caller ! 372: cli ! 373: ! 374: / if got here from user mode or from idle process, call stand() ! 375: / else just do cleanup and return ! 376: ! 377: movb X_ERR+8(%esp),%al / trapped CS: user RPL? ! 378: andb $3,%al ! 379: cmpb $R_USR,%al ! 380: je tsave1a / jmp if user mode ! 381: cmpl $__idle__,X_ERR+4(%esp) / trapped EIP == idle process? ! 382: jnz tsave1b / Call stand() only if idle ! 383: movl $1,disflag ! 384: ! 385: tsave1a: ! 386: sti ! 387: call stand ! 388: tsave1b: ! 389: cli / No more interrupts ! 390: pop %gs / Restore ! 391: pop %fs ! 392: pop %es ! 393: pop %ds ! 394: popa ! 395: add $8,%esp / forget err, trapno ! 396: iret / Done. ! 397: ! 398: / ! 399: / Here is another version of tsave, called only from the GP vector (RING 0) ! 400: / ! 401: ! 402: BYPASS .macro addr ! 403: cmpl $addr,X_ERR+4(%esp) / trapped EIP ! 404: jz tsave0b ! 405: .endm ! 406: ! 407: tsave0: / What level of interrupt ? ! 408: pusha ! 409: push %ds / Save current state ! 410: push %es ! 411: push %fs ! 412: push %gs ! 413: ! 414: mov $SEG_386_KD,%eax / Map ds ! 415: movw %ax,%ds ! 416: mov $SEG_386_UD|R_USR,%eax / Map es ! 417: movw %ax,%es / to system ds ! 418: ! 419: jmp tsave0b ! 420: ! 421: //The following lines help find traps during startup. ! 422: BYPASS read_cr0 ! 423: BYPASS read_cr2 ! 424: BYPASS read_cr3 ! 425: tsave0q: ! 426: mov 52(%esp),%eax / Print fault code. ! 427: cmpb $0x40,%al ! 428: je tsave0b / Skip over hardware interrupts. ! 429: push %eax ! 430: call print32 ! 431: pop %ecx ! 432: ! 433: push $' ' ! 434: call mchirp ! 435: pop %ecx ! 436: ! 437: mov 56(%esp),%eax / Print eip. ! 438: push %eax ! 439: call print32 ! 440: pop %ecx ! 441: ! 442: push $' ' ! 443: call mchirp ! 444: pop %ecx ! 445: ! 446: push %esp / Print esp. ! 447: call print32 ! 448: pop %ecx ! 449: ! 450: tsave0a: jmp tsave0a ! 451: tsave0b: ! 452: // ! 453: ! 454: icall X_TRAPNO(%esp) / and call the caller ! 455: ! 456: pop %gs / Restore ! 457: pop %fs ! 458: pop %es ! 459: pop %ds ! 460: popa ! 461: add $8,%esp / forget err, trapno ! 462: iret / Done. ! 463: ! 464: /////// ! 465: ! 466: / Save the environment of a process ! 467: / envsave(p) ! 468: / MENV *p; ! 469: ! 470: / Save the context of a process ! 471: / consave(p) ! 472: / MCON *p; ! 473: ! 474: /////// ! 475: ! 476: envsave: ! 477: consave: ! 478: mov %edi,%ecx / Hide di. ! 479: mov 4(%esp), %edi / di at the MCON block. ! 480: ! 481: movw %es,%dx / save = setspace(SEG_386_KD) -- should be %edx ! 482: movw $SEG_386_KD,%ax ! 483: movw %ax,%es ! 484: ! 485: cld / Ensure increment. ! 486: mov %ecx, %eax / Save di ! 487: stosl ! 488: mov %esi, %eax / Save si ! 489: stosl ! 490: mov %ebx, %eax / Save bx ! 491: stosl ! 492: mov %ebp, %eax / Save bp ! 493: stosl ! 494: mov %esp, %eax / Save sp ! 495: stosl ! 496: mov (%esp), %eax / Save ra as pc ! 497: stosl ! 498: pushfl / Save fw ! 499: pop %eax ! 500: stosl ! 501: mov %ecx, %edi / Put di back, ! 502: sub %eax, %eax / indicate a state save and ! 503: movw %dx,%es / setspace(save) ! 504: ret / return to caller. ! 505: ! 506: /////// ! 507: ! 508: / Restore the environment of a process. ! 509: / envrest(p) ! 510: / MENV *p; ! 511: ! 512: /////// ! 513: ! 514: envrest: ! 515: cli ! 516: cld ! 517: mov 4(%esp),%esi / Pointer to context ! 518: lodsl / Restore di ! 519: mov %eax, %edi ! 520: lodsl / Restore si ! 521: mov %eax, %ecx / Save for later ! 522: lodsl / Restore bx ! 523: mov %eax, %ebx ! 524: lodsl / Restore bp ! 525: mov %eax, %ebp ! 526: lodsl / Restore sp ! 527: mov %eax, %esp ! 528: push %cs / Push current CS ! 529: lodsl / Restore pc ! 530: push %eax ! 531: lodsl / Restore flags ! 532: mov %eax, 8(%esp) / Stack now in form PSW,CS,IP. ! 533: mov %ecx, %esi / Restore si ! 534: mov $1,%eax / We are restoring ! 535: iret / Return through PSW,CS,IP. ! 536: ! 537: /////// ! 538: ! 539: / Restore the context of a process. ! 540: / Called with interrupts disabled from dispatch. ! 541: / conrest(u, o) ! 542: / saddr_t u; ! 543: ! 544: /////// ! 545: ! 546: conrest: ! 547: mov 8(%esp), %esi / Fetch syscon offset ! 548: ! 549: cli / Interrupts on hold ! 550: cld ! 551: ! 552: / Map new u area into linear space and update paging hardware ! 553: ! 554: mov 4(%esp),%eax / Fetch new u area saddr_t ! 555: orb $SEG_SRW,%al ! 556: mov %eax,[PTABLE1_V<<BPCSHIFT]+UADDR ! 557: ! 558: lcall $SEG_MMUUPD,$0 / strobe CR3 ! 559: ! 560: / Restore context ! 561: ! 562: lodsl / Restore di ! 563: mov %eax,%edi ! 564: lodsl / Restore si ! 565: mov %eax,%ecx / Save for later ! 566: lodsl / Restore bx ! 567: mov %eax,%ebx ! 568: lodsl / Restore bp ! 569: mov %eax,%ebp ! 570: lodsl / Restore sp ! 571: mov %eax,%esp ! 572: push %cs / Push current CS ! 573: lodsl / Restore pc ! 574: push %eax ! 575: ! 576: lodsl / Restore flags ! 577: mov %eax,8(%esp) / Stack now in form PSW,CS,IP. ! 578: mov %ecx,%esi / Restore si ! 579: mov $1,%eax / We are restoring ! 580: iret / Return through PSW,CS,IP. ! 581: ! 582: / Save useful registers. ! 583: ! 584: / msysgen(p) ! 585: / MGEN *p; ! 586: ! 587: msysgen: ! 588: ret / Nothing useful to save ! 589: ! 590: / Disable interrupts. Previous value is returned. ! 591: ! 592: sphi: ! 593: pushf / Save flags ! 594: pop %eax / Return current value ! 595: cli / Disable interrupts ! 596: ret / And return ! 597: ! 598: / Enable interrupts. Previous value is returned. ! 599: ! 600: splo: ! 601: pushf ! 602: pop %eax ! 603: sti ! 604: ret ! 605: ! 606: / Change interrupt flag. Previous value is returned. ! 607: ! 608: spl: ! 609: pop %eax / ip ! 610: pop %edx / psw ! 611: push %edx ! 612: push %edx / push psw, cs, ip for iret ! 613: push %cs ! 614: push %eax ! 615: pushf / old psw ! 616: pop %eax ! 617: iret ! 618: ! 619: /////// ! 620: ! 621: / Idle routine. ! 622: / Enable interupts, and wait for something to ! 623: / happen. Does not do anything to the 8259, bacause ! 624: / this will be set up correctly. ! 625: ! 626: /////// ! 627: .globl idle ! 628: idle: ! 629: sti / Interupts on. ! 630: __idle__: ! 631: jmp __idle__ / Wait for an interrupt ! 632: ret / and return. ! 633: ! 634: /////// ! 635: ! 636: / The world is indeed grim. ! 637: / Hang. Keep the interrupts on so that the ! 638: / keyboard can get int. ! 639: ! 640: /////// ! 641: ! 642: halt: sti / Be safe, ! 643: __halt__ ! 644: jmp __halt__ / And hang. ! 645: ! 646: /////// ! 647: ! 648: / Basic port level I/O. ! 649: ! 650: / Byte I/O (8 bits) ! 651: / int inb(port); ! 652: / int outb(port, data); ! 653: ! 654: / Word I/O (16 bits) ! 655: / int inw(port); ! 656: / int outw(port, data); ! 657: ! 658: / Long I/O (32 bits) ! 659: / int inl(port); ! 660: / int outl(port, data); ! 661: ! 662: /////// ! 663: ! 664: inb: mov 4(%esp),%edx ! 665: sub %eax,%eax ! 666: inb (%dx) ! 667: ret ! 668: ! 669: outb: movl 4(%esp),%edx ! 670: movl 8(%esp),%eax ! 671: outb (%dx) ! 672: ret ! 673: ! 674: inw: mov 4(%esp),%edx ! 675: sub %eax,%eax ! 676: inw (%dx) ! 677: ret ! 678: ! 679: outw: movl 4(%esp),%edx ! 680: movl 8(%esp),%eax ! 681: outw (%dx) ! 682: ret ! 683: ! 684: inl: mov 4(%esp),%edx ! 685: sub %eax,%eax ! 686: inl (%dx) ! 687: ret ! 688: ! 689: outl: movl 4(%esp),%edx ! 690: movl 8(%esp),%eax ! 691: outl (%dx) ! 692: ret ! 693: ! 694: /////// ! 695: ! 696: / AT Hard Disk Assembler Support ! 697: ! 698: / atsend( va ) - send 512 bytes from virtual address to hard disk ! 699: / atrecv( va ) - receive 512 bytes from hard disk into virtual address ! 700: / DRQ is not checked. DRQ must be true before atsend/atrecv are called. ! 701: ! 702: / va is a system global address ! 703: /////// ! 704: ! 705: .globl atsend ! 706: atsend: ! 707: enter $0,$4 / reserve 4 bytes (1 int) of local storage ! 708: push %esi ! 709: push %es ! 710: call workAlloc / get a temp virt page ! 711: movl %eax,-4(%ebp) / this is "work0" - a click number ! 712: ! 713: movw $SEG_386_KD,%ax ! 714: movw %ax,%es / save = setspace(SEG_386_KD) ! 715: ! 716: cld ! 717: mov 20(%esp),%eax / fetch argument va ! 718: shr $BPCSHIFT,%eax / get page table index from va ! 719: mov sysmem,%edx ! 720: leal (%edx,%eax,4),%esi / base = sysmem.u.pbase + btocrd(va) ! 721: ! 722: / Since the requested transfer may span a click boundary, have two clicks ! 723: / ready in the page table - the one containing the virtual address of the ! 724: / start of the user area, and the click which follows in virtual memory. ! 725: ! 726: lodsl / ptable1_V[WORK0] = *base++ | SEG_SRW ! 727: or $SEG_SRW,%eax ! 728: movl -4(%ebp),%edx / work0 ! 729: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 730: ! 731: lodsl / ptable1_V[WORK1] = *base++ | SEG_SRW ! 732: or $SEG_SRW,%eax ! 733: inc %edx / work1 ! 734: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 735: ! 736: MMUUPD ! 737: ! 738: / Now that page boundaries are set, work on the offsets. ! 739: ! 740: mov 20(%esp),%esi / va = ctob(WORK0) + (va & (NBPC-1)) ! 741: and $NBPC-1,%esi / get click offset part of va ! 742: movl -4(%ebp),%edx / work0 ! 743: shl $BPCSHIFT,%edx / ctob(work0) ! 744: add %edx,%esi ! 745: ! 746: mov $256, %ecx / copy one disk block ! 747: mov $0x1F0, %edx ! 748: ! 749: / Do the block transfer. ! 750: ! 751: rep ! 752: outsw ! 753: ! 754: MMUUPD ! 755: ! 756: push -4(%ebp) / workFree(work0) ! 757: call workFree ! 758: pop %edx ! 759: pop %es / setspace(save) ! 760: pop %esi ! 761: leave ! 762: ret ! 763: ! 764: .globl atrecv ! 765: atrecv: ! 766: enter $0,$4 / reserve 4 bytes (1 int) of local storage ! 767: push %esi ! 768: push %es ! 769: call workAlloc / get a temp virt page ! 770: movl %eax,-4(%ebp) / this is "work0" - a click number ! 771: ! 772: movw $SEG_386_KD,%ax ! 773: movw %ax,%es / save = setspace(SEG_386_KD) ! 774: ! 775: cld ! 776: mov 20(%esp),%eax ! 777: shr $BPCSHIFT,%eax ! 778: mov sysmem,%edx ! 779: leal (%edx,%eax,4),%esi / base = sysmem.u.pbase + btocrd(va) ! 780: ! 781: lodsl / ptable1_V[WORK1] = *base++ | SEG_SRW ! 782: or $SEG_SRW,%eax ! 783: movl -4(%ebp),%edx / work0 ! 784: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 785: ! 786: lodsl / ptable1_V[WORK1] = *base++ | SEG_SRW ! 787: or $SEG_SRW,%eax ! 788: inc %edx / work1 ! 789: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 790: ! 791: MMUUPD ! 792: ! 793: mov 20(%esp),%esi / va = ctob(WORK0) + (va & (NBPC-1)) ! 794: and $NBPC-1,%esi ! 795: movl -4(%ebp),%edx / work0 ! 796: shl $BPCSHIFT,%edx / ctob(work0) ! 797: add %edx,%esi ! 798: ! 799: mov $256, %ecx / copy one disk block ! 800: mov $0x1F0, %edx ! 801: ! 802: xchg %esi,%edi ! 803: rep / Value of the ECX register is not ! 804: / insw (%dx) / updated correctly ! 805: insw ! 806: xchg %esi,%edi ! 807: ! 808: MMUUPD ! 809: ! 810: push -4(%ebp) / workFree(work0) ! 811: call workFree ! 812: pop %edx ! 813: pop %es / setspace(save) ! 814: pop %esi ! 815: leave ! 816: ret ! 817: ! 818: /////// ! 819: ! 820: / This dummy routine is put in vector ! 821: / table slots that are unused. All it does is ! 822: / return to the caller. ! 823: ! 824: /////// ! 825: ! 826: vret: ret ! 827: ! 828: / mmuupd() uses a call gate. ! 829: mmuupd: ! 830: pushf ! 831: cli ! 832: lcall $SEG_MMUUPD,$0 / gates to mmuupdfR0 ! 833: popf ! 834: ret ! 835: ! 836: / Ring 0 far mmu update. Called via a gate. Uses %eax. ! 837: / Want interrupts off when we arrive since the interrupt gates ! 838: / lead into Ring 1. ! 839: mmuupdfR0: ! 840: mov $PTABLE0_P<<BPCSHIFT,%eax ! 841: mov %eax,%cr3 ! 842: lret ! 843: ! 844: / Ring 0 near mmu update. Called from ring 0 startup. Uses %eax. ! 845: mmuupdnR0: ! 846: mov $PTABLE0_P<<BPCSHIFT,%eax ! 847: mov %eax,%cr3 ! 848: ret ! 849: ! 850: /////// ! 851: / Get cs selector - return 0 if in kernel, CS if not in kernel. ! 852: / This version is for resident drivers. ! 853: / There is a different version (cs_self.s) for loadable drivers. ! 854: / int cs_sel(); ! 855: /////// ! 856: ! 857: cs_sel: ! 858: sub %eax, %eax ! 859: ret ! 860: ! 861: / load the 'alternate address space register' (es) ! 862: / with the segment reference passed as an argument. ! 863: ! 864: / The value returned is the old value of the 'es' register ! 865: ! 866: setspace: ! 867: movl %esp,%edx ! 868: sub %eax,%eax ! 869: movw %es,%ax ! 870: movl 4(%edx),%edx ! 871: movw %dx,%es ! 872: ret ! 873: ! 874: ///////////////////////// ! 875: / ! 876: / From __xtrap_on__ to __xtrap_off__, GP fault and page fault will not ! 877: / cause panic. Normally, these two traps coming from kernel text result ! 878: / in panic. ! 879: / ! 880: ///////////////////////// ! 881: .globl __xtrap_on__ ! 882: .globl __xtrap_break__ ! 883: .globl __xtrap_off__ ! 884: __xtrap_on__: ! 885: ! 886: /////// ! 887: ! 888: / Fetch a short from the user's data space. ! 889: / Coherent 386 fetches a 16 bit short ! 890: ! 891: / getusd(u) ! 892: / char *u; ! 893: ! 894: /////// ! 895: ! 896: getusd: ! 897: call start_copy ! 898: mov 4(%edx),%ecx ! 899: sub %eax,%eax ! 900: movw %es:(%ecx),%ax ! 901: jmp end_copy ! 902: ! 903: /////// ! 904: ! 905: / Fetch a word from the user's data space. ! 906: / Coherent 386 fetches a 32 bit word ! 907: ! 908: / getuwd(u) ! 909: / char *u; ! 910: ! 911: /////// ! 912: ! 913: getuwd: ! 914: getupd: ! 915: call start_copy ! 916: mov 4(%edx),%ecx ! 917: mov %es:(%ecx),%eax ! 918: jmp end_copy ! 919: ! 920: /////// ! 921: ! 922: / Fetch a byte from the user's data space. ! 923: ! 924: / getubd(u) ! 925: / char *u; ! 926: ! 927: /////// ! 928: ! 929: getubd: ! 930: call start_copy ! 931: mov 4(%edx),%ecx ! 932: sub %eax,%eax ! 933: movb %es:(%ecx),%al ! 934: jmp end_copy ! 935: ! 936: /////// ! 937: ! 938: / Store a short into the user's data space. ! 939: / Coherent 386 stores a 16 bit short ! 940: ! 941: / putusd(u, w) ! 942: / char *u; ! 943: / int w; ! 944: ! 945: /////// ! 946: ! 947: putusd: ! 948: call start_copy ! 949: mov 8(%edx),%eax ! 950: mov 4(%edx),%ecx / eax ! 951: movw %ax,%es:(%ecx) ! 952: jmp end_copy ! 953: ! 954: /////// ! 955: ! 956: / Store a word into the user's data space. ! 957: / Coherent 386 stores a 32 bit word ! 958: ! 959: / putuwd(u, w) ! 960: / char *u; ! 961: / int w; ! 962: ! 963: /////// ! 964: ! 965: putuwi: ! 966: putuwd: ! 967: call start_copy ! 968: mov 8(%edx),%eax ! 969: mov 4(%edx),%ecx / eax ! 970: mov %eax,%es:(%ecx) ! 971: jmp end_copy ! 972: ! 973: /////// ! 974: ! 975: / Store a byte into the user's data space. ! 976: ! 977: / putubd(u, w) ! 978: / char *u; ! 979: / int w; ! 980: ! 981: /////// ! 982: ! 983: putubd: ! 984: call start_copy ! 985: mov 8(%edx),%eax / get data ! 986: mov 4(%edx),%ecx / get addr ! 987: movb %al,%es:(%ecx) ! 988: jmp end_copy ! 989: ! 990: /////// ! 991: ! 992: / Read a byte from a selector and offset. ! 993: ! 994: / selkcopy(sel, off) ! 995: / unsigned long sel; ! 996: / unsigned long off; ! 997: ! 998: /////// ! 999: .globl selkcopy ! 1000: selkcopy: ! 1001: call start_copy ! 1002: push %es ! 1003: sub %eax,%eax ! 1004: mov 4(%edx), %es ! 1005: mov 8(%edx), %ecx ! 1006: movb %es:(%ecx), %al ! 1007: pop %es ! 1008: jmp end_copy ! 1009: ! 1010: / startup routine for 1-element (byte/word) move ! 1011: ! 1012: / Block transfer "n" bytes from location ! 1013: / "k" in the system map to location "u" in the ! 1014: / user's data space. Return the number of bytes ! 1015: / transferred. ! 1016: ! 1017: / kucopy(k, u, n) ! 1018: / char *k; ! 1019: / char *u; ! 1020: / int n; ! 1021: ! 1022: /////// ! 1023: ! 1024: / .globl udat ! 1025: kucopy: ! 1026: / mov 8(%esp),%eax / verify user address ! 1027: / push %eax ! 1028: / call udat ! 1029: / cmp $0,%eax ! 1030: / pop %eax ! 1031: / jne xx00 ! 1032: / ret ! 1033: /xx00: ! 1034: ! 1035: call start_copy ! 1036: ! 1037: movl 4(%edx),%esi / esi ! 1038: movl 8(%edx),%edi / edi ! 1039: ! 1040: mov 12(%edx),%ecx ! 1041: sar $2,%ecx ! 1042: je loc6 ! 1043: ! 1044: rep ! 1045: movsl ! 1046: ! 1047: loc6: ! 1048: mov 12(%edx),%ecx ! 1049: andl $3,%ecx ! 1050: je loc7 ! 1051: ! 1052: rep ! 1053: movsb ! 1054: ! 1055: loc7: ! 1056: mov 12(%edx),%eax ! 1057: jmp end_copy ! 1058: ! 1059: /////// ! 1060: ! 1061: / Block copy "n" bytes from location "u" in ! 1062: / the user data space to location "k" in the system ! 1063: / data space. Return the actual number of bytes ! 1064: / moved. ! 1065: ! 1066: / ukcopy(u, k, n) ! 1067: / char *u; ! 1068: / char *k; ! 1069: / int n; ! 1070: ! 1071: /////// ! 1072: ! 1073: ukcopy: ! 1074: call start_copy ! 1075: ! 1076: mov 4(%edx),%esi / esi ! 1077: mov 8(%edx),%edi / edi ! 1078: mov 12(%edx),%ecx ! 1079: ! 1080: push %ds / exchange ds,es ! 1081: movw %es,%ax / don't assume ss=ds ! 1082: movw %ax,%ds ! 1083: pop %es ! 1084: ! 1085: sar $2,%ecx ! 1086: je loc8 ! 1087: ! 1088: rep ! 1089: movsl ! 1090: ! 1091: loc8: mov %ss:12(%edx),%ecx ! 1092: andl $3,%ecx ! 1093: je loc9 ! 1094: ! 1095: rep ! 1096: movsb ! 1097: ! 1098: loc9: mov %ss:12(%edx),%eax ! 1099: jmp end_copy / Return ! 1100: ! 1101: //////// ! 1102: / ! 1103: / Block copy "n" bytes from far location "src" in ! 1104: / an arbitrary (but valid) to location "dst" in ! 1105: / data space. Return the actual number of bytes ! 1106: / moved. ! 1107: / ! 1108: / ffcopy(src, dst, n) ! 1109: / char far *src; ! 1110: / char far *dst; ! 1111: / int n; ! 1112: / ! 1113: //////// ! 1114: .globl ffcopy ! 1115: ffcopy: ! 1116: call start_copy ! 1117: ! 1118: mov 4(%edx),%esi / esi ! 1119: mov 8(%edx),%ebx / ds ! 1120: mov 12(%edx),%edi / edi ! 1121: mov 16(%edx),%eax / es ! 1122: mov 20(%edx),%ecx ! 1123: ! 1124: movw %ax,%es / now load segment regs ! 1125: movw %bx,%ds ! 1126: ! 1127: sar $2,%ecx ! 1128: je ff01 ! 1129: ! 1130: rep ! 1131: movsl ! 1132: ! 1133: ff01: mov %ss:20(%edx),%ecx ! 1134: andl $3,%ecx ! 1135: je ff01 ! 1136: ! 1137: rep ! 1138: movsb ! 1139: ! 1140: ff02: mov %ss:20(%edx),%eax ! 1141: jmp end_copy / Return ! 1142: ! 1143: //////// ! 1144: / ! 1145: / Read a byte from a selector and offset. ! 1146: / ! 1147: / ffbyte(off, sel) ! 1148: / unsigned long sel; ! 1149: / unsigned long off; ! 1150: / ! 1151: //////// ! 1152: .globl ffbyte ! 1153: ffbyte: ! 1154: call start_copy ! 1155: push %es ! 1156: sub %eax,%eax ! 1157: mov 4(%edx), %ecx ! 1158: mov 8(%edx), %es ! 1159: movb %es:(%ecx), %al ! 1160: pop %es ! 1161: jmp end_copy ! 1162: ! 1163: //////// ! 1164: / ! 1165: / write a byte using a selector and offset. ! 1166: / ! 1167: / sfbyte(off, sel, byte) ! 1168: / unsigned long sel; ! 1169: / unsigned long off; ! 1170: / int byte; ! 1171: / ! 1172: //////// ! 1173: .globl sfbyte ! 1174: sfbyte: ! 1175: call start_copy ! 1176: push %es ! 1177: mov 4(%edx), %ecx ! 1178: mov 8(%edx), %es ! 1179: mov 12(%edx), %eax ! 1180: movb %al, %es:(%ecx) ! 1181: pop %es ! 1182: jmp end_copy ! 1183: ! 1184: //////// ! 1185: / ! 1186: / Read a word from a selector and offset. ! 1187: / ! 1188: / ffword(off, sel) ! 1189: / unsigned long sel; ! 1190: / unsigned long off; ! 1191: / ! 1192: //////// ! 1193: .globl ffword ! 1194: ffword: ! 1195: call start_copy ! 1196: push %es ! 1197: sub %eax,%eax ! 1198: mov 4(%edx), %ecx ! 1199: mov 8(%edx), %es ! 1200: movw %es:(%ecx), %ax ! 1201: pop %es ! 1202: jmp end_copy ! 1203: ! 1204: //////// ! 1205: / ! 1206: / write a word using a selector and offset. ! 1207: / ! 1208: / sfword(off, sel, word) ! 1209: / unsigned long sel; ! 1210: / unsigned long off; ! 1211: / int word; ! 1212: / ! 1213: //////// ! 1214: .globl sfword ! 1215: sfword: ! 1216: call start_copy ! 1217: push %es ! 1218: mov 4(%edx), %ecx ! 1219: mov 8(%edx), %es ! 1220: mov 12(%edx), %eax ! 1221: movw %ax, %es:(%ecx) ! 1222: pop %es ! 1223: jmp end_copy ! 1224: ! 1225: / startup routine for n-element copy ! 1226: ! 1227: start_copy: ! 1228: pop %eax ! 1229: movl %esp,%edx ! 1230: push %esi ! 1231: push %edi ! 1232: push %ds ! 1233: push %es ! 1234: / lidt %cs:bdtmap ! 1235: ijmp %eax ! 1236: ! 1237: /////// ! 1238: ! 1239: / The n-element copy routines jump here ! 1240: / with the stack untouched, if they detect ! 1241: / a bounds error on a user address. ! 1242: ! 1243: /////// ! 1244: __xtrap_break__: ! 1245: ! 1246: / add $16,%esp / pop error code, IP, CS, PSW ! 1247: / movb $EFAULT,%ss:u+U_ERROR / Bad parameter error ! 1248: subl %eax,%eax / Return 0 to indicate error condition. ! 1249: ! 1250: / cleanup routine for n-byte copy ! 1251: ! 1252: end_copy: ! 1253: / lidt %cs:idtmap ! 1254: pop %es ! 1255: pop %ds ! 1256: pop %edi ! 1257: pop %esi ! 1258: ret / Return ! 1259: ! 1260: __xtrap_off__: / See __xtrap_on__ above. ! 1261: ! 1262: / the following four routines are used by [386/fakedma.c] ! 1263: / and will disappear when a 386 assembler implementation ! 1264: / is available ! 1265: ! 1266: / clearseg_b(nbytes, vaddr_t p, long fill) (byte clear) ! 1267: / clearseg_d(nbytes, vaddr_t p, long fill) (double word clear) ! 1268: ! 1269: ! 1270: clearseg_b: / setspace in caller ! 1271: mov %esp,%edx ! 1272: push %edi ! 1273: push %es ! 1274: ! 1275: mov 8(%edx),%edi ! 1276: mov $SEG_386_KD,%eax ! 1277: movw %ax,%es ! 1278: mov 12(%edx),%eax ! 1279: mov 4(%edx),%ecx ! 1280: ! 1281: cld ! 1282: rep ! 1283: stosb ! 1284: ! 1285: pop %es ! 1286: pop %edi ! 1287: ret ! 1288: ! 1289: clearseg_d: / setspace in caller ! 1290: mov %esp,%edx ! 1291: push %edi ! 1292: push %es ! 1293: ! 1294: mov 8(%edx),%edi ! 1295: mov $SEG_386_KD,%eax ! 1296: movw %ax,%es ! 1297: mov 12(%edx),%eax / mov eax,2(dx) ! 1298: mov 4(%edx),%ecx ! 1299: sar $2,%ecx / char to long ! 1300: ! 1301: cld ! 1302: rep ! 1303: stosl ! 1304: ! 1305: pop %es ! 1306: pop %edi ! 1307: ret ! 1308: ! 1309: / copyseg_b(nbytes, p, q) (byte copy) ! 1310: / copyseg_d(nbytes, p, q) (double word copy) ! 1311: ! 1312: / copy the user page @ virtual address "p" to virtual address "q" ! 1313: ! 1314: copyseg_d: / setspace in caller ! 1315: movl %esp,%edx ! 1316: push %esi ! 1317: push %edi ! 1318: ! 1319: mov 8(%edx),%esi ! 1320: mov 12(%edx),%edi ! 1321: mov 4(%edx),%ecx ! 1322: sar $2,%ecx ! 1323: ! 1324: cld ! 1325: rep ! 1326: movsl ! 1327: ! 1328: pop %edi ! 1329: pop %esi ! 1330: ret ! 1331: ! 1332: copyseg_b: / setspace in caller ! 1333: movl %esp,%edx ! 1334: push %esi ! 1335: push %edi ! 1336: ! 1337: mov 8(%edx),%esi ! 1338: mov 12(%edx),%edi ! 1339: mov 4(%edx),%ecx ! 1340: ! 1341: cld ! 1342: rep ! 1343: movsb ! 1344: ! 1345: pop %edi ! 1346: pop %esi ! 1347: ret ! 1348: ! 1349: ! 1350: / seg2io(long nbytes, vaddr_t p, long port) ! 1351: ! 1352: / nbytes must be a short word multiple ! 1353: ! 1354: seg2io: / setspace in caller ! 1355: movl %esp,%edx ! 1356: push %esi ! 1357: ! 1358: mov 4(%edx),%ecx ! 1359: mov 8(%edx),%esi ! 1360: mov 12(%edx),%edx / mov edx,2(dx) ! 1361: sar $1,%ecx / char to short ! 1362: ! 1363: cld ! 1364: rep ! 1365: outsw ! 1366: ! 1367: pop %esi ! 1368: ret ! 1369: ! 1370: ! 1371: ! 1372: / io2seg(long nbytes, vaddr_t p, long port) ! 1373: ! 1374: / nbytes must be a short word multiple ! 1375: ! 1376: io2seg: / setspace in caller ! 1377: mov %esp,%edx ! 1378: push %edi ! 1379: ! 1380: mov 4(%edx),%ecx ! 1381: mov 8(%edx),%edi ! 1382: mov 12(%edx),%edx / mov edx,2(dx) ! 1383: sar $1,%ecx / char to short ! 1384: ! 1385: cld ! 1386: rep / Value of the ECX register is not ! 1387: / insw (%dx) / updated correctly ! 1388: insw ! 1389: ! 1390: pop %edi ! 1391: ret ! 1392: ! 1393: ! 1394: /////// ! 1395: / ! 1396: / Profile scaling - special multiply routine is used for speed. ! 1397: / ! 1398: / pscale(a,b) is product a*b shifted right 16 bits ! 1399: / ! 1400: /////// ! 1401: ! 1402: .globl pscale ! 1403: pscale: ! 1404: mov 4(%esp),%eax / fetch first argument ! 1405: mull 8(%esp) / unsigned multiply by second argument ! 1406: shrd $16,%edx,%eax / shift 64-bit product right 16 bits ! 1407: ret ! 1408: ! 1409: /////// ! 1410: ! 1411: / Trap an interrupt linkage. ! 1412: / Each of the machine traps has a special little ! 1413: / linkage, that sets up the type code and sends ! 1414: / control off to the common trap processor. Device ! 1415: / interrupts, other than the clock (IR0), are ! 1416: / done here. ! 1417: ! 1418: /////// ! 1419: ! 1420: trap0: ! 1421: push $0x00 / Divide error. ! 1422: call tsave ! 1423: jmp trap ! 1424: ! 1425: / The debug vector is tricky. ! 1426: / ! 1427: / If single stepping user code, the vector must point into Ring 1 code ! 1428: / so that a ptraced child can be synchronized with its parent. ! 1429: / use trap1_usr for this ! 1430: / ! 1431: / If single stepping the kernel, the vector must point into Ring 0 code ! 1432: / so context switches switch out the debug stack frame. ! 1433: / use trap1_ker for this ! 1434: ! 1435: .globl __debug_usr__ ! 1436: trap1_usr: ! 1437: push $0x01 / Single step. ! 1438: call tsave ! 1439: jmp __debug_usr__ ! 1440: ! 1441: .globl __debug_ker__ ! 1442: trap1_ker: ! 1443: push $0x01 / Single step. ! 1444: call tsave0 ! 1445: jmp __debug_ker__ ! 1446: ! 1447: trap2: ! 1448: push $0x02 / Non-maskable interrupt. ! 1449: call tsave ! 1450: jmp trap ! 1451: ! 1452: trap3: ! 1453: push $0x03 / INT 3 (breakpoint). ! 1454: call tsave ! 1455: jmp trap ! 1456: ! 1457: trap4: ! 1458: push $0x04 / Overflow. ! 1459: call tsave ! 1460: jmp trap ! 1461: ! 1462: trap5: ! 1463: push $0x05 / Bound check. ! 1464: call tsave ! 1465: jmp trap ! 1466: ! 1467: trap6: ! 1468: push $0x06 / Invalid opcode. ! 1469: call tsave ! 1470: jmp trap ! 1471: ! 1472: trap7: ! 1473: push $0x07 / Processor Extension not available. ! 1474: call tsave ! 1475: jmp emtrap ! 1476: ! 1477: trap8: ! 1478: / pop %ss:trapcode / Get error code from stack [always 0] ! 1479: add $4,%esp ! 1480: push $0x08 / Double Exception detected ! 1481: call tsave ! 1482: jmp trap ! 1483: ! 1484: trap9: ! 1485: push $0x09 / Processor extension segment overrun ! 1486: call tsave ! 1487: jmp trap ! 1488: ! 1489: trap10: ! 1490: / pop %ss:trapcode / Get error code from stack ! 1491: add $4,%esp ! 1492: push $0x0A / Invalid task state segment ! 1493: call tsave ! 1494: jmp trap ! 1495: ! 1496: trap11: ! 1497: / pop %ss:trapcode / Get error code from stack ! 1498: add $4,%esp ! 1499: push $0x0B / Segment not present ! 1500: call tsave ! 1501: jmp trap ! 1502: ! 1503: trap12: ! 1504: / pop %ss:trapcode / Get error code from stack ! 1505: add $4,%esp ! 1506: push $0x0C / Stack segment overrun or not present ! 1507: call tsave ! 1508: jmp trap ! 1509: ! 1510: trap13: ! 1511: / pop %ss:trapcode / Get error code from stack ! 1512: / add $4,%esp ! 1513: / push $0x0D / General protection ! 1514: call tsave0 ! 1515: jmp gpfault ! 1516: ! 1517: trap14: ! 1518: / pop %ss:trapcode / Get error code from stack ! 1519: / add $4,%esp ! 1520: / push $0x0E / Page Fault ! 1521: call tsave ! 1522: jmp pagefault ! 1523: ! 1524: trap16: ! 1525: push $0x10 / Floating point error ! 1526: call tsave ! 1527: jmp fptrap ! 1528: ! 1529: syc: ! 1530: push $0x22 / Old format system calls. ! 1531: call tsave ! 1532: jmp trap ! 1533: ! 1534: .set FAKE_EFL,12 ! 1535: syc32: ! 1536: push %eax / save %eax ! 1537: pushf / modify current flags ! 1538: pop %eax ! 1539: orw $PSW_VAL,%ax / set IF=1, IOPL=1 (user) on iret ! 1540: mov %eax,FAKE_EFL(%esp) ! 1541: pop %eax / restore %eax ! 1542: push $0x20 / New format system calls. ! 1543: call tsave ! 1544: jmp trap ! 1545: ! 1546: sig32: ! 1547: push %eax ! 1548: pushf ! 1549: pop %eax ! 1550: orw $PSW_VAL,%ax ! 1551: mov %eax,FAKE_EFL(%esp) ! 1552: pop %eax ! 1553: push $0x20 / New format signal return. ! 1554: call tsave ! 1555: jmp msigend ! 1556: ! 1557: ran: ! 1558: push $0x21 / Random trap. ! 1559: call tsave ! 1560: jmp trap ! 1561: ! 1562: dev1: ! 1563: push $0x0140 / Device 1: keyboard ! 1564: call tsave ! 1565: icall [1<<2]+vecs ! 1566: jmp eoi / Dismiss interrupt ! 1567: ! 1568: / Device 2: mapped into device 9 ! 1569: dev3: ! 1570: push $0x0340 / Device 3: al1 ! 1571: call tsave ! 1572: icall [3<<2]+vecs ! 1573: jmp eoi / Dismiss interrupt ! 1574: ! 1575: dev4: ! 1576: push $0x0440 / Device 4: al0 ! 1577: call tsave ! 1578: icall [4<<2]+vecs ! 1579: jmp eoi / Dismiss interrupt ! 1580: ! 1581: dev5: ! 1582: push $0x0540 / Device 5: hard disk ! 1583: call tsave ! 1584: icall [5<<2]+vecs ! 1585: jmp eoi / Dismiss interrupt ! 1586: ! 1587: dev6: ! 1588: push $0x0640 / Device 6: floppy ! 1589: call tsave ! 1590: icall [6<<2]+vecs ! 1591: jmp eoi / Dismiss interrupt ! 1592: ! 1593: dev7: ! 1594: push $0x0740 / Device 7: lp ! 1595: call tsave ! 1596: icall [7<<2]+vecs ! 1597: jmp eoi / Dismiss interrupt ! 1598: ! 1599: dev8: ! 1600: push $0x0840 / Device 8: ! 1601: call tsave ! 1602: icall [8<<2]+vecs ! 1603: jmp eoi2 / Dismiss interrupt ! 1604: ! 1605: dev9: ! 1606: push $0x0940 / Device 9: ! 1607: call tsave ! 1608: icall [9<<2]+vecs ! 1609: jmp eoi2 / Dismiss interrupt ! 1610: ! 1611: dev10: ! 1612: push $0x0A40 / Device 10: ! 1613: call tsave ! 1614: icall [10<<2]+vecs ! 1615: jmp eoi2 / Dismiss interrupt ! 1616: ! 1617: dev11: ! 1618: push $0x0B40 / Device 11: ! 1619: call tsave ! 1620: icall [11<<2]+vecs ! 1621: jmp eoi2 / Dismiss interrupt ! 1622: ! 1623: dev12: ! 1624: push $0x0C40 / Device 12: ! 1625: call tsave ! 1626: icall [12<<2]+vecs ! 1627: jmp eoi2 / Dismiss interrupt ! 1628: ! 1629: .align 4 ! 1630: dev13: ! 1631: / Used to be coprocessor exception interrupt ! 1632: / Coprocessor err had to be cleared by writing a 0 byte to port 0xF0 ! 1633: / ! 1634: push $0x0D40 / Device 13: ! 1635: call tsave ! 1636: icall [13<<2]+vecs ! 1637: jmp eoi2 / Dismiss interrupt ! 1638: ! 1639: dev14: ! 1640: push $0x0E40 / Device 14: ! 1641: call tsave ! 1642: icall [14<<2]+vecs ! 1643: jmp eoi2 / Dismiss interrupt ! 1644: ! 1645: dev15: ! 1646: push $0x0F40 / Device 15: ! 1647: call tsave ! 1648: icall [15<<2]+vecs ! 1649: jmp eoi2 / Dismiss interrupt ! 1650: ! 1651: /////// ! 1652: ! 1653: / Clock interrupt. ! 1654: ! 1655: /////// ! 1656: ! 1657: clk: ! 1658: push $0x0040 ! 1659: call tsave / Perform trap save. ! 1660: mov X_ERR+12(%esp),%eax / ECS at tick time ! 1661: and $3,%eax / This will be R_USR iff user mode ! 1662: push %eax ! 1663: mov X_ERR+12(%esp),%eax / EIP at tick time ! 1664: push %eax ! 1665: call clock / clock(eip, umode) ! 1666: add $8,%esp / pop arguments. ! 1667: jmp eoi / Dismiss interrupt ! 1668: ! 1669: /////// ! 1670: ! 1671: / This co-routine is called to dismiss an interrupt. ! 1672: / The interrupt code is in X_ERR(%esp) ! 1673: ! 1674: / Control returns to "tsave" ! 1675: ! 1676: /////// ! 1677: ! 1678: .globl eoi2 ! 1679: eoi2: ! 1680: cli ! 1681: movb $0x20,%al / Send a non specific EOI ! 1682: outb $SPIC / to the slave PIC. ! 1683: IODELAY ! 1684: movb $0x0B,%al / OCW3 - read isr ! 1685: outb $SPIC ! 1686: IODELAY ! 1687: / inb $SPIC / in-service register to %eax:8..15 ! 1688: / testb %al,%al ! 1689: / jnz eoi2x / no EOI to master if slave isr nonzero ! 1690: eoi: ! 1691: cli ! 1692: movb $0x20,%al / Send a non specific EOI ! 1693: outb $PIC / to the master PIC. ! 1694: IODELAY ! 1695: eoi2x: ret / Done. ! 1696: ! 1697: /////// ! 1698: ! 1699: / Read the equipment description. Use ! 1700: / the "int 11" interface, so that the IBM ! 1701: / ROM will do all the details. ! 1702: ! 1703: /////// ! 1704: ! 1705: int11: mov %cs:val11,%eax / Ask the ROM ! 1706: ret / to put stuff in AX ! 1707: ! 1708: /////// ! 1709: ! 1710: / Bootstrap. ! 1711: / Called by the keyboard driver on control-alt-del. ! 1712: / Requests the 8042 controller to initiate a processor reset, ! 1713: / which is the only way to terminate protected mode operation. ! 1714: ! 1715: / Reference: IBM-AT Technical Reference Manual, ! 1716: / Real-time Clock/CMOS RAM [Page 1-45] ! 1717: / Keyboard controller [Page 1-40] ! 1718: / Test 3, Page 5-68. ! 1719: ! 1720: /////// ! 1721: ! 1722: boot: ! 1723: cli / Disable interrupts. ! 1724: ! 1725: subl %ecx,%ecx ! 1726: loc12: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 1727: testb $2, %al ! 1728: loopne loc12 ! 1729: IODELAY ! 1730: ! 1731: movb $0xFE,%al / Issue a shutdown command ! 1732: outb $KBCTRL / to the 8042 control port. ! 1733: ! 1734: loc13: hlt / Halt until processor reset occurs. ! 1735: jmp loc13 ! 1736: ! 1737: .globl putchar ! 1738: ! 1739: / Comment in the line below if debugging output is to go to the ! 1740: / printer ! 1741: ! 1742: /putchar: ! 1743: ! 1744: movb 4(%esp),%al ! 1745: cmpb $0xa,%al ! 1746: jne loc18 ! 1747: push $0xd ! 1748: call putchar ! 1749: add $4,%esp ! 1750: loc18: mov $LPSTAT,%edx ! 1751: inb (%dx) ! 1752: testb $IBMNBSY,%al ! 1753: je loc18 ! 1754: ! 1755: mov $LPCSR,%edx ! 1756: movb $SEL+NINIT, %al ! 1757: outb (%dx) ! 1758: ! 1759: mov $LPDATA, %edx ! 1760: movb 4(%esp),%al ! 1761: outb (%dx) ! 1762: ! 1763: mov $LPCSR,%edx ! 1764: movb $SEL+NINIT+STROBE,%al ! 1765: outb (%dx) ! 1766: movb $8, %cl ! 1767: l_1: decb %cl ! 1768: jne l_1 ! 1769: movb $SEL+NINIT, %al ! 1770: outb (%dx) ! 1771: ret ! 1772: ! 1773: / long _canl(l) long l; ! 1774: / This is called by the routines that ! 1775: / transform longs to and from the ! 1776: / canonical formats. ! 1777: ! 1778: _canl: ! 1779: mov 4(%esp),%eax ! 1780: rol $16,%eax ! 1781: ret ! 1782: ! 1783: regcr2: mov %cr2,%eax ! 1784: ret ! 1785: ! 1786: regfp: mov %ebp,%eax ! 1787: ret ! 1788: ! 1789: .align 4 / CPU resets if val11 isn't aligned. ! 1790: val11: .long 0 / Value obtained from int11 [in code]. ! 1791: ! 1792: aicodep: ! 1793: sub %ebx,%ebx ! 1794: sub $aicodep,%ebx ! 1795: lea fn(%ebx),%eax ! 1796: mov %eax,argl(%ebx) ! 1797: lea a1(%ebx),%eax ! 1798: mov %eax,argl+4(%ebx) ! 1799: lea argl+8(%ebx),%eax / No environment ! 1800: push %eax ! 1801: lea argl(%ebx),%eax / Argument list ! 1802: push %eax ! 1803: lea fn(%ebx),%eax / File name ! 1804: push %eax ! 1805: sub $4,%esp / Dummy word for exec ! 1806: movl $59, %eax ! 1807: lcall $0x7,$0 ! 1808: jmp . / Instant page fault if exec failed! ! 1809: .alignoff ! 1810: .align 2 ! 1811: argl: .long 0 / argv[0] = "/etc/init"; ! 1812: .long 0 / argv[1] = ""; ! 1813: .long 0 / argv[2] = NULL; ! 1814: ! 1815: fn: .byte "/etc/init",0 ! 1816: a1: .byte 0 ! 1817: sb: ! 1818: .set aicodes, .-aicodep ! 1819: ! 1820: /////// ! 1821: ! 1822: / Task State Segment - Coherent runs as a single protected mode 386 task. ! 1823: ! 1824: /////// ! 1825: .alignon ! 1826: .align 4 ! 1827: .globl tss_sp0 / Use run-time fixup for tss_sp0 ! 1828: .globl tssIoMap ! 1829: .globl tssIoEnd ! 1830: tss: / Task State Segment. ! 1831: tss_lnk:.long 0 / 0: Back link selector to TSS. ! 1832: tss_sp0:.long ESP0_START / 4: SP for CPL 0. ! 1833: tss_ss0:.long SEG_RNG0_STK / 8: SS for CPL 0. ! 1834: tss_sp1:.long ESP1_START / C: SP for CPL 1. ! 1835: tss_ss1:.long SEG_RNG1_STK / 10: SS for CPL 1. ! 1836: tss_sp2:.long u+NBPC / 14: SP for CPL 2. ! 1837: tss_ss2:.long SEG_386_KD / 18: SS for CPL 2. ! 1838: tss_cr3:.long PTABLE0_P<<BPCSHIFT / 1C: CR3 (PDBR) ! 1839: tss_ip: .long 0 / 20: EIP (Entry point). ! 1840: tss_psw:.long 0 / 24: Flag word. ! 1841: tss_ax: .long 0 / 28: Register AX. ! 1842: tss_cx: .long 0 / 2C: Register CX. ! 1843: tss_dx: .long 0 / 30: Register DX. ! 1844: tss_bx: .long 0 / 34: Register BX. ! 1845: tss_bp: .long 0 / 38: Register BP. ! 1846: tss_sp: .long 0 / 3C: Register SP. ! 1847: tss_si: .long 0 / 40: Register SI. ! 1848: tss_di: .long 0 / 44: Register DI. ! 1849: tss_es: .long 0 / 48: Register ES. ! 1850: tss_cs: .long 0 / 4C: Register CS. ! 1851: tss_ss: .long 0 / 50: Register SS. ! 1852: tss_ds: .long 0 / 54: Register DS. ! 1853: tss_fs: .long 0 / 58: Register FS. ! 1854: tss_gs: .long 0 / 5C: Register GS. ! 1855: tss_ldt:.long SEG_LDT / 60: Task LDT Selector. ! 1856: .long TSS_IOMAP_OFF / 64: T bit & I/O map base ! 1857: / I/O map is part of tss. ! 1858: / Bitmap up to port address TSS_IOMAP_LEN. ! 1859: / Initialize to all 1's, meaning no I/O allowed. ! 1860: / tss + 0x68 = tssIoMap ! 1861: tssIoMap: ! 1862: .long [TSS_IOMAP_LEN .div 32] # -1 ! 1863: tssIoEnd: ! 1864: .long -1 ! 1865: /////// ! 1866: ! 1867: / Data. ! 1868: ! 1869: /////// ! 1870: .data ! 1871: sdata: ! 1872: ! 1873: vecs: .long 16 # vret / Interrupt vector table ! 1874: ! 1875: trapcode:.long 0 ! 1876: ! 1877: .text ! 1878: /////// ! 1879: ! 1880: / i8086 coherent clist hack. ! 1881: ! 1882: /////// ! 1883: ! 1884: /LXXX: .long NCPCL+4 ! 1885: ! 1886: /cltinit: ! 1887: / pushf / s = sphi() ! 1888: / cli ! 1889: / mov NCLIST,%eax ! 1890: / imull LXXX,%eax ! 1891: / addl clistp,%eax ! 1892: / sub %ecx,%ecx ! 1893: / jmp loc32 ! 1894: ! 1895: /loc33: mov %ecx,(%eax) ! 1896: / mov %eax,%ecx ! 1897: /loc32: sub $NCPCL+4, %eax ! 1898: / cmp clistp,%eax ! 1899: / jnb loc33 ! 1900: ! 1901: / mov %ecx,cltfree ! 1902: / call spl ! 1903: / add $0x04,%esp ! 1904: / ret ! 1905: ! 1906: /getq: ! 1907: / push %esi ! 1908: ! 1909: / mov 8(%esp),%edx ! 1910: / sub %ecx,%ecx ! 1911: / cmp %ecx,(%edx) / if (cqp->cq_cc==0) ! 1912: / je loc21 ! 1913: ! 1914: / pushf / s = sphi() ! 1915: / cli ! 1916: / mov 12(%edx),%esi / op = cqp->cq_op [%esi] ! 1917: / mov 16(%edx),%eax / ox = cqp->cq_ox [%eax] ! 1918: / movb 4(%eax,%esi),%cl ! 1919: / push %ecx / save = op->cl_ch[ox] ! 1920: / decl (%edx) / if (--cqp->cq_cc == 0) ! 1921: / je loc23 ! 1922: / inc %eax / ++ox ! 1923: / mov %eax,16(%edx) / cqp->cq_ox = ox ! 1924: / cmp $NCPCL,%eax / if (ox == NCPL) ! 1925: / jne loc24 ! 1926: ! 1927: /loc23: sub %eax,%eax ! 1928: / mov %eax,16(%edx) / cqp->cq_ox = 0 ! 1929: / mov (%esi),%ecx / np = op->cl_fp ! 1930: / mov %ecx,12(%edx) / cqp->cq_op = np ! 1931: / cmp %eax,%ecx / if (np==0) ! 1932: / jne loc25 ! 1933: / mov %eax,4(%edx) / cqp->cq_ip = 0 ! 1934: / mov %eax,8(%edx) / cqp->cq_ix = 0 ! 1935: ! 1936: /loc25: mov cltfree,%ecx ! 1937: / mov %ecx,(%esi) / op->cl_fp = cltfree ! 1938: / mov %esi,cltfree / cltfree = op ! 1939: / cmp %eax,cltwant / if (cltwant) ! 1940: / je loc24 ! 1941: / mov %eax,cltwant / cltwant = 0 ! 1942: / push $cltwant ! 1943: / call wakeup / wakeup(&cltwant) ! 1944: / pop %eax ! 1945: ! 1946: /loc24: pop %esi ! 1947: / call spl / spl(s) ! 1948: / pop %eax ! 1949: / mov %esi,%eax / return save ! 1950: / pop %esi ! 1951: / ret ! 1952: /loc21: ! 1953: / mov $-1,%eax / return -1 ! 1954: / pop %esi ! 1955: / ret ! 1956: ! 1957: /putq: ! 1958: / push %esi ! 1959: / sub %eax,%eax ! 1960: / pushf / s = sphi(); ! 1961: / cli ! 1962: / mov 12(%esp),%edx / ebp = cqp ! 1963: / mov 4(%edx),%esi / ip = cqp->cq_ip [%esi] ! 1964: / mov 8(%edx),%ecx / ix = cqp->cq_ix [%ecx] ! 1965: / cmp %eax,%ecx / if (ix==0) { ! 1966: / jne loc26 ! 1967: / mov cltfree,%esi / ip = cltfree ! 1968: / cmp %eax,%esi / if (ip==0) ! 1969: / je loc27 / goto bad; ! 1970: / mov (%esi),%ecx ! 1971: / mov %ecx,cltfree / cltfree = cltfree->cl_fp ! 1972: / mov %eax,(%esi) / ip->cl_fp = 0 ! 1973: / mov 4(%edx),%ecx / np = cqp->cq_ip ! 1974: / cmp %eax,%ecx / if (np==0) ! 1975: / jne loc29 ! 1976: / mov %esi,12(%edx) / cqp->cq_op = ip ! 1977: / jmp loc30 ! 1978: / / else ! 1979: /loc29: mov %esi,(%ecx) / np->cl_fp = ip ! 1980: ! 1981: /loc30: mov %esi,4(%edx) / cqp->cq_ip = ip ! 1982: / mov %eax,%ecx / ix = 0 ! 1983: / / } ! 1984: ! 1985: /loc26: ! 1986: / movb 16(%esp),%al / ip->cl_ch[ix] = c ! 1987: / movb %al, 4(%esi,%ecx) ! 1988: / inc %ecx / ix++ ! 1989: / cmp $NCPCL,%ecx / if (ix==NCPCL) ! 1990: / jne loc31 ! 1991: / sub %ecx,%ecx / ix = 0 ! 1992: ! 1993: /loc31: mov %ecx,8(%edx) / cqp->cq_ix = ix ! 1994: / incl (%edx) / cqp->cq_cc++ ! 1995: / call spl / spl(s) ! 1996: / add $4,%esp ! 1997: / mov 12(%esp),%eax / return (c) ! 1998: /loc28: ! 1999: / pop %esi ! 2000: / ret ! 2001: /loc27: ! 2002: / call spl / spl(s) ! 2003: / add $4,%esp ! 2004: / mov $-1,%eax / return -1 ! 2005: / jmp loc28 ! 2006: ! 2007: /clrq: ! 2008: / mov 4(%esp),%edx ! 2009: / pushf ! 2010: / cli ! 2011: ! 2012: /loc34: push %edx ! 2013: / call getq ! 2014: / pop %edx ! 2015: / or %eax,%eax ! 2016: / jge loc34 ! 2017: ! 2018: / call spl ! 2019: / pop %eax ! 2020: / ret ! 2021: ! 2022: /loc35: movl $0x01,cltwant ! 2023: / push %eax ! 2024: / push %eax ! 2025: / push $0x0100 ! 2026: / push $cltwant ! 2027: / call sleep ! 2028: / add $16,%esp ! 2029: /waitq: ! 2030: / sub %eax,%eax ! 2031: / cmp %eax,cltfree ! 2032: / jne loc35 ! 2033: / ret ! 2034: ! 2035: /////// ! 2036: ! 2037: / atbsyw() -- wait for AT disk controller to become not busy ! 2038: ! 2039: / Return: 0 = timeout ! 2040: / * = not busy ! 2041: ! 2042: /////// ! 2043: /atbsyw: ! 2044: / mov $0x3FFFF, %ecx ! 2045: / mov ATSREG, %edx ! 2046: /loc16: inb (%dx) ! 2047: / testb $BSY_ST, %al ! 2048: / loopne loc16 ! 2049: / mov %ecx, %eax ! 2050: / ret ! 2051: ! 2052: /////// ! 2053: ! 2054: / AT Hard Disk Assembler Support ! 2055: / atbsyw() - wait while controller is busy ! 2056: / atdrqw() - wait for controller to request data transfer ! 2057: ! 2058: /////// ! 2059: /////// ! 2060: ! 2061: / atdrqw() -- wait for AT disk controller to initiate data request ! 2062: ! 2063: / Return: 0 = timeout ! 2064: / * = data requested ! 2065: ! 2066: /////// ! 2067: ! 2068: /atdrqw: ! 2069: / mov $0x3FFFF, %ecx ! 2070: / mov ATSREG, %edx ! 2071: /loc17: inb (%dx) ! 2072: / testb $DRQ_ST, %al ! 2073: / loope loc17 ! 2074: / mov %ecx, %eax ! 2075: / ret ! 2076: ! 2077: / Read a byte from the CMOS. Takes one argument--the ! 2078: / CMOS address to read from as an int; returns the ! 2079: / value read as a char. ! 2080: / ! 2081: / int read_cmos(int addr); ! 2082: ! 2083: read_cmos: ! 2084: push %esi ! 2085: push %edi ! 2086: movb 12(%esp), %al / Fetch address from stack. ! 2087: outb $CMOSA / Send address to CMOS. ! 2088: IODELAY ! 2089: sub %eax, %eax / Zero out everything we don't want. ! 2090: inb $CMOSD / Get Value from CMOS into al. ! 2091: pop %edi ! 2092: pop %esi ! 2093: ret / Return from read_cmos(). ! 2094: ! 2095: / Write a byte to the CMOS. ! 2096: / ! 2097: / void write_cmos(int addr, int data) ! 2098: ! 2099: write_cmos: ! 2100: push %esi ! 2101: push %edi ! 2102: movb 12(%esp), %al / Fetch address from stack. ! 2103: outb $CMOSA / Send address to CMOS. ! 2104: IODELAY ! 2105: movb 16(%esp), %al / Fetch address from stack. ! 2106: outb $CMOSD / Get Value from CMOS into al. ! 2107: IODELAY ! 2108: pop %edi ! 2109: pop %esi ! 2110: ret / Return from read_cmos(). ! 2111: ! 2112: / Read timer channel 0 into int value. ! 2113: / Clock counts down from 11932 to 0 with each clock tick. ! 2114: .globl read_t0 ! 2115: read_t0: ! 2116: pushfl ! 2117: cli ! 2118: xorl %eax,%eax / Counter latch timer 0 and clear return val ! 2119: outb $PIT+3 ! 2120: IODELAY ! 2121: inb $PIT / low byte of counter latch ! 2122: IODELAY ! 2123: movb %al,%ah ! 2124: inb $PIT / high byte of counter latch ! 2125: IODELAY ! 2126: xchgb %al,%ah ! 2127: popfl ! 2128: ret ! 2129: ! 2130: / return current contents of psw ! 2131: .globl read_psw ! 2132: read_psw: ! 2133: pushfl ! 2134: popl %eax ! 2135: ret ! 2136: ! 2137: / Read master PIC state ! 2138: / return 00:xx:yy:zz 4-byte int value ! 2139: / xx: interrupt mask ! 2140: / yy: isr ! 2141: / zz: irr ! 2142: ! 2143: / .globl mchirp ! 2144: /FOO .macro ch ! 2145: / push ch ! 2146: / call mchirp ! 2147: / add $4,%esp ! 2148: / .endm ! 2149: ! 2150: / .globl rd_m_pic ! 2151: /rd_m_pic: ! 2152: / pushfl ! 2153: / cli ! 2154: / sub %eax,%eax ! 2155: / inb $PICM / interrupt mask to %eax:16..23 ! 2156: / shl $8,%eax ! 2157: / movb $0x0B,%al / OCW3 - read isr ! 2158: / outb $PIC ! 2159: / IODELAY ! 2160: / inb $PIC / in-service register to %eax:8..15 ! 2161: / shl $8,%eax ! 2162: / movb $0x0A,%al / OCW3 - read irr ! 2163: / outb $PIC ! 2164: / IODELAY ! 2165: / inb $PIC / irpt request register to %eax:0..7 ! 2166: / popfl ! 2167: / ret ! 2168: ! 2169: / Read slave PIC state ! 2170: / return 00:xx:yy:zz 4-byte int value ! 2171: / xx: interrupt mask ! 2172: / yy: isr ! 2173: / zz: irr ! 2174: ! 2175: / .globl rd_s_pic ! 2176: /rd_s_pic: ! 2177: / pushfl ! 2178: / cli ! 2179: / sub %eax,%eax ! 2180: / inb $SPICM / interrupt mask to %eax:16..23 ! 2181: / shl $8,%eax ! 2182: / movb $0x0B,%al / OCW3 - read isr ! 2183: / outb $SPIC ! 2184: / IODELAY ! 2185: / inb $SPIC / in-service register to %eax:8..15 ! 2186: / shl $8,%eax ! 2187: / movb $0x0A,%al / OCW3 - read irr ! 2188: / outb $SPIC ! 2189: / IODELAY ! 2190: / inb $SPIC / irpt request register to %eax:0..7 ! 2191: / popfl ! 2192: / ret ! 2193: ! 2194: / return current contents of cr0 ! 2195: .globl read_cr0 ! 2196: read_cr0: ! 2197: movl %cr0,%eax ! 2198: ret ! 2199: ! 2200: / return current contents of cr2 ! 2201: .globl read_cr2 ! 2202: read_cr2: ! 2203: movl %cr2,%eax ! 2204: ret ! 2205: ! 2206: / return current contents of cr3 ! 2207: .globl read_cr3 ! 2208: read_cr3: ! 2209: movl %cr3,%eax ! 2210: ret ! 2211: ! 2212: ///////// ! 2213: / ! 2214: / Debugging support. ! 2215: / ! 2216: ///////// ! 2217: .globl write_dr0 ! 2218: .globl write_dr1 ! 2219: .globl write_dr2 ! 2220: .globl write_dr3 ! 2221: .globl write_dr6 ! 2222: .globl write_dr7 ! 2223: ! 2224: .globl read_dr0 ! 2225: .globl read_dr1 ! 2226: .globl read_dr2 ! 2227: .globl read_dr3 ! 2228: .globl read_dr6 ! 2229: .globl read_dr7 ! 2230: ! 2231: / write arg to dr0 ! 2232: write_dr0: ! 2233: movl 4(%esp),%eax ! 2234: movl %eax,%dr0 ! 2235: ret ! 2236: ! 2237: / write arg to dr1 ! 2238: write_dr1: ! 2239: movl 4(%esp),%eax ! 2240: movl %eax,%dr1 ! 2241: ret ! 2242: ! 2243: / write arg to dr2 ! 2244: write_dr2: ! 2245: movl 4(%esp),%eax ! 2246: movl %eax,%dr2 ! 2247: ret ! 2248: ! 2249: / write arg to dr3 ! 2250: write_dr3: ! 2251: movl 4(%esp),%eax ! 2252: movl %eax,%dr3 ! 2253: ret ! 2254: ! 2255: / write arg to dr6 ! 2256: write_dr6: ! 2257: movl 4(%esp),%eax ! 2258: movl %eax,%dr6 ! 2259: ret ! 2260: ! 2261: / write arg to dr7 ! 2262: write_dr7: ! 2263: movl 4(%esp),%eax ! 2264: movl %eax,%dr7 ! 2265: ret ! 2266: ! 2267: read_dr0: ! 2268: movl %dr0,%eax ! 2269: ret ! 2270: ! 2271: read_dr1: ! 2272: movl %dr1,%eax ! 2273: ret ! 2274: ! 2275: read_dr2: ! 2276: movl %dr2,%eax ! 2277: ret ! 2278: ! 2279: read_dr3: ! 2280: movl %dr3,%eax ! 2281: ret ! 2282: ! 2283: read_dr6: ! 2284: movl %dr6,%eax ! 2285: ret ! 2286: ! 2287: read_dr7: ! 2288: movl %dr7,%eax ! 2289: ret ! 2290: ! 2291: / write to the EM bit of CR0 ! 2292: / this routine is a stub for the ring 0 code ! 2293: / argument is 0 or 1 ! 2294: / ! 2295: / void setEm(int bit) ! 2296: .globl setEm ! 2297: setEm: ! 2298: movl 4(%esp),%eax / fetch argument ! 2299: pushf ! 2300: cli ! 2301: pushl %eax ! 2302: lcall $SEG_SET_EM,$0 / gate to setEmfR0 ! 2303: / setEmfR0 will delete 4 bytes worth of args ! 2304: popf ! 2305: ret ! 2306: ! 2307: / Ring 0 write to CR0 EM bit. Called via a gate. ! 2308: / Want interrupts off when we arrive since the interrupt gates ! 2309: / lead into Ring 1. ! 2310: setEmfR0: ! 2311: movb 8(%esp),%cl / fetch argument ! 2312: ! 2313: cmpb $0,%cl ! 2314: movl %cr0,%eax ! 2315: jz se00 ! 2316: orb $4,%al / set EM bit ! 2317: andb $0xDF,%al / clear NE bit ! 2318: jmp se01 ! 2319: se00: ! 2320: andb $0xFB,%al / clear EM bit ! 2321: orb $0x20,%al / set NE bit ! 2322: se01: ! 2323: mov %eax,%cr0 ! 2324: / make 4-byte arg list disappear ! 2325: lret $4 ! 2326: ! 2327: / return nonzero if paging is turned on ! 2328: .globl paging ! 2329: paging: ! 2330: movl (%esp),%eax / fetch return address ! 2331: cmpl $[SBASE<<BPCSHIFT],%eax / is it >= unsigned FFC0_0000? ! 2332: jae pagingMaybe ! 2333: xorl %eax,%eax / if not, no paging ! 2334: ret ! 2335: pagingMaybe: ! 2336: movw %cs,%ax / if return addr high, cs is a selector ! 2337: cmpw $0x58,%ax / selectors 58-6F are nonpaging ! 2338: jb pagingYes ! 2339: cmpw $0x6F,%ax / selectors 58-6F are nonpaging ! 2340: ja pagingYes ! 2341: xorl %eax,%eax / no paging ! 2342: ret ! 2343: pagingYes: ! 2344: movl $1,%eax ! 2345: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.