Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ata ATA sepcs changed the LBA48 boundary from 0xffff...



details:   https://anonhg.NetBSD.org/src/rev/c94f3239497c
branches:  trunk
changeset: 750124:c94f3239497c
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Thu Dec 17 21:03:10 2009 +0000

description:
ATA sepcs changed the LBA48 boundary from 0xfffffff to 0xffffffe between
ATA6r1 and ATA6r3, which caused drives conform to ATA6r3 or later to
reject LBA28 commands at sector 0xfffffff.
Get the right idea from the LBA48 boundary from IDENTIFY words 60-61.
Remove the WD_QUIRK_FORCE_LBA48 quirk, associated tables entries and
autodetect code, it's not needed any more.
Based on patch sent to teck-kern by Christoph Badura, use of words 60-61
instead of a constant for the LBA48 boundary by me.

diffstat:

 sys/dev/ata/wd.c    |  73 ++++++++++------------------------------------------
 sys/dev/ata/wdvar.h |   5 ++-
 2 files changed, 17 insertions(+), 61 deletions(-)

diffs (179 lines):

diff -r 536f8a8535c4 -r c94f3239497c sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Thu Dec 17 20:07:19 2009 +0000
+++ b/sys/dev/ata/wd.c  Thu Dec 17 21:03:10 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.379 2009/10/19 18:41:12 bouyer Exp $ */
+/*     $NetBSD: wd.c,v 1.380 2009/12/17 21:03:10 bouyer Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.379 2009/10/19 18:41:12 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.380 2009/12/17 21:03:10 bouyer Exp $");
 
 #include "opt_ata.h"
 
@@ -94,8 +94,6 @@
 
 #include <prop/proplib.h>
 
-#define        LBA48_THRESHOLD         (0xfffffff)     /* 128GB / DEV_BSIZE */
-
 #define        WDIORETRIES_SINGLE 4    /* number of retries before single-sector */
 #define        WDIORETRIES     5       /* number of retries before giving up */
 #define        RECOVERYTIME hz/2       /* time to wait before retrying a cmd */
@@ -194,7 +192,6 @@
 #endif
 
 #define        WD_QUIRK_SPLIT_MOD15_WRITE      0x0001  /* must split certain writes */
-#define        WD_QUIRK_FORCE_LBA48            0x0002  /* must use LBA48 commands */
 
 #define        WD_QUIRK_FMT "\20\1SPLIT_MOD15_WRITE\2FORCE_LBA48"
 
@@ -222,31 +219,6 @@
          WD_QUIRK_SPLIT_MOD15_WRITE },
        { "ST380023AS",
          WD_QUIRK_SPLIT_MOD15_WRITE },
-
-       /*
-        * These seagate drives seems to have issue addressing sector 0xfffffff
-        * (aka LBA48_THRESHOLD) in LBA mode. The workaround is to force
-        * LBA48
-        * Note that we can't just change the code to always use LBA48 for
-        * sector 0xfffffff, because this would break valid and working
-        * setups using LBA48 drives on non-LBA48-capable controllers
-        * (and it's hard to get a list of such controllers)
-        */
-       { "ST3160021A*",
-         WD_QUIRK_FORCE_LBA48 },
-       { "ST3160811A*",
-         WD_QUIRK_FORCE_LBA48 },
-       { "ST3160812A*",
-         WD_QUIRK_FORCE_LBA48 },
-       { "ST3160023A*",
-         WD_QUIRK_FORCE_LBA48 },
-       { "ST3160827A*",
-         WD_QUIRK_FORCE_LBA48 },
-       /* Attempt to catch all seagate drives larger than 200GB */
-       { "ST3[2-9][0-9][0-9][0-9][0-9][0-9][A-Z]*",
-         WD_QUIRK_FORCE_LBA48 },
-       { "ST3[1-9][0-9][0-9][0-9][0-9][0-9][0-9][A-Z]*",
-         WD_QUIRK_FORCE_LBA48 },
        { NULL,
          0 }
 };
@@ -374,14 +346,17 @@
                    ((u_int64_t) wd->sc_params.atap_max_lba[2] << 32) |
                    ((u_int64_t) wd->sc_params.atap_max_lba[1] << 16) |
                    ((u_int64_t) wd->sc_params.atap_max_lba[0] <<  0);
+               wd->sc_capacity28 =
+                   (wd->sc_params.atap_capacity[1] << 16) |
+                   wd->sc_params.atap_capacity[0];
        } else if ((wd->sc_flags & WDF_LBA) != 0) {
                aprint_verbose(" LBA addressing\n");
-               wd->sc_capacity =
-                   ((u_int64_t)wd->sc_params.atap_capacity[1] << 16) |
+               wd->sc_capacity28 = wd->sc_capacity =
+                   (wd->sc_params.atap_capacity[1] << 16) |
                    wd->sc_params.atap_capacity[0];
        } else {
                aprint_verbose(" chs addressing\n");
-               wd->sc_capacity =
+               wd->sc_capacity28 = wd->sc_capacity =
                    wd->sc_params.atap_cylinders *
                    wd->sc_params.atap_heads *
                    wd->sc_params.atap_sectors;
@@ -714,6 +689,8 @@
        }
 
        wd->sc_wdc_bio.blkno = bp->b_rawblkno;
