winedos / Reorganize interrupt handling

Jukka Heinonen jhei at iki.fi
Sun Mar 2 10:31:23 CST 2003


This patch reorganizes interrupt handling a bit. RM and PM
interrupts are now handled using similar functions.
This patch also contains some stuff for handling
emulated hardware interrupts in PM.



Changelog:
  Move real mode interrupt emulation code to file interrupts.c.
  Remove last wrapper check from int31 handler. 
  Move RM/PM hardware interrupt emulation code to separate functions.



Index: dlls/winedos/dosexe.h
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosexe.h,v
retrieving revision 1.22
diff -u -r1.22 dosexe.h
--- dlls/winedos/dosexe.h	11 Feb 2003 22:22:50 -0000	1.22
+++ dlls/winedos/dosexe.h	2 Mar 2003 15:34:41 -0000
@@ -93,7 +93,6 @@
 extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
 extern void WINAPI DOSVM_SetTimer( UINT ticks );
 extern UINT WINAPI DOSVM_GetTimer( void );
-extern void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context );
 
 /* devices.c */
 extern void DOSDEV_InstallDOSDevices(void);
@@ -198,6 +197,7 @@
 extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC);
 extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16);
 extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int);
+extern BOOL DOSVM_CheckWrappers(CONTEXT86*);
 
 /* int33.c */
 extern void WINAPI DOSVM_Int33Handler(CONTEXT86*);
@@ -218,13 +218,17 @@
 extern void WINAPI EMS_Ioctl_Handler(CONTEXT86*);
 
 /* interrupts.c */
-extern FARPROC16 DOSVM_GetRMHandler( BYTE intnum );
-extern void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler );
-extern FARPROC16 DOSVM_GetPMHandler16( BYTE intnum );
-extern void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler );
-extern FARPROC48 DOSVM_GetPMHandler48( BYTE intnum );
-extern void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler );
-extern INTPROC DOSVM_GetBuiltinHandler( BYTE intnum );
+extern void WINAPI DOSVM_CallBuiltinHandler( CONTEXT86 *, BYTE );
+extern void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *, BYTE );
+extern BOOL WINAPI DOSVM_EmulateInterruptRM( CONTEXT86 *, BYTE );
+extern FARPROC16   DOSVM_GetPMHandler16( BYTE );
+extern FARPROC48   DOSVM_GetPMHandler48( BYTE );
+extern FARPROC16   DOSVM_GetRMHandler( BYTE );
+extern void        DOSVM_HardwareInterruptPM( CONTEXT86 *, BYTE );
+extern void        DOSVM_HardwareInterruptRM( CONTEXT86 *, BYTE );
+extern void        DOSVM_SetPMHandler16( BYTE, FARPROC16 );
+extern void        DOSVM_SetPMHandler48( BYTE, FARPROC48 );
+extern void        DOSVM_SetRMHandler( BYTE, FARPROC16 );
 
 /* relay.c */
 void DOSVM_RelayHandler( CONTEXT86 * );




Index: dlls/winedos/dosvm.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/dosvm.c,v
retrieving revision 1.33
diff -u -r1.33 dosvm.c
--- dlls/winedos/dosvm.c	12 Feb 2003 01:26:05 -0000	1.33
+++ dlls/winedos/dosvm.c	2 Mar 2003 15:34:55 -0000
@@ -92,53 +92,6 @@
 static HANDLE event_notifier;
 static CONTEXT86 *current_context;
 
