From 88dadaec33d3b66991cd3eb339af103698b9357b Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Sun, 21 Apr 2002 22:09:47 +0000 Subject: [PATCH] Moved int13 support to the VWIN32_DIOC_DOS_INT13 ioctl. Added support for the floppy parameter table. --- msdos/int13.c | 213 ++++++++++++------------------------------ win32/device.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 299 insertions(+), 161 deletions(-) diff --git a/msdos/int13.c b/msdos/int13.c index 31a2bbda641..76c6f06c4fb 100644 --- a/msdos/int13.c +++ b/msdos/int13.c @@ -19,20 +19,49 @@ */ #include -#include #include -#include -#include -#ifdef linux -# include -#endif +#include + +#include "winbase.h" +#include "winioctl.h" #include "miscemu.h" -/* #define DEBUG_INT */ #include "wine/debug.h" -#include "drive.h" WINE_DEFAULT_DEBUG_CHANNEL(int); +static void DIOCRegs_2_CONTEXT( DIOC_REGISTERS *pIn, CONTEXT86 *pCxt ) +{ + memset( pCxt, 0, sizeof(*pCxt) ); + /* Note: segment registers == 0 means that CTX_SEG_OFF_TO_LIN + will interpret 32-bit register contents as linear pointers */ + + pCxt->ContextFlags=CONTEXT86_INTEGER|CONTEXT86_CONTROL; + pCxt->Eax = pIn->reg_EAX; + pCxt->Ebx = pIn->reg_EBX; + pCxt->Ecx = pIn->reg_ECX; + pCxt->Edx = pIn->reg_EDX; + pCxt->Esi = pIn->reg_ESI; + pCxt->Edi = pIn->reg_EDI; + + /* FIXME: Only partial CONTEXT86_CONTROL */ + pCxt->EFlags = pIn->reg_Flags; +} + +static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut ) +{ + memset( pOut, 0, sizeof(DIOC_REGISTERS) ); + + pOut->reg_EAX = pCxt->Eax; + pOut->reg_EBX = pCxt->Ebx; + pOut->reg_ECX = pCxt->Ecx; + pOut->reg_EDX = pCxt->Edx; + pOut->reg_ESI = pCxt->Esi; + pOut->reg_EDI = pCxt->Edi; + + /* FIXME: Only partial CONTEXT86_CONTROL */ + pOut->reg_Flags = pCxt->EFlags; +} + /********************************************************************** * INT_Int13Handler (WPROCS.119) * @@ -40,156 +69,28 @@ WINE_DEFAULT_DEBUG_CHANNEL(int); */ void WINAPI INT_Int13Handler( CONTEXT86 *context ) { - switch(AH_reg(context)) + HANDLE hVWin32; + DIOC_REGISTERS regs; + DWORD dwRet; + + hVWin32 = CreateFileA("\\\\.\\VWIN32", GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); + + if(hVWin32!=INVALID_HANDLE_VALUE) { - case 0x00: /* RESET DISK SYSTEM */ - 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 ? */ - case 0x04: /* VERIFY DISK SECTOR(S) */ - AL_reg(context) = 0; /* number of sectors verified */ - AH_reg(context) = 0; - break; - - case 0x05: /* FORMAT TRACK */ - case 0x06: /* FORMAT TRACK AND SET BAD SECTOR FLAGS */ - case 0x07: /* FORMAT DRIVE STARTING AT GIVEN TRACK */ - /* despite what Ralf Brown says, 0x06 and 0x07 seem to - * set CFLAG, too (at least my BIOS does that) */ - AH_reg(context) = 0x0c; + CONTEXT_2_DIOCRegs( context, ®s); + + if(!DeviceIoControl(hVWin32, VWIN32_DIOC_DOS_INT13, + ®s, sizeof regs, ®s, sizeof regs, &dwRet, NULL)) + DIOCRegs_2_CONTEXT(®s, context); + else SET_CFLAG(context); - break; - case 0x08: /* GET DRIVE PARAMETERS */ - 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; - char root[] = "A:\\"; - - AH_reg(context) = 0x00; /* success */ - - for (i = 0; i < MAX_DOS_DRIVES; i++, root[0]++) - if (GetDriveTypeA(root) == DRIVE_REMOVABLE) 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) - { - WARN("(GET DRIVE PARAMETERS): Can't determine floppy geometry !\n"); - 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; - } - context->SegEs = 0x0000; /* FIXME: drive parameter table */ - DI_reg(context) = 0x0000; -#else - AH_reg(context) = 0x01; - SET_CFLAG(context); - break; -#endif - } - break; - - case 0x09: /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */ - case 0x0a: /* FIXED DISK - READ LONG (XT,AT,XT286,PS) */ - case 0x0b: /* FIXED DISK - WRITE LONG (XT,AT,XT286,PS) */ - case 0x0c: /* SEEK TO CYLINDER */ - case 0x0d: /* ALTERNATE RESET HARD DISKS */ - case 0x10: /* CHECK IF DRIVE READY */ - case 0x11: /* RECALIBRATE DRIVE */ - case 0x14: /* CONTROLLER INTERNAL DIAGNOSTIC */ - AH_reg(context) = 0; - break; - - 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; - 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) */ - AH_reg(context) = 0x01; - SET_CFLAG(context); - break; - - case 0x16: /* FLOPPY - CHANGE OF DISK STATUS */ - AH_reg(context) = 0; /* FIXME - no change */ - break; - 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; - case 0x18: /* SET MEDIA TYPE FOR FORMAT */ - if (DL_reg(context) < 4) - AH_reg(context) = 0x00; /* successful completion */ - else - AH_reg(context) = 0x01; /* error */ - break; - case 0x19: /* FIXED DISK - PARK HEADS */ - default: - INT_BARF( context, 0x13 ); + CloseHandle(hVWin32); + } + else + { + ERR("Failed to open device VWIN32\n"); + SET_CFLAG(context); } } diff --git a/win32/device.c b/win32/device.c index b03698f3690..d9d18028431 100644 --- a/win32/device.c +++ b/win32/device.c @@ -43,7 +43,15 @@ #include "wine/server.h" #include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(win32); +/* int 13 stuff */ +#include +#include +#ifdef linux +# include +#endif +#include "drive.h" + +WINE_DEFAULT_DEBUG_CHANNEL(file); static BOOL DeviceIo_VTDAPI(DWORD dwIoControlCode, @@ -1152,6 +1160,228 @@ static void CONTEXT_2_DIOCRegs( CONTEXT86 *pCxt, DIOC_REGISTERS *pOut ) pOut->reg_Flags = pCxt->EFlags; } +#define DIOC_AH(regs) (((unsigned char*)&((regs)->reg_EAX))[1]) +#define DIOC_AL(regs) (((unsigned char*)&((regs)->reg_EAX))[0]) +#define DIOC_BH(regs) (((unsigned char*)&((regs)->reg_EBX))[1]) +#define DIOC_BL(regs) (((unsigned char*)&((regs)->reg_EBX))[0]) +#define DIOC_DH(regs) (((unsigned char*)&((regs)->reg_EDX))[1]) +#define DIOC_DL(regs) (((unsigned char*)&((regs)->reg_EDX))[0]) + +#define DIOC_AX(regs) (((unsigned short*)&((regs)->reg_EAX))[0]) +#define DIOC_BX(regs) (((unsigned short*)&((regs)->reg_EBX))[0]) +#define DIOC_CX(regs) (((unsigned short*)&((regs)->reg_ECX))[0]) +#define DIOC_DX(regs) (((unsigned short*)&((regs)->reg_EDX))[0]) + +#define DIOC_SET_CARRY(regs) (((regs)->reg_Flags)|=0x00000001) + +static const DWORD VWIN32_DriveTypeInfo[7]={ + 0x0000, /* none */ + 0x2709, /* 360 K */ + 0x4f0f, /* 1.2 M */ + 0x4f09, /* 720 K */ + 0x4f12, /* 1.44 M */ + 0x4f24, /* 2.88 M */ + 0x4f24 /* 2.88 M */ +}; + +static BYTE floppy_params[2][13] = +{ + { 0xaf, 0x02, 0x25, 0x02, 0x12, 0x1b, 0xff, 0x6c, 0xf6, 0x0f, 0x08 }, + { 0xaf, 0x02, 0x25, 0x02, 0x12, 0x1b, 0xff, 0x6c, 0xf6, 0x0f, 0x08 } +}; + +/********************************************************************** + * VWIN32_ReadFloppyParams + * + * Handler for int 13h (disk I/O). + */ +static VOID VWIN32_ReadFloppyParams(DIOC_REGISTERS *regs) +{ +#ifdef linux + unsigned int i, nr_of_drives = 0; + BYTE drive_nr = DIOC_DL(regs); + int floppy_fd,r; + struct floppy_drive_params floppy_parm; + char root[] = "A:\\"; + + TRACE("in [ EDX=%08lx ]\n", regs->reg_EDX ); + + DIOC_AH(regs) = 0x00; /* success */ + + for (i = 0; i < MAX_DOS_DRIVES; i++, root[0]++) + if (GetDriveTypeA(root) == DRIVE_REMOVABLE) nr_of_drives++; + DIOC_DL(regs) = nr_of_drives; + + if (drive_nr > 1) { /* invalid drive ? */ + DIOC_BX(regs) = 0; + DIOC_CX(regs) = 0; + DIOC_DH(regs) = 0; + DIOC_SET_CARRY(regs); + return; + } + + if ( (floppy_fd = DRIVE_OpenDevice( drive_nr, O_NONBLOCK)) == -1) + { + WARN("Can't determine floppy geometry !\n"); + DIOC_BX(regs) = 0; + DIOC_CX(regs) = 0; + DIOC_DH(regs) = 0; + DIOC_SET_CARRY(regs); + return; + } + r = ioctl(floppy_fd, FDGETDRVPRM, &floppy_parm); + + close(floppy_fd); + + if(r<0) + { + DIOC_SET_CARRY(regs); + return; + } + + regs->reg_ECX = 0; + DIOC_AL(regs) = 0; + DIOC_BL(regs) = 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 */ + if(DIOC_BL(regs) && (DIOC_BL(regs)<7)) + { + DIOC_DH(regs) = 0x01; + DIOC_CX(regs) = VWIN32_DriveTypeInfo[DIOC_BL(regs)]; + } + else + { + DIOC_CX(regs) = 0x0; + DIOC_DX(regs) = 0x0; + } + + regs->reg_EDI = (DWORD)floppy_params[drive_nr]; + + if(!regs->reg_EDI) + { + ERR("Get floppy params failed for drive %d\n",drive_nr); + DIOC_SET_CARRY(regs); + } + + TRACE("out [ EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx EDI=%08lx ]\n", + regs->reg_EAX, regs->reg_EBX, regs->reg_ECX, regs->reg_EDX, regs->reg_EDI); + + /* FIXME: Word exits quietly if we return with no error. Why? */ + FIXME("Returned ERROR!\n"); + DIOC_SET_CARRY(regs); + +#else + DIOC_AH(regs) = 0x01; + DIOC_SET_CARRY(regs); +#endif +} + +/********************************************************************** + * VWIN32_Int13Handler + * + * Handler for VWIN32_DIOC_DOS_INT13 (disk I/O). + */ +static VOID VWIN32_Int13Handler( DIOC_REGISTERS *regs) +{ + TRACE("AH=%02x\n",DIOC_AH(regs)); + switch(DIOC_AH(regs)) /* AH */ + { + case 0x00: /* RESET DISK SYSTEM */ + break; /* no return ? */ + + case 0x01: /* STATUS OF DISK SYSTEM */ + DIOC_AL(regs) = 0; /* successful completion */ + break; + + case 0x02: /* READ SECTORS INTO MEMORY */ + DIOC_AL(regs) = 0; /* number of sectors read */ + DIOC_AH(regs) = 0; /* status */ + break; + + case 0x03: /* WRITE SECTORS FROM MEMORY */ + break; /* no return ? */ + + case 0x04: /* VERIFY DISK SECTOR(S) */ + DIOC_AL(regs) = 0; /* number of sectors verified */ + DIOC_AH(regs) = 0; + break; + + case 0x05: /* FORMAT TRACK */ + case 0x06: /* FORMAT TRACK AND SET BAD SECTOR FLAGS */ + case 0x07: /* FORMAT DRIVE STARTING AT GIVEN TRACK */ + /* despite what Ralf Brown says, 0x06 and 0x07 seem to + * set CFLAG, too (at least my BIOS does that) */ + DIOC_AH(regs) = 0x0c; + DIOC_SET_CARRY(regs); + break; + + case 0x08: /* GET DRIVE PARAMETERS */ + if (DIOC_DL(regs) & 0x80) { /* hard disk ? */ + DIOC_AH(regs) = 0x07; + DIOC_SET_CARRY(regs); + } + else /* floppy disk */ + VWIN32_ReadFloppyParams(regs); + break; + + case 0x09: /* INITIALIZE CONTROLLER WITH DRIVE PARAMETERS */ + case 0x0a: /* FIXED DISK - READ LONG (XT,AT,XT286,PS) */ + case 0x0b: /* FIXED DISK - WRITE LONG (XT,AT,XT286,PS) */ + case 0x0c: /* SEEK TO CYLINDER */ + case 0x0d: /* ALTERNATE RESET HARD DISKS */ + case 0x10: /* CHECK IF DRIVE READY */ + case 0x11: /* RECALIBRATE DRIVE */ + case 0x14: /* CONTROLLER INTERNAL DIAGNOSTIC */ + DIOC_AH(regs) = 0; + break; + + case 0x15: /* GET DISK TYPE (AT,XT2,XT286,CONV,PS) */ + if (DIOC_DL(regs) & 0x80) { /* hard disk ? */ + DIOC_AH(regs) = 3; /* fixed disk */ + DIOC_SET_CARRY(regs); + } + else { /* floppy disk ? */ + DIOC_AH(regs) = 2; /* floppy with change detection */ + DIOC_SET_CARRY(regs); + } + break; + + 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) */ + DIOC_AH(regs) = 0x01; + DIOC_SET_CARRY(regs); + break; + + case 0x16: /* FLOPPY - CHANGE OF DISK STATUS */ + DIOC_AH(regs) = 0; /* FIXME - no change */ + break; + + case 0x17: /* SET DISK TYPE FOR FORMAT */ + if (DIOC_DL(regs) < 4) + DIOC_AH(regs) = 0x00; /* successful completion */ + else + DIOC_AH(regs) = 0x01; /* error */ + break; + + case 0x18: /* SET MEDIA TYPE FOR FORMAT */ + if (DIOC_DL(regs) < 4) + DIOC_AH(regs) = 0x00; /* successful completion */ + else + DIOC_AH(regs) = 0x01; /* error */ + break; + + case 0x19: /* FIXED DISK - PARK HEADS */ + break; + + default: + FIXME("Unknown VWIN32 INT13 call AX=%04X\n",DIOC_AX(regs)); + } +} static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, @@ -1163,8 +1393,17 @@ static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, switch (dwIoControlCode) { - case VWIN32_DIOC_DOS_IOCTL: case VWIN32_DIOC_DOS_INT13: + { + DIOC_REGISTERS *pIn = (DIOC_REGISTERS *)lpvInBuffer; + DIOC_REGISTERS *pOut = (DIOC_REGISTERS *)lpvOutBuffer; + + memcpy(pOut, pIn, sizeof (DIOC_REGISTERS)); + VWIN32_Int13Handler(pOut); + break; + } + + case VWIN32_DIOC_DOS_IOCTL: case VWIN32_DIOC_DOS_INT25: case VWIN32_DIOC_DOS_INT26: case VWIN32_DIOC_DOS_DRIVEINFO: @@ -1175,9 +1414,8 @@ static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, TRACE( "Control '%s': " "eax=0x%08lx, ebx=0x%08lx, ecx=0x%08lx, " - "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx ", + "edx=0x%08lx, esi=0x%08lx, edi=0x%08lx \n", (dwIoControlCode == VWIN32_DIOC_DOS_IOCTL)? "VWIN32_DIOC_DOS_IOCTL" : - (dwIoControlCode == VWIN32_DIOC_DOS_INT13)? "VWIN32_DIOC_DOS_INT13" : (dwIoControlCode == VWIN32_DIOC_DOS_INT25)? "VWIN32_DIOC_DOS_INT25" : (dwIoControlCode == VWIN32_DIOC_DOS_INT26)? "VWIN32_DIOC_DOS_INT26" : (dwIoControlCode == VWIN32_DIOC_DOS_DRIVEINFO)? "VWIN32_DIOC_DOS_DRIVEINFO" : "???", @@ -1189,7 +1427,6 @@ static BOOL DeviceIo_VWin32(DWORD dwIoControlCode, switch (dwIoControlCode) { case VWIN32_DIOC_DOS_IOCTL: DOS3Call( &cxt ); break; /* Call int 21h */ - case VWIN32_DIOC_DOS_INT13: INT_Int13Handler( &cxt ); break; case VWIN32_DIOC_DOS_INT25: INT_Int25Handler( &cxt ); break; case VWIN32_DIOC_DOS_INT26: INT_Int26Handler( &cxt ); break; case VWIN32_DIOC_DOS_DRIVEINFO: DOS3Call( &cxt ); break; /* Call int 21h 730x */