int13.c 5.54 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * BIOS interrupt 13h handler
 */

Alexandre Julliard's avatar
Alexandre Julliard committed
5
#include <stdlib.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
6 7 8 9 10 11 12 13
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef linux
#include <linux/fd.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
14
#include "miscemu.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
15
/* #define DEBUG_INT */
16
#include "debugtools.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
17
#include "drive.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
18

19 20
DEFAULT_DEBUG_CHANNEL(int)

Alexandre Julliard's avatar
Alexandre Julliard committed
21 22 23 24 25
/**********************************************************************
 *	    INT_Int13Handler
 *
 * Handler for int 13h (disk I/O).
 */
26
void WINAPI INT_Int13Handler( CONTEXT86 *context )
Alexandre Julliard's avatar
Alexandre Julliard committed
27
{
Alexandre Julliard's avatar
Alexandre Julliard committed
28
    switch(AH_reg(context))
Alexandre Julliard's avatar
Alexandre Julliard committed
29
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
30
	case 0x00:                            /* RESET DISK SYSTEM     */
31 32 33 34 35 36 37 38 39 40
		break; /* no return ? */
	case 0x01:			      /* STATUS OF DISK SYSTEM */
		AL_reg(context) = 0; /* successful completion */
		break;
	case 0x02:			      /* READ SECTORS INTO MEMORY */
		AL_reg(context) = 0; /* number of sectors read */
		AH_reg(context) = 0; /* status */
		break;
	case 0x03:			      /* WRITE SECTORS FROM MEMORY */
		break; /* no return ? */
Alexandre Julliard's avatar
Alexandre Julliard committed
41
	case 0x04:                            /* VERIFY DISK SECTOR(S) */
42
		AL_reg(context) = 0; /* number of sectors verified */
Alexandre Julliard's avatar
Alexandre Julliard committed
43
		AH_reg(context) = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
44 45 46
		break;
	       
	case 0x05:                                     /* FORMAT TRACK */
Alexandre Julliard's avatar
Alexandre Julliard committed
47 48
        case 0x06:             /* FORMAT TRACK AND SET BAD SECTOR FLAGS */
        case 0x07:             /* FORMAT DRIVE STARTING AT GIVEN TRACK  */
Alexandre Julliard's avatar
Alexandre Julliard committed
49 50 51 52 53
            /* despite what Ralf Brown says, 0x06 and 0x07 seem to
             * set CFLAG, too (at least my BIOS does that) */
            AH_reg(context) = 0x0c;
            SET_CFLAG(context);
            break;
Alexandre Julliard's avatar
Alexandre Julliard committed
54 55

	case 0x08:                              /* GET DRIVE PARAMETERS  */
Alexandre Julliard's avatar
Alexandre Julliard committed
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
		if (DL_reg(context) & 0x80) { /* hard disk ? */
			AH_reg(context) = 0x07;
			SET_CFLAG(context);
		}
		else { /* floppy disk */
#ifdef linux
			unsigned int i, nr_of_drives = 0;			
			BYTE drive_nr = DL_reg(context);
                        int floppy_fd;
                        struct floppy_drive_params floppy_parm;

                        AH_reg(context) = 0x00; /* success */

                        for (i = 0; i < MAX_DOS_DRIVES; i++)
                        if (DRIVE_GetType(i) == TYPE_FLOPPY) nr_of_drives++;
                        DL_reg(context) = nr_of_drives;

			if (drive_nr > 1) { /* invalid drive ? */
				BX_reg(context) = 0;
				CX_reg(context) = 0;
				DH_reg(context) = 0;
				break;
			}

                        if ( (floppy_fd = DRIVE_OpenDevice( drive_nr, O_NONBLOCK)) == -1)
                        {
82
                                WARN("(GET DRIVE PARAMETERS): Can't determine floppy geometry !\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
                                BX_reg(context) = 0;
                                CX_reg(context) = 0;
                                DH_reg(context) = 0;
                                break;
                        }
                        ioctl(floppy_fd, FDGETDRVPRM, &floppy_parm);
                        close(floppy_fd);

			BL_reg(context) = floppy_parm.cmos;

			/* CH = low eight bits of max cyl
			   CL = max sec nr (bits 5-0),
			   hi two bits of max cyl (bits 7-6)
			   DH = max head nr */ 
			DH_reg(context) = 0x01;
			switch (BL_reg(context))
			{
			    case 0: /* no drive */
				CX_reg(context) = 0x0;
				DX_reg(context) = 0x0;
				break;
			    case 1: /* 360 K */
				CX_reg(context) = 0x2709;
				break;
			    case 2: /* 1.2 M */
				CX_reg(context) = 0x4f0f;
				break;
			    case 3: /* 720 K */
				CX_reg(context) = 0x4f09;
				break;
			    case 4: /* 1.44 M */
				CX_reg(context) = 0x4f12;
				break;
			    case 5:
			    case 6: /* 2.88 M */
				CX_reg(context) = 0x4f24;
				break;
			}
121
			context->SegEs = 0x0000; /* FIXME: drive parameter table */
Alexandre Julliard's avatar
Alexandre Julliard committed
122 123 124 125 126 127 128
			DI_reg(context) = 0x0000;
#else
                	AH_reg(context) = 0x01;
                	SET_CFLAG(context);
                	break;
#endif
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
129 130 131
		break;

        case 0x09:         /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */
132 133
	case 0x0a:         /* FIXED DISK - READ LONG (XT,AT,XT286,PS)     */
	case 0x0b:	   /* FIXED DISK - WRITE LONG (XT,AT,XT286,PS)    */
Alexandre Julliard's avatar
Alexandre Julliard committed
134
	case 0x0c:         /* SEEK TO CYLINDER                            */
135
	case 0x0d:         /* ALTERNATE RESET HARD DISKS                  */
Alexandre Julliard's avatar
Alexandre Julliard committed
136 137 138
	case 0x10:         /* CHECK IF DRIVE READY                        */
	case 0x11:         /* RECALIBRATE DRIVE                           */
	case 0x14:         /* CONTROLLER INTERNAL DIAGNOSTIC              */
Alexandre Julliard's avatar
Alexandre Julliard committed
139
		AH_reg(context) = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
140 141
		break;

142 143 144 145 146 147 148 149 150 151
	case 0x15:	   /* GET DISK TYPE (AT,XT2,XT286,CONV,PS) */
		if (DL_reg(context) & 0x80) { /* hard disk ? */
			AH_reg(context) = 3; /* fixed disk */
			SET_CFLAG(context);
		}
		else { /* floppy disk ? */
			AH_reg(context) = 2; /* floppy with change detection */
			SET_CFLAG(context);
		}
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
152 153 154 155
	case 0x0e:                    /* READ SECTOR BUFFER (XT only)      */
	case 0x0f:                    /* WRITE SECTOR BUFFER (XT only)     */
        case 0x12:                    /* CONTROLLER RAM DIAGNOSTIC (XT,PS) */
	case 0x13:                    /* DRIVE DIAGNOSTIC (XT,PS)          */
Alexandre Julliard's avatar
Alexandre Julliard committed
156 157
		AH_reg(context) = 0x01;
                SET_CFLAG(context);
Alexandre Julliard's avatar
Alexandre Julliard committed
158 159
		break;

160 161 162
	case 0x16:	   /* FLOPPY - CHANGE OF DISK STATUS */
		AH_reg(context) = 0; /* FIXME - no change */
		break;
Alexandre Julliard's avatar
Alexandre Julliard committed
163 164 165 166 167 168
	case 0x17:	   /* SET DISK TYPE FOR FORMAT */
		if (DL_reg(context) < 4)
		    AH_reg(context) = 0x00; /* successful completion */
		else
		    AH_reg(context) = 0x01; /* error */
		break;
169
	case 0x18:         /* SET MEDIA TYPE FOR FORMAT */
Alexandre Julliard's avatar
Alexandre Julliard committed
170 171 172 173 174
		if (DL_reg(context) < 4)
		    AH_reg(context) = 0x00; /* successful completion */
		else
		    AH_reg(context) = 0x01; /* error */
		break;
175
	case 0x19:	   /* FIXED DISK - PARK HEADS */
Alexandre Julliard's avatar
Alexandre Julliard committed
176
	default:
Alexandre Julliard's avatar
Alexandre Julliard committed
177
		INT_BARF( context, 0x13 );
Alexandre Julliard's avatar
Alexandre Julliard committed
178
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
179
}