Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
770eb51e
Commit
770eb51e
authored
Sep 24, 2000
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved most global data out of the LPDOSTASK structure.
Allocate DPMI real-mode segments globally at startup. Try to allocate DOS memory at address 0.
parent
0ff083ba
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
440 additions
and
656 deletions
+440
-656
dosexe.h
include/dosexe.h
+4
-36
ldt.h
include/ldt.h
+2
-0
miscemu.h
include/miscemu.h
+8
-5
winnt.h
include/winnt.h
+0
-1
dosvm.c
loader/dos/dosvm.c
+85
-148
module.c
loader/dos/module.c
+108
-193
task.c
loader/task.c
+4
-5
instr.c
memory/instr.c
+2
-2
devices.c
msdos/devices.c
+9
-10
dosmem.c
msdos/dosmem.c
+152
-75
dpmi.c
msdos/dpmi.c
+21
-114
int09.c
msdos/int09.c
+14
-25
int2f.c
msdos/int2f.c
+7
-14
int33.c
msdos/int33.c
+24
-28
No files found.
include/dosexe.h
View file @
770eb51e
...
...
@@ -11,38 +11,13 @@
#include "winbase.h"
/* for LPSTARTUPINFO32A */
#include "winnt.h"
/* for PCONTEXT */
typedef
struct
_DOSSYSTEM
{
int
id
;
void
*
data
;
struct
_DOSSYSTEM
*
next
;
}
DOSSYSTEM
;
struct
_DOSEVENT
;
typedef
struct
_DOSTASK
{
LPVOID
img
;
unsigned
img_ofs
;
WORD
psp_seg
,
load_seg
;
WORD
init_cs
,
init_ip
,
init_ss
,
init_sp
;
WORD
xms_seg
;
WORD
dpmi_seg
,
dpmi_sel
,
dpmi_flag
;
char
mm_name
[
128
];
int
mm_fd
;
HANDLE
hReadPipe
,
hXPipe
,
hConInput
,
hConOutput
;
int
read_pipe
,
write_pipe
;
pid_t
task
;
int
sig_sent
,
entered
,
idling
;
struct
_DOSEVENT
*
pending
,
*
current
;
DOSSYSTEM
*
sys
;
WORD
psp_seg
;
WORD
dpmi_flag
;
}
DOSTASK
,
*
LPDOSTASK
;
typedef
struct
_DOSEVENT
{
int
irq
,
priority
;
void
(
*
relay
)(
LPDOSTASK
,
CONTEXT86
*
,
void
*
);
void
*
data
;
struct
_DOSEVENT
*
next
;
}
DOSEVENT
,
*
LPDOSEVENT
;
#define DOS_PRIORITY_REALTIME 0
/* IRQ0 */
#define DOS_PRIORITY_KEYBOARD 1
/* IRQ1 */
#define DOS_PRIORITY_VGA 2
/* IRQ9 */
...
...
@@ -50,26 +25,19 @@ typedef struct _DOSEVENT {
#define DOS_PRIORITY_SERIAL 10
/* IRQ4 */
#if defined(linux) && defined(__i386__)
#define MZ_SUPPORTED
extern
BOOL
MZ_InitTask
(
LPDOSTASK
lpDosTask
);
extern
void
MZ_KillTask
(
LPDOSTASK
lpDosTask
);
extern
LPDOSTASK
MZ_AllocDPMITask
(
void
);
#endif
/* linux-i386 */
#define V86_FLAG 0x00020000
extern
BOOL
MZ_LoadImage
(
HMODULE
module
,
HANDLE
hFile
,
LPCSTR
filename
);
extern
LPDOSTASK
MZ_Current
(
void
);
extern
LPDOSTASK
MZ_AllocDPMITask
(
void
);
extern
int
DOSVM_Enter
(
CONTEXT86
*
context
);
extern
void
DOSVM_Wait
(
int
read_pipe
,
HANDLE
hObject
);
extern
void
DOSVM_QueueEvent
(
int
irq
,
int
priority
,
void
(
*
relay
)(
LPDOSTASK
,
CONTEXT86
*
,
void
*
),
void
*
data
);
extern
void
DOSVM_QueueEvent
(
int
irq
,
int
priority
,
void
(
*
relay
)(
CONTEXT86
*
,
void
*
),
void
*
data
);
extern
void
DOSVM_PIC_ioport_out
(
WORD
port
,
BYTE
val
);
extern
void
DOSVM_SetTimer
(
unsigned
ticks
);
extern
unsigned
DOSVM_GetTimer
(
void
);
extern
void
DOSVM_SetSystemData
(
int
id
,
void
*
data
);
extern
void
*
DOSVM_GetSystemData
(
int
id
);
#endif
/* __WINE_DOSEXE_H */
include/ldt.h
View file @
770eb51e
...
...
@@ -60,6 +60,8 @@ extern ldt_copy_entry ldt_copy[LDT_SIZE];
#define PTR_SEG_OFF_TO_LIN(seg,off) \
((void*)(GET_SEL_BASE(seg) + (unsigned int)(off)))
#define PTR_REAL_TO_LIN(seg,off) \
((void*)(((unsigned int)(seg) << 4) + LOWORD(off)))
#define PTR_SEG_TO_LIN(ptr) \
PTR_SEG_OFF_TO_LIN(SELECTOROF(ptr),OFFSETOF(ptr))
#define PTR_SEG_OFF_TO_SEGPTR(seg,off) \
...
...
include/miscemu.h
View file @
770eb51e
...
...
@@ -128,8 +128,11 @@ extern BYTE * DOSMEM_BiosSys();
extern
DWORD
DOSMEM_CollateTable
;
extern
DWORD
DOSMEM_ErrorCall
;
extern
DWORD
DOSMEM_ErrorBuffer
;
/* various real-mode code stubs */
extern
WORD
DOSMEM_wrap_seg
;
extern
WORD
DOSMEM_xms_seg
;
extern
WORD
DOSMEM_dpmi_seg
;
extern
WORD
DOSMEM_dpmi_sel
;
extern
DWORD
DOS_LOLSeg
;
extern
struct
_DOS_LISTOFLISTS
*
DOSMEM_LOL
();
...
...
@@ -249,7 +252,7 @@ extern void ASPI_DOS_HandleInt(CONTEXT86 *context);
* a *32-bit* general register as third parameter, e.g.
* CTX_SEG_OFF_TO_LIN( context, DS_reg(context), EDX_reg(context) )
* This will generate a linear pointer in all three cases:
* Real-Mode: Seg*16 + LOWORD(Offset)
+ V86BASE
* Real-Mode: Seg*16 + LOWORD(Offset)
* 16-bit: convert (Seg, LOWORD(Offset)) to linear
* 32-bit: use Offset as linear address (DeviceIoControl!)
*
...
...
@@ -258,8 +261,8 @@ extern void ASPI_DOS_HandleInt(CONTEXT86 *context);
* (0 counts also as 32-bit segment).
*/
#define CTX_SEG_OFF_TO_LIN(context,seg,off) \
(ISV86(context) ?
(void*)(V86BASE(context)+((seg)<<4)+(off&0xff
ff)) : \
(!seg || IS_SELECTOR_SYSTEM(seg))? (void *)
off : PTR_SEG_OFF_TO_LIN(seg,off&0xffff
))
(ISV86(context) ?
PTR_REAL_TO_LIN((seg),(o
ff)) : \
(!seg || IS_SELECTOR_SYSTEM(seg))? (void *)
(off) : PTR_SEG_OFF_TO_LIN((seg),LOWORD(off)
))
#define INT_BARF(context,num) \
ERR( "int%x: unknown/not implemented parameters:\n" \
...
...
include/winnt.h
View file @
770eb51e
...
...
@@ -730,7 +730,6 @@ typedef HANDLE *PHANDLE;
#define RESET_ZFLAG(context) (EFL_reg(context) &= ~0x0040)
#define ISV86(context) (EFL_reg(context) & 0x00020000)
#define V86BASE(context) DOSMEM_MemoryBase()
/* Macros to retrieve the current context */
...
...
loader/dos/dosvm.c
View file @
770eb51e
...
...
@@ -58,6 +58,21 @@ DECLARE_DEBUG_CHANNEL(relay)
#undef TRY_PICRETURN
typedef
struct
_DOSEVENT
{
int
irq
,
priority
;
void
(
*
relay
)(
CONTEXT86
*
,
void
*
);
void
*
data
;
struct
_DOSEVENT
*
next
;
}
DOSEVENT
,
*
LPDOSEVENT
;
static
struct
_DOSEVENT
*
pending_event
,
*
current_event
;
static
int
sig_sent
,
entered
;
/* from module.c */
extern
int
read_pipe
,
write_pipe
;
extern
HANDLE
hReadPipe
;
extern
pid_t
dosmod_pid
;
static
void
do_exception
(
int
signal
,
CONTEXT86
*
context
)
{
EXCEPTION_RECORD
rec
;
...
...
@@ -77,10 +92,8 @@ static void do_exception( int signal, CONTEXT86 *context )
EXC_RtlRaiseException
(
&
rec
,
context
);
}
static
void
DOSVM_Dump
(
LPDOSTASK
lpDosTask
,
int
fn
,
int
sig
,
struct
vm86plus_struct
*
VM86
)
static
void
DOSVM_Dump
(
int
fn
,
int
sig
,
struct
vm86plus_struct
*
VM86
)
{
unsigned
iofs
;
BYTE
*
inst
;
int
x
;
...
...
@@ -106,20 +119,17 @@ static void DOSVM_Dump( LPDOSTASK lpDosTask, int fn, int sig,
fprintf
(
stderr
,
"CS=%04X DS=%04X ES=%04X SS=%04X
\n
"
,
REGS
.
cs
,
REGS
.
ds
,
REGS
.
es
,
REGS
.
ss
);
fprintf
(
stderr
,
"IP=%04lX EFLAGS=%08lX
\n
"
,
REGS
.
eip
,
REGS
.
eflags
);
i
ofs
=
((
DWORD
)
REGS
.
cs
<<
4
)
+
REGS
.
eip
;
i
nst
=
PTR_REAL_TO_LIN
(
REGS
.
cs
,
REGS
.
eip
)
;
#undef REGS
inst
=
(
BYTE
*
)
lpDosTask
->
img
+
iofs
;
printf
(
"Opcodes:"
);
for
(
x
=
0
;
x
<
8
;
x
++
)
printf
(
" %02x"
,
inst
[
x
]);
printf
(
"
\n
"
);
}
static
int
DOSVM_Int
(
int
vect
,
CONTEXT86
*
context
,
LPDOSTASK
lpDosTask
)
static
int
DOSVM_Int
(
int
vect
,
CONTEXT86
*
context
)
{
extern
UINT16
DPMI_wrap_seg
;
if
(
vect
==
0x31
)
{
if
(
CS_reg
(
context
)
==
D
PMI
_wrap_seg
)
{
if
(
CS_reg
(
context
)
==
D
OSMEM
_wrap_seg
)
{
/* exit from real-mode wrapper */
return
-
1
;
}
...
...
@@ -129,7 +139,7 @@ static int DOSVM_Int( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask )
return
0
;
}
static
void
DOSVM_SimulateInt
(
int
vect
,
CONTEXT86
*
context
,
LPDOSTASK
lpDosTask
)
static
void
DOSVM_SimulateInt
(
int
vect
,
CONTEXT86
*
context
)
{
FARPROC16
handler
=
INT_GetRMHandler
(
vect
);
...
...
@@ -137,7 +147,7 @@ static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask
/* if internal interrupt, call it directly */
INT_RealModeInterrupt
(
vect
,
context
);
}
else
{
WORD
*
stack
=
(
WORD
*
)(
V86BASE
(
context
)
+
(((
DWORD
)
SS_reg
(
context
))
<<
4
)
+
LOWORD
(
ESP_reg
(
context
))
);
WORD
*
stack
=
PTR_REAL_TO_LIN
(
context
->
SegSs
,
context
->
Esp
);
WORD
flag
=
LOWORD
(
EFL_reg
(
context
));
if
(
IF_ENABLED
(
context
))
flag
|=
IF_MASK
;
...
...
@@ -154,51 +164,50 @@ static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask
}
#define SHOULD_PEND(x) \
(x && ((!
lpDosTask->current) || (x->priority < lpDosTask->curr
ent->priority)))
(x && ((!
current_event) || (x->priority < current_ev
ent->priority)))
static
void
DOSVM_SendQueuedEvent
(
CONTEXT86
*
context
,
LPDOSTASK
lpDosTask
)
static
void
DOSVM_SendQueuedEvent
(
CONTEXT86
*
context
)
{
LPDOSEVENT
event
=
lpDosTask
->
pending
;
LPDOSEVENT
event
=
pending_event
;
if
(
SHOULD_PEND
(
event
))
{
/* remove from "pending" list */
lpDosTask
->
pending
=
event
->
next
;
pending_event
=
event
->
next
;
/* process event */
if
(
event
->
irq
>=
0
)
{
/* it's an IRQ, move it to "current" list */
event
->
next
=
lpDosTask
->
curr
ent
;
lpDosTask
->
curr
ent
=
event
;
event
->
next
=
current_ev
ent
;
current_ev
ent
=
event
;
TRACE_
(
int
)(
"dispatching IRQ %d
\n
"
,
event
->
irq
);
/* note that if DOSVM_SimulateInt calls an internal interrupt directly,
*
lpDosTask->curr
ent might be cleared (and event freed) in this very call! */
DOSVM_SimulateInt
((
event
->
irq
<
8
)
?
(
event
->
irq
+
8
)
:
(
event
->
irq
-
8
+
0x70
),
context
,
lpDosTask
);
*
current_ev
ent might be cleared (and event freed) in this very call! */
DOSVM_SimulateInt
((
event
->
irq
<
8
)
?
(
event
->
irq
+
8
)
:
(
event
->
irq
-
8
+
0x70
),
context
);
}
else
{
/* callback event */
TRACE_
(
int
)(
"dispatching callback event
\n
"
);
(
*
event
->
relay
)(
lpDosTask
,
context
,
event
->
data
);
(
*
event
->
relay
)(
context
,
event
->
data
);
free
(
event
);
}
}
if
(
!
SHOULD_PEND
(
lpDosTask
->
pending
))
{
if
(
!
SHOULD_PEND
(
pending_event
))
{
TRACE_
(
int
)(
"clearing Pending flag
\n
"
);
CLR_PEND
(
context
);
}
}
static
void
DOSVM_SendQueuedEvents
(
CONTEXT86
*
context
,
LPDOSTASK
lpDosTask
)
static
void
DOSVM_SendQueuedEvents
(
CONTEXT86
*
context
)
{
/* we will send all queued events as long as interrupts are enabled,
* but IRQ events will disable interrupts again */
while
(
IS_PEND
(
context
)
&&
IF_ENABLED
(
context
))
DOSVM_SendQueuedEvent
(
context
,
lpDosTask
);
DOSVM_SendQueuedEvent
(
context
);
}
void
DOSVM_QueueEvent
(
int
irq
,
int
priority
,
void
(
*
relay
)(
LPDOSTASK
,
CONTEXT86
*
,
void
*
),
void
*
data
)
void
DOSVM_QueueEvent
(
int
irq
,
int
priority
,
void
(
*
relay
)(
CONTEXT86
*
,
void
*
),
void
*
data
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
LPDOSEVENT
event
,
cur
,
prev
;
if
(
lpDosTask
&&
lpDosTask
->
entered
)
{
if
(
entered
)
{
event
=
malloc
(
sizeof
(
DOSEVENT
));
if
(
!
event
)
{
ERR_
(
int
)(
"out of memory allocating event entry
\n
"
);
...
...
@@ -209,20 +218,20 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*
/* insert event into linked list, in order *after*
* all earlier events of higher or equal priority */
cur
=
lpDosTask
->
pending
;
prev
=
NULL
;
cur
=
pending_event
;
prev
=
NULL
;
while
(
cur
&&
cur
->
priority
<=
priority
)
{
prev
=
cur
;
cur
=
cur
->
next
;
}
event
->
next
=
cur
;
if
(
prev
)
prev
->
next
=
event
;
else
lpDosTask
->
pending
=
event
;
else
pending_event
=
event
;
/* get dosmod's attention to the new event, if necessary */
if
(
!
lpDosTask
->
sig_sent
)
{
if
(
!
sig_sent
)
{
TRACE_
(
int
)(
"new event queued, signalling dosmod
\n
"
);
kill
(
lpDosTask
->
task
,
SIGUSR2
);
lpDosTask
->
sig_sent
++
;
kill
(
dosmod_pid
,
SIGUSR2
);
sig_sent
++
;
}
else
{
TRACE_
(
int
)(
"new event queued
\n
"
);
}
...
...
@@ -234,7 +243,7 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*
/* callback event, perform it with dummy context */
CONTEXT86
context
;
memset
(
&
context
,
0
,
sizeof
(
context
));
(
*
relay
)(
lpDosTask
,
&
context
,
data
);
(
*
relay
)(
&
context
,
data
);
}
else
{
ERR_
(
int
)(
"IRQ without DOS task: should not happen"
);
}
...
...
@@ -247,8 +256,7 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*
CP(ss,SS); CP(fs,FS); CP(gs,GS); \
CP(eip,EIP); CP(eflags,EFL)
static
int
DOSVM_Process
(
LPDOSTASK
lpDosTask
,
int
fn
,
int
sig
,
struct
vm86plus_struct
*
VM86
)
static
int
DOSVM_Process
(
int
fn
,
int
sig
,
struct
vm86plus_struct
*
VM86
)
{
CONTEXT86
context
;
int
ret
=
0
;
...
...
@@ -270,7 +278,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
}
#else
/* linux doesn't preserve pending flag on return */
if
(
SHOULD_PEND
(
lpDosTask
->
pending
))
{
if
(
SHOULD_PEND
(
pending_event
))
{
SET_PEND
(
&
context
);
}
#endif
...
...
@@ -280,48 +288,48 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
TRACE_
(
int
)(
"DOS module caught signal %d
\n
"
,
sig
);
if
((
sig
==
SIGALRM
)
||
(
sig
==
SIGUSR2
))
{
if
(
sig
==
SIGALRM
)
{
lpDosTask
->
sig_sent
++
;
sig_sent
++
;
DOSVM_QueueEvent
(
0
,
DOS_PRIORITY_REALTIME
,
NULL
,
NULL
);
}
if
(
lpDosTask
->
pending
)
{
if
(
pending_event
)
{
TRACE_
(
int
)(
"setting Pending flag, interrupts are currently %s
\n
"
,
IF_ENABLED
(
&
context
)
?
"enabled"
:
"disabled"
);
SET_PEND
(
&
context
);
DOSVM_SendQueuedEvents
(
&
context
,
lpDosTask
);
DOSVM_SendQueuedEvents
(
&
context
);
}
else
{
TRACE_
(
int
)(
"no events are pending, clearing Pending flag
\n
"
);
CLR_PEND
(
&
context
);
}
lpDosTask
->
sig_sent
--
;
sig_sent
--
;
}
else
if
((
sig
==
SIGHUP
)
||
(
sig
==
SIGILL
)
||
(
sig
==
SIGSEGV
))
{
do_exception
(
sig
,
&
context
);
}
else
{
DOSVM_Dump
(
lpDosTask
,
fn
,
sig
,
VM86
);
DOSVM_Dump
(
fn
,
sig
,
VM86
);
ret
=-
1
;
}
break
;
case
VM86_UNKNOWN
:
/* unhandled GPF */
DOSVM_Dump
(
lpDosTask
,
fn
,
sig
,
VM86
);
DOSVM_Dump
(
fn
,
sig
,
VM86
);
do_exception
(
SIGSEGV
,
&
context
);
break
;
case
VM86_INTx
:
if
(
TRACE_ON
(
relay
))
DPRINTF
(
"Call DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx
\n
"
,
VM86_ARG
(
fn
),
context
.
Eax
,
context
.
SegCs
,
context
.
Eip
);
ret
=
DOSVM_Int
(
VM86_ARG
(
fn
),
&
context
,
lpDosTask
);
ret
=
DOSVM_Int
(
VM86_ARG
(
fn
),
&
context
);
if
(
TRACE_ON
(
relay
))
DPRINTF
(
"Ret DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx
\n
"
,
VM86_ARG
(
fn
),
context
.
Eax
,
context
.
SegCs
,
context
.
Eip
);
break
;
case
VM86_STI
:
case
VM86_PICRETURN
:
TRACE_
(
int
)(
"DOS task enabled interrupts with events pending, sending events
\n
"
);
DOSVM_SendQueuedEvents
(
&
context
,
lpDosTask
);
DOSVM_SendQueuedEvents
(
&
context
);
break
;
case
VM86_TRAP
:
do_exception
(
SIGTRAP
,
&
context
);
break
;
default:
DOSVM_Dump
(
lpDosTask
,
fn
,
sig
,
VM86
);
DOSVM_Dump
(
fn
,
sig
,
VM86
);
ret
=-
1
;
}
...
...
@@ -335,7 +343,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
return
ret
;
}
static
void
DOSVM_ProcessConsole
(
LPDOSTASK
lpDosTask
)
static
void
DOSVM_ProcessConsole
(
void
)
{
INPUT_RECORD
msg
;
DWORD
res
;
...
...
@@ -360,7 +368,7 @@ static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask)
}
}
static
void
DOSVM_ProcessMessage
(
LPDOSTASK
lpDosTask
,
MSG
*
msg
)
static
void
DOSVM_ProcessMessage
(
MSG
*
msg
)
{
BYTE
scan
=
0
;
...
...
@@ -391,21 +399,20 @@ static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg)
void
DOSVM_Wait
(
int
read_pipe
,
HANDLE
hObject
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
MSG
msg
;
DWORD
waitret
;
HANDLE
objs
[
2
];
int
objc
;
BOOL
got_msg
=
FALSE
;
objs
[
0
]
=
lpDosTask
->
hConInput
;
objs
[
0
]
=
GetStdHandle
(
STD_INPUT_HANDLE
)
;
objs
[
1
]
=
hObject
;
objc
=
hObject
?
2
:
1
;
do
{
/* check for messages (waste time before the response check below) */
while
(
Callout
.
PeekMessageA
(
&
msg
,
0
,
0
,
0
,
PM_REMOVE
|
PM_NOYIELD
))
{
/* got a message */
DOSVM_ProcessMessage
(
lpDosTask
,
&
msg
);
DOSVM_ProcessMessage
(
&
msg
);
/* we don't need a TranslateMessage here */
Callout
.
DispatchMessageA
(
&
msg
);
got_msg
=
TRUE
;
...
...
@@ -415,7 +422,7 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject )
INPUT_RECORD
msg
;
DWORD
num
;
if
(
PeekConsoleInputA
(
objs
[
0
],
&
msg
,
1
,
&
num
)
&&
num
)
{
DOSVM_ProcessConsole
(
lpDosTask
);
DOSVM_ProcessConsole
();
got_msg
=
TRUE
;
}
}
...
...
@@ -439,63 +446,42 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject )
if
(
waitret
==
(
WAIT_OBJECT_0
+
1
))
break
;
}
if
(
waitret
==
WAIT_OBJECT_0
)
{
DOSVM_ProcessConsole
(
lpDosTask
);
DOSVM_ProcessConsole
();
}
}
while
(
TRUE
);
}
int
DOSVM_Enter
(
CONTEXT86
*
context
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
struct
vm86plus_struct
VM86
;
int
stat
,
len
,
sig
;
if
(
!
lpDosTask
)
{
/* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */
ERR_
(
module
)(
"dosmod has not been initialized!"
);
return
-
1
;
}
if
(
context
)
{
#define CP(x,y) VM86.regs.x = y##_reg(context)
CV
;
#undef CP
if
(
VM86
.
regs
.
eflags
&
IF_MASK
)
VM86
.
regs
.
eflags
|=
VIF_MASK
;
}
else
{
/* initial setup */
/* registers */
memset
(
&
VM86
,
0
,
sizeof
(
VM86
));
VM86
.
regs
.
cs
=
lpDosTask
->
init_cs
;
VM86
.
regs
.
eip
=
lpDosTask
->
init_ip
;
VM86
.
regs
.
ss
=
lpDosTask
->
init_ss
;
VM86
.
regs
.
esp
=
lpDosTask
->
init_sp
;
VM86
.
regs
.
ds
=
lpDosTask
->
psp_seg
;
VM86
.
regs
.
es
=
lpDosTask
->
psp_seg
;
VM86
.
regs
.
eflags
=
VIF_MASK
;
/* hmm, what else do we need? */
}
/* main exchange loop */
lpDosTask
->
entered
++
;
entered
++
;
do
{
TRACE_
(
module
)(
"thread is: %lx
\n
"
,
GetCurrentThreadId
());
stat
=
VM86_ENTER
;
errno
=
0
;
/* transmit VM86 structure to dosmod task */
if
(
write
(
lpDosTask
->
write_pipe
,
&
stat
,
sizeof
(
stat
))
!=
sizeof
(
stat
))
{
ERR_
(
module
)(
"dosmod sync lost, errno=%d, fd=%d, pid=%d
\n
"
,
errno
,
lpDosTask
->
write_pipe
,
getpid
());
if
(
write
(
write_pipe
,
&
stat
,
sizeof
(
stat
))
!=
sizeof
(
stat
))
{
ERR_
(
module
)(
"dosmod sync lost, errno=%d, fd=%d, pid=%d
\n
"
,
errno
,
write_pipe
,
getpid
());
return
-
1
;
}
if
(
write
(
lpDosTask
->
write_pipe
,
&
VM86
,
sizeof
(
VM86
))
!=
sizeof
(
VM86
))
{
if
(
write
(
write_pipe
,
&
VM86
,
sizeof
(
VM86
))
!=
sizeof
(
VM86
))
{
ERR_
(
module
)(
"dosmod sync lost, errno=%d
\n
"
,
errno
);
return
-
1
;
}
/* wait for response, doing other things in the meantime */
DOSVM_Wait
(
lpDosTask
->
read_pipe
,
lpDosTask
->
hReadPipe
);
DOSVM_Wait
(
read_pipe
,
hReadPipe
);
/* read response */
while
(
1
)
{
if
((
len
=
read
(
lpDosTask
->
read_pipe
,
&
stat
,
sizeof
(
stat
)))
==
sizeof
(
stat
))
break
;
if
((
len
=
read
(
read_pipe
,
&
stat
,
sizeof
(
stat
)))
==
sizeof
(
stat
))
break
;
if
(((
errno
==
EINTR
)
||
(
errno
==
EAGAIN
))
&&
(
len
<=
0
))
{
WARN_
(
module
)(
"rereading dosmod return code due to errno=%d, result=%d
\n
"
,
errno
,
len
);
continue
;
...
...
@@ -505,11 +491,10 @@ int DOSVM_Enter( CONTEXT86 *context )
}
TRACE_
(
module
)(
"dosmod return code=%d
\n
"
,
stat
);
if
(
stat
==
DOSMOD_LEFTIDLE
)
{
lpDosTask
->
idling
--
;
continue
;
}
while
(
1
)
{
if
((
len
=
read
(
lpDosTask
->
read_pipe
,
&
VM86
,
sizeof
(
VM86
)))
==
sizeof
(
VM86
))
break
;
if
((
len
=
read
(
read_pipe
,
&
VM86
,
sizeof
(
VM86
)))
==
sizeof
(
VM86
))
break
;
if
(((
errno
==
EINTR
)
||
(
errno
==
EAGAIN
))
&&
(
len
<=
0
))
{
WARN_
(
module
)(
"rereading dosmod VM86 structure due to errno=%d, result=%d
\n
"
,
errno
,
len
);
continue
;
...
...
@@ -519,7 +504,7 @@ int DOSVM_Enter( CONTEXT86 *context )
}
if
((
stat
&
0xff
)
==
DOSMOD_SIGNAL
)
{
while
(
1
)
{
if
((
len
=
read
(
lpDosTask
->
read_pipe
,
&
sig
,
sizeof
(
sig
)))
==
sizeof
(
sig
))
break
;
if
((
len
=
read
(
read_pipe
,
&
sig
,
sizeof
(
sig
)))
==
sizeof
(
sig
))
break
;
if
(((
errno
==
EINTR
)
||
(
errno
==
EAGAIN
))
&&
(
len
<=
0
))
{
WARN_
(
module
)(
"rereading dosmod signal due to errno=%d, result=%d
\n
"
,
errno
,
len
);
continue
;
...
...
@@ -529,8 +514,8 @@ int DOSVM_Enter( CONTEXT86 *context )
}
while
(
0
);
}
else
sig
=
0
;
/* got response */
}
while
(
DOSVM_Process
(
lpDosTask
,
stat
,
sig
,
&
VM86
)
>=
0
);
lpDosTask
->
entered
--
;
}
while
(
DOSVM_Process
(
stat
,
sig
,
&
VM86
)
>=
0
);
entered
--
;
if
(
context
)
{
#define CP(x,y) y##_reg(context) = VM86.regs.x
...
...
@@ -542,27 +527,25 @@ int DOSVM_Enter( CONTEXT86 *context )
void
DOSVM_PIC_ioport_out
(
WORD
port
,
BYTE
val
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
LPDOSEVENT
event
;
LPDOSEVENT
event
;
if
(
lpDosTask
)
{
if
((
port
==
0x20
)
&&
(
val
==
0x20
))
{
if
(
lpDosTask
->
curr
ent
)
{
if
(
current_ev
ent
)
{
/* EOI (End Of Interrupt) */
TRACE_
(
int
)(
"received EOI for current IRQ, clearing
\n
"
);
event
=
lpDosTask
->
curr
ent
;
lpDosTask
->
curr
ent
=
event
->
next
;
event
=
current_ev
ent
;
current_ev
ent
=
event
->
next
;
if
(
event
->
relay
)
(
*
event
->
relay
)(
lpDosTask
,
NULL
,
event
->
data
);
(
*
event
->
relay
)(
NULL
,
event
->
data
);
free
(
event
);
if
(
lpDosTask
->
pending
&&
!
lpDosTask
->
sig_sent
)
{
if
(
pending_event
&&
!
sig_sent
)
{
/* another event is pending, which we should probably
* be able to process now, so tell dosmod about it */
TRACE_
(
int
)(
"another event pending, signalling dosmod
\n
"
);
kill
(
lpDosTask
->
task
,
SIGUSR2
);
lpDosTask
->
sig_sent
++
;
kill
(
dosmod_pid
,
SIGUSR2
);
sig_sent
++
;
}
}
else
{
WARN_
(
int
)(
"EOI without active IRQ
\n
"
);
...
...
@@ -570,27 +553,25 @@ void DOSVM_PIC_ioport_out( WORD port, BYTE val)
}
else
{
FIXME_
(
int
)(
"unrecognized PIC command %02x
\n
"
,
val
);
}
}
}
void
DOSVM_SetTimer
(
unsigned
ticks
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
int
stat
=
DOSMOD_SET_TIMER
;
struct
timeval
tim
;
if
(
lpDosTask
)
{
if
(
MZ_Current
()
)
{
/* the PC clocks ticks at 1193180 Hz */
tim
.
tv_sec
=
0
;
tim
.
tv_usec
=
((
unsigned
long
long
)
ticks
*
1000000
)
/
1193180
;
/* sanity check */
if
(
!
tim
.
tv_usec
)
tim
.
tv_usec
=
1
;
if
(
write
(
lpDosTask
->
write_pipe
,
&
stat
,
sizeof
(
stat
))
!=
sizeof
(
stat
))
{
if
(
write
(
write_pipe
,
&
stat
,
sizeof
(
stat
))
!=
sizeof
(
stat
))
{
ERR_
(
module
)(
"dosmod sync lost, errno=%d
\n
"
,
errno
);
return
;
}
if
(
write
(
lpDosTask
->
write_pipe
,
&
tim
,
sizeof
(
tim
))
!=
sizeof
(
tim
))
{
if
(
write
(
write_pipe
,
&
tim
,
sizeof
(
tim
))
!=
sizeof
(
tim
))
{
ERR_
(
module
)(
"dosmod sync lost, errno=%d
\n
"
,
errno
);
return
;
}
...
...
@@ -600,18 +581,17 @@ void DOSVM_SetTimer( unsigned ticks )
unsigned
DOSVM_GetTimer
(
void
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
int
stat
=
DOSMOD_GET_TIMER
;
struct
timeval
tim
;
if
(
lpDosTask
)
{
if
(
write
(
lpDosTask
->
write_pipe
,
&
stat
,
sizeof
(
stat
))
!=
sizeof
(
stat
))
{
if
(
MZ_Current
()
)
{
if
(
write
(
write_pipe
,
&
stat
,
sizeof
(
stat
))
!=
sizeof
(
stat
))
{
ERR_
(
module
)(
"dosmod sync lost, errno=%d
\n
"
,
errno
);
return
0
;
}
/* read response */
while
(
1
)
{
if
(
read
(
lpDosTask
->
read_pipe
,
&
tim
,
sizeof
(
tim
))
==
sizeof
(
tim
))
break
;
if
(
read
(
read_pipe
,
&
tim
,
sizeof
(
tim
))
==
sizeof
(
tim
))
break
;
if
((
errno
==
EINTR
)
||
(
errno
==
EAGAIN
))
continue
;
ERR_
(
module
)(
"dosmod sync lost, errno=%d
\n
"
,
errno
);
return
0
;
...
...
@@ -621,47 +601,6 @@ unsigned DOSVM_GetTimer( void )
return
0
;
}
void
DOSVM_SetSystemData
(
int
id
,
void
*
data
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
DOSSYSTEM
*
sys
,
*
prev
;
if
(
lpDosTask
)
{
sys
=
lpDosTask
->
sys
;
prev
=
NULL
;
while
(
sys
&&
(
sys
->
id
!=
id
))
{
prev
=
sys
;
sys
=
sys
->
next
;
}
if
(
sys
)
{
free
(
sys
->
data
);
sys
->
data
=
data
;
}
else
{
sys
=
malloc
(
sizeof
(
DOSSYSTEM
));
sys
->
id
=
id
;
sys
->
data
=
data
;
sys
->
next
=
NULL
;
if
(
prev
)
prev
->
next
=
sys
;
else
lpDosTask
->
sys
=
sys
;
}
}
else
free
(
data
);
}
void
*
DOSVM_GetSystemData
(
int
id
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
DOSSYSTEM
*
sys
;
if
(
lpDosTask
)
{
sys
=
lpDosTask
->
sys
;
while
(
sys
&&
(
sys
->
id
!=
id
))
sys
=
sys
->
next
;
if
(
sys
)
return
sys
->
data
;
}
return
NULL
;
}
#else
/* !MZ_SUPPORTED */
int
DOSVM_Enter
(
CONTEXT86
*
context
)
...
...
@@ -674,15 +613,13 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject) {}
void
DOSVM_PIC_ioport_out
(
WORD
port
,
BYTE
val
)
{}
void
DOSVM_SetTimer
(
unsigned
ticks
)
{}
unsigned
DOSVM_GetTimer
(
void
)
{
return
0
;
}
void
DOSVM_SetSystemData
(
int
id
,
void
*
data
)
{
free
(
data
);
}
void
*
DOSVM_GetSystemData
(
int
id
)
{
return
NULL
;
}
void
DOSVM_QueueEvent
(
int
irq
,
int
priority
,
void
(
*
relay
)(
LPDOSTASK
,
CONTEXT86
*
,
void
*
),
void
*
data
)
void
DOSVM_QueueEvent
(
int
irq
,
int
priority
,
void
(
*
relay
)(
CONTEXT86
*
,
void
*
),
void
*
data
)
{
if
(
irq
<
0
)
{
/* callback event, perform it with dummy context */
CONTEXT86
context
;
memset
(
&
context
,
0
,
sizeof
(
context
));
(
*
relay
)(
NULL
,
&
context
,
data
);
(
*
relay
)(
&
context
,
data
);
}
else
{
ERR_
(
int
)(
"IRQ without DOS task: should not happen"
);
}
...
...
loader/dos/module.c
View file @
770eb51e
...
...
@@ -37,6 +37,8 @@
DEFAULT_DEBUG_CHANNEL
(
module
);
static
LPDOSTASK
dos_current
;
#ifdef MZ_SUPPORTED
#ifdef HAVE_SYS_MMAN_H
...
...
@@ -48,15 +50,21 @@ DEFAULT_DEBUG_CHANNEL(module);
#undef MZ_MAPSELF
#define BIOS_DATA_SEGMENT 0x40
#define START_OFFSET 0
#define PSP_SIZE 0x10
#define SEG16(ptr,seg) ((LPVOID)((BYTE*)ptr+((DWORD)(seg)<<4)))
#define SEGPTR16(ptr,segptr) ((LPVOID)((BYTE*)ptr+((DWORD)SELECTOROF(segptr)<<4)+OFFSETOF(segptr)))
static
LPDOSTASK
dos_current
;
static
WORD
init_cs
,
init_ip
,
init_ss
,
init_sp
;
static
char
mm_name
[
128
];
int
read_pipe
,
write_pipe
;
HANDLE
hReadPipe
,
hWritePipe
;
pid_t
dosmod_pid
;
static
void
MZ_Launch
(
void
);
static
BOOL
MZ_InitTask
(
void
);
static
void
MZ_KillTask
(
void
);
static
void
MZ_CreatePSP
(
LPVOID
lpPSP
,
WORD
env
)
{
...
...
@@ -107,68 +115,18 @@ static char int08[]={
0xCF
/* iret */
};
static
void
MZ_InitHandlers
(
LPDOSTASK
lpDosTask
)
static
void
MZ_InitHandlers
(
void
)
{
WORD
seg
;
LPBYTE
start
=
DOSMEM_GetBlock
(
sizeof
(
int08
),
&
seg
);
memcpy
(
start
,
int08
,
sizeof
(
int08
));
/* INT 08: point it at our tick-incrementing handler */
((
SEGPTR
*
)
(
lpDosTask
->
img
)
)[
0x08
]
=
PTR_SEG_OFF_TO_SEGPTR
(
seg
,
0
);
((
SEGPTR
*
)
0
)[
0x08
]
=
PTR_SEG_OFF_TO_SEGPTR
(
seg
,
0
);
/* INT 1C: just point it to IRET, we don't want to handle it ourselves */
((
SEGPTR
*
)
(
lpDosTask
->
img
)
)[
0x1C
]
=
PTR_SEG_OFF_TO_SEGPTR
(
seg
,
sizeof
(
int08
)
-
1
);
((
SEGPTR
*
)
0
)[
0x1C
]
=
PTR_SEG_OFF_TO_SEGPTR
(
seg
,
sizeof
(
int08
)
-
1
);
}
static
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
void
MZ_InitXMS
(
LPDOSTASK
lpDosTask
)
{
LPBYTE
start
=
DOSMEM_GetBlock
(
sizeof
(
enter_xms
),
&
(
lpDosTask
->
xms_seg
));
memcpy
(
start
,
enter_xms
,
sizeof
(
enter_xms
));
}
static
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 */
0xCB
/* lret */
};
static
void
MZ_InitDPMI
(
LPDOSTASK
lpDosTask
)
{
unsigned
size
=
sizeof
(
enter_pm
);
LPBYTE
start
=
DOSMEM_GetBlock
(
size
,
&
(
lpDosTask
->
dpmi_seg
));
lpDosTask
->
dpmi_sel
=
SELECTOR_AllocBlock
(
start
,
size
,
SEGMENT_CODE
,
FALSE
,
FALSE
);
memcpy
(
start
,
enter_pm
,
sizeof
(
enter_pm
));
}
static
WORD
MZ_InitEnvironment
(
LPDOSTASK
lpDosTask
,
LPCSTR
env
,
LPCSTR
name
)
static
WORD
MZ_InitEnvironment
(
LPCSTR
env
,
LPCSTR
name
)
{
unsigned
sz
=
0
;
WORD
seg
;
...
...
@@ -191,39 +149,33 @@ static WORD MZ_InitEnvironment( LPDOSTASK lpDosTask, LPCSTR env, LPCSTR name )
return
seg
;
}
static
BOOL
MZ_InitMemory
(
LPDOSTASK
lpDosTask
)
static
BOOL
MZ_InitMemory
(
void
)
{
if
(
lpDosTask
->
img
)
return
TRUE
;
/* already allocated */
/* allocate 1MB+64K shared memory */
lpDosTask
->
img_ofs
=
START_OFFSET
;
#ifdef MZ_MAPSELF
lpDosTask
->
img
=
VirtualAlloc
(
NULL
,
0x110000
,
MEM_COMMIT
,
PAGE_READWRITE
);
/* make sure mmap accepts it */
((
char
*
)
lpDosTask
->
img
)[
0x10FFFF
]
=
0
;
#else
tmpnam
(
lpDosTask
->
mm_name
);
/* strcpy(lpDosTask->mm_name,"/tmp/mydosimage"); */
lpDosTask
->
mm_fd
=
open
(
lpDosTask
->
mm_name
,
O_RDWR
|
O_CREAT
/* |O_TRUNC */
,
S_IRUSR
|
S_IWUSR
);
if
(
lpDosTask
->
mm_fd
<
0
)
ERR
(
"file %s could not be opened
\n
"
,
lpDosTask
->
mm_name
);
/* expand file to 1MB+64K */
ftruncate
(
lpDosTask
->
mm_fd
,
0x110000
);
/* map it in */
lpDosTask
->
img
=
mmap
(
NULL
,
0x110000
-
START_OFFSET
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
lpDosTask
->
mm_fd
,
0
);
#endif
if
(
lpDosTask
->
img
==
(
LPVOID
)
-
1
)
{
ERR
(
"could not map shared memory, error=%s
\n
"
,
strerror
(
errno
));
return
FALSE
;
}
TRACE
(
"DOS VM86 image mapped at %08lx
\n
"
,(
DWORD
)
lpDosTask
->
img
);
/* initialize the memory */
TRACE
(
"Initializing DOS memory structures
\n
"
);
DOSMEM_Init
(
TRUE
);
MZ_InitHandlers
(
lpDosTask
);
MZ_InitXMS
(
lpDosTask
);
MZ_InitDPMI
(
lpDosTask
);
return
TRUE
;
int
mm_fd
;
void
*
img_base
;
/* initialize the memory */
TRACE
(
"Initializing DOS memory structures
\n
"
);
DOSMEM_Init
(
TRUE
);
/* allocate 1MB+64K shared memory */
tmpnam
(
mm_name
);
/* strcpy(mm_name,"/tmp/mydosimage"); */
mm_fd
=
open
(
mm_name
,
O_RDWR
|
O_CREAT
/* |O_TRUNC */
,
S_IRUSR
|
S_IWUSR
);
if
(
mm_fd
<
0
)
ERR
(
"file %s could not be opened
\n
"
,
mm_name
);
/* fill the file with the DOS memory */
if
(
write
(
mm_fd
,
NULL
,
0x110000
)
!=
0x110000
)
ERR
(
"cannot write DOS mem
\n
"
);
/* map it in */
img_base
=
mmap
(
NULL
,
0x110000
,
PROT_READ
|
PROT_WRITE
|
PROT_EXEC
,
MAP_SHARED
|
MAP_FIXED
,
mm_fd
,
0
);
close
(
mm_fd
);
if
(
img_base
)
{
ERR
(
"could not map shared memory, error=%s
\n
"
,
strerror
(
errno
));
return
FALSE
;
}
MZ_InitHandlers
();
return
TRUE
;
}
BOOL
MZ_LoadImage
(
HMODULE
module
,
HANDLE
hFile
,
LPCSTR
filename
)
...
...
@@ -235,7 +187,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
BYTE
*
psp_start
,
*
load_start
;
int
x
,
old_com
=
0
,
alloc
=
0
;
SEGPTR
reloc
;
WORD
env_seg
;
WORD
env_seg
,
load_seg
;
DWORD
len
;
win_hdr
->
OptionalHeader
.
Subsystem
=
IMAGE_SUBSYSTEM_WINDOWS_CUI
;
...
...
@@ -244,7 +196,6 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
if
(
!
lpDosTask
)
{
alloc
=
1
;
lpDosTask
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
DOSTASK
));
lpDosTask
->
mm_fd
=
-
1
;
dos_current
=
lpDosTask
;
}
...
...
@@ -269,10 +220,10 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
max_size
=
image_size
+
((
DWORD
)
mz_header
.
e_maxalloc
<<
4
)
+
(
PSP_SIZE
<<
4
);
}
MZ_InitMemory
(
lpDosTask
);
MZ_InitMemory
();
/* allocate environment block */
env_seg
=
MZ_InitEnvironment
(
lpDosTask
,
GetEnvironmentStringsA
(),
filename
);
env_seg
=
MZ_InitEnvironment
(
GetEnvironmentStringsA
(),
filename
);
/* allocate memory for the executable */
TRACE
(
"Allocating DOS memory (min=%ld, max=%ld)
\n
"
,
min_size
,
max_size
);
...
...
@@ -289,7 +240,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
load_error
;
}
l
pDosTask
->
l
oad_seg
=
lpDosTask
->
psp_seg
+
(
old_com
?
0
:
PSP_SIZE
);
load_seg
=
lpDosTask
->
psp_seg
+
(
old_com
?
0
:
PSP_SIZE
);
load_start
=
psp_start
+
(
PSP_SIZE
<<
4
);
MZ_CreatePSP
(
psp_start
,
env_seg
);
...
...
@@ -311,19 +262,19 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
SetLastError
(
ERROR_BAD_FORMAT
);
goto
load_error
;
}
*
(
WORD
*
)
SEGPTR16
(
load_start
,
reloc
)
+=
l
pDosTask
->
l
oad_seg
;
*
(
WORD
*
)
SEGPTR16
(
load_start
,
reloc
)
+=
load_seg
;
}
}
lpDosTask
->
init_cs
=
lpDosTask
->
load_seg
+
mz_header
.
e_cs
;
lpDosTask
->
init_ip
=
mz_header
.
e_ip
;
lpDosTask
->
init_ss
=
lpDosTask
->
load_seg
+
mz_header
.
e_ss
;
lpDosTask
->
init_sp
=
mz_header
.
e_sp
;
init_cs
=
load_seg
+
mz_header
.
e_cs
;
init_ip
=
mz_header
.
e_ip
;
init_ss
=
load_seg
+
mz_header
.
e_ss
;
init_sp
=
mz_header
.
e_sp
;
TRACE
(
"entry point: %04x:%04x
\n
"
,
lpDosTask
->
init_cs
,
lpDosTask
->
init_ip
);
TRACE
(
"entry point: %04x:%04x
\n
"
,
init_cs
,
init_ip
);
if
(
!
MZ_InitTask
(
lpDosTask
))
{
MZ_KillTask
(
lpDosTask
);
if
(
!
MZ_InitTask
())
{
MZ_KillTask
();
SetLastError
(
ERROR_GEN_FAILURE
);
return
FALSE
;
}
...
...
@@ -333,12 +284,7 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
load_error:
if
(
alloc
)
{
dos_current
=
NULL
;
if
(
lpDosTask
->
mm_name
[
0
]
!=
0
)
{
if
(
lpDosTask
->
img
!=
NULL
)
munmap
(
lpDosTask
->
img
,
0x110000
-
START_OFFSET
);
if
(
lpDosTask
->
mm_fd
>=
0
)
close
(
lpDosTask
->
mm_fd
);
unlink
(
lpDosTask
->
mm_name
);
}
else
if
(
lpDosTask
->
img
!=
NULL
)
VirtualFree
(
lpDosTask
->
img
,
0x110000
,
MEM_RELEASE
);
if
(
mm_name
[
0
]
!=
0
)
unlink
(
mm_name
);
}
return
FALSE
;
...
...
@@ -349,14 +295,14 @@ LPDOSTASK MZ_AllocDPMITask( void )
LPDOSTASK
lpDosTask
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
DOSTASK
));
if
(
lpDosTask
)
{
lpDosTask
->
mm_fd
=
-
1
;
dos_current
=
lpDosTask
;
MZ_InitMemory
(
lpDosTask
);
MZ_InitMemory
();
MZ_InitTask
();
}
return
lpDosTask
;
}
static
void
MZ_InitTimer
(
LPDOSTASK
lpDosTask
,
int
ver
)
static
void
MZ_InitTimer
(
int
ver
)
{
if
(
ver
<
1
)
{
/* can't make timer ticks */
...
...
@@ -367,55 +313,42 @@ static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver )
/* start dosmod timer at 55ms (18.2Hz) */
func
=
DOSMOD_SET_TIMER
;
tim
.
tv_sec
=
0
;
tim
.
tv_usec
=
54925
;
write
(
lpDosTask
->
write_pipe
,
&
func
,
sizeof
(
func
));
write
(
lpDosTask
->
write_pipe
,
&
tim
,
sizeof
(
tim
));
write
(
write_pipe
,
&
func
,
sizeof
(
func
));
write
(
write_pipe
,
&
tim
,
sizeof
(
tim
));
}
}
BOOL
MZ_InitTask
(
LPDOSTASK
lpDosTask
)
static
BOOL
MZ_InitTask
(
void
)
{
int
write_fd
[
2
],
x_fd
;
pid_t
child
;
char
*
fname
,
*
farg
,
arg
[
16
],
fproc
[
64
],
path
[
256
],
*
fpath
;
char
path
[
256
],
*
fpath
;
if
(
!
lpDosTask
)
return
FALSE
;
/* create pipes */
if
(
!
CreatePipe
(
&
(
lpDosTask
->
hReadPipe
),
&
(
lpDosTask
->
hXPipe
)
,
NULL
,
0
))
return
FALSE
;
if
(
!
CreatePipe
(
&
hReadPipe
,
&
hWritePipe
,
NULL
,
0
))
return
FALSE
;
if
(
pipe
(
write_fd
)
<
0
)
{
CloseHandle
(
lpDosTask
->
hReadPipe
);
CloseHandle
(
lpDosTask
->
hX
Pipe
);
CloseHandle
(
hReadPipe
);
CloseHandle
(
hWrite
Pipe
);
return
FALSE
;
}
lpDosTask
->
read_pipe
=
FILE_GetUnixHandle
(
lpDosTask
->
hReadPipe
,
GENERIC_READ
);
x_fd
=
FILE_GetUnixHandle
(
lpDosTask
->
hX
Pipe
,
GENERIC_WRITE
);
read_pipe
=
FILE_GetUnixHandle
(
hReadPipe
,
GENERIC_READ
);
x_fd
=
FILE_GetUnixHandle
(
hWrite
Pipe
,
GENERIC_WRITE
);
TRACE
(
"win32 pipe: read=%d, write=%d, unix pipe: read=%d, write=%d
\n
"
,
lpDosTask
->
hReadPipe
,
lpDosTask
->
hXPipe
,
lpDosTask
->
read_pipe
,
x_fd
);
hReadPipe
,
hWritePipe
,
read_pipe
,
x_fd
);
TRACE
(
"outbound unix pipe: read=%d, write=%d, pid=%d
\n
"
,
write_fd
[
0
],
write_fd
[
1
],
getpid
());
lpDosTask
->
write_pipe
=
write_fd
[
1
];
lpDosTask
->
hConInput
=
GetStdHandle
(
STD_INPUT_HANDLE
);
lpDosTask
->
hConOutput
=
GetStdHandle
(
STD_OUTPUT_HANDLE
);
/* if we have a mapping file, use it */
fname
=
lpDosTask
->
mm_name
;
farg
=
NULL
;
if
(
!
fname
[
0
])
{
/* otherwise, map our own memory image */
sprintf
(
fproc
,
"/proc/%d/mem"
,
getpid
());
sprintf
(
arg
,
"%ld"
,(
unsigned
long
)
lpDosTask
->
img
);
fname
=
fproc
;
farg
=
arg
;
}
write_pipe
=
write_fd
[
1
];
TRACE
(
"Loading DOS VM support module
\n
"
);
if
((
child
=
fork
())
<
0
)
{
close
(
write_fd
[
0
]);
close
(
lpDosTask
->
read_pipe
);
close
(
lpDosTask
->
write_pipe
);
close
(
read_pipe
);
close
(
write_pipe
);
close
(
x_fd
);
CloseHandle
(
lpDosTask
->
hReadPipe
);
CloseHandle
(
lpDosTask
->
hX
Pipe
);
CloseHandle
(
hReadPipe
);
CloseHandle
(
hWrite
Pipe
);
return
FALSE
;
}
if
(
child
!=
0
)
{
...
...
@@ -424,21 +357,21 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask )
close
(
write_fd
[
0
]);
close
(
x_fd
);
lpDosTask
->
task
=
child
;
dosmod_pid
=
child
;
/* wait for child process to signal readiness */
while
(
1
)
{
if
(
read
(
lpDosTask
->
read_pipe
,
&
ret
,
sizeof
(
ret
))
==
sizeof
(
ret
))
break
;
if
(
read
(
read_pipe
,
&
ret
,
sizeof
(
ret
))
==
sizeof
(
ret
))
break
;
if
((
errno
==
EINTR
)
||
(
errno
==
EAGAIN
))
continue
;
/* failure */
ERR
(
"dosmod has failed to initialize
\n
"
);
if
(
lpDosTask
->
mm_name
[
0
]
!=
0
)
unlink
(
lpDosTask
->
mm_name
);
if
(
mm_name
[
0
]
!=
0
)
unlink
(
mm_name
);
return
FALSE
;
}
/* the child has now mmaped the temp file, it's now safe to unlink.
* do it here to avoid leaving a mess in /tmp if/when Wine crashes... */
if
(
lpDosTask
->
mm_name
[
0
]
!=
0
)
unlink
(
lpDosTask
->
mm_name
);
if
(
mm_name
[
0
]
!=
0
)
unlink
(
mm_name
);
/* start simulated system timer */
MZ_InitTimer
(
lpDosTask
,
ret
);
MZ_InitTimer
(
ret
);
if
(
ret
<
2
)
{
ERR
(
"dosmod version too old! Please install newer dosmod properly
\n
"
);
ERR
(
"If you don't, the new dosmod event handling system will not work
\n
"
);
...
...
@@ -446,8 +379,8 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask )
/* all systems are now go */
}
else
{
/* child process */
close
(
lpDosTask
->
read_pipe
);
close
(
lpDosTask
->
write_pipe
);
close
(
read_pipe
);
close
(
write_pipe
);
/* put our pipes somewhere dosmod can find them */
dup2
(
write_fd
[
0
],
0
);
/* stdin */
dup2
(
x_fd
,
1
);
/* stdout */
...
...
@@ -457,16 +390,16 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask )
fpath
=
strrchr
(
strcpy
(
path
,
full_argv0
),
'/'
);
if
(
fpath
)
{
strcpy
(
fpath
,
"/dosmod"
);
execl
(
path
,
fname
,
farg
,
NULL
);
execl
(
path
,
mm_name
,
NULL
);
strcpy
(
fpath
,
"/loader/dos/dosmod"
);
execl
(
path
,
fname
,
farg
,
NULL
);
execl
(
path
,
mm_name
,
NULL
);
}
/* okay, it wasn't there, try in the path */
execlp
(
"dosmod"
,
fname
,
farg
,
NULL
);
execlp
(
"dosmod"
,
mm_name
,
NULL
);
/* last desperate attempts: current directory */
execl
(
"dosmod"
,
fname
,
farg
,
NULL
);
execl
(
"dosmod"
,
mm_name
,
NULL
);
/* and, just for completeness... */
execl
(
"loader/dos/dosmod"
,
fname
,
farg
,
NULL
);
execl
(
"loader/dos/dosmod"
,
mm_name
,
NULL
);
/* if failure, exit */
ERR
(
"Failed to spawn dosmod, error=%s
\n
"
,
strerror
(
errno
));
exit
(
1
);
...
...
@@ -477,53 +410,29 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask )
static
void
MZ_Launch
(
void
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
BYTE
*
psp_start
=
(
BYTE
*
)
lpDosTask
->
img
+
((
DWORD
)
lpDosTask
->
psp_seg
<<
4
);
CONTEXT
context
;
TDB
*
pTask
=
(
TDB
*
)
GlobalLock16
(
GetCurrentTask
()
);
BYTE
*
psp_start
=
PTR_REAL_TO_LIN
(
lpDosTask
->
psp_seg
,
0
);
MZ_FillPSP
(
psp_start
,
GetCommandLineA
());
DOSVM_Enter
(
NULL
);
pTask
->
flags
|=
TDBF_WINOLDAP
;
memset
(
&
context
,
0
,
sizeof
(
context
)
);
context
.
SegCs
=
init_cs
;
context
.
Eip
=
init_ip
;
context
.
SegSs
=
init_ss
;
context
.
Esp
=
init_sp
;
context
.
SegDs
=
lpDosTask
->
psp_seg
;
context
.
SegEs
=
lpDosTask
->
psp_seg
;
context
.
EFlags
=
0x00080000
;
/* virtual interrupt flag */
DOSVM_Enter
(
&
context
);
}
void
MZ_KillTask
(
LPDOSTASK
lpDosTask
)
static
void
MZ_KillTask
(
void
)
{
DOSEVENT
*
event
,
*
p_event
;
DOSSYSTEM
*
sys
,
*
p_sys
;
TRACE
(
"killing DOS task
\n
"
);
VGA_Clean
();
if
(
lpDosTask
->
mm_name
[
0
]
!=
0
)
{
munmap
(
lpDosTask
->
img
,
0x110000
-
START_OFFSET
);
close
(
lpDosTask
->
mm_fd
);
}
else
VirtualFree
(
lpDosTask
->
img
,
0x110000
,
MEM_RELEASE
);
close
(
lpDosTask
->
read_pipe
);
close
(
lpDosTask
->
write_pipe
);
CloseHandle
(
lpDosTask
->
hReadPipe
);
CloseHandle
(
lpDosTask
->
hXPipe
);
kill
(
lpDosTask
->
task
,
SIGTERM
);
/* free memory allocated for events and systems */
#define DFREE(var,pvar,svar) \
var = lpDosTask->svar; \
while (var) { \
if (var->data) free(var->data); \
pvar = var->next; free(var); var = pvar; \
}
DFREE
(
event
,
p_event
,
pending
)
DFREE
(
event
,
p_event
,
current
)
DFREE
(
sys
,
p_sys
,
sys
)
#undef DFREE
#if 0
/* FIXME: this seems to crash */
if (lpDosTask->dpmi_sel)
SELECTOR_FreeBlock(lpDosTask->dpmi_sel, 1);
#endif
}
LPDOSTASK
MZ_Current
(
void
)
{
return
dos_current
;
kill
(
dosmod_pid
,
SIGTERM
);
}
#else
/* !MZ_SUPPORTED */
...
...
@@ -535,9 +444,15 @@ BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
return
FALSE
;
}
LPDOSTASK
MZ_
Current
(
void
)
LPDOSTASK
MZ_
AllocDPMITask
(
void
)
{
return
NULL
;
ERR
(
"Actual real-mode calls not supported on this architecture!
\n
"
);
return
NULL
;
}
#endif
#endif
/* !MZ_SUPPORTED */
LPDOSTASK
MZ_Current
(
void
)
{
return
dos_current
;
}
loader/task.c
View file @
770eb51e
...
...
@@ -29,13 +29,13 @@
#include "winsock.h"
#include "syslevel.h"
#include "debugtools.h"
#include "dosexe.h"
#include "services.h"
#include "server.h"
DEFAULT_DEBUG_CHANNEL
(
task
)
DECLARE_DEBUG_CHANNEL
(
relay
)
DECLARE_DEBUG_CHANNEL
(
toolhelp
)
DEFAULT_DEBUG_CHANNEL
(
task
);
DECLARE_DEBUG_CHANNEL
(
relay
);
DECLARE_DEBUG_CHANNEL
(
toolhelp
);
/* Min. number of thunks allocated when creating a new segment */
#define MIN_THUNKS 32
...
...
@@ -243,7 +243,6 @@ BOOL TASK_Create( NE_MODULE *pModule, UINT16 cmdShow, TEB *teb, LPCSTR cmdline,
/* NOTE: for 16-bit tasks, the instance handles are updated later on
in NE_InitProcess */
}
if
(
MZ_Current
()
&&
MZ_Current
()
->
load_seg
)
pTask
->
flags
|=
TDBF_WINOLDAP
;
pTask
->
version
=
pModule
->
expected_version
;
pTask
->
hModule
=
pModule
->
self
;
...
...
memory/instr.c
View file @
770eb51e
...
...
@@ -29,7 +29,7 @@ inline static void add_stack( CONTEXT86 *context, int offset )
inline
static
void
*
make_ptr
(
CONTEXT86
*
context
,
DWORD
seg
,
DWORD
off
,
int
long_addr
)
{
if
(
ISV86
(
context
))
return
DOSMEM_MemoryBase
()
+
(
seg
<<
4
)
+
LOWORD
(
off
);
if
(
ISV86
(
context
))
return
PTR_REAL_TO_LIN
(
seg
,
off
);
if
(
IS_SELECTOR_SYSTEM
(
seg
))
return
(
void
*
)
off
;
if
(
!
long_addr
)
off
=
LOWORD
(
off
);
return
PTR_SEG_OFF_TO_LIN
(
seg
,
off
);
...
...
@@ -38,7 +38,7 @@ inline static void *make_ptr( CONTEXT86 *context, DWORD seg, DWORD off, int long
inline
static
void
*
get_stack
(
CONTEXT86
*
context
)
{
if
(
ISV86
(
context
))
return
DOSMEM_MemoryBase
()
+
(
context
->
SegSs
<<
4
)
+
LOWORD
(
context
->
Esp
);
return
PTR_REAL_TO_LIN
(
context
->
SegSs
,
context
->
Esp
);
if
(
IS_SELECTOR_SYSTEM
(
context
->
SegSs
))
return
(
void
*
)
context
->
Esp
;
if
(
IS_SELECTOR_32BIT
(
context
->
SegSs
))
...
...
msdos/devices.c
View file @
770eb51e
...
...
@@ -47,8 +47,9 @@ typedef struct {
#define CON_BUFFER 128
#define SYSTEM_STRATEGY_NUL 0x0100
#define SYSTEM_STRATEGY_CON 0x0101
enum
strategy
{
SYSTEM_STRATEGY_NUL
,
SYSTEM_STRATEGY_CON
,
NB_SYSTEM_STRATEGIES
};
static
void
*
strategy_data
[
NB_SYSTEM_STRATEGIES
];
#define NONEXT ((DWORD)-1)
...
...
@@ -150,20 +151,19 @@ static void do_lret(CONTEXT86*ctx)
static
void
do_strategy
(
CONTEXT86
*
ctx
,
int
id
,
int
extra
)
{
REQUEST_HEADER
*
hdr
=
CTX_SEG_OFF_TO_LIN
(
ctx
,
ES_reg
(
ctx
),
EBX_reg
(
ctx
));
void
**
hdr_ptr
=
DOSVM_GetSystemData
(
id
)
;
void
**
hdr_ptr
=
strategy_data
[
id
]
;
if
(
!
hdr_ptr
)
{
hdr_ptr
=
calloc
(
1
,
sizeof
(
void
*
)
+
extra
);
DOSVM_SetSystemData
(
id
,
hdr_ptr
)
;
strategy_data
[
id
]
=
hdr_ptr
;
}
*
hdr_ptr
=
hdr
;
do_lret
(
ctx
);
}
static
REQUEST_HEADER
*
get_hdr
(
int
id
,
void
**
extra
)
{
void
**
hdr_ptr
=
DOSVM_GetSystemData
(
id
)
;
void
**
hdr_ptr
=
strategy_data
[
id
]
;
if
(
extra
)
*
extra
=
hdr_ptr
?
(
void
*
)(
hdr_ptr
+
1
)
:
(
void
*
)
NULL
;
return
hdr_ptr
?
*
hdr_ptr
:
(
void
*
)
NULL
;
...
...
@@ -209,7 +209,6 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
BYTE
*
curbuffer
=
(
lol
->
offs_unread_CON
)
?
(((
BYTE
*
)
dataseg
)
+
lol
->
offs_unread_CON
)
:
(
BYTE
*
)
NULL
;
DOS_DEVICE_HEADER
*
con
=
dataseg
->
dev
;
LPDOSTASK
lpDosTask
=
MZ_Current
();
switch
(
hdr
->
command
)
{
case
CMD_INPUT
:
...
...
@@ -301,7 +300,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
/* a character */
if
((
len
+
1
)
<
CON_BUFFER
)
{
linebuffer
[
len
]
=
LOBYTE
(
data
);
WriteFile
(
lpDosTask
->
hConOutput
,
&
linebuffer
[
len
++
],
1
,
NULL
,
NULL
);
WriteFile
(
GetStdHandle
(
STD_OUTPUT_HANDLE
)
,
&
linebuffer
[
len
++
],
1
,
NULL
,
NULL
);
}
/* else beep, but I don't like noise */
}
...
...
@@ -309,7 +308,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
case
'\b'
:
if
(
len
>
0
)
{
len
--
;
WriteFile
(
lpDosTask
->
hConOutput
,
"
\b
\b
"
,
3
,
NULL
,
NULL
);
WriteFile
(
GetStdHandle
(
STD_OUTPUT_HANDLE
)
,
"
\b
\b
"
,
3
,
NULL
,
NULL
);
}
break
;
}
...
...
@@ -377,7 +376,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
SELECTOROF
(
io
->
buffer
),
(
DWORD
)
OFFSETOF
(
io
->
buffer
));
DWORD
result
=
0
;
WriteFile
(
lpDosTask
->
hConOutput
,
buffer
,
io
->
count
,
&
result
,
NULL
);
WriteFile
(
GetStdHandle
(
STD_OUTPUT_HANDLE
)
,
buffer
,
io
->
count
,
&
result
,
NULL
);
io
->
count
=
result
;
hdr
->
status
=
STAT_DONE
;
}
...
...
msdos/dosmem.c
View file @
770eb51e
...
...
@@ -5,30 +5,33 @@
* Copyright 1996 Marcus Meissner
*/
#include "config.h"
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#include "winbase.h"
#include "wine/winbase16.h"
#include "global.h"
#include "ldt.h"
#include "selectors.h"
#include "miscemu.h"
#include "vga.h"
#include "dosexe.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL
(
dosmem
)
DECLARE_DEBUG_CHANNEL
(
selector
)
DEFAULT_DEBUG_CHANNEL
(
dosmem
)
;
DECLARE_DEBUG_CHANNEL
(
selector
)
;
HANDLE16
DOSMEM_BiosDataSeg
;
/* BIOS data segment at 0x40:0 */
HANDLE16
DOSMEM_BiosSysSeg
;
/* BIOS ROM segment at 0xf000:0 */
static
char
*
DOSMEM_dosmem
;
DWORD
DOSMEM_CollateTable
;
DWORD
DOSMEM_ErrorCall
;
DWORD
DOSMEM_ErrorBuffer
;
DWORD
DOSMEM_CollateTable
;
/* use 2 low bits of 'size' for the housekeeping */
...
...
@@ -57,6 +60,17 @@ typedef struct {
#define VM_STUB(x) (0x90CF00CD|(x<<8))
/* INT x; IRET; NOP */
#define VM_STUB_SEGMENT 0xf000
/* BIOS segment */
/* DOS memory base */
static
char
*
DOSMEM_dosmem
;
/* bios area; normally at offset 0x400, but can be moved to trap NULL pointers */
static
void
*
DOSMEM_biosdata
;
/* various real-mode code stubs */
WORD
DOSMEM_wrap_seg
;
WORD
DOSMEM_xms_seg
;
WORD
DOSMEM_dpmi_seg
;
WORD
DOSMEM_dpmi_sel
;
/***********************************************************************
* DOSMEM_MemoryBase
*
...
...
@@ -64,12 +78,7 @@ typedef struct {
*/
char
*
DOSMEM_MemoryBase
(
void
)
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
if
(
lpDosTask
&&
lpDosTask
->
img
)
return
lpDosTask
->
img
;
else
return
DOSMEM_dosmem
;
return
DOSMEM_dosmem
;
}
/***********************************************************************
...
...
@@ -79,7 +88,7 @@ char *DOSMEM_MemoryBase(void)
*/
static
char
*
DOSMEM_MemoryTop
(
void
)
{
return
DOSMEM_
MemoryBase
()
+
0x9FFFC
;
/* 640K */
return
DOSMEM_
dosmem
+
0x9FFFC
;
/* 640K */
}
/***********************************************************************
...
...
@@ -89,7 +98,7 @@ static char *DOSMEM_MemoryTop(void)
*/
static
dosmem_info
*
DOSMEM_InfoBlock
(
void
)
{
return
(
dosmem_info
*
)(
DOSMEM_
MemoryBase
()
+
0x10000
);
/* 64K */
return
(
dosmem_info
*
)(
DOSMEM_
dosmem
+
0x10000
);
/* 64K */
}
/***********************************************************************
...
...
@@ -118,7 +127,7 @@ static dosmem_entry *DOSMEM_RootBlock(void)
*/
static
void
DOSMEM_FillIsrTable
(
void
)
{
SEGPTR
*
isr
=
(
SEGPTR
*
)
DOSMEM_
MemoryBase
()
;
SEGPTR
*
isr
=
(
SEGPTR
*
)
DOSMEM_
dosmem
;
DWORD
*
stub
=
(
DWORD
*
)((
char
*
)
isr
+
(
VM_STUB_SEGMENT
<<
4
));
int
x
;
...
...
@@ -133,24 +142,66 @@ static void DOSMEM_FillIsrTable(void)
*/
static
void
DOSMEM_InitDPMI
(
void
)
{
extern
UINT16
DPMI_wrap_seg
;
static
char
wrap_code
[]
=
{
LPSTR
ptr
;
static
const
char
wrap_code
[]
=
{
0xCD
,
0x31
,
/* int $0x31 */
0xCB
/* lret */
};
LPSTR
wrapper
=
(
LPSTR
)
DOSMEM_GetBlock
(
sizeof
(
wrap_code
),
&
DPMI_wrap_seg
);
memcpy
(
wrapper
,
wrap_code
,
sizeof
(
wrap_code
));
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 */
0xCB
/* lret */
};
ptr
=
DOSMEM_GetBlock
(
sizeof
(
wrap_code
),
&
DOSMEM_wrap_seg
);
memcpy
(
ptr
,
wrap_code
,
sizeof
(
wrap_code
)
);
ptr
=
DOSMEM_GetBlock
(
sizeof
(
enter_xms
),
&
DOSMEM_xms_seg
);
memcpy
(
ptr
,
enter_xms
,
sizeof
(
enter_xms
)
);
ptr
=
DOSMEM_GetBlock
(
sizeof
(
enter_pm
),
&
DOSMEM_dpmi_seg
);
memcpy
(
ptr
,
enter_pm
,
sizeof
(
enter_pm
)
);
DOSMEM_dpmi_sel
=
SELECTOR_AllocBlock
(
ptr
,
sizeof
(
enter_pm
),
SEGMENT_CODE
,
FALSE
,
FALSE
);
}
BIOSDATA
*
DOSMEM_BiosData
()
{
return
(
BIOSDATA
*
)
(
DOSMEM_MemoryBase
()
+
0x400
)
;
return
(
BIOSDATA
*
)
DOSMEM_biosdata
;
}
BYTE
*
DOSMEM_BiosSys
()
{
return
DOSMEM_
MemoryBase
()
+
0xf0000
;
return
DOSMEM_
dosmem
+
0xf0000
;
}
struct
_DOS_LISTOFLISTS
*
DOSMEM_LOL
()
...
...
@@ -293,6 +344,7 @@ static void DOSMEM_InitCollateTable()
*/
static
void
DOSMEM_InitErrorTable
()
{
#if 0 /* no longer used */
DWORD x;
char *call;
...
...
@@ -336,7 +388,7 @@ static void DOSMEM_InitErrorTable()
call = DOSMEM_MapRealToLinear(DOSMEM_ErrorCall);
memset(call, 0, SIZE_TO_ALLOCATE);
#endif
/* Fixme - Copy assembly into buffer here */
}
...
...
@@ -368,28 +420,56 @@ static void DOSMEM_InitMemory(void)
;
}
/**********************************************************************
*
*
DOSMEM_MovePointers
/**********************************************************************
*
setup_dos_mem
*
*
Relocates any pointers into DOS memory to a new address space.
*
Setup the first megabyte for DOS memory access
*/
static
void
DOSMEM_MovePointers
(
LPVOID
dest
,
LPVOID
src
,
DWORD
size
)
static
void
setup_dos_mem
(
int
dos_init
)
{
unsigned
long
delta
=
(
char
*
)
dest
-
(
char
*
)
src
;
unsigned
cnt
;
ldt_entry
ent
;
/* relocate base addresses of any selectors pointing into memory */
for
(
cnt
=
FIRST_LDT_ENTRY_TO_ALLOC
;
cnt
<
LDT_SIZE
;
cnt
++
)
{
LDT_GetEntry
(
cnt
,
&
ent
);
if
((
ent
.
base
>=
(
unsigned
long
)
src
)
&&
\
(
ent
.
base
<
((
unsigned
long
)
src
+
size
)))
{
ent
.
base
+=
delta
;
LDT_SetEntry
(
cnt
,
&
ent
);
int
bios_offset
=
0x400
;
int
page_size
=
VIRTUAL_GetPageSize
();
void
*
addr
=
VIRTUAL_mmap
(
-
1
,
(
void
*
)
page_size
,
0x110000
-
page_size
,
0
,
PROT_READ
|
PROT_WRITE
|
PROT_EXEC
,
0
);
if
(
addr
==
(
void
*
)
page_size
)
/* we got what we wanted */
{
/* now map from address 0 */
addr
=
VIRTUAL_mmap
(
-
1
,
NULL
,
0x110000
,
0
,
PROT_READ
|
PROT_WRITE
|
PROT_EXEC
,
MAP_FIXED
);
if
(
addr
)
{
ERR
(
"MAP_FIXED failed at address 0 for DOS address space
\n
"
);
ExitProcess
(
1
);
}
/* inform the memory manager that there is a mapping here */
VirtualAlloc
(
addr
,
0x110000
,
MEM_RESERVE
|
MEM_SYSTEM
,
PAGE_EXECUTE_READWRITE
);
/* protect the first 64K to catch NULL pointers */
if
(
!
dos_init
)
{
VirtualProtect
(
addr
,
0x10000
,
PAGE_NOACCESS
,
NULL
);
/* move the BIOS data from 0x400 to 0xf0400 */
bios_offset
+=
0xf0000
;
}
}
else
{
ERR
(
"Cannot use first megabyte for DOS address space, please report
\n
"
);
if
(
dos_init
)
ExitProcess
(
1
);
/* allocate the DOS area somewhere else */
addr
=
VirtualAlloc
(
NULL
,
0x110000
,
MEM_COMMIT
,
PAGE_EXECUTE_READWRITE
);
if
(
!
addr
)
{
ERR
(
"Cannot allocate DOS memory
\n
"
);
ExitProcess
(
1
);
}
}
}
DOSMEM_dosmem
=
addr
;
DOSMEM_biosdata
=
(
char
*
)
addr
+
bios_offset
;
}
/***********************************************************************
* DOSMEM_Init
*
...
...
@@ -398,44 +478,41 @@ static void DOSMEM_MovePointers(LPVOID dest, LPVOID src, DWORD size)
*/
BOOL
DOSMEM_Init
(
BOOL
dos_init
)
{
LPVOID
base
=
DOSMEM_MemoryBase
();
BOOL
do_init
=
dos_init
&&
!
DOSMEM_dosmem
;
static
int
already_done
;
if
(
!
bas
e
)
if
(
!
already_don
e
)
{
/* Allocate 1 MB dosmemory
*/
DOSMEM_dosmem
=
VirtualAlloc
(
NULL
,
0x100000
,
MEM_COMMIT
,
PAGE_EXECUTE_READWRITE
);
if
(
!
DOSMEM_dosmem
)
{
WARN
(
"Could not allocate DOS memory.
\n
"
);
return
FALSE
;
}
DOSMEM_BiosDataSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_dosmem
+
0x400
,
0x100
,
0
,
FALSE
,
FALSE
,
FALSE
);
DOSMEM_BiosSysSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_dosmem
+
0xf0000
,
0x10000
,
0
,
FALSE
,
FALSE
,
FALSE
);
base
=
DOSMEM_dosmem
;
do_init
=
TRUE
;
}
setup_dos_mem
(
dos_init
);
if
(
do_init
)
{
DOSMEM_FillIsrTable
();
DOSMEM_BiosDataSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_biosdata
,
0x100
,
0
,
FALSE
,
FALSE
,
FALSE
);
DOSMEM_BiosSysSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_dosmem
+
0xf0000
,
0x10000
,
0
,
FALSE
,
FALSE
,
FALSE
);
DOSMEM_FillBiosSegments
();
DOSMEM_InitMemory
();
DOSMEM_InitCollateTable
();
DOSMEM_InitErrorTable
();
DOSMEM_InitDPMI
();
DOSDEV_InstallDOSDevices
();
DOSDEV_InstallDOSDevices
();
already_done
=
1
;
}
else
if
(
dos_init
)
{
/* bootstrap the new V86 task with a copy of the "system" memory */
memcpy
(
base
,
DOSMEM_dosmem
,
0x100000
);
/* then move existing selectors to it */
DOSMEM_MovePointers
(
base
,
DOSMEM_dosmem
,
0x100000
);
if
(
DOSMEM_dosmem
)
{
ERR
(
"Needs access to the first megabyte for DOS mode
\n
"
);
ExitProcess
(
1
);
}
MESSAGE
(
"Warning: unprotecting the first 64KB of memory to allow real-mode calls.
\n
"
" NULL pointer accesses will no longer be caught.
\n
"
);
VirtualProtect
(
NULL
,
0x10000
,
PAGE_EXECUTE_READWRITE
,
NULL
);
/* copy the BIOS area down to 0x400 */
memcpy
(
DOSMEM_dosmem
+
0x400
,
DOSMEM_biosdata
,
0x100
);
DOSMEM_biosdata
=
DOSMEM_dosmem
+
0x400
;
SetSelectorBase
(
DOSMEM_BiosDataSeg
,
0x400
);
}
/* interrupt table is at addr 0, so only do this when setting up DOS mode */
if
(
dos_init
)
DOSMEM_FillIsrTable
();
return
TRUE
;
}
...
...
@@ -513,7 +590,7 @@ LPVOID DOSMEM_GetBlock(UINT size, UINT16* pseg)
info_block
->
blocks
++
;
info_block
->
free
-=
dm
->
size
;
if
(
pseg
)
*
pseg
=
(
block
-
DOSMEM_
MemoryBase
()
)
>>
4
;
if
(
pseg
)
*
pseg
=
(
block
-
DOSMEM_
dosmem
)
>>
4
;
#ifdef __DOSMEM_DEBUG__
dm
->
size
|=
DM_BLOCK_DEBUG
;
#endif
...
...
@@ -535,7 +612,7 @@ BOOL DOSMEM_FreeBlock(void* ptr)
if
(
ptr
>=
(
void
*
)(((
char
*
)
DOSMEM_RootBlock
())
+
sizeof
(
dosmem_entry
))
&&
ptr
<
(
void
*
)
DOSMEM_MemoryTop
()
&&
!
((((
char
*
)
ptr
)
-
DOSMEM_
MemoryBase
()
)
&
0xf
)
)
-
DOSMEM_
dosmem
)
&
0xf
)
)
{
dosmem_entry
*
dm
=
(
dosmem_entry
*
)(((
char
*
)
ptr
)
-
sizeof
(
dosmem_entry
));
...
...
@@ -565,11 +642,11 @@ LPVOID DOSMEM_ResizeBlock(void* ptr, UINT size, UINT16* pseg)
if
(
ptr
>=
(
void
*
)(((
char
*
)
DOSMEM_RootBlock
())
+
sizeof
(
dosmem_entry
))
&&
ptr
<
(
void
*
)
DOSMEM_MemoryTop
()
&&
!
((((
char
*
)
ptr
)
-
DOSMEM_
MemoryBase
()
)
&
0xf
)
)
-
DOSMEM_
dosmem
)
&
0xf
)
)
{
dosmem_entry
*
dm
=
(
dosmem_entry
*
)(((
char
*
)
ptr
)
-
sizeof
(
dosmem_entry
));
if
(
pseg
)
*
pseg
=
((
char
*
)
ptr
-
DOSMEM_
MemoryBase
()
)
>>
4
;
if
(
pseg
)
*
pseg
=
((
char
*
)
ptr
-
DOSMEM_
dosmem
)
>>
4
;
if
(
!
(
dm
->
size
&
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
))
)
...
...
@@ -689,9 +766,9 @@ UINT DOSMEM_Available(void)
*/
UINT
DOSMEM_MapLinearToDos
(
LPVOID
ptr
)
{
if
(((
char
*
)
ptr
>=
DOSMEM_
MemoryBase
()
)
&&
((
char
*
)
ptr
<
DOSMEM_
MemoryBase
()
+
0x100000
))
return
(
UINT
)
ptr
-
(
UINT
)
DOSMEM_
MemoryBase
()
;
if
(((
char
*
)
ptr
>=
DOSMEM_
dosmem
)
&&
((
char
*
)
ptr
<
DOSMEM_
dosmem
+
0x100000
))
return
(
UINT
)
ptr
-
(
UINT
)
DOSMEM_
dosmem
;
return
(
UINT
)
ptr
;
}
...
...
@@ -703,7 +780,7 @@ UINT DOSMEM_MapLinearToDos(LPVOID ptr)
*/
LPVOID
DOSMEM_MapDosToLinear
(
UINT
ptr
)
{
if
(
ptr
<
0x100000
)
return
(
LPVOID
)(
ptr
+
(
UINT
)
DOSMEM_
MemoryBase
()
);
if
(
ptr
<
0x100000
)
return
(
LPVOID
)(
ptr
+
(
UINT
)
DOSMEM_
dosmem
);
return
(
LPVOID
)
ptr
;
}
...
...
@@ -717,7 +794,7 @@ LPVOID DOSMEM_MapRealToLinear(DWORD x)
{
LPVOID
lin
;
lin
=
DOSMEM_
MemoryBase
()
+
(
x
&
0xffff
)
+
(((
x
&
0xffff0000
)
>>
16
)
*
16
);
lin
=
DOSMEM_
dosmem
+
(
x
&
0xffff
)
+
(((
x
&
0xffff0000
)
>>
16
)
*
16
);
TRACE_
(
selector
)(
"(0x%08lx) returns 0x%p.
\n
"
,
x
,
lin
);
return
lin
;
}
...
...
msdos/dpmi.c
View file @
770eb51e
...
...
@@ -62,7 +62,6 @@ typedef struct tagRMCB {
static
RMCB
*
FirstRMCB
=
NULL
;
UINT16
DPMI_wrap_seg
;
/**********************************************************************
* DPMI_xalloc
...
...
@@ -261,7 +260,7 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
DWORD
esp
,
edi
;
INT_SetRealModeContext
((
REALMODECALL
*
)
PTR_SEG_OFF_TO_LIN
(
rmcb
->
regs_sel
,
rmcb
->
regs_ofs
),
context
);
ss
=
SELECTOR_AllocBlock
(
DOSMEM_MemoryBase
()
+
(
DWORD
)(
SS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
ss
=
SELECTOR_AllocBlock
(
(
void
*
)(
SS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
esp
=
ESP_reg
(
context
);
FIXME
(
"untested!
\n
"
);
...
...
@@ -354,17 +353,12 @@ callrmproc_again:
CurrRMCB
=
CurrRMCB
->
next
;
if
(
!
(
CurrRMCB
||
lpDosTask
))
{
#ifdef MZ_SUPPORTED
FIXME
(
"DPMI real-mode call using DOS VM task system, not fully tested!
\n
"
);
TRACE
(
"creating VM86 task
\n
"
);
if
(
!
MZ_InitTask
(
lpDosTask
=
MZ_AllocDPMITask
()
))
{
if
(
!
(
lpDosTask
=
MZ_AllocDPMITask
()
))
{
ERR
(
"could not setup VM86 task
\n
"
);
return
1
;
}
#else
ERR
(
"Actual real-mode calls not supported on this architecture!
\n
"
);
return
1
;
#endif
}
if
(
!
already
)
{
if
(
!
SS_reg
(
context
))
{
...
...
@@ -388,7 +382,7 @@ callrmproc_again:
*
stack16
=
LOWORD
(
EFL_reg
(
context
));
}
/* push return address (return to interrupt wrapper) */
*
(
--
stack16
)
=
D
PMI
_wrap_seg
;
*
(
--
stack16
)
=
D
OSMEM
_wrap_seg
;
*
(
--
stack16
)
=
0
;
/* adjust stack */
ESP_reg
(
context
)
-=
2
*
sizeof
(
WORD
);
...
...
@@ -399,21 +393,16 @@ callrmproc_again:
/* RMCB call, invoke protected-mode handler directly */
DPMI_CallRMCBProc
(
context
,
CurrRMCB
,
lpDosTask
?
lpDosTask
->
dpmi_flag
:
0
);
/* check if we returned to where we thought we would */
if
((
CS_reg
(
context
)
!=
D
PMI
_wrap_seg
)
||
if
((
CS_reg
(
context
)
!=
D
OSMEM
_wrap_seg
)
||
(
LOWORD
(
EIP_reg
(
context
))
!=
0
))
{
/* we need to continue at different address in real-mode space,
so we need to set it all up for real mode again */
goto
callrmproc_again
;
}
}
else
{
#ifdef MZ_SUPPORTED
TRACE
(
"entering real mode...
\n
"
);
DOSVM_Enter
(
context
);
TRACE
(
"returned from real-mode call
\n
"
);
#else
/* we should never get here, but... */
ERR
(
"cannot perform real-mode call
\n
"
);
#endif
}
if
(
alloc
)
DOSMEM_FreeBlock
(
addr
);
return
0
;
...
...
@@ -585,16 +574,14 @@ void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc )
}
#ifdef MZ_SUPPORTED
/* (see loader/dos/module.c, function MZ_InitDPMI) */
/* (see dosmem.c, function DOSMEM_InitDPMI) */
static
void
StartPM
(
CONTEXT86
*
context
,
LPDOSTASK
lpDosTask
)
{
char
*
base
=
DOSMEM_MemoryBase
();
UINT16
cs
,
ss
,
ds
,
es
;
CONTEXT86
pm_ctx
;
DWORD
psp_ofs
=
(
DWORD
)(
lpDosTask
->
psp_seg
<<
4
);
PDB16
*
psp
=
(
PDB16
*
)
(
base
+
psp_ofs
)
;
PDB16
*
psp
=
(
PDB16
*
)
psp_ofs
;
HANDLE16
env_seg
=
psp
->
environment
;
int
is32
;
...
...
@@ -602,22 +589,22 @@ static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask )
lpDosTask
->
dpmi_flag
=
AX_reg
(
context
);
is32
=
lpDosTask
->
dpmi_flag
&
1
;
/* our mode switch wrapper have placed the desired CS into DX */
cs
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
DX_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_CODE
,
FALSE
,
FALSE
);
cs
=
SELECTOR_AllocBlock
(
(
void
*
)(
DX_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_CODE
,
FALSE
,
FALSE
);
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
32-bit code using this stack. */
ss
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
SS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
is32
,
FALSE
);
ss
=
SELECTOR_AllocBlock
(
(
void
*
)(
SS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
is32
,
FALSE
);
/* do the same for the data segments, just in case */
if
(
DS_reg
(
context
)
==
SS_reg
(
context
))
ds
=
ss
;
else
ds
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
DS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
is32
,
FALSE
);
es
=
SELECTOR_AllocBlock
(
base
+
psp_ofs
,
0x100
,
SEGMENT_DATA
,
is32
,
FALSE
);
else
ds
=
SELECTOR_AllocBlock
(
(
void
*
)(
DS_reg
(
context
)
<<
4
),
0x10000
,
SEGMENT_DATA
,
is32
,
FALSE
);
es
=
SELECTOR_AllocBlock
(
psp
,
0x100
,
SEGMENT_DATA
,
is32
,
FALSE
);
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
psp
->
environment
=
SELECTOR_AllocBlock
(
base
+
(
DWORD
)(
env_seg
<<
4
),
psp
->
environment
=
SELECTOR_AllocBlock
(
(
void
*
)(
env_seg
<<
4
),
0x10000
,
SEGMENT_DATA
,
FALSE
,
FALSE
);
pm_ctx
=
*
context
;
CS_reg
(
&
pm_ctx
)
=
lpDosTask
->
dpmi_sel
;
CS_reg
(
&
pm_ctx
)
=
DOSMEM_
dpmi_sel
;
/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
EAX_reg
(
&
pm_ctx
)
=
ss
;
EDX_reg
(
&
pm_ctx
)
=
cs
;
...
...
@@ -697,26 +684,6 @@ void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
}
#endif
#else
#if 0
void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
{
ERR("don't even think about DPMI raw mode switch without DOS support!\n");
ExitProcess(1);
}
#endif
#endif
#define DOS_APP_ISDOS(addr,base) ((addr) < 0x110000)
#define DOS_WINE_ISDOS(addr,base) (((addr) >= (base)) && ((addr) < (base) + 0x110000))
#define DOS_UC_APPTOWINE(addr,base) ((addr) + (base))
#define DOS_UC_WINETOAPP(addr,base) ((addr) - (base))
#define DOS_APPTOWINE(addr,base) (DOS_APP_ISDOS(addr,base) ? DOS_UC_APPTOWINE(addr,base) : (addr))
#define DOS_WINETOAPP(addr,base) (DOS_WINE_ISDOS(addr,base) ? DOS_UC_WINETOAPP(addr,base) : (addr))
#define DOS_BADLIMIT(addr,base,limit) \
((limit == 0xffffffff) ||
/* disallow "fat DS" for now */
\
(DOS_WINE_ISDOS(addr,base) && \
((addr) + (limit) > (base) + 0x110000)))
/**********************************************************************
* INT_Int31Handler
...
...
@@ -738,16 +705,15 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
LPDOSTASK
lpDosTask
=
MZ_Current
();
#ifdef MZ_SUPPORTED
if
(
ISV86
(
context
)
&&
lpDosTask
)
{
/* Called from real mode, check if it's our wrapper */
TRACE
(
"called from real mode
\n
"
);
if
(
CS_reg
(
context
)
==
lpDosTask
->
dpmi_seg
)
{
if
(
CS_reg
(
context
)
==
DOSMEM_
dpmi_seg
)
{
/* This is the protected mode switch */
StartPM
(
context
,
lpDosTask
);
return
;
}
else
if
(
CS_reg
(
context
)
==
lpDosTask
->
xms_seg
)
{
if
(
CS_reg
(
context
)
==
DOSMEM_
xms_seg
)
{
/* This is the XMS driver entry point */
XMS_Handler
(
context
);
return
;
...
...
@@ -766,7 +732,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
}
}
}
#endif
RESET_CFLAG
(
context
);
switch
(
AX_reg
(
context
))
...
...
@@ -849,12 +814,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
}
else
{
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
();
dw
=
DOS_WINETOAPP
(
dw
,
base
);
}
#endif
CX_reg
(
context
)
=
HIWORD
(
W32S_WINE2APP
(
dw
,
offset
));
DX_reg
(
context
)
=
LOWORD
(
W32S_WINE2APP
(
dw
,
offset
));
}
...
...
@@ -865,40 +824,12 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
BX_reg
(
context
),
W32S_APP2WINE
(
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)),
offset
));
dw
=
W32S_APP2WINE
(
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)),
offset
);
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
();
dw
=
DOS_APPTOWINE
(
dw
,
base
);
}
#endif
SetSelectorBase
(
BX_reg
(
context
),
dw
);
break
;
case
0x0008
:
/* Set selector limit */
TRACE
(
"set selector limit (0x%04x,0x%08lx)
\n
"
,
BX_reg
(
context
),
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)));
dw
=
MAKELONG
(
DX_reg
(
context
),
CX_reg
(
context
)
);
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
();
DWORD
sbase
=
GetSelectorBase
(
BX_reg
(
context
)
);
if
(
!
sbase
)
{
/* the app has set the limit without setting the base,
* it must be relying on that the default should be DOS space;
* so set the base address now */
SetSelectorBase
(
BX_reg
(
context
),
sbase
=
base
);
if
(
dw
==
0xffffffff
)
{
/* djgpp does this without checking (in _dos_ds setup, crt1.c),
* so we have to override the limit here */
dw
=
0x110000
;
}
}
if
(
DOS_BADLIMIT
(
sbase
,
base
,
dw
))
{
AX_reg
(
context
)
=
0x8021
;
/* invalid value */
SET_CFLAG
(
context
);
break
;
}
}
#endif
SetSelectorLimit16
(
BX_reg
(
context
),
dw
);
break
;
...
...
@@ -921,12 +852,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
{
ldt_entry
entry
;
LDT_GetEntry
(
SELECTOR_TO_ENTRY
(
BX_reg
(
context
)
),
&
entry
);
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
();
entry
.
base
=
DOS_WINETOAPP
(
entry
.
base
,
base
);
}
#endif
entry
.
base
=
W32S_WINE2APP
(
entry
.
base
,
offset
);
/* FIXME: should use ES:EDI for 32-bit clients */
...
...
@@ -942,18 +867,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
LDT_BytesToEntry
(
PTR_SEG_OFF_TO_LIN
(
ES_reg
(
context
),
DI_reg
(
context
)
),
&
entry
);
entry
.
base
=
W32S_APP2WINE
(
entry
.
base
,
offset
);
#ifdef MZ_SUPPORTED
if
(
lpDosTask
)
{
DWORD
base
=
(
DWORD
)
DOSMEM_MemoryBase
();
entry
.
base
=
DOS_APPTOWINE
(
entry
.
base
,
base
);
if
(
DOS_BADLIMIT
(
entry
.
base
,
base
,
entry
.
limit
))
{
AX_reg
(
context
)
=
0x8021
;
/* invalid value */
SET_CFLAG
(
context
);
break
;
}
}
#endif
LDT_SetEntry
(
SELECTOR_TO_ENTRY
(
BX_reg
(
context
)
),
&
entry
);
}
break
;
...
...
@@ -1032,7 +945,7 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
/* we probably won't need this kind of state saving */
AX_reg
(
context
)
=
0
;
/* real mode: just point to the lret */
BX_reg
(
context
)
=
D
PMI
_wrap_seg
;
BX_reg
(
context
)
=
D
OSMEM
_wrap_seg
;
ECX_reg
(
context
)
=
2
;
/* protected mode: don't have any handler yet... */
FIXME
(
"no protected-mode dummy state save/restore handler yet
\n
"
);
...
...
@@ -1042,18 +955,12 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
case
0x0306
:
/* Get Raw Mode Switch Addresses */
TRACE
(
"get raw mode switch addresses
\n
"
);
if
(
lpDosTask
)
{
/* real mode, point to standard DPMI return wrapper */
BX_reg
(
context
)
=
DPMI_wrap_seg
;
ECX_reg
(
context
)
=
0
;
/* protected mode, point to DPMI call wrapper */
SI_reg
(
context
)
=
lpDosTask
->
dpmi_sel
;
EDI_reg
(
context
)
=
8
;
/* offset of the INT 0x31 call */
}
else
{
ERR
(
"win app attempting to get raw mode switch!
\n
"
);
AX_reg
(
context
)
=
0x8001
;
/* unsupported function */
SET_CFLAG
(
context
);
}
/* real mode, point to standard DPMI return wrapper */
BX_reg
(
context
)
=
DOSMEM_wrap_seg
;
ECX_reg
(
context
)
=
0
;
/* protected mode, point to DPMI call wrapper */
SI_reg
(
context
)
=
DOSMEM_dpmi_sel
;
EDI_reg
(
context
)
=
8
;
/* offset of the INT 0x31 call */
break
;
case
0x0400
:
/* Get DPMI version */
TRACE
(
"get DPMI version
\n
"
);
...
...
msdos/int09.c
View file @
770eb51e
...
...
@@ -15,9 +15,11 @@ DEFAULT_DEBUG_CHANNEL(int);
#define QUEUELEN 31
typedef
struct
{
static
struct
{
BYTE
queuelen
,
queue
[
QUEUELEN
],
ascii
[
QUEUELEN
];
}
KBDSYSTEM
;
}
kbdinfo
;
/**********************************************************************
* INT_Int09Handler
...
...
@@ -58,48 +60,35 @@ void WINAPI INT_Int09Handler( CONTEXT86 *context )
DOSVM_PIC_ioport_out
(
0x20
,
0x20
);
/* send EOI */
}
static
void
KbdRelay
(
LPDOSTASK
lpDosTask
,
CONTEXT86
*
context
,
void
*
data
)
static
void
KbdRelay
(
CONTEXT86
*
context
,
void
*
data
)
{
KBDSYSTEM
*
sys
=
(
KBDSYSTEM
*
)
DOSVM_GetSystemData
(
0x09
);
if
(
sys
&&
sys
->
queuelen
)
{
if
(
kbdinfo
.
queuelen
)
{
/* cleanup operation, called from DOSVM_PIC_ioport_out:
* we'll remove current scancode from keyboard buffer here,
* rather than in ReadScan, because some DOS apps depend on
* the scancode being available for reading multiple times... */
if
(
--
sys
->
queuelen
)
{
memmove
(
sys
->
queue
,
sys
->
queue
+
1
,
sys
->
queuelen
);
memmove
(
sys
->
ascii
,
sys
->
ascii
+
1
,
sys
->
queuelen
);
if
(
--
kbdinfo
.
queuelen
)
{
memmove
(
kbdinfo
.
queue
,
kbdinfo
.
queue
+
1
,
kbdinfo
.
queuelen
);
memmove
(
kbdinfo
.
ascii
,
kbdinfo
.
ascii
+
1
,
kbdinfo
.
queuelen
);
}
}
}
void
WINAPI
INT_Int09SendScan
(
BYTE
scan
,
BYTE
ascii
)
{
KBDSYSTEM
*
sys
=
(
KBDSYSTEM
*
)
DOSVM_GetSystemData
(
0x09
);
if
(
!
sys
)
{
sys
=
calloc
(
1
,
sizeof
(
KBDSYSTEM
));
DOSVM_SetSystemData
(
0x09
,
sys
);
}
if
(
sys
->
queuelen
==
QUEUELEN
)
{
if
(
kbdinfo
.
queuelen
==
QUEUELEN
)
{
ERR
(
"keyboard queue overflow
\n
"
);
return
;
}
/* add scancode to queue */
sys
->
queue
[
sys
->
queuelen
]
=
scan
;
sys
->
ascii
[
sys
->
queuelen
++
]
=
ascii
;
kbdinfo
.
queue
[
kbdinfo
.
queuelen
]
=
scan
;
kbdinfo
.
ascii
[
kbdinfo
.
queuelen
++
]
=
ascii
;
/* tell app to read it by triggering IRQ 1 (int 09) */
DOSVM_QueueEvent
(
1
,
DOS_PRIORITY_KEYBOARD
,
KbdRelay
,
NULL
);
}
BYTE
WINAPI
INT_Int09ReadScan
(
BYTE
*
ascii
)
{
KBDSYSTEM
*
sys
=
(
KBDSYSTEM
*
)
DOSVM_GetSystemData
(
0x09
);
if
(
sys
)
{
if
(
ascii
)
*
ascii
=
sys
->
ascii
[
0
];
return
sys
->
queue
[
0
];
}
else
{
if
(
ascii
)
*
ascii
=
0
;
return
0
;
}
if
(
ascii
)
*
ascii
=
kbdinfo
.
ascii
[
0
];
return
kbdinfo
.
queue
[
0
];
}
msdos/int2f.c
View file @
770eb51e
...
...
@@ -115,9 +115,7 @@ void WINAPI INT_Int2fHandler( CONTEXT86 *context )
break
;
case
0x10
:
/* XMS v2+ get driver address */
{
LPDOSTASK
lpDosTask
=
MZ_Current
();
ES_reg
(
context
)
=
lpDosTask
?
lpDosTask
->
xms_seg
:
0
;
ES_reg
(
context
)
=
DOSMEM_xms_seg
;
BX_reg
(
context
)
=
0
;
break
;
}
...
...
@@ -349,15 +347,13 @@ static void do_int2f_16( CONTEXT86 *context )
#endif
{
SYSTEM_INFO
si
;
LPDOSTASK
lpDosTask
=
MZ_Current
();
GetSystemInfo
(
&
si
);
AX_reg
(
context
)
=
0x0000
;
/* DPMI Installed */
BX_reg
(
context
)
=
0x0001
;
/* 32bits available */
CL_reg
(
context
)
=
si
.
wProcessorLevel
;
DX_reg
(
context
)
=
0x005a
;
/* DPMI major/minor 0.90 */
SI_reg
(
context
)
=
0
;
/* # of para. of DOS extended private data */
ES_reg
(
context
)
=
lpDosTask
?
lpDosTask
->
dpmi_seg
:
0
;
ES_reg
(
context
)
=
DOSMEM_dpmi_seg
;
DI_reg
(
context
)
=
0
;
/* ES:DI is DPMI switch entry point */
break
;
}
...
...
@@ -402,9 +398,8 @@ static void MSCDEX_Dump(char* pfx, BYTE* req, int dorealmode)
case 3:
case 12:
ptr += sprintf(ptr, "\n\t\t\t\tIO_struct => ");
ios = (dorealmode) ?
DOSMEM_MapRealToLinear(MAKELONG(PTR_AT(req, 14, WORD), PTR_AT(req, 16, WORD))) :
PTR_SEG_OFF_TO_LIN(PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD));
ios = (dorealmode) ? PTR_REAL_TO_LIN( PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD)) :
PTR_SEG_OFF_TO_LIN(PTR_AT(req, 16, WORD), PTR_AT(req, 14, WORD));
for (i = 0; i < PTR_AT(req, 18, WORD); i++) {
ptr += sprintf(ptr, "%02x ", ios[i]);
...
...
@@ -476,9 +471,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
BYTE
Error
=
255
;
/* No Error */
int
dorealmode
=
ISV86
(
context
);
driver_request
=
(
dorealmode
)
?
DOSMEM_MapRealToLinear
(
MAKELONG
(
BX_reg
(
context
),
ES_reg
(
context
)))
:
PTR_SEG_OFF_TO_LIN
(
ES_reg
(
context
),
BX_reg
(
context
));
driver_request
=
CTX_SEG_OFF_TO_LIN
(
context
,
context
->
SegEs
,
context
->
Ebx
);
if
(
!
driver_request
)
{
/* FIXME - to be deleted ?? */
...
...
@@ -517,7 +510,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
switch
(
driver_request
[
2
])
{
case
3
:
io_stru
=
(
dorealmode
)
?
DOSMEM_MapRealToLinear
(
MAKELONG
(
PTR_AT
(
driver_request
,
14
,
WORD
),
PTR_AT
(
driver_request
,
16
,
WORD
))
)
:
PTR_REAL_TO_LIN
(
PTR_AT
(
driver_request
,
16
,
WORD
),
PTR_AT
(
driver_request
,
14
,
WORD
)
)
:
PTR_SEG_OFF_TO_LIN
(
PTR_AT
(
driver_request
,
16
,
WORD
),
PTR_AT
(
driver_request
,
14
,
WORD
));
TRACE
(
" --> IOCTL INPUT <%d>
\n
"
,
io_stru
[
0
]);
...
...
@@ -682,7 +675,7 @@ static void MSCDEX_Handler(CONTEXT86* context)
case
12
:
io_stru
=
(
dorealmode
)
?
DOSMEM_MapRealToLinear
(
MAKELONG
(
PTR_AT
(
driver_request
,
14
,
WORD
),
PTR_AT
(
driver_request
,
16
,
WORD
)
))
:
PTR_REAL_TO_LIN
(
PTR_AT
(
driver_request
,
16
,
WORD
),
PTR_AT
(
driver_request
,
14
,
WORD
))
:
PTR_SEG_OFF_TO_LIN
(
PTR_AT
(
driver_request
,
16
,
WORD
),
PTR_AT
(
driver_request
,
14
,
WORD
));
TRACE
(
" --> IOCTL OUTPUT <%d>
\n
"
,
io_stru
[
0
]);
...
...
msdos/int33.c
View file @
770eb51e
...
...
@@ -13,11 +13,12 @@
DEFAULT_DEBUG_CHANNEL
(
int
)
typedef
struct
{
static
struct
{
DWORD
x
,
y
,
but
;
FARPROC16
callback
;
WORD
callmask
;
}
MOUSESYSTEM
;
}
mouse_info
;
/**********************************************************************
* INT_Int33Handler
...
...
@@ -26,15 +27,12 @@ typedef struct {
*/
void
WINAPI
INT_Int33Handler
(
CONTEXT86
*
context
)
{
MOUSESYSTEM
*
sys
=
(
MOUSESYSTEM
*
)
DOSVM_GetSystemData
(
0x33
);
switch
(
AX_reg
(
context
))
{
case
0x00
:
TRACE
(
"Reset mouse driver and request status
\n
"
);
AX_reg
(
context
)
=
0xFFFF
;
/* installed */
BX_reg
(
context
)
=
3
;
/* # of buttons */
sys
=
calloc
(
1
,
sizeof
(
MOUSESYSTEM
));
DOSVM_SetSystemData
(
0x33
,
sys
);
memset
(
&
mouse_info
,
0
,
sizeof
(
mouse_info
)
);
break
;
case
0x01
:
FIXME
(
"Show mouse cursor
\n
"
);
...
...
@@ -44,9 +42,9 @@ void WINAPI INT_Int33Handler( CONTEXT86 *context )
break
;
case
0x03
:
TRACE
(
"Return mouse position and button status
\n
"
);
BX_reg
(
context
)
=
sys
->
but
;
CX_reg
(
context
)
=
sys
->
x
;
DX_reg
(
context
)
=
sys
->
y
;
BX_reg
(
context
)
=
mouse_info
.
but
;
CX_reg
(
context
)
=
mouse_info
.
x
;
DX_reg
(
context
)
=
mouse_info
.
y
;
break
;
case
0x04
:
FIXME
(
"Position mouse cursor
\n
"
);
...
...
@@ -65,8 +63,8 @@ void WINAPI INT_Int33Handler( CONTEXT86 *context )
break
;
case
0x0C
:
TRACE
(
"Define mouse interrupt subroutine
\n
"
);
sys
->
callmask
=
CX_reg
(
context
);
sys
->
callback
=
(
FARPROC16
)
PTR_SEG_OFF_TO_SEGPTR
(
ES_reg
(
context
),
DX_reg
(
context
));
mouse_info
.
callmask
=
CX_reg
(
context
);
mouse_info
.
callback
=
(
FARPROC16
)
PTR_SEG_OFF_TO_SEGPTR
(
ES_reg
(
context
),
DX_reg
(
context
));
break
;
case
0x10
:
FIXME
(
"Define screen region for update
\n
"
);
...
...
@@ -81,7 +79,7 @@ typedef struct {
WORD
mask
,
but
,
x
,
y
,
mx
,
my
;
}
MCALLDATA
;
static
void
MouseRelay
(
LPDOSTASK
lpDosTask
,
CONTEXT86
*
context
,
void
*
mdata
)
static
void
MouseRelay
(
CONTEXT86
*
context
,
void
*
mdata
)
{
MCALLDATA
*
data
=
(
MCALLDATA
*
)
mdata
;
CONTEXT86
ctx
=
*
context
;
...
...
@@ -100,58 +98,56 @@ static void MouseRelay(LPDOSTASK lpDosTask,CONTEXT86 *context,void *mdata)
void
WINAPI
INT_Int33Message
(
UINT
message
,
WPARAM
wParam
,
LPARAM
lParam
)
{
MOUSESYSTEM
*
sys
=
(
MOUSESYSTEM
*
)
DOSVM_GetSystemData
(
0x33
);
WORD
mask
=
0
;
unsigned
Height
,
Width
,
SX
=
1
,
SY
=
1
;
if
(
!
sys
)
return
;
if
(
!
VGA_GetMode
(
&
Height
,
&
Width
,
NULL
))
{
/* may need to do some coordinate scaling */
SX
=
640
/
Width
;
if
(
!
SX
)
SX
=
1
;
}
sys
->
x
=
LOWORD
(
lParam
)
*
SX
;
sys
->
y
=
HIWORD
(
lParam
)
*
SY
;
mouse_info
.
x
=
LOWORD
(
lParam
)
*
SX
;
mouse_info
.
y
=
HIWORD
(
lParam
)
*
SY
;
switch
(
message
)
{
case
WM_MOUSEMOVE
:
mask
|=
0x01
;
break
;
case
WM_LBUTTONDOWN
:
case
WM_LBUTTONDBLCLK
:
sys
->
but
|=
0x01
;
mouse_info
.
but
|=
0x01
;
mask
|=
0x02
;
break
;
case
WM_LBUTTONUP
:
sys
->
but
&=
~
0x01
;
mouse_info
.
but
&=
~
0x01
;
mask
|=
0x04
;
break
;
case
WM_RBUTTONDOWN
:
case
WM_RBUTTONDBLCLK
:
sys
->
but
|=
0x02
;
mouse_info
.
but
|=
0x02
;
mask
|=
0x08
;
break
;
case
WM_RBUTTONUP
:
sys
->
but
&=
~
0x02
;
mouse_info
.
but
&=
~
0x02
;
mask
|=
0x10
;
break
;
case
WM_MBUTTONDOWN
:
case
WM_MBUTTONDBLCLK
:
sys
->
but
|=
0x04
;
mouse_info
.
but
|=
0x04
;
mask
|=
0x20
;
break
;
case
WM_MBUTTONUP
:
sys
->
but
&=
~
0x04
;
mouse_info
.
but
&=
~
0x04
;
mask
|=
0x40
;
break
;
}
if
((
mask
&
sys
->
callmask
)
&&
sys
->
callback
)
{
if
((
mask
&
mouse_info
.
callmask
)
&&
mouse_info
.
callback
)
{
MCALLDATA
*
data
=
calloc
(
1
,
sizeof
(
MCALLDATA
));
data
->
proc
=
sys
->
callback
;
data
->
mask
=
mask
&
sys
->
callmask
;
data
->
but
=
sys
->
but
;
data
->
x
=
sys
->
x
;
data
->
y
=
sys
->
y
;
data
->
proc
=
mouse_info
.
callback
;
data
->
mask
=
mask
&
mouse_info
.
callmask
;
data
->
but
=
mouse_info
.
but
;
data
->
x
=
mouse_info
.
x
;
data
->
y
=
mouse_info
.
y
;
DOSVM_QueueEvent
(
-
1
,
DOS_PRIORITY_MOUSE
,
MouseRelay
,
data
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment