| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| CachingModePage |
|
| 1.0;1 |
| 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 | 0 | super(parametersSaveable,// PS |
| 285 | 0x08,// pageCode | |
| 286 | 0x12);// pageLength | |
| 287 | 0 | this.initiatorControl = initiatorControl; |
| 288 | 0 | this.abortPrefetch = abortPrefetch; |
| 289 | 0 | this.cachingAnalysisPermitted = cachingAnalysisPermitted; |
| 290 | 0 | this.discontinuity = discontinuity; |
| 291 | 0 | this.sizeEnable = sizeEnable; |
| 292 | 0 | this.writebackCacheEnable = writebackCacheEnable; |
| 293 | 0 | this.multiplicationFactor = multiplicationFactor; |
| 294 | 0 | this.readCacheDisable = readCacheDisable; |
| 295 | 0 | this.demandReadRetentionPriority = (byte) (demandReadRetentionPriority & 0xf); |
| 296 | 0 | this.writeRetentionPriority = (byte) (writeRetentionPriority & 0xf); |
| 297 | 0 | this.disablePrefetchTransferLength = disablePrefetchTransferLength & 0xffff; |
| 298 | 0 | this.minimumPrefetch = minimumPrefetch & 0xffff; |
| 299 | 0 | this.maximumPrefetch = maximumPrefetch & 0xffff; |
| 300 | 0 | this.maximumPrefetchCeiling = maximumPrefetchCeiling & 0xffff; |
| 301 | 0 | this.forceSequentialWrite = forceSequentialWrite; |
| 302 | 0 | this.logicalBlockCacheSegmentSize = logicalBlockCacheSegmentSize; |
| 303 | 0 | this.disableReadAhead = disableReadAhead; |
| 304 | 0 | this.nonVolatileCacheDisabled = nonVolatileCacheDisabled; |
| 305 | 0 | this.numberOfCacheSegments = (short) (numberOfCacheSegments & 0xff); |
| 306 | 0 | this.cacheSegmentSize = cacheSegmentSize & 0xffff; |
| 307 | 0 | } |
| 308 | ||
| 309 | @Override | |
| 310 | protected void serializeModeParameters (ByteBuffer buffer, int index) { | |
| 311 | // serialize byte 2 | |
| 312 | 0 | buffer.position(index + 2); |
| 313 | 0 | byte b = 0; |
| 314 | 0 | b = BitManip.getByteWithBitSet(b, 7, initiatorControl); |
| 315 | 0 | b = BitManip.getByteWithBitSet(b, 6, abortPrefetch); |
| 316 | 0 | b = BitManip.getByteWithBitSet(b, 5, cachingAnalysisPermitted); |
| 317 | 0 | b = BitManip.getByteWithBitSet(b, 4, discontinuity); |
| 318 | 0 | b = BitManip.getByteWithBitSet(b, 3, sizeEnable); |
| 319 | 0 | b = BitManip.getByteWithBitSet(b, 2, writebackCacheEnable); |
| 320 | 0 | b = BitManip.getByteWithBitSet(b, 1, multiplicationFactor); |
| 321 | 0 | b = BitManip.getByteWithBitSet(b, 0, readCacheDisable); |
| 322 | 0 | buffer.put(b); |
| 323 | // serialize byte 3 | |
| 324 | 0 | b = (byte) ((demandReadRetentionPriority << 4) | writeRetentionPriority); |
| 325 | 0 | buffer.put(b); |
| 326 | // bytes 4 to 11 (unsigned short fields) | |
| 327 | 0 | ReadWrite.writeTwoByteInt(buffer,// buffer |
| 328 | disablePrefetchTransferLength,// value | |
| 329 | index + 4);// index | |
| 330 | 0 | ReadWrite.writeTwoByteInt(buffer,// buffer |
| 331 | minimumPrefetch,// value | |
| 332 | index + 6);// index | |
| 333 | 0 | ReadWrite.writeTwoByteInt(buffer,// buffer |
| 334 | maximumPrefetch,// value | |
| 335 | index + 8);// index | |
| 336 | 0 | ReadWrite.writeTwoByteInt(buffer,// buffer |
| 337 | maximumPrefetchCeiling,// value | |
| 338 | index + 10);// index | |
| 339 | // byte 12 | |
| 340 | 0 | b = 0; |
| 341 | 0 | b = BitManip.getByteWithBitSet(b, 7, forceSequentialWrite); |
| 342 | 0 | b = BitManip.getByteWithBitSet(b, 6, logicalBlockCacheSegmentSize); |
| 343 | 0 | b = BitManip.getByteWithBitSet(b, 5, disableReadAhead); |
| 344 | 0 | b = BitManip.getByteWithBitSet(b, 0, nonVolatileCacheDisabled); |
| 345 | 0 | buffer.position(index + 12); |
| 346 | 0 | buffer.put(b); |
| 347 | // byte 13 | |
| 348 | 0 | buffer.put((byte) numberOfCacheSegments); |
| 349 | // bytes 14 and 15 | |
| 350 | 0 | ReadWrite.writeTwoByteInt(buffer,// buffer |
| 351 | cacheSegmentSize,// value | |
| 352 | index + 14);// index | |
| 353 | // the remaining bytes are reserved or obsolete | |
| 354 | 0 | } |
| 355 | ||
| 356 | } |