Subject: kern/32169: PIO modes 1 and 2 not used
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Matthew Orgass <darkstar@city-net.com>
List: netbsd-bugs
Date: 11/26/2005 22:41:00
>Number: 32169
>Category: kern
>Synopsis: PIO modes 1 and 2 not used
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Nov 26 22:41:00 +0000 2005
>Originator: darkstar@city-net.com
>Release: NetBSD 2.1.0_STABLE
>Organization:
>Description:
wdc_probe_caps does not detect PIO mode 1 or 2 in the oldpiotiming field,
leading to lower performance on some flash drives.
>How-To-Repeat:
This should primarily affect some flash controllers (both CF and larger IDE
flash drives). The affected card I have has a Hitachi XXM2.3.0 Rev 3.00
controller.
>Fix:
Inspired by changes in OpenBSD. This patch will also do PIO 1/2 detection
and use flags when bous values are returned in the extended PIO modes. At
least the flags should be checked in that case, I think, and the mode 1/2
field may be more reliable than the extended fields. The CF card I have does
not have this problem, so that part of the patch could be modified or removed.
I can't test if this patch would fully fix the performance problems with
this card since viaide apparently does not support faster speeds in PIO
modes 1 or 2. The manufacturer claims the card supports PIO mode 4 (and a
few hundered megabytes of testing showed no corruption), however I suspect
"supports" means "will automatically slow down with IORDY". The card
reports PIO mode 1 capability and does not support SET FEATURES/SET MODE
at all (meaning that forcing any mode currently does not work due to
piomode error). This patch would allow forcing PIO mode 2 for this card,
but not 3 or 4. Since the maximum transfer speed I get at PIO 3 on viaide
is 3.2MB/s (raw read), PIO 1 or 2 seem likely to get full speed and it
isn't worth another flag to work around combinations of broken hardware.
Index: ata/ata_wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/ata_wdc.c,v
retrieving revision 1.53.2.3.2.4
diff -u -p -r1.53.2.3.2.4 ata_wdc.c
--- ata/ata_wdc.c 18 Jul 2005 03:57:36 -0000 1.53.2.3.2.4
+++ ata/ata_wdc.c 26 Nov 2005 21:44:26 -0000
@@ -258,8 +258,15 @@ wdc_ata_bio_start(struct wdc_channel *ch
errstring = "piomode";
if (wdcwait(chp, WDCS_DRDY, WDCS_DRDY, ATA_DELAY, wait_flags))
goto ctrltimeout;
+ /* Ignore an ABRT error for PIO <= 2 since SET_FEATURES
+ * SET_MODE 0x08 is for flow control transfer (IORDY), which
+ * may not be used for PIO <= 2. */
+ if (drvp->PIO_mode <= 2 && ((chp->ch_status & (WDCS_ERR |
+ WDCS_DWF)) == WDCS_ERR) && chp->ch_error == WDCE_ABRT)
+ goto dma;
if (chp->ch_status & (WDCS_ERR | WDCS_DWF))
goto ctrlerror;
+dma:
if (drvp->drive_flags & DRIVE_UDMA) {
wdccommand(chp, drvp->drive, SET_FEATURES, 0, 0, 0,
0x40 | drvp->UDMA_mode, WDSF_SET_MODE);
Index: ic/wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.172.2.7.2.10
diff -u -p -r1.172.2.7.2.10 wdc.c
--- ic/wdc.c 23 Aug 2005 13:35:55 -0000 1.172.2.7.2.10
+++ ic/wdc.c 26 Nov 2005 21:44:30 -0000
@@ -1419,13 +1419,13 @@ wdc_probe_caps(struct ata_drive_datas *d
if (drvp->drive_flags & DRIVE_ATAPI)
drvp->PIO_mode = 3;
+ printed = 0;
/*
* It's not in the specs, but it seems that some drive
* returns 0xffff in atap_extensions when this field is invalid
*/
if (params.atap_extensions != 0xffff &&
(params.atap_extensions & WDC_EXT_MODES)) {
- printed = 0;
/*
* XXX some drives report something wrong here (they claim to
* support PIO mode 8 !). As mode is coded on 3 bits in
@@ -1436,7 +1436,7 @@ wdc_probe_caps(struct ata_drive_datas *d
if ((params.atap_piomode_supp & (1 << i)) == 0)
continue;
if (i > 4)
- return;
+ goto flags;
/*
* See if mode is accepted.
* If the controller can't set its PIO mode,
@@ -1473,7 +1473,7 @@ wdc_probe_caps(struct ata_drive_datas *d
* We didn't find a valid PIO mode.
* Assume the values returned for DMA are buggy too
*/
- return;
+ goto flags;
}
drvp->drive_flags |= DRIVE_MODE;
printed = 0;
@@ -1539,6 +1539,15 @@ wdc_probe_caps(struct ata_drive_datas *d
aprint_normal("\n");
}
+flags:
+ if (!printed && params.atap_oldpiotiming && params.atap_oldpiotiming
+ <= 2) {
+ drvp->PIO_cap = drvp->PIO_mode = params.atap_oldpiotiming;
+ drvp->drive_flags |= DRIVE_MODE;
+ aprint_normal("%s: drive supports PIO mode %d\n",
+ drv_dev->dv_xname, drvp->PIO_mode);
+ }
+
/* Try to guess ATA version here, if it didn't get reported */
if (drvp->ata_vers == 0) {
if (drvp->drive_flags & DRIVE_UDMA)