[PATCH] IDE: Improving speed on reading data

This patch improves the speed when reading blocks from
IDE devices by reading more than one block at a time. Up to
128 blocks are requested in one read command.

On my testplatform (Janz emPC-A400 with CompactFLASH card)
this nearly doubled speed.

Also the ide_wait() code was rewritten to have lower latency
by polling more frequently for status.


The patch is against "latest" u-boot git-repository

Please (still) be patient if style of submission or patches are
offending.

Signed-off-by: Stefan Althoefer <[EMAIL PROTECTED]>
----

diff -uprN u-boot-orig//common/cmd_ide.c u-boot/common/cmd_ide.c
--- u-boot-orig//common/cmd_ide.c       2008-12-02 17:25:31.000000000 +0100
+++ u-boot/common/cmd_ide.c     2008-12-03 09:22:29.000000000 +0100
@@ -1302,6 +1361,7 @@ ulong ide_read (int device, lbaint_t blk
        ulong n = 0;
        unsigned char c;
        unsigned char pwrsave=0; /* power save */
+       ulong scnt;
 #ifdef CONFIG_LBA48
        unsigned char lba48 = 0;
 
@@ -1346,7 +1406,7 @@ ulong ide_read (int device, lbaint_t blk
        }
 
 
-       while (blkcnt-- > 0) {
+       while (blkcnt > 0) {
 
                c = ide_wait (device, IDE_TIME_OUT);
 
@@ -1368,7 +1428,8 @@ ulong ide_read (int device, lbaint_t blk
 #endif
                }
 #endif
-               ide_outb (device, ATA_SECT_CNT, 1);
+               scnt = (blkcnt > 128) ? 128 : blkcnt;
+               ide_outb (device, ATA_SECT_CNT, scnt);
                ide_outb (device, ATA_LBA_LOW,  (blknr >>  0) & 0xFF);
                ide_outb (device, ATA_LBA_MID,  (blknr >>  8) & 0xFF);
                ide_outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
@@ -1387,32 +1448,36 @@ ulong ide_read (int device, lbaint_t blk
                        ide_outb (device, ATA_COMMAND,  ATA_CMD_READ);
                }
 
-               udelay (50);
+               while (scnt > 0) {
+                       udelay (50);
 
-               if(pwrsave) {
-                       c = ide_wait (device, IDE_SPIN_UP_TIME_OUT);    /* may 
take up to 4 sec */
-                       pwrsave=0;
-               } else {
-                       c = ide_wait (device, IDE_TIME_OUT);    /* can't take 
over 500 ms */
-               }
+                       if(pwrsave) {
+                               c = ide_wait (device, IDE_SPIN_UP_TIME_OUT);    
/* may take up to 4 sec */
+                               pwrsave=0;
+                       } else {
+                               c = ide_wait (device, IDE_TIME_OUT);    /* 
can't take over 500 ms */
+                       }
 
-               if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != 
ATA_STAT_DRQ) {
+                       if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != 
ATA_STAT_DRQ) {
 #if defined(CONFIG_SYS_64BIT_LBA) && defined(CONFIG_SYS_64BIT_VSPRINTF)
-                       printf ("Error (no IRQ) dev %d blk %qd: status 
0x%02x\n",
-                               device, blknr, c);
+                               printf ("Error (no IRQ) dev %d blk %qd: status 
0x%02x\n",
+                                       device, blknr, c);
 #else
-                       printf ("Error (no IRQ) dev %d blk %ld: status 
0x%02x\n",
-                               device, (ulong)blknr, c);
+                               printf ("Error (no IRQ) dev %d blk %ld: status 
0x%02x\n",
+                                       device, (ulong)blknr, c);
 #endif
-                       break;
-               }
+                               break;
+                       }
 
-               input_data (device, buffer, ATA_SECTORWORDS);
-               (void) ide_inb (device, ATA_STATUS);    /* clear IRQ */
-
-               ++n;
-               ++blknr;
-               buffer += ATA_BLOCKSIZE;
+                       input_data (device, buffer, ATA_SECTORWORDS);
+                       (void) ide_inb (device, ATA_STATUS);    /* clear IRQ */
+
+                       ++n;
+                       ++blknr;
+                       --blkcnt;
+                       --scnt;
+                       buffer += ATA_BLOCKSIZE;
+               }
        }
 IDE_READ_E:
        ide_led (DEVICE_LED(device), 0);        /* LED off      */
@@ -1548,11 +1613,11 @@ OUT:
  */
 static uchar ide_wait (int dev, ulong t)
 {
-       ulong delay = 10 * t;           /* poll every 100 us */
+       ulong delay = (1000/5) * t;             /* poll every 5 us */
        uchar c;
 
        while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) {
-               udelay (100);
+               udelay (5);
                if (delay-- == 0) {
                        break;
                }
_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to