Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ata Add ATA8-ACS Long Logical Sector Feature Set sup...



details:   https://anonhg.NetBSD.org/src/rev/ba6ac1d27284
branches:  trunk
changeset: 346618:ba6ac1d27284
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Fri Jul 22 04:08:10 2016 +0000

description:
Add ATA8-ACS Long Logical Sector Feature Set support to wd(4).

diffstat:

 sys/dev/ata/wd.c    |  78 ++++++++++++++++++++++++++++++++++++++++------------
 sys/dev/ata/wdvar.h |   4 ++-
 2 files changed, 63 insertions(+), 19 deletions(-)

diffs (202 lines):

diff -r 1af3d99d0c9f -r ba6ac1d27284 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Thu Jul 21 19:49:58 2016 +0000
+++ b/sys/dev/ata/wd.c  Fri Jul 22 04:08:10 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.423 2016/07/21 19:05:03 jakllsch Exp $ */
+/*     $NetBSD: wd.c,v 1.424 2016/07/22 04:08:10 jakllsch 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.423 2016/07/21 19:05:03 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.424 2016/07/22 04:08:10 jakllsch Exp $");
 
 #include "opt_ata.h"
 
@@ -391,7 +391,16 @@
                    wd->sc_params.atap_heads *
                    wd->sc_params.atap_sectors;
        }
-       format_bytes(pbuf, sizeof(pbuf), wd->sc_capacity * DEV_BSIZE);
+       if ((wd->sc_params.atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID
+           && ((wd->sc_params.atap_secsz & ATA_SECSZ_LLS) != 0)) {
+               wd->sc_blksize = 2ULL *
+                   (wd->sc_params.atap_lls_secsz[1] << 16 |
+                    wd->sc_params.atap_lls_secsz[0] <<  0);
+       } else {
+               wd->sc_blksize = 512;
+       }
+       wd->sc_capacity512 = (wd->sc_capacity * wd->sc_blksize) / DEV_BSIZE;
+       format_bytes(pbuf, sizeof(pbuf), wd->sc_capacity * wd->sc_blksize);
        aprint_normal_dev(self, "%s, %d cyl, %d head, %d sec, "
            "%d bytes/sect x %llu sectors\n",
            pbuf,
@@ -399,11 +408,17 @@
                (wd->sc_params.atap_heads * wd->sc_params.atap_sectors)) :
                wd->sc_params.atap_cylinders,
            wd->sc_params.atap_heads, wd->sc_params.atap_sectors,
-           DEV_BSIZE, (unsigned long long)wd->sc_capacity);
+           wd->sc_blksize, (unsigned long long)wd->sc_capacity);
 
        ATADEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
            device_xname(self), wd->sc_params.atap_dmatiming_mimi,
            wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
+
+       if (wd->sc_blksize <= 0 || !powerof2(wd->sc_blksize) ||
+           wd->sc_blksize < DEV_BSIZE || wd->sc_blksize > MAXPHYS) {
+               aprint_normal_dev(self, "WARNING: block size %u "
+                   "might not actually work\n", wd->sc_blksize);
+       }
 out:
        /*
         * Initialize and attach the disk structure.
@@ -544,7 +559,7 @@
         */
        if (WDPART(bp->b_dev) == RAW_PART) {
                if (bounds_check_with_mediasize(bp, DEV_BSIZE,
-                   wd->sc_capacity) <= 0)
+                   wd->sc_capacity512) <= 0)
                        goto done;
        } else {
                if (bounds_check_with_label(&wd->sc_dk, bp,
@@ -577,7 +592,7 @@
         */
        if (__predict_false(!SLIST_EMPTY(&wd->sc_bslist))) {
                struct disk_badsectors *dbs;
-               daddr_t maxblk = blkno + (bp->b_bcount >> DEV_BSHIFT) - 1;
+               daddr_t maxblk = blkno + (bp->b_bcount / wd->sc_blksize) - 1;
 
                SLIST_FOREACH(dbs, &wd->sc_bslist, dbs_next)
                        if ((dbs->dbs_min <= blkno && blkno <= dbs->dbs_max) ||
@@ -664,8 +679,8 @@
        bp->b_oflags = obp->b_oflags;
        bp->b_cflags = obp->b_cflags;
        bp->b_data = (char *)bp->b_data + bp->b_bcount;
-       bp->b_blkno += (bp->b_bcount / 512);
-       bp->b_rawblkno += (bp->b_bcount / 512);
+       bp->b_blkno += (bp->b_bcount / DEV_BSIZE);
+       bp->b_rawblkno += (bp->b_bcount / sc->sc_blksize);
        s = splbio();
        wdstart1(sc, bp);
        splx(s);
@@ -837,7 +852,8 @@
 
                        dbs = malloc(sizeof *dbs, M_TEMP, M_WAITOK);
                        dbs->dbs_min = bp->b_rawblkno;
-                       dbs->dbs_max = dbs->dbs_min + (bp->b_bcount >> DEV_BSHIFT) - 1;
+                       dbs->dbs_max = dbs->dbs_min +
+                           (bp->b_bcount /wd->sc_blksize) - 1;
                        microtime(&dbs->dbs_failedat);
                        SLIST_INSERT_HEAD(&wd->sc_bslist, dbs, dbs_next);
                        wd->sc_bscount++;
@@ -894,9 +910,11 @@
 static void
 wdminphys(struct buf *bp)
 {
+       const struct wd_softc * const wd =
+           device_lookup_private(&wd_cd, WDUNIT(bp->b_dev));
 
-       if (bp->b_bcount > (512 * 128)) {
-               bp->b_bcount = (512 * 128);
+       if (bp->b_bcount > (wd->sc_blksize * 128)) {
+               bp->b_bcount = (wd->sc_blksize * 128);
        }
        minphys(bp);
 }
@@ -1065,7 +1083,7 @@
        ATADEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS);
        memset(lp, 0, sizeof(struct disklabel));
 
-       lp->d_secsize = DEV_BSIZE;
+       lp->d_secsize = wd->sc_blksize;
        lp->d_ntracks = wd->sc_params.atap_heads;
        lp->d_nsectors = wd->sc_params.atap_sectors;
        lp->d_ncylinders = (wd->sc_flags & WDF_LBA) ? wd->sc_capacity /
@@ -1537,8 +1555,8 @@
                return EIO;
 
        /* round the start up and the end down */
-       bno = (pos + DEV_BSIZE - 1) >> DEV_BSHIFT;
-       size = ((pos + len) >> DEV_BSHIFT) - bno;
+       bno = (pos + wd->sc_blksize - 1) / wd->sc_blksize;
+       size = ((pos + len) / wd->sc_blksize) - bno;
 
        done = 0;
        while (done < size) {
@@ -1737,7 +1755,7 @@
        memset(dg, 0, sizeof(*dg));
 
        dg->dg_secperunit = wd->sc_capacity;
-       dg->dg_secsize = DEV_BSIZE /* XXX 512? */;
+       dg->dg_secsize = wd->sc_blksize;
        dg->dg_nsectors = wd->sc_params.atap_sectors;
        dg->dg_ntracks = wd->sc_params.atap_heads;
        if ((wd->sc_flags & WDF_LBA) == 0)
@@ -2036,6 +2054,30 @@
        return (wi);
 }
 
+static uint
+wi_sector_size(const struct wd_ioctl * const wi)
+{
+       switch (wi->wi_atareq.command) {
+       case WDCC_READ:
+       case WDCC_WRITE:
+       case WDCC_READMULTI:
+       case WDCC_WRITEMULTI:
+       case WDCC_READDMA:
+       case WDCC_WRITEDMA:
+       case WDCC_READ_EXT:
+       case WDCC_WRITE_EXT:
+       case WDCC_READMULTI_EXT:
+       case WDCC_WRITEMULTI_EXT:
+       case WDCC_READDMA_EXT:
+       case WDCC_WRITEDMA_EXT:
+       case WDCC_READ_FPDMA_QUEUED:
+       case WDCC_WRITE_FPDMA_QUEUED:
+               return wi->wi_softc->sc_blksize;
+       default:
+               return 512;
+       }
+}
+
 /*
  * Ioctl pseudo strategy routine
  *
@@ -2087,11 +2129,11 @@
 
        /*
         * Abort if we didn't get a buffer size that was a multiple of
-        * our sector size (or was larger than NBBY)
+        * our sector size (or overflows CHS/LBA28 sector count)
         */
 
-       if ((bp->b_bcount % wi->wi_softc->sc_dk.dk_label->d_secsize) != 0 ||
-           (bp->b_bcount / wi->wi_softc->sc_dk.dk_label->d_secsize) >=
+       if ((bp->b_bcount % wi_sector_size(wi)) != 0 ||
+           (bp->b_bcount / wi_sector_size(wi)) >=
             (1 << NBBY)) {
                error = EINVAL;
                goto bad;
diff -r 1af3d99d0c9f -r ba6ac1d27284 sys/dev/ata/wdvar.h
--- a/sys/dev/ata/wdvar.h       Thu Jul 21 19:49:58 2016 +0000
+++ b/sys/dev/ata/wdvar.h       Fri Jul 22 04:08:10 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wdvar.h,v 1.42 2015/04/13 16:33:24 riastradh Exp $     */
+/*     $NetBSD: wdvar.h,v 1.43 2016/07/22 04:08:10 jakllsch Exp $      */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -60,7 +60,9 @@
 #define WDF_KLABEL     0x080 /* retain label after 'full' close */
 #define WDF_LBA48      0x100 /* using 48-bit LBA mode */
        uint64_t sc_capacity; /* full capacity of the device */
+       uint64_t sc_capacity512; /* ... in DEV_BSIZE blocks */
        uint32_t sc_capacity28; /* capacity accessible with LBA28 commands */
+       uint32_t sc_blksize; /* logical block size, in bytes */
 
        int retries; /* number of xfer retry */
 



Home | Main Index | Thread Index | Old Index