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 {

Reply via email to