Rev 3555 | Rev 4265 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2142 | serge | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
2465 | Serge | 3 | ;; Copyright (C) KolibriOS team 2011-2012. All rights reserved. ;; |
2142 | serge | 4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
||
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
7 | |||
3908 | Serge | 8 | $Revision: 3742 $ |
2142 | serge | 9 | |
10 | ; This function is intended to replace the old 'hd_read' function when |
||
11 | ; [hdd_appl_data] = 0, so its input/output parameters are the same, except |
||
12 | ; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
||
13 | ; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
||
14 | ; eax is relative to partition start |
||
15 | ; out: eax = error code; 0 = ok |
||
16 | fs_read32_sys: |
||
3908 | Serge | 17 | ; Save ecx, set ecx to SysCache and let the common part do its work. |
2142 | serge | 18 | push ecx |
19 | mov ecx, [ebp+PARTITION.Disk] |
||
20 | add ecx, DISK.SysCache |
||
21 | jmp fs_read32_common |
||
22 | |||
23 | ; This function is intended to replace the old 'hd_read' function when |
||
24 | ; [hdd_appl_data] = 1, so its input/output parameters are the same, except |
||
25 | ; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
||
26 | ; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
||
27 | ; eax is relative to partition start |
||
28 | ; out: eax = error code; 0 = ok |
||
29 | fs_read32_app: |
||
3908 | Serge | 30 | ; Save ecx, set ecx to AppCache and let the common part do its work. |
2142 | serge | 31 | push ecx |
32 | mov ecx, [ebp+PARTITION.Disk] |
||
33 | add ecx, DISK.AppCache |
||
34 | |||
35 | ; This label is the common part of fs_read32_sys and fs_read32_app. |
||
36 | fs_read32_common: |
||
37 | ; 1. Check that the required sector is inside the partition. If no, return |
||
38 | ; DISK_STATUS_END_OF_MEDIA. |
||
39 | cmp dword [ebp+PARTITION.Length+4], 0 |
||
40 | jnz @f |
||
41 | cmp dword [ebp+PARTITION.Length], eax |
||
42 | ja @f |
||
43 | mov eax, DISK_STATUS_END_OF_MEDIA |
||
44 | pop ecx |
||
45 | ret |
||
46 | @@: |
||
47 | ; 2. Get the absolute sector on the disk. |
||
2987 | Serge | 48 | push edx esi |
2142 | serge | 49 | xor edx, edx |
50 | add eax, dword [ebp+PARTITION.FirstSector] |
||
51 | adc edx, dword [ebp+PARTITION.FirstSector+4] |
||
52 | ; 3. If there is no cache for this disk, just pass the request to the driver. |
||
53 | cmp [ecx+DISKCACHE.pointer], 0 |
||
54 | jnz .scancache |
||
55 | push 1 |
||
56 | push esp ; numsectors |
||
57 | push edx ; startsector |
||
58 | push eax ; startsector |
||
59 | push ebx ; buffer |
||
2987 | Serge | 60 | mov esi, [ebp+PARTITION.Disk] |
2142 | serge | 61 | mov al, DISKFUNC.read |
62 | call disk_call_driver |
||
63 | pop ecx |
||
2987 | Serge | 64 | pop esi edx |
2142 | serge | 65 | pop ecx |
66 | ret |
||
67 | .scancache: |
||
68 | ; 4. Scan the cache. |
||
2987 | Serge | 69 | push edi ecx ; scan cache |
2142 | serge | 70 | push edx eax |
71 | virtual at esp |
||
72 | .sector_lo dd ? |
||
73 | .sector_hi dd ? |
||
74 | .cache dd ? |
||
75 | end virtual |
||
76 | ; The following code is inherited from hd_read. The differences are: |
||
77 | ; all code is protected by the cache lock; instead of static calls |
||
78 | ; to hd_read_dma/hd_read_pio/bd_read the dynamic call to DISKFUNC.read is used; |
||
79 | ; sector is 64-bit, not 32-bit. |
||
80 | call mutex_lock |
||
81 | mov eax, [.sector_lo] |
||
82 | mov edx, [.sector_hi] |
||
83 | mov esi, [ecx+DISKCACHE.pointer] |
||
84 | mov ecx, [ecx+DISKCACHE.sad_size] |
||
85 | add esi, 12 |
||
86 | |||
87 | mov edi, 1 |
||
88 | |||
89 | .hdreadcache: |
||
90 | |||
91 | cmp dword [esi+8], 0 ; empty |
||
92 | je .nohdcache |
||
93 | |||
94 | cmp [esi], eax ; correct sector |
||
95 | jne .nohdcache |
||
96 | cmp [esi+4], edx ; correct sector |
||
97 | je .yeshdcache |
||
98 | |||
99 | .nohdcache: |
||
100 | |||
101 | add esi, 12 |
||
102 | inc edi |
||
103 | dec ecx |
||
104 | jnz .hdreadcache |
||
105 | |||
106 | mov esi, [.cache] |
||
107 | call find_empty_slot64 ; ret in edi |
||
108 | test eax, eax |
||
109 | jnz .read_done |
||
110 | |||
111 | push 1 |
||
112 | push esp |
||
113 | push edx |
||
114 | push [.sector_lo+12] |
||
3232 | Serge | 115 | mov ecx, [.cache+16] |
2142 | serge | 116 | mov eax, edi |
117 | shl eax, 9 |
||
118 | add eax, [ecx+DISKCACHE.data] |
||
119 | push eax |
||
120 | mov esi, [ebp+PARTITION.Disk] |
||
121 | mov al, DISKFUNC.read |
||
122 | call disk_call_driver |
||
123 | pop ecx |
||
124 | dec ecx |
||
125 | jnz .read_done |
||
126 | |||
127 | mov ecx, [.cache] |
||
128 | lea eax, [edi*3] |
||
129 | mov esi, [ecx+DISKCACHE.pointer] |
||
130 | lea esi, [eax*4+esi] |
||
131 | |||
132 | mov eax, [.sector_lo] |
||
133 | mov edx, [.sector_hi] |
||
134 | mov [esi], eax ; sector number |
||
135 | mov [esi+4], edx ; sector number |
||
136 | mov dword [esi+8], 1; hd read - mark as same as in hd |
||
137 | |||
138 | .yeshdcache: |
||
139 | |||
140 | mov esi, edi |
||
141 | mov ecx, [.cache] |
||
142 | shl esi, 9 |
||
143 | add esi, [ecx+DISKCACHE.data] |
||
144 | |||
145 | mov edi, ebx |
||
146 | mov ecx, 512/4 |
||
3555 | Serge | 147 | rep movsd ; move data |
2142 | serge | 148 | xor eax, eax ; successful read |
149 | .read_done: |
||
150 | mov ecx, [.cache] |
||
151 | push eax |
||
152 | call mutex_unlock |
||
153 | pop eax |
||
154 | add esp, 12 |
||
155 | pop edi esi edx ecx |
||
156 | ret |
||
157 | |||
158 | ; This function is intended to replace the old 'hd_write' function when |
||
159 | ; [hdd_appl_data] = 0, so its input/output parameters are the same, except |
||
160 | ; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
||
161 | ; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
||
162 | ; eax is relative to partition start |
||
163 | ; out: eax = error code; 0 = ok |
||
164 | fs_write32_sys: |
||
3908 | Serge | 165 | ; Save ecx, set ecx to SysCache and let the common part do its work. |
2142 | serge | 166 | push ecx |
167 | mov ecx, [ebp+PARTITION.Disk] |
||
168 | add ecx, DISK.SysCache |
||
169 | jmp fs_write32_common |
||
170 | |||
171 | ; This function is intended to replace the old 'hd_write' function when |
||
172 | ; [hdd_appl_data] = 1, so its input/output parameters are the same, except |
||
173 | ; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. |
||
174 | ; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure |
||
175 | ; eax is relative to partition start |
||
176 | ; out: eax = error code; 0 = ok |
||
177 | fs_write32_app: |
||
3908 | Serge | 178 | ; Save ecx, set ecx to AppCache and let the common part do its work. |
2142 | serge | 179 | push ecx |
180 | mov ecx, [ebp+PARTITION.Disk] |
||
181 | add ecx, DISK.AppCache |
||
182 | |||
183 | ; This label is the common part of fs_read32_sys and fs_read32_app. |
||
184 | fs_write32_common: |
||
185 | ; 1. Check that the required sector is inside the partition. If no, return |
||
186 | ; DISK_STATUS_END_OF_MEDIA. |
||
187 | cmp dword [ebp+PARTITION.Length+4], 0 |
||
188 | jnz @f |
||
189 | cmp dword [ebp+PARTITION.Length], eax |
||
190 | ja @f |
||
191 | mov eax, DISK_STATUS_END_OF_MEDIA |
||
192 | pop ecx |
||
193 | ret |
||
194 | @@: |
||
2987 | Serge | 195 | push edx esi |
2142 | serge | 196 | ; 2. Get the absolute sector on the disk. |
197 | xor edx, edx |
||
198 | add eax, dword [ebp+PARTITION.FirstSector] |
||
199 | adc edx, dword [ebp+PARTITION.FirstSector+4] |
||
200 | ; 3. If there is no cache for this disk, just pass request to the driver. |
||
201 | cmp [ecx+DISKCACHE.pointer], 0 |
||
202 | jnz .scancache |
||
203 | push 1 |
||
204 | push esp ; numsectors |
||
205 | push edx ; startsector |
||
206 | push eax ; startsector |
||
207 | push ebx ; buffer |
||
2987 | Serge | 208 | mov esi, [ebp+PARTITION.Disk] |
2142 | serge | 209 | mov al, DISKFUNC.write |
210 | call disk_call_driver |
||
211 | pop ecx |
||
2987 | Serge | 212 | pop esi edx |
2142 | serge | 213 | pop ecx |
214 | ret |
||
215 | .scancache: |
||
216 | ; 4. Scan the cache. |
||
2987 | Serge | 217 | push edi ecx ; scan cache |
2142 | serge | 218 | push edx eax |
219 | virtual at esp |
||
220 | .sector_lo dd ? |
||
221 | .sector_hi dd ? |
||
222 | .cache dd ? |
||
223 | end virtual |
||
224 | ; The following code is inherited from hd_write. The differences are: |
||
225 | ; all code is protected by the cache lock; |
||
226 | ; sector is 64-bit, not 32-bit. |
||
227 | call mutex_lock |
||
228 | |||
229 | ; check if the cache already has the sector and overwrite it |
||
230 | mov eax, [.sector_lo] |
||
231 | mov edx, [.sector_hi] |
||
232 | mov esi, [ecx+DISKCACHE.pointer] |
||
233 | mov ecx, [ecx+DISKCACHE.sad_size] |
||
234 | add esi, 12 |
||
235 | |||
236 | mov edi, 1 |
||
237 | |||
238 | .hdwritecache: |
||
239 | cmp dword [esi+8], 0 ; if cache slot is empty |
||
240 | je .not_in_cache_write |
||
241 | |||
242 | cmp [esi], eax ; if the slot has the sector |
||
243 | jne .not_in_cache_write |
||
244 | cmp [esi+4], edx ; if the slot has the sector |
||
245 | je .yes_in_cache_write |
||
246 | |||
247 | .not_in_cache_write: |
||
248 | |||
249 | add esi, 12 |
||
250 | inc edi |
||
251 | dec ecx |
||
252 | jnz .hdwritecache |
||
253 | |||
254 | ; sector not found in cache |
||
255 | ; write the block to a new location |
||
256 | |||
257 | mov esi, [.cache] |
||
258 | call find_empty_slot64 ; ret in edi |
||
259 | test eax, eax |
||
260 | jne .hd_write_access_denied |
||
261 | |||
262 | mov ecx, [.cache] |
||
263 | lea eax, [edi*3] |
||
264 | mov esi, [ecx+DISKCACHE.pointer] |
||
265 | lea esi, [eax*4+esi] |
||
266 | |||
267 | mov eax, [.sector_lo] |
||
268 | mov edx, [.sector_hi] |
||
269 | mov [esi], eax ; sector number |
||
270 | mov [esi+4], edx ; sector number |
||
271 | |||
272 | .yes_in_cache_write: |
||
273 | |||
3232 | Serge | 274 | mov dword [esi+8], 2 ; write - differs from hd |
2142 | serge | 275 | |
276 | shl edi, 9 |
||
277 | mov ecx, [.cache] |
||
278 | add edi, [ecx+DISKCACHE.data] |
||
279 | |||
280 | mov esi, ebx |
||
281 | mov ecx, 512/4 |
||
3555 | Serge | 282 | rep movsd ; move data |
2142 | serge | 283 | xor eax, eax ; success |
284 | .hd_write_access_denied: |
||
285 | mov ecx, [.cache] |
||
286 | push eax |
||
287 | call mutex_unlock |
||
288 | pop eax |
||
289 | add esp, 12 |
||
290 | pop edi esi edx ecx |
||
291 | ret |
||
292 | |||
293 | ; This internal function is called from fs_read32_* and fs_write32_*. It is the |
||
294 | ; analogue of find_empty_slot for 64-bit sectors. |
||
295 | find_empty_slot64: |
||
296 | ;----------------------------------------------------------- |
||
297 | ; find empty or read slot, flush cache if next 12.5% is used by write |
||
298 | ; output : edi = cache slot |
||
299 | ;----------------------------------------------------------- |
||
300 | .search_again: |
||
301 | mov ecx, [esi+DISKCACHE.sad_size] |
||
302 | mov edi, [esi+DISKCACHE.search_start] |
||
303 | shr ecx, 3 |
||
304 | .search_for_empty: |
||
305 | inc edi |
||
306 | cmp edi, [esi+DISKCACHE.sad_size] |
||
307 | jbe .inside_cache |
||
308 | mov edi, 1 |
||
309 | .inside_cache: |
||
310 | lea eax, [edi*3] |
||
311 | shl eax, 2 |
||
312 | add eax, [esi+DISKCACHE.pointer] |
||
313 | cmp dword [eax+8], 2 |
||
314 | jb .found_slot ; it's empty or read |
||
315 | dec ecx |
||
316 | jnz .search_for_empty |
||
2987 | Serge | 317 | stdcall write_cache64, [ebp+PARTITION.Disk] ; no empty slots found, write all |
2142 | serge | 318 | test eax, eax |
319 | jne .found_slot_access_denied |
||
320 | jmp .search_again ; and start again |
||
321 | .found_slot: |
||
322 | mov [esi+DISKCACHE.search_start], edi |
||
323 | xor eax, eax ; success |
||
324 | .found_slot_access_denied: |
||
325 | ret |
||
326 | |||
327 | ; This function is intended to replace the old 'write_cache' function. |
||
2987 | Serge | 328 | proc write_cache64 uses ecx edx esi edi, disk:dword |
2142 | serge | 329 | locals |
3232 | Serge | 330 | cache_chain_started dd 0 |
2142 | serge | 331 | cache_chain_size dd ? |
332 | cache_chain_pos dd ? |
||
333 | cache_chain_ptr dd ? |
||
334 | endl |
||
3232 | Serge | 335 | saved_esi_pos = 16+12 ; size of local variables + size of registers before esi |
2142 | serge | 336 | ; If there is no cache for this disk, nothing to do. |
337 | cmp [esi+DISKCACHE.pointer], 0 |
||
338 | jz .flush |
||
339 | ;----------------------------------------------------------- |
||
340 | ; write all changed sectors to disk |
||
341 | ;----------------------------------------------------------- |
||
342 | |||
343 | ; write difference ( 2 ) from cache to DISK |
||
344 | mov ecx, [esi+DISKCACHE.sad_size] |
||
345 | mov esi, [esi+DISKCACHE.pointer] |
||
346 | add esi, 12 |
||
347 | mov edi, 1 |
||
348 | .write_cache_more: |
||
349 | cmp dword [esi+8], 2 ; if cache slot is not different |
||
350 | jne .write_chain |
||
351 | mov dword [esi+8], 1 ; same as in hd |
||
352 | mov eax, [esi] |
||
353 | mov edx, [esi+4] ; edx:eax = sector to write |
||
3555 | Serge | 354 | ; Объединяем запись цепочки последовательных секторов в одно обращение к диску |
2142 | serge | 355 | cmp ecx, 1 |
356 | jz .nonext |
||
357 | cmp dword [esi+12+8], 2 |
||
358 | jnz .nonext |
||
359 | push eax edx |
||
360 | add eax, 1 |
||
361 | adc edx, 0 |
||
362 | cmp eax, [esi+12] |
||
363 | jnz @f |
||
364 | cmp edx, [esi+12+4] |
||
365 | @@: |
||
366 | pop edx eax |
||
367 | jnz .nonext |
||
368 | cmp [cache_chain_started], 1 |
||
369 | jz @f |
||
370 | mov [cache_chain_started], 1 |
||
371 | mov [cache_chain_size], 0 |
||
372 | mov [cache_chain_pos], edi |
||
373 | mov [cache_chain_ptr], esi |
||
374 | @@: |
||
375 | inc [cache_chain_size] |
||
376 | cmp [cache_chain_size], 16 |
||
377 | jnz .continue |
||
378 | jmp .write_chain |
||
379 | .nonext: |
||
380 | call .flush_cache_chain |
||
381 | test eax, eax |
||
382 | jnz .nothing |
||
383 | mov [cache_chain_size], 1 |
||
384 | mov [cache_chain_ptr], esi |
||
385 | call .write_cache_sector |
||
386 | test eax, eax |
||
387 | jnz .nothing |
||
388 | jmp .continue |
||
389 | .write_chain: |
||
390 | call .flush_cache_chain |
||
391 | test eax, eax |
||
392 | jnz .nothing |
||
393 | .continue: |
||
394 | add esi, 12 |
||
395 | inc edi |
||
396 | dec ecx |
||
397 | jnz .write_cache_more |
||
398 | call .flush_cache_chain |
||
399 | test eax, eax |
||
400 | jnz .nothing |
||
401 | .flush: |
||
2987 | Serge | 402 | mov esi, [disk] |
2142 | serge | 403 | mov al, DISKFUNC.flush |
404 | call disk_call_driver |
||
405 | .nothing: |
||
406 | ret |
||
407 | |||
408 | .flush_cache_chain: |
||
409 | xor eax, eax |
||
410 | cmp [cache_chain_started], eax |
||
411 | jz @f |
||
412 | call .write_cache_chain |
||
413 | mov [cache_chain_started], 0 |
||
414 | @@: |
||
415 | retn |
||
416 | |||
417 | .write_cache_sector: |
||
418 | mov [cache_chain_size], 1 |
||
419 | mov [cache_chain_pos], edi |
||
420 | .write_cache_chain: |
||
421 | pusha |
||
422 | mov edi, [cache_chain_pos] |
||
3232 | Serge | 423 | mov ecx, [ebp-saved_esi_pos] |
2142 | serge | 424 | shl edi, 9 |
425 | add edi, [ecx+DISKCACHE.data] |
||
426 | mov ecx, [cache_chain_size] |
||
427 | push ecx |
||
428 | push esp ; numsectors |
||
429 | mov eax, [cache_chain_ptr] |
||
430 | pushd [eax+4] |
||
431 | pushd [eax] ; startsector |
||
432 | push edi ; buffer |
||
433 | mov esi, [ebp] |
||
434 | mov esi, [esi+PARTITION.Disk] |
||
435 | mov al, DISKFUNC.write |
||
436 | call disk_call_driver |
||
437 | pop ecx |
||
438 | mov [esp+28], eax |
||
439 | popa |
||
440 | retn |
||
441 | endp |
||
442 | |||
443 | ; This internal function is called from disk_add to initialize the caching for |
||
444 | ; a new DISK. |
||
445 | ; The algorithm is inherited from getcache.inc: take 1/32 part of the available |
||
446 | ; physical memory, round down to 8 pages, limit by 128K from below and by 1M |
||
447 | ; from above. Reserve 1/8 part of the cache for system data and 7/8 for app |
||
448 | ; data. |
||
449 | ; After the size is calculated, but before the cache is allocated, the device |
||
450 | ; driver can adjust the size. In particular, setting size to zero disables |
||
451 | ; caching: there is no sense in a cache for a ramdisk. In fact, such action |
||
452 | ; is most useful example of a non-trivial adjustment. |
||
453 | ; esi = pointer to DISK structure |
||
454 | disk_init_cache: |
||
455 | ; 1. Calculate the suggested cache size. |
||
456 | ; 1a. Get the size of free physical memory in pages. |
||
457 | mov eax, [pg_data.pages_free] |
||
458 | ; 1b. Use the value to calculate the size. |
||
459 | shl eax, 12 - 5 ; 1/32 of it in bytes |
||
460 | and eax, -8*4096 ; round down to the multiple of 8 pages |
||
461 | ; 1c. Force lower and upper limits. |
||
462 | cmp eax, 1024*1024 |
||
463 | jb @f |
||
464 | mov eax, 1024*1024 |
||
465 | @@: |
||
466 | cmp eax, 128*1024 |
||
467 | ja @f |
||
468 | mov eax, 128*1024 |
||
469 | @@: |
||
470 | ; 1d. Give a chance to the driver to adjust the size. |
||
471 | push eax |
||
472 | mov al, DISKFUNC.adjust_cache_size |
||
473 | call disk_call_driver |
||
474 | ; Cache size calculated. |
||
475 | mov [esi+DISK.cache_size], eax |
||
476 | test eax, eax |
||
477 | jz .nocache |
||
478 | ; 2. Allocate memory for the cache. |
||
479 | ; 2a. Call the allocator. |
||
480 | stdcall kernel_alloc, eax |
||
481 | test eax, eax |
||
482 | jnz @f |
||
483 | ; 2b. If it failed, say a message and return with eax = 0. |
||
484 | dbgstr 'no memory for disk cache' |
||
485 | jmp .nothing |
||
486 | @@: |
||
487 | ; 3. Fill two DISKCACHE structures. |
||
488 | mov [esi+DISK.SysCache.pointer], eax |
||
2434 | Serge | 489 | lea ecx, [esi+DISK.SysCache.mutex] |
2142 | serge | 490 | call mutex_init |
2434 | Serge | 491 | lea ecx, [esi+DISK.AppCache.mutex] |
2142 | serge | 492 | call mutex_init |
493 | ; The following code is inherited from getcache.inc. |
||
494 | mov edx, [esi+DISK.SysCache.pointer] |
||
495 | and [esi+DISK.SysCache.search_start], 0 |
||
496 | and [esi+DISK.AppCache.search_start], 0 |
||
497 | mov eax, [esi+DISK.cache_size] |
||
498 | shr eax, 3 |
||
499 | mov [esi+DISK.SysCache.data_size], eax |
||
500 | add edx, eax |
||
501 | imul eax, 7 |
||
502 | mov [esi+DISK.AppCache.data_size], eax |
||
503 | mov [esi+DISK.AppCache.pointer], edx |
||
504 | |||
505 | mov eax, [esi+DISK.SysCache.data_size] |
||
506 | push ebx |
||
3232 | Serge | 507 | call calculate_for_hd64 |
2142 | serge | 508 | pop ebx |
509 | add eax, [esi+DISK.SysCache.pointer] |
||
510 | mov [esi+DISK.SysCache.data], eax |
||
511 | mov [esi+DISK.SysCache.sad_size], ecx |
||
512 | |||
513 | push edi |
||
514 | mov edi, [esi+DISK.SysCache.pointer] |
||
515 | lea ecx, [ecx*3] |
||
516 | xor eax, eax |
||
3555 | Serge | 517 | rep stosd |
2142 | serge | 518 | pop edi |
519 | |||
520 | mov eax, [esi+DISK.AppCache.data_size] |
||
521 | push ebx |
||
3232 | Serge | 522 | call calculate_for_hd64 |
2142 | serge | 523 | pop ebx |
524 | add eax, [esi+DISK.AppCache.pointer] |
||
525 | mov [esi+DISK.AppCache.data], eax |
||
526 | mov [esi+DISK.AppCache.sad_size], ecx |
||
527 | |||
528 | push edi |
||
529 | mov edi, [esi+DISK.AppCache.pointer] |
||
530 | lea ecx, [ecx*3] |
||
531 | xor eax, eax |
||
3555 | Serge | 532 | rep stosd |
2142 | serge | 533 | pop edi |
534 | |||
535 | ; 4. Return with nonzero al. |
||
536 | mov al, 1 |
||
537 | ; 5. Return. |
||
538 | .nothing: |
||
539 | ret |
||
540 | ; No caching is required for this driver. Zero cache pointers and return with |
||
541 | ; nonzero al. |
||
542 | .nocache: |
||
543 | mov [esi+DISK.SysCache.pointer], eax |
||
544 | mov [esi+DISK.AppCache.pointer], eax |
||
545 | mov al, 1 |
||
546 | ret |
||
547 | |||
3232 | Serge | 548 | calculate_for_hd64: |
549 | push eax |
||
550 | mov ebx, eax |
||
551 | shr eax, 9 |
||
552 | lea eax, [eax*3] |
||
553 | shl eax, 2 |
||
554 | sub ebx, eax |
||
555 | shr ebx, 9 |
||
556 | mov ecx, ebx |
||
557 | shl ebx, 9 |
||
558 | pop eax |
||
559 | sub eax, ebx |
||
560 | dec ecx |
||
561 | ret |
||
562 | |||
563 | |||
2142 | serge | 564 | ; This internal function is called from disk_media_dereference to free the |
565 | ; allocated cache, if there is one. |
||
566 | ; esi = pointer to DISK structure |
||
567 | disk_free_cache: |
||
568 | ; The algorithm is straightforward. |
||
569 | mov eax, [esi+DISK.SysCache.pointer] |
||
570 | test eax, eax |
||
571 | jz .nothing |
||
572 | stdcall kernel_free, eax |
||
573 | .nothing: |
||
574 | ret |
||
2987 | Serge | 575 | |
576 | ; This function flushes all modified data from both caches for the given DISK. |
||
577 | ; esi = pointer to DISK |
||
578 | disk_sync: |
||
579 | ; The algorithm is straightforward. |
||
580 | push esi |
||
581 | push esi ; for second write_cache64 |
||
582 | push esi ; for first write_cache64 |
||
583 | add esi, DISK.SysCache |
||
584 | call write_cache64 |
||
585 | add esi, DISK.AppCache - DISK.SysCache |
||
586 | call write_cache64 |
||
587 | pop esi |
||
588 | ret |