btx.S revision 200254
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 200254 2009-12-08 13:04:26Z 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 24200254Snyan .set MEM_ESPR,0x5e00 # Real mode stack 25200254Snyan .set MEM_IDT,0x5e00 # IDT 26200254Snyan .set MEM_TSS,0x5f98 # TSS 27200254Snyan .set MEM_MAP,0x6000 # I/O bit map 28200254Snyan .set MEM_TSS_END,0x7fff # End of TSS 2943561Skato .set MEM_ORG,0x9000 # BTX code 3043561Skato .set MEM_USR,0xa000 # Start of user memory 31128710Sru/* 32128710Sru * Paging control. 33128710Sru */ 3443561Skato .set PAG_SIZ,0x1000 # Page size 3543561Skato .set PAG_CNT,0x1000 # Pages to map 36128710Sru/* 37200254Snyan * Fields in %eflags. 38200254Snyan */ 39200254Snyan .set PSL_RESERVED_DEFAULT,0x00000002 40200254Snyan .set PSL_T,0x00000100 # Trap flag 41200254Snyan .set PSL_I,0x00000200 # Interrupt enable flag 42200254Snyan .set PSL_VM,0x00020000 # Virtual 8086 mode flag 43200254Snyan .set PSL_AC,0x00040000 # Alignment check flag 44200254Snyan/* 45128710Sru * Segment selectors. 46128710Sru */ 4743561Skato .set SEL_SCODE,0x8 # Supervisor code 4843561Skato .set SEL_SDATA,0x10 # Supervisor data 4943561Skato .set SEL_RCODE,0x18 # Real mode code 5043561Skato .set SEL_RDATA,0x20 # Real mode data 5143561Skato .set SEL_UCODE,0x28|3 # User code 5243561Skato .set SEL_UDATA,0x30|3 # User data 5343561Skato .set SEL_TSS,0x38 # TSS 54128710Sru/* 55128710Sru * Task state segment fields. 56128710Sru */ 5743561Skato .set TSS_ESP0,0x4 # PL 0 ESP 5843561Skato .set TSS_SS0,0x8 # PL 0 SS 5943561Skato .set TSS_MAP,0x66 # I/O bit map base 60128710Sru/* 61128710Sru * System calls. 62128710Sru */ 6343561Skato .set SYS_EXIT,0x0 # Exit 6443561Skato .set SYS_EXEC,0x1 # Exec 65128710Sru/* 66200254Snyan * Fields in V86 interface structure. 67128710Sru */ 68200254Snyan .set V86_CTL,0x0 # Control flags 69200254Snyan .set V86_ADDR,0x4 # Int number/address 70200254Snyan .set V86_ES,0x8 # V86 ES 71200254Snyan .set V86_DS,0xc # V86 DS 72200254Snyan .set V86_FS,0x10 # V86 FS 73200254Snyan .set V86_GS,0x14 # V86 GS 74128710Sru/* 75200254Snyan * V86 control flags. 76200254Snyan */ 77200254Snyan .set V86F_ADDR,0x10000 # Segment:offset address 78200254Snyan .set V86F_CALLF,0x20000 # Emulate far call 79200254Snyan .set V86F_FLAGS,0x40000 # Return flags 80200254Snyan/* 81128710Sru * Dump format control bytes. 82128710Sru */ 8343561Skato .set DMP_X16,0x1 # Word 8443561Skato .set DMP_X32,0x2 # Long 8543561Skato .set DMP_MEM,0x4 # Memory 8643561Skato .set DMP_EOL,0x8 # End of line 87128710Sru/* 88128710Sru * Screen defaults and assumptions. 89128710Sru */ 9043561Skato .set SCR_MAT,0xe1 # Mode/attribute 9143561Skato .set SCR_COL,0x50 # Columns per row 9243561Skato .set SCR_ROW,0x19 # Rows per screen 93128710Sru/* 94128710Sru * BIOS Data Area locations. 95128710Sru */ 9658871Skato .set BDA_MEM,0x501 # Free memory 9758871Skato .set BDA_POS,0x53e # Cursor position 98128710Sru/* 99128710Sru * Derivations, for brevity. 100128710Sru */ 10143561Skato .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0 10243561Skato .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base 103176645Snyan .set _TSSLM,MEM_TSS_END-MEM_TSS # TSS limit 10443561Skato .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit 105128710Sru/* 106128710Sru * Code segment. 107128710Sru */ 10843561Skato .globl start 10961064Snyan .code16 11043561Skatostart: # Start of code 111128710Sru/* 112128710Sru * BTX header. 113128710Sru */ 11443561Skatobtx_hdr: .byte 0xeb # Machine ID 11543561Skato .byte 0xe # Header size 11643561Skato .ascii "BTX" # Magic 11743561Skato .byte 0x1 # Major version 118200254Snyan .byte 0x2 # Minor version 11968358Snyan .byte BTX_FLAGS # Flags 12043561Skato .word PAG_CNT-MEM_ORG>>0xc # Paging control 12143561Skato .word break-start # Text size 12243561Skato .long 0x0 # Entry address 123128710Sru/* 124128710Sru * Initialization routine. 125128710Sru */ 12643561Skatoinit: cli # Disable interrupts 12761064Snyan xor %ax,%ax # Zero/segment 12861064Snyan mov %ax,%ss # Set up 12961064Snyan mov $MEM_ESP0,%sp # stack 13061064Snyan mov %ax,%es # Address 13161064Snyan mov %ax,%ds # data 13261064Snyan pushl $0x2 # Clear 13361064Snyan popfl # flags 134128710Sru/* 135128710Sru * Initialize memory. 136128710Sru */ 13761064Snyan mov $MEM_IDT,%di # Memory to initialize 13861064Snyan mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero 13943561Skato rep # Zero-fill 14061064Snyan stosw # memory 141128710Sru/* 142200254Snyan * Update real mode IDT for reflecting hardware interrupts. 143200254Snyan */ 144200254Snyan mov $intr20,%bx # Address first handler 145200254Snyan mov $0x10,%cx # Number of handlers 146200254Snyan mov $0x20*4,%di # First real mode IDT entry 147200254Snyaninit.0: mov %bx,(%di) # Store IP 148200254Snyan inc %di # Address next 149200254Snyan inc %di # entry 150200254Snyan stosw # Store CS 151200254Snyan add $4,%bx # Next handler 152200254Snyan loop init.0 # Next IRQ 153200254Snyan/* 154128710Sru * Create IDT. 155128710Sru */ 156200254Snyan mov $MEM_IDT,%di 15761064Snyan mov $idtctl,%si # Control string 15843561Skatoinit.1: lodsb # Get entry 15961064Snyan cbw # count 16061064Snyan xchg %ax,%cx # as word 16161064Snyan jcxz init.4 # If done 16243561Skato lodsb # Get segment 16361064Snyan xchg %ax,%dx # P:DPL:type 16461064Snyan lodsw # Get control 16561064Snyan xchg %ax,%bx # set 16661064Snyan lodsw # Get handler offset 16761064Snyan mov $SEL_SCODE,%dh # Segment selector 16861064Snyaninit.2: shr %bx # Handle this int? 16943561Skato jnc init.3 # No 17061064Snyan mov %ax,(%di) # Set handler offset 17161064Snyan mov %dh,0x2(%di) # and selector 17261064Snyan mov %dl,0x5(%di) # Set P:DPL:type 17361064Snyan add $0x4,%ax # Next handler 17461064Snyaninit.3: lea 0x8(%di),%di # Next entry 17543561Skato loop init.2 # Till set done 17643561Skato jmp init.1 # Continue 177128710Sru/* 178128710Sru * Initialize TSS. 179128710Sru */ 18061064Snyaninit.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 18161064Snyan movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 18261064Snyan movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base 183128710Sru/* 184128710Sru * Bring up the system. 185128710Sru */ 18661064Snyan mov $0x2820,%bx # Set protected mode 18761064Snyan callw setpic # IRQ offsets 18861064Snyan lidt idtdesc # Set IDT 18961064Snyan lgdt gdtdesc # Set GDT 19061064Snyan mov %cr0,%eax # Switch to protected 191164114Snyan inc %ax # mode 192128710Sru mov %eax,%cr0 # 19361064Snyan ljmp $SEL_SCODE,$init.8 # To 32-bit code 19461064Snyan .code32 19543561Skatoinit.8: xorl %ecx,%ecx # Zero 19643561Skato movb $SEL_SDATA,%cl # To 32-bit 19761064Snyan movw %cx,%ss # stack 198128710Sru/* 199128710Sru * Launch user task. 200128710Sru */ 20143561Skato movb $SEL_TSS,%cl # Set task 20261064Snyan ltr %cx # register 20343561Skato movl $MEM_USR,%edx # User base address 20443561Skato movzwl %ss:BDA_MEM,%eax # Get free memory 20543561Skato andl $0x7,%eax 20643561Skato incl %eax 20743561Skato shll $0x11,%eax # To bytes 20843561Skato subl $0x1000,%eax # Less arg space 20943561Skato subl %edx,%eax # Less base 21043561Skato movb $SEL_UDATA,%cl # User data selector 21143561Skato pushl %ecx # Set SS 21243561Skato pushl %eax # Set ESP 21361064Snyan push $0x202 # Set flags (IF set) 21461064Snyan push $SEL_UCODE # Set CS 21543561Skato pushl btx_hdr+0xc # Set EIP 21643561Skato pushl %ecx # Set GS 21743561Skato pushl %ecx # Set FS 21843561Skato pushl %ecx # Set DS 21943561Skato pushl %ecx # Set ES 22043561Skato pushl %edx # Set EAX 22143561Skato movb $0x7,%cl # Set remaining 22261064Snyaninit.9: push $0x0 # general 22343561Skato loop init.9 # registers 224125780Snyan#ifdef BTX_SERIAL 22586497Snyan call sio_init # setup the serial console 226125780Snyan#endif 22743561Skato popa # and initialize 22843561Skato popl %es # Initialize 22943561Skato popl %ds # user 23043561Skato popl %fs # segment 23143561Skato popl %gs # registers 23243561Skato iret # To user mode 233128710Sru/* 234128710Sru * Exit routine. 235128710Sru */ 23643561Skatoexit: cli # Disable interrupts 23743561Skato movl $MEM_ESP0,%esp # Clear stack 238128710Sru/* 239128710Sru * Turn off paging. 240128710Sru */ 24143561Skato movl %cr0,%eax # Get CR0 24243561Skato andl $~0x80000000,%eax # Disable 24343561Skato movl %eax,%cr0 # paging 24443561Skato xorl %ecx,%ecx # Zero 24543561Skato movl %ecx,%cr3 # Flush TLB 246128710Sru/* 247128710Sru * Restore the GDT in case we caught a kernel trap. 248128710Sru */ 24976927Snyan lgdt gdtdesc # Set GDT 250128710Sru/* 251128710Sru * To 16 bits. 252128710Sru */ 25361064Snyan ljmpw $SEL_RCODE,$exit.1 # Reload CS 25461064Snyan .code16 25561064Snyanexit.1: mov $SEL_RDATA,%cl # 16-bit selector 25661064Snyan mov %cx,%ss # Reload SS 25761064Snyan mov %cx,%ds # Load 25861064Snyan mov %cx,%es # remaining 25961064Snyan mov %cx,%fs # segment 26061064Snyan mov %cx,%gs # registers 261128710Sru/* 262128710Sru * To real-address mode. 263128710Sru */ 26461064Snyan dec %ax # Switch to 26561064Snyan mov %eax,%cr0 # real mode 26661064Snyan ljmp $0x0,$exit.2 # Reload CS 26761064Snyanexit.2: xor %ax,%ax # Real mode segment 26861064Snyan mov %ax,%ss # Reload SS 26961064Snyan mov %ax,%ds # Address data 27061064Snyan mov $0x1008,%bx # Set real mode 27161064Snyan callw setpic # IRQ offsets 27261064Snyan lidt ivtdesc # Set IVT 273128710Sru/* 274128710Sru * Reboot or await reset. 275128710Sru */ 27643561Skato sti # Enable interrupts 27761064Snyan testb $0x1,btx_hdr+0x7 # Reboot? 27843561Skatoexit.3: jz exit.3 # No 27943561Skato movb $0xa0,%al 28043561Skato outb %al,$0x35 281200254Snyan movb $0x00,%al 282200254Snyan outb %al,$0xf0 # reboot the machine 28343561Skatoexit.4: jmp exit.4 284128710Sru/* 285128710Sru * Set IRQ offsets by reprogramming 8259A PICs. 286128710Sru */ 28761064Snyansetpic: in $0x02,%al # Save master 28861064Snyan push %ax # IMR 28961064Snyan in $0x0a,%al # Save slave 29061064Snyan push %ax # IMR 29143561Skato movb $0x11,%al # ICW1 to 29243561Skato outb %al,$0x00 # master, 29343561Skato outb %al,$0x08 # slave 29443561Skato movb %bl,%al # ICW2 to 29543561Skato outb %al,$0x02 # master 29643561Skato movb %bh,%al # ICW2 to 29743561Skato outb %al,$0x0a # slave 29843561Skato movb $0x80,%al # ICW3 to 29943561Skato outb %al,$0x02 # master 30043561Skato movb $0x7,%al # ICW3 to 30143561Skato outb %al,$0x0a # slave 30243561Skato movb $0x1d,%al # ICW4 to 30343561Skato outb %al,$0x02 # master, 30443561Skato movb $0x9,%al # ICW4 to 30543561Skato outb %al,$0x0a # slave 30661064Snyan pop %ax # Restore slave 30743561Skato outb %al,$0x0a # IMR 30861064Snyan pop %ax # Restore master 30943561Skato outb %al,$0x02 # IMR 31061064Snyan retw # To caller 31161064Snyan .code32 312128710Sru/* 313128710Sru * Exception jump table. 314128710Sru */ 31561064Snyanintx00: push $0x0 # Int 0x0: #DE 31643561Skato jmp ex_noc # Divide error 31761064Snyan push $0x1 # Int 0x1: #DB 31843561Skato jmp ex_noc # Debug 31961064Snyan push $0x3 # Int 0x3: #BP 32043561Skato jmp ex_noc # Breakpoint 32161064Snyan push $0x4 # Int 0x4: #OF 32243561Skato jmp ex_noc # Overflow 32361064Snyan push $0x5 # Int 0x5: #BR 32443561Skato jmp ex_noc # BOUND range exceeded 32561064Snyan push $0x6 # Int 0x6: #UD 32643561Skato jmp ex_noc # Invalid opcode 32761064Snyan push $0x7 # Int 0x7: #NM 32843561Skato jmp ex_noc # Device not available 32961064Snyan push $0x8 # Int 0x8: #DF 33043561Skato jmp except # Double fault 33161064Snyan push $0xa # Int 0xa: #TS 33243561Skato jmp except # Invalid TSS 33361064Snyan push $0xb # Int 0xb: #NP 33443561Skato jmp except # Segment not present 33561064Snyan push $0xc # Int 0xc: #SS 33643561Skato jmp except # Stack segment fault 33761064Snyan push $0xd # Int 0xd: #GP 338200254Snyan jmp except # General protection 33961064Snyan push $0xe # Int 0xe: #PF 34043561Skato jmp except # Page fault 34161064Snyanintx10: push $0x10 # Int 0x10: #MF 34243561Skato jmp ex_noc # Floating-point error 343128710Sru/* 344128710Sru * Save a zero error code. 345128710Sru */ 34643561Skatoex_noc: pushl (%esp,1) # Duplicate int no 34743561Skato movb $0x0,0x4(%esp,1) # Fake error code 348128710Sru/* 349128710Sru * Handle exception. 350128710Sru */ 35143561Skatoexcept: cld # String ops inc 35243561Skato pushl %ds # Save 35343561Skato pushl %es # most 35443561Skato pusha # registers 35543561Skato pushl %gs # Set GS 35643561Skato pushl %fs # Set FS 35743561Skato pushl %ds # Set DS 35843561Skato pushl %es # Set ES 35943561Skato cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? 36043561Skato jne except.1 # No 36143561Skato pushl %ss # Set SS 36243561Skato jmp except.2 # Join common code 363200254Snyanexcept.1: pushl 0x50(%esp,1) # Set SS 364200254Snyanexcept.2: pushl 0x50(%esp,1) # Set ESP 365200254Snyan push $SEL_SDATA # Set up 36643561Skato popl %ds # to 36743561Skato pushl %ds # address 36843561Skato popl %es # data 36943561Skato movl %esp,%ebx # Stack frame 37043561Skato movl $dmpfmt,%esi # Dump format string 37143561Skato movl $MEM_BUF,%edi # Buffer 37243561Skato pushl %eax 37343561Skato pushl %edx 374200254Snyanwait.1: inb $0x60,%al 37543561Skato testb $0x04,%al 37643561Skato jz wait.1 37743561Skato movb $0xe0,%al 37843561Skato outb %al,$0x62 379200254Snyanwait.2: inb $0x60,%al 38043561Skato testb $0x01,%al 38143561Skato jz wait.2 38243561Skato xorl %edx,%edx 38343561Skato inb $0x62,%al 38443561Skato movb %al,%dl 38543561Skato inb $0x62,%al 38643561Skato movb %al,%dh 38743561Skato inb $0x62,%al 38843561Skato inb $0x62,%al 38943561Skato inb $0x62,%al 39043561Skato movl %edx,%eax 39143561Skato shlw $1,%ax 39243561Skato movl $BDA_POS,%edx 39343561Skato movw %ax,(%edx) 39443561Skato popl %edx 39543561Skato popl %eax 39643561Skato pushl %edi # Dump to 39743561Skato call dump # buffer 39843561Skato popl %esi # and 39943561Skato call putstr # display 40043561Skato leal 0x18(%esp,1),%esp # Discard frame 40143561Skato popa # Restore 40243561Skato popl %es # registers 40343561Skato popl %ds # saved 40443561Skato cmpb $0x3,(%esp,1) # Breakpoint? 40543561Skato je except.3 # Yes 40686497Snyan cmpb $0x1,(%esp,1) # Debug? 40786497Snyan jne except.2a # No 408200254Snyan testl $PSL_T,0x10(%esp,1) # Trap flag set? 40986497Snyan jnz except.3 # Yes 41086497Snyanexcept.2a: jmp exit # Exit 41143561Skatoexcept.3: leal 0x8(%esp,1),%esp # Discard err, int no 41243561Skato iret # From interrupt 41352202Skato 414128710Sru/* 415128710Sru * Reboot the machine by setting the reboot flag and exiting 416128710Sru */ 41758871Skatoreboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag 41858871Skato jmp exit # Terminate BTX and reboot 41958871Skato 420128710Sru/* 421200254Snyan * Protected Mode Hardware interrupt jump table. 422128710Sru */ 42361064Snyanintx20: push $0x8 # Int 0x20: IRQ0 42443561Skato jmp int_hw # V86 int 0x8 42561064Snyan push $0x9 # Int 0x21: IRQ1 42643561Skato jmp int_hw # V86 int 0x9 42761064Snyan push $0xa # Int 0x22: IRQ2 42843561Skato jmp int_hw # V86 int 0xa 42961064Snyan push $0xb # Int 0x23: IRQ3 43043561Skato jmp int_hw # V86 int 0xb 43161064Snyan push $0xc # Int 0x24: IRQ4 43243561Skato jmp int_hw # V86 int 0xc 43361064Snyan push $0xd # Int 0x25: IRQ5 43443561Skato jmp int_hw # V86 int 0xd 43561064Snyan push $0xe # Int 0x26: IRQ6 43643561Skato jmp int_hw # V86 int 0xe 43761064Snyan push $0xf # Int 0x27: IRQ7 43843561Skato jmp int_hw # V86 int 0xf 43961064Snyan push $0x10 # Int 0x28: IRQ8 44043561Skato jmp int_hw # V86 int 0x10 44161064Snyan push $0x11 # Int 0x29: IRQ9 44243561Skato jmp int_hw # V86 int 0x11 44361064Snyan push $0x12 # Int 0x2a: IRQ10 44443561Skato jmp int_hw # V86 int 0x12 44561064Snyan push $0x13 # Int 0x2b: IRQ11 44643561Skato jmp int_hw # V86 int 0x13 44761064Snyan push $0x14 # Int 0x2c: IRQ12 44843561Skato jmp int_hw # V86 int 0x14 44961064Snyan push $0x15 # Int 0x2d: IRQ13 45043561Skato jmp int_hw # V86 int 0x15 45161064Snyan push $0x16 # Int 0x2e: IRQ14 45243561Skato jmp int_hw # V86 int 0x16 45361064Snyan push $0x17 # Int 0x2f: IRQ15 45443561Skato jmp int_hw # V86 int 0x17 455200254Snyan 456128710Sru/* 457200254Snyan * Invoke real mode interrupt/function call from user mode with arguments. 458128710Sru */ 459200254Snyanintx31: pushl $-1 # Dummy int no for btx_v86 460128710Sru/* 461200254Snyan * Invoke real mode interrupt/function call from protected mode. 462200254Snyan * 463200254Snyan * We place a trampoline on the user stack that will return to rret_tramp 464200254Snyan * which will reenter protected mode and then finally return to the user 465200254Snyan * client. 466200254Snyan * 467200254Snyan * Kernel frame %esi points to: Real mode stack frame at MEM_ESPR: 468200254Snyan * 469200254Snyan * -0x00 user %ss -0x04 kernel %esp (with full frame) 470200254Snyan * -0x04 user %esp -0x08 btx_v86 pointer 471200254Snyan * -0x08 user %eflags -0x0c flags (only used if interrupt) 472200254Snyan * -0x0c user %cs -0x10 real mode CS:IP return trampoline 473200254Snyan * -0x10 user %eip -0x12 real mode flags 474200254Snyan * -0x14 int no -0x16 real mode CS:IP (target) 475200254Snyan * -0x18 %eax 476200254Snyan * -0x1c %ecx 477200254Snyan * -0x20 %edx 478200254Snyan * -0x24 %ebx 479200254Snyan * -0x28 %esp 480200254Snyan * -0x2c %ebp 481200254Snyan * -0x30 %esi 482200254Snyan * -0x34 %edi 483200254Snyan * -0x38 %gs 484200254Snyan * -0x3c %fs 485200254Snyan * -0x40 %ds 486200254Snyan * -0x44 %es 487200254Snyan * -0x48 zero %eax (hardware int only) 488200254Snyan * -0x4c zero %ecx (hardware int only) 489200254Snyan * -0x50 zero %edx (hardware int only) 490200254Snyan * -0x54 zero %ebx (hardware int only) 491200254Snyan * -0x58 zero %esp (hardware int only) 492200254Snyan * -0x5c zero %ebp (hardware int only) 493200254Snyan * -0x60 zero %esi (hardware int only) 494200254Snyan * -0x64 zero %edi (hardware int only) 495200254Snyan * -0x68 zero %gs (hardware int only) 496200254Snyan * -0x6c zero %fs (hardware int only) 497200254Snyan * -0x70 zero %ds (hardware int only) 498200254Snyan * -0x74 zero %es (hardware int only) 499128710Sru */ 500200254Snyanint_hw: cld # String ops inc 501200254Snyan pusha # Save gp regs 50243561Skato pushl %gs # Save 503200254Snyan pushl %fs # seg 504200254Snyan pushl %ds # regs 505200254Snyan pushl %es 50661064Snyan push $SEL_SDATA # Set up 50743561Skato popl %ds # to 50843561Skato pushl %ds # address 50943561Skato popl %es # data 510200254Snyan leal 0x44(%esp,1),%esi # Base of frame 511200254Snyan movl %esp,MEM_ESPR-0x04 # Save kernel stack pointer 512200254Snyan movl -0x14(%esi),%eax # Get Int no 513200254Snyan cmpl $-1,%eax # Hardware interrupt? 514200254Snyan jne intusr.1 # Yes 515200254Snyan/* 516200254Snyan * v86 calls save the btx_v86 pointer on the real mode stack and read 517200254Snyan * the address and flags from the btx_v86 structure. For interrupt 518200254Snyan * handler invocations (VM86 INTx requests), disable interrupts, 519200254Snyan * tracing, and alignment checking while the handler runs. 520200254Snyan */ 52143561Skato movl $MEM_USR,%ebx # User base 52243561Skato movl %ebx,%edx # address 52343561Skato addl -0x4(%esi),%ebx # User ESP 52443561Skato movl (%ebx),%ebp # btx_v86 pointer 52543561Skato addl %ebp,%edx # Flatten btx_v86 ptr 526200254Snyan movl %edx,MEM_ESPR-0x08 # Save btx_v86 ptr 527200254Snyan movl V86_ADDR(%edx),%eax # Get int no/address 528200254Snyan movl V86_CTL(%edx),%edx # Get control flags 529200254Snyan movl -0x08(%esi),%ebx # Save user flags in %ebx 530200254Snyan testl $V86F_ADDR,%edx # Segment:offset? 531200254Snyan jnz intusr.4 # Yes 532200254Snyan andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing, 533200254Snyan # and alignment checking for 534200254Snyan # interrupt handler 535200254Snyan jmp intusr.3 # Skip hardware interrupt 536200254Snyan/* 537200254Snyan * Hardware interrupts store a NULL btx_v86 pointer and use the 538200254Snyan * address (interrupt number) from the stack with empty flags. Also, 539200254Snyan * push a dummy frame of zeros onto the stack for all the general 540200254Snyan * purpose and segment registers and clear %eflags. This gives the 541200254Snyan * hardware interrupt handler a clean slate. 542200254Snyan */ 543200254Snyanintusr.1: xorl %edx,%edx # Control flags 544200254Snyan movl %edx,MEM_ESPR-0x08 # NULL btx_v86 ptr 545200254Snyan movl $12,%ecx # Frame is 12 dwords 546200254Snyanintusr.2: pushl $0x0 # Fill frame 547200254Snyan loop intusr.2 # with zeros 548200254Snyan movl $PSL_RESERVED_DEFAULT,%ebx # Set clean %eflags 549200254Snyan/* 550200254Snyan * Look up real mode IDT entry for hardware interrupts and VM86 INTx 551200254Snyan * requests. 552200254Snyan */ 553200254Snyanintusr.3: shll $0x2,%eax # Scale 55443561Skato movl (%eax),%eax # Load int vector 555200254Snyan jmp intusr.5 # Skip CALLF test 556128710Sru/* 557200254Snyan * Panic if V86F_CALLF isn't set with V86F_ADDR. 558200254Snyan */ 559200254Snyanintusr.4: testl $V86F_CALLF,%edx # Far call? 560200254Snyan jnz intusr.5 # Ok 561200254Snyan movl %edx,0x30(%esp,1) # Place VM86 flags in int no 562200254Snyan movl $badvm86,%esi # Display bad 563200254Snyan call putstr # VM86 call 564200254Snyan popl %es # Restore 565200254Snyan popl %ds # seg 566200254Snyan popl %fs # regs 567200254Snyan popl %gs 568200254Snyan popal # Restore gp regs 569200254Snyan jmp ex_noc # Panic 570200254Snyan/* 571200254Snyan * %eax now holds the segment:offset of the function. 572200254Snyan * %ebx now holds the %eflags to pass to real mode. 573200254Snyan * %edx now holds the V86F_* flags. 574200254Snyan */ 575200254Snyanintusr.5: movw %bx,MEM_ESPR-0x12 # Pass user flags to real mode 576200254Snyan # target 577200254Snyan/* 578200254Snyan * If this is a v86 call, copy the seg regs out of the btx_v86 structure. 579200254Snyan */ 580200254Snyan movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr 581200254Snyan jecxz intusr.6 # Skip for hardware ints 582200254Snyan leal -0x44(%esi),%edi # %edi => kernel stack seg regs 583200254Snyan pushl %esi # Save 584200254Snyan leal V86_ES(%ecx),%esi # %esi => btx_v86 seg regs 585200254Snyan movl $4,%ecx # Copy seg regs 586200254Snyan rep # from btx_v86 587200254Snyan movsl # to kernel stack 588200254Snyan popl %esi # Restore 589200254Snyanintusr.6: movl -0x08(%esi),%ebx # Copy user flags to real 590200254Snyan movl %ebx,MEM_ESPR-0x0c # mode return trampoline 591200254Snyan movl $rret_tramp,%ebx # Set return trampoline 592200254Snyan movl %ebx,MEM_ESPR-0x10 # CS:IP 593200254Snyan movl %eax,MEM_ESPR-0x16 # Real mode target CS:IP 594200254Snyan ljmpw $SEL_RCODE,$intusr.7 # Change to 16-bit segment 595200254Snyan .code16 596200254Snyanintusr.7: movl %cr0,%eax # Leave 597200254Snyan dec %al # protected 598200254Snyan movl %eax,%cr0 # mode 599200254Snyan ljmpw $0x0,$intusr.8 600200254Snyanintusr.8: xorw %ax,%ax # Reset %ds 601200254Snyan movw %ax,%ds # and 602200254Snyan movw %ax,%ss # %ss 603200254Snyan lidt ivtdesc # Set IVT 604200254Snyan popl %es # Restore 605200254Snyan popl %ds # seg 606200254Snyan popl %fs # regs 607200254Snyan popl %gs 608200254Snyan popal # Restore gp regs 609200254Snyan movw $MEM_ESPR-0x16,%sp # Switch to real mode stack 610200254Snyan iret # Call target routine 611200254Snyan/* 612200254Snyan * For the return to real mode we setup a stack frame like this on the real 613200254Snyan * mode stack. Note that callf calls won't pop off the flags, but we just 614200254Snyan * ignore that by repositioning %sp to be just above the btx_v86 pointer 615200254Snyan * so it is aligned. The stack is relative to MEM_ESPR. 616200254Snyan * 617200254Snyan * -0x04 kernel %esp 618200254Snyan * -0x08 btx_v86 619200254Snyan * -0x0c %eax 620200254Snyan * -0x10 %ecx 621200254Snyan * -0x14 %edx 622200254Snyan * -0x18 %ebx 623200254Snyan * -0x1c %esp 624200254Snyan * -0x20 %ebp 625200254Snyan * -0x24 %esi 626200254Snyan * -0x28 %edi 627200254Snyan * -0x2c %gs 628200254Snyan * -0x30 %fs 629200254Snyan * -0x34 %ds 630200254Snyan * -0x38 %es 631200254Snyan * -0x3c %eflags 632200254Snyan */ 633200254Snyanrret_tramp: movw $MEM_ESPR-0x08,%sp # Reset stack pointer 634200254Snyan pushal # Save gp regs 635200254Snyan pushl %gs # Save 636200254Snyan pushl %fs # seg 637200254Snyan pushl %ds # regs 638200254Snyan pushl %es 639200254Snyan pushfl # Save %eflags 640200254Snyan cli # Disable interrupts 641200254Snyan std # String ops dec 642200254Snyan xorw %ax,%ax # Reset seg 643200254Snyan movw %ax,%ds # regs 644200254Snyan movw %ax,%es # (%ss is already 0) 645200254Snyan lidt idtdesc # Set IDT 646200254Snyan lgdt gdtdesc # Set GDT 647200254Snyan mov %cr0,%eax # Switch to protected 648200254Snyan inc %ax # mode 649200254Snyan mov %eax,%cr0 # 650200254Snyan ljmp $SEL_SCODE,$rret_tramp.1 # To 32-bit code 651200254Snyan .code32 652200254Snyanrret_tramp.1: xorl %ecx,%ecx # Zero 653200254Snyan movb $SEL_SDATA,%cl # Setup 654200254Snyan movw %cx,%ss # 32-bit 655200254Snyan movw %cx,%ds # seg 656200254Snyan movw %cx,%es # regs 657200254Snyan movl MEM_ESPR-0x04,%esp # Switch to kernel stack 658200254Snyan leal 0x44(%esp,1),%esi # Base of frame 659200254Snyan andb $~0x2,tss_desc+0x5 # Clear TSS busy 660200254Snyan movb $SEL_TSS,%cl # Set task 661200254Snyan ltr %cx # register 662200254Snyan/* 663200254Snyan * Now we are back in protected mode. The kernel stack frame set up 664200254Snyan * before entering real mode is still intact. For hardware interrupts, 665200254Snyan * leave the frame unchanged. 666200254Snyan */ 667200254Snyan cmpl $0,MEM_ESPR-0x08 # Leave saved regs unchanged 668200254Snyan jz rret_tramp.3 # for hardware ints 669200254Snyan/* 670200254Snyan * For V86 calls, copy the registers off of the real mode stack onto 671200254Snyan * the kernel stack as we want their updated values. Also, initialize 672200254Snyan * the segment registers on the kernel stack. 673200254Snyan * 674200254Snyan * Note that the %esp in the kernel stack after this is garbage, but popa 675200254Snyan * ignores it, so we don't have to fix it up. 676200254Snyan */ 677200254Snyan leal -0x18(%esi),%edi # Kernel stack GP regs 678200254Snyan pushl %esi # Save 679200254Snyan movl $MEM_ESPR-0x0c,%esi # Real mode stack GP regs 680200254Snyan movl $8,%ecx # Copy GP regs from 681200254Snyan rep # real mode stack 682200254Snyan movsl # to kernel stack 683200254Snyan movl $SEL_UDATA,%eax # Selector for data seg regs 684200254Snyan movl $4,%ecx # Initialize %ds, 685200254Snyan rep # %es, %fs, and 686200254Snyan stosl # %gs 687200254Snyan/* 688200254Snyan * For V86 calls, copy the saved seg regs on the real mode stack back 689200254Snyan * over to the btx_v86 structure. Also, conditionally update the 690200254Snyan * saved eflags on the kernel stack based on the flags from the user. 691200254Snyan */ 692200254Snyan movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr 693200254Snyan leal V86_GS(%ecx),%edi # %edi => btx_v86 seg regs 694200254Snyan leal MEM_ESPR-0x2c,%esi # %esi => real mode seg regs 695200254Snyan xchgl %ecx,%edx # Save btx_v86 ptr 696200254Snyan movl $4,%ecx # Copy seg regs 697200254Snyan rep # from real mode stack 698200254Snyan movsl # to btx_v86 699200254Snyan popl %esi # Restore 700200254Snyan movl V86_CTL(%edx),%edx # Read V86 control flags 701200254Snyan testl $V86F_FLAGS,%edx # User wants flags? 702200254Snyan jz rret_tramp.3 # No 703200254Snyan movl MEM_ESPR-0x3c,%eax # Read real mode flags 704200254Snyan movw %ax,-0x08(%esi) # Update user flags (low 16) 705200254Snyan/* 706200254Snyan * Return to the user task 707200254Snyan */ 708200254Snyanrret_tramp.3: popl %es # Restore 709200254Snyan popl %ds # seg 710200254Snyan popl %fs # regs 711200254Snyan popl %gs 712200254Snyan popal # Restore gp regs 713200254Snyan addl $4,%esp # Discard int no 714200254Snyan iret # Return to user mode 715200254Snyan 716200254Snyan/* 717128710Sru * System Call. 718128710Sru */ 71943561Skatointx30: cmpl $SYS_EXEC,%eax # Exec system call? 72043561Skato jne intx30.1 # No 72143561Skato pushl %ss # Set up 72243561Skato popl %es # all 72343561Skato pushl %es # segment 72443561Skato popl %ds # registers 72543561Skato pushl %ds # for the 72643561Skato popl %fs # program 72743561Skato pushl %fs # we're 72843561Skato popl %gs # invoking 72943561Skato movl $MEM_USR,%eax # User base address 73043561Skato addl 0xc(%esp,1),%eax # Change to user 73143561Skato leal 0x4(%eax),%esp # stack 73243561Skato popl %eax # Call 73343561Skato call *%eax # program 73478650Skatointx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot 73543561Skato jmp exit # Exit 736128710Sru/* 737128710Sru * Dump structure [EBX] to [EDI], using format string [ESI]. 738128710Sru */ 73943561Skatodump.0: stosb # Save char 74043561Skatodump: lodsb # Load char 74143561Skato testb %al,%al # End of string? 74243561Skato jz dump.10 # Yes 74343561Skato testb $0x80,%al # Control? 74443561Skato jz dump.0 # No 74543561Skato movb %al,%ch # Save control 74643561Skato movb $'=',%al # Append 74743561Skato stosb # '=' 74843561Skato lodsb # Get offset 74943561Skato pushl %esi # Save 75043561Skato movsbl %al,%esi # To 75143561Skato addl %ebx,%esi # pointer 75243561Skato testb $DMP_X16,%ch # Dump word? 75343561Skato jz dump.1 # No 75443561Skato lodsw # Get and 75543561Skato call hex16 # dump it 75643561Skatodump.1: testb $DMP_X32,%ch # Dump long? 75743561Skato jz dump.2 # No 75843561Skato lodsl # Get and 75943561Skato call hex32 # dump it 76043561Skatodump.2: testb $DMP_MEM,%ch # Dump memory? 76143561Skato jz dump.8 # No 76243561Skato pushl %ds # Save 763200254Snyan testl $PSL_VM,0x50(%ebx) # V86 mode? 76443561Skato jnz dump.3 # Yes 76561064Snyan verr 0x4(%esi) # Readable selector? 76643561Skato jnz dump.3 # No 76743561Skato ldsl (%esi),%esi # Load pointer 76843561Skato jmp dump.4 # Join common code 76943561Skatodump.3: lodsl # Set offset 77043561Skato xchgl %eax,%edx # Save 77143561Skato lodsl # Get segment 77243561Skato shll $0x4,%eax # * 0x10 77343561Skato addl %edx,%eax # + offset 77443561Skato xchgl %eax,%esi # Set pointer 77586497Snyandump.4: movb $2,%dl # Num lines 77686497Snyandump.4a: movb $0x10,%cl # Bytes to dump 77743561Skatodump.5: lodsb # Get byte and 77843561Skato call hex8 # dump it 77943561Skato decb %cl # Keep count 78086497Snyan jz dump.6a # If done 78143561Skato movb $'-',%al # Separator 78243561Skato cmpb $0x8,%cl # Half way? 78343561Skato je dump.6 # Yes 78443561Skato movb $' ',%al # Use space 78543561Skatodump.6: stosb # Save separator 78643561Skato jmp dump.5 # Continue 78786497Snyandump.6a: decb %dl # Keep count 78886497Snyan jz dump.7 # If done 78986497Snyan movb $0xa,%al # Line feed 79086497Snyan stosb # Save one 79186497Snyan movb $7,%cl # Leading 79286497Snyan movb $' ',%al # spaces 79386497Snyandump.6b: stosb # Dump 79486497Snyan decb %cl # spaces 79586497Snyan jnz dump.6b 79686497Snyan jmp dump.4a # Next line 79743561Skatodump.7: popl %ds # Restore 79843561Skatodump.8: popl %esi # Restore 79943561Skato movb $0xa,%al # Line feed 80043561Skato testb $DMP_EOL,%ch # End of line? 80143561Skato jnz dump.9 # Yes 80243561Skato movb $' ',%al # Use spaces 80343561Skato stosb # Save one 80443561Skatodump.9: jmp dump.0 # Continue 80543561Skatodump.10: stosb # Terminate string 80643561Skato ret # To caller 807128710Sru/* 808128710Sru * Convert EAX, AX, or AL to hex, saving the result to [EDI]. 809128710Sru */ 81043561Skatohex32: pushl %eax # Save 81143561Skato shrl $0x10,%eax # Do upper 81243561Skato call hex16 # 16 81343561Skato popl %eax # Restore 81443561Skatohex16: call hex16.1 # Do upper 8 81543561Skatohex16.1: xchgb %ah,%al # Save/restore 81643561Skatohex8: pushl %eax # Save 81743561Skato shrb $0x4,%al # Do upper 81843561Skato call hex8.1 # 4 81943561Skato popl %eax # Restore 82043561Skatohex8.1: andb $0xf,%al # Get lower 4 82143561Skato cmpb $0xa,%al # Convert 82243561Skato sbbb $0x69,%al # to hex 82343561Skato das # digit 82443561Skato orb $0x20,%al # To lower case 82543561Skato stosb # Save char 82643561Skato ret # (Recursive) 827128710Sru/* 828128710Sru * Output zero-terminated string [ESI] to the console. 829128710Sru */ 83043561Skatoputstr.0: call putchr # Output char 83143561Skatoputstr: lodsb # Load char 83243561Skato testb %al,%al # End of string? 83343561Skato jnz putstr.0 # No 83443561Skato ret # To caller 835125780Snyan#ifdef BTX_SERIAL 83686497Snyan .set SIO_PRT,SIOPRT # Base port 83786497Snyan .set SIO_FMT,SIOFMT # 8N1 83886497Snyan .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD 83986497Snyan 840138189Snyan/* 841128710Sru * void sio_init(void) 842138189Snyan */ 84386497Snyansio_init: movw $SIO_PRT+0x3,%dx # Data format reg 84486497Snyan movb $SIO_FMT|0x80,%al # Set format 84586497Snyan outb %al,(%dx) # and DLAB 84686497Snyan pushl %edx # Save 84786497Snyan subb $0x3,%dl # Divisor latch reg 84886497Snyan movw $SIO_DIV,%ax # Set 84986497Snyan outw %ax,(%dx) # BPS 85086497Snyan popl %edx # Restore 85186497Snyan movb $SIO_FMT,%al # Clear 85286497Snyan outb %al,(%dx) # DLAB 85386497Snyan incl %edx # Modem control reg 85486497Snyan movb $0x3,%al # Set RTS, 85586497Snyan outb %al,(%dx) # DTR 85686497Snyan incl %edx # Line status reg 85786497Snyan 858138189Snyan/* 859128710Sru * void sio_flush(void) 860138189Snyan */ 86186497Snyansio_flush.0: call sio_getc.1 # Get character 86286497Snyansio_flush: call sio_ischar # Check for character 86386497Snyan jnz sio_flush.0 # Till none 86486497Snyan ret # To caller 86586497Snyan 866138189Snyan/* 867128710Sru * void sio_putc(int c) 868138189Snyan */ 86986497Snyansio_putc: movw $SIO_PRT+0x5,%dx # Line status reg 87086497Snyan xor %ecx,%ecx # Timeout 87186497Snyan movb $0x40,%ch # counter 87286497Snyansio_putc.1: inb (%dx),%al # Transmitter 87386497Snyan testb $0x20,%al # buffer empty? 87486497Snyan loopz sio_putc.1 # No 87586497Snyan jz sio_putc.2 # If timeout 87686497Snyan movb 0x4(%esp,1),%al # Get character 87786497Snyan subb $0x5,%dl # Transmitter hold reg 87886497Snyan outb %al,(%dx) # Write character 87986497Snyansio_putc.2: ret $0x4 # To caller 88086497Snyan 881138189Snyan/* 882128710Sru * int sio_getc(void) 883138189Snyan */ 88486497Snyansio_getc: call sio_ischar # Character available? 88586497Snyan jz sio_getc # No 88686497Snyansio_getc.1: subb $0x5,%dl # Receiver buffer reg 88786497Snyan inb (%dx),%al # Read character 88886497Snyan ret # To caller 88986497Snyan 890138189Snyan/* 891128710Sru * int sio_ischar(void) 892138189Snyan */ 89386497Snyansio_ischar: movw $SIO_PRT+0x5,%dx # Line status register 89486497Snyan xorl %eax,%eax # Zero 89586497Snyan inb (%dx),%al # Received data 89686497Snyan andb $0x1,%al # ready? 89786497Snyan ret # To caller 89886497Snyan 899128710Sru/* 900128710Sru * Output character AL to the serial console. 901128710Sru */ 90286497Snyanputchr: pusha # Save 90386497Snyan cmpb $10, %al # is it a newline? 90486497Snyan jne putchr.1 # no?, then leave 90586497Snyan push $13 # output a carriage 90686497Snyan call sio_putc # return first 90786497Snyan movb $10, %al # restore %al 90886497Snyanputchr.1: pushl %eax # Push the character 90986497Snyan # onto the stack 91086497Snyan call sio_putc # Output the character 91186497Snyan popa # Restore 91286497Snyan ret # To caller 913125780Snyan#else 914128710Sru/* 915128710Sru * Output character AL to the console. 916128710Sru */ 91743561Skatoputchr: pusha # Save 91843561Skato xorl %ecx,%ecx # Zero for loops 91943561Skato movb $SCR_MAT,%ah # Mode/attribute 92043561Skato movl $BDA_POS,%ebx # BDA pointer 92143561Skato movw (%ebx),%dx # Cursor position 92243561Skato movl $0xa0000,%edi 92343561Skatoputchr.1: cmpb $0xa,%al # New line? 92443561Skato je putchr.2 # Yes 92543561Skato movw %dx,%cx 92643561Skato movb %al,(%edi,%ecx,1) # Write char 92743561Skato addl $0x2000,%ecx 92843561Skato movb %ah,(%edi,%ecx,1) # Write attr 92943561Skato addw $0x02,%dx 93043561Skato jmp putchr.3 93143561Skatoputchr.2: movw %dx,%ax 93243561Skato movb $SCR_COL*2,%dl 93343561Skato div %dl 93443561Skato incb %al 93543561Skato mul %dl 93643561Skato movw %ax,%dx 93743561Skatoputchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx 93843561Skato jb putchr.4 # No 93943561Skato leal 2*SCR_COL(%edi),%esi # New top line 94043561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 94143561Skato rep # Scroll 94243561Skato movsl # screen 94386497Snyan movb $0x20,%al # Space 94443561Skato xorb %ah,%ah 94543561Skato movb $SCR_COL,%cl # Columns to clear 94643561Skato rep # Clear 94743561Skato stosw # line 94843561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 94943561Skatoputchr.4: movw %dx,(%ebx) # Update position 95043561Skato popa # Restore 95143561Skato ret # To caller 952125780Snyan#endif 95343561Skato 954200254Snyan .code16 955200254Snyan/* 956200254Snyan * Real Mode Hardware interrupt jump table. 957200254Snyan */ 958200254Snyanintr20: push $0x8 # Int 0x20: IRQ0 959200254Snyan jmp int_hwr # V86 int 0x8 960200254Snyan push $0x9 # Int 0x21: IRQ1 961200254Snyan jmp int_hwr # V86 int 0x9 962200254Snyan push $0xa # Int 0x22: IRQ2 963200254Snyan jmp int_hwr # V86 int 0xa 964200254Snyan push $0xb # Int 0x23: IRQ3 965200254Snyan jmp int_hwr # V86 int 0xb 966200254Snyan push $0xc # Int 0x24: IRQ4 967200254Snyan jmp int_hwr # V86 int 0xc 968200254Snyan push $0xd # Int 0x25: IRQ5 969200254Snyan jmp int_hwr # V86 int 0xd 970200254Snyan push $0xe # Int 0x26: IRQ6 971200254Snyan jmp int_hwr # V86 int 0xe 972200254Snyan push $0xf # Int 0x27: IRQ7 973200254Snyan jmp int_hwr # V86 int 0xf 974200254Snyan push $0x10 # Int 0x28: IRQ8 975200254Snyan jmp int_hwr # V86 int 0x10 976200254Snyan push $0x11 # Int 0x29: IRQ9 977200254Snyan jmp int_hwr # V86 int 0x11 978200254Snyan push $0x12 # Int 0x2a: IRQ10 979200254Snyan jmp int_hwr # V86 int 0x12 980200254Snyan push $0x13 # Int 0x2b: IRQ11 981200254Snyan jmp int_hwr # V86 int 0x13 982200254Snyan push $0x14 # Int 0x2c: IRQ12 983200254Snyan jmp int_hwr # V86 int 0x14 984200254Snyan push $0x15 # Int 0x2d: IRQ13 985200254Snyan jmp int_hwr # V86 int 0x15 986200254Snyan push $0x16 # Int 0x2e: IRQ14 987200254Snyan jmp int_hwr # V86 int 0x16 988200254Snyan push $0x17 # Int 0x2f: IRQ15 989200254Snyan jmp int_hwr # V86 int 0x17 990200254Snyan/* 991200254Snyan * Reflect hardware interrupts in real mode. 992200254Snyan */ 993200254Snyanint_hwr: push %ax # Save 994200254Snyan push %ds # Save 995200254Snyan push %bp # Save 996200254Snyan mov %sp,%bp # Address stack frame 997200254Snyan xchg %bx,6(%bp) # Swap BX, int no 998200254Snyan xor %ax,%ax # Set %ds:%bx to 999200254Snyan shl $2,%bx # point to 1000200254Snyan mov %ax,%ds # IDT entry 1001200254Snyan mov (%bx),%ax # Load IP 1002200254Snyan mov 2(%bx),%bx # Load CS 1003200254Snyan xchg %ax,4(%bp) # Swap saved %ax,%bx with 1004200254Snyan xchg %bx,6(%bp) # CS:IP of handler 1005200254Snyan pop %bp # Restore 1006200254Snyan pop %ds # Restore 1007200254Snyan lret # Jump to handler 1008200254Snyan 100943561Skato .p2align 4 1010128710Sru/* 1011128710Sru * Global descriptor table. 1012128710Sru */ 101343561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 101443561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 101543561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 101643561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 101743561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 101843561Skato .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE 101943561Skato .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA 1020200254Snyantss_desc: .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS 102143561Skatogdt.1: 1022128710Sru/* 1023128710Sru * Pseudo-descriptors. 1024128710Sru */ 102543561Skatogdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT 102643561Skatoidtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT 102743561Skatoivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT 1028128710Sru/* 1029128710Sru * IDT construction control string. 1030128710Sru */ 103143561Skatoidtctl: .byte 0x10, 0x8e # Int 0x0-0xf 103243561Skato .word 0x7dfb,intx00 # (exceptions) 103343561Skato .byte 0x10, 0x8e # Int 0x10 103443561Skato .word 0x1, intx10 # (exception) 103543561Skato .byte 0x10, 0x8e # Int 0x20-0x2f 103643561Skato .word 0xffff,intx20 # (hardware) 103743561Skato .byte 0x1, 0xee # int 0x30 103843561Skato .word 0x1, intx30 # (system call) 103943561Skato .byte 0x2, 0xee # Int 0x31-0x32 104043561Skato .word 0x1, intx31 # (V86, null) 104143561Skato .byte 0x0 # End of string 1042128710Sru/* 1043128710Sru * Dump format string. 1044128710Sru */ 104543561Skatodmpfmt: .byte '\n' # "\n" 104643561Skato .ascii "int" # "int=" 104743561Skato .byte 0x80|DMP_X32, 0x40 # "00000000 " 104843561Skato .ascii "err" # "err=" 104943561Skato .byte 0x80|DMP_X32, 0x44 # "00000000 " 105043561Skato .ascii "efl" # "efl=" 105143561Skato .byte 0x80|DMP_X32, 0x50 # "00000000 " 105243561Skato .ascii "eip" # "eip=" 105343561Skato .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" 105443561Skato .ascii "eax" # "eax=" 105543561Skato .byte 0x80|DMP_X32, 0x34 # "00000000 " 105643561Skato .ascii "ebx" # "ebx=" 105743561Skato .byte 0x80|DMP_X32, 0x28 # "00000000 " 105843561Skato .ascii "ecx" # "ecx=" 105943561Skato .byte 0x80|DMP_X32, 0x30 # "00000000 " 106043561Skato .ascii "edx" # "edx=" 106143561Skato .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" 106243561Skato .ascii "esi" # "esi=" 106343561Skato .byte 0x80|DMP_X32, 0x1c # "00000000 " 106443561Skato .ascii "edi" # "edi=" 106543561Skato .byte 0x80|DMP_X32, 0x18 # "00000000 " 106643561Skato .ascii "ebp" # "ebp=" 106743561Skato .byte 0x80|DMP_X32, 0x20 # "00000000 " 106843561Skato .ascii "esp" # "esp=" 106943561Skato .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" 107043561Skato .ascii "cs" # "cs=" 107143561Skato .byte 0x80|DMP_X16, 0x4c # "0000 " 107243561Skato .ascii "ds" # "ds=" 107343561Skato .byte 0x80|DMP_X16, 0xc # "0000 " 107443561Skato .ascii "es" # "es=" 107543561Skato .byte 0x80|DMP_X16, 0x8 # "0000 " 107643561Skato .ascii " " # " " 107743561Skato .ascii "fs" # "fs=" 107843561Skato .byte 0x80|DMP_X16, 0x10 # "0000 " 107943561Skato .ascii "gs" # "gs=" 108043561Skato .byte 0x80|DMP_X16, 0x14 # "0000 " 108143561Skato .ascii "ss" # "ss=" 108243561Skato .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" 108343561Skato .ascii "cs:eip" # "cs:eip=" 108443561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" 108543561Skato .ascii "ss:esp" # "ss:esp=" 108643561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" 108786497Snyan .asciz "BTX halted\n" # End 1088128710Sru/* 1089200254Snyan * Bad VM86 call panic 1090200254Snyan */ 1091200254Snyanbadvm86: .asciz "Invalid VM86 Request\n" 1092200254Snyan 1093200254Snyan/* 1094128710Sru * End of BTX memory. 1095128710Sru */ 109643561Skato .p2align 4 109743561Skatobreak: 1098