Annotation of coherent/b/kernel/i386/as.s, revision 1.1.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.