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