package org.jscsi.target.scsi.modeSense; import java.nio.ByteBuffer; import org.jscsi.target.connection.TargetSession; import org.jscsi.target.scsi.IResponseData; /** * The mode parameter list contains a header, followed by zero or more block * descriptors, followed by zero or more variable-length mode pages. * <p> * This class uses the builder pattern to minimize the number of constructors and to avoid constructor use * with a lot of <code>null</code> parameters. * * @author Andreas Ergenzinger */ public final class ModeParameterList implements IResponseData { /** * The header contains information about the fields that follow. */ private final ModeParameterHeader modeParameterHeader; /** * Contains the elements of the list of Logical Block Descriptors. */ private final LogicalBlockDescriptor[] logicalBlockDescriptors; /** * Contains the elements of the list of Mode Pages. */ private final ModePage[] modePages; /** * Returns a new {@link ModeParameterList} instance based the variables of * the <i>builder</i> object. If these variables are mutually exclusive, * then this method will return <code>null</code> instead. * * @param builder * contains all necessary information to create a {@link ModeParameterList} object * @return a new {@link ModeParameterList} or <code>null</code> */ public static ModeParameterList build(final ModeParameterListBuilder builder, final TargetSession session) { if (!builder.checkIntegrity()) return null; // everything is okay, so // - calculate block descriptor length int blockDescriptorLength; if (builder.logicalBlockDescriptors == null) blockDescriptorLength = 0; else { int singleLbdLength; if (builder.longLba) singleLbdLength = LongLogicalBlockDescriptor.SIZE; else singleLbdLength = ShortLogicalBlockDescriptor.SIZE; blockDescriptorLength = builder.logicalBlockDescriptors.length * singleLbdLength; } // - calculate mode data length int modeDataLength; // -- calculate contribution of the header without bytes of MODE DATA // LENGTH field final boolean writeProtect = session.getStorageModule().isWriteProtected(); if (builder.headerType == HeaderType.MODE_PARAMETER_HEADER_6) modeDataLength = ModeParameterHeader6.SIZE - ModeParameterHeader6.MODE_DATA_LENGTH_FIELD_SIZE; else modeDataLength = ModeParameterHeader10.SIZE - ModeParameterHeader10.MODE_DATA_LENGTH_FIELD_SIZE; // -- add length of logical block descriptors modeDataLength += blockDescriptorLength; // -- add length of mode pages if (builder.modePages != null) for (ModePage mp : builder.modePages) modeDataLength += mp.size(); /* * It might be nice to check the values for overflow here, however this * is not necessary, since the length of all available/returned elements * will always be less than 256. */ ModeParameterHeader modeParameterHeader; if (builder.headerType == HeaderType.MODE_PARAMETER_HEADER_6) modeParameterHeader = new ModeParameterHeader6(modeDataLength, blockDescriptorLength, writeProtect); else modeParameterHeader = new ModeParameterHeader10(modeDataLength, blockDescriptorLength, writeProtect, builder.longLba); // create and return the ModeParameterList return new ModeParameterList(modeParameterHeader, builder.logicalBlockDescriptors, builder.modePages); } private ModeParameterList(final ModeParameterHeader modeParameterHeader, final LogicalBlockDescriptor[] logicalBlockDescriptors, final ModePage[] modePages) { this.modeParameterHeader = modeParameterHeader; this.logicalBlockDescriptors = logicalBlockDescriptors; this.modePages = modePages; } public void serialize(ByteBuffer byteBuffer, int index) { int offset = 0; // serialize header modeParameterHeader.serialize(byteBuffer, index); offset += modeParameterHeader.size(); // serialize logical block descriptors if (logicalBlockDescriptors != null) for (LogicalBlockDescriptor lbd : logicalBlockDescriptors) { lbd.serialize(byteBuffer, index + offset); offset += lbd.size(); } // serialize mode pages if (modePages != null) for (ModePage mp : modePages) { mp.serialize(byteBuffer, index + offset); offset += mp.size(); } } public int size() { // size = header + logical block descriptors + mode pages int size = modeParameterHeader.size(); if (logicalBlockDescriptors != null && logicalBlockDescriptors.length > 0) size += logicalBlockDescriptors[0].size() * logicalBlockDescriptors.length;// all have the same // size if (modePages != null) for (ModePage mp : modePages) size += mp.size(); return size; } }