Commit ed6bdb3c authored by Alexandre Julliard's avatar Alexandre Julliard

krnl386: Remove support for DPMI real-mode calls.

parent 4a589081
...@@ -7,7 +7,6 @@ EXTRADLLFLAGS = -m16 -nodefaultlibs -Wb,--dll-name,kernel ...@@ -7,7 +7,6 @@ EXTRADLLFLAGS = -m16 -nodefaultlibs -Wb,--dll-name,kernel
C_SRCS = \ C_SRCS = \
atom.c \ atom.c \
dma.c \ dma.c \
dosaspi.c \
dosmem.c \ dosmem.c \
dosvm.c \ dosvm.c \
error.c \ error.c \
......
/*
* Copyright 2000 David Elliott
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wine/windef16.h"
#include "wine/winaspi.h"
#include "wine/debug.h"
#include "dosexe.h"
#include "winerror.h"
WINE_DEFAULT_DEBUG_CHANNEL(aspi);
static HINSTANCE hWNASPI32 = INVALID_HANDLE_VALUE;
static DWORD (__cdecl *pSendASPI32Command) (LPSRB) = NULL;
static void
DOSASPI_PostProc( SRB_ExecSCSICmd *lpPRB )
{
DWORD ptrSRB;
LPSRB16 lpSRB16;
memcpy(&ptrSRB,lpPRB->SenseArea + lpPRB->SRB_SenseLen,sizeof(DWORD));
TRACE("Copying data back to DOS client at 0x%8x\n",ptrSRB);
lpSRB16 = PTR_REAL_TO_LIN(SELECTOROF(ptrSRB),OFFSETOF(ptrSRB));
lpSRB16->cmd.SRB_TargStat = lpPRB->SRB_TargStat;
lpSRB16->cmd.SRB_HaStat = lpPRB->SRB_HaStat;
memcpy(lpSRB16->cmd.CDBByte + lpSRB16->cmd.SRB_CDBLen,lpPRB->SenseArea,lpSRB16->cmd.SRB_SenseLen);
/* Now do posting */
if( lpPRB->SRB_Status == SS_SECURITY_VIOLATION )
{
/* SS_SECURITY_VIOLATION isn't defined in DOS ASPI */
TRACE("Returning SS_NO_DEVICE for SS_SECURITY_VIOLATION\n");
lpPRB->SRB_Status = SS_NO_DEVICE;
}
lpSRB16->cmd.SRB_Status = lpPRB->SRB_Status;
TRACE("SRB_Status = 0x%x\n", lpPRB->SRB_Status);
HeapFree(GetProcessHeap(),0,lpPRB);
if( (lpSRB16->cmd.SRB_Flags & SRB_POSTING) && lpSRB16->cmd.SRB_PostProc )
{
CONTEXT ctx;
/* The stack should look like this on entry to proc
* NOTE: the SDK draws the following diagram bass awkwardly, use this one
* to avoid being confused. Remember, the act of pushing something on
* an intel stack involves decreasing the stack pointer by the size of
* the data, and then copying the data at the new SP.
*/
/***************************
* ... Other crap that is already on the stack ...
* Segment of SRB Pointer <- SP+6
* Offset of SRB Pointer <- SP+4
* Segment of return address <- SP+2
* Offset of return address <- SP+0
*/
/* FIXME: I am about 99% sure what is here is correct,
* but this code has never been tested (and probably
* won't be either until someone finds a DOS program
* that actually uses a Post Routine) */
/* Zero everything */
memset(&ctx, 0, sizeof(ctx));
ctx.EFlags |= V86_FLAG;
/* CS:IP is routine to call */
ctx.SegCs = SELECTOROF(lpSRB16->cmd.SRB_PostProc);
ctx.Eip = OFFSETOF(lpSRB16->cmd.SRB_PostProc);
/* DPMI_CallRMProc will push the pointer to the stack
* it is given (in this case &ptrSRB) with length
* 2*sizeof(WORD), that is, it copies the contents
* of ptrSRB onto the stack, and decs sp by 2*sizeof(WORD).
* After doing that, it pushes the return address
* onto the stack (so we don't need to worry about that)
* So the stack should be okay for the PostProc
*/
if(DPMI_CallRMProc(&ctx, (LPWORD)&ptrSRB, 2, FALSE))
{
TRACE("DPMI_CallRMProc returned nonzero (error) status\n");
}
} /* if ((SRB_Flags&SRB_POSTING) && SRB_PostProc) */
}
static
DWORD ASPI_SendASPIDOSCommand(DWORD ptrSRB)
{
PSRB_ExecSCSICmd lpPRB;
DWORD retval;
union tagSRB16 * lpSRB16;
lpSRB16 = PTR_REAL_TO_LIN(SELECTOROF(ptrSRB),OFFSETOF(ptrSRB));
retval = SS_ERR;
switch( lpSRB16->common.SRB_Cmd )
{
case SC_HA_INQUIRY:
TRACE("SC_HA_INQUIRY\n");
/* Format is identical in this case */
retval = (*pSendASPI32Command)((LPSRB)lpSRB16);
break;
case SC_GET_DEV_TYPE:
TRACE("SC_GET_DEV_TYPE\n");
/* Format is identical in this case */
retval = (*pSendASPI32Command)((LPSRB)lpSRB16);
break;
case SC_EXEC_SCSI_CMD:
TRACE("SC_EXEC_SCSI_CMD\n");
TRACE("Copying data from DOS client at 0x%8x\n",ptrSRB);
lpPRB = HeapAlloc(GetProcessHeap(),0,sizeof(SRB)+lpSRB16->cmd.SRB_SenseLen+sizeof(DWORD));
#define srb_dos_to_w32(name) \
lpPRB->SRB_##name = lpSRB16->cmd.SRB_##name
srb_dos_to_w32(Cmd);
srb_dos_to_w32(Status);
srb_dos_to_w32(HaId);
srb_dos_to_w32(BufLen);
srb_dos_to_w32(SenseLen);
srb_dos_to_w32(CDBLen);
srb_dos_to_w32(Target);
srb_dos_to_w32(Lun);
#undef srb_dos_to_w32
/* Allow certain flags to go on to WNASPI32, we also need
* to make sure SRB_POSTING is enabled */
lpPRB->SRB_Flags = SRB_POSTING | (lpSRB16->cmd.SRB_Flags&(SRB_DIR_IN|SRB_DIR_OUT|SRB_ENABLE_RESIDUAL_COUNT));
/* Pointer to data buffer */
lpPRB->SRB_BufPointer = PTR_REAL_TO_LIN(SELECTOROF(lpSRB16->cmd.SRB_BufPointer),
OFFSETOF(lpSRB16->cmd.SRB_BufPointer));
/* Copy CDB in */
memcpy(&lpPRB->CDBByte[0],&lpSRB16->cmd.CDBByte[0],lpSRB16->cmd.SRB_CDBLen);
/* Set post proc to our post proc */
lpPRB->SRB_PostProc = DOSASPI_PostProc;
/* Stick the DWORD after all the sense info */
memcpy(lpPRB->SenseArea + lpPRB->SRB_SenseLen,&ptrSRB,sizeof(DWORD));
retval = (*pSendASPI32Command)((LPSRB)lpPRB);
break;
case SC_ABORT_SRB:
TRACE("SC_ABORT_SRB\n");
/* Would need some sort of table of active shit */
break;
case SC_RESET_DEV:
TRACE("SC_RESET_DEV\n");
break;
default:
TRACE("Unknown command code\n");
break;
}
TRACE("Returning %x\n", retval );
return retval;
}
static void WINAPI ASPI_DOS_func(CONTEXT *context)
{
WORD *stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
DWORD ptrSRB = *(DWORD *)&stack[2];
ASPI_SendASPIDOSCommand(ptrSRB);
/* simulate a normal RETF sequence as required by DPMI CallRMProcFar */
context->Eip = *(stack++);
context->SegCs = *(stack++);
context->Esp += 2*sizeof(WORD);
}
/**********************************************************************
* ASPIHandler
*
* returns the address of a real mode callback to ASPI_DOS_func()
*/
void DOSVM_ASPIHandler( CONTEXT *context )
{
FARPROC16 *p = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
TRACE("DOS ASPI opening\n");
if ((CX_reg(context) == 4) || (CX_reg(context) == 5))
{
if( hWNASPI32 == INVALID_HANDLE_VALUE )
{
TRACE("Loading WNASPI32\n");
hWNASPI32 = LoadLibraryExA("WNASPI32", 0, 0);
}
if( hWNASPI32 == INVALID_HANDLE_VALUE )
{
ERR("Error loading WNASPI32\n");
goto error_exit;
}
/* Get SendASPI32Command by Ordinal 2 */
/* Cast to correct argument/return types */
pSendASPI32Command = (DWORD (*)(LPSRB))GetProcAddress(hWNASPI32, (LPCSTR)2);
if( !pSendASPI32Command )
{
ERR("Error getting ordinal 2 from WNASPI32\n");
goto error_exit;
}
*p = DPMI_AllocInternalRMCB(ASPI_DOS_func);
TRACE("allocated real mode proc %p\n", *p);
SET_AX( context, CX_reg(context) );
return;
}
error_exit:
/* Return some error... General Failure sounds okay */
SET_AX( context, ERROR_GEN_FAILURE );
SET_CFLAG(context);
}
...@@ -38,22 +38,11 @@ ...@@ -38,22 +38,11 @@
/* various real-mode code stubs */ /* various real-mode code stubs */
struct DPMI_segments struct DPMI_segments
{ {
WORD wrap_seg;
WORD xms_seg;
WORD dpmi_seg;
WORD dpmi_sel;
WORD int48_sel;
WORD int16_sel; WORD int16_sel;
WORD relay_code_sel; WORD relay_code_sel;
WORD relay_data_sel; WORD relay_data_sel;
}; };
/* 48-bit segmented pointers for DOS DPMI32 */
typedef struct {
WORD selector;
DWORD offset;
} SEGPTR48, FARPROC48;
typedef void (*DOSRELAY)(CONTEXT*,void*); typedef void (*DOSRELAY)(CONTEXT*,void*);
typedef void (WINAPI *RMCBPROC)(CONTEXT*); typedef void (WINAPI *RMCBPROC)(CONTEXT*);
typedef void (WINAPI *INTPROC)(CONTEXT*); typedef void (WINAPI *INTPROC)(CONTEXT*);
...@@ -239,9 +228,6 @@ extern int DMA_Transfer(int channel,int reqlength,void* buffer) DECLSPEC_HIDDEN; ...@@ -239,9 +228,6 @@ extern int DMA_Transfer(int channel,int reqlength,void* buffer) DECLSPEC_HIDDEN;
extern void DMA_ioport_out( WORD port, BYTE val ) DECLSPEC_HIDDEN; extern void DMA_ioport_out( WORD port, BYTE val ) DECLSPEC_HIDDEN;
extern BYTE DMA_ioport_in( WORD port ) DECLSPEC_HIDDEN; extern BYTE DMA_ioport_in( WORD port ) DECLSPEC_HIDDEN;
/* dosaspi.c */
extern void DOSVM_ASPIHandler(CONTEXT*) DECLSPEC_HIDDEN;
/* dosmem.c */ /* dosmem.c */
extern BIOSDATA *DOSVM_BiosData( void ) DECLSPEC_HIDDEN; extern BIOSDATA *DOSVM_BiosData( void ) DECLSPEC_HIDDEN;
extern void DOSVM_start_bios_timer(void) DECLSPEC_HIDDEN; extern void DOSVM_start_bios_timer(void) DECLSPEC_HIDDEN;
...@@ -281,11 +267,6 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT*) DECLSPEC_HIDDEN; ...@@ -281,11 +267,6 @@ extern void WINAPI DOSVM_Int2fHandler(CONTEXT*) DECLSPEC_HIDDEN;
/* int31.c */ /* int31.c */
extern void WINAPI DOSVM_Int31Handler(CONTEXT*) DECLSPEC_HIDDEN; extern void WINAPI DOSVM_Int31Handler(CONTEXT*) DECLSPEC_HIDDEN;
extern void WINAPI DOSVM_RawModeSwitchHandler(CONTEXT*) DECLSPEC_HIDDEN;
extern BOOL DOSVM_IsDos32(void) DECLSPEC_HIDDEN;
extern FARPROC16 DPMI_AllocInternalRMCB(RMCBPROC) DECLSPEC_HIDDEN;
extern int DPMI_CallRMProc(CONTEXT*,LPWORD,int,int) DECLSPEC_HIDDEN;
extern BOOL DOSVM_CheckWrappers(CONTEXT*) DECLSPEC_HIDDEN;
/* int67.c */ /* int67.c */
extern void WINAPI DOSVM_Int67Handler(CONTEXT*) DECLSPEC_HIDDEN; extern void WINAPI DOSVM_Int67Handler(CONTEXT*) DECLSPEC_HIDDEN;
...@@ -296,12 +277,8 @@ extern void __wine_call_int_handler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN; ...@@ -296,12 +277,8 @@ extern void __wine_call_int_handler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern void DOSVM_CallBuiltinHandler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN; extern void DOSVM_CallBuiltinHandler( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern BOOL DOSVM_EmulateInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN; extern BOOL DOSVM_EmulateInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern FARPROC16 DOSVM_GetPMHandler16( BYTE ) DECLSPEC_HIDDEN; extern FARPROC16 DOSVM_GetPMHandler16( BYTE ) DECLSPEC_HIDDEN;
extern FARPROC48 DOSVM_GetPMHandler48( BYTE ) DECLSPEC_HIDDEN;
extern FARPROC16 DOSVM_GetRMHandler( BYTE ) DECLSPEC_HIDDEN;
extern void DOSVM_HardwareInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN; extern void DOSVM_HardwareInterruptPM( CONTEXT *, BYTE ) DECLSPEC_HIDDEN;
extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN; extern void DOSVM_SetPMHandler16( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
extern void DOSVM_SetPMHandler48( BYTE, FARPROC48 ) DECLSPEC_HIDDEN;
extern void DOSVM_SetRMHandler( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
/* ioports.c */ /* ioports.c */
extern DWORD DOSVM_inport( int port, int size ) DECLSPEC_HIDDEN; extern DWORD DOSVM_inport( int port, int size ) DECLSPEC_HIDDEN;
......
...@@ -160,17 +160,11 @@ static WORD alloc_selector( void *base, DWORD size, unsigned char flags ) ...@@ -160,17 +160,11 @@ static WORD alloc_selector( void *base, DWORD size, unsigned char flags )
* *
* FIXME: should allocate a single PM selector for the whole UMB range. * FIXME: should allocate a single PM selector for the whole UMB range.
*/ */
static LPVOID DOSVM_AllocCodeUMB( DWORD size, WORD *segment, WORD *selector ) static LPVOID DOSVM_AllocCodeUMB( DWORD size, WORD *selector )
{ {
LPVOID ptr = DOSVM_AllocUMB( size ); LPVOID ptr = DOSVM_AllocUMB( size );
if (segment)
*segment = (DWORD)ptr >> 4;
if (selector)
*selector = alloc_selector( ptr, size, WINE_LDT_FLAGS_CODE ); *selector = alloc_selector( ptr, size, WINE_LDT_FLAGS_CODE );
return ptr;
return ptr;
} }
...@@ -207,50 +201,6 @@ void DOSVM_InitSegments(void) ...@@ -207,50 +201,6 @@ void DOSVM_InitSegments(void)
LPSTR ptr; LPSTR ptr;
int i; int i;
static const char wrap_code[]={
0xCD,0x31, /* int $0x31 */
0xCB /* lret */
};
static const char enter_xms[]=
{
/* XMS hookable entry point */
0xEB,0x03, /* jmp entry */
0x90,0x90,0x90, /* nop;nop;nop */
/* entry: */
/* real entry point */
/* for simplicity, we'll just use the same hook as DPMI below */
0xCD,0x31, /* int $0x31 */
0xCB /* lret */
};
static const char enter_pm[]=
{
0x50, /* pushw %ax */
0x52, /* pushw %dx */
0x55, /* pushw %bp */
0x89,0xE5, /* movw %sp,%bp */
/* get return CS */
0x8B,0x56,0x08, /* movw 8(%bp),%dx */
/* just call int 31 here to get into protected mode... */
/* it'll check whether it was called from dpmi_seg... */
0xCD,0x31, /* int $0x31 */
/* we are now in the context of a 16-bit relay call */
/* need to fixup our stack;
* 16-bit relay return address will be lost,
* but we won't worry quite yet
*/
0x8E,0xD0, /* movw %ax,%ss */
0x66,0x0F,0xB7,0xE5, /* movzwl %bp,%esp */
/* set return CS */
0x89,0x56,0x08, /* movw %dx,8(%bp) */
0x5D, /* popw %bp */
0x5A, /* popw %dx */
0x58, /* popw %ax */
0xfb, /* sti, enable and check virtual interrupts */
0xCB /* lret */
};
static const char relay[]= static const char relay[]=
{ {
0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */ 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */
...@@ -264,53 +214,9 @@ void DOSVM_InitSegments(void) ...@@ -264,53 +214,9 @@ void DOSVM_InitSegments(void)
DOSVM_dpmi_segments = DOSVM_AllocUMB( sizeof(struct DPMI_segments) ); DOSVM_dpmi_segments = DOSVM_AllocUMB( sizeof(struct DPMI_segments) );
/* /*
* RM / offset 0: Exit from real mode.
* RM / offset 2: Points to lret opcode.
*/
ptr = DOSVM_AllocCodeUMB( sizeof(wrap_code),
&DOSVM_dpmi_segments->wrap_seg, 0 );
memcpy( ptr, wrap_code, sizeof(wrap_code) );
/*
* RM / offset 0: XMS driver entry.
*/
ptr = DOSVM_AllocCodeUMB( sizeof(enter_xms),
&DOSVM_dpmi_segments->xms_seg, 0 );
memcpy( ptr, enter_xms, sizeof(enter_xms) );
/*
* RM / offset 0: Switch to DPMI.
* PM / offset 8: DPMI raw mode switch.
*/
ptr = DOSVM_AllocCodeUMB( sizeof(enter_pm),
&DOSVM_dpmi_segments->dpmi_seg,
&DOSVM_dpmi_segments->dpmi_sel );
memcpy( ptr, enter_pm, sizeof(enter_pm) );
/*
* PM / offset N*6: Interrupt N in DPMI32.
*/
ptr = DOSVM_AllocCodeUMB( 6 * 256,
0, &DOSVM_dpmi_segments->int48_sel );
for(i=0; i<256; i++) {
/*
* Each 32-bit interrupt handler is 6 bytes:
* 0xCD,<i> = int <i> (nested 16-bit interrupt)
* 0x66,0xCA,0x04,0x00 = ret 4 (32-bit far return and pop 4 bytes / eflags)
*/
ptr[i * 6 + 0] = 0xCD;
ptr[i * 6 + 1] = i;
ptr[i * 6 + 2] = 0x66;
ptr[i * 6 + 3] = 0xCA;
ptr[i * 6 + 4] = 0x04;
ptr[i * 6 + 5] = 0x00;
}
/*
* PM / offset N*5: Interrupt N in 16-bit protected mode. * PM / offset N*5: Interrupt N in 16-bit protected mode.
*/ */
ptr = DOSVM_AllocCodeUMB( 5 * 256, ptr = DOSVM_AllocCodeUMB( 5 * 256, &DOSVM_dpmi_segments->int16_sel );
0, &DOSVM_dpmi_segments->int16_sel );
for(i=0; i<256; i++) { for(i=0; i<256; i++) {
/* /*
* Each 16-bit interrupt handler is 5 bytes: * Each 16-bit interrupt handler is 5 bytes:
...@@ -329,8 +235,7 @@ void DOSVM_InitSegments(void) ...@@ -329,8 +235,7 @@ void DOSVM_InitSegments(void)
* PM / offset 3: Stub which swaps back to 32-bit application code/stack. * PM / offset 3: Stub which swaps back to 32-bit application code/stack.
* PM / offset 5: Stub which enables interrupts * PM / offset 5: Stub which enables interrupts
*/ */
ptr = DOSVM_AllocCodeUMB( sizeof(relay), ptr = DOSVM_AllocCodeUMB( sizeof(relay), &DOSVM_dpmi_segments->relay_code_sel);
0, &DOSVM_dpmi_segments->relay_code_sel);
memcpy( ptr, relay, sizeof(relay) ); memcpy( ptr, relay, sizeof(relay) );
/* /*
......
...@@ -865,12 +865,10 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) ...@@ -865,12 +865,10 @@ DWORD __wine_emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context )
return ExceptionContinueExecution; return ExceptionContinueExecution;
case 0xfa: /* cli */ case 0xfa: /* cli */
get_vm86_teb_info()->dpmi_vif = 0;
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return ExceptionContinueExecution; return ExceptionContinueExecution;
case 0xfb: /* sti */ case 0xfb: /* sti */
get_vm86_teb_info()->dpmi_vif = 1;
context->Eip += prefixlen + 1; context->Eip += prefixlen + 1;
return ExceptionContinueExecution; return ExceptionContinueExecution;
} }
......
...@@ -2582,15 +2582,12 @@ static void INT21_IoctlScsiMgrHandler( CONTEXT *context ) ...@@ -2582,15 +2582,12 @@ static void INT21_IoctlScsiMgrHandler( CONTEXT *context )
SET_DX( context, 0xc0c0 ); SET_DX( context, 0xc0c0 );
break; break;
case 0x02: /* READ FROM CHARACTER DEVICE CONTROL CHANNEL */
DOSVM_ASPIHandler(context);
break;
case 0x0a: /* CHECK IF HANDLE IS REMOTE */ case 0x0a: /* CHECK IF HANDLE IS REMOTE */
SET_DX( context, 0 ); SET_DX( context, 0 );
break; break;
case 0x01: /* SET DEVICE INFORMATION */ case 0x01: /* SET DEVICE INFORMATION */
case 0x02: /* READ FROM CHARACTER DEVICE CONTROL CHANNEL */
case 0x03: /* WRITE TO CHARACTER DEVICE CONTROL CHANNEL */ case 0x03: /* WRITE TO CHARACTER DEVICE CONTROL CHANNEL */
case 0x06: /* GET INPUT STATUS */ case 0x06: /* GET INPUT STATUS */
case 0x07: /* GET OUTPUT STATUS */ case 0x07: /* GET OUTPUT STATUS */
...@@ -4291,10 +4288,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context ) ...@@ -4291,10 +4288,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
TRACE("SET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); TRACE("SET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
{ {
FARPROC16 ptr = (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context) ); FARPROC16 ptr = (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context) );
if (!ISV86(context)) DOSVM_SetPMHandler16( AL_reg(context), ptr );
DOSVM_SetPMHandler16( AL_reg(context), ptr );
else
DOSVM_SetRMHandler( AL_reg(context), ptr );
} }
break; break;
...@@ -4487,11 +4481,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context ) ...@@ -4487,11 +4481,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT *context )
case 0x35: /* GET INTERRUPT VECTOR */ case 0x35: /* GET INTERRUPT VECTOR */
TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context)); TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
{ {
FARPROC16 addr; FARPROC16 addr = DOSVM_GetPMHandler16( AL_reg(context) );
if (!ISV86(context))
addr = DOSVM_GetPMHandler16( AL_reg(context) );
else
addr = DOSVM_GetRMHandler( AL_reg(context) );
context->SegEs = SELECTOROF(addr); context->SegEs = SELECTOROF(addr);
SET_BX( context, OFFSETOF(addr) ); SET_BX( context, OFFSETOF(addr) );
} }
......
...@@ -139,26 +139,8 @@ void WINAPI DOSVM_Int2fHandler( CONTEXT *context ) ...@@ -139,26 +139,8 @@ void WINAPI DOSVM_Int2fHandler( CONTEXT *context )
break; break;
case 0x43: case 0x43:
#if 1
switch (LOBYTE(context->Eax))
{
case 0x00: /* XMS v2+ installation check */
WARN("XMS is not fully implemented\n");
SET_AL( context, 0x80 );
break;
case 0x10: /* XMS v2+ get driver address */
{
context->SegEs = DOSVM_dpmi_segments->xms_seg;
SET_BX( context, 0 );
break;
}
default:
INT_BARF( context, 0x2f );
}
#else
FIXME("check for XMS (not supported)\n"); FIXME("check for XMS (not supported)\n");
SET_AL( context, 0x42 ); /* != 0x80 */ SET_AL( context, 0x42 ); /* != 0x80 */
#endif
break; break;
case 0x45: case 0x45:
...@@ -399,7 +381,7 @@ static void do_int2f_16( CONTEXT *context ) ...@@ -399,7 +381,7 @@ static void do_int2f_16( CONTEXT *context )
SET_CL( context, si.wProcessorLevel ); SET_CL( context, si.wProcessorLevel );
SET_DX( context, 0x005a ); /* DPMI major/minor 0.90 */ SET_DX( context, 0x005a ); /* DPMI major/minor 0.90 */
SET_SI( context, 0 ); /* # of para. of DOS extended private data */ SET_SI( context, 0 ); /* # of para. of DOS extended private data */
context->SegEs = DOSVM_dpmi_segments->dpmi_seg; context->SegEs = 0; /* no DPMI switch */
SET_DI( context, 0 ); /* ES:DI is DPMI switch entry point */ SET_DI( context, 0 ); /* ES:DI is DPMI switch entry point */
break; break;
} }
......
...@@ -47,7 +47,6 @@ static void WINAPI DOSVM_Int5cHandler(CONTEXT*); ...@@ -47,7 +47,6 @@ static void WINAPI DOSVM_Int5cHandler(CONTEXT*);
static void WINAPI DOSVM_DefaultHandler(CONTEXT*); static void WINAPI DOSVM_DefaultHandler(CONTEXT*);
static FARPROC16 DOSVM_Vectors16[256]; static FARPROC16 DOSVM_Vectors16[256];
static FARPROC48 DOSVM_Vectors48[256];
static const INTPROC DOSVM_VectorsBuiltin[] = static const INTPROC DOSVM_VectorsBuiltin[] =
{ {
/* 00 */ 0, 0, 0, 0, /* 00 */ 0, 0, 0, 0,
...@@ -83,30 +82,7 @@ static const INTPROC DOSVM_VectorsBuiltin[] = ...@@ -83,30 +82,7 @@ static const INTPROC DOSVM_VectorsBuiltin[] =
/* /*
* Sizes of real mode and protected mode interrupt stubs. * Sizes of real mode and protected mode interrupt stubs.
*/ */
#define DOSVM_STUB_RM 4
#define DOSVM_STUB_PM16 5 #define DOSVM_STUB_PM16 5
#define DOSVM_STUB_PM48 6
/**********************************************************************
* DOSVM_GetRMVector
*
* Return pointer to real mode interrupt vector. These are not at fixed
* location because those Win16 programs that do not use any real mode
* code have protected NULL pointer catching block at low linear memory
* and interrupt vectors have been moved to another location.
*/
static FARPROC16* DOSVM_GetRMVector( BYTE intnum )
{
LDT_ENTRY entry;
FARPROC16 proc;
proc = GetProcAddress16( GetModuleHandle16( "KERNEL" ),
(LPCSTR)(ULONG_PTR)183 );
wine_ldt_get_entry( LOWORD(proc), &entry );
return (FARPROC16*)wine_ldt_get_base( &entry ) + intnum;
}
/********************************************************************** /**********************************************************************
...@@ -224,40 +200,13 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum ) ...@@ -224,40 +200,13 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
DOSMEM_InitDosMemory(); DOSMEM_InitDosMemory();
if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel) if (context->SegCs == DOSVM_dpmi_segments->relay_code_sel)
{
DOSVM_BuildCallFrame( context,
DOSVM_IntProcRelay,
DOSVM_RawModeSwitchHandler );
}
else if (context->SegCs == DOSVM_dpmi_segments->relay_code_sel)
{ {
/* /*
* This must not be called using DOSVM_BuildCallFrame. * This must not be called using DOSVM_BuildCallFrame.
*/ */
DOSVM_RelayHandler( context ); DOSVM_RelayHandler( context );
} }
else if (context->SegCs == DOSVM_dpmi_segments->int48_sel)
{
/* Restore original flags stored into the stack by the caller. */
DWORD *stack = CTX_SEG_OFF_TO_LIN(context,
context->SegSs, context->Esp);
context->EFlags = stack[2];
if (intnum != context->Eip / DOSVM_STUB_PM48)
WARN( "interrupt stub has been modified "
"(interrupt is %02x, interrupt stub is %02x)\n",
intnum, context->Eip/DOSVM_STUB_PM48 );
TRACE( "builtin interrupt %02x has been branched to\n", intnum );
if (intnum == 0x25 || intnum == 0x26)
DOSVM_PushFlags( context, TRUE, TRUE );
DOSVM_BuildCallFrame( context,
DOSVM_IntProcRelay,
DOSVM_GetBuiltinHandler(intnum) );
}
else if (context->SegCs == DOSVM_dpmi_segments->int16_sel) else if (context->SegCs == DOSVM_dpmi_segments->int16_sel)
{ {
/* Restore original flags stored into the stack by the caller. */ /* Restore original flags stored into the stack by the caller. */
...@@ -304,104 +253,40 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum ) ...@@ -304,104 +253,40 @@ BOOL DOSVM_EmulateInterruptPM( CONTEXT *context, BYTE intnum )
*/ */
void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum ) void DOSVM_HardwareInterruptPM( CONTEXT *context, BYTE intnum )
{ {
if(DOSVM_IsDos32()) FARPROC16 addr = DOSVM_GetPMHandler16( intnum );
{
FARPROC48 addr = DOSVM_GetPMHandler48( intnum );
if (addr.selector == DOSVM_dpmi_segments->int48_sel)
{
TRACE( "builtin interrupt %02x has been invoked "
"(through vector %02x)\n",
addr.offset / DOSVM_STUB_PM48, intnum );
if (intnum == 0x25 || intnum == 0x26) if (SELECTOROF(addr) == DOSVM_dpmi_segments->int16_sel)
DOSVM_PushFlags( context, TRUE, FALSE ); {
TRACE( "builtin interrupt %02x has been invoked "
DOSVM_BuildCallFrame( context, "(through vector %02x)\n",
DOSVM_IntProcRelay, OFFSETOF(addr)/DOSVM_STUB_PM16, intnum );
DOSVM_GetBuiltinHandler(
addr.offset/DOSVM_STUB_PM48 ) );
}
else
{
DWORD *stack;
TRACE( "invoking hooked interrupt %02x at %04x:%08x\n",
intnum, addr.selector, addr.offset );
/* Push the flags and return address on the stack */ if (intnum == 0x25 || intnum == 0x26)
stack = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp); DOSVM_PushFlags( context, FALSE, FALSE );
*(--stack) = context->EFlags;
*(--stack) = context->SegCs;
*(--stack) = context->Eip;
context->Esp += -12;
/* Jump to the interrupt handler */ DOSVM_BuildCallFrame( context,
context->SegCs = addr.selector; DOSVM_IntProcRelay,
context->Eip = addr.offset; DOSVM_GetBuiltinHandler(
} OFFSETOF(addr)/DOSVM_STUB_PM16 ) );
} }
else else
{ {
FARPROC16 addr = DOSVM_GetPMHandler16( intnum ); TRACE( "invoking hooked interrupt %02x at %04x:%04x\n",
intnum, SELECTOROF(addr), OFFSETOF(addr) );
if (SELECTOROF(addr) == DOSVM_dpmi_segments->int16_sel)
{
TRACE( "builtin interrupt %02x has been invoked "
"(through vector %02x)\n",
OFFSETOF(addr)/DOSVM_STUB_PM16, intnum );
if (intnum == 0x25 || intnum == 0x26)
DOSVM_PushFlags( context, FALSE, FALSE );
DOSVM_BuildCallFrame( context,
DOSVM_IntProcRelay,
DOSVM_GetBuiltinHandler(
OFFSETOF(addr)/DOSVM_STUB_PM16 ) );
}
else
{
TRACE( "invoking hooked interrupt %02x at %04x:%04x\n",
intnum, SELECTOROF(addr), OFFSETOF(addr) );
/* Push the flags and return address on the stack */ /* Push the flags and return address on the stack */
PUSH_WORD16( context, LOWORD(context->EFlags) ); PUSH_WORD16( context, LOWORD(context->EFlags) );
PUSH_WORD16( context, context->SegCs ); PUSH_WORD16( context, context->SegCs );
PUSH_WORD16( context, LOWORD(context->Eip) ); PUSH_WORD16( context, LOWORD(context->Eip) );
/* Jump to the interrupt handler */ /* Jump to the interrupt handler */
context->SegCs = HIWORD(addr); context->SegCs = HIWORD(addr);
context->Eip = LOWORD(addr); context->Eip = LOWORD(addr);
}
} }
} }
/********************************************************************** /**********************************************************************
* DOSVM_GetRMHandler
*
* Return the real mode interrupt vector for a given interrupt.
*/
FARPROC16 DOSVM_GetRMHandler( BYTE intnum )
{
return *DOSVM_GetRMVector( intnum );
}
/**********************************************************************
* DOSVM_SetRMHandler
*
* Set the real mode interrupt handler for a given interrupt.
*/
void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
{
TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
intnum, HIWORD(handler), LOWORD(handler) );
*DOSVM_GetRMVector( intnum ) = handler;
}
/**********************************************************************
* DOSVM_GetPMHandler16 * DOSVM_GetPMHandler16
* *
* Return the protected mode interrupt vector for a given interrupt. * Return the protected mode interrupt vector for a given interrupt.
...@@ -497,37 +382,6 @@ void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler ) ...@@ -497,37 +382,6 @@ void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler )
/********************************************************************** /**********************************************************************
* DOSVM_GetPMHandler48
*
* Return the protected mode interrupt vector for a given interrupt.
* Used to get 48-bit pointer for 32-bit interrupt handlers in DPMI32.
*/
FARPROC48 DOSVM_GetPMHandler48( BYTE intnum )
{
if (!DOSVM_Vectors48[intnum].selector)
{
DOSVM_Vectors48[intnum].selector = DOSVM_dpmi_segments->int48_sel;
DOSVM_Vectors48[intnum].offset = DOSVM_STUB_PM48 * intnum;
}
return DOSVM_Vectors48[intnum];
}
/**********************************************************************
* DOSVM_SetPMHandler48
*
* Set the protected mode interrupt handler for a given interrupt.
* Used to set 48-bit pointer for 32-bit interrupt handlers in DPMI32.
*/
void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler )
{
TRACE("Set 32-bit protected mode interrupt vector %02x <- %04x:%08x\n",
intnum, handler.selector, handler.offset );
DOSVM_Vectors48[intnum] = handler;
}
/**********************************************************************
* DOSVM_CallBuiltinHandler * DOSVM_CallBuiltinHandler
* *
* Execute Wine interrupt handler procedure. * Execute Wine interrupt handler procedure.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment