btx.S revision 164114
1128710Sru/* 2128710Sru * Copyright (c) 1998 Robert Nordier 3128710Sru * All rights reserved. 4128710Sru * 5128710Sru * Redistribution and use in source and binary forms are freely 6128710Sru * permitted provided that the above copyright notice and this 7128710Sru * paragraph and the following disclaimer are duplicated in all 8128710Sru * such forms. 9128710Sru * 10128710Sru * This software is provided "AS IS" and without any express or 11128710Sru * implied warranties, including, without limitation, the implied 12128710Sru * warranties of merchantability and fitness for a particular 13128710Sru * purpose. 14128710Sru * 15128710Sru * $FreeBSD: head/sys/boot/pc98/btx/btx/btx.S 164114 2006-11-09 08:05:51Z nyan $ 16128710Sru */ 1743561Skato 18128710Sru/* 19128710Sru * Memory layout. 20128710Sru */ 2143561Skato .set MEM_BTX,0x1000 # Start of BTX memory 2243561Skato .set MEM_ESP0,0x1800 # Supervisor stack 2343561Skato .set MEM_BUF,0x1800 # Scratch buffer 2443561Skato .set MEM_ESP1,0x1e00 # Link stack 2543561Skato .set MEM_IDT,0x1e00 # IDT 2643561Skato .set MEM_TSS,0x1f98 # TSS 2743561Skato .set MEM_MAP,0x2000 # I/O bit map 2843561Skato .set MEM_DIR,0x4000 # Page directory 2943561Skato .set MEM_TBL,0x5000 # Page tables 3043561Skato .set MEM_ORG,0x9000 # BTX code 3143561Skato .set MEM_USR,0xa000 # Start of user memory 32128710Sru/* 33128710Sru * Paging control. 34128710Sru */ 3543561Skato .set PAG_SIZ,0x1000 # Page size 3643561Skato .set PAG_CNT,0x1000 # Pages to map 37128710Sru/* 38128710Sru * Segment selectors. 39128710Sru */ 4043561Skato .set SEL_SCODE,0x8 # Supervisor code 4143561Skato .set SEL_SDATA,0x10 # Supervisor data 4243561Skato .set SEL_RCODE,0x18 # Real mode code 4343561Skato .set SEL_RDATA,0x20 # Real mode data 4443561Skato .set SEL_UCODE,0x28|3 # User code 4543561Skato .set SEL_UDATA,0x30|3 # User data 4643561Skato .set SEL_TSS,0x38 # TSS 47128710Sru/* 48128710Sru * Task state segment fields. 49128710Sru */ 5043561Skato .set TSS_ESP0,0x4 # PL 0 ESP 5143561Skato .set TSS_SS0,0x8 # PL 0 SS 5243561Skato .set TSS_ESP1,0xc # PL 1 ESP 5343561Skato .set TSS_MAP,0x66 # I/O bit map base 54128710Sru/* 55128710Sru * System calls. 56128710Sru */ 5743561Skato .set SYS_EXIT,0x0 # Exit 5843561Skato .set SYS_EXEC,0x1 # Exec 59128710Sru/* 60128710Sru * V86 constants. 61128710Sru */ 6243561Skato .set V86_FLG,0x208eff # V86 flag mask 6343561Skato .set V86_STK,0x400 # V86 stack allowance 64128710Sru/* 65128710Sru * Dump format control bytes. 66128710Sru */ 6743561Skato .set DMP_X16,0x1 # Word 6843561Skato .set DMP_X32,0x2 # Long 6943561Skato .set DMP_MEM,0x4 # Memory 7043561Skato .set DMP_EOL,0x8 # End of line 71128710Sru/* 72128710Sru * Screen defaults and assumptions. 73128710Sru */ 7443561Skato .set SCR_MAT,0xe1 # Mode/attribute 7543561Skato .set SCR_COL,0x50 # Columns per row 7643561Skato .set SCR_ROW,0x19 # Rows per screen 77128710Sru/* 78128710Sru * BIOS Data Area locations. 79128710Sru */ 8058871Skato .set BDA_MEM,0x501 # Free memory 8158871Skato .set BDA_KEYFLAGS,0x53a # Keyboard shift-state flags 8258871Skato .set BDA_POS,0x53e # Cursor position 83128710Sru/* 84128710Sru * Derivations, for brevity. 85128710Sru */ 8643561Skato .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0 8743561Skato .set _ESP1H,MEM_ESP1>>0x8 # Byte 1 of ESP1 8843561Skato .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base 8943561Skato .set _TSSLM,MEM_DIR-MEM_TSS-1 # TSS limit 9043561Skato .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit 91128710Sru/* 92128710Sru * Code segment. 93128710Sru */ 9443561Skato .globl start 9561064Snyan .code16 9643561Skatostart: # Start of code 97128710Sru/* 98128710Sru * BTX header. 99128710Sru */ 10043561Skatobtx_hdr: .byte 0xeb # Machine ID 10143561Skato .byte 0xe # Header size 10243561Skato .ascii "BTX" # Magic 10343561Skato .byte 0x1 # Major version 10444368Skato .byte 0x1 # Minor version 10568358Snyan .byte BTX_FLAGS # Flags 10643561Skato .word PAG_CNT-MEM_ORG>>0xc # Paging control 10743561Skato .word break-start # Text size 10843561Skato .long 0x0 # Entry address 109128710Sru/* 110128710Sru * Initialization routine. 111128710Sru */ 11243561Skatoinit: cli # Disable interrupts 11361064Snyan xor %ax,%ax # Zero/segment 11461064Snyan mov %ax,%ss # Set up 11561064Snyan mov $MEM_ESP0,%sp # stack 11661064Snyan mov %ax,%es # Address 11761064Snyan mov %ax,%ds # data 11861064Snyan pushl $0x2 # Clear 11961064Snyan popfl # flags 120128710Sru/* 121128710Sru * Initialize memory. 122128710Sru */ 12361064Snyan mov $MEM_IDT,%di # Memory to initialize 12461064Snyan mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero 12561064Snyan push %di # Save 12643561Skato rep # Zero-fill 12761064Snyan stosw # memory 12861064Snyan pop %di # Restore 129128710Sru/* 130128710Sru * Create IDT. 131128710Sru */ 13261064Snyan mov $idtctl,%si # Control string 13343561Skatoinit.1: lodsb # Get entry 13461064Snyan cbw # count 13561064Snyan xchg %ax,%cx # as word 13661064Snyan jcxz init.4 # If done 13743561Skato lodsb # Get segment 13861064Snyan xchg %ax,%dx # P:DPL:type 13961064Snyan lodsw # Get control 14061064Snyan xchg %ax,%bx # set 14161064Snyan lodsw # Get handler offset 14261064Snyan mov $SEL_SCODE,%dh # Segment selector 14361064Snyaninit.2: shr %bx # Handle this int? 14443561Skato jnc init.3 # No 14561064Snyan mov %ax,(%di) # Set handler offset 14661064Snyan mov %dh,0x2(%di) # and selector 14761064Snyan mov %dl,0x5(%di) # Set P:DPL:type 14861064Snyan add $0x4,%ax # Next handler 14961064Snyaninit.3: lea 0x8(%di),%di # Next entry 15043561Skato loop init.2 # Till set done 15143561Skato jmp init.1 # Continue 152128710Sru/* 153128710Sru * Initialize TSS. 154128710Sru */ 15561064Snyaninit.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 15661064Snyan movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 15761064Snyan movb $_ESP1H,TSS_ESP1+1(%di) # Set ESP1 15861064Snyan movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base 159125780Snyan#ifdef PAGING 160128710Sru/* 161128710Sru * Create page directory. 162128710Sru */ 16361064Snyan xor %edx,%edx # Page 16461064Snyan mov $PAG_SIZ>>0x8,%dh # size 16561064Snyan xor %eax,%eax # Zero 16661064Snyan mov $MEM_DIR,%di # Page directory 16761064Snyan mov $PAG_CNT>>0xa,%cl # Entries 16861064Snyan mov $MEM_TBL|0x7,%ax # First entry 16961064Snyaninit.5: stosl # Write entry 17061064Snyan add %dx,%ax # To next 17143561Skato loop init.5 # Till done 172128710Sru/* 173128710Sru * Create page tables. 174128710Sru */ 17561064Snyan mov $MEM_TBL,%di # Page table 17661064Snyan mov $PAG_CNT>>0x8,%ch # Entries 17761064Snyan xor %ax,%ax # Start address 17861064Snyaninit.6: mov $0x7,%al # Set U:W:P flags 17961064Snyan cmp btx_hdr+0x8,%cx # Standard user page? 18043561Skato jb init.7 # Yes 18161064Snyan cmp $PAG_CNT-MEM_BTX>>0xc,%cx # BTX memory? 18243561Skato jae init.7 # No or first page 18361064Snyan and $~0x2,%al # Clear W flag 18461064Snyan cmp $PAG_CNT-MEM_USR>>0xc,%cx # User page zero? 18543561Skato jne init.7 # No 18661064Snyan testb $0x80,btx_hdr+0x7 # Unmap it? 18743561Skato jz init.7 # No 18861064Snyan and $~0x1,%al # Clear P flag 18961064Snyaninit.7: stosl # Set entry 19061064Snyan add %edx,%eax # Next address 19143561Skato loop init.6 # Till done 192125780Snyan#endif 193128710Sru/* 194128710Sru * Bring up the system. 195128710Sru */ 19661064Snyan mov $0x2820,%bx # Set protected mode 19761064Snyan callw setpic # IRQ offsets 19861064Snyan lidt idtdesc # Set IDT 199125780Snyan#ifdef PAGING 20061064Snyan xor %eax,%eax # Set base 20161064Snyan mov $MEM_DIR>>0x8,%ah # of page 20261064Snyan mov %eax,%cr3 # directory 203125780Snyan#endif 20461064Snyan lgdt gdtdesc # Set GDT 20561064Snyan mov %cr0,%eax # Switch to protected 206125780Snyan#ifdef PAGING 20761064Snyan or $0x80000001,%eax # mode and enable paging 208125780Snyan#else 209164114Snyan inc %ax # mode 210125780Snyan#endif 211128710Sru mov %eax,%cr0 # 21261064Snyan ljmp $SEL_SCODE,$init.8 # To 32-bit code 21361064Snyan .code32 21443561Skatoinit.8: xorl %ecx,%ecx # Zero 21543561Skato movb $SEL_SDATA,%cl # To 32-bit 21661064Snyan movw %cx,%ss # stack 217128710Sru/* 218128710Sru * Launch user task. 219128710Sru */ 22043561Skato movb $SEL_TSS,%cl # Set task 22161064Snyan ltr %cx # register 22243561Skato movl $MEM_USR,%edx # User base address 22343561Skato movzwl %ss:BDA_MEM,%eax # Get free memory 22443561Skato andl $0x7,%eax 22543561Skato incl %eax 22643561Skato shll $0x11,%eax # To bytes 22743561Skato subl $0x1000,%eax # Less arg space 22843561Skato subl %edx,%eax # Less base 22943561Skato movb $SEL_UDATA,%cl # User data selector 23043561Skato pushl %ecx # Set SS 23143561Skato pushl %eax # Set ESP 23261064Snyan push $0x202 # Set flags (IF set) 23361064Snyan push $SEL_UCODE # Set CS 23443561Skato pushl btx_hdr+0xc # Set EIP 23543561Skato pushl %ecx # Set GS 23643561Skato pushl %ecx # Set FS 23743561Skato pushl %ecx # Set DS 23843561Skato pushl %ecx # Set ES 23943561Skato pushl %edx # Set EAX 24043561Skato movb $0x7,%cl # Set remaining 24161064Snyaninit.9: push $0x0 # general 24243561Skato loop init.9 # registers 243125780Snyan#ifdef BTX_SERIAL 24486497Snyan call sio_init # setup the serial console 245125780Snyan#endif 24643561Skato popa # and initialize 24743561Skato popl %es # Initialize 24843561Skato popl %ds # user 24943561Skato popl %fs # segment 25043561Skato popl %gs # registers 25143561Skato iret # To user mode 252128710Sru/* 253128710Sru * Exit routine. 254128710Sru */ 25543561Skatoexit: cli # Disable interrupts 25643561Skato movl $MEM_ESP0,%esp # Clear stack 257128710Sru/* 258128710Sru * Turn off paging. 259128710Sru */ 26043561Skato movl %cr0,%eax # Get CR0 26143561Skato andl $~0x80000000,%eax # Disable 26243561Skato movl %eax,%cr0 # paging 26343561Skato xorl %ecx,%ecx # Zero 26443561Skato movl %ecx,%cr3 # Flush TLB 265128710Sru/* 266128710Sru * Restore the GDT in case we caught a kernel trap. 267128710Sru */ 26876927Snyan lgdt gdtdesc # Set GDT 269128710Sru/* 270128710Sru * To 16 bits. 271128710Sru */ 27261064Snyan ljmpw $SEL_RCODE,$exit.1 # Reload CS 27361064Snyan .code16 27461064Snyanexit.1: mov $SEL_RDATA,%cl # 16-bit selector 27561064Snyan mov %cx,%ss # Reload SS 27661064Snyan mov %cx,%ds # Load 27761064Snyan mov %cx,%es # remaining 27861064Snyan mov %cx,%fs # segment 27961064Snyan mov %cx,%gs # registers 280128710Sru/* 281128710Sru * To real-address mode. 282128710Sru */ 28361064Snyan dec %ax # Switch to 28461064Snyan mov %eax,%cr0 # real mode 28561064Snyan ljmp $0x0,$exit.2 # Reload CS 28661064Snyanexit.2: xor %ax,%ax # Real mode segment 28761064Snyan mov %ax,%ss # Reload SS 28861064Snyan mov %ax,%ds # Address data 28961064Snyan mov $0x1008,%bx # Set real mode 29061064Snyan callw setpic # IRQ offsets 29161064Snyan lidt ivtdesc # Set IVT 292128710Sru/* 293128710Sru * Reboot or await reset. 294128710Sru */ 29543561Skato sti # Enable interrupts 29661064Snyan testb $0x1,btx_hdr+0x7 # Reboot? 29743561Skatoexit.3: jz exit.3 # No 29843561Skato movb $0xa0,%al 29943561Skato outb %al,$0x35 30043561Skato movb 0,%al 30143561Skato outb %al,$0xf0 30243561Skatoexit.4: jmp exit.4 303128710Sru/* 304128710Sru * Set IRQ offsets by reprogramming 8259A PICs. 305128710Sru */ 30661064Snyansetpic: in $0x02,%al # Save master 30761064Snyan push %ax # IMR 30861064Snyan in $0x0a,%al # Save slave 30961064Snyan push %ax # IMR 31043561Skato movb $0x11,%al # ICW1 to 31143561Skato outb %al,$0x00 # master, 31243561Skato outb %al,$0x08 # slave 31343561Skato movb %bl,%al # ICW2 to 31443561Skato outb %al,$0x02 # master 31543561Skato movb %bh,%al # ICW2 to 31643561Skato outb %al,$0x0a # slave 31743561Skato movb $0x80,%al # ICW3 to 31843561Skato outb %al,$0x02 # master 31943561Skato movb $0x7,%al # ICW3 to 32043561Skato outb %al,$0x0a # slave 32143561Skato movb $0x1d,%al # ICW4 to 32243561Skato outb %al,$0x02 # master, 32343561Skato movb $0x9,%al # ICW4 to 32443561Skato outb %al,$0x0a # slave 32561064Snyan pop %ax # Restore slave 32643561Skato outb %al,$0x0a # IMR 32761064Snyan pop %ax # Restore master 32843561Skato outb %al,$0x02 # IMR 32961064Snyan retw # To caller 33061064Snyan .code32 331128710Sru/* 332128710Sru * Initiate return from V86 mode to user mode. 333128710Sru */ 33443561Skatointhlt: hlt # To supervisor mode 335128710Sru/* 336128710Sru * Exception jump table. 337128710Sru */ 33861064Snyanintx00: push $0x0 # Int 0x0: #DE 33943561Skato jmp ex_noc # Divide error 34061064Snyan push $0x1 # Int 0x1: #DB 34143561Skato jmp ex_noc # Debug 34261064Snyan push $0x3 # Int 0x3: #BP 34343561Skato jmp ex_noc # Breakpoint 34461064Snyan push $0x4 # Int 0x4: #OF 34543561Skato jmp ex_noc # Overflow 34661064Snyan push $0x5 # Int 0x5: #BR 34743561Skato jmp ex_noc # BOUND range exceeded 34861064Snyan push $0x6 # Int 0x6: #UD 34943561Skato jmp ex_noc # Invalid opcode 35061064Snyan push $0x7 # Int 0x7: #NM 35143561Skato jmp ex_noc # Device not available 35261064Snyan push $0x8 # Int 0x8: #DF 35343561Skato jmp except # Double fault 35461064Snyan push $0xa # Int 0xa: #TS 35543561Skato jmp except # Invalid TSS 35661064Snyan push $0xb # Int 0xb: #NP 35743561Skato jmp except # Segment not present 35861064Snyan push $0xc # Int 0xc: #SS 35943561Skato jmp except # Stack segment fault 36061064Snyan push $0xd # Int 0xd: #GP 36143561Skato jmp ex_v86 # General protection 36261064Snyan push $0xe # Int 0xe: #PF 36343561Skato jmp except # Page fault 36461064Snyanintx10: push $0x10 # Int 0x10: #MF 36543561Skato jmp ex_noc # Floating-point error 366128710Sru/* 367128710Sru * Handle #GP exception. 368128710Sru */ 36943561Skatoex_v86: testb $0x2,0x12(%esp,1) # V86 mode? 37043561Skato jz except # No 37143561Skato jmp v86mon # To monitor 372128710Sru/* 373128710Sru * Save a zero error code. 374128710Sru */ 37543561Skatoex_noc: pushl (%esp,1) # Duplicate int no 37643561Skato movb $0x0,0x4(%esp,1) # Fake error code 377128710Sru/* 378128710Sru * Handle exception. 379128710Sru */ 38043561Skatoexcept: cld # String ops inc 38143561Skato pushl %ds # Save 38243561Skato pushl %es # most 38343561Skato pusha # registers 38443561Skato movb $0x6,%al # Push loop count 38543561Skato testb $0x2,0x3a(%esp,1) # V86 mode? 38643561Skato jnz except.1 # Yes 38743561Skato pushl %gs # Set GS 38843561Skato pushl %fs # Set FS 38943561Skato pushl %ds # Set DS 39043561Skato pushl %es # Set ES 39143561Skato movb $0x2,%al # Push loop count 39243561Skato cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? 39343561Skato jne except.1 # No 39443561Skato pushl %ss # Set SS 39543561Skato leal 0x50(%esp,1),%eax # Set 39643561Skato pushl %eax # ESP 39743561Skato jmp except.2 # Join common code 39843561Skatoexcept.1: pushl 0x50(%esp,1) # Set GS, FS, DS, ES 39943561Skato decb %al # (if V86 mode), and 40043561Skato jne except.1 # SS, ESP 40161064Snyanexcept.2: push $SEL_SDATA # Set up 40243561Skato popl %ds # to 40343561Skato pushl %ds # address 40443561Skato popl %es # data 40543561Skato movl %esp,%ebx # Stack frame 40643561Skato movl $dmpfmt,%esi # Dump format string 40743561Skato movl $MEM_BUF,%edi # Buffer 40843561Skato pushl %eax 40943561Skato pushl %edx 41043561Skatowait.1: 41143561Skato inb $0x60,%al 41243561Skato testb $0x04,%al 41343561Skato jz wait.1 41443561Skato movb $0xe0,%al 41543561Skato outb %al,$0x62 41643561Skatowait.2: 41743561Skato inb $0x60,%al 41843561Skato testb $0x01,%al 41943561Skato jz wait.2 42043561Skato xorl %edx,%edx 42143561Skato inb $0x62,%al 42243561Skato movb %al,%dl 42343561Skato inb $0x62,%al 42443561Skato movb %al,%dh 42543561Skato inb $0x62,%al 42643561Skato inb $0x62,%al 42743561Skato inb $0x62,%al 42843561Skato movl %edx,%eax 42943561Skato shlw $1,%ax 43043561Skato movl $BDA_POS,%edx 43143561Skato movw %ax,(%edx) 43243561Skato popl %edx 43343561Skato popl %eax 43443561Skato pushl %edi # Dump to 43543561Skato call dump # buffer 43643561Skato popl %esi # and 43743561Skato call putstr # display 43843561Skato leal 0x18(%esp,1),%esp # Discard frame 43943561Skato popa # Restore 44043561Skato popl %es # registers 44143561Skato popl %ds # saved 44243561Skato cmpb $0x3,(%esp,1) # Breakpoint? 44343561Skato je except.3 # Yes 44486497Snyan cmpb $0x1,(%esp,1) # Debug? 44586497Snyan jne except.2a # No 44686497Snyan testl $0x100,0x10(%esp,1) # Trap flag set? 44786497Snyan jnz except.3 # Yes 44886497Snyanexcept.2a: jmp exit # Exit 44943561Skatoexcept.3: leal 0x8(%esp,1),%esp # Discard err, int no 45043561Skato iret # From interrupt 451128710Sru/* 452128710Sru * Return to user mode from V86 mode. 453128710Sru */ 45443561Skatointrtn: cld # String ops inc 45543561Skato pushl %ds # Address 45643561Skato popl %es # data 45743561Skato leal 0x3c(%ebp),%edx # V86 Segment registers 45843561Skato movl MEM_TSS+TSS_ESP1,%esi # Link stack pointer 45943561Skato lodsl # INT_V86 args pointer 46043561Skato movl %esi,%ebx # Saved exception frame 46143561Skato testl %eax,%eax # INT_V86 args? 46243561Skato jz intrtn.2 # No 46343561Skato movl $MEM_USR,%edi # User base 46443561Skato movl 0x1c(%esi),%ebx # User ESP 46543561Skato movl %eax,(%edi,%ebx,1) # Restore to user stack 46643561Skato leal 0x8(%edi,%eax,1),%edi # Arg segment registers 46743561Skato testb $0x4,-0x6(%edi) # Return flags? 46843561Skato jz intrtn.1 # No 46943561Skato movl 0x30(%ebp),%eax # Get V86 flags 47043561Skato movw %ax,0x18(%esi) # Set user flags 47143561Skatointrtn.1: leal 0x10(%esi),%ebx # Saved exception frame 47243561Skato xchgl %edx,%esi # Segment registers 47343561Skato movb $0x4,%cl # Update seg regs 47443561Skato rep # in INT_V86 47543561Skato movsl # args 476164114Snyanintrtn.2: xchgl %edx,%esi # Segment registers 47743561Skato leal 0x28(%ebp),%edi # Set up seg 47843561Skato movb $0x4,%cl # regs for 47943561Skato rep # later 48043561Skato movsl # pop 481164114Snyan xchgl %ebx,%esi # Restore exception 48243561Skato movb $0x5,%cl # frame to 48343561Skato rep # supervisor 48443561Skato movsl # stack 48543561Skato movl %esi,MEM_TSS+TSS_ESP1 # Link stack pointer 48643561Skato popa # Restore 48743561Skato leal 0x8(%esp,1),%esp # Discard err, int no 48843561Skato popl %es # Restore 48943561Skato popl %ds # user 49043561Skato popl %fs # segment 49143561Skato popl %gs # registers 49243561Skato iret # To user mode 493128710Sru/* 494128710Sru * V86 monitor. 495128710Sru */ 49643561Skatov86mon: cld # String ops inc 49743561Skato pushl $SEL_SDATA # Set up for 49843561Skato popl %ds # flat addressing 49943561Skato pusha # Save registers 50043561Skato movl %esp,%ebp # Address stack frame 50143561Skato movzwl 0x2c(%ebp),%edi # Load V86 CS 50243561Skato shll $0x4,%edi # To linear 50343561Skato movl 0x28(%ebp),%esi # Load V86 IP 50443561Skato addl %edi,%esi # Code pointer 50543561Skato xorl %ecx,%ecx # Zero 50643561Skato movb $0x2,%cl # 16-bit operands 50743561Skato xorl %eax,%eax # Zero 50843561Skatov86mon.1: lodsb # Get opcode 50943561Skato cmpb $0x66,%al # Operand size prefix? 51043561Skato jne v86mon.2 # No 51143561Skato movb $0x4,%cl # 32-bit operands 51243561Skato jmp v86mon.1 # Continue 51343561Skatov86mon.2: cmpb $0xf4,%al # HLT? 51443561Skato jne v86mon.3 # No 51543561Skato cmpl $inthlt+0x1,%esi # Is inthlt? 51644368Skato jne v86mon.7 # No (ignore) 51743561Skato jmp intrtn # Return to user mode 51864019Snyanv86mon.3: cmpb $0xf,%al # Prefixed instruction? 51964019Snyan jne v86mon.4 # No 52064019Snyan cmpb $0x09,(%esi) # Is it a WBINVD? 52164019Snyan je v86wbinvd # Yes 52264019Snyan cmpb $0x30,(%esi) # Is it a WRMSR? 52364019Snyan je v86wrmsr # Yes 52464019Snyan cmpb $0x32,(%esi) # Is it a RDMSR? 52564019Snyan je v86rdmsr # Yes 526164114Snyan cmpb $0x20,(%esi) # Is this a MOV reg,CRx? 52744368Skato je v86mov # Yes 52844368Skatov86mon.4: cmpb $0xfa,%al # CLI? 52943561Skato je v86cli # Yes 53043561Skato cmpb $0xfb,%al # STI? 53143561Skato je v86sti # Yes 53243561Skato movzwl 0x38(%ebp),%ebx # Load V86 SS 53343561Skato shll $0x4,%ebx # To offset 53443561Skato pushl %ebx # Save 53543561Skato addl 0x34(%ebp),%ebx # Add V86 SP 53643561Skato movl 0x30(%ebp),%edx # Load V86 flags 53743561Skato cmpb $0x9c,%al # PUSHF/PUSHFD? 53843561Skato je v86pushf # Yes 53943561Skato cmpb $0x9d,%al # POPF/POPFD? 54043561Skato je v86popf # Yes 54143561Skato cmpb $0xcd,%al # INT imm8? 54243561Skato je v86intn # Yes 54343561Skato cmpb $0xcf,%al # IRET/IRETD? 54443561Skato je v86iret # Yes 54543561Skato popl %ebx # Restore 54643561Skato popa # Restore 54743561Skato jmp except # Handle exception 54844368Skatov86mon.5: movl %edx,0x30(%ebp) # Save V86 flags 54944368Skatov86mon.6: popl %edx # V86 SS adjustment 55043561Skato subl %edx,%ebx # Save V86 55143561Skato movl %ebx,0x34(%ebp) # SP 55244368Skatov86mon.7: subl %edi,%esi # From linear 55343561Skato movl %esi,0x28(%ebp) # Save V86 IP 55443561Skato popa # Restore 55543561Skato leal 0x8(%esp,1),%esp # Discard int no, error 55643561Skato iret # To V86 mode 557128710Sru/* 558164114Snyan * Emulate MOV reg,CRx. 559128710Sru */ 560164114Snyanv86mov: movb 0x1(%esi),%bl # Fetch Mod R/M byte 561164114Snyan testb $0x10,%bl # Read CR2 or CR3? 562164114Snyan jnz v86mov.1 # Yes 563164114Snyan movl %cr0,%eax # Read CR0 564164114Snyan testb $0x20,%bl # Read CR4 instead? 565164114Snyan jz v86mov.2 # No 566164114Snyan movl %cr4,%eax # Read CR4 567164114Snyan jmp v86mov.2 568164114Snyanv86mov.1: movl %cr2,%eax # Read CR2 569164114Snyan testb $0x08,%bl # Read CR3 instead? 570164114Snyan jz v86mov.2 # No 571164114Snyan movl %cr3,%eax # Read CR3 572164114Snyanv86mov.2: andl $0x7,%ebx # Compute offset in 573164114Snyan shl $2,%ebx # frame of destination 574164114Snyan neg %ebx # register 575164114Snyan movl %eax,0x1c(%ebp,%ebx,1) # Store CR to reg 57664019Snyan incl %esi # Adjust IP 577128710Sru/* 578128710Sru * Return from emulating a 0x0f prefixed instruction 579128710Sru */ 58064019Snyanv86preret: incl %esi # Adjust IP 58144368Skato jmp v86mon.7 # Finish up 582128710Sru/* 583128710Sru * Emulate WBINVD 584128710Sru */ 58564019Snyanv86wbinvd: wbinvd # Write back and invalidate 58664019Snyan # cache 58764019Snyan jmp v86preret # Finish up 588128710Sru/* 589128710Sru * Emulate WRMSR 590128710Sru */ 59164019Snyanv86wrmsr: movl 0x18(%ebp),%ecx # Get user's %ecx (MSR to write) 59264019Snyan movl 0x14(%ebp),%edx # Load the value 59364019Snyan movl 0x1c(%ebp),%eax # to write 59464019Snyan wrmsr # Write MSR 59564019Snyan jmp v86preret # Finish up 596128710Sru/* 597128710Sru * Emulate RDMSR 598128710Sru */ 59964019Snyanv86rdmsr: movl 0x18(%ebp),%ecx # MSR to read 60064019Snyan rdmsr # Read the MSR 60164019Snyan movl %eax,0x1c(%ebp) # Return the value of 60264019Snyan movl %edx,0x14(%ebp) # the MSR to the user 60364019Snyan jmp v86preret # Finish up 604128710Sru/* 605128710Sru * Emulate CLI. 606128710Sru */ 60743561Skatov86cli: andb $~0x2,0x31(%ebp) # Clear IF 60844368Skato jmp v86mon.7 # Finish up 609128710Sru/* 610128710Sru * Emulate STI. 611128710Sru */ 61243561Skatov86sti: orb $0x2,0x31(%ebp) # Set IF 61344368Skato jmp v86mon.7 # Finish up 614128710Sru/* 615128710Sru * Emulate PUSHF/PUSHFD. 616128710Sru */ 61743561Skatov86pushf: subl %ecx,%ebx # Adjust SP 61843561Skato cmpb $0x4,%cl # 32-bit 61943561Skato je v86pushf.1 # Yes 62061064Snyan data16 # 16-bit 62143561Skatov86pushf.1: movl %edx,(%ebx) # Save flags 62244368Skato jmp v86mon.6 # Finish up 623128710Sru/* 624128710Sru * Emulate IRET/IRETD. 625128710Sru */ 62643561Skatov86iret: movzwl (%ebx),%esi # Load V86 IP 62743561Skato movzwl 0x2(%ebx),%edi # Load V86 CS 62843561Skato leal 0x4(%ebx),%ebx # Adjust SP 62943561Skato movl %edi,0x2c(%ebp) # Save V86 CS 63043561Skato xorl %edi,%edi # No ESI adjustment 631128710Sru/* 632128710Sru * Emulate POPF/POPFD (and remainder of IRET/IRETD). 633128710Sru */ 63443561Skatov86popf: cmpb $0x4,%cl # 32-bit? 63543561Skato je v86popf.1 # Yes 63643561Skato movl %edx,%eax # Initialize 63761064Snyan data16 # 16-bit 63843561Skatov86popf.1: movl (%ebx),%eax # Load flags 63943561Skato addl %ecx,%ebx # Adjust SP 64043561Skato andl $V86_FLG,%eax # Merge 64143561Skato andl $~V86_FLG,%edx # the 64243561Skato orl %eax,%edx # flags 64344368Skato jmp v86mon.5 # Finish up 644128710Sru/* 645128710Sru * trap int 15, function 87 646128710Sru * reads %es:%si from saved registers on stack to find a GDT containing 647128710Sru * source and destination locations 648128710Sru * reads count of words from saved %cx 649128710Sru * returns success by setting %ah to 0 650128710Sru */ 651164114Snyanint15_87: pushl %esi # Save 652164114Snyan pushl %edi # registers 653164114Snyan movl 0x3C(%ebp),%edi # Load ES 654164114Snyan movzwl 0x4(%ebp),%eax # Load user's SI 655164114Snyan shll $0x4,%edi # EDI = (ES << 4) + 656164114Snyan addl %eax,%edi # SI 657164114Snyan movl 0x11(%edi),%eax # Read base of 658164114Snyan movb 0x17(%edi),%al # GDT entry 659164114Snyan ror $8,%eax # for source 660164114Snyan xchgl %eax,%esi # into %esi 661164114Snyan movl 0x19(%edi),%eax # Read base of 662164114Snyan movb 0x1f(%edi),%al # GDT entry for 663164114Snyan ror $8,%eax # destination 664164114Snyan xchgl %eax,%edi # into %edi 66552202Skato pushl %ds # Make: 66652202Skato popl %es # es = ds 667164114Snyan movzwl 0x18(%ebp),%ecx # Get user's CX 668164114Snyan shll $0x1,%ecx # Convert count from words 66952202Skato rep # repeat... 67052202Skato movsb # perform copy. 671164114Snyan popl %edi # Restore 672164114Snyan popl %esi # registers 67352202Skato movb $0x0,0x1d(%ebp) # set ah = 0 to indicate 67452202Skato # success 67552202Skato andb $0xfe,%dl # clear CF 67652202Skato jmp v86mon.5 # Finish up 67752202Skato 678128710Sru/* 679128710Sru * Reboot the machine by setting the reboot flag and exiting 680128710Sru */ 68158871Skatoreboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag 68258871Skato jmp exit # Terminate BTX and reboot 68358871Skato 684128710Sru/* 685128710Sru * Emulate INT imm8... also make sure to check if it's int 15/87 686128710Sru */ 68743561Skatov86intn: lodsb # Get int no 68858871Skato cmpb $0x19,%al # is it int 19? 68958871Skato je reboot # yes, reboot the machine 69052202Skato cmpb $0x15,%al # is it int 15? 691164114Snyan jne v86intn.1 # no, skip parse 692164114Snyan cmpb $0x87,0x1d(%ebp) # is it the memcpy subfunction? 693164114Snyan je int15_87 # yes 694164114Snyan cmpw $0x4f53,0x1c(%ebp) # is it the delete key callout? 695164114Snyan jne v86intn.1 # no, handle the int normally 696164114Snyan movb BDA_KEYFLAGS,%ch # get the shift key state 697164114Snyan andb $0x18,%ch # mask off just Ctrl and Alt 698164114Snyan cmpb $0x18,%ch # are both Ctrl and Alt down? 699164114Snyan je reboot # yes, reboot the machine 700164114Snyanv86intn.1: subl %edi,%esi # From 70143561Skato shrl $0x4,%edi # linear 70243561Skato movw %dx,-0x2(%ebx) # Save flags 70343561Skato movw %di,-0x4(%ebx) # Save CS 70443561Skato leal -0x6(%ebx),%ebx # Adjust SP 70543561Skato movw %si,(%ebx) # Save IP 70643561Skato shll $0x2,%eax # Scale 70743561Skato movzwl (%eax),%esi # Load IP 70843561Skato movzwl 0x2(%eax),%edi # Load CS 70943561Skato movl %edi,0x2c(%ebp) # Save CS 71043561Skato xorl %edi,%edi # No ESI adjustment 71161064Snyan andb $~0x1,%dh # Clear TF 71244368Skato jmp v86mon.5 # Finish up 713128710Sru/* 714128710Sru * Hardware interrupt jump table. 715128710Sru */ 71661064Snyanintx20: push $0x8 # Int 0x20: IRQ0 71743561Skato jmp int_hw # V86 int 0x8 71861064Snyan push $0x9 # Int 0x21: IRQ1 71943561Skato jmp int_hw # V86 int 0x9 72061064Snyan push $0xa # Int 0x22: IRQ2 72143561Skato jmp int_hw # V86 int 0xa 72261064Snyan push $0xb # Int 0x23: IRQ3 72343561Skato jmp int_hw # V86 int 0xb 72461064Snyan push $0xc # Int 0x24: IRQ4 72543561Skato jmp int_hw # V86 int 0xc 72661064Snyan push $0xd # Int 0x25: IRQ5 72743561Skato jmp int_hw # V86 int 0xd 72861064Snyan push $0xe # Int 0x26: IRQ6 72943561Skato jmp int_hw # V86 int 0xe 73061064Snyan push $0xf # Int 0x27: IRQ7 73143561Skato jmp int_hw # V86 int 0xf 73261064Snyan push $0x10 # Int 0x28: IRQ8 73343561Skato jmp int_hw # V86 int 0x10 73461064Snyan push $0x11 # Int 0x29: IRQ9 73543561Skato jmp int_hw # V86 int 0x11 73661064Snyan push $0x12 # Int 0x2a: IRQ10 73743561Skato jmp int_hw # V86 int 0x12 73861064Snyan push $0x13 # Int 0x2b: IRQ11 73943561Skato jmp int_hw # V86 int 0x13 74061064Snyan push $0x14 # Int 0x2c: IRQ12 74143561Skato jmp int_hw # V86 int 0x14 74261064Snyan push $0x15 # Int 0x2d: IRQ13 74343561Skato jmp int_hw # V86 int 0x15 74461064Snyan push $0x16 # Int 0x2e: IRQ14 74543561Skato jmp int_hw # V86 int 0x16 74661064Snyan push $0x17 # Int 0x2f: IRQ15 74743561Skato jmp int_hw # V86 int 0x17 748128710Sru/* 749128710Sru * Reflect hardware interrupts. 750128710Sru */ 75143561Skatoint_hw: testb $0x2,0xe(%esp,1) # V86 mode? 75243561Skato jz intusr # No 75343561Skato pushl $SEL_SDATA # Address 75443561Skato popl %ds # data 75543561Skato xchgl %eax,(%esp,1) # Swap EAX, int no 75643561Skato pushl %ebp # Address 75743561Skato movl %esp,%ebp # stack frame 75843561Skato pushl %ebx # Save 75943561Skato shll $0x2,%eax # Get int 76043561Skato movl (%eax),%eax # vector 76143561Skato subl $0x6,0x14(%ebp) # Adjust V86 ESP 76243561Skato movzwl 0x18(%ebp),%ebx # V86 SS 76343561Skato shll $0x4,%ebx # * 0x10 76443561Skato addl 0x14(%ebp),%ebx # + V86 ESP 76543561Skato xchgw %ax,0x8(%ebp) # Swap V86 IP 76643561Skato rorl $0x10,%eax # Swap words 76743561Skato xchgw %ax,0xc(%ebp) # Swap V86 CS 76843561Skato roll $0x10,%eax # Swap words 76943561Skato movl %eax,(%ebx) # CS:IP for IRET 77043561Skato movl 0x10(%ebp),%eax # V86 flags 77143561Skato movw %ax,0x4(%ebx) # Flags for IRET 77243561Skato andb $~0x3,0x11(%ebp) # Clear IF, TF 77343561Skato popl %ebx # Restore 77443561Skato popl %ebp # saved 77543561Skato popl %eax # registers 77643561Skato iret # To V86 mode 777128710Sru/* 778128710Sru * Invoke V86 interrupt from user mode, with arguments. 779128710Sru */ 78043561Skatointx31: stc # Have btx_v86 78143561Skato pushl %eax # Missing int no 782128710Sru/* 783128710Sru * Invoke V86 interrupt from user mode. 784128710Sru */ 78543561Skatointusr: std # String ops dec 78643561Skato pushl %eax # Expand 78743561Skato pushl %eax # stack 78843561Skato pushl %eax # frame 78943561Skato pusha # Save 79043561Skato pushl %gs # Save 79143561Skato movl %esp,%eax # seg regs 79243561Skato pushl %fs # and 79343561Skato pushl %ds # point 79443561Skato pushl %es # to them 79561064Snyan push $SEL_SDATA # Set up 79643561Skato popl %ds # to 79743561Skato pushl %ds # address 79843561Skato popl %es # data 79943561Skato movl $MEM_USR,%ebx # User base 80043561Skato movl %ebx,%edx # address 80143561Skato jc intusr.1 # If btx_v86 80243561Skato xorl %edx,%edx # Control flags 80343561Skato xorl %ebp,%ebp # btx_v86 pointer 80443561Skatointusr.1: leal 0x50(%esp,1),%esi # Base of frame 80543561Skato pushl %esi # Save 80643561Skato addl -0x4(%esi),%ebx # User ESP 80743561Skato movl MEM_TSS+TSS_ESP1,%edi # Link stack pointer 80843561Skato leal -0x4(%edi),%edi # Adjust for push 80943561Skato xorl %ecx,%ecx # Zero 81043561Skato movb $0x5,%cl # Push exception 81143561Skato rep # frame on 81243561Skato movsl # link stack 81343561Skato xchgl %eax,%esi # Saved seg regs 81443561Skato movl 0x40(%esp,1),%eax # Get int no 81543561Skato testl %edx,%edx # Have btx_v86? 81643561Skato jz intusr.2 # No 81743561Skato movl (%ebx),%ebp # btx_v86 pointer 81843561Skato movb $0x4,%cl # Count 81943561Skato addl %ecx,%ebx # Adjust for pop 82043561Skato rep # Push saved seg regs 82143561Skato movsl # on link stack 82243561Skato addl %ebp,%edx # Flatten btx_v86 ptr 82343561Skato leal 0x14(%edx),%esi # Seg regs pointer 82443561Skato movl 0x4(%edx),%eax # Get int no/address 82543561Skato movzwl 0x2(%edx),%edx # Get control flags 82643561Skatointusr.2: movl %ebp,(%edi) # Push btx_v86 and 82743561Skato movl %edi,MEM_TSS+TSS_ESP1 # save link stack ptr 82843561Skato popl %edi # Base of frame 82943561Skato xchgl %eax,%ebp # Save intno/address 83043561Skato movl 0x48(%esp,1),%eax # Get flags 83143561Skato testb $0x2,%dl # Simulate CALLF? 83243561Skato jnz intusr.3 # Yes 83343561Skato decl %ebx # Push flags 83443561Skato decl %ebx # on V86 83543561Skato movw %ax,(%ebx) # stack 83643561Skatointusr.3: movb $0x4,%cl # Count 83743561Skato subl %ecx,%ebx # Push return address 83843561Skato movl $inthlt,(%ebx) # on V86 stack 83943561Skato rep # Copy seg regs to 84043561Skato movsl # exception frame 84143561Skato xchgl %eax,%ecx # Save flags 84243561Skato movl %ebx,%eax # User ESP 84343561Skato subl $V86_STK,%eax # Less bytes 84443561Skato ja intusr.4 # to 84543561Skato xorl %eax,%eax # keep 84643561Skatointusr.4: shrl $0x4,%eax # Gives segment 84743561Skato stosl # Set SS 84843561Skato shll $0x4,%eax # To bytes 84943561Skato xchgl %eax,%ebx # Swap 85043561Skato subl %ebx,%eax # Gives offset 85143561Skato stosl # Set ESP 85243561Skato xchgl %eax,%ecx # Get flags 85343561Skato btsl $0x11,%eax # Set VM 85461064Snyan andb $~0x1,%ah # Clear TF 85543561Skato stosl # Set EFL 85643561Skato xchgl %eax,%ebp # Get int no/address 85743561Skato testb $0x1,%dl # Address? 85843561Skato jnz intusr.5 # Yes 85943561Skato shll $0x2,%eax # Scale 86043561Skato movl (%eax),%eax # Load int vector 86143561Skatointusr.5: movl %eax,%ecx # Save 86243561Skato shrl $0x10,%eax # Gives segment 86343561Skato stosl # Set CS 86443561Skato movw %cx,%ax # Restore 86543561Skato stosl # Set EIP 86643561Skato leal 0x10(%esp,1),%esp # Discard seg regs 86743561Skato popa # Restore 86843561Skato iret # To V86 mode 869128710Sru/* 870128710Sru * System Call. 871128710Sru */ 87243561Skatointx30: cmpl $SYS_EXEC,%eax # Exec system call? 87343561Skato jne intx30.1 # No 87443561Skato pushl %ss # Set up 87543561Skato popl %es # all 87643561Skato pushl %es # segment 87743561Skato popl %ds # registers 87843561Skato pushl %ds # for the 87943561Skato popl %fs # program 88043561Skato pushl %fs # we're 88143561Skato popl %gs # invoking 88243561Skato movl $MEM_USR,%eax # User base address 88343561Skato addl 0xc(%esp,1),%eax # Change to user 88443561Skato leal 0x4(%eax),%esp # stack 885125780Snyan#ifdef PAGING 88643561Skato movl %cr0,%eax # Turn 88743561Skato andl $~0x80000000,%eax # off 88843561Skato movl %eax,%cr0 # paging 88943561Skato xorl %eax,%eax # Flush 89043561Skato movl %eax,%cr3 # TLB 891125780Snyan#endif 89243561Skato popl %eax # Call 89343561Skato call *%eax # program 89478650Skatointx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot 89543561Skato jmp exit # Exit 896128710Sru/* 897128710Sru * Dump structure [EBX] to [EDI], using format string [ESI]. 898128710Sru */ 89943561Skatodump.0: stosb # Save char 90043561Skatodump: lodsb # Load char 90143561Skato testb %al,%al # End of string? 90243561Skato jz dump.10 # Yes 90343561Skato testb $0x80,%al # Control? 90443561Skato jz dump.0 # No 90543561Skato movb %al,%ch # Save control 90643561Skato movb $'=',%al # Append 90743561Skato stosb # '=' 90843561Skato lodsb # Get offset 90943561Skato pushl %esi # Save 91043561Skato movsbl %al,%esi # To 91143561Skato addl %ebx,%esi # pointer 91243561Skato testb $DMP_X16,%ch # Dump word? 91343561Skato jz dump.1 # No 91443561Skato lodsw # Get and 91543561Skato call hex16 # dump it 91643561Skatodump.1: testb $DMP_X32,%ch # Dump long? 91743561Skato jz dump.2 # No 91843561Skato lodsl # Get and 91943561Skato call hex32 # dump it 92043561Skatodump.2: testb $DMP_MEM,%ch # Dump memory? 92143561Skato jz dump.8 # No 92243561Skato pushl %ds # Save 92343561Skato testb $0x2,0x52(%ebx) # V86 mode? 92443561Skato jnz dump.3 # Yes 92561064Snyan verr 0x4(%esi) # Readable selector? 92643561Skato jnz dump.3 # No 92743561Skato ldsl (%esi),%esi # Load pointer 92843561Skato jmp dump.4 # Join common code 92943561Skatodump.3: lodsl # Set offset 93043561Skato xchgl %eax,%edx # Save 93143561Skato lodsl # Get segment 93243561Skato shll $0x4,%eax # * 0x10 93343561Skato addl %edx,%eax # + offset 93443561Skato xchgl %eax,%esi # Set pointer 93586497Snyandump.4: movb $2,%dl # Num lines 93686497Snyandump.4a: movb $0x10,%cl # Bytes to dump 93743561Skatodump.5: lodsb # Get byte and 93843561Skato call hex8 # dump it 93943561Skato decb %cl # Keep count 94086497Snyan jz dump.6a # If done 94143561Skato movb $'-',%al # Separator 94243561Skato cmpb $0x8,%cl # Half way? 94343561Skato je dump.6 # Yes 94443561Skato movb $' ',%al # Use space 94543561Skatodump.6: stosb # Save separator 94643561Skato jmp dump.5 # Continue 94786497Snyandump.6a: decb %dl # Keep count 94886497Snyan jz dump.7 # If done 94986497Snyan movb $0xa,%al # Line feed 95086497Snyan stosb # Save one 95186497Snyan movb $7,%cl # Leading 95286497Snyan movb $' ',%al # spaces 95386497Snyandump.6b: stosb # Dump 95486497Snyan decb %cl # spaces 95586497Snyan jnz dump.6b 95686497Snyan jmp dump.4a # Next line 95743561Skatodump.7: popl %ds # Restore 95843561Skatodump.8: popl %esi # Restore 95943561Skato movb $0xa,%al # Line feed 96043561Skato testb $DMP_EOL,%ch # End of line? 96143561Skato jnz dump.9 # Yes 96243561Skato movb $' ',%al # Use spaces 96343561Skato stosb # Save one 96443561Skatodump.9: jmp dump.0 # Continue 96543561Skatodump.10: stosb # Terminate string 96643561Skato ret # To caller 967128710Sru/* 968128710Sru * Convert EAX, AX, or AL to hex, saving the result to [EDI]. 969128710Sru */ 97043561Skatohex32: pushl %eax # Save 97143561Skato shrl $0x10,%eax # Do upper 97243561Skato call hex16 # 16 97343561Skato popl %eax # Restore 97443561Skatohex16: call hex16.1 # Do upper 8 97543561Skatohex16.1: xchgb %ah,%al # Save/restore 97643561Skatohex8: pushl %eax # Save 97743561Skato shrb $0x4,%al # Do upper 97843561Skato call hex8.1 # 4 97943561Skato popl %eax # Restore 98043561Skatohex8.1: andb $0xf,%al # Get lower 4 98143561Skato cmpb $0xa,%al # Convert 98243561Skato sbbb $0x69,%al # to hex 98343561Skato das # digit 98443561Skato orb $0x20,%al # To lower case 98543561Skato stosb # Save char 98643561Skato ret # (Recursive) 987128710Sru/* 988128710Sru * Output zero-terminated string [ESI] to the console. 989128710Sru */ 99043561Skatoputstr.0: call putchr # Output char 99143561Skatoputstr: lodsb # Load char 99243561Skato testb %al,%al # End of string? 99343561Skato jnz putstr.0 # No 99443561Skato ret # To caller 995125780Snyan#ifdef BTX_SERIAL 99686497Snyan .set SIO_PRT,SIOPRT # Base port 99786497Snyan .set SIO_FMT,SIOFMT # 8N1 99886497Snyan .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD 99986497Snyan 1000138189Snyan/* 1001128710Sru * void sio_init(void) 1002138189Snyan */ 100386497Snyansio_init: movw $SIO_PRT+0x3,%dx # Data format reg 100486497Snyan movb $SIO_FMT|0x80,%al # Set format 100586497Snyan outb %al,(%dx) # and DLAB 100686497Snyan pushl %edx # Save 100786497Snyan subb $0x3,%dl # Divisor latch reg 100886497Snyan movw $SIO_DIV,%ax # Set 100986497Snyan outw %ax,(%dx) # BPS 101086497Snyan popl %edx # Restore 101186497Snyan movb $SIO_FMT,%al # Clear 101286497Snyan outb %al,(%dx) # DLAB 101386497Snyan incl %edx # Modem control reg 101486497Snyan movb $0x3,%al # Set RTS, 101586497Snyan outb %al,(%dx) # DTR 101686497Snyan incl %edx # Line status reg 101786497Snyan 1018138189Snyan/* 1019128710Sru * void sio_flush(void) 1020138189Snyan */ 102186497Snyansio_flush.0: call sio_getc.1 # Get character 102286497Snyansio_flush: call sio_ischar # Check for character 102386497Snyan jnz sio_flush.0 # Till none 102486497Snyan ret # To caller 102586497Snyan 1026138189Snyan/* 1027128710Sru * void sio_putc(int c) 1028138189Snyan */ 102986497Snyansio_putc: movw $SIO_PRT+0x5,%dx # Line status reg 103086497Snyan xor %ecx,%ecx # Timeout 103186497Snyan movb $0x40,%ch # counter 103286497Snyansio_putc.1: inb (%dx),%al # Transmitter 103386497Snyan testb $0x20,%al # buffer empty? 103486497Snyan loopz sio_putc.1 # No 103586497Snyan jz sio_putc.2 # If timeout 103686497Snyan movb 0x4(%esp,1),%al # Get character 103786497Snyan subb $0x5,%dl # Transmitter hold reg 103886497Snyan outb %al,(%dx) # Write character 103986497Snyansio_putc.2: ret $0x4 # To caller 104086497Snyan 1041138189Snyan/* 1042128710Sru * int sio_getc(void) 1043138189Snyan */ 104486497Snyansio_getc: call sio_ischar # Character available? 104586497Snyan jz sio_getc # No 104686497Snyansio_getc.1: subb $0x5,%dl # Receiver buffer reg 104786497Snyan inb (%dx),%al # Read character 104886497Snyan ret # To caller 104986497Snyan 1050138189Snyan/* 1051128710Sru * int sio_ischar(void) 1052138189Snyan */ 105386497Snyansio_ischar: movw $SIO_PRT+0x5,%dx # Line status register 105486497Snyan xorl %eax,%eax # Zero 105586497Snyan inb (%dx),%al # Received data 105686497Snyan andb $0x1,%al # ready? 105786497Snyan ret # To caller 105886497Snyan 1059128710Sru/* 1060128710Sru * Output character AL to the serial console. 1061128710Sru */ 106286497Snyanputchr: pusha # Save 106386497Snyan cmpb $10, %al # is it a newline? 106486497Snyan jne putchr.1 # no?, then leave 106586497Snyan push $13 # output a carriage 106686497Snyan call sio_putc # return first 106786497Snyan movb $10, %al # restore %al 106886497Snyanputchr.1: pushl %eax # Push the character 106986497Snyan # onto the stack 107086497Snyan call sio_putc # Output the character 107186497Snyan popa # Restore 107286497Snyan ret # To caller 1073125780Snyan#else 1074128710Sru/* 1075128710Sru * Output character AL to the console. 1076128710Sru */ 107743561Skatoputchr: pusha # Save 107843561Skato xorl %ecx,%ecx # Zero for loops 107943561Skato movb $SCR_MAT,%ah # Mode/attribute 108043561Skato movl $BDA_POS,%ebx # BDA pointer 108143561Skato movw (%ebx),%dx # Cursor position 108243561Skato movl $0xa0000,%edi 108343561Skatoputchr.1: cmpb $0xa,%al # New line? 108443561Skato je putchr.2 # Yes 108543561Skato movw %dx,%cx 108643561Skato movb %al,(%edi,%ecx,1) # Write char 108743561Skato addl $0x2000,%ecx 108843561Skato movb %ah,(%edi,%ecx,1) # Write attr 108943561Skato addw $0x02,%dx 109043561Skato jmp putchr.3 109143561Skatoputchr.2: movw %dx,%ax 109243561Skato movb $SCR_COL*2,%dl 109343561Skato div %dl 109443561Skato incb %al 109543561Skato mul %dl 109643561Skato movw %ax,%dx 109743561Skatoputchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx 109843561Skato jb putchr.4 # No 109943561Skato leal 2*SCR_COL(%edi),%esi # New top line 110043561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 110143561Skato rep # Scroll 110243561Skato movsl # screen 110386497Snyan movb $0x20,%al # Space 110443561Skato xorb %ah,%ah 110543561Skato movb $SCR_COL,%cl # Columns to clear 110643561Skato rep # Clear 110743561Skato stosw # line 110843561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 110943561Skatoputchr.4: movw %dx,(%ebx) # Update position 111043561Skato popa # Restore 111143561Skato ret # To caller 1112125780Snyan#endif 111343561Skato 111443561Skato .p2align 4 1115128710Sru/* 1116128710Sru * Global descriptor table. 1117128710Sru */ 111843561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 111943561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 112043561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 112143561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 112243561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 112343561Skato .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE 112443561Skato .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA 112543561Skato .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS 112643561Skatogdt.1: 1127128710Sru/* 1128128710Sru * Pseudo-descriptors. 1129128710Sru */ 113043561Skatogdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT 113143561Skatoidtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT 113243561Skatoivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT 1133128710Sru/* 1134128710Sru * IDT construction control string. 1135128710Sru */ 113643561Skatoidtctl: .byte 0x10, 0x8e # Int 0x0-0xf 113743561Skato .word 0x7dfb,intx00 # (exceptions) 113843561Skato .byte 0x10, 0x8e # Int 0x10 113943561Skato .word 0x1, intx10 # (exception) 114043561Skato .byte 0x10, 0x8e # Int 0x20-0x2f 114143561Skato .word 0xffff,intx20 # (hardware) 114243561Skato .byte 0x1, 0xee # int 0x30 114343561Skato .word 0x1, intx30 # (system call) 114443561Skato .byte 0x2, 0xee # Int 0x31-0x32 114543561Skato .word 0x1, intx31 # (V86, null) 114643561Skato .byte 0x0 # End of string 1147128710Sru/* 1148128710Sru * Dump format string. 1149128710Sru */ 115043561Skatodmpfmt: .byte '\n' # "\n" 115143561Skato .ascii "int" # "int=" 115243561Skato .byte 0x80|DMP_X32, 0x40 # "00000000 " 115343561Skato .ascii "err" # "err=" 115443561Skato .byte 0x80|DMP_X32, 0x44 # "00000000 " 115543561Skato .ascii "efl" # "efl=" 115643561Skato .byte 0x80|DMP_X32, 0x50 # "00000000 " 115743561Skato .ascii "eip" # "eip=" 115843561Skato .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" 115943561Skato .ascii "eax" # "eax=" 116043561Skato .byte 0x80|DMP_X32, 0x34 # "00000000 " 116143561Skato .ascii "ebx" # "ebx=" 116243561Skato .byte 0x80|DMP_X32, 0x28 # "00000000 " 116343561Skato .ascii "ecx" # "ecx=" 116443561Skato .byte 0x80|DMP_X32, 0x30 # "00000000 " 116543561Skato .ascii "edx" # "edx=" 116643561Skato .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" 116743561Skato .ascii "esi" # "esi=" 116843561Skato .byte 0x80|DMP_X32, 0x1c # "00000000 " 116943561Skato .ascii "edi" # "edi=" 117043561Skato .byte 0x80|DMP_X32, 0x18 # "00000000 " 117143561Skato .ascii "ebp" # "ebp=" 117243561Skato .byte 0x80|DMP_X32, 0x20 # "00000000 " 117343561Skato .ascii "esp" # "esp=" 117443561Skato .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" 117543561Skato .ascii "cs" # "cs=" 117643561Skato .byte 0x80|DMP_X16, 0x4c # "0000 " 117743561Skato .ascii "ds" # "ds=" 117843561Skato .byte 0x80|DMP_X16, 0xc # "0000 " 117943561Skato .ascii "es" # "es=" 118043561Skato .byte 0x80|DMP_X16, 0x8 # "0000 " 118143561Skato .ascii " " # " " 118243561Skato .ascii "fs" # "fs=" 118343561Skato .byte 0x80|DMP_X16, 0x10 # "0000 " 118443561Skato .ascii "gs" # "gs=" 118543561Skato .byte 0x80|DMP_X16, 0x14 # "0000 " 118643561Skato .ascii "ss" # "ss=" 118743561Skato .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" 118843561Skato .ascii "cs:eip" # "cs:eip=" 118943561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" 119043561Skato .ascii "ss:esp" # "ss:esp=" 119143561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" 119286497Snyan .asciz "BTX halted\n" # End 1193128710Sru/* 1194128710Sru * End of BTX memory. 1195128710Sru */ 119643561Skato .p2align 4 119743561Skatobreak: 1198