View Javadoc

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 }