1 package org.jscsi.target.scsi.cdb; 2 3 4 import java.nio.ByteBuffer; 5 6 import org.jscsi.target.storage.IStorageModule; 7 8 9 /** 10 * This abstract class represents Command Descriptor Blocks for the <code>READ</code> and <code>WRITE</code> SCSI 11 * commands. This grouping makes sense, since, apart from the different values of the OPERATION CODE field, Read and 12 * Write CDBs are identical. 13 * 14 * @author Andreas Ergenzinger 15 */ 16 public abstract class ReadOrWriteCdb extends CommandDescriptorBlock { 17 18 /** 19 * The logical block address of the first logical block of data, where data shall be read from or written to. 20 * 21 * @see #transferLength 22 */ 23 private final long logicalBlockAddress; 24 25 /** 26 * The TRANSFER LENGTH field specifies the number of contiguous logical blocks of data that shall be read/written 27 * and transferred to/from the (initiator's) data-in buffer, starting with the logical block specified by the 28 * {@link #logicalBlockAddress} field. 29 */ 30 private final int transferLength; 31 32 public ReadOrWriteCdb (ByteBuffer buffer) { 33 super(buffer); 34 logicalBlockAddress = deserializeLogicalBlockAddress(buffer); 35 transferLength = deserializeTransferLength(buffer); 36 } 37 38 /** 39 * Deserializes the value of the {@link #logicalBlockAddress} field. 40 * 41 * @param buffer the {@link ByteBuffer} containing the CDB 42 * @return value of the {@link #logicalBlockAddress} field 43 */ 44 protected abstract long deserializeLogicalBlockAddress (final ByteBuffer buffer); 45 46 /** 47 * Deserializes the value of the {@link #transferLength} field. 48 * 49 * @param buffer the {@link ByteBuffer} containing the CDB 50 * @return value of the {@link #transferLength} field 51 */ 52 protected abstract int deserializeTransferLength (final ByteBuffer buffer); 53 54 /** 55 * Returns the value of {@link #logicalBlockAddress}. 56 * 57 * @return the value of {@link #logicalBlockAddress} 58 */ 59 public final long getLogicalBlockAddress () { 60 return logicalBlockAddress; 61 } 62 63 /** 64 * Returns the value of {@link #transferLength}. 65 * 66 * @return the value of {@link #transferLength} 67 */ 68 public final int getTransferLength () { 69 return transferLength; 70 } 71 72 /** 73 * Returns the index position of the first byte used for encoding the {@link #logicalBlockAddress} field. 74 * 75 * @return the index position of the first byte used for encoding the {@link #logicalBlockAddress} field 76 */ 77 protected abstract int getLogicalBlockAddressFieldIndex (); 78 79 /** 80 * Returns the index position of the first byte used for encoding the {@link #transferLength} field. 81 * 82 * @return the index position of the first byte used for encoding the {@link #transferLength} field 83 */ 84 protected abstract int getTransferLengthFieldIndex (); 85 86 /** 87 * This method is used for signaling an illegal value of the {@link #logicalBlockAddress} variable. 88 * <p> 89 * This method must be called if the {@link #logicalBlockAddress} lies outside the bounds of the used medium. 90 * 91 * @see #getIllegalFieldPointers() 92 * @see IStorageModule#checkBounds(long, int) 93 */ 94 public final void addIllegalFieldPointerForLogicalBlockAddress () { 95 addIllegalFieldPointer(getLogicalBlockAddressFieldIndex()); 96 } 97 98 /** 99 * This method is used for signaling an illegal value of the {@link #transferLength} variable. 100 * <p> 101 * This method must be called if the {@link #transferLength} field value would result in accessing of out-of-bounds 102 * blocks of the storage medium. 103 * 104 * @see #getIllegalFieldPointers() 105 * @see IStorageModule#checkBounds(long, int) 106 */ 107 public final void addIllegalFieldPointerForTransferLength () { 108 addIllegalFieldPointer(getTransferLengthFieldIndex()); 109 } 110 }