btx.S revision 237763
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: stable/9/sys/boot/pc98/btx/btx/btx.S 237763 2012-06-29 10:12:18Z avg $ 16128710Sru */ 1743561Skato 18237763Savg#include <bootargs.h> 19237763Savg 20128710Sru/* 21128710Sru * Memory layout. 22128710Sru */ 2343561Skato .set MEM_BTX,0x1000 # Start of BTX memory 2443561Skato .set MEM_ESP0,0x1800 # Supervisor stack 2543561Skato .set MEM_BUF,0x1800 # Scratch buffer 26200254Snyan .set MEM_ESPR,0x5e00 # Real mode stack 27200254Snyan .set MEM_IDT,0x5e00 # IDT 28200254Snyan .set MEM_TSS,0x5f98 # TSS 29200254Snyan .set MEM_MAP,0x6000 # I/O bit map 30200254Snyan .set MEM_TSS_END,0x7fff # End of TSS 3143561Skato .set MEM_ORG,0x9000 # BTX code 3243561Skato .set MEM_USR,0xa000 # Start of user memory 33128710Sru/* 34128710Sru * Paging control. 35128710Sru */ 3643561Skato .set PAG_SIZ,0x1000 # Page size 3743561Skato .set PAG_CNT,0x1000 # Pages to map 38128710Sru/* 39200254Snyan * Fields in %eflags. 40200254Snyan */ 41200254Snyan .set PSL_RESERVED_DEFAULT,0x00000002 42200254Snyan .set PSL_T,0x00000100 # Trap flag 43200254Snyan .set PSL_I,0x00000200 # Interrupt enable flag 44200254Snyan .set PSL_VM,0x00020000 # Virtual 8086 mode flag 45200254Snyan .set PSL_AC,0x00040000 # Alignment check flag 46200254Snyan/* 47128710Sru * Segment selectors. 48128710Sru */ 4943561Skato .set SEL_SCODE,0x8 # Supervisor code 5043561Skato .set SEL_SDATA,0x10 # Supervisor data 5143561Skato .set SEL_RCODE,0x18 # Real mode code 5243561Skato .set SEL_RDATA,0x20 # Real mode data 5343561Skato .set SEL_UCODE,0x28|3 # User code 5443561Skato .set SEL_UDATA,0x30|3 # User data 5543561Skato .set SEL_TSS,0x38 # TSS 56128710Sru/* 57128710Sru * Task state segment fields. 58128710Sru */ 5943561Skato .set TSS_ESP0,0x4 # PL 0 ESP 6043561Skato .set TSS_SS0,0x8 # PL 0 SS 6143561Skato .set TSS_MAP,0x66 # I/O bit map base 62128710Sru/* 63128710Sru * System calls. 64128710Sru */ 6543561Skato .set SYS_EXIT,0x0 # Exit 6643561Skato .set SYS_EXEC,0x1 # Exec 67128710Sru/* 68200254Snyan * Fields in V86 interface structure. 69128710Sru */ 70200254Snyan .set V86_CTL,0x0 # Control flags 71200254Snyan .set V86_ADDR,0x4 # Int number/address 72200254Snyan .set V86_ES,0x8 # V86 ES 73200254Snyan .set V86_DS,0xc # V86 DS 74200254Snyan .set V86_FS,0x10 # V86 FS 75200254Snyan .set V86_GS,0x14 # V86 GS 76128710Sru/* 77200254Snyan * V86 control flags. 78200254Snyan */ 79200254Snyan .set V86F_ADDR,0x10000 # Segment:offset address 80200254Snyan .set V86F_CALLF,0x20000 # Emulate far call 81200254Snyan .set V86F_FLAGS,0x40000 # Return flags 82200254Snyan/* 83128710Sru * Dump format control bytes. 84128710Sru */ 8543561Skato .set DMP_X16,0x1 # Word 8643561Skato .set DMP_X32,0x2 # Long 8743561Skato .set DMP_MEM,0x4 # Memory 8843561Skato .set DMP_EOL,0x8 # End of line 89128710Sru/* 90128710Sru * Screen defaults and assumptions. 91128710Sru */ 9243561Skato .set SCR_MAT,0xe1 # Mode/attribute 9343561Skato .set SCR_COL,0x50 # Columns per row 9443561Skato .set SCR_ROW,0x19 # Rows per screen 95128710Sru/* 96128710Sru * BIOS Data Area locations. 97128710Sru */ 9858871Skato .set BDA_MEM,0x501 # Free memory 9958871Skato .set BDA_POS,0x53e # Cursor position 100128710Sru/* 101128710Sru * Derivations, for brevity. 102128710Sru */ 10343561Skato .set _ESP0H,MEM_ESP0>>0x8 # Byte 1 of ESP0 10443561Skato .set _TSSIO,MEM_MAP-MEM_TSS # TSS I/O base 105176645Snyan .set _TSSLM,MEM_TSS_END-MEM_TSS # TSS limit 10643561Skato .set _IDTLM,MEM_TSS-MEM_IDT-1 # IDT limit 107128710Sru/* 108128710Sru * Code segment. 109128710Sru */ 11043561Skato .globl start 11161064Snyan .code16 11243561Skatostart: # Start of code 113128710Sru/* 114128710Sru * BTX header. 115128710Sru */ 11643561Skatobtx_hdr: .byte 0xeb # Machine ID 11743561Skato .byte 0xe # Header size 11843561Skato .ascii "BTX" # Magic 11943561Skato .byte 0x1 # Major version 120200254Snyan .byte 0x2 # Minor version 12168358Snyan .byte BTX_FLAGS # Flags 12243561Skato .word PAG_CNT-MEM_ORG>>0xc # Paging control 12343561Skato .word break-start # Text size 12443561Skato .long 0x0 # Entry address 125128710Sru/* 126128710Sru * Initialization routine. 127128710Sru */ 12843561Skatoinit: cli # Disable interrupts 12961064Snyan xor %ax,%ax # Zero/segment 13061064Snyan mov %ax,%ss # Set up 13161064Snyan mov $MEM_ESP0,%sp # stack 13261064Snyan mov %ax,%es # Address 13361064Snyan mov %ax,%ds # data 13461064Snyan pushl $0x2 # Clear 13561064Snyan popfl # flags 136128710Sru/* 137128710Sru * Initialize memory. 138128710Sru */ 13961064Snyan mov $MEM_IDT,%di # Memory to initialize 14061064Snyan mov $(MEM_ORG-MEM_IDT)/2,%cx # Words to zero 14143561Skato rep # Zero-fill 14261064Snyan stosw # memory 143128710Sru/* 144200254Snyan * Update real mode IDT for reflecting hardware interrupts. 145200254Snyan */ 146200254Snyan mov $intr20,%bx # Address first handler 147200254Snyan mov $0x10,%cx # Number of handlers 148200254Snyan mov $0x20*4,%di # First real mode IDT entry 149200254Snyaninit.0: mov %bx,(%di) # Store IP 150200254Snyan inc %di # Address next 151200254Snyan inc %di # entry 152200254Snyan stosw # Store CS 153200254Snyan add $4,%bx # Next handler 154200254Snyan loop init.0 # Next IRQ 155200254Snyan/* 156128710Sru * Create IDT. 157128710Sru */ 158200254Snyan mov $MEM_IDT,%di 15961064Snyan mov $idtctl,%si # Control string 16043561Skatoinit.1: lodsb # Get entry 16161064Snyan cbw # count 16261064Snyan xchg %ax,%cx # as word 16361064Snyan jcxz init.4 # If done 16443561Skato lodsb # Get segment 16561064Snyan xchg %ax,%dx # P:DPL:type 16661064Snyan lodsw # Get control 16761064Snyan xchg %ax,%bx # set 16861064Snyan lodsw # Get handler offset 16961064Snyan mov $SEL_SCODE,%dh # Segment selector 17061064Snyaninit.2: shr %bx # Handle this int? 17143561Skato jnc init.3 # No 17261064Snyan mov %ax,(%di) # Set handler offset 17361064Snyan mov %dh,0x2(%di) # and selector 17461064Snyan mov %dl,0x5(%di) # Set P:DPL:type 17561064Snyan add $0x4,%ax # Next handler 17661064Snyaninit.3: lea 0x8(%di),%di # Next entry 17743561Skato loop init.2 # Till set done 17843561Skato jmp init.1 # Continue 179128710Sru/* 180128710Sru * Initialize TSS. 181128710Sru */ 18261064Snyaninit.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 18361064Snyan movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 18461064Snyan movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base 185128710Sru/* 186128710Sru * Bring up the system. 187128710Sru */ 18861064Snyan mov $0x2820,%bx # Set protected mode 18961064Snyan callw setpic # IRQ offsets 19061064Snyan lidt idtdesc # Set IDT 19161064Snyan lgdt gdtdesc # Set GDT 19261064Snyan mov %cr0,%eax # Switch to protected 193164114Snyan inc %ax # mode 194128710Sru mov %eax,%cr0 # 19561064Snyan ljmp $SEL_SCODE,$init.8 # To 32-bit code 19661064Snyan .code32 19743561Skatoinit.8: xorl %ecx,%ecx # Zero 19843561Skato movb $SEL_SDATA,%cl # To 32-bit 19961064Snyan movw %cx,%ss # stack 200128710Sru/* 201128710Sru * Launch user task. 202128710Sru */ 20343561Skato movb $SEL_TSS,%cl # Set task 20461064Snyan ltr %cx # register 20543561Skato movl $MEM_USR,%edx # User base address 20643561Skato movzwl %ss:BDA_MEM,%eax # Get free memory 20743561Skato andl $0x7,%eax 20843561Skato incl %eax 20943561Skato shll $0x11,%eax # To bytes 210237763Savg subl $ARGSPACE,%eax # Less arg space 21143561Skato subl %edx,%eax # Less base 21243561Skato movb $SEL_UDATA,%cl # User data selector 21343561Skato pushl %ecx # Set SS 21443561Skato pushl %eax # Set ESP 21561064Snyan push $0x202 # Set flags (IF set) 21661064Snyan push $SEL_UCODE # Set CS 21743561Skato pushl btx_hdr+0xc # Set EIP 21843561Skato pushl %ecx # Set GS 21943561Skato pushl %ecx # Set FS 22043561Skato pushl %ecx # Set DS 22143561Skato pushl %ecx # Set ES 22243561Skato pushl %edx # Set EAX 22343561Skato movb $0x7,%cl # Set remaining 22461064Snyaninit.9: push $0x0 # general 22543561Skato loop init.9 # registers 226125780Snyan#ifdef BTX_SERIAL 22786497Snyan call sio_init # setup the serial console 228125780Snyan#endif 22943561Skato popa # and initialize 23043561Skato popl %es # Initialize 23143561Skato popl %ds # user 23243561Skato popl %fs # segment 23343561Skato popl %gs # registers 23443561Skato iret # To user mode 235128710Sru/* 236128710Sru * Exit routine. 237128710Sru */ 23843561Skatoexit: cli # Disable interrupts 23943561Skato movl $MEM_ESP0,%esp # Clear stack 240128710Sru/* 241128710Sru * Turn off paging. 242128710Sru */ 24343561Skato movl %cr0,%eax # Get CR0 24443561Skato andl $~0x80000000,%eax # Disable 24543561Skato movl %eax,%cr0 # paging 24643561Skato xorl %ecx,%ecx # Zero 24743561Skato movl %ecx,%cr3 # Flush TLB 248128710Sru/* 249128710Sru * Restore the GDT in case we caught a kernel trap. 250128710Sru */ 25176927Snyan lgdt gdtdesc # Set GDT 252128710Sru/* 253128710Sru * To 16 bits. 254128710Sru */ 25561064Snyan ljmpw $SEL_RCODE,$exit.1 # Reload CS 25661064Snyan .code16 25761064Snyanexit.1: mov $SEL_RDATA,%cl # 16-bit selector 25861064Snyan mov %cx,%ss # Reload SS 25961064Snyan mov %cx,%ds # Load 26061064Snyan mov %cx,%es # remaining 26161064Snyan mov %cx,%fs # segment 26261064Snyan mov %cx,%gs # registers 263128710Sru/* 264128710Sru * To real-address mode. 265128710Sru */ 26661064Snyan dec %ax # Switch to 26761064Snyan mov %eax,%cr0 # real mode 26861064Snyan ljmp $0x0,$exit.2 # Reload CS 26961064Snyanexit.2: xor %ax,%ax # Real mode segment 27061064Snyan mov %ax,%ss # Reload SS 27161064Snyan mov %ax,%ds # Address data 27261064Snyan mov $0x1008,%bx # Set real mode 27361064Snyan callw setpic # IRQ offsets 27461064Snyan lidt ivtdesc # Set IVT 275128710Sru/* 276128710Sru * Reboot or await reset. 277128710Sru */ 27843561Skato sti # Enable interrupts 27961064Snyan testb $0x1,btx_hdr+0x7 # Reboot? 28043561Skatoexit.3: jz exit.3 # No 28143561Skato movb $0xa0,%al 28243561Skato outb %al,$0x35 283200254Snyan movb $0x00,%al 284200254Snyan outb %al,$0xf0 # reboot the machine 28543561Skatoexit.4: jmp exit.4 286128710Sru/* 287128710Sru * Set IRQ offsets by reprogramming 8259A PICs. 288128710Sru */ 28961064Snyansetpic: in $0x02,%al # Save master 29061064Snyan push %ax # IMR 29161064Snyan in $0x0a,%al # Save slave 29261064Snyan push %ax # IMR 29343561Skato movb $0x11,%al # ICW1 to 29443561Skato outb %al,$0x00 # master, 29543561Skato outb %al,$0x08 # slave 29643561Skato movb %bl,%al # ICW2 to 29743561Skato outb %al,$0x02 # master 29843561Skato movb %bh,%al # ICW2 to 29943561Skato outb %al,$0x0a # slave 30043561Skato movb $0x80,%al # ICW3 to 30143561Skato outb %al,$0x02 # master 30243561Skato movb $0x7,%al # ICW3 to 30343561Skato outb %al,$0x0a # slave 30443561Skato movb $0x1d,%al # ICW4 to 30543561Skato outb %al,$0x02 # master, 30643561Skato movb $0x9,%al # ICW4 to 30743561Skato outb %al,$0x0a # slave 30861064Snyan pop %ax # Restore slave 30943561Skato outb %al,$0x0a # IMR 31061064Snyan pop %ax # Restore master 31143561Skato outb %al,$0x02 # IMR 31261064Snyan retw # To caller 31361064Snyan .code32 314128710Sru/* 315128710Sru * Exception jump table. 316128710Sru */ 31761064Snyanintx00: push $0x0 # Int 0x0: #DE 31843561Skato jmp ex_noc # Divide error 31961064Snyan push $0x1 # Int 0x1: #DB 32043561Skato jmp ex_noc # Debug 32161064Snyan push $0x3 # Int 0x3: #BP 32243561Skato jmp ex_noc # Breakpoint 32361064Snyan push $0x4 # Int 0x4: #OF 32443561Skato jmp ex_noc # Overflow 32561064Snyan push $0x5 # Int 0x5: #BR 32643561Skato jmp ex_noc # BOUND range exceeded 32761064Snyan push $0x6 # Int 0x6: #UD 32843561Skato jmp ex_noc # Invalid opcode 32961064Snyan push $0x7 # Int 0x7: #NM 33043561Skato jmp ex_noc # Device not available 33161064Snyan push $0x8 # Int 0x8: #DF 33243561Skato jmp except # Double fault 33361064Snyan push $0xa # Int 0xa: #TS 33443561Skato jmp except # Invalid TSS 33561064Snyan push $0xb # Int 0xb: #NP 33643561Skato jmp except # Segment not present 33761064Snyan push $0xc # Int 0xc: #SS 33843561Skato jmp except # Stack segment fault 33961064Snyan push $0xd # Int 0xd: #GP 340200254Snyan jmp except # General protection 34161064Snyan push $0xe # Int 0xe: #PF 34243561Skato jmp except # Page fault 34361064Snyanintx10: push $0x10 # Int 0x10: #MF 34443561Skato jmp ex_noc # Floating-point error 345128710Sru/* 346128710Sru * Save a zero error code. 347128710Sru */ 34843561Skatoex_noc: pushl (%esp,1) # Duplicate int no 34943561Skato movb $0x0,0x4(%esp,1) # Fake error code 350128710Sru/* 351128710Sru * Handle exception. 352128710Sru */ 35343561Skatoexcept: cld # String ops inc 35443561Skato pushl %ds # Save 35543561Skato pushl %es # most 35643561Skato pusha # registers 35743561Skato pushl %gs # Set GS 35843561Skato pushl %fs # Set FS 35943561Skato pushl %ds # Set DS 36043561Skato pushl %es # Set ES 36143561Skato cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? 36243561Skato jne except.1 # No 36343561Skato pushl %ss # Set SS 36443561Skato jmp except.2 # Join common code 365200254Snyanexcept.1: pushl 0x50(%esp,1) # Set SS 366200254Snyanexcept.2: pushl 0x50(%esp,1) # Set ESP 367200254Snyan push $SEL_SDATA # Set up 36843561Skato popl %ds # to 36943561Skato pushl %ds # address 37043561Skato popl %es # data 37143561Skato movl %esp,%ebx # Stack frame 37243561Skato movl $dmpfmt,%esi # Dump format string 37343561Skato movl $MEM_BUF,%edi # Buffer 37443561Skato pushl %eax 37543561Skato pushl %edx 376200254Snyanwait.1: inb $0x60,%al 37743561Skato testb $0x04,%al 37843561Skato jz wait.1 37943561Skato movb $0xe0,%al 38043561Skato outb %al,$0x62 381200254Snyanwait.2: inb $0x60,%al 38243561Skato testb $0x01,%al 38343561Skato jz wait.2 38443561Skato xorl %edx,%edx 38543561Skato inb $0x62,%al 38643561Skato movb %al,%dl 38743561Skato inb $0x62,%al 38843561Skato movb %al,%dh 38943561Skato inb $0x62,%al 39043561Skato inb $0x62,%al 39143561Skato inb $0x62,%al 39243561Skato movl %edx,%eax 39343561Skato shlw $1,%ax 39443561Skato movl $BDA_POS,%edx 39543561Skato movw %ax,(%edx) 39643561Skato popl %edx 39743561Skato popl %eax 39843561Skato pushl %edi # Dump to 39943561Skato call dump # buffer 40043561Skato popl %esi # and 40143561Skato call putstr # display 40243561Skato leal 0x18(%esp,1),%esp # Discard frame 40343561Skato popa # Restore 40443561Skato popl %es # registers 40543561Skato popl %ds # saved 40643561Skato cmpb $0x3,(%esp,1) # Breakpoint? 40743561Skato je except.3 # Yes 40886497Snyan cmpb $0x1,(%esp,1) # Debug? 40986497Snyan jne except.2a # No 410200254Snyan testl $PSL_T,0x10(%esp,1) # Trap flag set? 41186497Snyan jnz except.3 # Yes 41286497Snyanexcept.2a: jmp exit # Exit 41343561Skatoexcept.3: leal 0x8(%esp,1),%esp # Discard err, int no 41443561Skato iret # From interrupt 41552202Skato 416128710Sru/* 417128710Sru * Reboot the machine by setting the reboot flag and exiting 418128710Sru */ 41958871Skatoreboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag 42058871Skato jmp exit # Terminate BTX and reboot 42158871Skato 422128710Sru/* 423200254Snyan * Protected Mode Hardware interrupt jump table. 424128710Sru */ 42561064Snyanintx20: push $0x8 # Int 0x20: IRQ0 42643561Skato jmp int_hw # V86 int 0x8 42761064Snyan push $0x9 # Int 0x21: IRQ1 42843561Skato jmp int_hw # V86 int 0x9 42961064Snyan push $0xa # Int 0x22: IRQ2 43043561Skato jmp int_hw # V86 int 0xa 43161064Snyan push $0xb # Int 0x23: IRQ3 43243561Skato jmp int_hw # V86 int 0xb 43361064Snyan push $0xc # Int 0x24: IRQ4 43443561Skato jmp int_hw # V86 int 0xc 43561064Snyan push $0xd # Int 0x25: IRQ5 43643561Skato jmp int_hw # V86 int 0xd 43761064Snyan push $0xe # Int 0x26: IRQ6 43843561Skato jmp int_hw # V86 int 0xe 43961064Snyan push $0xf # Int 0x27: IRQ7 44043561Skato jmp int_hw # V86 int 0xf 44161064Snyan push $0x10 # Int 0x28: IRQ8 44243561Skato jmp int_hw # V86 int 0x10 44361064Snyan push $0x11 # Int 0x29: IRQ9 44443561Skato jmp int_hw # V86 int 0x11 44561064Snyan push $0x12 # Int 0x2a: IRQ10 44643561Skato jmp int_hw # V86 int 0x12 44761064Snyan push $0x13 # Int 0x2b: IRQ11 44843561Skato jmp int_hw # V86 int 0x13 44961064Snyan push $0x14 # Int 0x2c: IRQ12 45043561Skato jmp int_hw # V86 int 0x14 45161064Snyan push $0x15 # Int 0x2d: IRQ13 45243561Skato jmp int_hw # V86 int 0x15 45361064Snyan push $0x16 # Int 0x2e: IRQ14 45443561Skato jmp int_hw # V86 int 0x16 45561064Snyan push $0x17 # Int 0x2f: IRQ15 45643561Skato jmp int_hw # V86 int 0x17 457200254Snyan 458128710Sru/* 459200254Snyan * Invoke real mode interrupt/function call from user mode with arguments. 460128710Sru */ 461200254Snyanintx31: pushl $-1 # Dummy int no for btx_v86 462128710Sru/* 463200254Snyan * Invoke real mode interrupt/function call from protected mode. 464200254Snyan * 465200254Snyan * We place a trampoline on the user stack that will return to rret_tramp 466200254Snyan * which will reenter protected mode and then finally return to the user 467200254Snyan * client. 468200254Snyan * 469200254Snyan * Kernel frame %esi points to: Real mode stack frame at MEM_ESPR: 470200254Snyan * 471200254Snyan * -0x00 user %ss -0x04 kernel %esp (with full frame) 472200254Snyan * -0x04 user %esp -0x08 btx_v86 pointer 473200254Snyan * -0x08 user %eflags -0x0c flags (only used if interrupt) 474200254Snyan * -0x0c user %cs -0x10 real mode CS:IP return trampoline 475200254Snyan * -0x10 user %eip -0x12 real mode flags 476200254Snyan * -0x14 int no -0x16 real mode CS:IP (target) 477200254Snyan * -0x18 %eax 478200254Snyan * -0x1c %ecx 479200254Snyan * -0x20 %edx 480200254Snyan * -0x24 %ebx 481200254Snyan * -0x28 %esp 482200254Snyan * -0x2c %ebp 483200254Snyan * -0x30 %esi 484200254Snyan * -0x34 %edi 485200254Snyan * -0x38 %gs 486200254Snyan * -0x3c %fs 487200254Snyan * -0x40 %ds 488200254Snyan * -0x44 %es 489200254Snyan * -0x48 zero %eax (hardware int only) 490200254Snyan * -0x4c zero %ecx (hardware int only) 491200254Snyan * -0x50 zero %edx (hardware int only) 492200254Snyan * -0x54 zero %ebx (hardware int only) 493200254Snyan * -0x58 zero %esp (hardware int only) 494200254Snyan * -0x5c zero %ebp (hardware int only) 495200254Snyan * -0x60 zero %esi (hardware int only) 496200254Snyan * -0x64 zero %edi (hardware int only) 497200254Snyan * -0x68 zero %gs (hardware int only) 498200254Snyan * -0x6c zero %fs (hardware int only) 499200254Snyan * -0x70 zero %ds (hardware int only) 500200254Snyan * -0x74 zero %es (hardware int only) 501128710Sru */ 502200254Snyanint_hw: cld # String ops inc 503200254Snyan pusha # Save gp regs 50443561Skato pushl %gs # Save 505200254Snyan pushl %fs # seg 506200254Snyan pushl %ds # regs 507200254Snyan pushl %es 50861064Snyan push $SEL_SDATA # Set up 50943561Skato popl %ds # to 51043561Skato pushl %ds # address 51143561Skato popl %es # data 512200254Snyan leal 0x44(%esp,1),%esi # Base of frame 513200254Snyan movl %esp,MEM_ESPR-0x04 # Save kernel stack pointer 514200254Snyan movl -0x14(%esi),%eax # Get Int no 515200254Snyan cmpl $-1,%eax # Hardware interrupt? 516200254Snyan jne intusr.1 # Yes 517200254Snyan/* 518200254Snyan * v86 calls save the btx_v86 pointer on the real mode stack and read 519200254Snyan * the address and flags from the btx_v86 structure. For interrupt 520200254Snyan * handler invocations (VM86 INTx requests), disable interrupts, 521200254Snyan * tracing, and alignment checking while the handler runs. 522200254Snyan */ 52343561Skato movl $MEM_USR,%ebx # User base 52443561Skato movl %ebx,%edx # address 52543561Skato addl -0x4(%esi),%ebx # User ESP 52643561Skato movl (%ebx),%ebp # btx_v86 pointer 52743561Skato addl %ebp,%edx # Flatten btx_v86 ptr 528200254Snyan movl %edx,MEM_ESPR-0x08 # Save btx_v86 ptr 529200254Snyan movl V86_ADDR(%edx),%eax # Get int no/address 530200254Snyan movl V86_CTL(%edx),%edx # Get control flags 531200254Snyan movl -0x08(%esi),%ebx # Save user flags in %ebx 532200254Snyan testl $V86F_ADDR,%edx # Segment:offset? 533200254Snyan jnz intusr.4 # Yes 534200254Snyan andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing, 535200254Snyan # and alignment checking for 536200254Snyan # interrupt handler 537200254Snyan jmp intusr.3 # Skip hardware interrupt 538200254Snyan/* 539200254Snyan * Hardware interrupts store a NULL btx_v86 pointer and use the 540200254Snyan * address (interrupt number) from the stack with empty flags. Also, 541200254Snyan * push a dummy frame of zeros onto the stack for all the general 542200254Snyan * purpose and segment registers and clear %eflags. This gives the 543200254Snyan * hardware interrupt handler a clean slate. 544200254Snyan */ 545200254Snyanintusr.1: xorl %edx,%edx # Control flags 546200254Snyan movl %edx,MEM_ESPR-0x08 # NULL btx_v86 ptr 547200254Snyan movl $12,%ecx # Frame is 12 dwords 548200254Snyanintusr.2: pushl $0x0 # Fill frame 549200254Snyan loop intusr.2 # with zeros 550200254Snyan movl $PSL_RESERVED_DEFAULT,%ebx # Set clean %eflags 551200254Snyan/* 552200254Snyan * Look up real mode IDT entry for hardware interrupts and VM86 INTx 553200254Snyan * requests. 554200254Snyan */ 555200254Snyanintusr.3: shll $0x2,%eax # Scale 55643561Skato movl (%eax),%eax # Load int vector 557200254Snyan jmp intusr.5 # Skip CALLF test 558128710Sru/* 559200254Snyan * Panic if V86F_CALLF isn't set with V86F_ADDR. 560200254Snyan */ 561200254Snyanintusr.4: testl $V86F_CALLF,%edx # Far call? 562200254Snyan jnz intusr.5 # Ok 563200254Snyan movl %edx,0x30(%esp,1) # Place VM86 flags in int no 564200254Snyan movl $badvm86,%esi # Display bad 565200254Snyan call putstr # VM86 call 566200254Snyan popl %es # Restore 567200254Snyan popl %ds # seg 568200254Snyan popl %fs # regs 569200254Snyan popl %gs 570200254Snyan popal # Restore gp regs 571200254Snyan jmp ex_noc # Panic 572200254Snyan/* 573200254Snyan * %eax now holds the segment:offset of the function. 574200254Snyan * %ebx now holds the %eflags to pass to real mode. 575200254Snyan * %edx now holds the V86F_* flags. 576200254Snyan */ 577200254Snyanintusr.5: movw %bx,MEM_ESPR-0x12 # Pass user flags to real mode 578200254Snyan # target 579200254Snyan/* 580200254Snyan * If this is a v86 call, copy the seg regs out of the btx_v86 structure. 581200254Snyan */ 582200254Snyan movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr 583200254Snyan jecxz intusr.6 # Skip for hardware ints 584200254Snyan leal -0x44(%esi),%edi # %edi => kernel stack seg regs 585200254Snyan pushl %esi # Save 586200254Snyan leal V86_ES(%ecx),%esi # %esi => btx_v86 seg regs 587200254Snyan movl $4,%ecx # Copy seg regs 588200254Snyan rep # from btx_v86 589200254Snyan movsl # to kernel stack 590200254Snyan popl %esi # Restore 591200254Snyanintusr.6: movl -0x08(%esi),%ebx # Copy user flags to real 592200254Snyan movl %ebx,MEM_ESPR-0x0c # mode return trampoline 593200254Snyan movl $rret_tramp,%ebx # Set return trampoline 594200254Snyan movl %ebx,MEM_ESPR-0x10 # CS:IP 595200254Snyan movl %eax,MEM_ESPR-0x16 # Real mode target CS:IP 596200254Snyan ljmpw $SEL_RCODE,$intusr.7 # Change to 16-bit segment 597200254Snyan .code16 598200254Snyanintusr.7: movl %cr0,%eax # Leave 599200254Snyan dec %al # protected 600200254Snyan movl %eax,%cr0 # mode 601200254Snyan ljmpw $0x0,$intusr.8 602200254Snyanintusr.8: xorw %ax,%ax # Reset %ds 603200254Snyan movw %ax,%ds # and 604200254Snyan movw %ax,%ss # %ss 605200254Snyan lidt ivtdesc # Set IVT 606200254Snyan popl %es # Restore 607200254Snyan popl %ds # seg 608200254Snyan popl %fs # regs 609200254Snyan popl %gs 610200254Snyan popal # Restore gp regs 611200254Snyan movw $MEM_ESPR-0x16,%sp # Switch to real mode stack 612200254Snyan iret # Call target routine 613200254Snyan/* 614200254Snyan * For the return to real mode we setup a stack frame like this on the real 615200254Snyan * mode stack. Note that callf calls won't pop off the flags, but we just 616200254Snyan * ignore that by repositioning %sp to be just above the btx_v86 pointer 617200254Snyan * so it is aligned. The stack is relative to MEM_ESPR. 618200254Snyan * 619200254Snyan * -0x04 kernel %esp 620200254Snyan * -0x08 btx_v86 621200254Snyan * -0x0c %eax 622200254Snyan * -0x10 %ecx 623200254Snyan * -0x14 %edx 624200254Snyan * -0x18 %ebx 625200254Snyan * -0x1c %esp 626200254Snyan * -0x20 %ebp 627200254Snyan * -0x24 %esi 628200254Snyan * -0x28 %edi 629200254Snyan * -0x2c %gs 630200254Snyan * -0x30 %fs 631200254Snyan * -0x34 %ds 632200254Snyan * -0x38 %es 633200254Snyan * -0x3c %eflags 634200254Snyan */ 635200254Snyanrret_tramp: movw $MEM_ESPR-0x08,%sp # Reset stack pointer 636200254Snyan pushal # Save gp regs 637200254Snyan pushl %gs # Save 638200254Snyan pushl %fs # seg 639200254Snyan pushl %ds # regs 640200254Snyan pushl %es 641200254Snyan pushfl # Save %eflags 642200254Snyan cli # Disable interrupts 643200254Snyan std # String ops dec 644200254Snyan xorw %ax,%ax # Reset seg 645200254Snyan movw %ax,%ds # regs 646200254Snyan movw %ax,%es # (%ss is already 0) 647200254Snyan lidt idtdesc # Set IDT 648200254Snyan lgdt gdtdesc # Set GDT 649200254Snyan mov %cr0,%eax # Switch to protected 650200254Snyan inc %ax # mode 651200254Snyan mov %eax,%cr0 # 652200254Snyan ljmp $SEL_SCODE,$rret_tramp.1 # To 32-bit code 653200254Snyan .code32 654200254Snyanrret_tramp.1: xorl %ecx,%ecx # Zero 655200254Snyan movb $SEL_SDATA,%cl # Setup 656200254Snyan movw %cx,%ss # 32-bit 657200254Snyan movw %cx,%ds # seg 658200254Snyan movw %cx,%es # regs 659200254Snyan movl MEM_ESPR-0x04,%esp # Switch to kernel stack 660200254Snyan leal 0x44(%esp,1),%esi # Base of frame 661200254Snyan andb $~0x2,tss_desc+0x5 # Clear TSS busy 662200254Snyan movb $SEL_TSS,%cl # Set task 663200254Snyan ltr %cx # register 664200254Snyan/* 665200254Snyan * Now we are back in protected mode. The kernel stack frame set up 666200254Snyan * before entering real mode is still intact. For hardware interrupts, 667200254Snyan * leave the frame unchanged. 668200254Snyan */ 669200254Snyan cmpl $0,MEM_ESPR-0x08 # Leave saved regs unchanged 670200254Snyan jz rret_tramp.3 # for hardware ints 671200254Snyan/* 672200254Snyan * For V86 calls, copy the registers off of the real mode stack onto 673200254Snyan * the kernel stack as we want their updated values. Also, initialize 674200254Snyan * the segment registers on the kernel stack. 675200254Snyan * 676200254Snyan * Note that the %esp in the kernel stack after this is garbage, but popa 677200254Snyan * ignores it, so we don't have to fix it up. 678200254Snyan */ 679200254Snyan leal -0x18(%esi),%edi # Kernel stack GP regs 680200254Snyan pushl %esi # Save 681200254Snyan movl $MEM_ESPR-0x0c,%esi # Real mode stack GP regs 682200254Snyan movl $8,%ecx # Copy GP regs from 683200254Snyan rep # real mode stack 684200254Snyan movsl # to kernel stack 685200254Snyan movl $SEL_UDATA,%eax # Selector for data seg regs 686200254Snyan movl $4,%ecx # Initialize %ds, 687200254Snyan rep # %es, %fs, and 688200254Snyan stosl # %gs 689200254Snyan/* 690200254Snyan * For V86 calls, copy the saved seg regs on the real mode stack back 691200254Snyan * over to the btx_v86 structure. Also, conditionally update the 692200254Snyan * saved eflags on the kernel stack based on the flags from the user. 693200254Snyan */ 694200254Snyan movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr 695200254Snyan leal V86_GS(%ecx),%edi # %edi => btx_v86 seg regs 696200254Snyan leal MEM_ESPR-0x2c,%esi # %esi => real mode seg regs 697200254Snyan xchgl %ecx,%edx # Save btx_v86 ptr 698200254Snyan movl $4,%ecx # Copy seg regs 699200254Snyan rep # from real mode stack 700200254Snyan movsl # to btx_v86 701200254Snyan popl %esi # Restore 702200254Snyan movl V86_CTL(%edx),%edx # Read V86 control flags 703200254Snyan testl $V86F_FLAGS,%edx # User wants flags? 704200254Snyan jz rret_tramp.3 # No 705200254Snyan movl MEM_ESPR-0x3c,%eax # Read real mode flags 706200254Snyan movw %ax,-0x08(%esi) # Update user flags (low 16) 707200254Snyan/* 708200254Snyan * Return to the user task 709200254Snyan */ 710200254Snyanrret_tramp.3: popl %es # Restore 711200254Snyan popl %ds # seg 712200254Snyan popl %fs # regs 713200254Snyan popl %gs 714200254Snyan popal # Restore gp regs 715200254Snyan addl $4,%esp # Discard int no 716200254Snyan iret # Return to user mode 717200254Snyan 718200254Snyan/* 719128710Sru * System Call. 720128710Sru */ 72143561Skatointx30: cmpl $SYS_EXEC,%eax # Exec system call? 72243561Skato jne intx30.1 # No 72343561Skato pushl %ss # Set up 72443561Skato popl %es # all 72543561Skato pushl %es # segment 72643561Skato popl %ds # registers 72743561Skato pushl %ds # for the 72843561Skato popl %fs # program 72943561Skato pushl %fs # we're 73043561Skato popl %gs # invoking 73143561Skato movl $MEM_USR,%eax # User base address 73243561Skato addl 0xc(%esp,1),%eax # Change to user 73343561Skato leal 0x4(%eax),%esp # stack 73443561Skato popl %eax # Call 73543561Skato call *%eax # program 73678650Skatointx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot 73743561Skato jmp exit # Exit 738128710Sru/* 739128710Sru * Dump structure [EBX] to [EDI], using format string [ESI]. 740128710Sru */ 74143561Skatodump.0: stosb # Save char 74243561Skatodump: lodsb # Load char 74343561Skato testb %al,%al # End of string? 74443561Skato jz dump.10 # Yes 74543561Skato testb $0x80,%al # Control? 74643561Skato jz dump.0 # No 74743561Skato movb %al,%ch # Save control 74843561Skato movb $'=',%al # Append 74943561Skato stosb # '=' 75043561Skato lodsb # Get offset 75143561Skato pushl %esi # Save 75243561Skato movsbl %al,%esi # To 75343561Skato addl %ebx,%esi # pointer 75443561Skato testb $DMP_X16,%ch # Dump word? 75543561Skato jz dump.1 # No 75643561Skato lodsw # Get and 75743561Skato call hex16 # dump it 75843561Skatodump.1: testb $DMP_X32,%ch # Dump long? 75943561Skato jz dump.2 # No 76043561Skato lodsl # Get and 76143561Skato call hex32 # dump it 76243561Skatodump.2: testb $DMP_MEM,%ch # Dump memory? 76343561Skato jz dump.8 # No 76443561Skato pushl %ds # Save 765200254Snyan testl $PSL_VM,0x50(%ebx) # V86 mode? 76643561Skato jnz dump.3 # Yes 76761064Snyan verr 0x4(%esi) # Readable selector? 76843561Skato jnz dump.3 # No 76943561Skato ldsl (%esi),%esi # Load pointer 77043561Skato jmp dump.4 # Join common code 77143561Skatodump.3: lodsl # Set offset 77243561Skato xchgl %eax,%edx # Save 77343561Skato lodsl # Get segment 77443561Skato shll $0x4,%eax # * 0x10 77543561Skato addl %edx,%eax # + offset 77643561Skato xchgl %eax,%esi # Set pointer 77786497Snyandump.4: movb $2,%dl # Num lines 77886497Snyandump.4a: movb $0x10,%cl # Bytes to dump 77943561Skatodump.5: lodsb # Get byte and 78043561Skato call hex8 # dump it 78143561Skato decb %cl # Keep count 78286497Snyan jz dump.6a # If done 78343561Skato movb $'-',%al # Separator 78443561Skato cmpb $0x8,%cl # Half way? 78543561Skato je dump.6 # Yes 78643561Skato movb $' ',%al # Use space 78743561Skatodump.6: stosb # Save separator 78843561Skato jmp dump.5 # Continue 78986497Snyandump.6a: decb %dl # Keep count 79086497Snyan jz dump.7 # If done 79186497Snyan movb $0xa,%al # Line feed 79286497Snyan stosb # Save one 79386497Snyan movb $7,%cl # Leading 79486497Snyan movb $' ',%al # spaces 79586497Snyandump.6b: stosb # Dump 79686497Snyan decb %cl # spaces 79786497Snyan jnz dump.6b 79886497Snyan jmp dump.4a # Next line 79943561Skatodump.7: popl %ds # Restore 80043561Skatodump.8: popl %esi # Restore 80143561Skato movb $0xa,%al # Line feed 80243561Skato testb $DMP_EOL,%ch # End of line? 80343561Skato jnz dump.9 # Yes 80443561Skato movb $' ',%al # Use spaces 80543561Skato stosb # Save one 80643561Skatodump.9: jmp dump.0 # Continue 80743561Skatodump.10: stosb # Terminate string 80843561Skato ret # To caller 809128710Sru/* 810128710Sru * Convert EAX, AX, or AL to hex, saving the result to [EDI]. 811128710Sru */ 81243561Skatohex32: pushl %eax # Save 81343561Skato shrl $0x10,%eax # Do upper 81443561Skato call hex16 # 16 81543561Skato popl %eax # Restore 81643561Skatohex16: call hex16.1 # Do upper 8 81743561Skatohex16.1: xchgb %ah,%al # Save/restore 81843561Skatohex8: pushl %eax # Save 81943561Skato shrb $0x4,%al # Do upper 82043561Skato call hex8.1 # 4 82143561Skato popl %eax # Restore 82243561Skatohex8.1: andb $0xf,%al # Get lower 4 82343561Skato cmpb $0xa,%al # Convert 82443561Skato sbbb $0x69,%al # to hex 82543561Skato das # digit 82643561Skato orb $0x20,%al # To lower case 82743561Skato stosb # Save char 82843561Skato ret # (Recursive) 829128710Sru/* 830128710Sru * Output zero-terminated string [ESI] to the console. 831128710Sru */ 83243561Skatoputstr.0: call putchr # Output char 83343561Skatoputstr: lodsb # Load char 83443561Skato testb %al,%al # End of string? 83543561Skato jnz putstr.0 # No 83643561Skato ret # To caller 837125780Snyan#ifdef BTX_SERIAL 83886497Snyan .set SIO_PRT,SIOPRT # Base port 83986497Snyan .set SIO_FMT,SIOFMT # 8N1 84086497Snyan .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD 84186497Snyan 842138189Snyan/* 843128710Sru * void sio_init(void) 844138189Snyan */ 84586497Snyansio_init: movw $SIO_PRT+0x3,%dx # Data format reg 84686497Snyan movb $SIO_FMT|0x80,%al # Set format 84786497Snyan outb %al,(%dx) # and DLAB 84886497Snyan pushl %edx # Save 84986497Snyan subb $0x3,%dl # Divisor latch reg 85086497Snyan movw $SIO_DIV,%ax # Set 85186497Snyan outw %ax,(%dx) # BPS 85286497Snyan popl %edx # Restore 85386497Snyan movb $SIO_FMT,%al # Clear 85486497Snyan outb %al,(%dx) # DLAB 85586497Snyan incl %edx # Modem control reg 85686497Snyan movb $0x3,%al # Set RTS, 85786497Snyan outb %al,(%dx) # DTR 85886497Snyan incl %edx # Line status reg 85986497Snyan 860138189Snyan/* 861128710Sru * void sio_flush(void) 862138189Snyan */ 86386497Snyansio_flush.0: call sio_getc.1 # Get character 86486497Snyansio_flush: call sio_ischar # Check for character 86586497Snyan jnz sio_flush.0 # Till none 86686497Snyan ret # To caller 86786497Snyan 868138189Snyan/* 869128710Sru * void sio_putc(int c) 870138189Snyan */ 87186497Snyansio_putc: movw $SIO_PRT+0x5,%dx # Line status reg 87286497Snyan xor %ecx,%ecx # Timeout 87386497Snyan movb $0x40,%ch # counter 87486497Snyansio_putc.1: inb (%dx),%al # Transmitter 87586497Snyan testb $0x20,%al # buffer empty? 87686497Snyan loopz sio_putc.1 # No 87786497Snyan jz sio_putc.2 # If timeout 87886497Snyan movb 0x4(%esp,1),%al # Get character 87986497Snyan subb $0x5,%dl # Transmitter hold reg 88086497Snyan outb %al,(%dx) # Write character 88186497Snyansio_putc.2: ret $0x4 # To caller 88286497Snyan 883138189Snyan/* 884128710Sru * int sio_getc(void) 885138189Snyan */ 88686497Snyansio_getc: call sio_ischar # Character available? 88786497Snyan jz sio_getc # No 88886497Snyansio_getc.1: subb $0x5,%dl # Receiver buffer reg 88986497Snyan inb (%dx),%al # Read character 89086497Snyan ret # To caller 89186497Snyan 892138189Snyan/* 893128710Sru * int sio_ischar(void) 894138189Snyan */ 89586497Snyansio_ischar: movw $SIO_PRT+0x5,%dx # Line status register 89686497Snyan xorl %eax,%eax # Zero 89786497Snyan inb (%dx),%al # Received data 89886497Snyan andb $0x1,%al # ready? 89986497Snyan ret # To caller 90086497Snyan 901128710Sru/* 902128710Sru * Output character AL to the serial console. 903128710Sru */ 90486497Snyanputchr: pusha # Save 90586497Snyan cmpb $10, %al # is it a newline? 90686497Snyan jne putchr.1 # no?, then leave 90786497Snyan push $13 # output a carriage 90886497Snyan call sio_putc # return first 90986497Snyan movb $10, %al # restore %al 91086497Snyanputchr.1: pushl %eax # Push the character 91186497Snyan # onto the stack 91286497Snyan call sio_putc # Output the character 91386497Snyan popa # Restore 91486497Snyan ret # To caller 915125780Snyan#else 916128710Sru/* 917128710Sru * Output character AL to the console. 918128710Sru */ 91943561Skatoputchr: pusha # Save 92043561Skato xorl %ecx,%ecx # Zero for loops 92143561Skato movb $SCR_MAT,%ah # Mode/attribute 92243561Skato movl $BDA_POS,%ebx # BDA pointer 92343561Skato movw (%ebx),%dx # Cursor position 92443561Skato movl $0xa0000,%edi 92543561Skatoputchr.1: cmpb $0xa,%al # New line? 92643561Skato je putchr.2 # Yes 92743561Skato movw %dx,%cx 92843561Skato movb %al,(%edi,%ecx,1) # Write char 92943561Skato addl $0x2000,%ecx 93043561Skato movb %ah,(%edi,%ecx,1) # Write attr 93143561Skato addw $0x02,%dx 93243561Skato jmp putchr.3 93343561Skatoputchr.2: movw %dx,%ax 93443561Skato movb $SCR_COL*2,%dl 93543561Skato div %dl 93643561Skato incb %al 93743561Skato mul %dl 93843561Skato movw %ax,%dx 93943561Skatoputchr.3: cmpw $SCR_ROW*SCR_COL*2,%dx 94043561Skato jb putchr.4 # No 94143561Skato leal 2*SCR_COL(%edi),%esi # New top line 94243561Skato movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 94343561Skato rep # Scroll 94443561Skato movsl # screen 94586497Snyan movb $0x20,%al # Space 94643561Skato xorb %ah,%ah 94743561Skato movb $SCR_COL,%cl # Columns to clear 94843561Skato rep # Clear 94943561Skato stosw # line 95043561Skato movw $(SCR_ROW-1)*SCR_COL*2,%dx 95143561Skatoputchr.4: movw %dx,(%ebx) # Update position 95243561Skato popa # Restore 95343561Skato ret # To caller 954125780Snyan#endif 95543561Skato 956200254Snyan .code16 957200254Snyan/* 958200254Snyan * Real Mode Hardware interrupt jump table. 959200254Snyan */ 960200254Snyanintr20: push $0x8 # Int 0x20: IRQ0 961200254Snyan jmp int_hwr # V86 int 0x8 962200254Snyan push $0x9 # Int 0x21: IRQ1 963200254Snyan jmp int_hwr # V86 int 0x9 964200254Snyan push $0xa # Int 0x22: IRQ2 965200254Snyan jmp int_hwr # V86 int 0xa 966200254Snyan push $0xb # Int 0x23: IRQ3 967200254Snyan jmp int_hwr # V86 int 0xb 968200254Snyan push $0xc # Int 0x24: IRQ4 969200254Snyan jmp int_hwr # V86 int 0xc 970200254Snyan push $0xd # Int 0x25: IRQ5 971200254Snyan jmp int_hwr # V86 int 0xd 972200254Snyan push $0xe # Int 0x26: IRQ6 973200254Snyan jmp int_hwr # V86 int 0xe 974200254Snyan push $0xf # Int 0x27: IRQ7 975200254Snyan jmp int_hwr # V86 int 0xf 976200254Snyan push $0x10 # Int 0x28: IRQ8 977200254Snyan jmp int_hwr # V86 int 0x10 978200254Snyan push $0x11 # Int 0x29: IRQ9 979200254Snyan jmp int_hwr # V86 int 0x11 980200254Snyan push $0x12 # Int 0x2a: IRQ10 981200254Snyan jmp int_hwr # V86 int 0x12 982200254Snyan push $0x13 # Int 0x2b: IRQ11 983200254Snyan jmp int_hwr # V86 int 0x13 984200254Snyan push $0x14 # Int 0x2c: IRQ12 985200254Snyan jmp int_hwr # V86 int 0x14 986200254Snyan push $0x15 # Int 0x2d: IRQ13 987200254Snyan jmp int_hwr # V86 int 0x15 988200254Snyan push $0x16 # Int 0x2e: IRQ14 989200254Snyan jmp int_hwr # V86 int 0x16 990200254Snyan push $0x17 # Int 0x2f: IRQ15 991200254Snyan jmp int_hwr # V86 int 0x17 992200254Snyan/* 993200254Snyan * Reflect hardware interrupts in real mode. 994200254Snyan */ 995200254Snyanint_hwr: push %ax # Save 996200254Snyan push %ds # Save 997200254Snyan push %bp # Save 998200254Snyan mov %sp,%bp # Address stack frame 999200254Snyan xchg %bx,6(%bp) # Swap BX, int no 1000200254Snyan xor %ax,%ax # Set %ds:%bx to 1001200254Snyan shl $2,%bx # point to 1002200254Snyan mov %ax,%ds # IDT entry 1003200254Snyan mov (%bx),%ax # Load IP 1004200254Snyan mov 2(%bx),%bx # Load CS 1005200254Snyan xchg %ax,4(%bp) # Swap saved %ax,%bx with 1006200254Snyan xchg %bx,6(%bp) # CS:IP of handler 1007200254Snyan pop %bp # Restore 1008200254Snyan pop %ds # Restore 1009200254Snyan lret # Jump to handler 1010200254Snyan 101143561Skato .p2align 4 1012128710Sru/* 1013128710Sru * Global descriptor table. 1014128710Sru */ 101543561Skatogdt: .word 0x0,0x0,0x0,0x0 # Null entry 101643561Skato .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 101743561Skato .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 101843561Skato .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 101943561Skato .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 102043561Skato .word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE 102143561Skato .word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA 1022200254Snyantss_desc: .word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS 102343561Skatogdt.1: 1024128710Sru/* 1025128710Sru * Pseudo-descriptors. 1026128710Sru */ 102743561Skatogdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT 102843561Skatoidtdesc: .word _IDTLM,MEM_IDT,0x0 # IDT 102943561Skatoivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT 1030128710Sru/* 1031128710Sru * IDT construction control string. 1032128710Sru */ 103343561Skatoidtctl: .byte 0x10, 0x8e # Int 0x0-0xf 103443561Skato .word 0x7dfb,intx00 # (exceptions) 103543561Skato .byte 0x10, 0x8e # Int 0x10 103643561Skato .word 0x1, intx10 # (exception) 103743561Skato .byte 0x10, 0x8e # Int 0x20-0x2f 103843561Skato .word 0xffff,intx20 # (hardware) 103943561Skato .byte 0x1, 0xee # int 0x30 104043561Skato .word 0x1, intx30 # (system call) 104143561Skato .byte 0x2, 0xee # Int 0x31-0x32 104243561Skato .word 0x1, intx31 # (V86, null) 104343561Skato .byte 0x0 # End of string 1044128710Sru/* 1045128710Sru * Dump format string. 1046128710Sru */ 104743561Skatodmpfmt: .byte '\n' # "\n" 104843561Skato .ascii "int" # "int=" 104943561Skato .byte 0x80|DMP_X32, 0x40 # "00000000 " 105043561Skato .ascii "err" # "err=" 105143561Skato .byte 0x80|DMP_X32, 0x44 # "00000000 " 105243561Skato .ascii "efl" # "efl=" 105343561Skato .byte 0x80|DMP_X32, 0x50 # "00000000 " 105443561Skato .ascii "eip" # "eip=" 105543561Skato .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" 105643561Skato .ascii "eax" # "eax=" 105743561Skato .byte 0x80|DMP_X32, 0x34 # "00000000 " 105843561Skato .ascii "ebx" # "ebx=" 105943561Skato .byte 0x80|DMP_X32, 0x28 # "00000000 " 106043561Skato .ascii "ecx" # "ecx=" 106143561Skato .byte 0x80|DMP_X32, 0x30 # "00000000 " 106243561Skato .ascii "edx" # "edx=" 106343561Skato .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" 106443561Skato .ascii "esi" # "esi=" 106543561Skato .byte 0x80|DMP_X32, 0x1c # "00000000 " 106643561Skato .ascii "edi" # "edi=" 106743561Skato .byte 0x80|DMP_X32, 0x18 # "00000000 " 106843561Skato .ascii "ebp" # "ebp=" 106943561Skato .byte 0x80|DMP_X32, 0x20 # "00000000 " 107043561Skato .ascii "esp" # "esp=" 107143561Skato .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" 107243561Skato .ascii "cs" # "cs=" 107343561Skato .byte 0x80|DMP_X16, 0x4c # "0000 " 107443561Skato .ascii "ds" # "ds=" 107543561Skato .byte 0x80|DMP_X16, 0xc # "0000 " 107643561Skato .ascii "es" # "es=" 107743561Skato .byte 0x80|DMP_X16, 0x8 # "0000 " 107843561Skato .ascii " " # " " 107943561Skato .ascii "fs" # "fs=" 108043561Skato .byte 0x80|DMP_X16, 0x10 # "0000 " 108143561Skato .ascii "gs" # "gs=" 108243561Skato .byte 0x80|DMP_X16, 0x14 # "0000 " 108343561Skato .ascii "ss" # "ss=" 108443561Skato .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" 108543561Skato .ascii "cs:eip" # "cs:eip=" 108643561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" 108743561Skato .ascii "ss:esp" # "ss:esp=" 108843561Skato .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" 108986497Snyan .asciz "BTX halted\n" # End 1090128710Sru/* 1091200254Snyan * Bad VM86 call panic 1092200254Snyan */ 1093200254Snyanbadvm86: .asciz "Invalid VM86 Request\n" 1094200254Snyan 1095200254Snyan/* 1096128710Sru * End of BTX memory. 1097128710Sru */ 109843561Skato .p2align 4 109943561Skatobreak: 1100