Fix Int21 block device read/write

Andreas Mohr andi at rhlx01.fht-esslingen.de
Sun Sep 5 04:40:57 CDT 2004


Hi all,

this functionality was rather completely broken:
- struct dereferencing was wrong
- no segmented to linear calc
- the linear block address calculation was wrong (it's NOT
a simple x*y*z calc)

So I fixed all that (took me a slight while to figure all that out)
and:
- moved device block access log messages to inner function
  used by two different places
- remove bogus CloseHandle()

Note that the geometry of devices is not queried from the system
(some default values used).
That's why we don't write for drive letters other than A:
This should probably be done by querying NT APIs for drive
attributes (which ones are those?), since we want this functionality
to reside in the NT layer, for speed reasons and a cleaner
architecture.

This patch, together with the OS/2 binary patch, makes the Dell
system utility actually write a fully functional DOS disk
instead of writing very incomprehensible garbage data. :-)

Andreas Mohr
-------------- next part --------------
Determining best CVS host...
Using CVSROOT :pserver:cvs at rhlx01.fht-esslingen.de:/home/wine
Index: dlls/winedos/int21.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int21.c,v
retrieving revision 1.68
diff -u -r1.68 int21.c
--- dlls/winedos/int21.c	18 Aug 2004 00:04:58 -0000	1.68
+++ dlls/winedos/int21.c	5 Sep 2004 09:25:49 -0000
@@ -2408,6 +2408,12 @@
     }
 }
 
+inline DWORD INT21_Ioctl_CylHeadSect2Lin(WORD cyl, WORD head, WORD sec, WORD cyl_cnt, WORD head_cnt, WORD sec_cnt)
+{
+    DWORD res = (cyl * head_cnt*sec_cnt + head * sec_cnt + sec);
+    return res;
+}
+
 /***********************************************************************
  *           INT21_Ioctl_Block
  *
@@ -2462,7 +2468,7 @@
         break;
 
     case 0x0d: /* GENERIC BLOCK DEVICE REQUEST */
-        /* Get pointer to IOCTL parameter block. */
+        /* Get pointer to IOCTL parameter block */
         dataptr = CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
 
         switch (CX_reg(context))
