[NTOS]
[reactos.git] / reactos / ntoskrnl / ke / i386 / v86vdm.c
index ab937ad..503f413 100644 (file)
@@ -53,37 +53,40 @@ KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame,
 {
     ULONG Esp, V86EFlags, TrapEFlags;
     
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
+
     /* Get current V8086 flags and mask out interrupt flag */
     V86EFlags = *KiNtVdmState;
     V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
-    
+
     /* Get trap frame EFLags and leave only align, nested task and interrupt */
     TrapEFlags = TrapFrame->EFlags;
-    TrapEFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK);
-    
+    V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK);
+
     /* Add in those flags if they exist, and add in the IOPL flag */
     V86EFlags |= TrapEFlags;
     V86EFlags |= EFLAGS_IOPL;
     
     /* Build flat ESP */
     Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
-    Esp -= 2;
     
     /* Check for OPER32 */
     if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32)
     {
         /* Save EFlags */
-        Esp -= 2;
-        *(PULONG)(Esp - 2) = V86EFlags;
+        Esp -= 4;
+        *(PULONG)Esp = V86EFlags;
     }
     else
     {
         /* Save EFLags */
+        Esp -= 2;
         *(PUSHORT)Esp = (USHORT)V86EFlags;
     }
     
     /* Set new ESP and EIP */
-    TrapFrame->HardwareEsp = (USHORT)Esp;
+    TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
     TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
     
     /* We're done */
@@ -100,20 +103,22 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
     /* Build flat ESP */
     Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
     
-    /* Read EFlags */
-    EFlags = *(PULONG)Esp;
-    Esp += 4;
-    
     /* Check for OPER32 */
-    if (!(KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32))
+    if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32)
     {
-        /* Read correct flags and use correct stack address */
-        Esp -= 2;
-        EFlags &= 0xFFFF;
+        /* Read EFlags */
+        EFlags = *(PULONG)Esp;
+        Esp += 4;
+    }
+    else
+    {
+        /* Read EFlags */
+        EFlags = *(PUSHORT)Esp;
+        Esp += 2;
     }
     
     /* Set new ESP */
-    TrapFrame->HardwareEsp = Esp;
+    TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
     
     /* Mask out IOPL from the flags */
     EFlags &= ~EFLAGS_IOPL;
@@ -124,15 +129,18 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
     /* Now leave only alignment, nested task and interrupt flag */
     EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK);
     
-    /* FIXME: Check for VME support */
-    
+    /* Get trap EFlags */
+    TrapEFlags = TrapFrame->EFlags;
+                
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
+
     /* Add V86 and Interrupt flag */
     V86EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
-    
+
     /* Update EFlags in trap frame */
-    TrapEFlags = TrapFrame->EFlags;
-    TrapFrame->EFlags = (TrapFrame->EFlags & EFLAGS_VIP) | V86EFlags;
-    
+    TrapFrame->EFlags = V86EFlags;
+
     /* Check if ESP0 needs to be fixed up */
     if (TrapEFlags & EFLAGS_V86_MASK) Ki386AdjustEsp0(TrapFrame);
     
@@ -166,7 +174,8 @@ KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame,
     /* Keep only alignment and interrupt flag from the V8086 state */
     V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_INTERRUPT_MASK);
     
-    /* FIXME: Support VME */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
     
     /* Mask in the relevant V86 EFlags into the trap flags */
     V86EFlags |= (TrapEFlags & ~EFLAGS_INTERRUPT_MASK);
@@ -277,7 +286,8 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
     EFlags &= ~(EFLAGS_IOPL + EFLAGS_VIF + EFLAGS_NESTED_TASK + EFLAGS_VIP);
     V86EFlags = EFlags;
     
-    /* FIXME: Check for VME support */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
     
     /* Add V86 and Interrupt flag */
     EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
@@ -303,6 +313,7 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
     else
     {
         /* FIXME: Check for VDM interrupts */
+       DPRINT("FIXME: Check for VDM interrupts\n");
     }
     
     /* We're done */
@@ -314,7 +325,8 @@ FASTCALL
 KiVdmOpcodeCLI(IN PKTRAP_FRAME TrapFrame,
                IN ULONG Flags)
 {       
-    /* FIXME: Support VME */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
 
     /* Disable interrupts */
     KiVdmClearVdmEFlags(EFLAGS_INTERRUPT_MASK);
@@ -331,7 +343,8 @@ FASTCALL
 KiVdmOpcodeSTI(IN PKTRAP_FRAME TrapFrame,
                IN ULONG Flags)
 {
-    /* FIXME: Support VME */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
 
     /* Enable interrupts */
     KiVdmSetVdmEFlags(EFLAGS_INTERRUPT_MASK);
@@ -461,7 +474,7 @@ KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
 
     /* Restore TEB addresses */
     Thread->Teb = V86Frame->ThreadTeb;
-    KeGetPcr()->Tib.Self = V86Frame->PcrTeb;
+    KeGetPcr()->NtTib.Self = V86Frame->PcrTeb;
     
     /* Setup real TEB descriptor */
     GdtEntry = &((PKIPCR)KeGetPcr())->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)];
