Subject: Re: kern/28514: READ_FORMAT_CAPACITIES reply has 32-bit block count
To: None <jpk@panix.com>
From: Jason Thorpe <thorpej@shagadelic.org>
List: netbsd-bugs
Date: 12/02/2004 21:11:09
--Apple-Mail-24--810581729
Content-Type: multipart/mixed; boundary=Apple-Mail-23--810581759


--Apple-Mail-23--810581759
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed


On Dec 2, 2004, at 1:21 PM, jpk@panix.com wrote:

> thorej suggested:
> It might require our sd driver to issue a different command to read the
> capacity, because the READ_FORMAT_CAPACITIES reply only has a 32-bit
> block count.

Can you please try the following patch?

         -- Jason R. Thorpe <thorpej@shagadelic.org>

--Apple-Mail-23--810581759
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0644;
	name="src16-patch.txt"
Content-Disposition: attachment;
	filename=src16-patch.txt

Index: scsipi_base.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipi_base.c,v
retrieving revision 1.121
diff -c -p -r1.121 scsipi_base.c
*** scsipi_base.c	1 Oct 2004 03:39:11 -0000	1.121
--- scsipi_base.c	3 Dec 2004 05:09:47 -0000
*************** scsipi_interpret_sense(struct scsipi_xfe
*** 1026,1047 ****
  u_int64_t
  scsipi_size(struct scsipi_periph *periph, int flags)
  {
! 	struct scsipi_read_capacity cmd;
! 	struct scsipi_read_cap_data data;
  
  	memset(&cmd, 0, sizeof(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,
  	    flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
  		return (0);
  
! 	return (_4btol(data.addr) + 1);
  }
  
  /*
--- 1026,1072 ----
  u_int64_t
  scsipi_size(struct scsipi_periph *periph, int flags)
  {
! 	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.cmd.opcode = READ_CAPACITY;
  
  	/*
  	 * If the command works, interpret the result as a 4 byte
  	 * number of blocks
  	 */
! 	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);
  
! 	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);
  }
  
  /*
Index: scsipi_disk.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipi_disk.h,v
retrieving revision 1.9
diff -c -p -r1.9 scsipi_disk.h
*** scsipi_disk.h	17 Sep 2003 23:33:43 -0000	1.9
--- scsipi_disk.h	3 Dec 2004 05:09:47 -0000
*************** struct scsipi_read_cap_data {
*** 86,91 ****
--- 86,113 ----
  	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;
Index: scsipiconf.h
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/scsipiconf.h,v
retrieving revision 1.90
diff -c -p -r1.90 scsipiconf.h
*** scsipiconf.h	17 Sep 2004 23:43:17 -0000	1.90
--- scsipiconf.h	3 Dec 2004 05:09:48 -0000
*************** _5btol(const u_int8_t *bytes)
*** 773,778 ****
--- 773,794 ----
  	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)
  {

--Apple-Mail-23--810581759--

--Apple-Mail-24--810581729
content-type: application/pgp-signature; x-mac-type=70674453;
	name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (Darwin)

iD8DBQFBr/VuOpVKkaBm8XkRAmTbAKCpEW25nFe2gg8jC5H/dfafSQie2QCdF6my
ZZv5Ney8OXLnCKzGoF+HgyA=
=qb9+
-----END PGP SIGNATURE-----

--Apple-Mail-24--810581729--