View Javadoc

1   package org.jscsi.target.scsi.modeSense;
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   * The Caching mode page defines the parameters that affect the use of the data cache by the storage medium.
12   * 
13   * @author Andreas Ergenzinger
14   */
15  public final class CachingModePage extends Page_0FormatModePage {
16  
17      /**
18       * An initiator control (IC) enable bit set to one specifies that the device server use one of the following fields
19       * to control the caching algorithm rather than the device server’s own adaptive algorithm:
20       * <ol>
21       * <li>
22       * the NUMBER OF CACHE SEGMENTS field, if the SIZE bit is set to zero; or</li>
23       * <li>
24       * the CACHE SEGMENT SIZE field, if the SIZE bit is set to one.</li>
25       * </ol>
26       */
27      private final boolean initiatorControl;
28  
29      /**
30       * An abort pre-fetch (ABPF) bit set to one when the DRA bit is set to zero specifies that the device server abort a
31       * pre-fetch upon receipt of a new command. An ABPF bit set to one takes precedence over the value specified in the
32       * MINIMUM PRE-FETCH field. An ABPF bit set to zero when the DRA bit set to zero specifies that the termination of
33       * any active pre-fetch is dependent upon Caching mode page bytes 4 through 11 and is vendor specific.
34       */
35      private final boolean abortPrefetch;
36  
37      /**
38       * A caching analysis permitted (CAP) bit set to one specifies that the device server perform caching analysis
39       * during subsequent operations. A CAP bit set to zero specifies that caching analysis be disabled (e.g., to reduce
40       * overhead time or to prevent nonpertinent operations from impacting tuning values).
41       */
42      private final boolean cachingAnalysisPermitted;
43  
44      /**
45       * A discontinuity (DISC) bit set to one specifies that the device server continue the pre-fetch across time
46       * discontinuities (e.g., across cylinders) up to the limits of the buffer, or segment, space available for the
47       * pre-fetch. A DISC bit set to zero specifies that pre-fetches be truncated or wrapped at time discontinuities.
48       */
49      private final boolean discontinuity;
50  
51      /**
52       * A size enable (SIZE) bit set to one specifies that the CACHE SEGMENT SIZE field be used to control caching
53       * segmentation. A SIZE bit set to zero specifies that the NUMBER OF CACHE SEGMENTS field be used to control caching
54       * segmentation. Simultaneous use of both the number of segments and the segment size is vendor specific.
55       */
56      private final boolean sizeEnable;
57  
58      /**
59       * A writeback cache enable (WCE) bit set to zero specifies that the device server shall complete a WRITE command
60       * with GOOD status only after writing all of the data to the medium without error. A WCE bit set to one specifies
61       * that the device server may complete a WRITE command with GOOD status after receiving the data without error and
62       * prior to having written the data to the medium.
63       */
64      private final boolean writebackCacheEnable;
65  
66      /**
67       * A multiplication factor (MF) bit set to zero specifies that the device server shall interpret the MINIMUM
68       * PRE-FETCH field and the MAXIMUM PRE-FETCH field in terms of the number of logical blocks for each of the
69       * respective types of pre-fetch. An MF bit set to one specifies that the device server shall interpret the MINIMUM
70       * PRE-FETCH field and the MAXIMUM PRE-FETCH field to be specified in terms of a scalar number that, when multiplied
71       * by the number of logical blocks to be transferred for the current command, yields the number of logical blocks
72       * for each of the respective types of pre-fetch.
73       */
74      private final boolean multiplicationFactor;
75  
76      /**
77       * A read cache disable (RCD) bit set to zero specifies that the device server may return data requested by a READ
78       * command by accessing either the cache or medium. A RCD bit set to one specifies that the device server shall
79       * transfer all of the data requested by a READ command from the medium (i.e., data shall not be transferred from
80       * the cache).
81       */
82      private final boolean readCacheDisable;
83  
84      /**
85       * The DEMAND READ RETENTION PRIORITY field specifies the retention priority the device server should assign for
86       * data read into the cache that has also been transferred to the data-in buffer.
87       * <table border="1">
88       * <tr>
89       * <th>Code</th>
90       * <th>Description</th>
91       * </tr>
92       * <tr>
93       * <td>0x0</td>
94       * <td>The device server should not distinguish between retaining the<br/>
95       * indicated data and data placed into the cache by other means <br/>
96       * (e.g., pre-fetch).</td>
97       * </tr>
98       * <tr>
99       * <td>0x1</td>
100      * <td>The device server should replace data put into the cache via a<br/>
101      * READ command sooner (i.e., read data has lower priority) than data<br/>
102      * placed into the cache by other means (e.g., pre-fetch).</td>
103      * </tr>
104      * <tr>
105      * <td>0x2 to 0xE</td>
106      * <td>Reserved</td>
107      * </tr>
108      * </tr>
109      * <tr>
110      * <td>0xF</td>
111      * <td>The device server should not replace data put into the cache<br/>
112      * via a READ command if there is other data in the cache that was<br/>
113      * placed into the cache by other means (e.g., pre-fetch) and the<br/>
114      * data in the cache may be replaced.</td>
115      * </tr>
116      * </table>
117      */
118     private final byte demandReadRetentionPriority;
119 
120     /**
121      * The WRITE RETENTION PRIORITY field (see table 155) specifies the retention priority the device server should
122      * assign for data written into the cache that has also been transferred from the cache to the medium.
123      * <table border="1">
124      * <tr>
125      * <th>Code</th>
126      * <th>Description</th>
127      * </tr>
128      * <tr>
129      * <td>0x0</td>
130      * <td>The device server should not distinguish between retaining the<br/>
131      * indicated data and data placed into the cache by other means<br/>
132      * (e.g., pre-fetch).</td>
133      * </tr>
134      * <tr>
135      * <td>0x1</td>
136      * <td>The device server should replace data put into the cache during a<br/>
137      * WRITE command or a WRITE AND VERIFY command sooner (i.e., has lower<br/>
138      * priority) than data placed into the cache by other means (e.g., pre-fetch).</td>
139      * </tr>
140      * <tr>
141      * <td>0x2 to 0xE</td>
142      * <td>Reserved</td>
143      * </tr>
144      * </tr>
145      * <tr>
146      * <td>0xF</td>
147      * <td>The device server should not replace data put into the cache during<br/>
148      * a WRITE command or a WRITE AND VERIFY command if there is other data in<br/>
149      * the cache that was placed into the cache by other means (e.g., pre-fetch) <br/>
150      * and the data in the cache may be replaced.</td>
151      * </tr>
152      * </table>
153      */
154     private final byte writeRetentionPriority;
155 
156     /**
157      * The DISABLE PRE-FETCH TRANSFER LENGTH field specifies the selective disabling of anticipatory pre-fetch on long
158      * transfer lengths. The value in this field is compared to the transfer length requested by a READ command. If the
159      * transfer length is greater than the disable pre-fetch transfer length, then an anticipatory pre-fetch is not done
160      * for the command. Otherwise the device server should attempt an anticipatory pre-fetch. If the DISABLE PRE-FETCH
161      * TRANSFER LENGTH field is set to zero, then all anticipatory pre-fetching is disabled for any request for data,
162      * including those with a transfer length of zero.
163      * <p>
164      * An anticipatory pre-fetch occurs when data is placed in the cache that has not been requested. This may happen in
165      * conjunction with the reading of data that has been requested. The DISABLE PRE-FETCH TRANSFER LENGTH field, the
166      * MINIMUM PRE-FETCH field, the MAXIMUM PRE-FETCH field, and the MAXIMUM PRE-FETCH CEILING field give an indication
167      * to the device server how it should manage the cache based on the most recent READ command. An anticipatory
168      * pre-fetch may occur based on other information. These fields are only recommendations to the device server and
169      * should not cause a CHECK CONDITION to occur if the device server is not able to satisfy the request.
170      */
171     private final int disablePrefetchTransferLength;
172 
173     /**
174      * The MINIMUM PRE-FETCH field specifies the number of logical blocks to pre-fetch regardless of the delays it might
175      * cause in processing subsequent commands. The field contains either:
176      * <ol>
177      * <li>a number of logical blocks, if the MF bit is set to zero; or</li>
178      * <li>a scalar multiplier of the value in the TRANSFER LENGTH field, if the MF bit is set to one.</li>
179      * </ol>
180      * The pre-fetching operation begins at the logical block after the last logical block of a READ command.
181      * <p>
182      * Pre-fetching shall always halt when it reaches the last logical block on the medium. Errors that occur during the
183      * pre-fetching operation shall not be reported to the application client unless the device server is unable to
184      * process subsequent commands correctly as a result of the error. In this case the error may be reported either as
185      * an error for that subsequent command, or as a deferred error, at the discretion of the device server and
186      * according to the rules for reporting deferred errors (see SPC-4).
187      * <p>
188      * If the pre-fetch has read more than the amount of data specified by the MINIMUM PRE-FETCH field, then
189      * pre-fetching should be terminated whenever another command enters the enabled state (see SAM-4). This requirement
190      * is ignored when the MINIMUM PRE-FETCH field value is equal to the MAXIMUM PRE-FETCH field value.
191      * 
192      * @see #disablePrefetchTransferLength
193      */
194     private final int minimumPrefetch;
195 
196     /**
197      * A complementary field to the {@link #minimumPrefetch} field.
198      * 
199      * @see #disablePrefetchTransferLength
200      * @see #minimumPrefetch
201      */
202     private final int maximumPrefetch;
203 
204     /**
205      * The MAXIMUM PRE-FETCH CEILING field specifies an upper limit on the number of logical blocks computed as the
206      * maximum pre-fetch. If this number of logical blocks is greater than the value in the MAXIMUM PRE-FETCH field,
207      * then the number of logical blocks to pre-fetch shall be truncated to the value stored in the MAXIMUM PRE-FETCH
208      * CEILING field.
209      * 
210      * @see #disablePrefetchTransferLength
211      */
212     private final int maximumPrefetchCeiling;
213 
214     /**
215      * A force sequential write (FSW) bit set to one specifies that, for commands writing to more than one logical
216      * block, the device server shall write the logical blocks to the medium in ascending sequential order. An FSW bit
217      * set to zero specifies that the device server may reorder the sequence of writing logical blocks (e.g., in order
218      * to achieve faster command completion).
219      */
220     private final boolean forceSequentialWrite;
221 
222     /**
223      * A logical block cache segment size (LBCSS) bit set to one specifies that the CACHE SEGMENT SIZE field units shall
224      * be interpreted as logical blocks. An LBCSS bit set to zero specifies that the CACHE SEGMENT SIZE field units
225      * shall be interpreted as bytes. The LBCSS shall not impact the units of other fields.
226      */
227     private final boolean logicalBlockCacheSegmentSize;
228 
229     /**
230      * A disable read-ahead (DRA) bit set to one specifies that the device server shall not read into the pre-fetch
231      * buffer any logical blocks beyond the addressed logical block(s). A DRA bit set to zero specifies that the device
232      * server may continue to read logical blocks into the pre-fetch buffer beyond the addressed logical block(s).
233      */
234     private final boolean disableReadAhead;
235 
236     /**
237      * An NV_DIS bit set to one specifies that the device server shall disable a non-volatile cache and indicates that a
238      * non-volatile cache is supported but disabled. An NV_DIS bit set to zero specifies that the device server may use
239      * a non-volatile cache and indicates that a non-volatile cache may be present and enabled.
240      */
241     private final boolean nonVolatileCacheDisabled;
242 
243     /**
244      * The NUMBER OF CACHE SEGMENTS field specifies the number of segments into which the device server shall divide the
245      * cache.
246      */
247     private final short numberOfCacheSegments;
248 
249     /**
250      * The CACHE SEGMENT SIZE field specifies the segment size in bytes if the LBCSS bit is set to zero or in logical
251      * blocks if the LBCSS bit is set to one. The CACHE SEGMENT SIZE field is valid only when the SIZE bit is set to
252      * one.
253      */
254     private final int cacheSegmentSize;
255 
256     /**
257      * The constructor.
258      * <p>
259      * The meaning of all parameters is described in the member descriptions of the variables with the same name.
260      * 
261      * @param parametersSaveable
262      * @param initiatorControl
263      * @param abortPrefetch
264      * @param cachingAnalysisPermitted
265      * @param discontinuity
266      * @param sizeEnable
267      * @param writebackCacheEnable
268      * @param multiplicationFactor
269      * @param readCacheDisable
270      * @param demandReadRetentionPriority
271      * @param writeRetentionPriority
272      * @param disablePrefetchTransferLength
273      * @param minimumPrefetch
274      * @param maximumPrefetch
275      * @param maximumPrefetchCeiling
276      * @param forceSequentialWrite
277      * @param logicalBlockCacheSegmentSize
278      * @param disableReadAhead
279      * @param nonVolatileCacheDisabled
280      * @param numberOfCacheSegments
281      * @param cacheSegmentSize
282      */
283     public CachingModePage (final boolean parametersSaveable, final boolean initiatorControl, final boolean abortPrefetch, final boolean cachingAnalysisPermitted, final boolean discontinuity, final boolean sizeEnable, final boolean writebackCacheEnable, final boolean multiplicationFactor, final boolean readCacheDisable, final int demandReadRetentionPriority, final int writeRetentionPriority, final int disablePrefetchTransferLength, final int minimumPrefetch, final int maximumPrefetch, final int maximumPrefetchCeiling, final boolean forceSequentialWrite, final boolean logicalBlockCacheSegmentSize, final boolean disableReadAhead, final boolean nonVolatileCacheDisabled, final int numberOfCacheSegments, final int cacheSegmentSize) {
284         super(parametersSaveable,// PS
285         0x08,// pageCode
286         0x12);// pageLength
287         this.initiatorControl = initiatorControl;
288         this.abortPrefetch = abortPrefetch;
289         this.cachingAnalysisPermitted = cachingAnalysisPermitted;
290         this.discontinuity = discontinuity;
291         this.sizeEnable = sizeEnable;
292         this.writebackCacheEnable = writebackCacheEnable;
293         this.multiplicationFactor = multiplicationFactor;
294         this.readCacheDisable = readCacheDisable;
295         this.demandReadRetentionPriority = (byte) (demandReadRetentionPriority & 0xf);
296         this.writeRetentionPriority = (byte) (writeRetentionPriority & 0xf);
297         this.disablePrefetchTransferLength = disablePrefetchTransferLength & 0xffff;
298         this.minimumPrefetch = minimumPrefetch & 0xffff;
299         this.maximumPrefetch = maximumPrefetch & 0xffff;
300         this.maximumPrefetchCeiling = maximumPrefetchCeiling & 0xffff;
301         this.forceSequentialWrite = forceSequentialWrite;
302         this.logicalBlockCacheSegmentSize = logicalBlockCacheSegmentSize;
303         this.disableReadAhead = disableReadAhead;
304         this.nonVolatileCacheDisabled = nonVolatileCacheDisabled;
305         this.numberOfCacheSegments = (short) (numberOfCacheSegments & 0xff);
306         this.cacheSegmentSize = cacheSegmentSize & 0xffff;
307     }
308 
309     @Override
310     protected void serializeModeParameters (ByteBuffer buffer, int index) {
311         // serialize byte 2
312         buffer.position(index + 2);
313         byte b = 0;
314         b = BitManip.getByteWithBitSet(b, 7, initiatorControl);
315         b = BitManip.getByteWithBitSet(b, 6, abortPrefetch);
316         b = BitManip.getByteWithBitSet(b, 5, cachingAnalysisPermitted);
317         b = BitManip.getByteWithBitSet(b, 4, discontinuity);
318         b = BitManip.getByteWithBitSet(b, 3, sizeEnable);
319         b = BitManip.getByteWithBitSet(b, 2, writebackCacheEnable);
320         b = BitManip.getByteWithBitSet(b, 1, multiplicationFactor);
321         b = BitManip.getByteWithBitSet(b, 0, readCacheDisable);
322         buffer.put(b);
323         // serialize byte 3
324         b = (byte) ((demandReadRetentionPriority << 4) | writeRetentionPriority);
325         buffer.put(b);
326         // bytes 4 to 11 (unsigned short fields)
327         ReadWrite.writeTwoByteInt(buffer,// buffer
328                 disablePrefetchTransferLength,// value
329                 index + 4);// index
330         ReadWrite.writeTwoByteInt(buffer,// buffer
331                 minimumPrefetch,// value
332                 index + 6);// index
333         ReadWrite.writeTwoByteInt(buffer,// buffer
334                 maximumPrefetch,// value
335                 index + 8);// index
336         ReadWrite.writeTwoByteInt(buffer,// buffer
337                 maximumPrefetchCeiling,// value
338                 index + 10);// index
339         // byte 12
340         b = 0;
341         b = BitManip.getByteWithBitSet(b, 7, forceSequentialWrite);
342         b = BitManip.getByteWithBitSet(b, 6, logicalBlockCacheSegmentSize);
343         b = BitManip.getByteWithBitSet(b, 5, disableReadAhead);
344         b = BitManip.getByteWithBitSet(b, 0, nonVolatileCacheDisabled);
345         buffer.position(index + 12);
346         buffer.put(b);
347         // byte 13
348         buffer.put((byte) numberOfCacheSegments);
349         // bytes 14 and 15
350         ReadWrite.writeTwoByteInt(buffer,// buffer
351                 cacheSegmentSize,// value
352                 index + 14);// index
353         // the remaining bytes are reserved or obsolete
354     }
355 
356 }