4 * Copyright 1995 Alexandre Julliard
21 #define DOS_GET_DRIVE(reg) ((reg) ? (reg) - 1 : DRIVE_GetCurrentDrive())
23 void CreateBPB(int drive
, BYTE
*data
); /* defined in int21.c */
26 /* Structure for real-mode callbacks */
48 extern void do_mscdex( CONTEXT
*context
);
50 /**********************************************************************
53 * Handler for int 31h (DPMI).
55 void WINAPI
INT_Int31Handler( CONTEXT
*context
)
61 switch(AX_reg(context
))
63 case 0x0000: /* Allocate LDT descriptors */
64 if (!(AX_reg(context
) = AllocSelectorArray( CX_reg(context
) )))
66 AX_reg(context
) = 0x8011; /* descriptor unavailable */
71 case 0x0001: /* Free LDT descriptor */
72 if (FreeSelector( BX_reg(context
) ))
74 AX_reg(context
) = 0x8022; /* invalid selector */
79 /* If a segment register contains the selector being freed, */
81 if (!((DS_reg(context
)^BX_reg(context
)) & ~3)) DS_reg(context
) = 0;
82 if (!((ES_reg(context
)^BX_reg(context
)) & ~3)) ES_reg(context
) = 0;
83 if (!((FS_reg(context
)^BX_reg(context
)) & ~3)) FS_reg(context
) = 0;
84 if (!((GS_reg(context
)^BX_reg(context
)) & ~3)) GS_reg(context
) = 0;
88 case 0x0002: /* Real mode segment to descriptor */
90 WORD entryPoint
= 0; /* KERNEL entry point for descriptor */
91 switch(BX_reg(context
))
93 case 0x0000: entryPoint
= 183; break; /* __0000H */
94 case 0x0040: entryPoint
= 193; break; /* __0040H */
95 case 0xa000: entryPoint
= 174; break; /* __A000H */
96 case 0xb000: entryPoint
= 181; break; /* __B000H */
97 case 0xb800: entryPoint
= 182; break; /* __B800H */
98 case 0xc000: entryPoint
= 195; break; /* __C000H */
99 case 0xd000: entryPoint
= 179; break; /* __D000H */
100 case 0xe000: entryPoint
= 190; break; /* __E000H */
101 case 0xf000: entryPoint
= 194; break; /* __F000H */
103 AX_reg(context
) = DOSMEM_AllocSelector(BX_reg(context
));
107 AX_reg(context
) = LOWORD(MODULE_GetEntryPoint(
108 GetModuleHandle16( "KERNEL" ),
113 case 0x0003: /* Get next selector increment */
114 AX_reg(context
) = __AHINCR
;
117 case 0x0004: /* Lock selector (not supported) */
118 AX_reg(context
) = 0; /* FIXME: is this a correct return value? */
121 case 0x0005: /* Unlock selector (not supported) */
122 AX_reg(context
) = 0; /* FIXME: is this a correct return value? */
125 case 0x0006: /* Get selector base address */
126 if (!(dw
= GetSelectorBase( BX_reg(context
) )))
128 AX_reg(context
) = 0x8022; /* invalid selector */
133 CX_reg(context
) = HIWORD(dw
);
134 DX_reg(context
) = LOWORD(dw
);
138 case 0x0007: /* Set selector base address */
139 SetSelectorBase( BX_reg(context
),
140 MAKELONG( DX_reg(context
), CX_reg(context
) ) );
143 case 0x0008: /* Set selector limit */
144 SetSelectorLimit( BX_reg(context
),
145 MAKELONG( DX_reg(context
), CX_reg(context
) ) );
148 case 0x0009: /* Set selector access rights */
149 SelectorAccessRights( BX_reg(context
), 1, CX_reg(context
) );
152 case 0x000a: /* Allocate selector alias */
153 if (!(AX_reg(context
) = AllocCStoDSAlias( BX_reg(context
) )))
155 AX_reg(context
) = 0x8011; /* descriptor unavailable */
160 case 0x000b: /* Get descriptor */
163 LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context
) ), &entry
);
164 /* FIXME: should use ES:EDI for 32-bit clients */
165 LDT_EntryToBytes( PTR_SEG_OFF_TO_LIN( ES_reg(context
),
166 DI_reg(context
) ), &entry
);
170 case 0x000c: /* Set descriptor */
173 LDT_BytesToEntry( PTR_SEG_OFF_TO_LIN( ES_reg(context
),
174 DI_reg(context
) ), &entry
);
175 LDT_GetEntry( SELECTOR_TO_ENTRY( BX_reg(context
) ), &entry
);
179 case 0x000d: /* Allocate specific LDT descriptor */
180 AX_reg(context
) = 0x8011; /* descriptor unavailable */
183 case 0x0200: /* get real mode interrupt vector */
185 "int31: get realmode interupt vector(0x%02x) unimplemented.\n",
190 case 0x0201: /* set real mode interrupt vector */
192 "int31: set realmode interupt vector(0x%02x,0x%04x:0x%04x) unimplemented\n",
193 BL_reg(context
),CX_reg(context
),DX_reg(context
)
197 case 0x0204: /* Get protected mode interrupt vector */
198 dw
= (DWORD
)INT_GetHandler( BL_reg(context
) );
199 CX_reg(context
) = HIWORD(dw
);
200 DX_reg(context
) = LOWORD(dw
);
203 case 0x0205: /* Set protected mode interrupt vector */
204 INT_SetHandler( BL_reg(context
),
205 (FARPROC16
)PTR_SEG_OFF_TO_SEGPTR( CX_reg(context
),
209 case 0x0300: /* Simulate real mode interrupt
210 * Interrupt number is in BL, flags are in BH
211 * ES:DI points to real-mode call structure
212 * Currently we just print it out and return error.
214 RESET_CFLAG(context
);
216 REALMODECALL
*p
= (REALMODECALL
*)PTR_SEG_OFF_TO_LIN( ES_reg(context
), DI_reg(context
) );
218 switch (BL_reg(context
)) {
219 case 0x2f: /* int2f */
220 switch ((p
->eax
& 0xFF00)>>8) {
223 AX_reg(context
) = p
->eax
& 0xFFFF;
224 do_mscdex( context
);
231 case 0x21: /* int21 */
232 switch ((p
->eax
& 0xFF00)>>8) {
234 switch (p
->eax
& 0xFF) {
235 case 06:{/* get collate table */
237 /* ES:DI is a REALMODE pointer to 5 byte dosmem
238 * we fill that with 0x6, realmode pointer to collateTB
240 table
= DOSMEM_MapRealToLinear(MAKELONG(p
->edi
,p
->es
));
241 *(BYTE
*)table
= 0x06;
242 *(DWORD
*)(table
+1) = DOSMEM_CollateTable
;
244 CX_reg(context
) = 258;/*FIXME: size of table?*/
252 switch (p
->eax
& 0xFF) {
253 case 0x0D:{/* generic block device request */
254 BYTE
*dataptr
= DOSMEM_MapRealToLinear((p
->ds
)*0x1000+(p
->edx
& 0xFFFF));
255 int drive
= DOS_GET_DRIVE(p
->ebx
&0xFF);
257 if ((p
->ecx
& 0xFF00) != 0x0800) {
261 switch (p
->ecx
& 0xFF) {
264 char label
[12],fsname
[9],path
[4];
267 strcpy(path
,"x:\\");path
[0]=drive
+'A';
268 GetVolumeInformation32A(path
,label
,12,&serial
,NULL
,NULL
,fsname
,9);
270 memcpy(dataptr
+2,&serial
,4);
271 memcpy(dataptr
+6,label
,11);
272 memcpy(dataptr
+17,fsname
,8);
275 case 0x60: /* get device parameters */
276 /* used by defrag.exe of win95 */
277 memset(dataptr
, 0, 0x26);
279 dataptr
[6] = 0; /* media type */
281 dataptr
[1] = 0x05; /* fixed disk */
282 setword(&dataptr
[2], 0x01); /* non removable */
283 setword(&dataptr
[4], 0x300); /* # of cylinders */
285 dataptr
[1] = 0x07; /* block dev, floppy */
286 setword(&dataptr
[2], 0x02); /* removable */
287 setword(&dataptr
[4], 80); /* # of cylinders */
289 CreateBPB(drive
, &dataptr
[7]);
311 if (EFL_reg(context
)&1) {
313 "RealModeInt %02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
314 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x\n",
315 BL_reg(context
), p
->eax
, p
->ebx
, p
->ecx
, p
->edx
,
316 p
->esi
, p
->edi
, p
->es
, p
->ds
321 case 0x0301: /* Call real mode procedure with far return */
323 REALMODECALL
*p
= (REALMODECALL
*)PTR_SEG_OFF_TO_LIN( ES_reg(context
), DI_reg(context
) );
325 "RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
326 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n",
327 p
->eax
, p
->ebx
, p
->ecx
, p
->edx
,
328 p
->esi
, p
->edi
, p
->es
, p
->ds
, p
->cs
, p
->ip
);
333 case 0x0302: /* Call real mode procedure with interrupt return */
335 REALMODECALL
*p
= (REALMODECALL
*)PTR_SEG_OFF_TO_LIN( ES_reg(context
), DI_reg(context
) );
337 "RealModeCallIret: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
338 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n",
339 p
->eax
, p
->ebx
, p
->ecx
, p
->edx
,
340 p
->esi
, p
->edi
, p
->es
, p
->ds
, p
->cs
, p
->ip
);
345 case 0x0303: /* Allocate Real Mode Callback Address */
347 REALMODECALL
*p
= (REALMODECALL
*)PTR_SEG_OFF_TO_LIN( ES_reg(context
), DI_reg(context
) );
349 "AllocRMCB: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
350 " ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x\n"
351 " Function to call: %04x:%04x\n",
352 p
->eax
, p
->ebx
, p
->ecx
, p
->edx
,
353 p
->esi
, p
->edi
, p
->es
, p
->ds
, p
->cs
, p
->ip
,
354 (WORD
)DS_reg(context
), SI_reg(context
) );
359 case 0x0400: /* Get DPMI version */
364 AX_reg(context
) = 0x005a; /* DPMI version 0.90 */
365 BX_reg(context
) = 0x0005; /* Flags: 32-bit, virtual memory */
366 CL_reg(context
) = si
.wProcessorLevel
;
367 DX_reg(context
) = 0x0102; /* Master/slave interrupt controller base*/
370 case 0x0500: /* Get free memory information */
374 mmi
.dwSize
= sizeof(mmi
);
376 ptr
= (BYTE
*)PTR_SEG_OFF_TO_LIN(ES_reg(context
),DI_reg(context
));
377 /* the layout is just the same as MEMMANINFO, but without
380 memcpy(ptr
,((char*)&mmi
)+4,sizeof(mmi
)-4);
383 case 0x0501: /* Allocate memory block */
384 if (!(ptr
= (BYTE
*)HeapAlloc( GetProcessHeap(), 0,
385 MAKELONG( CX_reg(context
),
388 AX_reg(context
) = 0x8012; /* linear memory not available */
393 BX_reg(context
) = SI_reg(context
) = HIWORD(ptr
);
394 CX_reg(context
) = DI_reg(context
) = LOWORD(ptr
);
398 case 0x0502: /* Free memory block */
399 HeapFree( GetProcessHeap(), 0,
400 (void *)MAKELONG( DI_reg(context
), SI_reg(context
) ) );
403 case 0x0503: /* Resize memory block */
404 if (!(ptr
= (BYTE
*)HeapReAlloc( GetProcessHeap(), 0,
405 (void *)MAKELONG(DI_reg(context
),SI_reg(context
)),
406 MAKELONG(CX_reg(context
),BX_reg(context
)))))
408 AX_reg(context
) = 0x8012; /* linear memory not available */
413 BX_reg(context
) = SI_reg(context
) = HIWORD(ptr
);
414 CX_reg(context
) = DI_reg(context
) = LOWORD(ptr
);
418 case 0x0600: /* Lock linear region */
419 break; /* Just ignore it */
421 case 0x0601: /* Unlock linear region */
422 break; /* Just ignore it */
424 case 0x0602: /* Unlock real-mode region */
425 break; /* Just ignore it */
427 case 0x0603: /* Lock real-mode region */
428 break; /* Just ignore it */
430 case 0x0604: /* Get page size */
432 CX_reg(context
) = 4096;
435 case 0x0702: /* Mark page as demand-paging candidate */
436 break; /* Just ignore it */
438 case 0x0703: /* Discard page contents */
439 break; /* Just ignore it */
442 INT_BARF( context
, 0x31 );
443 AX_reg(context
) = 0x8001; /* unsupported function */