1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 
7 #ifndef __CDRW_WCACHE_LIB_H__
8 #define __CDRW_WCACHE_LIB_H__
9 
10 extern "C" {
11 
12 #include "platform.h"
13 
14 #ifdef _CONSOLE
15 #include "env_spec_w32.h"
16 #else
17 //#include "env_spec.h"
18 #endif
19 
20 #define WCACHE_BOUND_CHECKS
21 
22 typedef OSSTATUS     (*PWRITE_BLOCK) (IN PVOID Context,
23                                       IN PVOID Buffer,     // Target buffer
24                                       IN SIZE_T Length,
25                                       IN lba_t Lba,
26                                       OUT PSIZE_T WrittenBytes,
27                                       IN uint32 Flags);
28 
29 typedef OSSTATUS     (*PREAD_BLOCK) (IN PVOID Context,
30                                      IN PVOID Buffer,     // Target buffer
31                                      IN SIZE_T Length,
32                                      IN lba_t Lba,
33                                      OUT PSIZE_T ReadBytes,
34                                      IN uint32 Flags);
35 
36 typedef OSSTATUS     (*PWRITE_BLOCK_ASYNC) (IN PVOID Context,
37                                             IN PVOID WContext,
38                                             IN PVOID Buffer,     // Target buffer
39                                             IN SIZE_T Length,
40                                             IN lba_t Lba,
41                                             OUT PSIZE_T WrittenBytes,
42                                             IN BOOLEAN FreeBuffer);
43 
44 typedef OSSTATUS     (*PREAD_BLOCK_ASYNC) (IN PVOID Context,
45                                            IN PVOID WContext,
46                                            IN PVOID Buffer,     // Source buffer
47                                            IN SIZE_T Length,
48                                            IN lba_t Lba,
49                                            OUT PSIZE_T ReadBytes);
50 
51 /*typedef BOOLEAN      (*PCHECK_BLOCK) (IN PVOID Context,
52                                       IN lba_t Lba);*/
53 
54 #define WCACHE_BLOCK_USED    0x01
55 #define WCACHE_BLOCK_ZERO    0x02
56 #define WCACHE_BLOCK_BAD     0x04
57 
58 typedef ULONG        (*PCHECK_BLOCK) (IN PVOID Context,
59                                       IN lba_t Lba);
60 
61 typedef OSSTATUS     (*PUPDATE_RELOC) (IN PVOID Context,
62                                        IN lba_t Lba,
63                                        IN PULONG RelocTab,
64                                        IN ULONG BCount);
65 
66 #define WCACHE_ERROR_READ     0x0001
67 #define WCACHE_ERROR_WRITE    0x0002
68 #define WCACHE_ERROR_INTERNAL 0x0003
69 
70 #define WCACHE_W_OP     FALSE
71 #define WCACHE_R_OP     TRUE
72 
73 typedef struct _WCACHE_ERROR_CONTEXT {
74     ULONG WCErrorCode;
75     OSSTATUS Status;
76     BOOLEAN  Retry;
77     UCHAR    Padding[3];
78     union {
79         struct {
80             ULONG    Lba;
81             ULONG    BCount;
82             PVOID    Buffer;
83         } ReadWrite;
84         struct {
85             ULONG    p1;
86             ULONG    p2;
87             ULONG    p3;
88             ULONG    p4;
89         } Internal;
90     };
91 } WCACHE_ERROR_CONTEXT, *PWCACHE_ERROR_CONTEXT;
92 
93 typedef OSSTATUS     (*PWC_ERROR_HANDLER) (IN PVOID Context,
94                                            IN PWCACHE_ERROR_CONTEXT ErrorInfo);
95 // array of pointers to cached data
96 // each entry corresponds to logical block on disk
97 typedef struct _W_CACHE_ENTRY {
98     union {
99         PCHAR Sector;
100         UCHAR Flags:3;
101     };
102 } W_CACHE_ENTRY, *PW_CACHE_ENTRY;
103 
104 // array of pointers to cache frames
105 // each frame corresponds to extent of logical blocks
106 typedef struct _W_CACHE_FRAME {
107     PW_CACHE_ENTRY Frame;
108     ULONG BlockCount;
109     //ULONG WriteCount;      // number of modified packets in cache frame, is always 0, shall be removed
110     ULONG UpdateCount;     // number of updates in cache frame
111     ULONG AccessCount;     // number of accesses to cache frame
112 } W_CACHE_FRAME, *PW_CACHE_FRAME;
113 
114 // memory type for cached blocks
115 #define CACHED_BLOCK_MEMORY_TYPE PagedPool
116 #define MAX_TRIES_FOR_NA         3
117 
118 #define WCACHE_ADDR_MASK     0xfffffff8
119 #define WCACHE_FLAG_MASK     0x00000007
120 #define WCACHE_FLAG_MODIFIED 0x00000001
121 #define WCACHE_FLAG_ZERO     0x00000002
122 #define WCACHE_FLAG_BAD      0x00000004
123 
124 #define WCACHE_MODE_ROM      0x00000000  // read only (CD-ROM)
125 #define WCACHE_MODE_RW       0x00000001  // rewritable (CD-RW)
126 #define WCACHE_MODE_R        0x00000002  // WORM (CD-R)
127 #define WCACHE_MODE_RAM      0x00000003  // random writable device (HDD)
128 #define WCACHE_MODE_EWR      0x00000004  // ERASE-cycle required (MO)
129 #define WCACHE_MODE_MAX      WCACHE_MODE_RAM
130 
131 #define PH_TMP_BUFFER          1
132 
133 struct _W_CACHE_ASYNC;
134 
135 typedef struct _W_CACHE {
136     // cache tables
137     ULONG Tag;
138     PW_CACHE_FRAME FrameList;   // pointer to list of Frames
139     lba_t* CachedBlocksList;    // sorted list of cached blocks
140     lba_t* CachedFramesList;    // sorted list of cached frames
141     lba_t* CachedModifiedBlocksList;    // sorted list of cached modified blocks
142     // settings & current state
143     ULONG BlocksPerFrame;
144     ULONG BlocksPerFrameSh;
145     ULONG BlockCount;
146     ULONG MaxBlocks;
147     ULONG MaxBytesToRead;
148     ULONG FrameCount;
149     ULONG MaxFrames;
150     ULONG PacketSize;      // number of blocks in packet
151     ULONG PacketSizeSh;
152     ULONG BlockSize;
153     ULONG BlockSizeSh;
154     ULONG WriteCount;      // number of modified packets in cache
155     lba_t FirstLba;
156     lba_t LastLba;
157     ULONG Mode;            // RO/WOR/RW/EWR
158 
159     ULONG Flags;
160     BOOLEAN CacheWholePacket;
161     BOOLEAN DoNotCompare;
162     BOOLEAN Chained;
163     BOOLEAN RememberBB;
164     BOOLEAN NoWriteBB;
165     BOOLEAN NoWriteThrough;
166     UCHAR  Padding[2];
167 
168     ULONG RBalance;
169     ULONG WBalance;
170     ULONG FramesToKeepFree;
171     // callbacks
172     PWRITE_BLOCK WriteProc;
173     PREAD_BLOCK ReadProc;
174     PWRITE_BLOCK_ASYNC WriteProcAsync;
175     PREAD_BLOCK_ASYNC ReadProcAsync;
176     PCHECK_BLOCK CheckUsedProc;
177     PUPDATE_RELOC UpdateRelocProc;
178     PWC_ERROR_HANDLER ErrorHandlerProc;
179     // sync resource
180     ERESOURCE WCacheLock;
181 //    BOOLEAN WCResInit;
182     // preallocated tmp buffers
183     PCHAR tmp_buff;
184     PCHAR tmp_buff_r;
185     PULONG reloc_tab;
186 
187 } W_CACHE, *PW_CACHE;
188 
189 #define WCACHE_INVALID_LBA  ((lba_t)(-1))
190 
191 #define WCACHE_CACHE_WHOLE_PACKET   0x01
192 #define WCACHE_DO_NOT_COMPARE       0x02
193 #define WCACHE_CHAINED_IO           0x04
194 #define WCACHE_MARK_BAD_BLOCKS      0x08
195 #define WCACHE_RO_BAD_BLOCKS        0x10
196 #define WCACHE_NO_WRITE_THROUGH     0x20
197 
198 #define WCACHE_VALID_FLAGS          (WCACHE_CACHE_WHOLE_PACKET | \
199                                      WCACHE_DO_NOT_COMPARE | \
200                                      WCACHE_CHAINED_IO | \
201                                      WCACHE_MARK_BAD_BLOCKS | \
202                                      WCACHE_RO_BAD_BLOCKS | \
203                                      WCACHE_NO_WRITE_THROUGH)
204 
205 #define WCACHE_INVALID_FLAGS        (0xffffffff)
206 
207 // init cache
208 OSSTATUS WCacheInit__(IN PW_CACHE Cache,
209                       IN ULONG MaxFrames,
210                       IN ULONG MaxBlocks,
211                       IN SIZE_T MaxBytesToRead,
212                       IN ULONG PacketSizeSh,    // number of blocks in packet (bit shift)
213                       IN ULONG BlockSizeSh,     // bit shift
214                       IN ULONG BlocksPerFrameSh,// bit shift
215                       IN lba_t FirstLba,
216                       IN lba_t LastLba,
217                       IN ULONG Mode,
218                       IN ULONG Flags,
219                       IN ULONG FramesToKeepFree,
220                       IN PWRITE_BLOCK WriteProc,
221                       IN PREAD_BLOCK ReadProc,
222                       IN PWRITE_BLOCK_ASYNC WriteProcAsync,
223                       IN PREAD_BLOCK_ASYNC ReadProcAsync,
224                       IN PCHECK_BLOCK CheckUsedProc,
225                       IN PUPDATE_RELOC UpdateRelocProc,
226                       IN PWC_ERROR_HANDLER ErrorHandlerProc);
227 // write cached
228 OSSTATUS WCacheWriteBlocks__(IN PW_CACHE Cache,
229                              IN PVOID Context,
230                              IN PCHAR Buffer,
231                              IN lba_t Lba,
232                              IN ULONG BCount,
233                              OUT PSIZE_T WrittenBytes,
234                              IN BOOLEAN CachedOnly);
235 // read cached
236 OSSTATUS WCacheReadBlocks__(IN PW_CACHE Cache,
237                             IN PVOID Context,
238                             IN PCHAR Buffer,
239                             IN lba_t Lba,
240                             IN ULONG BCount,
241                             OUT PSIZE_T ReadBytes,
242                             IN BOOLEAN CachedOnly);
243 // flush blocks
244 OSSTATUS WCacheFlushBlocks__(IN PW_CACHE Cache,
245                              IN PVOID Context,
246                              IN lba_t Lba,
247                              IN ULONG BCount);
248 // discard blocks
249 VOID     WCacheDiscardBlocks__(IN PW_CACHE Cache,
250                                IN PVOID Context,
251                                IN lba_t Lba,
252                                IN ULONG BCount);
253 // flush whole cache
254 VOID     WCacheFlushAll__(IN PW_CACHE Cache,
255                           IN PVOID Context);
256 // purge whole cache
257 VOID     WCachePurgeAll__(IN PW_CACHE Cache,
258                           IN PVOID Context);
259 // free structures
260 VOID     WCacheRelease__(IN PW_CACHE Cache);
261 
262 // check if initialized
263 BOOLEAN  WCacheIsInitialized__(IN PW_CACHE Cache);
264 
265 // direct access to cached data
266 OSSTATUS WCacheDirect__(IN PW_CACHE Cache,
267                         IN PVOID Context,
268                         IN lba_t Lba,
269                         IN BOOLEAN Modified,
270                         OUT PCHAR* CachedBlock,
271                         IN BOOLEAN CachedOnly);
272 // release resources after direct access
273 OSSTATUS WCacheEODirect__(IN PW_CACHE Cache,
274                           IN PVOID Context);
275 // release resources before direct access
276 OSSTATUS WCacheStartDirect__(IN PW_CACHE Cache,
277                              IN PVOID Context,
278                              IN BOOLEAN Exclusive);
279 // check if requested extent completly cached
280 BOOLEAN  WCacheIsCached__(IN PW_CACHE Cache,
281                           IN lba_t Lba,
282                           IN ULONG BCount);
283 
284 // change cache media mode
285 OSSTATUS WCacheSetMode__(IN PW_CACHE Cache,
286                          IN ULONG Mode);
287 //
288 ULONG    WCacheGetMode__(IN PW_CACHE Cache);
289 //
290 ULONG    WCacheGetWriteBlockCount__(IN PW_CACHE Cache);
291 //
292 VOID     WCacheSyncReloc__(IN PW_CACHE Cache,
293                            IN PVOID Context);
294 
295 VOID     WCacheDiscardBlocks__(IN PW_CACHE Cache,
296                              IN PVOID Context,
297                              IN lba_t ReqLba,
298                              IN ULONG BCount);
299 
300 ULONG    WCacheChFlags__(IN PW_CACHE Cache,
301                          IN ULONG SetFlags,
302                          IN ULONG ClrFlags);
303 
304 };
305 
306 // complete async request (callback)
307 OSSTATUS WCacheCompleteAsync__(IN PVOID WContext,
308                                IN OSSTATUS Status);
309 
310 #endif // __CDRW_WCACHE_LIB_H__
311