Module Name: src Committed By: jakllsch Date: Thu Feb 27 17:03:46 UTC 2025
Modified Files: src/sys/dev/scsipi: sd.c sdvar.h Log Message: Implement DIOCGSECTORALIGN for sd(4). Use only READ CAPACITY 16 if peripheral claims conformance to SPC-3. To generate a diff of this commit: cvs rdiff -u -r1.339 -r1.340 src/sys/dev/scsipi/sd.c cvs rdiff -u -r1.40 -r1.41 src/sys/dev/scsipi/sdvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/scsipi/sd.c diff -u src/sys/dev/scsipi/sd.c:1.339 src/sys/dev/scsipi/sd.c:1.340 --- src/sys/dev/scsipi/sd.c:1.339 Thu Feb 27 15:23:44 2025 +++ src/sys/dev/scsipi/sd.c Thu Feb 27 17:03:46 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: sd.c,v 1.339 2025/02/27 15:23:44 jakllsch Exp $ */ +/* $NetBSD: sd.c,v 1.340 2025/02/27 17:03:46 jakllsch Exp $ */ /*- * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. @@ -47,7 +47,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.339 2025/02/27 15:23:44 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.340 2025/02/27 17:03:46 jakllsch Exp $"); #ifdef _KERNEL_OPT #include "opt_scsi.h" @@ -111,7 +111,7 @@ static int sd_mode_sense(struct sd_softc static int sd_mode_select(struct sd_softc *, u_int8_t, void *, size_t, int, int); static int sd_validate_blksize(struct scsipi_periph *, int); -static u_int64_t sd_read_capacity(struct scsipi_periph *, int *, int flags); +static u_int64_t sd_read_capacity(struct sd_softc *, int *, int flags); static int sd_get_simplifiedparms(struct sd_softc *, struct disk_parms *, int); static int sd_get_capacity(struct sd_softc *, struct disk_parms *, int); @@ -1002,6 +1002,28 @@ sdioctl(dev_t dev, u_long cmd, void *add } return (0); + case DIOCGSECTORALIGN: { + struct disk_sectoralign *dsa = addr; + + dsa->dsa_alignment = 1u << sd->params.lbppbe; + dsa->dsa_firstaligned = sd->params.lalba; + if (part != RAW_PART) { + struct disklabel *lp = dksc->sc_dkdev.dk_label; + daddr_t offset = lp->d_partitions[part].p_offset; + uint32_t r = offset % dsa->dsa_alignment; + + if (r < dsa->dsa_firstaligned) + dsa->dsa_firstaligned = dsa->dsa_firstaligned + - r; + else + dsa->dsa_firstaligned = (dsa->dsa_firstaligned + + dsa->dsa_alignment) - r; + } + dsa->dsa_firstaligned %= dsa->dsa_alignment; + + return 0; + } + default: error = dk_ioctl(dksc, dev, cmd, addr, flag, l); if (error == ENOTTY) @@ -1328,8 +1350,9 @@ sd_validate_blksize(struct scsipi_periph * Find out from the device what its capacity is. */ static u_int64_t -sd_read_capacity(struct scsipi_periph *periph, int *blksize, int flags) +sd_read_capacity(struct sd_softc *sd, int *blksize, int flags) { + struct scsipi_periph *periph = sd->sc_periph; union { struct scsipi_read_capacity_10 cmd; struct scsipi_read_capacity_16 cmd16; @@ -1340,6 +1363,9 @@ sd_read_capacity(struct scsipi_periph *p } *datap; uint64_t rv; + sd->params.lbppbe = 0; + sd->params.lalba = 0; + memset(&cmd, 0, sizeof(cmd)); cmd.cmd.opcode = READ_CAPACITY_10; @@ -1353,6 +1379,9 @@ sd_read_capacity(struct scsipi_periph *p if (datap == NULL) return 0; + if (periph->periph_version >= 5) /* SPC-3 */ + goto rc16; + /* * If the command works, interpret the result as a 4 byte * number of blocks @@ -1375,6 +1404,7 @@ sd_read_capacity(struct scsipi_periph *p * Try READ CAPACITY (16). */ + rc16: memset(&cmd, 0, sizeof(cmd)); cmd.cmd16.opcode = READ_CAPACITY_16; cmd.cmd16.byte2 = SRC16_SERVICE_ACTION; @@ -1388,6 +1418,8 @@ sd_read_capacity(struct scsipi_periph *p *blksize = _4btol(datap->data16.length); rv = _8btol(datap->data16.addr) + 1; + sd->params.lbppbe = datap->data16.byte14 & SRC16D_LBPPB_EXPONENT; + sd->params.lalba = _2btol(datap->data16.lowest_aligned) & SRC16D_LALBA; out: free(datap, M_TEMP); @@ -1419,7 +1451,7 @@ sd_get_simplifiedparms(struct sd_softc * * XXX probably differs for removable media */ dp->blksize = SD_DEFAULT_BLKSIZE; - if ((blocks = sd_read_capacity(sd->sc_periph, &blksize, flags)) == 0) + if ((blocks = sd_read_capacity(sd, &blksize, flags)) == 0) return (SDGP_RESULT_OFFLINE); /* XXX? */ error = scsipi_mode_sense(sd->sc_periph, SMS_DBD, 6, @@ -1467,8 +1499,7 @@ sd_get_capacity(struct sd_softc *sd, str u_int8_t *p; #endif - dp->disksize = blocks = sd_read_capacity(sd->sc_periph, &blksize, - flags); + dp->disksize = blocks = sd_read_capacity(sd, &blksize, flags); if (blocks == 0) { struct scsipi_read_format_capacities cmd; struct { Index: src/sys/dev/scsipi/sdvar.h diff -u src/sys/dev/scsipi/sdvar.h:1.40 src/sys/dev/scsipi/sdvar.h:1.41 --- src/sys/dev/scsipi/sdvar.h:1.40 Sun Aug 28 10:26:37 2022 +++ src/sys/dev/scsipi/sdvar.h Thu Feb 27 17:03:46 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: sdvar.h,v 1.40 2022/08/28 10:26:37 mlelstv Exp $ */ +/* $NetBSD: sdvar.h,v 1.41 2025/02/27 17:03:46 jakllsch Exp $ */ /*- * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. @@ -71,6 +71,8 @@ struct disk_parms { u_long rot_rate; /* rotational rate, in RPM */ u_int64_t disksize; /* total number sectors */ u_int64_t disksize512; /* total number sectors */ + uint8_t lbppbe; /* logical blocks per physical block exponent */ + uint16_t lalba; /* lowest aligned logical block address */ }; struct sd_softc {