Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 1 | /* -*- tab-width: 8; c-basic-offset: 4 -*- */ |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 2 | /* |
| 3 | * DOS interrupt 2fh handler |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 4 | * |
| 5 | * Cdrom - device driver emulation - Audio features. |
| 6 | * (c) 1998 Petr Tomasek <tomasek@etf.cuni.cz> |
| 7 | * (c) 1999 Eric Pouech |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
Alexandre Julliard | 5819953 | 1994-04-21 01:20:00 +0000 | [diff] [blame] | 10 | #include <stdlib.h> |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 11 | #include <string.h> |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 12 | #include <unistd.h> |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 13 | |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame^] | 14 | #include "wine/winbase16.h" |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 15 | #include "ldt.h" |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 16 | #include "drive.h" |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 17 | #include "msdos.h" |
Alexandre Julliard | 234bc24 | 1994-12-10 13:02:28 +0000 | [diff] [blame] | 18 | #include "miscemu.h" |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 19 | #include "module.h" |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 20 | #include "task.h" |
| 21 | #include "dosexe.h" |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 22 | #include "heap.h" |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 23 | /* #define DEBUG_INT */ |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 24 | #include "debug.h" |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 25 | #include "cdrom.h" |
Alexandre Julliard | 5819953 | 1994-04-21 01:20:00 +0000 | [diff] [blame] | 26 | |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 27 | /* base WPROCS.DLL ordinal number for VxDs */ |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 28 | #define VXD_BASE 400 |
| 29 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 30 | static void do_int2f_16( CONTEXT *context ); |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 31 | static void do_mscdex( CONTEXT *context ); |
Alexandre Julliard | 6b81b39 | 1994-07-07 16:23:58 +0000 | [diff] [blame] | 32 | |
Alexandre Julliard | e2991ea | 1995-07-29 13:09:43 +0000 | [diff] [blame] | 33 | /********************************************************************** |
| 34 | * INT_Int2fHandler |
| 35 | * |
| 36 | * Handler for int 2fh (multiplex). |
| 37 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 38 | void WINAPI INT_Int2fHandler( CONTEXT *context ) |
Alexandre Julliard | 5819953 | 1994-04-21 01:20:00 +0000 | [diff] [blame] | 39 | { |
Marcus Meissner | 6b5a811 | 1999-01-30 13:06:00 +0000 | [diff] [blame] | 40 | TRACE(int,"Subfunction 0x%X\n", AX_reg(context)); |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 41 | |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 42 | switch(AH_reg(context)) |
Alexandre Julliard | e2991ea | 1995-07-29 13:09:43 +0000 | [diff] [blame] | 43 | { |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 44 | case 0x10: |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 45 | AL_reg(context) = 0xff; /* share is installed */ |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 46 | break; |
Alexandre Julliard | 7e50df3 | 1994-08-06 11:22:41 +0000 | [diff] [blame] | 47 | |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 48 | case 0x11: /* Network Redirector / IFSFUNC */ |
| 49 | switch (AL_reg(context)) |
| 50 | { |
| 51 | case 0x00: /* Install check */ |
| 52 | /* not installed */ |
| 53 | break; |
| 54 | case 0x80: /* Enhanced services - Install check */ |
| 55 | /* not installed */ |
| 56 | break; |
| 57 | default: |
| 58 | INT_BARF( context, 0x2f ); |
| 59 | break; |
| 60 | } |
| 61 | break; |
| 62 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 63 | case 0x12: |
| 64 | switch (AL_reg(context)) |
| 65 | { |
| 66 | case 0x2e: /* get or set DOS error table address */ |
| 67 | switch (DL_reg(context)) |
| 68 | { |
| 69 | /* Four tables: even commands are 'get', odd are 'set' */ |
| 70 | /* DOS 5.0+ ignores "set" commands */ |
| 71 | case 0x01: |
| 72 | case 0x03: |
| 73 | case 0x05: |
| 74 | case 0x07: |
| 75 | case 0x09: |
| 76 | break; |
| 77 | /* Instead of having a message table in DOS-space, */ |
| 78 | /* we can use a special case for MS-DOS to force */ |
| 79 | /* the secondary interface. */ |
| 80 | case 0x00: |
| 81 | case 0x02: |
| 82 | case 0x04: |
| 83 | case 0x06: |
| 84 | ES_reg(context) = 0x0001; |
| 85 | DI_reg(context) = 0x0000; |
| 86 | break; |
| 87 | case 0x08: |
| 88 | FIXME(int, "No real-mode handler for errors yet! (bye!)"); |
| 89 | break; |
| 90 | default: |
| 91 | INT_BARF(context, 0x2f); |
| 92 | } |
| 93 | break; |
| 94 | default: |
| 95 | INT_BARF(context, 0x2f); |
| 96 | } |
| 97 | break; |
| 98 | |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 99 | case 0x15: /* mscdex */ |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 100 | do_mscdex(context); |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 101 | break; |
Alexandre Julliard | 7cc9c0c | 1994-06-15 15:45:11 +0000 | [diff] [blame] | 102 | |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 103 | case 0x16: |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 104 | do_int2f_16( context ); |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 105 | break; |
Joseph Pranevich | 1491e3f | 1998-10-17 11:58:15 +0000 | [diff] [blame] | 106 | |
| 107 | case 0x1a: /* ANSI.SYS / AVATAR.SYS Install Check */ |
| 108 | /* Not supported yet, do nothing */ |
| 109 | break; |
| 110 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 111 | case 0x43: |
Ove Kaaven | 32486cd | 1998-10-11 12:16:56 +0000 | [diff] [blame] | 112 | #if 1 |
| 113 | switch (AL_reg(context)) |
| 114 | { |
| 115 | case 0x00: /* XMS v2+ installation check */ |
| 116 | WARN(int,"XMS is not fully implemented\n"); |
| 117 | AL_reg(context) = 0x80; |
| 118 | break; |
| 119 | case 0x10: /* XMS v2+ get driver address */ |
| 120 | { |
| 121 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
| 122 | NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL; |
| 123 | GlobalUnlock16( GetCurrentTask() ); |
| 124 | #ifdef MZ_SUPPORTED |
| 125 | if (pModule && pModule->lpDosTask) |
| 126 | ES_reg(context) = pModule->lpDosTask->xms_seg; |
| 127 | else |
| 128 | #endif |
| 129 | ES_reg(context) = 0; |
| 130 | BX_reg(context) = 0; |
| 131 | break; |
| 132 | } |
| 133 | default: |
| 134 | INT_BARF( context, 0x2f ); |
| 135 | } |
| 136 | #else |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 137 | FIXME(int,"check for XMS (not supported)\n"); |
| 138 | AL_reg(context) = 0x42; /* != 0x80 */ |
Ove Kaaven | 32486cd | 1998-10-11 12:16:56 +0000 | [diff] [blame] | 139 | #endif |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 140 | break; |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 141 | |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 142 | case 0x45: |
| 143 | switch (AL_reg(context)) |
| 144 | { |
| 145 | case 0x00: |
| 146 | case 0x01: |
| 147 | case 0x02: |
| 148 | case 0x03: |
| 149 | case 0x04: |
| 150 | case 0x05: |
| 151 | case 0x06: |
| 152 | case 0x07: |
| 153 | case 0x08: |
| 154 | /* Microsoft Profiler - not installed */ |
| 155 | break; |
| 156 | default: |
| 157 | INT_BARF( context, 0x2f ); |
| 158 | } |
| 159 | break; |
| 160 | |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 161 | case 0x4a: |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 162 | switch(AL_reg(context)) |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 163 | { |
Alexandre Julliard | ade697e | 1995-11-26 13:59:11 +0000 | [diff] [blame] | 164 | case 0x10: /* smartdrv */ |
| 165 | break; /* not installed */ |
Alexandre Julliard | 0c126c7 | 1996-02-18 18:44:41 +0000 | [diff] [blame] | 166 | case 0x11: /* dblspace */ |
| 167 | break; /* not installed */ |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 168 | case 0x12: /* realtime compression interface */ |
| 169 | break; /* not installed */ |
Ulrich Weigand | ab635b2 | 1998-11-14 18:33:34 +0000 | [diff] [blame] | 170 | case 0x32: /* patch IO.SYS (???) */ |
| 171 | break; /* we have no IO.SYS, so we can't patch it :-/ */ |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 172 | default: |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 173 | INT_BARF( context, 0x2f ); |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 174 | } |
| 175 | break; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 176 | case 0x56: /* INTERLNK */ |
| 177 | switch(AL_reg(context)) |
| 178 | { |
| 179 | case 0x01: /* check if redirected drive */ |
| 180 | AL_reg(context) = 0; /* not redirected */ |
| 181 | break; |
| 182 | default: |
| 183 | INT_BARF( context, 0x2f ); |
| 184 | } |
| 185 | break; |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 186 | case 0x7a: /* NOVELL NetWare */ |
| 187 | switch (AL_reg(context)) |
| 188 | { |
| 189 | case 0x20: /* Get VLM Call Address */ |
| 190 | /* return nothing -> NetWare not installed */ |
| 191 | break; |
| 192 | default: |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 193 | INT_BARF( context, 0x2f ); |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 194 | break; |
| 195 | } |
| 196 | break; |
Alexandre Julliard | d2e1c1a | 1996-03-09 16:12:43 +0000 | [diff] [blame] | 197 | case 0xb7: /* append */ |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 198 | AL_reg(context) = 0; /* not installed */ |
Alexandre Julliard | d2e1c1a | 1996-03-09 16:12:43 +0000 | [diff] [blame] | 199 | break; |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 200 | case 0xb8: /* network */ |
| 201 | switch (AL_reg(context)) |
| 202 | { |
| 203 | case 0x00: /* Install check */ |
| 204 | /* not installed */ |
| 205 | break; |
| 206 | default: |
| 207 | INT_BARF( context, 0x2f ); |
| 208 | break; |
| 209 | } |
| 210 | break; |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 211 | case 0xbd: /* some Novell network install check ??? */ |
| 212 | AX_reg(context) = 0xa5a5; /* pretend to have Novell IPX installed */ |
| 213 | break; |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 214 | case 0xbf: /* REDIRIFS.EXE */ |
| 215 | switch (AL_reg(context)) |
| 216 | { |
| 217 | case 0x00: /* Install check */ |
| 218 | /* not installed */ |
| 219 | break; |
| 220 | default: |
| 221 | INT_BARF( context, 0x2f ); |
| 222 | break; |
| 223 | } |
| 224 | break; |
| 225 | case 0xd7: /* Banyan Vines */ |
| 226 | switch (AL_reg(context)) |
| 227 | { |
| 228 | case 0x01: /* Install check - Get Int Number */ |
| 229 | /* not installed */ |
| 230 | break; |
| 231 | default: |
| 232 | INT_BARF( context, 0x2f ); |
| 233 | break; |
| 234 | } |
| 235 | break; |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 236 | case 0xfa: /* Watcom debugger check, returns 0x666 if installed */ |
| 237 | break; |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 238 | default: |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 239 | INT_BARF( context, 0x2f ); |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 240 | break; |
| 241 | } |
Alexandre Julliard | 5819953 | 1994-04-21 01:20:00 +0000 | [diff] [blame] | 242 | } |
Alexandre Julliard | 6b81b39 | 1994-07-07 16:23:58 +0000 | [diff] [blame] | 243 | |
| 244 | |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 245 | /********************************************************************** |
| 246 | * do_int2f_16 |
| 247 | */ |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 248 | static void do_int2f_16( CONTEXT *context ) |
Alexandre Julliard | 6b81b39 | 1994-07-07 16:23:58 +0000 | [diff] [blame] | 249 | { |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 250 | DWORD addr; |
| 251 | |
Alexandre Julliard | 808cb04 | 1995-08-17 17:11:36 +0000 | [diff] [blame] | 252 | switch(AL_reg(context)) |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 253 | { |
| 254 | case 0x00: /* Windows enhanced mode installation check */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 255 | AX_reg(context) = (GetWinFlags() & WF_ENHANCED) ? |
| 256 | LOWORD(GetVersion16()) : 0; |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 257 | break; |
Alexandre Julliard | ff8331e | 1995-09-18 11:19:54 +0000 | [diff] [blame] | 258 | |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 259 | case 0x0a: /* Get Windows version and type */ |
Alexandre Julliard | 808cb04 | 1995-08-17 17:11:36 +0000 | [diff] [blame] | 260 | AX_reg(context) = 0; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 261 | BX_reg(context) = (LOWORD(GetVersion16()) << 8) | |
| 262 | (LOWORD(GetVersion16()) >> 8); |
| 263 | CX_reg(context) = (GetWinFlags() & WF_ENHANCED) ? 3 : 2; |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 264 | break; |
| 265 | |
Ulrich Weigand | ab635b2 | 1998-11-14 18:33:34 +0000 | [diff] [blame] | 266 | case 0x0b: /* Identify Windows-aware TSRs */ |
| 267 | /* we don't have any pre-Windows TSRs */ |
| 268 | break; |
| 269 | |
Joseph Pranevich | 1491e3f | 1998-10-17 11:58:15 +0000 | [diff] [blame] | 270 | case 0x11: /* Get Shell Parameters - (SHELL= in CONFIG.SYS) */ |
| 271 | /* We can mock this up. But not today... */ |
| 272 | FIXME(int, "Get Shell Parameters\n"); |
| 273 | break; |
| 274 | |
Alexandre Julliard | e2991ea | 1995-07-29 13:09:43 +0000 | [diff] [blame] | 275 | case 0x80: /* Release time-slice */ |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 276 | AL_reg(context) = 0; |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 277 | break; |
Alexandre Julliard | e2991ea | 1995-07-29 13:09:43 +0000 | [diff] [blame] | 278 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 279 | case 0x81: /* Begin critical section. */ |
| 280 | /* FIXME? */ |
| 281 | break; |
| 282 | |
| 283 | case 0x82: /* End critical section. */ |
| 284 | /* FIXME? */ |
| 285 | break; |
| 286 | |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 287 | case 0x83: /* Return Current Virtual Machine ID */ |
| 288 | /* Virtual Machines are usually created/destroyed when Windows runs |
| 289 | * DOS programs. Since we never do, we are always in the System VM. |
| 290 | * According to Ralf Brown's Interrupt List, never return 0. But it |
| 291 | * seems to work okay (returning 0), just to be sure we return 1. |
| 292 | */ |
| 293 | BX_reg(context) = 1; /* VM 1 is probably the System VM */ |
| 294 | break; |
| 295 | |
| 296 | case 0x84: /* Get device API entry point */ |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 297 | addr = (DWORD)NE_GetEntryPoint( GetModuleHandle16("WPROCS"), |
| 298 | VXD_BASE + BX_reg(context) ); |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 299 | if (!addr) /* not supported */ |
| 300 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 301 | ERR(int,"Accessing unknown VxD %04x - Expect a failure now.\n", |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 302 | BX_reg(context) ); |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 303 | } |
| 304 | ES_reg(context) = SELECTOROF(addr); |
| 305 | DI_reg(context) = OFFSETOF(addr); |
| 306 | break; |
Alexandre Julliard | ff8331e | 1995-09-18 11:19:54 +0000 | [diff] [blame] | 307 | |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 308 | case 0x86: /* DPMI detect mode */ |
Alexandre Julliard | 808cb04 | 1995-08-17 17:11:36 +0000 | [diff] [blame] | 309 | AX_reg(context) = 0; /* Running under DPMI */ |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 310 | break; |
| 311 | |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 312 | case 0x87: /* DPMI installation check */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 313 | #if 1 /* DPMI still breaks pkunzip */ |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 314 | if (ISV86(context)) break; /* so bail out for now if in v86 mode */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 315 | #endif |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 316 | { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 317 | TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); |
| 318 | NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL; |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 319 | SYSTEM_INFO si; |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 320 | |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 321 | GlobalUnlock16( GetCurrentTask() ); |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 322 | GetSystemInfo(&si); |
| 323 | AX_reg(context) = 0x0000; /* DPMI Installed */ |
| 324 | BX_reg(context) = 0x0001; /* 32bits available */ |
| 325 | CL_reg(context) = si.wProcessorLevel; |
| 326 | DX_reg(context) = 0x005a; /* DPMI major/minor 0.90 */ |
| 327 | SI_reg(context) = 0; /* # of para. of DOS extended private data */ |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 328 | #ifdef MZ_SUPPORTED /* ES:DI is DPMI switch entry point */ |
| 329 | if (pModule && pModule->lpDosTask) |
| 330 | ES_reg(context) = pModule->lpDosTask->dpmi_seg; |
| 331 | else |
| 332 | #endif |
| 333 | ES_reg(context) = 0; |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 334 | DI_reg(context) = 0; |
| 335 | break; |
| 336 | } |
Alexandre Julliard | af0bae5 | 1995-10-03 17:06:08 +0000 | [diff] [blame] | 337 | case 0x8a: /* DPMI get vendor-specific API entry point. */ |
| 338 | /* The 1.0 specs say this should work with all 0.9 hosts. */ |
| 339 | break; |
| 340 | |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 341 | default: |
Alexandre Julliard | 808cb04 | 1995-08-17 17:11:36 +0000 | [diff] [blame] | 342 | INT_BARF( context, 0x2f ); |
Alexandre Julliard | bd34d4f | 1995-06-20 19:08:12 +0000 | [diff] [blame] | 343 | } |
Alexandre Julliard | 6b81b39 | 1994-07-07 16:23:58 +0000 | [diff] [blame] | 344 | } |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 345 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 346 | void do_mscdex( CONTEXT *context ) |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 347 | { |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 348 | int drive, count; |
| 349 | char* p; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 350 | |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 351 | switch(AL_reg(context)) { |
| 352 | case 0x00: /* Installation check */ |
| 353 | /* Count the number of contiguous CDROM drives |
| 354 | */ |
| 355 | for (drive = count = 0; drive < MAX_DOS_DRIVES; drive++) { |
| 356 | if (DRIVE_GetType(drive) == TYPE_CDROM) { |
| 357 | while (DRIVE_GetType(drive + count) == TYPE_CDROM) count++; |
| 358 | break; |
| 359 | } |
| 360 | } |
| 361 | TRACE(int, "Installation check: %d cdroms, starting at %d\n", count, drive); |
| 362 | BX_reg(context) = count; |
| 363 | CX_reg(context) = (drive < MAX_DOS_DRIVES) ? drive : 0; |
| 364 | break; |
| 365 | |
| 366 | case 0x0B: /* drive check */ |
| 367 | AX_reg(context) = (DRIVE_GetType(CX_reg(context)) == TYPE_CDROM); |
| 368 | BX_reg(context) = 0xADAD; |
| 369 | break; |
| 370 | |
| 371 | case 0x0C: /* get version */ |
| 372 | BX_reg(context) = 0x020a; |
| 373 | break; |
| 374 | |
| 375 | case 0x0D: /* get drive letters */ |
| 376 | p = CTX_SEG_OFF_TO_LIN(context, ES_reg(context), EBX_reg(context)); |
| 377 | memset( p, 0, MAX_DOS_DRIVES ); |
| 378 | for (drive = 0; drive < MAX_DOS_DRIVES; drive++) { |
| 379 | if (DRIVE_GetType(drive) == TYPE_CDROM) *p++ = drive; |
| 380 | } |
| 381 | break; |
| 382 | |
| 383 | case 0x10: /* direct driver acces */ |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 384 | { |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 385 | static WINE_CDAUDIO wcda; |
| 386 | BYTE* driver_request; |
| 387 | BYTE* io_stru; |
| 388 | u_char Error = 255; /* No Error */ |
| 389 | int dorealmode = ISV86(context); |
| 390 | |
| 391 | driver_request = (dorealmode) ? |
| 392 | DOSMEM_MapRealToLinear(MAKELONG(BX_reg(context),ES_reg(context))) : |
| 393 | PTR_SEG_OFF_TO_LIN(ES_reg(context),BX_reg(context)); |
| 394 | |
| 395 | if (!driver_request) { |
| 396 | /* FIXME - to be deleted ?? */ |
| 397 | ERR(int," ES:BX==0 ! SEGFAULT ?\n"); |
| 398 | ERR(int," -->BX=0x%04x, ES=0x%04lx, DS=0x%04lx, CX=0x%04x\n", |
| 399 | BX_reg(context), ES_reg(context), DS_reg(context), CX_reg(context)); |
| 400 | } else { |
| 401 | /* FIXME - would be best to open the device at the begining of the wine session .... |
| 402 | */ |
| 403 | if (wcda.unixdev <= 0) |
| 404 | CDAUDIO_Open(&wcda); |
| 405 | } |
| 406 | TRACE(int,"CDROM device driver -> command <%d>\n", (unsigned char)driver_request[2]); |
| 407 | |
| 408 | /* set status to 0 */ |
| 409 | driver_request[3] = driver_request[4] = 0; |
| 410 | CDAUDIO_GetCDStatus(&wcda); |
| 411 | |
| 412 | switch (driver_request[2]) { |
| 413 | case 3: |
| 414 | io_stru = (dorealmode) ? |
| 415 | DOSMEM_MapRealToLinear(MAKELONG(*((WORD*)(driver_request + 14)), *((WORD*)(driver_request + 16)))) : |
| 416 | PTR_SEG_OFF_TO_LIN(*((WORD*)(driver_request + 16)), *((WORD*)(driver_request + 18))); |
| 417 | |
| 418 | TRACE(int," --> IOCTL INPUT <%d>\n", io_stru[0]); |
| 419 | switch (io_stru[0]) { |
| 420 | #if 0 |
| 421 | case 0: /* Get device Header */ |
| 422 | { |
| 423 | static LPSTR ptr = 0; |
| 424 | if (ptr == 0) { |
| 425 | ptr = SEGPTR_ALLOC(22); |
| 426 | *((DWORD*)(ptr )) = ~1; /* Next Device Driver */ |
| 427 | *((WORD* )(ptr + 4)) = 0xC800; /* Device attributes */ |
| 428 | *((WORD* )(ptr + 6)) = 0x1234; /* Pointer to device strategy routine: FIXME */ |
| 429 | *((WORD* )(ptr + 8)) = 0x3142; /* Pointer to device interrupt routine: FIXME */ |
| 430 | *((char*) (ptr + 10)) = 'W'; /* 8-byte character device name field */ |
| 431 | *((char*) (ptr + 11)) = 'I'; |
| 432 | *((char*) (ptr + 12)) = 'N'; |
| 433 | *((char*) (ptr + 13)) = 'E'; |
| 434 | *((char*) (ptr + 14)) = '_'; |
| 435 | *((char*) (ptr + 15)) = 'C'; |
| 436 | *((char*) (ptr + 16)) = 'D'; |
| 437 | *((char*) (ptr + 17)) = '_'; |
| 438 | *((WORD*) (ptr + 18)) = 0; /* Reserved (must be zero) */ |
| 439 | *((BYTE*) (ptr + 20)) = 0; /* Drive letter (must be zero) */ |
| 440 | *((BYTE*) (ptr + 21)) = 1; /* Number of units supported (one or more) FIXME*/ |
| 441 | } |
| 442 | ((DWORD*)io_stru+1)[0] = SEGPTR_GET(ptr); |
| 443 | } |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 444 | break; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 445 | #endif |
Eric Pouech | 6aa4f2e | 1999-02-02 16:10:10 +0000 | [diff] [blame] | 446 | |
| 447 | case 1: /* location of head */ |
| 448 | if (io_stru[1] == 0) { |
| 449 | /* FIXME: what if io_stru+2 is not DWORD aligned ? */ |
| 450 | ((DWORD*)io_stru+2)[0] = wcda.dwCurFrame; |
| 451 | TRACE(int," ----> HEAD LOCATION <%ld>\n", ((DWORD*)io_stru+2)[0]); |
| 452 | } else { |
| 453 | ERR(int,"CDRom-Driver: Unsupported addressing mode !!\n"); |
| 454 | Error = 0x0c; |
| 455 | } |
| 456 | break; |
| 457 | |
| 458 | case 4: /* Audio channel info */ |
| 459 | io_stru[1] = 0; |
| 460 | io_stru[2] = 0xff; |
| 461 | io_stru[3] = 1; |
| 462 | io_stru[4] = 0xff; |
| 463 | io_stru[5] = 2; |
| 464 | io_stru[6] = 0xff; |
| 465 | io_stru[7] = 3; |
| 466 | io_stru[8] = 0xff; |
| 467 | TRACE(int," ----> AUDIO CHANNEL CONTROL\n"); |
| 468 | break; |
| 469 | |
| 470 | case 6: /* device status */ |
| 471 | /* FIXME .. does this work properly ?? */ |
| 472 | io_stru[3] = io_stru[4] = 0; |
| 473 | io_stru[2] = 1; /* supports audio channels (?? FIXME ??) */ |
| 474 | io_stru[1] = 16; /* data read and plays audio tracks */ |
| 475 | if (wcda.cdaMode == WINE_CDA_OPEN) |
| 476 | io_stru[1] |= 1; |
| 477 | TRACE(int," ----> DEVICE STATUS <0x%08lx>\n", (DWORD)io_stru[1]); |
| 478 | break; |
| 479 | |
| 480 | case 8: /* Volume size */ |
| 481 | *((DWORD*)(io_stru+1)) = wcda.dwTotalLen; |
| 482 | TRACE(int," ----> VOLMUE SIZE <0x%08lx>\n", *((DWORD*)(io_stru+1))); |
| 483 | break; |
| 484 | |
| 485 | case 9: /* media changed ? */ |
| 486 | /* answers don't know... -1/1 for yes/no would be better */ |
| 487 | io_stru[0] = 0; /* FIXME? 1? */ |
| 488 | break; |
| 489 | |
| 490 | case 10: /* audio disk info */ |
| 491 | io_stru[1] = wcda.nFirstTrack; /* starting track of the disc */ |
| 492 | io_stru[2] = wcda.nLastTrack; /* ending track */ |
| 493 | ((DWORD*)io_stru+3)[0] = wcda.dwFirstOffset; |
| 494 | TRACE(int," ----> AUDIO DISK INFO <%d-%d/%ld>\n", |
| 495 | io_stru[1], io_stru[2], ((DWORD *)io_stru+3)[0]); |
| 496 | break; |
| 497 | |
| 498 | case 11: /* audio track info */ |
| 499 | ((DWORD*)io_stru+2)[0] = wcda.lpdwTrackPos[io_stru[1]]; |
| 500 | /* starting point if the track */ |
| 501 | io_stru[6] = wcda.lpbTrackFlags[io_stru[1]]; |
| 502 | TRACE(int," ----> AUDIO TRACK INFO <track=%d>[%ld:%d]\n", |
| 503 | io_stru[1],((DWORD *)io_stru+2)[0], io_stru[6]); |
| 504 | break; |
| 505 | |
| 506 | case 12: /* get Q-Channel / Subchannel (??) info */ |
| 507 | io_stru[ 1] = wcda.lpbTrackFlags[wcda.nCurTrack]; |
| 508 | io_stru[ 2] = wcda.nCurTrack; |
| 509 | io_stru[ 3] = 0; /* FIXME ?? */ |
| 510 | { |
| 511 | DWORD f = wcda.lpdwTrackPos[wcda.nCurTrack] - wcda.dwCurFrame; |
| 512 | io_stru[ 4] = f / CDFRAMES_PERMIN; |
| 513 | io_stru[ 5] = (f - CDFRAMES_PERMIN * io_stru[4]) / CDFRAMES_PERSEC; |
| 514 | io_stru[ 6] = f - CDFRAMES_PERMIN * io_stru[4] - CDFRAMES_PERSEC * io_stru[5]; |
| 515 | } |
| 516 | io_stru[ 7] = 0; |
| 517 | { |
| 518 | DWORD f = wcda.dwCurFrame; |
| 519 | io_stru[ 8] = f / CDFRAMES_PERMIN; |
| 520 | io_stru[ 9] = (f - CDFRAMES_PERMIN * io_stru[4]) / CDFRAMES_PERSEC; |
| 521 | io_stru[10] = f - CDFRAMES_PERMIN * io_stru[4] - CDFRAMES_PERSEC * io_stru[5]; |
| 522 | } |
| 523 | break; |
| 524 | |
| 525 | case 15: /* Audio status info */ |
| 526 | /* !!!! FIXME FIXME FIXME !! */ |
| 527 | *((WORD*)(io_stru+1)) = (wcda.cdaMode == WINE_CDA_PAUSE); |
| 528 | *((DWORD*)(io_stru+3)) = wcda.lpdwTrackPos[0]; |
| 529 | *((DWORD*)(io_stru+7)) = wcda.lpdwTrackPos[wcda.nTracks - 1]; |
| 530 | break; |
| 531 | |
| 532 | default: |
| 533 | FIXME(int," Cdrom-driver: IOCTL INPUT: Unimplemented <%d>!!\n", io_stru[0]); |
| 534 | Error=0x0c; |
| 535 | break; |
| 536 | } |
| 537 | break; |
| 538 | |
| 539 | case 12: |
| 540 | io_stru = (dorealmode) ? |
| 541 | DOSMEM_MapRealToLinear(MAKELONG(*((WORD*)(driver_request + 14)), *((WORD*)(driver_request + 16)))) : |
| 542 | PTR_SEG_OFF_TO_LIN(*((WORD*)(driver_request + 16)), *((WORD*)(driver_request + 18))); |
| 543 | |
| 544 | TRACE(int," --> IOCTL OUTPUT <%d>\n",io_stru[0]); |
| 545 | switch (io_stru[0]) { |
| 546 | case 0: /* eject */ |
| 547 | CDAUDIO_SetDoor(&wcda, 1); |
| 548 | TRACE(int," ----> EJECT\n"); |
| 549 | break; |
| 550 | case 2: /* reset drive */ |
| 551 | CDAUDIO_Reset(&wcda); |
| 552 | TRACE(int," ----> RESET\n"); |
| 553 | break; |
| 554 | case 3: /* Audio Channel Control */ |
| 555 | FIXME(int, " ----> AUDIO CHANNEL CONTROL (NIY)\n"); |
| 556 | break; |
| 557 | case 5: /* close tray */ |
| 558 | CDAUDIO_SetDoor(&wcda, 0); |
| 559 | TRACE(int," ----> CLOSE TRAY\n"); |
| 560 | break; |
| 561 | default: |
| 562 | FIXME(int," Cdrom-driver: IOCTL OUPUT: Unimplemented <%d>!!\n", |
| 563 | io_stru[0]); |
| 564 | Error=0x0c; |
| 565 | break; |
| 566 | } |
| 567 | break; |
| 568 | |
| 569 | case 132: /* FIXME - It didn't function for me... */ |
| 570 | TRACE(int," --> PLAY AUDIO\n"); |
| 571 | if (driver_request[13] == 0) { |
| 572 | TRACE(int,"Mode :<0x%02X> , [%ld-%ld]\n", |
| 573 | (unsigned char)driver_request[13], |
| 574 | ((DWORD*)driver_request+14)[0], |
| 575 | ((DWORD*)driver_request+18)[0]); |
| 576 | CDAUDIO_Play(&wcda, ((DWORD*)driver_request+14)[0], ((DWORD*)driver_request+14)[0] + ((DWORD*)driver_request+18)[0]); |
| 577 | } else { |
| 578 | ERR(int, "CDRom-Driver: Unsupported address mode !!\n"); |
| 579 | Error=0x0c; |
| 580 | } |
| 581 | break; |
| 582 | |
| 583 | case 133: |
| 584 | if (wcda.cdaMode == WINE_CDA_PLAY) { |
| 585 | CDAUDIO_Pause(&wcda, 1); |
| 586 | TRACE(int," --> STOP AUDIO (Paused)\n"); |
| 587 | } else { |
| 588 | CDAUDIO_Stop(&wcda); |
| 589 | TRACE(int," --> STOP AUDIO (Stopped)\n"); |
| 590 | } |
| 591 | break; |
| 592 | |
| 593 | case 136: |
| 594 | TRACE(int," --> RESUME AUDIO\n"); |
| 595 | CDAUDIO_Pause(&wcda, 0); |
| 596 | break; |
| 597 | |
| 598 | default: |
| 599 | FIXME(int," CDRom-Driver - ioctl uninplemented <%d>\n",driver_request[2]); |
| 600 | Error=0x0c; |
| 601 | } |
| 602 | |
| 603 | if (Error<255) { |
| 604 | driver_request[4] |= 127; |
| 605 | driver_request[3] = Error; |
| 606 | } |
| 607 | driver_request[4] |= 2 * (wcda.cdaMode = WINE_CDA_PLAY); |
| 608 | |
| 609 | /* close (fdcd); FIXME !! -- cannot use close when ejecting |
| 610 | the cd-rom - close would close it again */ |
| 611 | } |
| 612 | break; |
| 613 | default: |
| 614 | FIXME(int, "Unimplemented MSCDEX function 0x%02X.\n", AL_reg(context)); |
| 615 | break; |
Alexandre Julliard | 7e56f68 | 1996-01-31 19:02:28 +0000 | [diff] [blame] | 616 | } |
| 617 | } |