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>SEND DIAGNOSTIC</code> SCSI command. * * @author Andreas Ergenzinger */ public final class SendDiagnosticCdb extends CommandDescriptorBlock { /** * If the {@link #selfTest} bit is set to one, the {@link #selfTestCode} field shall contain 000b ( * {@link SelfTestCode#ALL_ZEROS}. If the SELFTEST * bit is set to zero, the contents of SELF-TEST CODE specifies which * diagnostic operation the device server shall perform. * * @see SelfTestCode */ private final SelfTestCode selfTestCode; /** * A self-test (SELFTEST) bit set to one specifies that the device server * shall perform the logical unit default self-test. * <p> * A SELFTEST bit set to zero specifies that the device server shall perform the diagnostic operation * specified by the {@link #selfTestCode} field or in the parameter list. * <p> * Only support for the default self-test feature, as required by SPC-3, is implemented. Request for other * types of self-test operations will be declined. */ private final boolean selfTest; /** * A page format (PF) bit set to one specifies that the SEND DIAGNOSTIC * parameters and any parameters returned by a following RECEIVE DIAGNOSTIC * RESULTS command with the PCV bit set to zero shall contain a single * diagnostic page. * <p> * A PF bit set to zero specifies that all SEND DIAGNOSTIC parameters are vendor specific. If the * PARAMETER LIST LENGTH field is set to zero and the SEND DIAGNOSTIC command is not going to be followed * by a corresponding RECEIVE DIAGNOSTIC RESULTS command with the PCV bit set to zero, then the * application client shall set the PF bit to zero. * <p> * The implementation of the PF bit is optional and therefore not supported by the jSCSI Target. */ private final boolean pageFormat; /** * A unit offline (UNITOFFL) bit set to one specifies that the device server * may perform diagnostic operations that may affect the user accessible * medium on the logical unit (e.g., write operations to the user accessible * medium, or repositioning of the medium on sequential access devices). The * device server may ignore the UNITOFFL bit. A UNITOFFL bit set to zero * prohibits any diagnostic operations that may be detected by subsequent * tasks. When the {@link #selfTest} bit is set to zero, the UNITOFFL bit * shall be ignored. */ private final boolean unitOffline; /** * A SCSI target device offline (DEVOFFL) bit set to one grants permission * to the device server to perform diagnostic operations that may affect all * the logical units in the SCSI target device (e.g., alteration of * reservations, log parameters, or sense data). The device server may * ignore the DEVOFFL bit. A DEVOFFL bit set to zero prohibits diagnostic * operations that may be detected by subsequent tasks. When the {@link #selfTest} bit is set to zero, the * DEVOFFL bit shall be ignored. */ private final boolean deviceOffline; /** * The PARAMETER LIST LENGTH field specifies the length in bytes of the * parameter list that shall be transferred from the application client * Data-Out Buffer to the device server. A parameter list length of zero * specifies that no data shall be transferred. This condition shall not be * considered an error. If PF bit is set to one and the specified parameter * list length results in the truncation of the diagnostic page (e.g., the * parameter list length does not match the page length specified in the * diagnostic page), then the command shall be terminated with CHECK * CONDITION status, with the sense key set to ILLEGAL REQUEST, and the * additional sense code set to INVALID FIELD IN CDB. */ private final short parameterListLength; public SendDiagnosticCdb(ByteBuffer buffer) { super(buffer); // deserialize specific fields final byte b = buffer.get(1); // self test selfTest = BitManip.getBit(b, 2); if (!selfTest) addIllegalFieldPointer(1, 2);// only the default self-test feature // is supported // self test code selfTestCode = SelfTestCode.getValue(b >>> 5); if (selfTest && selfTestCode != SelfTestCode.ALL_ZEROS) addIllegalFieldPointer(1, 7); // page format pageFormat = BitManip.getBit(b, 4); if (pageFormat) addIllegalFieldPointer(1, 4);// The implementation of the PF bit is // optional. // device offline deviceOffline = BitManip.getBit(b, 1); // unit offline unitOffline = BitManip.getBit(b, 0); // parameter list length parameterListLength = (short)ReadWrite.readTwoByteInt(buffer, 3); } public final boolean getSelfTest() { return selfTest; } public final SelfTestCode getSelfTestCode() { return selfTestCode; } public final boolean getPageFormat() { return pageFormat; } public final boolean getUnitOffline() { return unitOffline; } public final boolean getDeviceOffline() { return deviceOffline; } public final short getParameterListLength() { return parameterListLength; } }