package org.jscsi.target.scsi.modeSense; import java.nio.ByteBuffer; import org.jscsi.target.scsi.ISerializable; import org.jscsi.target.util.BitManip; /** * MODE PAGEs are sent in response to successful <code>MODE SENSE</code> SCSI * commands. There are two different, command-specific formats for MODE PAGEs - * the PAGE_0 FORMAT and the SUB-PAGE FORMAT, represented by the non-abstract * children of this class, {@link Page_0FormatModePage} and {@link SubPageFormatModePage}, respectively. * * @author Andreas Ergenzinger */ public abstract class ModePage implements ISerializable { /** * This value plus {@link #pageLength} equals the length in bytes of a MODE * PAGE using the SUB-PAGE FORMAT. */ private static final int SUB_PAGE_FORMAT_PAGE_LENGTH_MODIFIER = 4; /** * This value plus {@link #pageLength} equals the length in bytes of a MODE * PAGE using the PAGE_0 FORMAT. */ private static final int PAGE_0_FORMAT_PAGE_LENGTH_MODIFIER = 2; /** * When using the MODE SENSE command, a parameters saveable (PS) bit set to * one indicates that the mode page may be saved by the logical unit in a * nonvolatile, vendor specific location. A PS bit set to zero indicates * that the device server is not able to save the supporte parameters. When * using the MODE SELECT command, the PS bit is reserved. */ private final boolean parametersSaveable; /** * A SubPage Format (SPF) bit set to <code>false</code>/zero indicates that * the page_0 mode page format is being used. A SPF bit set to <code>true</code>/one indicates that the * sub_page mode page format is * being used. */ private final boolean subPageFormat; /** * Specifies what kind of information is contained in the MODE PAGE. */ private final int pageCode; /** * The number of bytes following the PAGE LENGTH field. */ protected final int pageLength; /** * This value plus {@link #pageLength} equals the length in bytes of the * MODE PAGE. */ private final int pageLengthModifier; /** * The abstract constructor. * * @param parametersSaveable * value of the PARAMETERS SAVEABLE bit * @param subPageFormat * <code>true</code> if and only if the SUB-PAGE FORMAT is to be * used * @param pageCode * specifies the kind of information is contained in the MODE * PAGE * @param pageLength * the value of the PAGE LENGTH field */ public ModePage(final boolean parametersSaveable, final boolean subPageFormat, final int pageCode, final int pageLength) { this.parametersSaveable = parametersSaveable; this.subPageFormat = subPageFormat; if (subPageFormat) pageLengthModifier = SUB_PAGE_FORMAT_PAGE_LENGTH_MODIFIER; else pageLengthModifier = PAGE_0_FORMAT_PAGE_LENGTH_MODIFIER; this.pageCode = pageCode; this.pageLength = pageLength; } public final void serialize(final ByteBuffer byteBuffer, final int index) { // serialize first byte // (for convenience reasons from least significant to most significant // field) byte b = (byte)pageCode;// PAGE CODE b = BitManip.getByteWithBitSet(b, 6, subPageFormat);// SPF b = BitManip.getByteWithBitSet(b, 7, parametersSaveable);// PS byteBuffer.position(index); byteBuffer.put(b); // serialize remaining fields serializeSubPageCode(byteBuffer, index); serializePageLength(byteBuffer, index); serializeModeParameters(byteBuffer, index); } /** * This method serializes the SUBPAGE CODE field, if the mode page format * says this field exists (only for the sub_page mode page format). * * @param buffer * where to insert the serialized object representation * @param index * the position of the first byte of the serialized object in the {@link ByteBuffer} */ protected abstract void serializeSubPageCode(final ByteBuffer buffer, final int index); /** * Serializes the PAGE LENGTH field. * * @param buffer * where to insert the serialized object representation * @param index * the position of the first byte of the serialized object in the {@link ByteBuffer} */ protected abstract void serializePageLength(final ByteBuffer buffer, final int index); /** * @param buffer * where to insert the serialized object representation * @param index * the position of the first byte of the serialized object in the {@link ByteBuffer} */ protected abstract void serializeModeParameters(final ByteBuffer buffer, final int index); public final int size() { return pageLength + pageLengthModifier; } }