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 {