Release 980601
[wine.git] / msdos / dpmi.c
blobd7128d9fe9d7ef6bd443cf7d7a5f2fafe60b40fa
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 "ldt.h"
12 #include "module.h"
13 #include "miscemu.h"
14 #include "drive.h"
15 #include "msdos.h"
16 #include "toolhelp.h"
17 #include "debug.h"
18 #include "selectors.h"
19 #include "thread.h"
20 #include "stackframe.h"
21 #include "callback.h"
23 #define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive())
25 void CreateBPB(int drive, BYTE *data, BOOL16 limited); /* defined in int21.c */
28 /* Structure for real-mode callbacks */
29 typedef struct
31 DWORD edi;
32 DWORD esi;
33 DWORD ebp;
34 DWORD reserved;
35 DWORD ebx;
36 DWORD edx;
37 DWORD ecx;
38 DWORD eax;
39 WORD fl;
40 WORD es;
41 WORD ds;
42 WORD fs;
43 WORD gs;
44 WORD ip;
45 WORD cs;
46 WORD sp;
47 WORD ss;
48 } REALMODECALL;
52 typedef struct tagRMCB {
53 DWORD address;
54 struct tagRMCB *next;
56 } RMCB;
58 static RMCB *FirstRMCB = NULL;
60 /**********************************************************************
61 * INT_GetRealModeContext
63 static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT *context )
65 EAX_reg(context) = call->eax;
66 EBX_reg(context) = call->ebx;
67 ECX_reg(context) = call->ecx;
68 EDX_reg(context) = call->edx;
69 ESI_reg(context) = call->esi;
70 EDI_reg(context) = call->edi;
71 EBP_reg(context) = call->ebp;
72 EFL_reg(context) = call->fl;
73 EIP_reg(context) = call->ip;
74 ESP_reg(context) = call->sp;
75 CS_reg(context) = call->cs;
76 DS_reg(context) = call->ds;
77 ES_reg(context) = call->es;
78 FS_reg(context) = call->fs;
79 GS_reg(context) = call->gs;
83 /**********************************************************************
84 * INT_SetRealModeContext
86 static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT *context )
88 call->eax = EAX_reg(context);
89 call->ebx = EBX_reg(context);
90 call->ecx = ECX_reg(context);
91 call->edx = EDX_reg(context);
92 call->esi = ESI_reg(context);
93 call->edi = EDI_reg(context);
94 call->ebp = EBP_reg(context);
95 call->fl = FL_reg(context);
96 call->ip = IP_reg(context);
97 call->sp = SP_reg(context);
98 call->cs = CS_reg(context);
99 call->ds = DS_reg(context);
100 call->es = ES_reg(context);
101 call->fs = FS_reg(context);
102 call->gs = GS_reg(context);
106 /**********************************************************************
107 * INT_DoRealModeInt
109 static void INT_DoRealModeInt( CONTEXT *context )
111 CONTEXT realmode_ctx;
112 REALMODECALL *call = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context),
113 DI_reg(context) );
114 INT_GetRealModeContext( call, &realmode_ctx );
116 RESET_CFLAG(context);
117 switch (BL_reg(context))
119 case 0x2f: /* int2f */
120 switch (AH_reg(&realmode_ctx))
122 case 0x15:
123 /* MSCDEX hook */
124 do_mscdex( &realmode_ctx );
125 break;
126 default:
127 SET_CFLAG(context);
128 break;
130 break;
131 case 0x21: /* int21 */
132 switch (AH_reg(&realmode_ctx))
134 case 0x52:
135 ES_reg(&realmode_ctx) = 0;
136 EBX_reg(&realmode_ctx) = 0;
137 break;
138 case 0x65:
139 switch (AL_reg(&realmode_ctx))
141 case 0x06:
142 {/* get collate table */
143 /* ES:DI is a REALMODE pointer to 5 byte dosmem
144 * we fill that with 0x6, realmode pointer to collateTB
146 char *table = DOSMEM_MapRealToLinear(
147 MAKELONG(EDI_reg(&realmode_ctx),ES_reg(&realmode_ctx)));
148 *(BYTE*)table = 0x06;
149 *(DWORD*)(table+1) = DOSMEM_CollateTable;
150 CX_reg(&realmode_ctx) = 258;/*FIXME: size of table?*/
151 break;
153 default:
154 SET_CFLAG(context);
155 break;
157 break;
158 case 0x44:
159 switch (AL_reg(&realmode_ctx))
161 case 0x0D:
162 {/* generic block device request */
163 BYTE *dataptr = DOSMEM_MapRealToLinear(
164 MAKELONG(EDX_reg(&realmode_ctx),DS_reg(&realmode_ctx)));
165 int drive = DOS_GET_DRIVE(BL_reg(&realmode_ctx));
166 if (CH_reg(&realmode_ctx) != 0x08)
168 SET_CFLAG(context);
169 break;
171 switch (CL_reg(&realmode_ctx))
173 case 0x66:
175 char label[12],fsname[9],path[4];
176 DWORD serial;
178 strcpy(path,"x:\\");path[0]=drive+'A';
179 GetVolumeInformation32A(path,label,12,&serial,NULL,NULL,fsname,9);
180 *(WORD*)dataptr = 0;
181 memcpy(dataptr+2,&serial,4);
182 memcpy(dataptr+6,label ,11);
183 memcpy(dataptr+17,fsname,8);
184 break;
186 case 0x60: /* get device parameters */
187 /* used by defrag.exe of win95 */
188 memset(dataptr, 0, 0x26);
189 dataptr[0] = 0x04;
190 dataptr[6] = 0; /* media type */
191 if (drive > 1)
193 dataptr[1] = 0x05; /* fixed disk */
194 setword(&dataptr[2], 0x01); /* non removable */
195 setword(&dataptr[4], 0x300); /* # of cylinders */
197 else
199 dataptr[1] = 0x07; /* block dev, floppy */
200 setword(&dataptr[2], 0x02); /* removable */
201 setword(&dataptr[4], 80); /* # of cylinders */
203 CreateBPB(drive, &dataptr[7], FALSE);
204 break;
205 default:
206 SET_CFLAG(context);
207 break;
210 break;
211 default:
212 SET_CFLAG(context);
213 break;
215 break;
216 default:
217 SET_CFLAG(context);
218 break;
220 break;
221 default:
222 SET_CFLAG(context);
223 break;
226 if (EFL_reg(context)&1) {
227 FIXME(int31,"%02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
228 BL_reg(context), EAX_reg(&realmode_ctx), EBX_reg(&realmode_ctx),
229 ECX_reg(&realmode_ctx), EDX_reg(&realmode_ctx));
230 FIXME(int31," ESI=%08lx EDI=%08lx DS=%04lx ES=%04lx\n",
231 ESI_reg(&realmode_ctx), EDI_reg(&realmode_ctx),
232 DS_reg(&realmode_ctx), ES_reg(&realmode_ctx) );
234 INT_SetRealModeContext( call, &realmode_ctx );
238 static void CallRMProcFar( CONTEXT *context )
240 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) );
241 CONTEXT context16;
242 THDB *thdb = THREAD_Current();
243 WORD argsize, sel;
244 LPVOID addr;
245 SEGPTR seg_addr;
247 TRACE(int31, "RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
248 p->eax, p->ebx, p->ecx, p->edx);
249 TRACE(int31, " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments\n",
250 p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context) );
252 if (!(p->cs) && !(p->ip)) { /* remove this check
253 if Int21/6501 case map function
254 has been implemented */
255 SET_CFLAG(context);
256 return;
258 INT_GetRealModeContext(p, &context16);
260 addr = DOSMEM_MapRealToLinear(MAKELONG(p->ip, p->cs));
261 sel = SELECTOR_AllocBlock( addr, 0x10000, SEGMENT_CODE, FALSE, FALSE );
262 seg_addr = PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
264 CS_reg(&context16) = HIWORD(seg_addr);
265 IP_reg(&context16) = LOWORD(seg_addr);
266 EBP_reg(&context16) = OFFSETOF( thdb->cur_stack )
267 + (WORD)&((STACK16FRAME*)0)->bp;
269 argsize = CX_reg(context)*sizeof(WORD);
270 memcpy( ((LPBYTE)THREAD_STACK16(thdb))-argsize,
271 (LPBYTE)PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context))+6, argsize );
273 Callbacks->CallRegisterShortProc(&context16, argsize);
275 UnMapLS(seg_addr);
276 INT_SetRealModeContext(p, &context16);
280 void WINAPI RMCallbackProc( FARPROC16 pmProc, REALMODECALL *rmc )
282 CONTEXT ctx;
283 INT_GetRealModeContext(rmc, &ctx);
284 Callbacks->CallRegisterShortProc(&ctx, 0);
288 static void AllocRMCB( CONTEXT *context )
290 RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
291 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) );
292 UINT16 uParagraph;
294 FIXME(int31, "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", p->eax, p->ebx, p->ecx, p->edx);
295 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);
296 FIXME(int31, " Function to call: %04x:%04x\n",
297 (WORD)DS_reg(context), SI_reg(context) );
299 if (NewRMCB)
301 LPVOID RMCBmem = DOSMEM_GetBlock(20, &uParagraph);
302 LPBYTE p = RMCBmem;
304 *p++ = 0x68; /* pushl */
305 *(FARPROC16 *)p =
306 PTR_SEG_OFF_TO_LIN(ES_reg(context), SI_reg(context)); /* pmode proc to call */
307 p+=4;
308 *p++ = 0x68; /* pushl */
309 *(LPVOID *)p =
310 PTR_SEG_OFF_TO_LIN(ES_reg(context), DI_reg(context));
311 p+=4;
312 *p++ = 0x9a; /* lcall */
313 *(FARPROC16 *)p = (FARPROC16)RMCallbackProc; /* FIXME ? */
314 p+=4;
315 GET_CS(*(WORD *)p);
316 p+=2;
317 *p++=0xc3; /* retf */
318 NewRMCB->address = MAKELONG(0, uParagraph);
319 NewRMCB->next = FirstRMCB;
320 FirstRMCB = NewRMCB;
321 CX_reg(context) = uParagraph;
322 DX_reg(context) = 0;
324 else
326 AX_reg(context) = 0x8015; /* callback unavailable */
327 SET_CFLAG(context);
332 static void FreeRMCB( CONTEXT *context )
334 RMCB *CurrRMCB = FirstRMCB;
335 RMCB *PrevRMCB = NULL;
337 FIXME(int31, "callback address: %04x:%04x\n",
338 CX_reg(context), DX_reg(context));
340 while (CurrRMCB && (CurrRMCB->address != MAKELONG(DX_reg(context), CX_reg(context))))
342 PrevRMCB = CurrRMCB;
343 CurrRMCB = CurrRMCB->next;
345 if (CurrRMCB)
347 if (PrevRMCB)
348 PrevRMCB->next = CurrRMCB->next;
349 else
350 FirstRMCB = CurrRMCB->next;
351 DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address));
352 HeapFree(GetProcessHeap(), 0, CurrRMCB);
354 else
356 AX_reg(context) = 0x8024; /* invalid callback address */
357 SET_CFLAG(context);
362 /**********************************************************************
363 * INT_Int31Handler
365 * Handler for int 31h (DPMI).
367 void WINAPI INT_Int31Handler( CONTEXT *context )
369 DWORD dw;
370 BYTE *ptr;
372 RESET_CFLAG(context);
373 switch(AX_reg(context))
375 case 0x0000: /* Allocate LDT descriptors */
376 TRACE(int31,"allocate LDT descriptors (%d)\n",CX_reg(context));
377 if (!(AX_reg(context) = AllocSelectorArray( CX_reg(context) )))
379 TRACE(int31,"failed\n");
380 AX_reg(context) = 0x8011; /* descriptor unavailable */
381 SET_CFLAG(context);
383 TRACE(int31,"success, array starts at 0x%04x\n",AX_reg(context));
384 break;
386 case 0x0001: /* Free LDT descriptor */
387 TRACE(int31,"free LDT descriptor (0x%04x)\n",BX_reg(context));
388 if (FreeSelector( BX_reg(context) ))
390 AX_reg(context) = 0x8022; /* invalid selector */
391 SET_CFLAG(context);
393 else
395 /* If a segment register contains the selector being freed, */
396 /* set it to zero. */
397 if (!((DS_reg(context)^BX_reg(context)) & ~3)) DS_reg(context) = 0;
398 if (!((ES_reg(context)^BX_reg(context)) & ~3)) ES_reg(context) = 0;
399 if (!((FS_reg(context)^BX_reg(context)) & ~3)) FS_reg(context) = 0;
400 if (!((GS_reg(context)^BX_reg(context)) & ~3)) GS_reg(context) = 0;
402 break;
404 case 0x0002: /* Real mode segment to descriptor */
405 TRACE(int31,"real mode segment to descriptor (0x%04x)\n",BX_reg(context));
407 WORD entryPoint = 0; /* KERNEL entry point for descriptor */
408 switch(BX_reg(context))
410 case 0x0000: entryPoint = 183; break; /* __0000H */
411 case 0x0040: entryPoint = 193; break; /* __0040H */
412 case 0xa000: entryPoint = 174; break; /* __A000H */
413 case 0xb000: entryPoint = 181; break; /* __B000H */
414 case 0xb800: entryPoint = 182; break; /* __B800H */
415 case 0xc000: entryPoint = 195; break; /* __C000H */
416 case 0xd000: entryPoint = 179; break; /* __D000H */
417 case 0xe000: entryPoint = 190; break; /* __E000H */
418 case 0xf000: entryPoint = 194; break; /* __F000H */
419 default:
420 AX_reg(context) = DOSMEM_AllocSelector(BX_reg(context));
421 break;
423 if (entryPoint)
424 AX_reg(context) = LOWORD(NE_GetEntryPoint(
425 GetModuleHandle16( "KERNEL" ),
426 entryPoint ));
428 break;
430 case 0x0003: /* Get next selector increment */
431 TRACE(int31,"get selector increment (__AHINCR)\n");
432 AX_reg(context) = __AHINCR;
433 break;
435 case 0x0004: /* Lock selector (not supported) */
436 FIXME(int31,"lock selector not supported\n");
437 AX_reg(context) = 0; /* FIXME: is this a correct return value? */
438 break;
440 case 0x0005: /* Unlock selector (not supported) */
441 FIXME(int31,"unlock selector not supported\n");
442 AX_reg(context) = 0; /* FIXME: is this a correct return value? */
443 break;
445 case 0x0006: /* Get selector base address */
446 TRACE(int31,"get selector base address (0x%04x)\n",BX_reg(context));
447 if (!(dw = GetSelectorBase( BX_reg(context) )))
449 AX_reg(context) = 0x8022; /* invalid selector */
450 SET_CFLAG(context);
452 else
454 CX_reg(context) = HIWORD(dw);
455 DX_reg(context) = LOWORD(dw);
457 break;
459 case 0x0007: /* Set selector base address */
460 TRACE(int31,"set selector base address (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context)));
461 SetSelectorBase( BX_reg(context),
462 MAKELONG( DX_reg(context), CX_reg(context) ) );
463 break;
465 case 0x0008: /* Set selector limit */
466 TRACE(int31,"set selector limit (0x%04x,0x%08lx)\n",BX_reg(context),MAKELONG(DX_reg(context),CX_reg(context)));
467 SetSelectorLimit( BX_reg(context),
468 MAKELONG( DX_reg(context), CX_reg(context) ) );
469 break;
471 case 0x0009: /* Set selector access rights */
472 TRACE(int31,"set selector access rights(0x%04x,0x%04x)\n",BX_reg(context),CX_reg(context));
473 SelectorAccessRights( BX_reg(context), 1, CX_reg(context) );
474 break;
476 case 0x000a: /* Allocate selector alias */
477 TRACE(int31,"allocate selector alias (0x%04x)\n",BX_reg(context));
478 if (!(AX_reg(context) = AllocCStoDSAlias( BX_reg(context) )))
480 AX_reg(context) = 0x8011; /* descriptor unavailable */
481 SET_CFLAG(context);
483 break;
485 case 0x000b: /* Get descriptor */
486 TRACE(int31,"get descriptor (0x%04x)\n",BX_reg(context));
488 ldt_entry entry;
489 LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
490 /* FIXME: should use ES:EDI for 32-bit clients */
491 LDT_EntryToBytes( PTR_SEG_OFF_TO_LIN( ES_reg(context),
492 DI_reg(context) ), &entry );
494 break;
496 case 0x000c: /* Set descriptor */
497 TRACE(int31,"set descriptor (0x%04x)\n",BX_reg(context));
499 ldt_entry entry;
500 LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context),
501 DI_reg(context) ), &entry );
502 LDT_SetEntry( SELECTOR_TO_ENTRY( BX_reg(context) ), &entry );
504 break;
506 case 0x000d: /* Allocate specific LDT descriptor */
507 FIXME(int31,"allocate descriptor (0x%04x), stub!\n",BX_reg(context));
508 AX_reg(context) = 0x8011; /* descriptor unavailable */
509 SET_CFLAG(context);
510 break;
511 case 0x0200: /* get real mode interrupt vector */
512 FIXME(int31,"get realmode interupt vector(0x%02x) unimplemented.\n",
513 BL_reg(context));
514 SET_CFLAG(context);
515 break;
516 case 0x0201: /* set real mode interrupt vector */
517 FIXME(int31, "set realmode interupt vector(0x%02x,0x%04x:0x%04x) unimplemented\n", BL_reg(context),CX_reg(context),DX_reg(context));
518 SET_CFLAG(context);
519 break;
520 case 0x0204: /* Get protected mode interrupt vector */
521 TRACE(int31,"get protected mode interrupt handler (0x%02x), stub!\n",BL_reg(context));
522 dw = (DWORD)INT_GetHandler( BL_reg(context) );
523 CX_reg(context) = HIWORD(dw);
524 DX_reg(context) = LOWORD(dw);
525 break;
527 case 0x0205: /* Set protected mode interrupt vector */
528 TRACE(int31,"set protected mode interrupt handler (0x%02x,0x%08lx), stub!\n",BL_reg(context),PTR_SEG_OFF_TO_LIN(CX_reg(context),DX_reg(context)));
529 INT_SetHandler( BL_reg(context),
530 (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( CX_reg(context),
531 DX_reg(context) ));
532 break;
534 case 0x0300: /* Simulate real mode interrupt */
535 INT_DoRealModeInt( context );
536 break;
538 case 0x0301: /* Call real mode procedure with far return */
539 CallRMProcFar( context );
540 break;
542 case 0x0302: /* Call real mode procedure with interrupt return */
544 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(context), DI_reg(context) );
545 FIXME(int31, "RealModeCallIret: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n", p->eax, p->ebx, p->ecx, p->edx);
546 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 );
547 SET_CFLAG(context);
549 break;
551 case 0x0303: /* Allocate Real Mode Callback Address */
552 AllocRMCB( context );
553 break;
555 case 0x0304: /* Free Real Mode Callback Address */
556 FreeRMCB( context );
557 break;
559 case 0x0400: /* Get DPMI version */
560 TRACE(int31,"get DPMI version\n");
562 SYSTEM_INFO si;
564 GetSystemInfo(&si);
565 AX_reg(context) = 0x005a; /* DPMI version 0.90 */
566 BX_reg(context) = 0x0005; /* Flags: 32-bit, virtual memory */
567 CL_reg(context) = si.wProcessorLevel;
568 DX_reg(context) = 0x0102; /* Master/slave interrupt controller base*/
569 break;
571 case 0x0500: /* Get free memory information */
572 TRACE(int31,"get free memory information\n");
574 MEMMANINFO mmi;
576 mmi.dwSize = sizeof(mmi);
577 MemManInfo(&mmi);
578 ptr = (BYTE *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context));
579 /* the layout is just the same as MEMMANINFO, but without
580 * the dwSize entry.
582 memcpy(ptr,((char*)&mmi)+4,sizeof(mmi)-4);
583 break;
585 case 0x0501: /* Allocate memory block */
586 TRACE(int31,"allocate memory block (%ld)\n",MAKELONG(CX_reg(context),BX_reg(context)));
587 if (!(ptr = (BYTE *)VirtualAlloc(NULL, MAKELONG(CX_reg(context), BX_reg(context)), MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
589 AX_reg(context) = 0x8012; /* linear memory not available */
590 SET_CFLAG(context);
592 else
594 BX_reg(context) = SI_reg(context) = HIWORD(ptr);
595 CX_reg(context) = DI_reg(context) = LOWORD(ptr);
597 break;
599 case 0x0502: /* Free memory block */
600 TRACE(int31,"free memory block (0x%08lx)\n",MAKELONG(DI_reg(context),SI_reg(context)));
601 VirtualFree((void *)MAKELONG(DI_reg(context), SI_reg(context)), 0, MEM_RELEASE);
602 break;
604 case 0x0503: /* Resize memory block */
605 TRACE(int31,"resize memory block (0x%08lx,%ld)\n",MAKELONG(DI_reg(context),SI_reg(context)),MAKELONG(CX_reg(context),BX_reg(context)));
606 if (!(ptr = (BYTE *)HeapReAlloc( GetProcessHeap(), 0,
607 (void *)MAKELONG(DI_reg(context),SI_reg(context)),
608 MAKELONG(CX_reg(context),BX_reg(context)))))
610 AX_reg(context) = 0x8012; /* linear memory not available */
611 SET_CFLAG(context);
613 else
615 BX_reg(context) = SI_reg(context) = HIWORD(ptr);
616 CX_reg(context) = DI_reg(context) = LOWORD(ptr);
618 break;
620 case 0x0600: /* Lock linear region */
621 FIXME(int31,"lock linear region unimplemented\n");
622 break; /* Just ignore it */
624 case 0x0601: /* Unlock linear region */
625 FIXME(int31,"unlock linear region unimplemented\n");
626 break; /* Just ignore it */
628 case 0x0602: /* Unlock real-mode region */
629 FIXME(int31,"unlock realmode region unimplemented\n");
630 break; /* Just ignore it */
632 case 0x0603: /* Lock real-mode region */
633 FIXME(int31,"lock realmode region unimplemented\n");
634 break; /* Just ignore it */
636 case 0x0604: /* Get page size */
637 TRACE(int31,"get pagesize\n");
638 BX_reg(context) = 0;
639 CX_reg(context) = VIRTUAL_GetPageSize();
640 break;
642 case 0x0702: /* Mark page as demand-paging candidate */
643 FIXME(int31,"mark page as demand-paging candidate\n");
644 break; /* Just ignore it */
646 case 0x0703: /* Discard page contents */
647 FIXME(int31,"discard page contents\n");
648 break; /* Just ignore it */
650 case 0x0800: /* Physical address mapping */
651 FIXME(int31,"map real to linear (0x%08lx)\n",MAKELONG(CX_reg(context),BX_reg(context)));
652 if(!(ptr=DOSMEM_MapRealToLinear(MAKELONG(CX_reg(context),BX_reg(context)))))
654 AX_reg(context) = 0x8021;
655 SET_CFLAG(context);
657 else
659 BX_reg(context) = HIWORD(ptr);
660 CX_reg(context) = LOWORD(ptr);
661 RESET_CFLAG(context);
663 break;
665 default:
666 INT_BARF( context, 0x31 );
667 AX_reg(context) = 0x8001; /* unsupported function */
668 SET_CFLAG(context);
669 break;