[PATCH] Bug fixes to block drivers

Juan Perez-Sanchez <[email protected]>
Newsgroups org.kernel.vger.linux-8086
Message-ID <CAD6VGuYyvvZmmUGntjY5h-Lp1mct_UKA4ScHrvJTAdHvTSqX=w@mail.gmail.com>
Hi,

 Attached is the first of a set of 5 patches to fix some bugs and do
several improvements.

Greetings,

Juan

PREVIOUS OPERATION AND BUGS

1. Command "mkfs" did not work because of a bug in function "blk_rw()"
in file fs/block_dev.c. When calculating the block number from   the
file position (filp->f_pos), it casted the file position to 16 bits
before dividing by the block size, making unreachable data beyond 64
Kbytes.

2. In function "bioshd_open()", file arch/i86/drivers/block/doshd.c,
disk geometry is determined by attempting to seek certain tracks and
sectors. But the implementation fails to work correctly when there is
no disk.

3. In function "do_bioshd_request()", file
arch/i86/drivers/block/doshd.c, variable "tmp" is defined 16 bits but
might need 18 bits. Variable
   "this_pass" is defined 32 bits, but 16 bits suffices.

NEW OPERATION

1. In function "blk_rw()" the block number is casted to 16 bits after
the division by the block size. Command mkfs now works. Using a block
device this way might also be done by fsck, fdisk and mtools commands.

2. Fixed problem in function "bioshd_open()", reducing at the same
time the code size.

3. Redefined sizes of variables in function "do_bioshd_request()". Put
explicit casts in the conversion from block addressing to CHS
addressing. Simplified conversion code.


4. In file "arch/i86/drivers/block/doshd.c", function
"bioshd_gethdinfo()" was rewritten to make it faster and smaller.

OTHER CHANGES

   Code size reduced by 64 bytes.

 The Image builded without errors. The kernel was tested with QEMU and
dioscuri emulators. Also in a PPro pc booting from floppy.
elksO.patch (application/octet-stream, 3.3 KB)
diff -Nurb elks.orig/arch/i86/drivers/block/doshd.c elks/arch/i86/drivers/block/doshd.c
--- elks.orig/arch/i86/drivers/block/doshd.c	2012-08-18 13:28:59.000000000 -0500
+++ elks/arch/i86/drivers/block/doshd.c	2012-10-15 17:22:02.000000000 -0500
@@ -154,26 +154,24 @@
 
 #ifdef CONFIG_BLK_DEV_BHD
 
-unsigned short int bioshd_gethdinfo(void)
+static unsigned short int bioshd_gethdinfo(void)
 {
     unsigned short int drive, ndrives = 0;
+    register struct drive_infot *drivep = &drive_info[0];
 
     for (drive = 0; drive <= 1; drive++) {
-	register struct drive_infot *drivep = &drive_info[drive];
-	ndrives++;
 	BD_AX = BIOSHD_DRIVE_PARMS;
 	BD_DX = drive + 0x80;
 	BD_IRQ = BIOSHD_INT;
 	call_bios();
-	if ((BD_AX != 0x100) && (!CARRY_SET)) {
-	    drivep->cylinders = ((BD_CX >> 8) & 255);
-	    drivep->cylinders += (((BD_CX >> 6) & 3) * 256);
+	if (!CARRY_SET) {
+	    drivep->cylinders = ((BD_CX >> 8) | ((BD_CX & 0xC0) << 2)) + 1;
 	    drivep->heads = (BD_DX >> 8) + 1;
 	    drivep->sectors = (BD_CX & 63);
 	    drivep->fdtype = -1;
+	    ndrives++;
 	}
-	if ((BD_DX & 255) < 2)
-	    break;
+	drivep++;
     }
     return ndrives;
 }
@@ -429,9 +427,9 @@
 
 #ifndef CONFIG_HW_USE_INT13_FOR_DISKPARMS
 
+	drivep->cylinders = 0;
 	for (count = 0; count < 2; count++) {
 	    if (seek_sector(hd_drive_map[target], track_probe[count], 1)) {
-		drivep->cylinders = track_probe[count - 1];
 		break;
 	    }
 	    drivep->cylinders = track_probe[count];
@@ -443,9 +441,9 @@
  * format is the correct one.
  */
 
+	drivep->sectors = 0;
 	for (count = 0; count < 5; count++) {
 	    if (seek_sector(hd_drive_map[target], 40, sector_probe[count])) {
-		drivep->sectors = sector_probe[count - 1];
 		break;
 	    }
 	    drivep->sectors = sector_probe[count];
@@ -648,9 +646,9 @@
 {
     register struct request *req;
     char *buff;
-    sector_t count, start, this_pass;
-    int drive, errs, tmp;
-    short cylinder, head, sector;
+    sector_t start, count, tmp;
+    int drive, errs;
+    unsigned int cylinder, head, sector, this_pass;
     unsigned short int minor;
 
 #if 0
@@ -713,15 +711,13 @@
 
 	while (count > 0) {
 	    register struct drive_infot *drivep = &drive_info[drive];
-	    sector = (start % drivep->sectors) + 1;
-	    tmp = start / drivep->sectors;
-	    head = (short int) (tmp % drivep->heads);
-	    cylinder = (short int) (tmp / drivep->heads);
-	    this_pass = count;
-	    if (count <= (sector_t) (drivep->sectors - sector + 1))
-		this_pass = count;
-	    else
-		this_pass = (sector_t) (drivep->sectors - sector + 1);
+	    sector = (unsigned int) ((start % (sector_t)drivep->sectors) + 1);
+	    tmp = start / (sector_t)drivep->sectors;
+	    head = (unsigned int) (tmp % (sector_t)drivep->heads);
+	    cylinder = (unsigned int) (tmp / (sector_t)drivep->heads);
+	    this_pass = drivep->sectors - sector + 1;
+	    if ((sector_t)this_pass > count)
+		this_pass = (unsigned int) count;
 	    while (!dma_avail)
 		sleep_on(&dma_wait);
 	    dma_avail = 0;
diff -Nurb elks.orig/fs/block_dev.c elks/fs/block_dev.c
--- elks.orig/fs/block_dev.c	2012-08-18 13:28:59.000000000 -0500
+++ elks/fs/block_dev.c	2012-10-15 15:03:46.000000000 -0500
@@ -37,7 +37,7 @@
      *      Offset to block/offset
      */
 
-    block = ((block_t) filp->f_pos) >> 10;
+    block = (block_t) (filp->f_pos >> 10);
     offset = filp->f_pos & (BLOCK_SIZE - 1);
 
     while (count > 0) {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.