Release 951226
[wine/gsoc-2012-control.git] / miscemu / dpmi.c
blob1ba8f1a42bac40c69f8bf8b683dc769bb3a80223
1 /*
2 * DPMI 0.9 emulation
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "windows.h"
11 #include "ldt.h"
12 #include "registers.h"
13 #include "wine.h"
14 #include "miscemu.h"
15 #include "stddebug.h"
16 /* #define DEBUG_INT */
17 #include "debug.h"
20 /* Structure for real-mode callbacks */
21 typedef struct
23 DWORD edi;
24 DWORD esi;
25 DWORD ebp;
26 DWORD reserved;
27 DWORD ebx;
28 DWORD edx;
29 DWORD ecx;
30 DWORD eax;
31 WORD flags;
32 WORD es;
33 WORD ds;
34 WORD fs;
35 WORD gs;
36 WORD ip;
37 WORD cs;
38 WORD sp;
39 WORD ss;
40 } REALMODECALL;
42 /**********************************************************************
43 * INT_Int31Handler
45 * Handler for int 31h (DPMI).
47 void INT_Int31Handler( struct sigcontext_struct context )
49 DWORD dw;
50 BYTE *ptr;
52 RESET_CFLAG(&context);
53 switch(AX_reg(&context))
55 case 0x0000: /* Allocate LDT descriptors */
56 if (!(AX_reg(&context) = AllocSelectorArray( CX_reg(&context) )))
58 AX_reg(&context) = 0x8011; /* descriptor unavailable */
59 SET_CFLAG(&context);
61 break;
63 case 0x0001: /* Free LDT descriptor */
64 if (FreeSelector( BX_reg(&context) ))
66 AX_reg(&context) = 0x8022; /* invalid selector */
67 SET_CFLAG(&context);
69 break;
71 case 0x0003: /* Get next selector increment */
72 AX_reg(&context) = __AHINCR;
73 break;
75 case 0x0004: /* Lock selector (not supported) */
76 AX_reg(&context) = 0; /* FIXME: is this a correct return value? */
77 break;
79 case 0x0005: /* Unlock selector (not supported) */
80 AX_reg(&context) = 0; /* FIXME: is this a correct return value? */
81 break;
83 case 0x0006: /* Get selector base address */
84 if (!(dw = GetSelectorBase( BX_reg(&context) )))
86 AX_reg(&context) = 0x8022; /* invalid selector */
87 SET_CFLAG(&context);
89 else
91 CX_reg(&context) = HIWORD(dw);
92 DX_reg(&context) = LOWORD(dw);
94 break;
96 case 0x0007: /* Set selector base address */
97 SetSelectorBase( BX_reg(&context),
98 MAKELONG( DX_reg(&context), CX_reg(&context) ) );
99 break;
101 case 0x0008: /* Set selector limit */
102 SetSelectorLimit( BX_reg(&context),
103 MAKELONG( DX_reg(&context), CX_reg(&context) ) );
104 break;
106 case 0x0009: /* Set selector access rights */
107 SelectorAccessRights( BX_reg(&context), 1, CX_reg(&context) );
109 case 0x000a: /* Allocate selector alias */
110 if (!(AX_reg(&context) = AllocCStoDSAlias( BX_reg(&context) )))
112 AX_reg(&context) = 0x8011; /* descriptor unavailable */
113 SET_CFLAG(&context);
115 break;
117 case 0x000b: /* Get descriptor */
119 ldt_entry entry;
120 LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(&context) ), &entry );
121 /* FIXME: should use ES:EDI for 32-bit clients */
122 LDT_EntryToBytes( PTR_SEG_OFF_TO_LIN( ES_reg(&context),
123 DI_reg(&context) ), &entry );
125 break;
127 case 0x000c: /* Set descriptor */
129 ldt_entry entry;
130 LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(&context),
131 DI_reg(&context) ), &entry );
132 LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(&context) ), &entry );
134 break;
136 case 0x000d: /* Allocate specific LDT descriptor */
137 AX_reg(&context) = 0x8011; /* descriptor unavailable */
138 SET_CFLAG(&context);
139 break;
141 case 0x0204: /* Get protected mode interrupt vector */
142 dw = (DWORD)INT_GetHandler( BL_reg(&context) );
143 CX_reg(&context) = HIWORD(dw);
144 DX_reg(&context) = LOWORD(dw);
145 break;
147 case 0x0205: /* Set protected mode interrupt vector */
148 INT_SetHandler( BL_reg(&context),
149 (SEGPTR)MAKELONG( DX_reg(&context), CX_reg(&context) ));
150 break;
152 case 0x0300: /* Simulate real mode interrupt
153 * Interrupt number is in BL, flags are in BH
154 * ES:DI points to real-mode call structure
155 * Currently we just print it out and return error.
158 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(&context), DI_reg(&context) );
159 fprintf(stdnimp,
160 "RealModeInt %02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
161 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x\n",
162 BL_reg(&context), p->eax, p->ebx, p->ecx, p->edx,
163 p->esi, p->edi, p->es, p->ds );
164 SET_CFLAG(&context);
166 break;
168 case 0x0301: /* Call real mode procedure with far return */
170 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(&context), DI_reg(&context) );
171 fprintf(stdnimp,
172 "RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
173 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n",
174 p->eax, p->ebx, p->ecx, p->edx,
175 p->esi, p->edi, p->es, p->ds, p->cs, p->ip );
176 SET_CFLAG(&context);
178 break;
180 case 0x0302: /* Call real mode procedure with interrupt return */
182 REALMODECALL *p = (REALMODECALL *)PTR_SEG_OFF_TO_LIN( ES_reg(&context), DI_reg(&context) );
183 fprintf(stdnimp,
184 "RealModeCallIret: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
185 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n",
186 p->eax, p->ebx, p->ecx, p->edx,
187 p->esi, p->edi, p->es, p->ds, p->cs, p->ip );
188 SET_CFLAG(&context);
190 break;
192 case 0x0400: /* Get DPMI version */
193 AX_reg(&context) = 0x005a; /* DPMI version 0.90 */
194 BX_reg(&context) = 0x0005; /* Flags: 32-bit, virtual memory */
195 CL_reg(&context) = runtime_cpu ();
196 DX_reg(&context) = 0x0102; /* Master/slave interrupt controller base*/
197 break;
199 case 0x0500: /* Get free memory information */
200 ptr = (BYTE *)PTR_SEG_OFF_TO_LIN( ES_reg(&context), DI_reg(&context) );
201 *(DWORD *)ptr = 0x00ff0000; /* Largest block available */
202 memset( ptr + 4, 0xff, 0x2c ); /* No other information supported */
203 break;
205 case 0x0501: /* Allocate memory block */
206 if (!(ptr = (BYTE *)malloc( MAKELONG( CX_reg(&context),
207 BX_reg(&context) ) )))
209 AX_reg(&context) = 0x8012; /* linear memory not available */
210 SET_CFLAG(&context);
212 else
214 BX_reg(&context) = SI_reg(&context) = HIWORD(ptr);
215 CX_reg(&context) = DI_reg(&context) = LOWORD(ptr);
217 break;
219 case 0x0502: /* Free memory block */
220 free( (void *)MAKELONG( DI_reg(&context), SI_reg(&context) ) );
221 break;
223 case 0x0503: /* Resize memory block */
224 if (!(ptr = (BYTE *)realloc( (void *)MAKELONG(DI_reg(&context),SI_reg(&context)),
225 MAKELONG(CX_reg(&context),BX_reg(&context)))))
227 AX_reg(&context) = 0x8012; /* linear memory not available */
228 SET_CFLAG(&context);
230 else
232 BX_reg(&context) = SI_reg(&context) = HIWORD(ptr);
233 CX_reg(&context) = DI_reg(&context) = LOWORD(ptr);
235 break;
237 case 0x0600: /* Lock linear region */
238 break; /* Just ignore it */
240 case 0x0601: /* Unlock linear region */
241 break; /* Just ignore it */
243 default:
244 INT_BARF( &context, 0x31 );
245 AX_reg(&context) = 0x8001; /* unsupported function */
246 SET_CFLAG(&context);
247 break;