-static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine )
-{
-  FARPROC16 handler=DOSVM_GetRMHandler(vect);
-
-  /* check for our real-mode hooks */
-  if (vect==0x31) {
-    if (context->SegCs==DOSVM_dpmi_segments->wrap_seg) {
-      /* exit from real-mode wrapper */
-      return -1;
-    }
-    /* we could probably move some other dodgy stuff here too from dpmi.c */
-  }
-  /* check if the call is from our fake BIOS interrupt stubs */
-  if ((context->SegCs==0xf000) && !inwine) {
-    if (vect != (context->Eip/4)) {
-      TRACE("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4);
-    }
-    TRACE("builtin interrupt %02x has been branched to\n", vect);
-    DOSVM_RealModeInterrupt(vect, context);
-  }
-  /* check if the call goes to an unhooked interrupt */
-  else if (SELECTOROF(handler)==0xf000) {
-    /* if so, call it directly */
-    TRACE("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect);
-    DOSVM_RealModeInterrupt(OFFSETOF(handler)/4, context);
-  }
-  /* the interrupt is hooked, simulate interrupt in DOS space */
-  else {
-    WORD*stack= PTR_REAL_TO_LIN( context->SegSs, context->Esp );
-    WORD flag=LOWORD(context->EFlags);
-
-    TRACE_(int)("invoking hooked interrupt %02x at %04x:%04x\n", vect,
-		SELECTOROF(handler), OFFSETOF(handler));
-    if (IF_ENABLED(context)) flag|=IF_MASK;
-    else flag&=~IF_MASK;
-
-    *(--stack)=flag;
-    *(--stack)=context->SegCs;
-    *(--stack)=LOWORD(context->Eip);
-    context->Esp-=6;
-    context->SegCs=SELECTOROF(handler);
-    context->Eip=OFFSETOF(handler);
-    IF_CLR(context);
-  }
-  return 0;
-}
-
 #define SHOULD_PEND(x) \
   (x && ((!current_event) || (x->priority < current_event->priority)))
 
@@ -157,7 +110,8 @@
       TRACE("dispatching IRQ %d\n",event->irq);
       /* note that if DOSVM_SimulateInt calls an internal interrupt directly,
        * current_event might be cleared (and event freed) in this very call! */
-      DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,TRUE);
+      DOSVM_HardwareInterruptRM( context, (event->irq < 8) ? 
+                                 (event->irq + 8) : (event->irq - 8 + 0x70) );
     } else {
       /* callback event */
       TRACE("dispatching callback event\n");
@@ -440,7 +394,8 @@
 {
   EXCEPTION_RECORD *rec = GetExceptionInformation()->ExceptionRecord;
   CONTEXT *context = GetExceptionInformation()->ContextRecord;
-  int ret, arg = rec->ExceptionInformation[0];
+  int arg = rec->ExceptionInformation[0];
+  BOOL ret;
 
   switch(rec->ExceptionCode) {
   case EXCEPTION_VM86_INTx:
@@ -454,7 +409,7 @@
 	      context->Ebp, context->Esp, context->SegDs, context->SegEs,
 	      context->SegFs, context->SegGs, context->EFlags );
       }
-    ret = DOSVM_SimulateInt(arg, context, FALSE);
+    ret = DOSVM_EmulateInterruptRM( context, arg );
     if (TRACE_ON(relay)) {
       DPRINTF("Ret  DOS int 0x%02x ret=%04lx:%04lx\n",
 	      arg, context->SegCs, context->Eip );
@@ -465,7 +420,7 @@
 	      context->Ebp, context->Esp, context->SegDs, context->SegEs,
 	      context->SegFs, context->SegGs, context->EFlags );
     }
-    return ret ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_EXECUTION;
+    return ret ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
 
   case EXCEPTION_VM86_STI:
   /* case EXCEPTION_VM86_PICRETURN: */
@@ -626,17 +581,6 @@
 }
 
 #endif
