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:
parent
d6e105789d
commit
056c6fdd05
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue