
[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 stefan.althoefer@web.de ----
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; }