-
-/**********************************************************************
- *	    DOSVM_RealModeInterrupt
- *
- * Handle real mode interrupts
- */
-void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context )
-{
-    INTPROC proc = DOSVM_GetBuiltinHandler( intnum );
-    proc(context);
-}
 
 
 /**********************************************************************




Index: dlls/winedos/interrupts.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/interrupts.c,v
retrieving revision 1.13
diff -u -r1.13 interrupts.c
--- dlls/winedos/interrupts.c	15 Dec 2002 01:18:40 -0000	1.13
+++ dlls/winedos/interrupts.c	2 Mar 2003 15:35:06 -0000
@@ -22,6 +22,19 @@
 #include "wine/debug.h"
 #include "wine/winbase16.h"
 
+#ifdef HAVE_SYS_VM86_H
+# include <sys/vm86.h>
+#endif
+
+#ifndef IF_MASK
+#define IF_MASK 0x00000200
+#endif
+
+#ifndef VIF_MASK
+#define VIF_MASK 0x00080000
+#endif
+
+
 WINE_DEFAULT_DEBUG_CHANNEL(int);
 
 static FARPROC16     DOSVM_Vectors16[256];
@@ -69,6 +82,24 @@
 
 
 /**********************************************************************
+ *         DOSVM_GetBuiltinHandler
+ *
+ * Return Wine interrupt handler procedure for a given interrupt.
+ */
+static INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
+{
+    if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) {
+        INTPROC proc = DOSVM_VectorsBuiltin[intnum];
+        if (proc)
+            return proc;
+    }
+
+    WARN("int%x not implemented, returning dummy handler\n", intnum );
+    return DOSVM_DefaultHandler;
+}
+
+
+/**********************************************************************
  *          DOSVM_IntProcRelay
  *
  * Simple DOSRELAY that interprets its argument as INTPROC and calls it.
@@ -173,7 +204,24 @@
                               DOSVM_IntProcRelay, 
                               DOSVM_GetBuiltinHandler(intnum) );
     }
-    else if(DOSVM_IsDos32())
+    else
+    {
+        DOSVM_HardwareInterruptPM( context, intnum );
+    }
+}
+
+
+/**********************************************************************
+ *         DOSVM_HardwareInterruptPM
+ *
+ * Emulate call to interrupt handler in 16-bit or 32-bit protected mode.
+ *
+ * Pushes interrupt frame to stack and changes instruction 
+ * pointer to interrupt handler.
+ */
+void DOSVM_HardwareInterruptPM( CONTEXT86 *context, BYTE intnum ) 
+{
+    if(DOSVM_IsDos32())
     {
         FARPROC48 addr = DOSVM_GetPMHandler48( intnum );
         
@@ -235,6 +283,100 @@
     }
 }
 
