package org.jscsi.target.connection.stage.fullfeature;
import java.io.IOException;
import java.security.DigestException;
import org.jscsi.exception.InternetSCSIException;
import org.jscsi.parser.BasicHeaderSegment;
import org.jscsi.parser.ProtocolDataUnit;
import org.jscsi.parser.scsi.SCSICommandParser;
import org.jscsi.parser.scsi.SCSIResponseParser;
import org.jscsi.parser.scsi.SCSIStatus;
import org.jscsi.target.connection.TargetPduFactory;
import org.jscsi.target.connection.phase.TargetFullFeaturePhase;
import org.jscsi.target.scsi.ScsiResponseDataSegment;
import org.jscsi.target.scsi.cdb.SendDiagnosticCdb;
import org.jscsi.target.scsi.sense.senseDataDescriptor.senseKeySpecific.FieldPointerSenseKeySpecificData;
import org.jscsi.target.settings.SettingsException;
/**
* A stage for processing <code>SEND DIAGNOSTIC</code> SCSI commands.
* <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.
*
* @author Andreas Ergenzinger
*/
public class SendDiagnosticStage extends TargetFullFeatureStage {
public SendDiagnosticStage(TargetFullFeaturePhase targetFullFeaturePhase) {
super(targetFullFeaturePhase);
}
@Override
public void execute(ProtocolDataUnit pdu) throws IOException, InterruptedException,
InternetSCSIException, DigestException, SettingsException {
final BasicHeaderSegment bhs = pdu.getBasicHeaderSegment();
final SCSICommandParser parser = (SCSICommandParser)bhs.getParser();
ProtocolDataUnit responsePdu = null;// the response PDU
// get command details in CDB
final SendDiagnosticCdb cdb = new SendDiagnosticCdb(parser.getCDB());
final FieldPointerSenseKeySpecificData[] illegalFieldPointers = cdb.getIllegalFieldPointers();
if (illegalFieldPointers != null) {
// an illegal request has been made
responsePdu = createFixedFormatErrorPdu(illegalFieldPointers,// senseKeySpecificData
bhs.getInitiatorTaskTag(),// initiatorTaskTag
parser.getExpectedDataTransferLength());// expectedDataTransferLength
} else {
// PDU is okay
// carry out command
/*
* The self-test bit is 1, since request of a non-default self-test
* is not supported and would have led to illegalFieldPointer !=
* null
*
* A self-test (SELFTEST) bit set to one specifies that the device
* server shall perform the logical unit default self-test. If the
* self-test successfully passes, the command shall be terminated
* with GOOD status. If the self-test fails, the command shall be
* terminated with CHECK CONDITION status, with the sense key set to
* HARDWARE ERROR.
*
* The self-test is always successful.
*/
responsePdu = TargetPduFactory.createSCSIResponsePdu(false,// bidirectionalReadResidualOverflow
false,// bidirectionalReadResidualUnderflow
false,// residualOverflow
false,// residualUnderflow,
SCSIResponseParser.ServiceResponse.COMMAND_COMPLETED_AT_TARGET,// response,
SCSIStatus.GOOD,// status,
bhs.getInitiatorTaskTag(),// initiatorTaskTag,
0,// snackTag
0,// expectedDataSequenceNumber
0,// bidirectionalReadResidualCount
0,// residualCount
ScsiResponseDataSegment.EMPTY_DATA_SEGMENT);// data
// segment
}
// send response
connection.sendPdu(responsePdu);
}
}