page 60,132 ;----------------------------------------------------------------------------- ; ; VME_6.ASM ; ; Copyright (c) 1995-Present Robert Collins ; ; You have my permission to copy and distribute this software for ; non-commercial purposes. Any commercial use of this software or ; source code is allowed, so long as the appropriate copyright ; attributions (to me) are intact, *AND* my email address is properly ; displayed. ; ; Basically, give me credit, where credit is due, and show my email ; address. ; ;----------------------------------------------------------------------------- ; ; Robert R. Collins email: rcollins@x86.org ; ;----------------------------------------------------------------------------- ; ; Synopsis: This set of programs (VME_n.ASM) will demonstrate how to ; reflect a software interrupt back to the v86 task. ; ;----------------------------------------------------------------------------- ; ; DPL INTR ; VME IOPL IGATE BITMAP ; VME_1.ASM 0 3 0 X ; VME_2.ASM 0 2 X X ; VME_3.ASM 0 3 3 X ; VME_4.ASM 1 3 0 1 ; VME_5.ASM 1 2 X 1 ; VME_6.ASM 1 3 3 1 *** This Program *** ; VME_7.ASM 1 3 X 0 ; VME_8.ASM 1 2 X 0 ; ; ;----------------------------------------------------------------------------- ; ; VME_6.ASM ; ;----------------------------------------------------------------------------- ;----------------------------------------------------------------------------- ; Assembler directives ;----------------------------------------------------------------------------- .xlist ; disable list file .model small .586P ;----------------------------------------------------------------------------- ; Include files ;----------------------------------------------------------------------------- Include Struct.inc Include Macros.inc Include SysSeg.inc ; System segments, GDT, IDT, TSS Include DataSeg.inc ; Normal data segment IDT_SEG segment para public use16 'DATA' ;----------------------------------------------------------------------------- ; Interrupt descriptor table ;----------------------------------------------------------------------------- org 13 * 8 IDT0D INT_Desc ; INT0D org 255 * 8 IDTFF INT_Desc ; INTFF IDT_SEG ENDS Data1 segment para public use16 'DATA' ;----------------------------------------------------------------------------- ; All other data ;----------------------------------------------------------------------------- SwapContext label far dd Offset @v86Exit,SEL_CPL0CS ;----------------------------------------------------------------------------- ; End of data segment ;----------------------------------------------------------------------------- Data1 ENDS .list Code1 segment para public use16 'CODE' ASSUME CS:Code1, DS:Data1, ES:GDT_SEG, FS:TSS_SEG, GS:DS4G, SS:STACK ;----------------------------------------------------------------------------- ; Code starts here ;----------------------------------------------------------------------------- ; Setup return from SMM ;----------------------------------------------------------------------------- Init: xor ax,ax ; clear it pushf push ds ; save far return on stack push ax mov ax,seg Data1 ; set current data segment mov ds,ax mov ax,seg GDT_SEG mov es,ax mov ax,seg TSS_SEG mov fs,ax xor ax,ax ; set segment to virtual interrupts mov gs,ax mov eax,RMINT255 ; get original INT-255 pointer mov SaveINT255,eax ; save it mov ax,ss shl eax,10h mov ax,sp mov VMEStackPtr,eax ; save it ;----------------------------------------------------------------------------- ; Check that this processor supports VME. ;----------------------------------------------------------------------------- xor eax,eax ; clear it db 66h ; were're going to do something smsw ax ; undocumented here, don't look test eax,80000001h ; page mode or pretected mode enabled? jz @F ; nope, continue mov dx,offset PG_Msg ; shl eax,1 ; check for PE jc @ErrorExit ; oops mov dx,offset PE_Msg @ErrorExit: mov ah,9 int 21h ; print message mov ax,4c01h ; set error code int 21h iret ; go split, just in case @@: mov eax,1 ; get CPUID flags cpuid ; test dx,10y ; does this processor support VME? mov dx,offset NotVME_Msg ; set message for failure jz @ErrorExit ; nope, go split INIT_GDT ; Initialize system structures GDT INIT_IDT ; IDT INIT_TSS ; TSS ;----------------------------------------------------------------------------- ; Test INT-255 when VME=1, DPL=0, CPL=0, IOPL=3, IRBitMap[255]=1 ;----------------------------------------------------------------------------- cli pushfd ; save 'em and dword ptr ss:[esp],not 111y SHL 0ch ; make IOPL=0, clear NT popfd Lidt fword ptr IDT3_Ptr ENTERPM JMPFAR @F,SEL_CPL0CS ASSUME CS:Code1, DS:Data1, ES:IDT_SEG, FS:TSS_SEG, GS:DS4G, SS:STACK ;----------------------------------------------------------------------------- ; Setup segments as follows: ; DS = Data segment ; ES = IDT segment ; FS = TSS segment ; GS = 4G segment ; SS = 32-bit stack segment ;----------------------------------------------------------------------------- @@: mov eax,cr4 or al,1 mov cr4,eax ; enable VME mov ax,SEL_CPL0SS mov ss,ax mov esp,Stack2Len ; initialize SS:ESP mov eax,SEL_CPL0DS ; set up DS mov ds,ax mov eax,SEL_IDTDS ; set up ES mov es,ax mov eax,SEL_TSSDS ; set up FS mov fs,ax mov eax,SEL_CPL0DS4G ; set up GS mov gs,ax mov ax,SEL_TSS386 ltr ax ; load task register pushfd ; save 'em pop ebx or ebx,11y SHL 0ch ; make IOPL=3 or ebx,1 SHL 11h ; set VM=1 mov eax,4567h ; GS push eax mov eax,3456h ; FS push eax mov eax,1234h ; DS push eax mov eax,2345h ; ES push eax movzx eax,word ptr VMEStackPtr[2] ; SS push eax movzx eax,word ptr VMEStackPtr[0] ; ESP push eax push ebx ; EFLAGS mov eax,seg Code1 ; get v86 code segment push eax mov eax,offset @v86 push eax iretd ; RET FAR to CPL=3 ;----------------------------------------------------------------------------- ; Now in v86 mode. Set up segment registers. ;----------------------------------------------------------------------------- @v86: mov ax,seg Data1 ; set current data segment mov ds,ax mov ax,seg IDT_SEG mov es,ax mov ax,seg TSS_SEG mov fs,ax xor ax,ax ; set segment to virtual interrupts mov gs,ax ;----------------------------------------------------------------------------- ; Modify IR bit map to make this interrupt transition to protected mode ;----------------------------------------------------------------------------- mov bx,word ptr TSS_386.TSS_T_IOMAP[2] ; get IO Map base dec bx ; point to last byte if IR bit map or byte ptr fs:[bx],80h ; disable INT 0FF from bit map ;----------------------------------------------------------------------------- ; This will fault to monitor ;----------------------------------------------------------------------------- mov TestVector,0 ; make sure initialize to 0 int 0ffh ; This interrupt will be reflected nop ; two dummy NOP's nop ; on purpose! int 0ffh ; This interrupt will exit this program @v86Exit: mov bx,SEL_CPL0DS ; set CPL=0 data segments mov ds,bx mov es,bx mov fs,bx mov gs,bx mov bx,SEL_RMSS mov ss,bx EXITPM @@: lidt ds:fword ptr RM_IDT3_Ptr mov bx,seg Data1 mov ds,bx mov es,bx mov fs,bx lss sp,VMEStackPtr xor ax,ax ; set segment to virtual interrupts mov gs,ax mov eax,SaveINT255 ; get original INT-255 pointer mov RMINT255,eax ; restore it mov eax,cr4 and al,not 1 ; disable VME mov cr4,eax mov ah,9 ; set interrupt function call mov dx,offset FailMsg cmp ExpectedResults,0aa55aa55h ; expected results? jne @F mov dx,offset PassMsg @@: int 21h iret ; split to DOS PMINT0FF: mov eax,SEL_CPL0DS ; set up DS mov ds,ax mov eax,SEL_IDTDS ; set up ES mov es,ax mov eax,SEL_TSSDS ; set up FS mov fs,ax mov eax,SEL_CPL0DS4G ; set up GS mov gs,ax not ExpectedResults ; invert pattern and IDTFF.Access_rights,not 60h ; clear to DPL=0 iretd Code1 ends Code3 segment para public use32 'CODE' ;----------------------------------------------------------------------------- ; Interrupt routines ;----------------------------------------------------------------------------- INT0d label word mov eax,SEL_CPL0DS ; set up DS mov ds,ax mov eax,SEL_IDTDS ; set up ES mov es,ax mov eax,SEL_TSSDS ; set up FS mov fs,ax mov eax,SEL_CPL0DS4G ; set up GS mov gs,ax mov eax,TestVector ; get status add TestVector,2 ; point to next table entry jmp far ptr SwapContext[eax*4] ; jump destination INT00 label word ICEBP iretd Code3 ENDS END Init