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