1 package org.jscsi.target.scsi.sense;
2
3
4 import java.nio.ByteBuffer;
5
6 import org.jscsi.target.scsi.cdb.ScsiOperationCode;
7 import org.jscsi.target.scsi.sense.information.FourByteInformation;
8 import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.SenseKeySpecificData;
9 import org.jscsi.target.util.BitManip;
10 import org.jscsi.target.util.ReadWrite;
11
12
13 /**
14 * Instances of this class represent sense data using the fixed format.
15 *
16 * @see SenseDataFormat#FIXED
17 * @author Andreas Ergenzinger
18 */
19 public class FixedFormatSenseData extends SenseData {
20
21 /**
22 * The position of the INFORMATION field.
23 */
24 private static final int INFORMATION_FIELD_INDEX = 3;
25
26 /**
27 * The position of the ADDITIONAL SENSE LENGTH field.
28 */
29 private static final int ADDITIONAL_SENSE_LENGTH_INDEX = 7;
30
31 /**
32 * The position of the COMMAND SPECIFIC INFORMATION field.
33 */
34 private static final int COMMAND_SPECIFIC_INFORMATION_FIELD_INDEX = 8;
35
36 /**
37 * The position of the ADDITIONAL SENSE CODE field.
38 */
39 private static final int ADDITIONAL_SENSE_CODE_INDEX = 12;
40
41 /**
42 * The position of the FIELD REPLACEABLE UNIT CODE field.
43 */
44 private static final int FIELD_REPLACEABLE_UNIT_CODE_INDEX = 14;
45
46 /**
47 * The position of the SENSE KEY SPECIFIC DATA field.
48 */
49 private static final int SENSE_KEY_SPECIFIC_DATA_INDEX = 15;
50
51 /**
52 * The minimum length in bytes of a serialized fixed format sense data object.
53 */
54 private static final int MIN_SIZE = 18;
55
56 /**
57 * The minimum value of the ADDITIONAL SENSE LENGTH field.
58 */
59 private static final int MIN_ADDITIONAL_SENSE_LENGTH = 10;
60
61 /**
62 * A VALID bit set to <code>false</code> indicates that the {@link #information} field is not defined in SPC or any
63 * other command standard. A VALID bit set to <code>true</code> indicates the INFORMATION field contains valid
64 * information as defined in the SPC or a command standard.
65 */
66 private final boolean valid;
67
68 /**
69 * See the SSC-2 READ and SPACE commands for examples of FILEMARK bit usage.
70 */
71 private final boolean fileMark;
72
73 /**
74 * See the SSC-2 READ, SPACE, and WRITE commands for examples of end-of-medium (EOM) bit usage.
75 */
76 private final boolean endOfMedium;
77
78 /**
79 * See the SBC-2 READ LONG, SBC-2 WRITE LONG, and SSC-2 READ commands and for examples of incorrect length indicator
80 * (ILI) bit usage.
81 */
82 private final boolean incorrectLengthIndicator;
83
84 /**
85 * If {@link #valid} == <code>true</code> the INFORMATION field contains valid information as defined in the SPC or
86 * SBC standard.
87 */
88 private final FourByteInformation information;
89
90 /**
91 * Command-specific information, if any.
92 */
93 private final FourByteInformation commandSpecificInformation;
94
95 /**
96 * Non-zero values in the FIELD REPLACEABLE UNIT CODE field are used to identify a component that has failed. A
97 * value of zero in this field indicates that no specific component has been identified to have failed or that the
98 * data is not available.
99 * <p>
100 * The format of this information is not specified by the SPC. Additional information about the field replaceable
101 * unit may be available in the ASCII Information VPD page, if supported by the device server.
102 */
103 private final byte fieldReplaceableUnitCode;
104
105 /**
106 * The SenseKeySpecificData sub-class MUST match the senseKey.
107 *
108 * @see SenseKeySpecificData
109 */
110 private final SenseKeySpecificData senseKeySpecificData;
111
112 /**
113 * The additional sense bytes may contain vendor specific data that further defines the nature of the exception
114 * condition.
115 */
116 private final AdditionalSenseBytes additionalSenseBytes;
117
118 /**
119 * The {@link #additionalSenseLength} field indicates the number of additional sense bytes that follow. The
120 * additional sense length shall be less than or equal to 244 (i.e., limiting the total length of the sense data to
121 * 252 bytes). If the sense data is being returned as parameter data by a {@link ScsiOperationCode#REQUEST_SENSE}
122 * command, then the relationship between the {@link #additionalSenseLength} field and the CDB ALLOCATION LENGTH
123 * field is defined in SPC-3.
124 */
125 final private int additionalSenseLength;
126
127 /**
128 * The constructor. All parameters without additional description are used to initialize the member variables with
129 * the same name.
130 *
131 * @param valid
132 * @param errorType the type of error that necessitated the sending of sense data
133 * @param fileMark
134 * @param endOfMedium
135 * @param incorrectLengthIndicator
136 * @param senseKey
137 * @param information
138 * @param commandSpecificInformation
139 * @param additionalSenseCodeAndQualifier
140 * @param fieldReplaceableUnitCode
141 * @param senseKeySpecificData
142 * @param additionalSenseBytes
143 */
144 public FixedFormatSenseData (final boolean valid, final ErrorType errorType, final boolean fileMark, final boolean endOfMedium, final boolean incorrectLengthIndicator, final SenseKey senseKey, final FourByteInformation information, final FourByteInformation commandSpecificInformation, final AdditionalSenseCodeAndQualifier additionalSenseCodeAndQualifier, final byte fieldReplaceableUnitCode, final SenseKeySpecificData senseKeySpecificData, final AdditionalSenseBytes additionalSenseBytes) {
145 super(errorType, SenseDataFormat.FIXED, senseKey, additionalSenseCodeAndQualifier);
146 this.valid = valid;
147 this.fileMark = fileMark;
148 this.endOfMedium = endOfMedium;
149 this.incorrectLengthIndicator = incorrectLengthIndicator;
150 this.information = information;
151 this.commandSpecificInformation = commandSpecificInformation;
152 this.fieldReplaceableUnitCode = fieldReplaceableUnitCode;
153 this.senseKeySpecificData = senseKeySpecificData;
154 this.additionalSenseBytes = additionalSenseBytes;
155 // additional sense length
156 int asl = MIN_ADDITIONAL_SENSE_LENGTH;
157 if (additionalSenseBytes != null) asl += additionalSenseBytes.size();
158 additionalSenseLength = asl;
159 }
160
161 public void serialize (ByteBuffer byteBuffer, int index) {
162
163 byteBuffer.position(index);
164
165 // *** byte 0 ***
166 // response code
167 byte b = (byte) getReponseCodeFor(errorType, SenseDataFormat.FIXED);
168 // valid flag
169 b = BitManip.getByteWithBitSet(b, 7, valid);
170 byteBuffer.put(b);
171
172 // *** byte 1 - is obsolete ***
173 byteBuffer.put((byte) 0);
174
175 // *** byte 2 ***
176 // file mark
177 b = BitManip.getByteWithBitSet((byte) 0, 7, fileMark);
178
179 // EOM
180 b = BitManip.getByteWithBitSet(b, 6, endOfMedium);
181
182 // ILI
183 b = BitManip.getByteWithBitSet(b, 5, incorrectLengthIndicator);
184
185 // sense key
186 b = (byte) (15 & senseKey.getValue());
187 byteBuffer.put(b);
188
189 // *** bytes 3 - 6 ***
190 // information
191 if (information != null) information.serialize(byteBuffer, index + INFORMATION_FIELD_INDEX);
192
193 // additional sense length
194 byteBuffer.put(index + ADDITIONAL_SENSE_LENGTH_INDEX, (byte) additionalSenseLength);
195
196 // command specific information
197 if (commandSpecificInformation != null) commandSpecificInformation.serialize(byteBuffer, index + COMMAND_SPECIFIC_INFORMATION_FIELD_INDEX);
198
199 // additional sense code and additional sense code qualifier
200 ReadWrite.writeTwoByteInt(byteBuffer, additionalSenseCodeAndQualifier.getValue(), index + ADDITIONAL_SENSE_CODE_INDEX);
201
202 // field replaceable unit code
203 byteBuffer.put(FIELD_REPLACEABLE_UNIT_CODE_INDEX, fieldReplaceableUnitCode);
204
205 // sense key specific data
206 if (senseKeySpecificData != null) senseKeySpecificData.serialize(byteBuffer, index + SENSE_KEY_SPECIFIC_DATA_INDEX);
207
208 // additional sense bytes
209 if (additionalSenseBytes != null) additionalSenseBytes.serialize(byteBuffer, index + MIN_SIZE);
210 }
211
212 public final int getAdditionalSenseLength () {
213 return additionalSenseLength;
214 }
215
216 public int size () {
217 int size = MIN_SIZE;
218 if (additionalSenseBytes != null) size += additionalSenseBytes.size();
219 return size;
220 }
221 }