summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-04-05 04:11:07 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-04-05 04:11:07 +0000
commitfbfa617257a7402d5273bd64a6ed24690d95b4d1 (patch)
tree3572f4933d339142f2e11da5baaf81c0bc5af191 /sys/dev
parent2c83979a55256852dc14382eb7dfd522012a50d5 (diff)
fill in the the lowest aligned logical block address field. it
indicates the LBA of the first logical block that is located at the beginning of a physical block implemented as best as i can by my understanding of the spec. not tested yet.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/atascsi.c22
-rw-r--r--sys/dev/ata/atascsi.h9
2 files changed, 28 insertions, 3 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c
index f10bd151361..05db19a77c0 100644
--- a/sys/dev/ata/atascsi.c
+++ b/sys/dev/ata/atascsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atascsi.c,v 1.78 2010/04/05 01:47:54 dlg Exp $ */
+/* $OpenBSD: atascsi.c,v 1.79 2010/04/05 04:11:06 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -99,6 +99,7 @@ int ata_polled(struct ata_xfer *);
u_int64_t ata_identify_blocks(struct ata_identify *);
u_int ata_identify_blocksize(struct ata_identify *);
u_int ata_identify_block_l2p_exp(struct ata_identify *);
+u_int ata_identify_block_logical_align(struct ata_identify *);
struct atascsi *
atascsi_attach(struct device *self, struct atascsi_attach_args *aaa)
@@ -821,6 +822,21 @@ ata_identify_block_l2p_exp(struct ata_identify *id)
return (exponent);
}
+u_int
+ata_identify_block_logical_align(struct ata_identify *id)
+{
+ u_int align = 0;
+ u_int16_t p2l_sect = letoh16(id->p2l_sect);
+ u_int16_t logical_align = letoh16(id->logical_align);
+
+ if ((p2l_sect & ATA_ID_P2L_SECT_MASK) == ATA_ID_P2L_SECT_VALID &&
+ ISSET(p2l_sect, ATA_ID_P2L_SECT_SET) &&
+ (logical_align & ATA_ID_LALIGN_MASK) == ATA_ID_LALIGN_VALID)
+ align = logical_align & ATA_ID_LALIGN;
+
+ return (align);
+}
+
void
atascsi_disk_capacity(struct scsi_xfer *xs)
{
@@ -850,12 +866,16 @@ atascsi_disk_capacity16(struct scsi_xfer *xs)
struct atascsi *as = link->adapter_softc;
struct ata_port *ap = as->as_ports[link->target];
struct scsi_read_cap_data_16 rcd;
+ u_int align;
bzero(&rcd, sizeof(rcd));
_lto4b(ata_identify_blocks(&ap->ap_identify), rcd.addr);
_lto4b(ata_identify_blocksize(&ap->ap_identify), rcd.length);
rcd.logical_per_phys = ata_identify_block_l2p_exp(&ap->ap_identify);
+ align = ata_identify_block_logical_align(&ap->ap_identify);
+ if (align > 0)
+ _lto2b((1 << rcd.logical_per_phys) - align, rcd.lowest_aligned);
bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));
diff --git a/sys/dev/ata/atascsi.h b/sys/dev/ata/atascsi.h
index df53e68d547..ac1e68854fd 100644
--- a/sys/dev/ata/atascsi.h
+++ b/sys/dev/ata/atascsi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: atascsi.h,v 1.37 2010/04/05 00:55:03 dlg Exp $ */
+/* $OpenBSD: atascsi.h,v 1.38 2010/04/05 04:11:06 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -137,7 +137,12 @@ struct ata_identify {
u_int16_t curmedser[30]; /* 176 */
u_int16_t sctsupport; /* 206 */
u_int16_t rpm; /* 207 */
- u_int16_t padding5[47]; /* 208 */
+ u_int16_t padding5[1]; /* 208 */
+ u_int16_t logical_align; /* 209 */
+#define ATA_ID_LALIGN_MASK 0xc000
+#define ATA_ID_LALIGN_VALID 0x4000
+#define ATA_ID_LALIGN 0x3fff
+ u_int16_t padding6[45]; /* 210 */
u_int16_t integrity; /* 255 */
} __packed;