+
+/**********************************************************************
+ *         DOSVM_EmulateInterruptRM
+ *
+ * Emulate software interrupt in real mode.
+ * Called from VM86 emulation when intXX opcode is executed. 
+ *
+ * Either calls directly builtin handler or pushes interrupt frame to 
+ * stack and changes instruction pointer to interrupt handler.
+ *
+ * Returns FALSE if this interrupt was caused by return 
+ * from real mode wrapper.
+ */
+BOOL WINAPI DOSVM_EmulateInterruptRM( CONTEXT86 *context, BYTE intnum ) 
+{
+    /* check for our real-mode hooks */
+    if (intnum == 0x31)
+    {
+        /* is this exit from real-mode wrapper */
+        if (context->SegCs == DOSVM_dpmi_segments->wrap_seg)
+            return FALSE;
+
+        if (DOSVM_CheckWrappers( context ))
+            return TRUE;
+    }
+
+    /* check if the call is from our fake BIOS interrupt stubs */
+    if (context->SegCs==0xf000)
+    {
+        if (intnum != (context->Eip/4))
+            TRACE( "something fishy going on here (interrupt stub is %02lx)\n", 
+                   context->Eip/4 );
+
+        TRACE( "builtin interrupt %02x has been branched to\n", intnum );
+        
+        DOSVM_CallBuiltinHandler( context, intnum );
+    }
+    else
+    {
+        DOSVM_HardwareInterruptRM( context, intnum );
+    }
+
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *         DOSVM_HardwareInterruptRM
+ *
+ * Emulate call to interrupt handler in real mode.
+ *
+ * Either calls directly builtin handler or pushes interrupt frame to 
+ * stack and changes instruction pointer to interrupt handler.
+ */
+void DOSVM_HardwareInterruptRM( CONTEXT86 *context, BYTE intnum ) 
+{
+     FARPROC16 handler = DOSVM_GetRMHandler( intnum );
+
+     /* check if the call goes to an unhooked interrupt */
+     if (SELECTOROF(handler) == 0xf000) 
+     {
+         /* if so, call it directly */
+         TRACE( "builtin interrupt %02x has been invoked (through vector %02x)\n", 
+                OFFSETOF(handler)/4, intnum );
+         DOSVM_CallBuiltinHandler( context, OFFSETOF(handler)/4 );
+     }
+     else 
+     {
+         /* the interrupt is hooked, simulate interrupt in DOS space */ 
+         WORD* stack = PTR_REAL_TO_LIN( context->SegSs, context->Esp );
+         WORD  flag  = LOWORD( context->EFlags );
+
+         TRACE_(int)( "invoking hooked interrupt %02x at %04x:%04x\n", 
+                      intnum, SELECTOROF(handler), OFFSETOF(handler) );
+
+         /* Copy virtual interrupt flag to pushed interrupt flag. */
+         if (context->EFlags & VIF_MASK)
+             flag |= IF_MASK;
+         else 
+             flag &= ~IF_MASK;
+
+         *(--stack) = flag;
+         *(--stack) = context->SegCs;
+         *(--stack) = LOWORD( context->Eip );
+         context->Esp -= 6;
+         context->SegCs = SELECTOROF( handler );
+         context->Eip   = OFFSETOF( handler );
+
+         /* Clear virtual interrupt flag. */
+         context->EFlags &= ~VIF_MASK;
+     }
+}
+
+
 /**********************************************************************
  *          DOSVM_GetRMHandler
  *
@@ -316,22 +458,6 @@
   DOSVM_Vectors48[intnum] = handler;
 }
 
-/**********************************************************************
- *         DOSVM_GetBuiltinHandler
- *
- * Return Wine interrupt handler procedure for a given interrupt.
- */
-INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
-{
-  if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) {
-    INTPROC proc = DOSVM_VectorsBuiltin[intnum];
-    if(proc)
-      return proc;
-  }
-
-  WARN("int%x not implemented, returning dummy handler\n", intnum );
-  return DOSVM_DefaultHandler;
-}
 
 /**********************************************************************
  *         DOSVM_CallBuiltinHandler




Index: dlls/winedos/int31.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int31.c,v
retrieving revision 1.18
diff -u -r1.18 int31.c
--- dlls/winedos/int31.c	26 Feb 2003 20:34:46 -0000	1.18
+++ dlls/winedos/int31.c	2 Mar 2003 15:35:12 -0000
@@ -387,7 +387,7 @@
 /* shortcut for chaining to internal interrupt handlers */
     if ((context->SegCs == 0xF000) && iret)
     {
-        DOSVM_RealModeInterrupt( LOWORD(context->Eip)/4, context);
+        DOSVM_CallBuiltinHandler( context, LOWORD(context->Eip)/4 );
         return 0;
     }
 
@@ -475,7 +475,7 @@
         RESET_CFLAG(context);
         /* use the IP we have instead of BL_reg, in case some apps
            decide to move interrupts around for whatever reason... */
-        DOSVM_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx );
+        DOSVM_CallBuiltinHandler( &realmode_ctx, LOWORD(rm_int)/4 );
     }
     INT_SetRealModeContext( call, &realmode_ctx );
 }
@@ -744,14 +744,9 @@
  *         DOSVM_CheckWrappers
  *
  * Check if this was really a wrapper call instead of an interrupt.
- * FIXME: Protected mode stuff does not work in 32-bit DPMI.
- * FIXME: If int31 is called asynchronously (unlikely) 
- *        wrapper checks are wrong (CS/IP must not be used).
  */
-static BOOL DOSVM_CheckWrappers( CONTEXT86 *context )
+BOOL DOSVM_CheckWrappers( CONTEXT86 *context )
 {
-    /* check if it's our wrapper */
-    TRACE("called from real mode\n");
     if (context->SegCs==DOSVM_dpmi_segments->dpmi_seg) {
         /* This is the protected mode switch */
         StartPM(context);
@@ -788,9 +783,6 @@
  */
 void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
 {
-    if (ISV86(context) && DOSVM_CheckWrappers(context))
-        return;
-
     RESET_CFLAG(context);
     switch(AX_reg(context))
     {




-- 
Jukka Heinonen <http://www.iki.fi/jhei/>



More information about the wine-patches mailing list