And thus spake SBC-3:

If the number of logical blocks exceeds the maximum value that is able to be
specified in the RETURNED  LOGICAL BLOCK ADDRESS field, the device server
shall set the RETURNED LOGICAL BLOCK ADDRESS field to  FFFFFFFFh. The
application client should then issue a READ CAPACITY (16) command (see 5.11)
to  retrieve the READ CAPACITY (16) parameter data.

Implement this in scsipi_size().

First issue in kern/28514.
This commit is contained in:
thorpej 2004-12-03 20:20:32 +00:00
parent c89e858b2a
commit e112950229
3 changed files with 73 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsipi_base.c,v 1.121 2004/10/01 03:39:11 enami Exp $ */
/* $NetBSD: scsipi_base.c,v 1.122 2004/12/03 20:20:32 thorpej 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.121 2004/10/01 03:39:11 enami Exp $");
__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.122 2004/12/03 20:20:32 thorpej Exp $");
#include "opt_scsi.h"
@ -1026,22 +1026,47 @@ scsipi_interpret_sense(struct scsipi_xfer *xs)
u_int64_t
scsipi_size(struct scsipi_periph *periph, int flags)
{
struct scsipi_read_capacity cmd;
struct scsipi_read_cap_data data;
union {
struct scsipi_read_capacity cmd;
struct scsipi_read_capacity_16 cmd16;
} cmd;
union {
struct scsipi_read_cap_data data;
struct scsipi_read_capacity_16_data data16;
} data;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = READ_CAPACITY;
cmd.cmd.opcode = READ_CAPACITY;
/*
* If the command works, interpret the result as a 4 byte
* number of blocks
*/
if (scsipi_command(periph, (void *)&cmd, sizeof(cmd),
(void *)&data, sizeof(data), SCSIPIRETRIES, 20000, NULL,
if (scsipi_command(periph, (void *)&cmd.cmd, sizeof(cmd.cmd),
(void *)&data.data, sizeof(data.data), SCSIPIRETRIES, 20000, NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
return (0);
return (_4btol(data.addr) + 1);
if (_4btol(data.data.addr) != 0xffffffff)
return (_4btol(data.data.addr) + 1);
/*
* Device is larger than can be reflected by READ CAPACITY (10).
* Try READ CAPACITY (16).
*/
memset(&cmd, 0, sizeof(cmd));
cmd.cmd16.opcode = READ_CAPACITY_16;
cmd.cmd16.byte2 = SRC16_SERVICE_ACTION;
_lto4b(sizeof(data.data16), cmd.cmd16.len);
if (scsipi_command(periph, (void *)&cmd.cmd16, sizeof(cmd.cmd16),
(void *)&data.data16, sizeof(data.data16), SCSIPIRETRIES, 20000,
NULL,
flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
return (0);
return (_8btol(data.data16.addr) + 1);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsipi_disk.h,v 1.9 2003/09/17 23:33:43 mycroft Exp $ */
/* $NetBSD: scsipi_disk.h,v 1.10 2004/12/03 20:20:32 thorpej Exp $ */
/*
* SCSI and SCSI-like interfaces description
@ -86,6 +86,28 @@ struct scsipi_read_cap_data {
u_int8_t length[4];
} __attribute__((packed));
#define READ_CAPACITY_16 0x9e /* really SERVICE ACTION IN */
struct scsipi_read_capacity_16 {
u_int8_t opcode;
u_int8_t byte2;
#define SRC16_SERVICE_ACTION 0x10
u_int8_t addr[8];
u_int8_t len[4];
u_int8_t byte15;
#define SRC16_PMI 0x01
u_int8_t control;
};
struct scsipi_read_capacity_16_data {
u_int8_t addr[8];
u_int8_t length[4];
u_int8_t byte13;
#define SRC16D_PROT_EN 0x01
#define SRC16D_RTO_EN 0x02
u_int8_t reserved[19];
};
/* XXX SBC-2 says this is vendor-specific */
#define READ_FORMAT_CAPACITIES 0x23
struct scsipi_read_format_capacities {
u_int8_t opcode;

View File

@ -1,4 +1,4 @@
/* $NetBSD: scsipiconf.h,v 1.90 2004/09/17 23:43:17 mycroft Exp $ */
/* $NetBSD: scsipiconf.h,v 1.91 2004/12/03 20:20:32 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2004 The NetBSD Foundation, Inc.
@ -773,6 +773,22 @@ _5btol(const u_int8_t *bytes)
return (rv);
}
static __inline u_int64_t __unused
_8btol(const u_int8_t *bytes)
{
u_int64_t rv;
rv = ((u_int64_t)bytes[0] << 56) |
((u_int64_t)bytes[1] << 48) |
((u_int64_t)bytes[2] << 40) |
((u_int64_t)bytes[3] << 32) |
((u_int64_t)bytes[4] << 24) |
((u_int64_t)bytes[5] << 16) |
((u_int64_t)bytes[6] << 8) |
(u_int64_t)bytes[7];
return (rv);
}
static __inline void __unused
_lto2l(u_int32_t val, u_int8_t *bytes)
{