Add a missing </sect3>.
[wine] / msdos / int13.c
1 /*
2  * BIOS interrupt 13h handler
3  */
4
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/ioctl.h>
10 #include <fcntl.h>
11 #ifdef linux
12 #include <linux/fd.h>
13 #endif
14 #include "miscemu.h"
15 /* #define DEBUG_INT */
16 #include "debugtools.h"
17 #include "drive.h"
18
19 DEFAULT_DEBUG_CHANNEL(int);
20
21 /**********************************************************************
22  *          INT_Int13Handler
23  *
24  * Handler for int 13h (disk I/O).
25  */
26 void WINAPI INT_Int13Handler( CONTEXT86 *context )
27 {
28     switch(AH_reg(context))
29     {
30         case 0x00:                            /* RESET DISK SYSTEM     */
31                 break; /* no return ? */
32         case 0x01:                            /* STATUS OF DISK SYSTEM */
33                 AL_reg(context) = 0; /* successful completion */
34                 break;
35         case 0x02:                            /* READ SECTORS INTO MEMORY */
36                 AL_reg(context) = 0; /* number of sectors read */
37                 AH_reg(context) = 0; /* status */
38                 break;
39         case 0x03:                            /* WRITE SECTORS FROM MEMORY */
40                 break; /* no return ? */
41         case 0x04:                            /* VERIFY DISK SECTOR(S) */
42                 AL_reg(context) = 0; /* number of sectors verified */
43                 AH_reg(context) = 0;
44                 break;
45                
46         case 0x05:                                     /* FORMAT TRACK */
47         case 0x06:             /* FORMAT TRACK AND SET BAD SECTOR FLAGS */
48         case 0x07:             /* FORMAT DRIVE STARTING AT GIVEN TRACK  */
49             /* despite what Ralf Brown says, 0x06 and 0x07 seem to
50              * set CFLAG, too (at least my BIOS does that) */
51             AH_reg(context) = 0x0c;
52             SET_CFLAG(context);
53             break;
54
55         case 0x08:                              /* GET DRIVE PARAMETERS  */
56                 if (DL_reg(context) & 0x80) { /* hard disk ? */
57                         AH_reg(context) = 0x07;
58                         SET_CFLAG(context);
59                 }
60                 else { /* floppy disk */
61 #ifdef linux
62                         unsigned int i, nr_of_drives = 0;                       
63                         BYTE drive_nr = DL_reg(context);
64                         int floppy_fd;
65                         struct floppy_drive_params floppy_parm;
66                         char root[] = "A:\\";
67
68                         AH_reg(context) = 0x00; /* success */
69
70                         for (i = 0; i < MAX_DOS_DRIVES; i++, root[0]++)
71                             if (GetDriveTypeA(root) == DRIVE_REMOVABLE) nr_of_drives++;
72                         DL_reg(context) = nr_of_drives;
73
74                         if (drive_nr > 1) { /* invalid drive ? */
75                                 BX_reg(context) = 0;
76                                 CX_reg(context) = 0;
77                                 DH_reg(context) = 0;
78                                 break;
79                         }
80
81                         if ( (floppy_fd = DRIVE_OpenDevice( drive_nr, O_NONBLOCK)) == -1)
82                         {
83                                 WARN("(GET DRIVE PARAMETERS): Can't determine floppy geometry !\n");
84                                 BX_reg(context) = 0;
85                                 CX_reg(context) = 0;
86                                 DH_reg(context) = 0;
87                                 break;
88                         }
89                         ioctl(floppy_fd, FDGETDRVPRM, &floppy_parm);
90                         close(floppy_fd);
91
92                         BL_reg(context) = floppy_parm.cmos;
93
94                         /* CH = low eight bits of max cyl
95                            CL = max sec nr (bits 5-0),
96                            hi two bits of max cyl (bits 7-6)
97                            DH = max head nr */ 
98                         DH_reg(context) = 0x01;
99                         switch (BL_reg(context))
100                         {
101                             case 0: /* no drive */
102                                 CX_reg(context) = 0x0;
103                                 DX_reg(context) = 0x0;
104                                 break;
105                             case 1: /* 360 K */
106                                 CX_reg(context) = 0x2709;
107                                 break;
108                             case 2: /* 1.2 M */
109                                 CX_reg(context) = 0x4f0f;
110                                 break;
111                             case 3: /* 720 K */
112                                 CX_reg(context) = 0x4f09;
113                                 break;
114                             case 4: /* 1.44 M */
115                                 CX_reg(context) = 0x4f12;
116                                 break;
117                             case 5:
118                             case 6: /* 2.88 M */
119                                 CX_reg(context) = 0x4f24;
120                                 break;
121                         }
122                         context->SegEs = 0x0000; /* FIXME: drive parameter table */
123                         DI_reg(context) = 0x0000;
124 #else
125                         AH_reg(context) = 0x01;
126                         SET_CFLAG(context);
127                         break;
128 #endif
129                 }
130                 break;
131
132         case 0x09:         /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */
133         case 0x0a:         /* FIXED DISK - READ LONG (XT,AT,XT286,PS)     */
134         case 0x0b:         /* FIXED DISK - WRITE LONG (XT,AT,XT286,PS)    */
135         case 0x0c:         /* SEEK TO CYLINDER                            */
136         case 0x0d:         /* ALTERNATE RESET HARD DISKS                  */
137         case 0x10:         /* CHECK IF DRIVE READY                        */
138         case 0x11:         /* RECALIBRATE DRIVE                           */
139         case 0x14:         /* CONTROLLER INTERNAL DIAGNOSTIC              */
140                 AH_reg(context) = 0;
141                 break;
142
143         case 0x15:         /* GET DISK TYPE (AT,XT2,XT286,CONV,PS) */
144                 if (DL_reg(context) & 0x80) { /* hard disk ? */
145                         AH_reg(context) = 3; /* fixed disk */
146                         SET_CFLAG(context);
147                 }
148                 else { /* floppy disk ? */
149                         AH_reg(context) = 2; /* floppy with change detection */
150                         SET_CFLAG(context);
151                 }
152                 break;
153         case 0x0e:                    /* READ SECTOR BUFFER (XT only)      */
154         case 0x0f:                    /* WRITE SECTOR BUFFER (XT only)     */
155         case 0x12:                    /* CONTROLLER RAM DIAGNOSTIC (XT,PS) */
156         case 0x13:                    /* DRIVE DIAGNOSTIC (XT,PS)          */
157                 AH_reg(context) = 0x01;
158                 SET_CFLAG(context);
159                 break;
160
161         case 0x16:         /* FLOPPY - CHANGE OF DISK STATUS */
162                 AH_reg(context) = 0; /* FIXME - no change */
163                 break;
164         case 0x17:         /* SET DISK TYPE FOR FORMAT */
165                 if (DL_reg(context) < 4)
166                     AH_reg(context) = 0x00; /* successful completion */
167                 else
168                     AH_reg(context) = 0x01; /* error */
169                 break;
170         case 0x18:         /* SET MEDIA TYPE FOR FORMAT */
171                 if (DL_reg(context) < 4)
172                     AH_reg(context) = 0x00; /* successful completion */
173                 else
174                     AH_reg(context) = 0x01; /* error */
175                 break;
176         case 0x19:         /* FIXED DISK - PARK HEADS */
177         default:
178                 INT_BARF( context, 0x13 );
179     }
180 }