Validate the sector size returned by READ CAPACITY. If it looks bogus
print a warning and fallback to a suitable default. Fixes a problem on hp700 reported by skrll@
This commit is contained in:
parent
e8ac1cad77
commit
4526a898c6
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: scsipi_base.c,v 1.139 2006/10/12 01:31:57 christos Exp $ */
|
||||
/* $NetBSD: scsipi_base.c,v 1.140 2006/10/20 07:11:50 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.139 2006/10/12 01:31:57 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.140 2006/10/20 07:11:50 scw Exp $");
|
||||
|
||||
#include "opt_scsi.h"
|
||||
|
||||
|
@ -1020,13 +1020,46 @@ scsipi_interpret_sense(struct scsipi_xfer *xs)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* scsipi_validate_secsize:
|
||||
*
|
||||
* Validate the sector size reported by READ_CAPACITY_1[06].
|
||||
* Use the supplied default if the reported size looks wrong.
|
||||
*/
|
||||
static int
|
||||
scsipi_validate_secsize(struct scsipi_periph *periph, const char *opcode,
|
||||
int raw_len, int def_len)
|
||||
{
|
||||
|
||||
switch (raw_len) {
|
||||
case 256:
|
||||
case 512:
|
||||
case 1024:
|
||||
case 2048:
|
||||
case 4096:
|
||||
break;
|
||||
|
||||
default:
|
||||
scsipi_printaddr(periph);
|
||||
printf("%s returned %s sector size: 0x%x. Defaulting to %d "
|
||||
"bytes.\n", opcode, (raw_len ^ (1 << (ffs(raw_len) - 1))) ?
|
||||
"preposterous" : "unsupported", raw_len, def_len);
|
||||
/*FALLTHROUGH*/
|
||||
case 0:
|
||||
raw_len = def_len;
|
||||
break;
|
||||
}
|
||||
|
||||
return (raw_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* scsipi_size:
|
||||
*
|
||||
* Find out from the device what its capacity is.
|
||||
*/
|
||||
u_int64_t
|
||||
scsipi_size(struct scsipi_periph *periph, int *secsize, int flags)
|
||||
scsipi_size(struct scsipi_periph *periph, int *secsize, int defsize, int flags)
|
||||
{
|
||||
union {
|
||||
struct scsipi_read_capacity_10 cmd;
|
||||
|
@ -1050,8 +1083,11 @@ scsipi_size(struct scsipi_periph *periph, int *secsize, int flags)
|
|||
return (0);
|
||||
|
||||
if (_4btol(data.data.addr) != 0xffffffff) {
|
||||
if (secsize)
|
||||
*secsize = _4btol(data.data.length);
|
||||
if (secsize) {
|
||||
*secsize = scsipi_validate_secsize(periph,
|
||||
"READ_CAPACITY_10", _4btol(data.data.length),
|
||||
defsize);
|
||||
}
|
||||
return (_4btol(data.data.addr) + 1);
|
||||
}
|
||||
|
||||
|
@ -1071,8 +1107,10 @@ scsipi_size(struct scsipi_periph *periph, int *secsize, int flags)
|
|||
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
|
||||
return (0);
|
||||
|
||||
if (secsize)
|
||||
*secsize = _4btol(data.data16.length);
|
||||
if (secsize) {
|
||||
*secsize = scsipi_validate_secsize(periph, "READ_CAPACITY_16",
|
||||
_4btol(data.data16.length), defsize);
|
||||
}
|
||||
return (_8btol(data.data16.addr) + 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: scsipiconf.h,v 1.104 2006/10/09 21:29:14 scw Exp $ */
|
||||
/* $NetBSD: scsipiconf.h,v 1.105 2006/10/20 07:11:50 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 *, int);
|
||||
u_int64_t scsipi_size(struct scsipi_periph *, int *, 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.252 2006/10/12 01:31:57 christos Exp $ */
|
||||
/* $NetBSD: sd.c,v 1.253 2006/10/20 07:11:50 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.252 2006/10/12 01:31:57 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.253 2006/10/20 07:11:50 scw Exp $");
|
||||
|
||||
#include "opt_scsi.h"
|
||||
#include "rnd.h"
|
||||
|
@ -1661,7 +1661,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, &blksize, flags)) == 0)
|
||||
if ((sectors = scsipi_size(sd->sc_periph, &blksize, 512, flags)) == 0)
|
||||
return (SDGP_RESULT_OFFLINE); /* XXX? */
|
||||
|
||||
error = scsipi_mode_sense(sd->sc_periph, SMS_DBD, 6,
|
||||
|
@ -1673,7 +1673,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 = blksize ? blksize : 512;
|
||||
dp->blksize = blksize;
|
||||
|
||||
/*
|
||||
* Create a pseudo-geometry.
|
||||
|
@ -1707,7 +1707,8 @@ sd_get_capacity(struct sd_softc *sd, struct disk_parms *dp, int flags)
|
|||
u_int8_t *p;
|
||||
#endif
|
||||
|
||||
dp->disksize = sectors = scsipi_size(sd->sc_periph, &blksize, flags);
|
||||
dp->disksize = sectors = scsipi_size(sd->sc_periph, &blksize, 512,
|
||||
flags);
|
||||
if (sectors == 0) {
|
||||
struct scsipi_read_format_capacities cmd;
|
||||
struct {
|
||||
|
@ -1762,7 +1763,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 = blksize ? blksize : 512;
|
||||
dp->blksize = blksize;
|
||||
if (!error) {
|
||||
if (big) {
|
||||
bdesc = (void *)(&scsipi_sense.header.big + 1);
|
||||
|
@ -1781,7 +1782,7 @@ printf("page 0 ok\n");
|
|||
if (bsize >= 8) {
|
||||
dp->blksize = _3btol(bdesc->blklen);
|
||||
if (dp->blksize == 0)
|
||||
dp->blksize = blksize ? blksize : 512;
|
||||
dp->blksize = blksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue