Some removable umass(4) devices don't respond to mode sense page 6, or

simply return zero for logical block size. In either case, use the sector
length reported by READ_CAPACITY instead of defaulting to 512 bytes.

This partially addresses the problems reported in PR port-i386/34707 and
PR kern/34737. Namely the incorrectly reported drive geometry and the
'hanging' issue.

However, since the device in question reports 2048-byte physical sectors
it will remain unusable until DEV_BSIZE is banished.
This commit is contained in:
scw 2006-10-09 21:29:14 +00:00
parent d6e105789d
commit 056c6fdd05
3 changed files with 20 additions and 15 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsipi_base.c,v 1.137 2006/09/11 19:43:55 reinoud Exp $ */
/* $NetBSD: scsipi_base.c,v 1.138 2006/10/09 21:29:14 scw Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.137 2006/09/11 19:43:55 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.138 2006/10/09 21:29:14 scw Exp $");
#include "opt_scsi.h"
@ -1025,7 +1025,7 @@ scsipi_interpret_sense(struct scsipi_xfer *xs)
* Find out from the device what its capacity is.
*/
u_int64_t
scsipi_size(struct scsipi_periph *periph, int flags)
scsipi_size(struct scsipi_periph *periph, int *secsize, int flags)
{
union {
struct scsipi_read_capacity_10 cmd;
@ -1048,8 +1048,11 @@ scsipi_size(struct scsipi_periph *periph, int flags)
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
return (0);
if (_4btol(data.data.addr) != 0xffffffff)
if (_4btol(data.data.addr) != 0xffffffff) {
if (secsize)
*secsize = _4btol(data.data.length);
return (_4btol(data.data.addr) + 1);
}
/*
* Device is larger than can be reflected by READ CAPACITY (10).
@ -1067,6 +1070,8 @@ scsipi_size(struct scsipi_periph *periph, int flags)
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
return (0);
if (secsize)
*secsize = _4btol(data.data16.length);
return (_8btol(data.data16.addr) + 1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsipiconf.h,v 1.103 2006/02/16 20:17:19 perry Exp $ */
/* $NetBSD: scsipiconf.h,v 1.104 2006/10/09 21:29:14 scw Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2004 The NetBSD Foundation, Inc.
@ -638,7 +638,7 @@ const void *scsipi_inqmatch(struct scsipi_inquiry_pattern *, const void *,
const char *scsipi_dtype(int);
void scsipi_strvis(u_char *, int, const u_char *, int);
int scsipi_execute_xs(struct scsipi_xfer *);
u_int64_t scsipi_size(struct scsipi_periph *, int);
u_int64_t scsipi_size(struct scsipi_periph *, int *, int);
int scsipi_test_unit_ready(struct scsipi_periph *, int);
int scsipi_prevent(struct scsipi_periph *, int, int);
int scsipi_inquire(struct scsipi_periph *,

View File

@ -1,4 +1,4 @@
/* $NetBSD: sd.c,v 1.250 2006/09/14 17:54:34 reinoud Exp $ */
/* $NetBSD: sd.c,v 1.251 2006/10/09 21:29:14 scw Exp $ */
/*-
* Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc.
@ -54,7 +54,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.250 2006/09/14 17:54:34 reinoud Exp $");
__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.251 2006/10/09 21:29:14 scw Exp $");
#include "opt_scsi.h"
#include "rnd.h"
@ -1651,7 +1651,7 @@ sd_get_simplifiedparms(struct sd_softc *sd, struct disk_parms *dp, int flags)
u_int8_t resvd;
} scsipi_sense;
u_int64_t sectors;
int error;
int error, blksize;
/*
* scsipi_size (ie "read capacity") and mode sense page 6
@ -1660,7 +1660,7 @@ sd_get_simplifiedparms(struct sd_softc *sd, struct disk_parms *dp, int flags)
* XXX probably differs for removable media
*/
dp->blksize = 512;
if ((sectors = scsipi_size(sd->sc_periph, flags)) == 0)
if ((sectors = scsipi_size(sd->sc_periph, &blksize, flags)) == 0)
return (SDGP_RESULT_OFFLINE); /* XXX? */
error = scsipi_mode_sense(sd->sc_periph, SMS_DBD, 6,
@ -1672,7 +1672,7 @@ sd_get_simplifiedparms(struct sd_softc *sd, struct disk_parms *dp, int flags)
dp->blksize = _2btol(scsipi_sense.lbs);
if (dp->blksize == 0)
dp->blksize = 512;
dp->blksize = blksize ? blksize : 512;
/*
* Create a pseudo-geometry.
@ -1700,13 +1700,13 @@ static int
sd_get_capacity(struct sd_softc *sd, struct disk_parms *dp, int flags)
{
u_int64_t sectors;
int error;
int error, blksize;
#if 0
int i;
u_int8_t *p;
#endif
dp->disksize = sectors = scsipi_size(sd->sc_periph, flags);
dp->disksize = sectors = scsipi_size(sd->sc_periph, &blksize, flags);
if (sectors == 0) {
struct scsipi_read_format_capacities cmd;
struct {
@ -1761,7 +1761,7 @@ printf("rfc result:"); for (i = sizeof(struct scsipi_capacity_list_header) + dat
memset(&scsipi_sense, 0, sizeof(scsipi_sense));
error = sd_mode_sense(sd, 0, &scsipi_sense,
sizeof(scsipi_sense.blk_desc), 0, flags | XS_CTL_SILENT, &big);
dp->blksize = 512;
dp->blksize = blksize ? blksize : 512;
if (!error) {
if (big) {
bdesc = (void *)(&scsipi_sense.header.big + 1);
@ -1780,7 +1780,7 @@ printf("page 0 ok\n");
if (bsize >= 8) {
dp->blksize = _3btol(bdesc->blklen);
if (dp->blksize == 0)
dp->blksize = 512;
dp->blksize = blksize ? blksize : 512;
}
}
}