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