Release 980913
[wine/wine-kai.git] / msdos / dpmi.c
blob48ae756b8d1c397117c636a5731dd420b8617a12
1 /*
2 * DPMI 0.9 emulation
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <unistd.h>
8 #include <string.h>
9 #include "windows.h"
10 #include "heap.h"
11 #include "global.h"
12 #include "ldt.h"
13 #include "module.h"
14 #include "miscemu.h"
15 #include "drive.h"
16 #include "msdos.h"
17 #include "toolhelp.h"
18 #include "debug.h"
19 #include "selectors.h"
20 #include "thread.h"
21 #include "process.h"
22 #include "stackframe.h"
23 #include "callback.h"
25 #define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive())
27 void CreateBPB(int drive, BYTE *data, BOOL16 limited); /* defined in int21.c */
29 static void* lastvalloced = NULL;
31 /* Structure for real-mode callbacks */
32 typedef struct
34 DWORD edi;
35 DWORD esi;
36 DWORD ebp;
37 DWORD reserved;
38 DWORD ebx;
39 DWORD edx;
40 DWORD ecx;
41 DWORD eax;
42 WORD fl;
43 WORD es;
44 WORD ds;
45 WORD fs;
46 WORD gs;
47 WORD ip;
48 WORD cs;
49 WORD sp;
50 WORD ss;
51 } REALMODECALL;
55 typedef struct tagRMCB {
56 DWORD address;
57 struct tagRMCB *next;
59 } RMCB;
61 static RMCB *FirstRMCB = NULL;
63 /**********************************************************************
64 * DPMI_xalloc
65 * special virtualalloc, allocates lineary monoton growing memory.
66 * (the usual VirtualAlloc does not satisfy that restriction)
68 static LPVOID
69 DPMI_xalloc(int len) {
70 LPVOID ret;
71 LPVOID oldlastv = lastvalloced;
73 if (lastvalloced) {
74 int xflag = 0;
75 ret = NULL;
76 while (!ret) {
77 ret=VirtualAlloc(lastvalloced,len,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
78 if (!ret)
79 lastvalloced+=0x10000;
80 /* we failed to allocate one in the first round.
81 * try non-linear
83 if (!xflag && (lastvalloced<oldlastv)) { /* wrapped */
84 FIXME(int31,"failed to allocate lineary growing memory (%d bytes), using non-linear growing...\n",len);
85 xflag++;
87 /* if we even fail to allocate something in the next
88 * round, return NULL
90 if ((xflag==1) && (lastvalloced >= oldlastv))
91 xflag++;
92 if ((xflag==2) && (lastvalloced < oldlastv)) {
93 FIXME(int31,"failed to allocate any memory of %d bytes!\n",len);
94 return NULL;
97 } else
98 ret=VirtualAlloc(NULL,len,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
99 lastvalloced = (LPVOID)(((DWORD)ret+len+0xffff)&~0xffff);
100 return ret;
103 static void
104 DPMI_xfree(LPVOID ptr) {
105 VirtualFree(ptr,0,MEM_RELEASE);
108 /* FIXME: perhaps we could grow this mapped area... */
109 static LPVOID
110 DPMI_xrealloc(LPVOID ptr,int newsize) {
111 MEMORY_BASIC_INFORMATION mbi;
112 LPVOID newptr;
114 newptr = DPMI_xalloc(newsize);
115 if (ptr) {
116 if (!VirtualQuery(ptr,&mbi,sizeof(mbi))) {
117 FIXME(int31,"realloc of DPMI_xallocd region %p?\n",ptr);
118 return NULL;
120 if (mbi.State == MEM_FREE) {
121 FIXME(int31,"realloc of DPMI_xallocd region %p?\n",ptr);
122 return NULL;
124 /* We do not shrink allocated memory. most reallocs
125 * only do grows anyway
127 if (newsize<=mbi.RegionSize)
128 return ptr;
129 memcpy(newptr,ptr,mbi.RegionSize);
130 DPMI_xfree(ptr);
132 return newptr;
134 /**********************************************************************
135 * INT_GetRealModeContext
137 static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT *context )
139 EAX_reg(context) = call->eax;
140 EBX_reg(context) = call->ebx;
141 ECX_reg(context) = call->ecx;
142 EDX_reg(context) = call->edx;
143 ESI_reg(context) = call->esi;
144 EDI_reg(context) = call->edi;
145 EBP_reg(context) = call->ebp;
146 EFL_reg(context) = call->fl | 0x00020000; /* V86 */
147 EIP_reg(context) = call->ip;
148 ESP_reg(context) = call->sp;
149 CS_reg(context) = call->cs;
150 DS_reg(context) = call->ds;
151 ES_reg(context) = call->es;
152 FS_reg(context) = call->fs;
153 GS_reg(context) = call->gs;
154 (char*)V86BASE(context) = DOSMEM_MemoryBase(0);
158 /**********************************************************************
159 * INT_SetRealModeContext
161 static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT *context )
163 call->eax = EAX_reg(context);
164 call->ebx = EBX_reg(context);
165 call->ecx = ECX_reg(context);
166 call->edx = EDX_reg(context);
167 call->esi = ESI_reg(context);
168 call->edi = EDI_reg(context);
169 call->ebp = EBP_reg(context);
170 call->fl = FL_reg(context);
171 call->ip = IP_reg(context);
172 call->sp = SP_reg(context);
173 call->cs = CS_reg(context);
174 call->ds = DS_reg(context);
175 call->es = ES_reg(context);
176 call->fs = FS_reg(context);
177 call->gs = GS_reg(context);
181 /**********************************************************************
182 * INT_DoRealModeInt
184 static void INT_DoRealModeInt( CONTEXT *context )
186 CONTEXT realmode_ctx;
187 REALMODECALL *call = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context),
188 DI_reg(context) );
189 INT_GetRealModeContext( call, &realmode_ctx );
191 RESET_CFLAG(context);
192 if (INT_RealModeInterrupt( BL_reg(context), context ))
193 SET_CFLAG(context);
194 if (EFL_reg(context)&1) {
195 FIXME(int31,"%02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
196 BL_reg(context), EAX_reg(&realmode_ctx), EBX_reg(&realmode_ctx),
197 ECX_reg(&realmode_ctx), EDX_reg(&realmode_ctx));
198 FIXME(int31," ESI=%08lx EDI=%08lx DS=%04lx ES=%04lx\n",
199 ESI_reg(&realmode_ctx), EDI_reg(&realmode_ctx),
200 DS_reg(&realmode_ctx), ES_reg(&realmode_ctx) );
202 INT_SetRealModeContext( call, &realmode_ctx );
206 static void CallRMProcFar( CONTEXT *context )
208 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) );
209 CONTEXT context16;
210 THDB *thdb = THREAD_Current();
211 WORD argsize, sel;
212 LPVOID addr;
213 SEGPTR seg_addr;
215 TRACE(int31, "RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
216 p->eax, p->ebx, p->ecx, p->edx);
217 TRACE(int31, " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments\n",
218 p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context) );
220 if (!(p->cs) && !(p->ip)) { /* remove this check
221 if Int21/6501 case map function
222 has been implemented */
223 SET_CFLAG(context);
224 return;
226 INT_GetRealModeContext(p, &context16);
228 addr = DOSMEM_MapRealToLinear(MAKELONG(p->ip, p->cs));
229 sel = SELECTOR_AllocBlock( addr, 0x10000, SEGMENT_CODE, FALSE, FALSE );
230 seg_addr = PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
232 CS_reg(&context16) = HIWORD(seg_addr);
233 IP_reg(&context16) = LOWORD(seg_addr);
234 EBP_reg(&context16) = OFFSETOF( thdb->cur_stack )
235 + (WORD)&((STACK16FRAME*)0)->bp;
237 argsize = CX_reg(context)*sizeof(WORD);
238 memcpy( ((LPBYTE)THREAD_STACK16(thdb))-argsize,
239 (LPBYTE)PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context))+6, argsize );
241 Callbacks->CallRegisterShortProc(&context16, argsize);
243 UnMapLS(seg_addr);
244 INT_SetRealModeContext(p, &context16);
248 void WINAPI RMCallbackProc( FARPROC16 pmProc, REALMODECALL *rmc )
250 CONTEXT ctx;
251 INT_GetRealModeContext(rmc, &ctx);
252 Callbacks->CallRegisterShortProc(&ctx, 0);
256 static void AllocRMCB( CONTEXT *context )
258 RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
259 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) );
260 UINT16 uParagraph;
262 FIXME(int31, "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", p->eax, p->ebx, p->ecx, p->edx);
263 FIXME(int31, " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n", p->esi, p->edi, p->es, p->ds, p->cs, p->ip);
264 FIXME(int31, " Function to call: %04x:%04x\n",
265 (WORD)DS_reg(context), SI_reg(context) );
267 if (NewRMCB)
269 LPVOID RMCBmem = DOSMEM_GetBlock(0, 20, &uParagraph);
270 LPBYTE p = RMCBmem;
272 *p++ = 0x68; /* pushl */
273 *(FARPROC16 *)p =
274 PTR_SEG_OFF_TO_LIN(ES_reg(context), SI_reg(context)); /* pmode proc to call */
275 p+=4;
276 *p++ = 0x68; /* pushl */
277 *(LPVOID *)p =
278 PTR_SEG_OFF_TO_LIN(ES_reg(context), DI_reg(context));
279 p+=4;
280 *p++ = 0x9a; /* lcall */
281 *(FARPROC16 *)p = (FARPROC16)RMCallbackProc; /* FIXME ? */
282 p+=4;
283 GET_CS(*(WORD *)p);
284 p+=2;
285 *p++=0xc3; /* retf */
286 NewRMCB->address = MAKELONG(0, uParagraph);
287 NewRMCB->next = FirstRMCB;
288 FirstRMCB = NewRMCB;
289 CX_reg(context) = uParagraph;
290 DX_reg(context) = 0;
292 else
294 AX_reg(context) = 0x8015; /* callback unavailable */
295 SET_CFLAG(context);
300 static void FreeRMCB( CONTEXT *context )
302 RMCB *CurrRMCB = FirstRMCB;
303 RMCB *PrevRMCB = NULL;
305 FIXME(int31, "callback address: %04x:%04x\n",
306 CX_reg(context), DX_reg(context));
308 while (CurrRMCB && (CurrRMCB->address != MAKELONG(DX_reg(context), CX_reg(context))))
310 PrevRMCB = CurrRMCB;
311 CurrRMCB = CurrRMCB->next;
313 if (CurrRMCB)
315 if (PrevRMCB)
316 PrevRMCB->next = CurrRMCB->next;
317 else
318 FirstRMCB = CurrRMCB->next;
319 DOSMEM_FreeBlock(0, DOSMEM_MapRealToLinear(CurrRMCB->address));
320 HeapFree(GetProcessHeap(), 0, CurrRMCB);
322 else
324 AX_reg(context) = 0x8024; /* invalid callback address */
325 SET_CFLAG(context);
330 /**********************************************************************
331 * INT_Int31Handler
333 * Handler for int 31h (DPMI).
336 void WINAPI INT_Int31Handler( CONTEXT *context )
339 * Note: For Win32s processes, the whole linear address space is
340 * shifted by 0x10000 relative to the OS linear address space.
341 * See the comment in msdos/vxd.c.
343 DWORD offset = PROCESS_Current()->flags & PDB32_WIN32S_PROC ? 0x10000 : 0;
344 #define AppToWine(addr) ((addr)? ((DWORD)(addr)) + offset : 0)
345 #define WineToApp(addr) ((addr)? ((DWORD)(addr)) - offset : 0)
347 DWORD dw;
348 BYTE *ptr;
350 RESET_CFLAG(context);
351 switch(AX_reg(context))
353 case 0x0000: /* Allocate LDT descriptors */
354 TRACE(int31,"allocate LDT descriptors (%d)\n",CX_reg(context));
355 if (!(AX_reg(context) = AllocSelectorArray( CX_reg(context) )))
357 TRACE(int31,"failed\n");
358 AX_reg(context) = 0x8011; /* descriptor unavailable */
359 SET_CFLAG(context);
361 TRACE(int31,"success, array starts at 0x%04x\n",AX_reg(context));
362 break;
364 case 0x0001: /* Free LDT descriptor */
365 TRACE(int31,"free LDT descriptor (0x%04x)\n",BX_reg(context));
366 if (FreeSelector( BX_reg(context) ))
368 AX_reg(context) = 0x8022; /* invalid selector */
369 SET_CFLAG(context);
371 else
373 /* If a segment register contains the selector being freed, */
374 /* set it to zero. */
375 if (!((DS_reg(context)^BX_reg(context)) & ~3)) DS_reg(context) = 0;
376 if (!((ES_reg(context)^BX_reg(context)) & ~3)) ES_reg(context) = 0;
377 if (!((FS_reg(context)^BX_reg(context)) & ~3)) FS_reg(context) = 0;
378 if (!((GS_reg(context)^BX_reg(context)) & ~3)) GS_reg(context) = 0;
380 break;
382 case 0x0002: /* Real mode segment to descriptor */
383 TRACE(int31,"real mode segment to descriptor (0x%04x)\n",BX_reg(context));
385 WORD entryPoint = 0; /* KERNEL entry point for descriptor */
386 switch(BX_reg(context))
388 case 0x0000: entryPoint = 183; break; /* __0000H */
389 case 0x0040: entryPoint = 193; break; /* __0040H */
390 case 0xa000: entryPoint = 174; break; /* __A000H */
391 case 0xb000: entryPoint = 181; break; /* __B000H */
392 case 0xb800: entryPoint = 182; break; /* __B800H */
393 case 0xc000: entryPoint = 195; break; /* __C000H */
394 case 0xd000: entryPoint = 179; break; /* __D000H */
395 case 0xe000: entryPoint = 190; break; /* __E000H */
396 case 0xf000: entryPoint = 194; break; /* __F000H */
397 default:
398 AX_reg(context) = DOSMEM_AllocSelector(BX_reg(context));
399 break;
401 if (entryPoint)
402 AX_reg(context) = LOWORD(NE_GetEntryPoint(
403 GetModuleHandle16( "KERNEL" ),
404 entryPoint ));
406 break;
408 case 0x0003: /* Get next selector increment */
409 TRACE(int31,"get selector increment (__AHINCR)\n");
410 AX_reg(context) = __AHINCR;
411 break;
413 case 0x0004: /* Lock selector (not supported) */
414 FIXME(int31,"lock selector not supported\n");
415 AX_reg(context) = 0; /* FIXME: is this a correct return value? */
416 break;
418 case 0x0005: /* Unlock selector (not supported) */
419 FIXME(int31,"unlock selector not supported\n");
420 AX_reg(context) = 0; /* FIXME: is this a correct return value? */
421 break;
423 case 0x0006: /* Get selector base address */
424 TRACE(int31,"get selector base address (0x%04x)\n",BX_reg(context));
425 if (!(dw = GetSelectorBase( BX_reg(context) )))
427 AX_reg(context) = 0x8022; /* invalid selector */
428 SET_CFLAG(context);
430 else
432 CX_reg(context) = HIWORD(WineToApp(dw));
433 DX_reg(context) = LOWORD(WineToApp(dw));
435 break;
437 case 0x0007: /* Set selector base address */
438 TRACE(int31, "set selector base address (0x%04x,0x%08lx)\n",
439 BX_reg(context),
440 AppToWine(MAKELONG(DX_reg(context),CX_reg(context))));
441 SetSelectorBase(BX_reg(context),
442 AppToWine(MAKELONG(DX_reg(context), CX_reg(context))));
443 break;
445 case 0x0008: /* Set selector limit */
446 TRACE(int31,"set selector limit (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context)));
447 SetSelectorLimit( BX_reg(context),
448 MAKELONG( DX_reg(context), CX_reg(context) ) );
449 break;
451 case 0x0009: /* Set selector access rights */
452 TRACE(int31,"set selector access rights(0x%04x,0x%04x)\n",BX_reg(context),CX_reg(context));
453 SelectorAccessRights( BX_reg(context), 1, CX_reg(context) );
454 break;
456 case 0x000a: /* Allocate selector alias */
457 TRACE(int31,"allocate selector alias (0x%04x)\n",BX_reg(context));
458 if (!(AX_reg(context) = AllocCStoDSAlias( BX_reg(context) )))
460 AX_reg(context) = 0x8011; /* descriptor unavailable */
461 SET_CFLAG(context);
463 break;
465 case 0x000b: /* Get descriptor */
466 TRACE(int31,"get descriptor (0x%04x)\n",BX_reg(context));
468 ldt_entry entry;
469 LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
470 entry.base = WineToApp(entry.base);
472 /* FIXME: should use ES:EDI for 32-bit clients */
473 LDT_EntryToBytes( PTR_SEG_OFF_TO_LIN( ES_reg(context),
474 DI_reg(context) ), &entry );
476 break;
478 case 0x000c: /* Set descriptor */
479 TRACE(int31,"set descriptor (0x%04x)\n",BX_reg(context));
481 ldt_entry entry;
482 LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context),
483 DI_reg(context) ), &entry );
484 entry.base = AppToWine(entry.base);
486 LDT_SetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
488 break;
490 case 0x000d: /* Allocate specific LDT descriptor */
491 FIXME(int31,"allocate descriptor (0x%04x), stub!\n",BX_reg(context));
492 AX_reg(context) = 0x8011; /* descriptor unavailable */
493 SET_CFLAG(context);
494 break;
495 case 0x0200: /* get real mode interrupt vector */
496 FIXME(int31,"get realmode interupt vector(0x%02x) unimplemented.\n",
497 BL_reg(context));
498 SET_CFLAG(context);
499 break;
500 case 0x0201: /* set real mode interrupt vector */
501 FIXME(int31, "set realmode interupt vector(0x%02x,0x%04x:0x%04x) unimplemented\n", BL_reg(context),CX_reg(context),DX_reg(context));
502 SET_CFLAG(context);
503 break;
504 case 0x0204: /* Get protected mode interrupt vector */
505 TRACE(int31,"get protected mode interrupt handler (0x%02x), stub!\n",BL_reg(context));
506 dw = (DWORD)INT_GetHandler( BL_reg(context) );
507 CX_reg(context) = HIWORD(dw);
508 DX_reg(context) = LOWORD(dw);
509 break;
511 case 0x0205: /* Set protected mode interrupt vector */
512 TRACE(int31,"set protected mode interrupt handler (0x%02x,%p), stub!\n",
513 BL_reg(context),PTR_SEG_OFF_TO_LIN(CX_reg(context),DX_reg(context)));
514 INT_SetHandler( BL_reg(context),
515 (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( CX_reg(context),
516 DX_reg(context) ));
517 break;
519 case 0x0300: /* Simulate real mode interrupt */
520 INT_DoRealModeInt( context );
521 break;
523 case 0x0301: /* Call real mode procedure with far return */
524 CallRMProcFar( context );
525 break;
527 case 0x0302: /* Call real mode procedure with interrupt return */
529 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) );
530 FIXME(int31, "RealModeCallIret: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", p->eax, p->ebx, p->ecx, p->edx);
531 FIXME(int31, " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n", p->esi, p->edi, p->es, p->ds, p->cs, p->ip );
532 SET_CFLAG(context);
534 break;
536 case 0x0303: /* Allocate Real Mode Callback Address */
537 AllocRMCB( context );
538 break;
540 case 0x0304: /* Free Real Mode Callback Address */
541 FreeRMCB( context );
542 break;
544 case 0x0400: /* Get DPMI version */
545 TRACE(int31,"get DPMI version\n");
547 SYSTEM_INFO si;
549 GetSystemInfo(&si);
550 AX_reg(context) = 0x005a; /* DPMI version 0.90 */
551 BX_reg(context) = 0x0005; /* Flags: 32-bit, virtual memory */
552 CL_reg(context) = si.wProcessorLevel;
553 DX_reg(context) = 0x0102; /* Master/slave interrupt controller base*/
554 break;
556 case 0x0500: /* Get free memory information */
557 TRACE(int31,"get free memory information\n");
559 MEMMANINFO mmi;
561 mmi.dwSize = sizeof(mmi);
562 MemManInfo(&mmi);
563 ptr = (BYTE *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context));
564 /* the layout is just the same as MEMMANINFO, but without
565 * the dwSize entry.
567 memcpy(ptr,((char*)&mmi)+4,sizeof(mmi)-4);
568 break;
570 case 0x0501: /* Allocate memory block */
571 TRACE(int31,"allocate memory block (%ld)\n",MAKELONG(CX_reg(context),BX_reg(context)));
572 if (!(ptr = (BYTE *)DPMI_xalloc(MAKELONG(CX_reg(context), BX_reg(context)))))
574 AX_reg(context) = 0x8012; /* linear memory not available */
575 SET_CFLAG(context);
576 } else {
577 BX_reg(context) = SI_reg(context) = HIWORD(WineToApp(ptr));
578 CX_reg(context) = DI_reg(context) = LOWORD(WineToApp(ptr));
580 break;
582 case 0x0502: /* Free memory block */
583 TRACE(int31, "free memory block (0x%08lx)\n",
584 AppToWine(MAKELONG(DI_reg(context),SI_reg(context))));
585 DPMI_xfree( (void *)AppToWine(MAKELONG(DI_reg(context),
586 SI_reg(context))) );
587 break;
589 case 0x0503: /* Resize memory block */
590 TRACE(int31, "resize memory block (0x%08lx,%ld)\n",
591 AppToWine(MAKELONG(DI_reg(context),SI_reg(context))),
592 MAKELONG(CX_reg(context),BX_reg(context)));
593 if (!(ptr = (BYTE *)DPMI_xrealloc(
594 (void *)AppToWine(MAKELONG(DI_reg(context),SI_reg(context))),
595 MAKELONG(CX_reg(context),BX_reg(context)))))
597 AX_reg(context) = 0x8012; /* linear memory not available */
598 SET_CFLAG(context);
599 } else {
600 BX_reg(context) = SI_reg(context) = HIWORD(WineToApp(ptr));
601 CX_reg(context) = DI_reg(context) = LOWORD(WineToApp(ptr));
603 break;
605 case 0x0600: /* Lock linear region */
606 FIXME(int31,"lock linear region unimplemented\n");
607 break; /* Just ignore it */
609 case 0x0601: /* Unlock linear region */
610 FIXME(int31,"unlock linear region unimplemented\n");
611 break; /* Just ignore it */
613 case 0x0602: /* Unlock real-mode region */
614 FIXME(int31,"unlock realmode region unimplemented\n");
615 break; /* Just ignore it */
617 case 0x0603: /* Lock real-mode region */
618 FIXME(int31,"lock realmode region unimplemented\n");
619 break; /* Just ignore it */
621 case 0x0604: /* Get page size */
622 TRACE(int31,"get pagesize\n");
623 BX_reg(context) = 0;
624 CX_reg(context) = VIRTUAL_GetPageSize();
625 break;
627 case 0x0702: /* Mark page as demand-paging candidate */
628 FIXME(int31,"mark page as demand-paging candidate\n");
629 break; /* Just ignore it */
631 case 0x0703: /* Discard page contents */
632 FIXME(int31,"discard page contents\n");
633 break; /* Just ignore it */
635 case 0x0800: /* Physical address mapping */
636 FIXME(int31,"map real to linear (0x%08lx)\n",MAKELONG(CX_reg(context),BX_reg(context)));
637 if(!(ptr=DOSMEM_MapRealToLinear(MAKELONG(CX_reg(context),BX_reg(context)))))
639 AX_reg(context) = 0x8021;
640 SET_CFLAG(context);
642 else
644 BX_reg(context) = HIWORD(WineToApp(ptr));
645 CX_reg(context) = LOWORD(WineToApp(ptr));
646 RESET_CFLAG(context);
648 break;
650 default:
651 INT_BARF( context, 0x31 );
652 AX_reg(context) = 0x8001; /* unsupported function */
653 SET_CFLAG(context);
654 break;
657 #undef AppToWine
658 #undef WineToApp