From 9d01ce4bfcb86648ad5c734a4aaae0ef02cc5170 Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Mon, 31 May 2004 14:47:12 +0000 Subject: [PATCH] - raw floppy access now supported in Win 9x (patch from Ben Lunt) --- bochs/iodev/floppy.cc | 133 +++++++++++++++++++++++++++++++++--------- bochs/iodev/floppy.h | 49 +++++++++++++++- 2 files changed, 155 insertions(+), 27 deletions(-) diff --git a/bochs/iodev/floppy.cc b/bochs/iodev/floppy.cc index 027095c84..31e187b03 100644 --- a/bochs/iodev/floppy.cc +++ b/bochs/iodev/floppy.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: floppy.cc,v 1.72 2004-02-08 18:38:26 vruppert Exp $ +// $Id: floppy.cc,v 1.73 2004-05-31 14:47:12 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. @@ -132,7 +132,7 @@ bx_floppy_ctrl_c::init(void) { Bit8u i; - BX_DEBUG(("Init $Id: floppy.cc,v 1.72 2004-02-08 18:38:26 vruppert Exp $")); + BX_DEBUG(("Init $Id: floppy.cc,v 1.73 2004-05-31 14:47:12 vruppert Exp $")); DEV_dma_register_8bit_channel(2, dma_read, dma_write, "Floppy Drive"); DEV_register_irq(6, "Floppy Drive"); for (unsigned addr=0x03F2; addr<=0x03F7; addr++) { @@ -1007,9 +1007,12 @@ bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) #endif { - ret = lseek(BX_FD_THIS s.media[drive].fd, offset, SEEK_SET); - if (ret < 0) { - BX_PANIC(("could not perform lseek() on floppy image file")); + // don't need to seek the file if we are using Win95 type direct access + if (!BX_FD_THIS s.media[drive].raw_floppy_win95) { + ret = lseek(BX_FD_THIS s.media[drive].fd, offset, SEEK_SET); + if (ret < 0) { + BX_PANIC(("could not perform lseek() on floppy image file")); + } } } @@ -1018,8 +1021,31 @@ bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) ret = fd_read((char *) buffer, offset, bytes); else +#endif +#ifdef WIN32 + // if using Win95 direct access + if (BX_FD_THIS s.media[drive].raw_floppy_win95) { + DWORD ret_cnt = 0; + DIOC_REGISTERS reg; + HANDLE hFile = CreateFile("\\\\.\\vwin32", 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (hFile == INVALID_HANDLE_VALUE) + BX_PANIC(("Could not open floppy device under Win95 for read")); + reg.reg_ECX = bytes >> 9; // / 512 + reg.reg_EDX = offset >> 9; // / 512 + reg.reg_EBX = (DWORD) buffer; + reg.reg_EAX = BX_FD_THIS s.media[drive].raw_floppy_win95_drv; + DeviceIoControl(hFile, VWIN32_DIOC_DOS_INT25, + ®, sizeof(reg), ®, sizeof(reg), &ret_cnt, NULL); + CloseHandle(hFile); + // I don't know why this returns 28 instead of 512, but it works + if (ret_cnt == 28) + ret = 512; + } else { #endif ret = ::read(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes); +#ifdef WIN32 + } +#endif if (ret < int(bytes)) { /* ??? */ if (ret > 0) { @@ -1040,8 +1066,31 @@ bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) ret = fd_write((char *) buffer, offset, bytes); else +#endif +#ifdef WIN32 + // if using Win95 direct access + if (BX_FD_THIS s.media[drive].raw_floppy_win95) { + DWORD ret_cnt = 0; + DIOC_REGISTERS reg; + HANDLE hFile = CreateFile("\\\\.\\vwin32", 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (hFile == INVALID_HANDLE_VALUE) + BX_PANIC(("Could not open floppy device under Win95")); + reg.reg_ECX = bytes >> 9; // / 512 + reg.reg_EDX = offset >> 9; // / 512 + reg.reg_EBX = (DWORD) buffer; + reg.reg_EAX = BX_FD_THIS s.media[drive].raw_floppy_win95_drv; + DeviceIoControl(hFile, VWIN32_DIOC_DOS_INT26, + ®, sizeof(reg), ®, sizeof(reg), (LPDWORD) &ret_cnt, NULL); + CloseHandle(hFile); + // I don't know why this returns 28 instead of 512, but it works + if (ret_cnt == 28) + ret = 512; + } else { #endif ret = ::write(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes); +#ifdef WIN32 + } +#endif if (ret < int(bytes)) { BX_PANIC(("could not perform write() on floppy image file")); } @@ -1406,6 +1455,7 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media) // open media file (image file or device) media->write_protected = 0; + media->raw_floppy_win95 = 0; #ifdef macintosh media->fd = 0; if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) @@ -1417,8 +1467,34 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media) hFile = CreateFile(sTemp, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { - BX_ERROR(("Cannot open floppy drive")); - return(0); + // try to open it with Win95 style + hFile = CreateFile("\\\\.\\vwin32", 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + BX_ERROR(("Cannot open floppy drive")); + return(0); + } + media->raw_floppy_win95 = 1; + media->raw_floppy_win95_drv = toupper(path[0]) - 'A'; + } + // if using Win95 direct access, get params this way + if (media->raw_floppy_win95) { + DWORD ret_cnt = 0; + DIOC_REGISTERS reg; + BLOCK_DEV_PARAMS params; + reg.reg_EAX = 0x440D; + reg.reg_ECX = 0x0860; + reg.reg_EDX = (DWORD) ¶ms; + reg.reg_EBX = media->raw_floppy_win95_drv+1; + //reg.reg_Flags = 0x0001; // assume error (carry flag is set) + if (DeviceIoControl(hFile, VWIN32_DIOC_DOS_IOCTL , + ®, sizeof(reg), ®, sizeof(reg), &ret_cnt, NULL)) { + tracks = params.cylinders; + heads = params.num_heads; + spt = params.sects_per_track; + } else { + CloseHandle(hFile); + return(0); + } } else { if (!DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg), &bytes, NULL)) { BX_ERROR(("No media in floppy drive")); @@ -1429,9 +1505,11 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media) heads = (unsigned)dg.TracksPerCylinder; spt = (unsigned)dg.SectorsPerTrack; } - CloseHandle(hFile); } - media->fd = open(sTemp, BX_RDWR); + CloseHandle(hFile); + // if using Win95 direct access, don't open the file + if (!media->raw_floppy_win95) + media->fd = open(sTemp, BX_RDWR); } else { media->fd = open(path, BX_RDWR); } @@ -1439,28 +1517,31 @@ bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media) media->fd = open(path, BX_RDWR); #endif - if (media->fd < 0) { - BX_INFO(( "tried to open '%s' read/write: %s",path,strerror(errno) )); - // try opening the file read-only - media->write_protected = 1; + // Don't open the handle if using Win95 style direct access + if (!media->raw_floppy_win95) { + if (media->fd < 0) { + BX_INFO(( "tried to open '%s' read/write: %s",path,strerror(errno) )); + // try opening the file read-only + media->write_protected = 1; #ifdef macintosh - media->fd = 0; - if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) + media->fd = 0; + if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) #endif #ifdef WIN32 - if (raw_floppy == 1) { - media->fd = open(sTemp, BX_RDONLY); - } else { - media->fd = open(path, BX_RDONLY); - } + if (raw_floppy == 1) { + media->fd = open(sTemp, BX_RDONLY); + } else { + media->fd = open(path, BX_RDONLY); + } #else - media->fd = open(path, BX_RDONLY); + media->fd = open(path, BX_RDONLY); #endif - if (media->fd < 0) { - // failed to open read-only too - BX_INFO(( "tried to open '%s' read only: %s",path,strerror(errno) )); - media->type = type; - return(0); + if (media->fd < 0) { + // failed to open read-only too + BX_INFO(( "tried to open '%s' read only: %s",path,strerror(errno) )); + media->type = type; + return(0); + } } } diff --git a/bochs/iodev/floppy.h b/bochs/iodev/floppy.h index 9a1ec2281..48f1fc36b 100644 --- a/bochs/iodev/floppy.h +++ b/bochs/iodev/floppy.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: floppy.h,v 1.17 2004-02-07 14:34:34 vruppert Exp $ +// $Id: floppy.h,v 1.18 2004-05-31 14:47:12 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. @@ -45,6 +45,10 @@ typedef struct { unsigned heads; /* number of heads */ unsigned type; unsigned write_protected; + unsigned char raw_floppy_win95; +#ifdef WIN32 + unsigned char raw_floppy_win95_drv; +#endif } floppy_t; class bx_floppy_ctrl_c : public bx_floppy_stub_c { @@ -137,3 +141,46 @@ public: BX_FD_SMF void increment_sector(void); BX_FD_SMF bx_bool evaluate_media(unsigned type, char *path, floppy_t *floppy); }; + + +#ifdef WIN32 + +// used for direct floppy access in Win95 +#define VWIN32_DIOC_DOS_IOCTL 1 +#define VWIN32_DIOC_DOS_INT25 2 +#define VWIN32_DIOC_DOS_INT26 3 + +typedef struct _DIOC_REGISTERS { + DWORD reg_EBX; + DWORD reg_EDX; + DWORD reg_ECX; + DWORD reg_EAX; + DWORD reg_EDI; + DWORD reg_ESI; + DWORD reg_Flags; +} DIOC_REGISTERS, *PDIOC_REGISTERS; + +#pragma pack(push, 1) +typedef struct _BLOCK_DEV_PARAMS { + BYTE features; + BYTE dev_type; + WORD attribs; + WORD cylinders; + BYTE media_type; + // BPB + WORD bytes_per_sector; + BYTE sect_per_cluster; + WORD reserved_sectors; + BYTE fats; + WORD root_entries; + WORD tot_sectors; + BYTE media_id; + WORD sects_per_fat; + WORD sects_per_track; + WORD num_heads; + WORD hidden_sectors; + BYTE remainder[5]; +} BLOCK_DEV_PARAMS, *PBLOCK_DEV_PARAMS; +#pragma pack(pop) + +#endif