Annotation of coherent/b/kernel/i386/as.s, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.