+       wd->sc_wdc_bio.bcount = bp->b_bcount;
+       wd->sc_wdc_bio.databuf = bp->b_data;
        wd->sc_wdc_bio.blkdone =0;
        wd->sc_bp = bp;
        /*
@@ -726,15 +703,14 @@
        else
                wd->sc_wdc_bio.flags = 0;
        if (wd->sc_flags & WDF_LBA48 &&
-           (wd->sc_wdc_bio.blkno > LBA48_THRESHOLD ||
-           (wd->sc_quirks & WD_QUIRK_FORCE_LBA48) != 0))
+           (wd->sc_wdc_bio.blkno +
+            wd->sc_wdc_bio.bcount / wd->sc_dk.dk_label->d_secsize) >
+           wd->sc_capacity28)
                wd->sc_wdc_bio.flags |= ATA_LBA48;
        if (wd->sc_flags & WDF_LBA)
                wd->sc_wdc_bio.flags |= ATA_LBA;
        if (bp->b_flags & B_READ)
                wd->sc_wdc_bio.flags |= ATA_READ;
-       wd->sc_wdc_bio.bcount = bp->b_bcount;
-       wd->sc_wdc_bio.databuf = bp->b_data;
        /* Instrumentation. */
        disk_busy(&wd->sc_dk);
        switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
@@ -756,7 +732,6 @@
        struct buf *bp = wd->sc_bp;
        const char *errmsg;
        int do_perror = 0;
-       int nblks;
 
        ATADEBUG_PRINT(("wddone %s\n", device_xname(wd->sc_dev)),
            DEBUG_XFERS);
@@ -783,25 +758,6 @@
                        goto noerror;
                errmsg = "error";
                do_perror = 1;
-               if ((wd->sc_wdc_bio.r_error & (WDCE_IDNF | WDCE_ABRT)) &&
-                   (wd->sc_quirks & WD_QUIRK_FORCE_LBA48) == 0) {
-                       nblks = wd->sc_wdc_bio.bcount /
-                           wd->sc_dk.dk_label->d_secsize;
-                       /*
-                        * If we get a "id not found" when crossing the
-                        * LBA48_THRESHOLD, and the drive is larger than
-                        * 128GB, then we can assume the drive has the
-                        * LBA48 bug and we switch to LBA48.
-                        */
-                       if (wd->sc_wdc_bio.blkno <= LBA48_THRESHOLD &&
-                           wd->sc_wdc_bio.blkno + nblks > LBA48_THRESHOLD &&
-                           wd->sc_capacity > LBA48_THRESHOLD + 1) {
-                               errmsg = "LBA48 bug";
-                               wd->sc_quirks |= WD_QUIRK_FORCE_LBA48;
-                               do_perror = 0;
-                               goto retry2;
-                       }
-               }
 retry:         /* Just reset and retry. Can we do more ? */
                (*wd->atabus->ata_reset_drive)(wd->drvp, AT_RST_NOCMD);
 retry2:
@@ -1628,8 +1584,7 @@
        wd->sc_wdc_bio.blkno = blkno;
        wd->sc_wdc_bio.flags = ATA_POLL;
        if (wd->sc_flags & WDF_LBA48 &&
-           (blkno > LBA48_THRESHOLD ||
-           (wd->sc_quirks & WD_QUIRK_FORCE_LBA48) != 0))
+           (wd->sc_wdc_bio.blkno + nblks) > wd->sc_capacity28)
                wd->sc_wdc_bio.flags |= ATA_LBA48;
        if (wd->sc_flags & WDF_LBA)
                wd->sc_wdc_bio.flags |= ATA_LBA;
diff -r 536f8a8535c4 -r c94f3239497c sys/dev/ata/wdvar.h
--- a/sys/dev/ata/wdvar.h       Thu Dec 17 20:07:19 2009 +0000
+++ b/sys/dev/ata/wdvar.h       Thu Dec 17 21:03:10 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdvar.h,v 1.37 2009/10/19 18:41:12 bouyer Exp $        */
+/*     $NetBSD: wdvar.h,v 1.38 2009/12/17 21:03:10 bouyer Exp $        */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -57,7 +57,8 @@
 #define WDF_LBA                0x040 /* using LBA mode */
 #define WDF_KLABEL     0x080 /* retain label after 'full' close */
 #define WDF_LBA48      0x100 /* using 48-bit LBA mode */
-       u_int64_t sc_capacity;
+       u_int64_t sc_capacity; /* full capacity of the device */
+       u_int32_t sc_capacity28; /* capacity accessible with LBA28 commands */
 
        int retries; /* number of xfer retry */
 



Home | Main Index | Thread Index | Old Index