1 package org.jscsi.target.scsi.cdb;
2
3
4 import java.nio.ByteBuffer;
5
6 import org.jscsi.target.util.BitManip;
7 import org.jscsi.target.util.ReadWrite;
8
9
10 /**
11 * This class represents Command Descriptor Blocks for the <code>SEND DIAGNOSTIC</code> SCSI command.
12 *
13 * @author Andreas Ergenzinger
14 */
15 public final class SendDiagnosticCdb extends CommandDescriptorBlock {
16
17 /**
18 * If the {@link #selfTest} bit is set to one, the {@link #selfTestCode} field shall contain 000b (
19 * {@link SelfTestCode#ALL_ZEROS}. If the SELFTEST bit is set to zero, the contents of SELF-TEST CODE specifies
20 * which diagnostic operation the device server shall perform.
21 *
22 * @see SelfTestCode
23 */
24 private final SelfTestCode selfTestCode;
25
26 /**
27 * A self-test (SELFTEST) bit set to one specifies that the device server shall perform the logical unit default
28 * self-test.
29 * <p>
30 * A SELFTEST bit set to zero specifies that the device server shall perform the diagnostic operation specified by
31 * the {@link #selfTestCode} field or in the parameter list.
32 * <p>
33 * Only support for the default self-test feature, as required by SPC-3, is implemented. Request for other types of
34 * self-test operations will be declined.
35 */
36 private final boolean selfTest;
37
38 /**
39 * A page format (PF) bit set to one specifies that the SEND DIAGNOSTIC parameters and any parameters returned by a
40 * following RECEIVE DIAGNOSTIC RESULTS command with the PCV bit set to zero shall contain a single diagnostic page.
41 * <p>
42 * A PF bit set to zero specifies that all SEND DIAGNOSTIC parameters are vendor specific. If the PARAMETER LIST
43 * LENGTH field is set to zero and the SEND DIAGNOSTIC command is not going to be followed by a corresponding
44 * RECEIVE DIAGNOSTIC RESULTS command with the PCV bit set to zero, then the application client shall set the PF bit
45 * to zero.
46 * <p>
47 * The implementation of the PF bit is optional and therefore not supported by the jSCSI Target.
48 */
49 private final boolean pageFormat;
50
51 /**
52 * A unit offline (UNITOFFL) bit set to one specifies that the device server may perform diagnostic operations that
53 * may affect the user accessible medium on the logical unit (e.g., write operations to the user accessible medium,
54 * or repositioning of the medium on sequential access devices). The device server may ignore the UNITOFFL bit. A
55 * UNITOFFL bit set to zero prohibits any diagnostic operations that may be detected by subsequent tasks. When the
56 * {@link #selfTest} bit is set to zero, the UNITOFFL bit shall be ignored.
57 */
58 private final boolean unitOffline;
59
60 /**
61 * A SCSI target device offline (DEVOFFL) bit set to one grants permission to the device server to perform
62 * diagnostic operations that may affect all the logical units in the SCSI target device (e.g., alteration of
63 * reservations, log parameters, or sense data). The device server may ignore the DEVOFFL bit. A DEVOFFL bit set to
64 * zero prohibits diagnostic operations that may be detected by subsequent tasks. When the {@link #selfTest} bit is
65 * set to zero, the DEVOFFL bit shall be ignored.
66 */
67 private final boolean deviceOffline;
68
69 /**
70 * The PARAMETER LIST LENGTH field specifies the length in bytes of the parameter list that shall be transferred
71 * from the application client Data-Out Buffer to the device server. A parameter list length of zero specifies that
72 * no data shall be transferred. This condition shall not be considered an error. If PF bit is set to one and the
73 * specified parameter list length results in the truncation of the diagnostic page (e.g., the parameter list length
74 * does not match the page length specified in the diagnostic page), then the command shall be terminated with CHECK
75 * CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD
76 * IN CDB.
77 */
78 private final short parameterListLength;
79
80 public SendDiagnosticCdb (ByteBuffer buffer) {
81 super(buffer);
82
83 // deserialize specific fields
84 final byte b = buffer.get(1);
85
86 // self test
87 selfTest = BitManip.getBit(b, 2);
88 if (!selfTest) addIllegalFieldPointer(1, 2);// only the default self-test feature
89 // is supported
90
91 // self test code
92 selfTestCode = SelfTestCode.getValue(b >>> 5);
93 if (selfTest && selfTestCode != SelfTestCode.ALL_ZEROS) addIllegalFieldPointer(1, 7);
94
95 // page format
96 pageFormat = BitManip.getBit(b, 4);
97 if (pageFormat) addIllegalFieldPointer(1, 4);// The implementation of the PF bit is
98 // optional.
99
100 // device offline
101 deviceOffline = BitManip.getBit(b, 1);
102
103 // unit offline
104 unitOffline = BitManip.getBit(b, 0);
105
106 // parameter list length
107 parameterListLength = (short) ReadWrite.readTwoByteInt(buffer, 3);
108 }
109
110 public final boolean getSelfTest () {
111 return selfTest;
112 }
113
114 public final SelfTestCode getSelfTestCode () {
115 return selfTestCode;
116 }
117
118 public final boolean getPageFormat () {
119 return pageFormat;
120 }
121
122 public final boolean getUnitOffline () {
123 return unitOffline;
124 }
125
126 public final boolean getDeviceOffline () {
127 return deviceOffline;
128 }
129
130 public final short getParameterListLength () {
131 return parameterListLength;
132 }
133
134 }