From fbfa617257a7402d5273bd64a6ed24690d95b4d1 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 5 Apr 2010 04:11:07 +0000 Subject: 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. --- sys/dev/ata/atascsi.c | 22 +++++++++++++++++++++- sys/dev/ata/atascsi.h | 9 +++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'sys/dev') 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 @@ -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 @@ -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; -- cgit v1.2.3