Skip to content

Commit 6b9e009

Browse files
mlelstvmlelstv
authored andcommitted
For SPC-3 devices try READ_CAPACITY_16 first and fall back to older
READ_CAPACITY_10. This fixes SCSI drivers like mpt(4) that announce SPC-3 conformity but don't support READ_CAPACITY_16 in all configurations.
1 parent 9a19c08 commit 6b9e009

1 file changed

Lines changed: 33 additions & 39 deletions

File tree

sys/dev/scsipi/sd.c

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $NetBSD: sd.c,v 1.345 2025/04/13 14:01:00 jakllsch Exp $ */
1+
/* $NetBSD: sd.c,v 1.346 2025/10/11 13:58:08 mlelstv Exp $ */
22

33
/*-
44
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@@ -48,7 +48,7 @@
4848
*/
4949

5050
#include <sys/cdefs.h>
51-
__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.345 2025/04/13 14:01:00 jakllsch Exp $");
51+
__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.346 2025/10/11 13:58:08 mlelstv Exp $");
5252

5353
#ifdef _KERNEL_OPT
5454
#include "opt_scsi.h"
@@ -1422,9 +1422,7 @@ sd_read_capacity(struct sd_softc *sd, int *blksize, int flags)
14221422

14231423
sd->params.lbppbe = 0;
14241424
sd->params.lalba = 0;
1425-
1426-
memset(&cmd, 0, sizeof(cmd));
1427-
cmd.cmd.opcode = READ_CAPACITY_10;
1425+
sd->flags &= ~SDF_LBPME;
14281426

14291427
/*
14301428
* Don't allocate data buffer on stack;
@@ -1436,54 +1434,50 @@ sd_read_capacity(struct sd_softc *sd, int *blksize, int flags)
14361434
if (datap == NULL)
14371435
return 0;
14381436

1439-
if (periph->periph_version >= 5) /* SPC-3 */
1440-
goto rc16;
1441-
1442-
/*
1443-
* If the command works, interpret the result as a 4 byte
1444-
* number of blocks
1445-
*/
14461437
rv = 0;
1447-
memset(datap, 0, sizeof(datap->data));
1448-
if (scsipi_command(periph, (void *)&cmd.cmd, sizeof(cmd.cmd),
1449-
(void *)datap, sizeof(datap->data), SCSIPIRETRIES, 20000, NULL,
1450-
flags | XS_CTL_DATA_IN | XS_CTL_SILENT) != 0)
1451-
goto out;
1452-
1453-
if (_4btol(datap->data.addr) != 0xffffffff) {
1454-
*blksize = _4btol(datap->data.length);
1455-
rv = _4btol(datap->data.addr) + 1;
1456-
goto out;
1457-
}
14581438

14591439
/*
1460-
* Device is larger than can be reflected by READ CAPACITY (10).
1461-
* Try READ CAPACITY (16).
1440+
* When device announces SPC-3 conformance,
1441+
* try READ CAPACITY (16) to collect information
1442+
* about physical blocks and management capabilities.
1443+
*
1444+
* Fall back to READ CAPACITY (10).
14621445
*/
14631446

1464-
rc16:
14651447
memset(&cmd, 0, sizeof(cmd));
14661448
cmd.cmd16.opcode = READ_CAPACITY_16;
14671449
cmd.cmd16.byte2 = SRC16_SERVICE_ACTION;
14681450
_lto4b(sizeof(datap->data16), cmd.cmd16.len);
14691451

14701452
memset(datap, 0, sizeof(datap->data16));
1471-
if (scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
1472-
(void *)datap, sizeof(datap->data16), SCSIPIRETRIES, 20000, NULL,
1473-
flags | XS_CTL_DATA_IN | XS_CTL_SILENT) != 0)
1474-
goto out;
1475-
1476-
*blksize = _4btol(datap->data16.length);
1477-
rv = _8btol(datap->data16.addr) + 1;
1478-
sd->params.lbppbe = datap->data16.byte14 & SRC16D_LBPPB_EXPONENT;
1479-
sd->params.lalba = _2btol(datap->data16.lowest_aligned) & SRC16D_LALBA;
1480-
if (_2btol(datap->data16.lowest_aligned) & SRC16D_LBPME) {
1481-
sd->flags |= SDF_LBPME;
1453+
if (periph->periph_version >= 5 &&
1454+
scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
1455+
(void *)datap, sizeof(datap->data16), SCSIPIRETRIES, 20000,
1456+
NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT) == 0) {
1457+
1458+
*blksize = _4btol(datap->data16.length);
1459+
rv = _8btol(datap->data16.addr) + 1;
1460+
1461+
sd->params.lbppbe = datap->data16.byte14
1462+
& SRC16D_LBPPB_EXPONENT;
1463+
sd->params.lalba = _2btol(datap->data16.lowest_aligned)
1464+
& SRC16D_LALBA;
1465+
if (_2btol(datap->data16.lowest_aligned) & SRC16D_LBPME)
1466+
sd->flags |= SDF_LBPME;
14821467
} else {
1483-
sd->flags &= ~SDF_LBPME;
1468+
memset(&cmd, 0, sizeof(cmd));
1469+
cmd.cmd.opcode = READ_CAPACITY_10;
1470+
1471+
memset(datap, 0, sizeof(datap->data));
1472+
if (scsipi_command(periph, (void *)&cmd.cmd, sizeof(cmd.cmd),
1473+
(void *)datap, sizeof(datap->data), SCSIPIRETRIES, 20000,
1474+
NULL, flags | XS_CTL_DATA_IN | XS_CTL_SILENT) == 0) {
1475+
1476+
*blksize = _4btol(datap->data.length);
1477+
rv = _4btol(datap->data.addr) + 1;
1478+
}
14841479
}
14851480

1486-
out:
14871481
free(datap, M_TEMP);
14881482
return rv;
14891483
}

0 commit comments

Comments
 (0)