@@ -495,7 +508,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
     
     /* Save TEB addresses */
     V86Frame->ThreadTeb = Thread->Teb;
-    V86Frame->PcrTeb = KeGetPcr()->Tib.Self;
+    V86Frame->PcrTeb = KeGetPcr()->NtTib.Self;
     
     /* Save return EIP */
     TrapFrame->Eip = (ULONG_PTR)Ki386BiosCallReturnAddress;
@@ -523,7 +536,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
     RtlCopyMemory(NpxFrame, V86Frame->ThreadStack, sizeof(FX_SAVE_AREA));
     
     /* Clear exception list */
-    KeGetPcr()->Tib.ExceptionList = EXCEPTION_CHAIN_END;
+    KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
     
     /* Set new ESP0 */
     KeGetPcr()->TSS->Esp0 = (ULONG_PTR)&TrapFrame->V86Es;
@@ -533,7 +546,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
         
     /* Set VDM TEB */
     Thread->Teb = (PTEB)TRAMPOLINE_TEB;
-    KeGetPcr()->Tib.Self = (PVOID)TRAMPOLINE_TEB;
+    KeGetPcr()->NtTib.Self = (PVOID)TRAMPOLINE_TEB;
     
     /* Setup VDM TEB descriptor */
     GdtEntry = &((PKIPCR)KeGetPcr())->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)];
@@ -649,37 +662,87 @@ Ke386CallBios(IN ULONG Int,
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 NTAPI
 Ke386IoSetAccessProcess(IN PKPROCESS Process,
-                        IN ULONG Flag)
+                        IN ULONG MapNumber)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    USHORT MapOffset;
+    PKPRCB Prcb;
+    KAFFINITY TargetProcessors;
+
+    if(MapNumber > IOPM_COUNT)
+        return FALSE;
+
+    MapOffset = KiComputeIopmOffset(MapNumber);
+
+    Process->IopmOffset = MapOffset;
+
+    TargetProcessors = Process->ActiveProcessors;
+    Prcb = KeGetCurrentPrcb();
+    if (TargetProcessors & Prcb->SetMember)
+        KeGetPcr()->TSS->IoMapBase = MapOffset;
+
+    return TRUE;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 NTAPI
-Ke386SetIoAccessMap(IN ULONG Flag,
-                    IN PVOID IopmBuffer)
+Ke386SetIoAccessMap(IN ULONG MapNumber,
+                    IN PKIO_ACCESS_MAP IopmBuffer)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    PKPROCESS CurrentProcess;
+    PKPRCB Prcb;
+    PVOID pt;
+
+    if ((MapNumber > IOPM_COUNT) || (MapNumber == IO_ACCESS_MAP_NONE))
+        return FALSE;
+
+    Prcb = KeGetCurrentPrcb();
+
+    // Copy the IOP map and load the map for the current process.
+    pt = &(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
+    RtlMoveMemory(pt, (PVOID)IopmBuffer, IOPM_SIZE);
+    CurrentProcess = Prcb->CurrentThread->ApcState.Process;
+    KeGetPcr()->TSS->IoMapBase = CurrentProcess->IopmOffset;
+
+    return TRUE;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 NTAPI
-Ke386QueryIoAccessMap(IN ULONG Flag,
-                      IN PVOID IopmBuffer)
+Ke386QueryIoAccessMap(IN ULONG MapNumber,
+                      IN PKIO_ACCESS_MAP IopmBuffer)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    ULONG i;
+    PVOID Map;
+    PUCHAR p;
+
+    if (MapNumber > IOPM_COUNT)
+        return FALSE;
+
+    if (MapNumber == IO_ACCESS_MAP_NONE)
+    {
+        // no access, simply return a map of all 1s
+        p = (PUCHAR)IopmBuffer;
+        for (i = 0; i < IOPM_SIZE; i++) {
+            p[i] = (UCHAR)-1;
+        }
+    }
+    else
+    {
+        // copy the bits
+        Map = (PVOID)&(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
+        RtlMoveMemory((PVOID)IopmBuffer, Map, IOPM_SIZE);
+    }
+
+    return TRUE;
 }