@@ -2471,13 +2477,31 @@
             TRACE( "GENERIC IOCTL - Write logical device track - %c:\n",
                    'A' + drive);
             {
-                WORD head   = *(WORD *)dataptr+1;
-                WORD cyl    = *(WORD *)dataptr+3;
-                WORD sect   = *(WORD *)dataptr+5;
-                WORD nrsect = *(WORD *)dataptr+7;
-                BYTE *data  =  (BYTE *)dataptr+9; /* FIXME: is this correct? */
+                WORD cyl    = *(WORD *)(dataptr+3);
+                WORD head   = *(WORD *)(dataptr+1);
+                WORD sect   = *(WORD *)(dataptr+5);
+                WORD nrsect = *(WORD *)(dataptr+7);
+                BYTE *data  = CTX_SEG_OFF_TO_LIN(context, *(WORD *)(dataptr+11), *(WORD *)(dataptr+9));
+		WORD cyl_cnt, head_cnt, sec_cnt;
+
+            	/* FIXME: we're faking some values here */
+		if (drive > 1)
+		{
+                    /* cyl_cnt = 0x300;
+                    head_cnt = 16;
+                    sec_cnt = 255; */
+                    SET_AX( context, ERROR_WRITE_FAULT );
+                    SET_CFLAG(context);
+		    break;
+		}
+		else
+		{ /* floppy */
+			cyl_cnt = 80;
+			head_cnt = 2;
+			sec_cnt = 18;
+		}
 
-                if (!DOSVM_RawWrite(drive, head*cyl*sect, nrsect, data, FALSE))
+                if (!DOSVM_RawWrite(drive, INT21_Ioctl_CylHeadSect2Lin(cyl, head, sect, cyl_cnt, head_cnt, sec_cnt), nrsect, data, FALSE))
                 {
                     SET_AX( context, ERROR_WRITE_FAULT );
                     SET_CFLAG(context);
@@ -2516,13 +2540,28 @@
             TRACE( "GENERIC IOCTL - Read logical device track - %c:\n",
                    'A' + drive);
             {
-                WORD head   = *(WORD *)dataptr+1;
-                WORD cyl    = *(WORD *)dataptr+3;
-                WORD sect   = *(WORD *)dataptr+5;
-                WORD nrsect = *(WORD *)dataptr+7;
-                BYTE *data  =  (BYTE *)dataptr+9; /* FIXME: is this correct? */
+                WORD cyl    = *(WORD *)(dataptr+3);
+                WORD head   = *(WORD *)(dataptr+1);
+                WORD sect   = *(WORD *)(dataptr+5);
+                WORD nrsect = *(WORD *)(dataptr+7);
+                BYTE *data  = CTX_SEG_OFF_TO_LIN(context, *(WORD *)(dataptr+11), *(WORD *)(dataptr+9));
+		WORD cyl_cnt, head_cnt, sec_cnt;
+
+            	/* FIXME: we're faking some values here */
+		if (drive > 1)
+		{
+                    cyl_cnt = 0x300;
+                    head_cnt = 16;
+                    sec_cnt = 255;
+		}
+		else
+		{ /* floppy */
+			cyl_cnt = 80;
+			head_cnt = 2;
+			sec_cnt = 18;
+		}
 
-                if (!DOSVM_RawRead(drive, head*cyl*sect, nrsect, data, FALSE))
+                if (!DOSVM_RawRead(drive, INT21_Ioctl_CylHeadSect2Lin(cyl, head, sect, cyl_cnt, head_cnt, sec_cnt), nrsect, data, FALSE))
                 {
                     SET_AX( context, ERROR_READ_FAULT );
                     SET_CFLAG(context);
@@ -2557,7 +2596,7 @@
             break;
 
         case 0x0872:
-            /* Trail on error implementation */
+            /* Trial and error implementation */
             SET_AX( context, drivetype == DRIVE_UNKNOWN ? 0x0f : 0x01 );
             SET_CFLAG(context);	/* Seems to be set all the time */
             break;
Index: dlls/winedos/int25.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int25.c,v
retrieving revision 1.4
diff -u -r1.4 int25.c
--- dlls/winedos/int25.c	27 Nov 2003 00:59:36 -0000	1.4
+++ dlls/winedos/int25.c	5 Sep 2004 09:25:49 -0000
@@ -43,6 +43,10 @@
     WCHAR root[] = {'\\','\\','.','\\','A',':',0};
     HANDLE h;
 
+    TRACE( "abs diskread, drive %d, sector %ld, "
+           "count %ld, buffer %p\n",
+           drive, begin, nr_sect, dataptr );
+
     root[4] += drive;
     h = CreateFileW(root, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                     FILE_FLAG_BACKUP_SEMANTICS, NULL);
@@ -55,7 +59,6 @@
     }
     else
     {
-        if (h != INVALID_HANDLE_VALUE) CloseHandle(h);
         memset( dataptr, 0, nr_sect * 512 );
         if (fake_success)
         {
@@ -107,10 +110,6 @@
         length = CX_reg( context );
     }
 
-    TRACE( "abs diskread, drive %d, sector %ld, "
-           "count %ld, buffer %p\n",
-           AL_reg( context ), begin, length, dataptr );
-
     DOSVM_RawRead( AL_reg( context ), begin, length, dataptr, TRUE );
     RESET_CFLAG( context );
 }
Index: dlls/winedos/int26.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int26.c,v
retrieving revision 1.4
diff -u -r1.4 int26.c
--- dlls/winedos/int26.c	27 Nov 2003 00:59:36 -0000	1.4
+++ dlls/winedos/int26.c	5 Sep 2004 09:25:49 -0000
@@ -42,6 +42,10 @@
     WCHAR root[] = {'\\','\\','.','\\','A',':',0};
     HANDLE h;
 
+    TRACE( "abs diskwrite, drive %d, sector %ld, "
+           "count %ld, buffer %p\n",
+           drive, begin, nr_sect, dataptr );
+
     root[4] += drive;
     h = CreateFileW(root, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                     0, NULL);
@@ -62,7 +66,7 @@
 /**********************************************************************
  *	    DOSVM_Int26Handler (WINEDOS16.138)
  *
- * Handler for int 26h (absolute disk read).
+ * Handler for int 26h (absolute disk write).
  */
 void WINAPI DOSVM_Int26Handler( CONTEXT86 *context )
 {
@@ -95,10 +99,6 @@
         length = CX_reg( context );
     }
 
-    TRACE( "abs diskwrite, drive %d, sector %ld, "
-           "count %ld, buffer %p\n",
-           AL_reg( context ), begin, length, dataptr );
-
     DOSVM_RawWrite( AL_reg( context ), begin, length, dataptr, TRUE );
     RESET_CFLAG( context );
 }


More information about the wine-patches mailing list