Fd type is no longer used, get rid of it.
[wine] / dlls / winedos / int13.c
1 /*
2  * BIOS interrupt 13h handler
3  *
4  * Copyright 1997 Andreas Mohr
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28
29 #ifdef HAVE_SYS_IOCTL_H
30 # include <sys/ioctl.h>
31 #endif
32 #include <fcntl.h>
33 #ifdef linux
34 # include <linux/fd.h>
35 #endif
36
37 #include "dosexe.h"
38 #include "wine/server.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(int);
42
43
44 /*
45  * Status of last int13 operation.
46  */
47 static BYTE INT13_last_status;
48
49
50 /**********************************************************************
51  *         INT13_SetStatus
52  *
53  * Write status to AH register and set carry flag on error (AH != 0).
54  *
55  * Despite what Ralf Brown says, at least functions 0x06 and 0x07 
56  * seem to set carry, too.
57  */
58 static void INT13_SetStatus( CONTEXT86 *context, BYTE status )
59 {
60     INT13_last_status = status;
61
62     SET_AH( context, status );
63
64     if (status)
65         SET_CFLAG( context );
66     else
67         RESET_CFLAG( context );        
68 }
69
70
71 /**********************************************************************
72  *          INT13_ReadFloppyParams
73  *
74  * Read floppy disk parameters.
75  */
76 static void INT13_ReadFloppyParams( CONTEXT86 *context )
77 {
78 #ifdef linux
79     static const BYTE floppy_params[2][13] =
80     {
81         { 0xaf, 0x02, 0x25, 0x02, 0x12, 0x1b, 0xff, 0x6c, 0xf6, 0x0f, 0x08 },
82         { 0xaf, 0x02, 0x25, 0x02, 0x12, 0x1b, 0xff, 0x6c, 0xf6, 0x0f, 0x08 }
83     };
84
85     static const DWORD drive_type_info[7]={
86         0x0000, /* none */
87         0x2709, /* 360 K */
88         0x4f0f, /* 1.2 M */
89         0x4f09, /* 720 K */
90         0x4f12, /* 1.44 M */
91         0x4f24, /* 2.88 M */
92         0x4f24  /* 2.88 M */
93     };
94
95     unsigned int i;
96     unsigned int nr_of_drives = 0;
97     BYTE drive_nr = DL_reg( context );
98     int floppy_fd;
99     int r;
100     struct floppy_drive_params floppy_parm;
101     WCHAR root[] = {'A',':','\\',0}, drive_root[] = {'\\','\\','.','\\','A',':',0};
102     HANDLE h;
103
104     TRACE("in  [ EDX=%08lx ]\n", context->Edx );
105
106     SET_AL( context, 0 );
107     SET_BX( context, 0 );
108     SET_CX( context, 0 );
109     SET_DH( context, 0 );
110
111     for (i = 0; i < MAX_DOS_DRIVES; i++, root[0]++)
112         if (GetDriveTypeW(root) == DRIVE_REMOVABLE) nr_of_drives++;
113     SET_DL( context, nr_of_drives );
114
115     if (drive_nr > 1) { 
116         /* invalid drive ? */
117         INT13_SetStatus( context, 0x07 ); /* drive parameter activity failed */
118         return;
119     }
120
121     drive_root[4] = 'A' + drive_nr;
122     h = CreateFileW(drive_root, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
123                     FILE_FLAG_BACKUP_SEMANTICS, NULL);
124     if (h == INVALID_HANDLE_VALUE ||
125         wine_server_handle_to_fd(h, GENERIC_READ, &floppy_fd, NULL))
126     {
127         WARN("Can't determine floppy geometry !\n");
128         INT13_SetStatus( context, 0x07 ); /* drive parameter activity failed */
129         return;
130     }
131     r = ioctl(floppy_fd, FDGETDRVPRM, &floppy_parm);
132     wine_server_release_fd( h, floppy_fd );
133     CloseHandle(h);
134
135     if(r<0)
136     {
137         INT13_SetStatus( context, 0x07 ); /* drive parameter activity failed */
138         return;
139     }
140
141     SET_BL( context, floppy_parm.cmos );
142
143     /*
144      * CH = low eight bits of max cyl
145      * CL = max sec nr (bits 5-0),
146      *      hi two bits of max cyl (bits 7-6)
147      * DH = max head nr 
148      */
149     if(BL_reg( context ) && BL_reg( context ) < 7)
150     {
151         SET_DH( context, 0x01 );
152         SET_CX( context, drive_type_info[BL_reg( context )] );
153     }
154
155     context->Edi = (DWORD)floppy_params[drive_nr];
156
157     if(!context->Edi)
158     {
159         ERR("Get floppy params failed for drive %d\n", drive_nr);
160         INT13_SetStatus( context, 0x07 ); /* drive parameter activity failed */
161         return;
162     }
163
164     TRACE("out [ EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx EDI=%08lx ]\n",
165           context->Eax, context->Ebx, context->Ecx, context->Edx, context->Edi);
166
167     INT13_SetStatus( context, 0x00 ); /* success */
168
169     /* FIXME: Word exits quietly if we return with no error. Why? */
170     FIXME("Returned ERROR!\n");
171     SET_CFLAG( context );
172
173 #else
174     INT13_SetStatus( context, 0x01 ); /* invalid function */
175 #endif
176 }
177
178
179 /**********************************************************************
180  *         DOSVM_Int13Handler (WINEDOS16.119)
181  *
182  * Handler for int 13h (disk I/O).
183  */
184 void WINAPI DOSVM_Int13Handler( CONTEXT86 *context )
185 {
186     TRACE( "AH=%02x\n", AH_reg( context ) );
187
188     switch( AH_reg( context ) )
189     {
190     case 0x00: /* RESET DISK SYSTEM */
191         INT13_SetStatus( context, 0x00 ); /* success */
192         break;
193
194     case 0x01: /* STATUS OF DISK SYSTEM */
195         INT13_SetStatus( context, INT13_last_status );
196         break;
197
198     case 0x02: /* READ SECTORS INTO MEMORY */
199         SET_AL( context, 0 ); /* number of sectors transferred */
200         INT13_SetStatus( context, 0x00 ); /* success */
201         break;
202
203     case 0x03: /* WRITE SECTORS FROM MEMORY */
204         SET_AL( context, 0 ); /* number of sectors transferred */
205         INT13_SetStatus( context, 0x00 ); /* success */
206         break;
207
208     case 0x04: /* VERIFY DISK SECTOR(S) */
209         SET_AL( context, 0 ); /* number of sectors verified */
210         INT13_SetStatus( context, 0x00 ); /* success */
211         break;
212
213     case 0x05: /* FORMAT TRACK */
214     case 0x06: /* FORMAT TRACK AND SET BAD SECTOR FLAGS */
215     case 0x07: /* FORMAT DRIVE STARTING AT GIVEN TRACK  */
216         INT13_SetStatus( context, 0x0c ); /* unsupported track or invalid media */
217         break;
218
219     case 0x08: /* GET DRIVE PARAMETERS  */
220         if (DL_reg( context ) & 0x80) 
221         {
222             /* hard disk ? */
223             INT13_SetStatus( context, 0x07 ); /* drive parameter activity failed */
224         }
225         else
226         { 
227             /* floppy disk */
228             INT13_ReadFloppyParams( context );
229         }
230         break;
231
232     case 0x09: /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */
233     case 0x0a: /* FIXED DISK - READ LONG */
234     case 0x0b: /* FIXED DISK - WRITE LONG */
235     case 0x0c: /* SEEK TO CYLINDER */
236     case 0x0d: /* ALTERNATE RESET HARD DISK */
237         INT13_SetStatus( context, 0x00 ); /* success */
238         break;
239
240     case 0x0e: /* READ SECTOR BUFFER */
241     case 0x0f: /* WRITE SECTOR BUFFER */
242         INT13_SetStatus( context, 0x01 ); /* invalid function */
243         break;
244
245     case 0x10: /* CHECK IF DRIVE READY */
246     case 0x11: /* RECALIBRATE DRIVE */
247         INT13_SetStatus( context, 0x00 ); /* success */
248         break;
249
250     case 0x12: /* CONTROLLER RAM DIAGNOSTIC */
251     case 0x13: /* DRIVE DIAGNOSTIC */
252         INT13_SetStatus( context, 0x01 ); /* invalid function */
253         break;
254
255     case 0x14: /* CONTROLLER INTERNAL DIAGNOSTIC */
256         INT13_SetStatus( context, 0x00 ); /* success */
257         break;
258
259     case 0x15: /* GET DISK TYPE */
260         if (DL_reg( context ) & 0x80) 
261         {
262             /* hard disk ? */
263             INT13_SetStatus( context, 0x00 ); /* success */
264             /* type is fixed disk, overwrites status */
265             SET_AH( context, 0x03 );
266         }
267         else
268         { 
269             /* floppy disk */
270             INT13_SetStatus( context, 0x00 ); /* success */
271             /* type is floppy with change detection, overwrites status */
272             SET_AH( context, 0x02 );
273         }
274         break;
275
276     case 0x16: /* FLOPPY - CHANGE OF DISK STATUS */
277         INT13_SetStatus( context, 0x00 ); /* success */
278         break;
279
280     case 0x17: /* SET DISK TYPE FOR FORMAT */
281         if (DL_reg( context ) < 4)
282             INT13_SetStatus( context, 0x00 ); /* successful completion */
283         else
284             INT13_SetStatus( context, 0x01 ); /* error */
285         break;
286
287     case 0x18: /* SET MEDIA TYPE FOR FORMAT */
288         if (DL_reg( context ) < 4)
289             INT13_SetStatus( context, 0x00 ); /* success */
290         else
291             INT13_SetStatus( context, 0x01 ); /* error */
292         break;
293
294     case 0x19: /* FIXED DISK - PARK HEADS */
295         INT13_SetStatus( context, 0x00 ); /* success */
296         break;
297
298     default:
299         INT_BARF( context, 0x13 );
300         INT13_SetStatus( context, 0x01 ); /* invalid function */
301     } 
302 }