krnl386.exe16: Make a couple of functions static.
[wine.git] / dlls / krnl386.exe16 / dosvm.c
bloba33b37a8a549fb79e4c3a92442e83c5335668217
1 /*
2 * DOS Virtual Machine
4 * Copyright 1998 Ove Kåven
5 * Copyright 2002 Jukka Heinonen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * Note: This code hasn't been completely cleaned up yet.
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #ifdef HAVE_SYS_TIME_H
38 # include <sys/time.h>
39 #endif
40 #include <sys/types.h>
42 #include "wine/winbase16.h"
43 #include "wine/exception.h"
44 #include "windef.h"
45 #include "winbase.h"
46 #include "winternl.h"
47 #include "wingdi.h"
48 #include "winuser.h"
49 #include "wownt32.h"
50 #include "winnt.h"
51 #include "wincon.h"
53 #include "dosexe.h"
54 #include "wine/debug.h"
55 #include "excpt.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(int);
59 WORD DOSVM_psp = 0;
60 WORD DOSVM_retval = 0;
63 * Wine DOS memory layout above 640k:
65 * a0000 - affff : VGA graphics (vga.c)
66 * b0000 - bffff : Monochrome text (unused)
67 * b8000 - bffff : VGA text (vga.c)
68 * c0000 - cffff : EMS frame (int67.c)
69 * d0000 - effff : Free memory for UMBs (himem.c)
70 * f0000 - fffff : BIOS stuff (msdos/dosmem.c)
71 * 100000 -10ffff : High memory area (unused)
75 * Table of real mode segments and protected mode selectors
76 * for code stubs and other miscellaneous storage.
78 struct DPMI_segments *DOSVM_dpmi_segments = NULL;
81 * First and last address available for upper memory blocks.
83 #define DOSVM_UMB_BOTTOM 0xd0000
84 #define DOSVM_UMB_TOP 0xeffff
87 * First free address for upper memory blocks.
89 static DWORD DOSVM_umb_free = DOSVM_UMB_BOTTOM;
92 /**********************************************************************
93 * DOSVM_Exit
95 void DOSVM_Exit( WORD retval )
97 DWORD count;
99 ReleaseThunkLock( &count );
100 ExitThread( retval );
103 /***********************************************************************
104 * DOSVM_AllocUMB
106 * Allocate upper memory block (UMB) from upper memory.
107 * Returned pointer is aligned to 16-byte (paragraph) boundary.
109 * This routine is only for allocating static storage for
110 * Wine internal uses. Allocated memory can be accessed from
111 * real mode, memory is taken from area already mapped and reserved
112 * by Wine and the allocation has very little memory and speed
113 * overhead. Use of this routine also preserves precious DOS
114 * conventional memory.
116 static LPVOID DOSVM_AllocUMB( DWORD size )
118 LPVOID ptr = (LPVOID)DOSVM_umb_free;
120 size = ((size + 15) >> 4) << 4;
122 if(DOSVM_umb_free + size - 1 > DOSVM_UMB_TOP) {
123 ERR("Out of upper memory area.\n");
124 return 0;
127 DOSVM_umb_free += size;
128 return ptr;
132 /**********************************************************************
133 * alloc_selector
135 * Allocate a selector corresponding to a real mode address.
136 * size must be < 64k.
138 static WORD alloc_selector( void *base, DWORD size, unsigned char flags )
140 WORD sel = wine_ldt_alloc_entries( 1 );
142 if (sel)
144 LDT_ENTRY entry;
145 wine_ldt_set_base( &entry, base );
146 wine_ldt_set_limit( &entry, size - 1 );
147 wine_ldt_set_flags( &entry, flags );
148 wine_ldt_set_entry( sel, &entry );
150 return sel;
154 /***********************************************************************
155 * DOSVM_AllocCodeUMB
157 * Allocate upper memory block for storing code stubs.
158 * Initializes real mode segment and 16-bit protected mode selector
159 * for the allocated code block.
161 * FIXME: should allocate a single PM selector for the whole UMB range.
163 static LPVOID DOSVM_AllocCodeUMB( DWORD size, WORD *selector )
165 LPVOID ptr = DOSVM_AllocUMB( size );
166 *selector = alloc_selector( ptr, size, WINE_LDT_FLAGS_CODE );
167 return ptr;
171 /***********************************************************************
172 * DOSVM_AllocDataUMB
174 * Allocate upper memory block for storing data.
175 * Initializes real mode segment and 16-bit protected mode selector
176 * for the allocated data block.
178 LPVOID DOSVM_AllocDataUMB( DWORD size, WORD *selector )
180 LPVOID ptr = DOSVM_AllocUMB( size );
181 *selector = alloc_selector( ptr, size, WINE_LDT_FLAGS_DATA );
182 return ptr;
186 /***********************************************************************
187 * DOSVM_InitSegments
189 * Initializes DOSVM_dpmi_segments. Allocates required memory and
190 * sets up segments and selectors for accessing the memory.
192 void DOSVM_InitSegments(void)
194 DWORD old_prot;
195 LPSTR ptr;
196 int i;
198 static const char relay[]=
200 0xca, 0x04, 0x00, /* 16-bit far return and pop 4 bytes (relay void* arg) */
201 0xcd, 0x31, /* int 31 */
202 0xfb, 0x66, 0xcb /* sti and 32-bit far return */
206 * Allocate pointer array.
208 DOSVM_dpmi_segments = DOSVM_AllocUMB( sizeof(struct DPMI_segments) );
211 * PM / offset N*5: Interrupt N in 16-bit protected mode.
213 ptr = DOSVM_AllocCodeUMB( 5 * 256, &DOSVM_dpmi_segments->int16_sel );
214 for(i=0; i<256; i++) {
216 * Each 16-bit interrupt handler is 5 bytes:
217 * 0xCD,<i> = int <i> (interrupt)
218 * 0xCA,0x02,0x00 = ret 2 (16-bit far return and pop 2 bytes / eflags)
220 ptr[i * 5 + 0] = 0xCD;
221 ptr[i * 5 + 1] = i;
222 ptr[i * 5 + 2] = 0xCA;
223 ptr[i * 5 + 3] = 0x02;
224 ptr[i * 5 + 4] = 0x00;
228 * PM / offset 0: Stub where __wine_call_from_16_regs returns.
229 * PM / offset 3: Stub which swaps back to 32-bit application code/stack.
230 * PM / offset 5: Stub which enables interrupts
232 ptr = DOSVM_AllocCodeUMB( sizeof(relay), &DOSVM_dpmi_segments->relay_code_sel);
233 memcpy( ptr, relay, sizeof(relay) );
236 * Space for 16-bit stack used by relay code.
238 ptr = DOSVM_AllocDataUMB( DOSVM_RELAY_DATA_SIZE, &DOSVM_dpmi_segments->relay_data_sel);
239 memset( ptr, 0, DOSVM_RELAY_DATA_SIZE );
242 * As we store code in UMB we should make sure it is executable
244 VirtualProtect((void *)DOSVM_UMB_BOTTOM, DOSVM_UMB_TOP - DOSVM_UMB_BOTTOM, PAGE_EXECUTE_READWRITE, &old_prot);