wined3d: Implement shadow sampling for the ARB shader backend.
[wine.git] / dlls / krnl386.exe16 / int31.c
blobb5af832f4f29f7e97d5b943e5b578c174e31fd2d
1 /*
2 * DPMI 0.9 emulation
4 * Copyright 1995 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winternl.h"
26 #include "wine/winbase16.h"
27 #include "wownt32.h"
28 #include "kernel16_private.h"
29 #include "dosexe.h"
31 #include "excpt.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(int31);
36 static void* lastvalloced = NULL;
38 /**********************************************************************
39 * DPMI_xalloc
40 * special virtualalloc, allocates linearly monoton growing memory.
41 * (the usual VirtualAlloc does not satisfy that restriction)
43 static LPVOID DPMI_xalloc( DWORD len )
45 LPVOID ret;
46 LPVOID oldlastv = lastvalloced;
48 if (lastvalloced)
50 int xflag = 0;
52 ret = NULL;
53 while (!ret)
55 ret = VirtualAlloc( lastvalloced, len,
56 MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE );
57 if (!ret)
58 lastvalloced = (char *) lastvalloced + 0x10000;
60 /* we failed to allocate one in the first round.
61 * try non-linear
63 if (!xflag && (lastvalloced<oldlastv))
65 /* wrapped */
66 FIXME( "failed to allocate linearly growing memory (%lu bytes), "
67 "using non-linear growing...\n", len );
68 xflag++;
71 /* if we even fail to allocate something in the next
72 * round, return NULL
74 if ((xflag==1) && (lastvalloced >= oldlastv))
75 xflag++;
77 if ((xflag==2) && (lastvalloced < oldlastv)) {
78 FIXME( "failed to allocate any memory of %lu bytes!\n", len );
79 return NULL;
83 else
85 ret = VirtualAlloc( NULL, len,
86 MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE );
89 lastvalloced = (LPVOID)(((DWORD)ret+len+0xffff)&~0xffff);
90 return ret;
93 /**********************************************************************
94 * DPMI_xfree
96 static void DPMI_xfree( LPVOID ptr )
98 VirtualFree( ptr, 0, MEM_RELEASE );
101 /**********************************************************************
102 * DPMI_xrealloc
104 * FIXME: perhaps we could grow this mapped area...
106 static LPVOID DPMI_xrealloc( LPVOID ptr, DWORD newsize )
108 MEMORY_BASIC_INFORMATION mbi;
110 if (ptr)
112 LPVOID newptr;
114 if (!VirtualQuery(ptr,&mbi,sizeof(mbi)))
116 FIXME( "realloc of DPMI_xallocd region %p?\n", ptr );
117 return NULL;
120 if (mbi.State == MEM_FREE)
122 FIXME( "realloc of DPMI_xallocd region %p?\n", ptr );
123 return NULL;
126 /* We do not shrink allocated memory. most reallocs
127 * only do grows anyway
129 if (newsize <= mbi.RegionSize)
130 return ptr;
132 newptr = DPMI_xalloc( newsize );
133 if (!newptr)
134 return NULL;
136 memcpy( newptr, ptr, mbi.RegionSize );
137 DPMI_xfree( ptr );
139 return newptr;
142 return DPMI_xalloc( newsize );
146 /**********************************************************************
147 * DOSVM_Int31Handler
149 * Handler for int 31h (DPMI).
151 void WINAPI DOSVM_Int31Handler( CONTEXT *context )
153 RESET_CFLAG(context);
154 switch(AX_reg(context))
156 case 0x0000: /* Allocate LDT descriptors */
157 TRACE( "allocate LDT descriptors (%d)\n", CX_reg(context) );
159 WORD sel = AllocSelectorArray16( CX_reg(context) );
160 if(!sel)
162 TRACE( "failed\n" );
163 SET_AX( context, 0x8011 ); /* descriptor unavailable */
164 SET_CFLAG( context );
166 else
168 TRACE( "success, array starts at 0x%04x\n", sel );
169 SET_AX( context, sel );
172 break;
174 case 0x0001: /* Free LDT descriptor */
175 TRACE( "free LDT descriptor (0x%04x)\n", BX_reg(context) );
176 if (FreeSelector16( BX_reg(context) ))
178 SET_AX( context, 0x8022 ); /* invalid selector */
179 SET_CFLAG( context );
181 else
183 /* If a segment register contains the selector being freed, */
184 /* set it to zero. */
185 if (!((context->SegDs^BX_reg(context)) & ~3)) context->SegDs = 0;
186 if (!((context->SegEs^BX_reg(context)) & ~3)) context->SegEs = 0;
187 if (!((context->SegFs^BX_reg(context)) & ~3)) context->SegFs = 0;
188 if (!((context->SegGs^BX_reg(context)) & ~3)) context->SegGs = 0;
190 break;
192 case 0x0002: /* Real mode segment to descriptor */
193 TRACE( "real mode segment to descriptor (0x%04x)\n", BX_reg(context) );
195 WORD entryPoint = 0; /* KERNEL entry point for descriptor */
196 switch(BX_reg(context))
198 case 0x0000: entryPoint = 183; break; /* __0000H */
199 case 0x0040: entryPoint = 193; break; /* __0040H */
200 case 0xa000: entryPoint = 174; break; /* __A000H */
201 case 0xb000: entryPoint = 181; break; /* __B000H */
202 case 0xb800: entryPoint = 182; break; /* __B800H */
203 case 0xc000: entryPoint = 195; break; /* __C000H */
204 case 0xd000: entryPoint = 179; break; /* __D000H */
205 case 0xe000: entryPoint = 190; break; /* __E000H */
206 case 0xf000: entryPoint = 194; break; /* __F000H */
207 default:
208 FIXME("Real mode segment (%x) to descriptor: no longer supported\n",
209 BX_reg(context));
210 SET_CFLAG( context );
211 break;
213 if (entryPoint)
215 FARPROC16 proc = GetProcAddress16( GetModuleHandle16( "KERNEL" ),
216 (LPCSTR)(ULONG_PTR)entryPoint );
217 SET_AX( context, LOWORD(proc) );
220 break;
222 case 0x0003: /* Get next selector increment */
223 TRACE("get selector increment (__AHINCR)\n");
224 context->Eax = __AHINCR;
225 break;
227 case 0x0004: /* Lock selector (not supported) */
228 FIXME("lock selector not supported\n");
229 context->Eax = 0; /* FIXME: is this a correct return value? */
230 break;
232 case 0x0005: /* Unlock selector (not supported) */
233 FIXME("unlock selector not supported\n");
234 context->Eax = 0; /* FIXME: is this a correct return value? */
235 break;
237 case 0x0006: /* Get selector base address */
238 TRACE( "get selector base address (0x%04x)\n", BX_reg(context) );
239 if (!ldt_is_valid( BX_reg(context) ))
241 context->Eax = 0x8022; /* invalid selector */
242 SET_CFLAG(context);
244 else
246 void *base = ldt_get_base( BX_reg(context) );
247 SET_CX( context, HIWORD(base) );
248 SET_DX( context, LOWORD(base) );
250 break;
252 case 0x0007: /* Set selector base address */
254 DWORD base = MAKELONG( DX_reg(context), CX_reg(context) );
255 WORD sel = BX_reg(context);
256 TRACE( "set selector base address (0x%04x,0x%08lx)\n", sel, base );
258 /* check if Win16 app wants to access lower 64K of DOS memory */
259 if (base < 0x10000) DOSMEM_MapDosLayout();
261 SetSelectorBase( sel, base );
263 break;
265 case 0x0008: /* Set selector limit */
267 DWORD limit = MAKELONG( DX_reg(context), CX_reg(context) );
268 TRACE( "set selector limit (0x%04x,0x%08lx)\n",
269 BX_reg(context), limit );
270 SetSelectorLimit16( BX_reg(context), limit );
272 break;
274 case 0x0009: /* Set selector access rights */
275 TRACE( "set selector access rights(0x%04x,0x%04x)\n",
276 BX_reg(context), CX_reg(context) );
277 SelectorAccessRights16( BX_reg(context), 1, CX_reg(context) );
278 break;
280 case 0x000a: /* Allocate selector alias */
281 TRACE( "allocate selector alias (0x%04x)\n", BX_reg(context) );
282 SET_AX( context, AllocCStoDSAlias16( BX_reg(context) ) );
283 if (!AX_reg(context))
285 SET_AX( context, 0x8011 ); /* descriptor unavailable */
286 SET_CFLAG(context);
288 break;
290 case 0x000b: /* Get descriptor */
291 TRACE( "get descriptor (0x%04x)\n", BX_reg(context) );
293 LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs,
294 context->Edi );
295 ldt_get_entry( BX_reg(context), entry );
297 break;
299 case 0x000c: /* Set descriptor */
300 TRACE( "set descriptor (0x%04x)\n", BX_reg(context) );
302 LDT_ENTRY *entry = CTX_SEG_OFF_TO_LIN( context, context->SegEs,
303 context->Edi );
304 if (!ldt_is_system( BX_reg(context) )) ldt_set_entry( BX_reg(context), *entry );
306 break;
308 case 0x000d: /* Allocate specific LDT descriptor */
309 FIXME( "allocate descriptor (0x%04x), stub!\n", BX_reg(context) );
310 SET_AX( context, 0x8011 ); /* descriptor unavailable */
311 SET_CFLAG( context );
312 break;
314 case 0x000e: /* Get Multiple Descriptors (1.0) */
315 FIXME( "get multiple descriptors - unimplemented\n" );
316 break;
318 case 0x000f: /* Set Multiple Descriptors (1.0) */
319 FIXME( "set multiple descriptors - unimplemented\n" );
320 break;
322 case 0x0100: /* Allocate DOS memory block */
323 TRACE( "allocate DOS memory block (0x%x paragraphs)\n", BX_reg(context) );
325 DWORD dw = GlobalDOSAlloc16( (DWORD)BX_reg(context) << 4 );
326 if (dw) {
327 SET_AX( context, HIWORD(dw) );
328 SET_DX( context, LOWORD(dw) );
329 } else {
330 SET_AX( context, 0x0008 ); /* insufficient memory */
331 SET_BX( context, DOSMEM_Available() >> 4 );
332 SET_CFLAG(context);
334 break;
337 case 0x0101: /* Free DOS memory block */
338 TRACE( "free DOS memory block (0x%04x)\n", DX_reg(context) );
340 WORD error = GlobalDOSFree16( DX_reg(context) );
341 if (error) {
342 SET_AX( context, 0x0009 ); /* memory block address invalid */
343 SET_CFLAG( context );
346 break;
348 case 0x0102: /* Resize DOS Memory Block */
349 FIXME( "resize DOS memory block (0x%04x, 0x%x paragraphs) - unimplemented\n",
350 DX_reg(context), BX_reg(context) );
351 break;
353 case 0x0200: /* get real mode interrupt vector */
354 TRACE( "get realmode interrupt vector (0x%02x) - not supported\n",
355 BL_reg(context) );
356 SET_CX( context, 0 );
357 SET_DX( context, 0 );
358 break;
360 case 0x0201: /* set real mode interrupt vector */
361 TRACE( "set realmode interrupt vector (0x%02x, 0x%04x:0x%04x) - not supported\n",
362 BL_reg(context), CX_reg(context), DX_reg(context) );
363 break;
365 case 0x0202: /* Get Processor Exception Handler Vector */
366 FIXME( "Get Processor Exception Handler Vector (0x%02x)\n",
367 BL_reg(context) );
368 SET_CX( context, 0 );
369 SET_DX( context, 0 );
370 break;
372 case 0x0203: /* Set Processor Exception Handler Vector */
373 FIXME( "Set Processor Exception Handler Vector (0x%02x)\n",
374 BL_reg(context) );
375 break;
377 case 0x0204: /* Get protected mode interrupt vector */
378 TRACE("get protected mode interrupt handler (0x%02x)\n",
379 BL_reg(context));
381 FARPROC16 handler = DOSVM_GetPMHandler16( BL_reg(context) );
382 SET_CX( context, SELECTOROF(handler) );
383 SET_DX( context, OFFSETOF(handler) );
385 break;
387 case 0x0205: /* Set protected mode interrupt vector */
388 TRACE("set protected mode interrupt handler (0x%02x,0x%04x:0x%08lx)\n",
389 BL_reg(context), CX_reg(context), context->Edx);
391 FARPROC16 handler;
392 handler = (FARPROC16)MAKESEGPTR( CX_reg(context), DX_reg(context));
393 DOSVM_SetPMHandler16( BL_reg(context), handler );
395 break;
397 case 0x0300: /* Simulate real mode interrupt */
398 TRACE( "Simulate real mode interrupt %02x - not supported\n", BL_reg(context));
399 break;
401 case 0x0301: /* Call real mode procedure with far return */
402 TRACE( "Call real mode procedure with far return - not supported\n" );
403 break;
405 case 0x0302: /* Call real mode procedure with interrupt return */
406 TRACE( "Call real mode procedure with interrupt return - not supported\n" );
407 break;
409 case 0x0303: /* Allocate Real Mode Callback Address */
410 TRACE( "Allocate real mode callback address - not supported\n" );
411 break;
413 case 0x0304: /* Free Real Mode Callback Address */
414 TRACE( "Free real mode callback address - not supported\n" );
415 break;
417 case 0x0305: /* Get State Save/Restore Addresses */
418 TRACE("get state save/restore addresses - no longer supported\n");
419 /* we probably won't need this kind of state saving */
420 SET_AX( context, 0 );
421 /* real mode */
422 SET_BX( context, 0 );
423 SET_CX( context, 0 );
424 /* protected mode */
425 SET_SI( context, 0 );
426 context->Edi = 0;
427 break;
429 case 0x0306: /* Get Raw Mode Switch Addresses */
430 TRACE("get raw mode switch addresses - no longer supported\n");
431 /* real mode */
432 SET_BX( context, 0 );
433 SET_CX( context, 0 );
434 /* protected mode */
435 SET_SI( context, 0 );
436 context->Edi = 0;
437 break;
439 case 0x0400: /* Get DPMI version */
440 TRACE("get DPMI version\n");
442 SYSTEM_INFO si;
444 GetSystemInfo(&si);
445 SET_AX( context, 0x005a ); /* DPMI version 0.90 */
446 SET_BX( context, 0x0005 ); /* Flags: 32-bit, virtual memory */
447 SET_CL( context, si.wProcessorLevel );
448 SET_DX( context, 0x0870 ); /* Interrupt controller base */
450 break;
452 case 0x0401: /* Get DPMI Capabilities (1.0) */
453 FIXME( "get dpmi capabilities - unimplemented\n");
454 break;
456 case 0x0500: /* Get free memory information */
457 TRACE("get free memory information\n");
459 MEMORYSTATUS status;
460 SYSTEM_BASIC_INFORMATION sbi;
462 /* the layout is just the same as MEMMANINFO, but without
463 * the dwSize entry.
465 struct
467 DWORD dwLargestFreeBlock;
468 DWORD dwMaxPagesAvailable;
469 DWORD dwMaxPagesLockable;
470 DWORD dwTotalLinearSpace;
471 DWORD dwTotalUnlockedPages;
472 DWORD dwFreePages;
473 DWORD dwTotalPages;
474 DWORD dwFreeLinearSpace;
475 DWORD dwSwapFilePages;
476 WORD wPageSize;
477 } *info = CTX_SEG_OFF_TO_LIN( context, context->SegEs, context->Edi );
479 GlobalMemoryStatus( &status );
480 NtQuerySystemInformation( SystemBasicInformation, &sbi, sizeof(sbi), NULL );
482 info->wPageSize = sbi.PageSize;
483 info->dwLargestFreeBlock = status.dwAvailVirtual;
484 info->dwMaxPagesAvailable = info->dwLargestFreeBlock / info->wPageSize;
485 info->dwMaxPagesLockable = info->dwMaxPagesAvailable;
486 info->dwTotalLinearSpace = status.dwTotalVirtual / info->wPageSize;
487 info->dwTotalUnlockedPages = info->dwTotalLinearSpace;
488 info->dwFreePages = info->dwMaxPagesAvailable;
489 info->dwTotalPages = info->dwTotalLinearSpace;
490 info->dwFreeLinearSpace = info->dwMaxPagesAvailable;
491 info->dwSwapFilePages = status.dwTotalPageFile / info->wPageSize;
492 break;
495 case 0x0501: /* Allocate memory block */
497 DWORD size = MAKELONG( CX_reg(context), BX_reg(context) );
498 BYTE *ptr;
500 TRACE( "allocate memory block (%lu bytes)\n", size );
502 ptr = DPMI_xalloc( size );
503 if (!ptr)
505 SET_AX( context, 0x8012 ); /* linear memory not available */
506 SET_CFLAG(context);
508 else
510 SET_BX( context, HIWORD(ptr) );
511 SET_CX( context, LOWORD(ptr) );
512 SET_SI( context, HIWORD(ptr) );
513 SET_DI( context, LOWORD(ptr) );
515 break;
518 case 0x0502: /* Free memory block */
520 DWORD handle = MAKELONG( DI_reg(context), SI_reg(context) );
521 TRACE( "free memory block (0x%08lx)\n", handle );
522 DPMI_xfree( (void *)handle );
524 break;
526 case 0x0503: /* Resize memory block */
528 DWORD size = MAKELONG( CX_reg(context), BX_reg(context) );
529 DWORD handle = MAKELONG( DI_reg(context), SI_reg(context) );
530 BYTE *ptr;
532 TRACE( "resize memory block (0x%08lx, %lu bytes)\n", handle, size );
534 ptr = DPMI_xrealloc( (void *)handle, size );
535 if (!ptr)
537 SET_AX( context, 0x8012 ); /* linear memory not available */
538 SET_CFLAG(context);
539 } else {
540 SET_BX( context, HIWORD(ptr) );
541 SET_CX( context, LOWORD(ptr) );
542 SET_SI( context, HIWORD(ptr) );
543 SET_DI( context, LOWORD(ptr) );
546 break;
548 case 0x0507: /* Set page attributes (1.0) */
549 FIXME( "set page attributes - unimplemented\n" );
550 break; /* Just ignore it */
552 case 0x0600: /* Lock linear region */
553 TRACE( "lock linear region - ignored (no paging)\n" );
554 break;
556 case 0x0601: /* Unlock linear region */
557 TRACE( "unlock linear region - ignored (no paging)\n" );
558 break;
560 case 0x0602: /* Mark real mode region as pageable */
561 TRACE( "mark real mode region as pageable - ignored (no paging)\n" );
562 break;
564 case 0x0603: /* Relock real mode region */
565 TRACE( "relock real mode region - ignored (no paging)\n" );
566 break;
568 case 0x0604: /* Get page size */
570 SYSTEM_BASIC_INFORMATION info;
571 TRACE("get pagesize\n");
572 NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
573 SET_BX( context, HIWORD(info.PageSize) );
574 SET_CX( context, LOWORD(info.PageSize) );
575 break;
577 case 0x0700: /* Mark pages as paging candidates */
578 TRACE( "mark pages as paging candidates - ignored (no paging)\n" );
579 break;
581 case 0x0701: /* Discard pages */
582 TRACE( "discard pages - ignored (no paging)\n" );
583 break;
585 case 0x0702: /* Mark page as demand-paging candidate */
586 TRACE( "mark page as demand-paging candidate - ignored (no paging)\n" );
587 break;
589 case 0x0703: /* Discard page contents */
590 TRACE( "discard page contents - ignored (no paging)\n" );
591 break;
593 case 0x0800: /* Physical address mapping */
594 FIXME( "physical address mapping (0x%08lx) - unimplemented\n",
595 MAKELONG(CX_reg(context),BX_reg(context)) );
596 break;
598 case 0x0900: /* Get and Disable Virtual Interrupt State */
599 TRACE( "Get and Disable Virtual Interrupt State - not supported\n" );
600 break;
602 case 0x0901: /* Get and Enable Virtual Interrupt State */
603 TRACE( "Get and Enable Virtual Interrupt State - not supported\n" );
604 break;
606 case 0x0902: /* Get Virtual Interrupt State */
607 TRACE( "Get Virtual Interrupt State - not supported\n" );
608 break;
610 case 0x0e00: /* Get Coprocessor Status (1.0) */
612 * Return status in AX bits:
613 * B0 - MPv (MP bit in the virtual MSW/CR0)
614 * 0 = numeric coprocessor is disabled for this client
615 * 1 = numeric coprocessor is enabled for this client
616 * B1 - EMv (EM bit in the virtual MSW/CR0)
617 * 0 = client is not emulating coprocessor instructions
618 * 1 = client is emulating coprocessor instructions
619 * B2 - MPr (MP bit from the actual MSW/CR0)
620 * 0 = numeric coprocessor is not present
621 * 1 = numeric coprocessor is present
622 * B3 - EMr (EM bit from the actual MSW/CR0)
623 * 0 = host is not emulating coprocessor instructions
624 * 1 = host is emulating coprocessor instructions
625 * B4-B7 - coprocessor type
626 * 00H = no coprocessor
627 * 02H = 80287
628 * 03H = 80387
629 * 04H = 80486 with numeric coprocessor
630 * 05H-0FH = reserved for future numeric processors
632 TRACE( "Get Coprocessor Status\n" );
633 SET_AX( context, 69 ); /* 486, coprocessor present and enabled */
634 break;
636 case 0x0e01: /* Set Coprocessor Emulation (1.0) */
638 * See function 0x0e00.
639 * BX bit B0 is new value for MPv.
640 * BX bit B1 is new value for EMv.
642 if (BX_reg(context) != 1)
643 FIXME( "Set Coprocessor Emulation to %d - unimplemented\n",
644 BX_reg(context) );
645 else
646 TRACE( "Set Coprocessor Emulation - ignored\n" );
647 break;
649 default:
650 INT_BARF( context, 0x31 );
651 SET_AX( context, 0x8001 ); /* unsupported function */
652 SET_CFLAG(context);
653 break;