|  | @@ -96,12 +96,41 @@ static int scsi_write ( struct block_device *blockdev, uint64_t block,
 | 
		
	
		
			
			| 96 | 96 |  }
 | 
		
	
		
			
			| 97 | 97 |  
 | 
		
	
		
			
			| 98 | 98 |  /**
 | 
		
	
		
			
			| 99 |  | - * Read capacity of SCSI device
 | 
		
	
		
			
			|  | 99 | + * Read capacity of SCSI device via READ CAPACITY (10)
 | 
		
	
		
			
			| 100 | 100 |   *
 | 
		
	
		
			
			| 101 | 101 |   * @v blockdev		Block device
 | 
		
	
		
			
			| 102 | 102 |   * @ret rc		Return status code
 | 
		
	
		
			
			| 103 | 103 |   */
 | 
		
	
		
			
			| 104 |  | -static int scsi_read_capacity ( struct block_device *blockdev ) {
 | 
		
	
		
			
			|  | 104 | +static int scsi_read_capacity_10 ( struct block_device *blockdev ) {
 | 
		
	
		
			
			|  | 105 | +	struct scsi_device *scsi = block_to_scsi ( blockdev );
 | 
		
	
		
			
			|  | 106 | +	struct scsi_command command;
 | 
		
	
		
			
			|  | 107 | +	struct scsi_cdb_read_capacity_10 *cdb = &command.cdb.readcap10;
 | 
		
	
		
			
			|  | 108 | +	struct scsi_capacity_10 capacity;
 | 
		
	
		
			
			|  | 109 | +	int rc;
 | 
		
	
		
			
			|  | 110 | +
 | 
		
	
		
			
			|  | 111 | +	/* Issue READ CAPACITY (10) */
 | 
		
	
		
			
			|  | 112 | +	memset ( &command, 0, sizeof ( command ) );
 | 
		
	
		
			
			|  | 113 | +	cdb->opcode = SCSI_OPCODE_READ_CAPACITY_10;
 | 
		
	
		
			
			|  | 114 | +	command.data_in = virt_to_user ( &capacity );
 | 
		
	
		
			
			|  | 115 | +	command.data_in_len = sizeof ( capacity );
 | 
		
	
		
			
			|  | 116 | +
 | 
		
	
		
			
			|  | 117 | +	if ( ( rc = scsi_command ( scsi, &command ) ) != 0 )
 | 
		
	
		
			
			|  | 118 | +		return rc;
 | 
		
	
		
			
			|  | 119 | +
 | 
		
	
		
			
			|  | 120 | +	/* Fill in block device fields */
 | 
		
	
		
			
			|  | 121 | +	blockdev->blksize = be32_to_cpu ( capacity.blksize );
 | 
		
	
		
			
			|  | 122 | +	blockdev->blocks = ( be32_to_cpu ( capacity.lba ) + 1 );
 | 
		
	
		
			
			|  | 123 | +
 | 
		
	
		
			
			|  | 124 | +	return 0;
 | 
		
	
		
			
			|  | 125 | +}
 | 
		
	
		
			
			|  | 126 | +
 | 
		
	
		
			
			|  | 127 | +/**
 | 
		
	
		
			
			|  | 128 | + * Read capacity of SCSI device via READ CAPACITY (16)
 | 
		
	
		
			
			|  | 129 | + *
 | 
		
	
		
			
			|  | 130 | + * @v blockdev		Block device
 | 
		
	
		
			
			|  | 131 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 132 | + */
 | 
		
	
		
			
			|  | 133 | +static int scsi_read_capacity_16 ( struct block_device *blockdev ) {
 | 
		
	
		
			
			| 105 | 134 |  	struct scsi_device *scsi = block_to_scsi ( blockdev );
 | 
		
	
		
			
			| 106 | 135 |  	struct scsi_command command;
 | 
		
	
		
			
			| 107 | 136 |  	struct scsi_cdb_read_capacity_16 *cdb = &command.cdb.readcap16;
 | 
		
	
	
		
			
			|  | @@ -125,6 +154,32 @@ static int scsi_read_capacity ( struct block_device *blockdev ) {
 | 
		
	
		
			
			| 125 | 154 |  	return 0;
 | 
		
	
		
			
			| 126 | 155 |  }
 | 
		
	
		
			
			| 127 | 156 |  
 | 
		
	
		
			
			|  | 157 | +/**
 | 
		
	
		
			
			|  | 158 | + * Read capacity of SCSI device
 | 
		
	
		
			
			|  | 159 | + *
 | 
		
	
		
			
			|  | 160 | + * @v blockdev		Block device
 | 
		
	
		
			
			|  | 161 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 162 | + */
 | 
		
	
		
			
			|  | 163 | +static int scsi_read_capacity ( struct block_device *blockdev ) {
 | 
		
	
		
			
			|  | 164 | +	int rc;
 | 
		
	
		
			
			|  | 165 | +
 | 
		
	
		
			
			|  | 166 | +	/* Try READ CAPACITY (10), which is a mandatory command, first. */
 | 
		
	
		
			
			|  | 167 | +	if ( ( rc = scsi_read_capacity_10 ( blockdev ) ) != 0 )
 | 
		
	
		
			
			|  | 168 | +		return rc;
 | 
		
	
		
			
			|  | 169 | +
 | 
		
	
		
			
			|  | 170 | +	/* If capacity range was exceeded (i.e. capacity.lba was
 | 
		
	
		
			
			|  | 171 | +	 * 0xffffffff, meaning that blockdev->blocks is now zero), use
 | 
		
	
		
			
			|  | 172 | +	 * READ CAPACITY (16) instead.  READ CAPACITY (16) is not
 | 
		
	
		
			
			|  | 173 | +	 * mandatory, so we can't just use it straight off.
 | 
		
	
		
			
			|  | 174 | +	 */
 | 
		
	
		
			
			|  | 175 | +	if ( blockdev->blocks == 0 ) {
 | 
		
	
		
			
			|  | 176 | +		if ( ( rc = scsi_read_capacity_16 ( blockdev ) ) != 0 )
 | 
		
	
		
			
			|  | 177 | +			return rc;
 | 
		
	
		
			
			|  | 178 | +	}
 | 
		
	
		
			
			|  | 179 | +
 | 
		
	
		
			
			|  | 180 | +	return 0;
 | 
		
	
		
			
			|  | 181 | +}
 | 
		
	
		
			
			|  | 182 | +
 | 
		
	
		
			
			| 128 | 183 |  /**
 | 
		
	
		
			
			| 129 | 184 |   * Initialise SCSI device
 | 
		
	
		
			
			| 130 | 185 |   *
 |