package org.jscsi.target.scsi.cdb;
import java.nio.ByteBuffer;
import org.jscsi.target.util.BitManip;
import org.jscsi.target.util.ReadWrite;
/**
* This class represents Command Descriptor Blocks for the <code>READ (10)
* </code> SCSI command.
* <p>
* The <code>READ (10)</code> command requests that the device server to read the specified logical block(s)
* and transfer them to the data-in buffer.
* <p>
* Each logical block read includes user data and, if the medium is formatted with protection information
* enabled, protection information. Each logical block transferred includes user data and may include
* protection information, based on the RDPROTECT field and the medium format.
*
* @author Andreas Ergenzinger
*/
public final class Read10Cdb extends ReadCdb {
/**
* The value of the RDPROTECT field determines which checks on the
* protection information read from the medium the target shall perform
* before returning status for the command associated with this command
* descriptor block.
* <p>
* Since the jSCSI Target simulates a logical unit formatted without any protection information (that can
* be checked), the value of this field is inconsequential.
*/
private final int readProtect;
/**
* This variable represents the value of the DPO bit. Since the jSCSI Target
* does not support advanced caching strategies, the value of this variable
* is ignored.
* <p>
* A disable page out (DPO) bit set to zero specifies that the retention priority shall be determined by
* the RETENTION PRIORITY fields in the Caching mode page (see 6.4.5). A DPO bit set to one specifies that
* the device server shall assign the logical blocks accessed by this command the lowest retention
* priority for being fetched into or retained by the cache. A DPO bit set to one overrides any retention
* priority specified in the Caching mode page. All other aspects of the algorithm implementing the cache
* replacement strategy are not defined by this standard.
* <p>
* NOTE 11 - The DPO bit is used to control replacement of logical blocks in the cache when the
* application client has information on the future usage of the logical blocks. If the DPO bit is set to
* one, then the application client is specifying that the logical blocks accessed by the command are not
* likely to be accessed again in the near future and should not be put in the cache nor retained by the
* cache. If the DPO bit is set to zero, then the application client is specifying that the logical blocks
* accessed by this command are likely to be accessed again in the near future.
*/
private final boolean disablePageOut;
/**
* The FUA ({@link #forceUnitAccess}) and FUA_NV ( {@link #forceUnitAccessNonVolatileCache}) bits together
* determine from
* exactly the requested data shall be retrieved (cache, non-volatile cache,
* or medium) and whether or not the returned data has to be transferred to
* the medium before sending the response.
* <p>
* <table border="1">
* <tr>
* <th>FUA</th>
* <th>FUA_NV</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>0</td>
* <td>0</td>
* <td>The device server may read the logical blocks from volatile cache, non-volatile cache, and/or the
* medium.</td>
* </tr>
* <tr>
* <td>0</td>
* <td>1</td>
* <td>If the NV_SUP bit is set to one in the Extended INQUIRY Data VPD page (see SPC-4), then the device
* server shall read the logical blocks from non-volatile cache or the medium. If a non-volatile cache is
* present and a volatile cache contains a more recent version of a logical block, then the device server
* shall write the logical block to:<br/>
* a) non-volatile cache; and/or<br/>
* b) the medium,<br/>
* before reading it. If the NV_SUP bit is set to zero in the Extended INQUIRY Data VPD page (see SPC-4),
* then the device server may read the logical blocks from volatile cache, non-volatile cache, and/or the
* medium.</td>
* </tr>
* <tr>
* <td>1</td>
* <td>0 or 1</td>
* <td>The device server may read the logical blocks from volatile cache, non-volatile cache, and/or the
* medium.</td>
* </tr>
* </table>
*/
private final boolean forceUnitAccess;
/**
* The FUA ({@link #forceUnitAccess}) and FUA_NV ( {@link #forceUnitAccessNonVolatileCache}) bits together
* determine from
* exactly the requested data shall be retrieved (cache, non-volatile cache,
* or medium) and whether or not the returned data has to be transferred to
* the medium before sending the response.
*
* @see #forceUnitAccess
*/
private final boolean forceUnitAccessNonVolatileCache;
/**
* The GROUP NUMBER field can specify a particular grouping function, which
* is a function that collects information about attributes associated with
* commands (i.e., information about commands with the same group value are
* collected into the specified group).
* <p>
* The collection of this information is outside the scope of the SCSI standard (as of SBC3R25) and also
* not part of the iSCSI specification, so the value of this field will be ignored.
* <p>
* Support for the grouping function is indicated in the GROUP_SUP bit in the Extended INQUIRY Data VPD
* page (see SPC-4).
* <p>
*
*/
private final int groupNumber;
public Read10Cdb(final ByteBuffer buffer) {
super(buffer);// OPERATION CODE + CONTROL
// RDPROTECT
byte b = buffer.get(1);
readProtect = (b >> 5) & 7;
// DPO
disablePageOut = BitManip.getBit(b, 4);
// FUA
forceUnitAccess = BitManip.getBit(b, 3);
// FUA_NV
forceUnitAccessNonVolatileCache = BitManip.getBit(b, 1);
// GROUP NUMBER
b = buffer.get(6);
groupNumber = b & 31;
}
@Override
protected long deserializeLogicalBlockAddress(ByteBuffer buffer) {
return ReadWrite.readUnsignedInt(buffer, 2);
}
@Override
protected int deserializeTransferLength(ByteBuffer buffer) {
return ReadWrite.readTwoByteInt(buffer, 7);
}
public int getReadProtect() {
return readProtect;
}
public boolean disablePageOut() {
return disablePageOut;
}
public boolean getForceUnitAccess() {
return forceUnitAccess;
}
public boolean getForceUnitAccessNonVolatile() {
return forceUnitAccessNonVolatileCache;
}
public int getGroupNumber() {
return groupNumber;
}
@Override
protected int getLogicalBlockAddressFieldIndex() {
return 2;
}
@Override
protected int getTransferLengthFieldIndex() {
return 7;
}
}