Subversion Repositories Kolibri OS

Rev

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