Subversion Repositories Kolibri OS

Rev

Rev 4465 | Rev 5095 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4465 Rev 5089
Line 3... Line 3...
3
;; Copyright (C) KolibriOS team 2011-2014. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2011-2014. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line 7... Line 7...
7
 
7
 
Line 8... Line 8...
8
$Revision: 4465 $
8
$Revision: 5089 $
9
 
9
 
10
; Read/write functions try to do large operations,
10
; Read/write functions try to do large operations,
11
; it is significantly faster than several small operations.
11
; it is significantly faster than several small operations.
Line 116... Line 116...
116
        mov     eax, dword [ebp+PARTITION.FirstSector]
116
        mov     eax, dword [ebp+PARTITION.FirstSector]
117
        mov     edx, dword [ebp+PARTITION.FirstSector+4]
117
        mov     edx, dword [ebp+PARTITION.FirstSector+4]
118
        add     [.sector_lo], eax
118
        add     [.sector_lo], eax
119
        adc     [.sector_hi], edx
119
        adc     [.sector_hi], edx
120
; 5. If the cache is disabled, pass the request directly to the driver.
120
; 5. If the cache is disabled, pass the request directly to the driver.
121
        mov     edi, [.buffer]
-
 
122
        cmp     [ebx+DISKCACHE.pointer], 0
121
        cmp     [ebx+DISKCACHE.pointer], 0
123
        jz      .nocache
122
        jz      .nocache
124
; 6. Look for sectors in the cache, sequentially from the beginning.
123
; 6. Look for sectors in the cache, sequentially from the beginning.
125
; Stop at the first sector that is not in the cache
124
; Stop at the first sector that is not in the cache
126
; or when all sectors were read from the cache.
125
; or when all sectors were read from the cache.
Line 135... Line 134...
135
        call    cache_lookup_read
134
        call    cache_lookup_read
136
; 6c. If it has failed, the sector is not in cache;
135
; 6c. If it has failed, the sector is not in cache;
137
; release the lock and go to 7.
136
; release the lock and go to 7.
138
        jc      .not_found_in_cache
137
        jc      .not_found_in_cache
139
; The sector is found in cache.
138
; The sector is found in cache.
140
; 6d. Copy data for the caller.
139
; 6d. Copy data for the caller, advance [.buffer].
-
 
140
        mov     esi, edi
141
; Note that buffer in edi is advanced automatically.
141
        mov     edi, [.buffer]
142
        mov     esi, ecx
142
        mov     eax, 1
143
        shl     esi, 9
143
        shl     eax, cl
144
        add     esi, [ebx+DISKCACHE.data]
144
        mov     ecx, eax
145
        mov     ecx, 512/4
145
        shr     ecx, 2
146
        rep movsd
146
        rep movsd
-
 
147
        mov     [.buffer], edi
147
; 6e. Advance the sector.
148
; 6e. Advance the sector.
148
        add     [.sector_lo], 1
149
        add     [.sector_lo], 1
149
        adc     [.sector_hi], 0
150
        adc     [.sector_hi], 0
150
; 6f. Decrement number of sectors left.
151
; 6f. Decrement number of sectors left.
151
; If all sectors were read, release the lock and return.
152
; If all sectors were read, release the lock and return.
Line 175... Line 176...
175
; 7. Allocate buffer for operations.
176
; 7. Allocate buffer for operations.
176
; Normally, create buffer that is sufficient for all remaining data.
177
; Normally, create buffer that is sufficient for all remaining data.
177
; However, for extra-large requests make an upper limit:
178
; However, for extra-large requests make an upper limit:
178
; do not use more than half of the free memory
179
; do not use more than half of the free memory
179
; or more than CACHE_MAX_ALLOC_SIZE bytes.
180
; or more than CACHE_MAX_ALLOC_SIZE bytes.
-
 
181
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
180
        mov     ebx, [pg_data.pages_free]
182
        mov     ebx, [pg_data.pages_free]
181
        shr     ebx, 1
183
        shr     ebx, 1
182
        jz      .nomemory
184
        jz      .nomemory
183
        cmp     ebx, CACHE_MAX_ALLOC_SIZE shr 12
185
        cmp     ebx, CACHE_MAX_ALLOC_SIZE shr 12
184
        jbe     @f
186
        jbe     @f
185
        mov     ebx, CACHE_MAX_ALLOC_SIZE shr 12
187
        mov     ebx, CACHE_MAX_ALLOC_SIZE shr 12
186
@@:
188
@@:
187
        shl     ebx, 12 - 9
189
        shl     ebx, 12
-
 
190
        shr     ebx, cl
-
 
191
        jz      .nomemory
188
        cmp     ebx, [.num_sectors]
192
        cmp     ebx, [.num_sectors]
189
        jbe     @f
193
        jbe     @f
190
        mov     ebx, [.num_sectors]
194
        mov     ebx, [.num_sectors]
191
@@:
195
@@:
192
        mov     eax, ebx
196
        mov     eax, ebx
193
        shl     eax, 9
197
        shl     eax, cl
194
        stdcall kernel_alloc, eax
198
        stdcall kernel_alloc, eax
195
; If failed, return the appropriate error code.
199
; If failed, return the appropriate error code.
196
        test    eax, eax
200
        test    eax, eax
197
        jz      .nomemory
201
        jz      .nomemory
198
        mov     esi, eax
202
        mov     esi, eax
Line 231... Line 235...
231
; If failed, save error code.
235
; If failed, save error code.
232
        test    eax, eax
236
        test    eax, eax
233
        jz      @f
237
        jz      @f
234
        mov     [.error_code+.local_vars2_size], eax
238
        mov     [.error_code+.local_vars2_size], eax
235
@@:
239
@@:
236
; 11. Copy data for the caller.
240
; 11. Copy data for the caller, advance .buffer.
237
; Note that buffer in edi is advanced automatically.
-
 
238
        cmp     [.current_num_sectors], 0
241
        cmp     [.current_num_sectors], 0
239
        jz      .copy_done
242
        jz      .copy_done
-
 
243
        mov     ebx, [.cache+.local_vars2_size]
240
        mov     ecx, [.current_num_sectors]
244
        mov     eax, [.current_num_sectors]
-
 
245
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
241
        shl     ecx, 9-2
246
        shl     eax, cl
242
        mov     esi, [.allocated_buffer]
247
        mov     esi, [.allocated_buffer]
-
 
248
        mov     edi, [.buffer+.local_vars2_size]
-
 
249
        mov     ecx, eax
-
 
250
        shr     ecx, 2
243
        rep movsd
251
        rep movsd
-
 
252
        mov     [.buffer+.local_vars2_size], edi
244
; 12. Copy data to the cache.
253
; 12. Copy data to the cache.
245
; 12a. Acquire the lock.
254
; 12a. Acquire the lock.
246
        mov     ebx, [.cache+.local_vars2_size]
-
 
247
        mov     ecx, [ebp+PARTITION.Disk]
255
        mov     ecx, [ebp+PARTITION.Disk]
248
        add     ecx, DISK.CacheLock
256
        add     ecx, DISK.CacheLock
249
        call    mutex_lock
257
        call    mutex_lock
250
; 12b. Prepare for the loop: save edi and create a local variable that
258
; 12b. Prepare for the loop: create a local variable that
251
; stores number of sectors to be copied.
259
; stores number of sectors to be copied.
252
        push    edi
-
 
253
        push    [.current_num_sectors+4]
260
        push    [.current_num_sectors]
254
.store_to_cache:
261
.store_to_cache:
255
; 12c. For each sector, call the lookup function with adding to the cache, if not yet.
262
; 12c. For each sector, call the lookup function with adding to the cache, if not yet.
256
        mov     eax, [.sector_lo+.local_vars2_size+8]
263
        mov     eax, [.sector_lo+.local_vars2_size+4]
257
        mov     edx, [.sector_hi+.local_vars2_size+8]
264
        mov     edx, [.sector_hi+.local_vars2_size+4]
258
        call    cache_lookup_write
265
        call    cache_lookup_write
259
        test    eax, eax
266
        test    eax, eax
260
        jnz     .cache_error
267
        jnz     .cache_error
261
; 12d. If the sector was already present in the cache as modified,
268
; 12d. If the sector was already present in the cache as modified,
262
; data that were read at step 10 for this sector are obsolete,
269
; data that were read at step 10 for this sector are obsolete,
263
; so rewrite data for the caller from the cache.
270
; so rewrite data for the caller from the cache.
264
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
271
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
265
        jnz     .not_modified
272
        jnz     .not_modified
266
        mov     esi, ecx
273
        mov     esi, edi
-
 
274
        mov     edi, [.buffer+.local_vars2_size+4]
267
        shl     esi, 9
275
        mov     eax, [esp]
268
        add     esi, [ebx+DISKCACHE.data]
276
        shl     eax, cl
269
        mov     edi, [esp+4]
277
        sub     edi, eax
270
        mov     ecx, [esp]
278
        mov     eax, 1
271
        shl     ecx, 9-2
279
        shl     eax, cl
272
        sub     edi, ecx
280
        mov     ecx, eax
273
        mov     ecx, 512/4
281
        shr     ecx, 2
274
        rep movsd
282
        rep movsd
275
        add     [.current_buffer+8], 512
283
        add     [.current_buffer+4], eax
276
        jmp     .sector_done
284
        jmp     .sector_done
277
.not_modified:
285
.not_modified:
278
; 12e. For each not-modified sector,
286
; 12e. For each not-modified sector,
279
; copy data, mark the item as not-modified copy of the disk,
287
; copy data, mark the item as not-modified copy of the disk,
280
; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
288
; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
281
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
289
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
282
        mov     esi, [.current_buffer+8]
290
        mov     eax, 1
283
        mov     edi, ecx
291
        shl     eax, cl
284
        shl     edi, 9
292
        mov     esi, [.current_buffer+4]
285
        add     edi, [ebx+DISKCACHE.data]
293
        mov     ecx, eax
286
        mov     ecx, 512/4
294
        shr     ecx, 2
287
        rep movsd
295
        rep movsd
288
        mov     [.current_buffer+8], esi
296
        mov     [.current_buffer+4], esi
289
.sector_done:
297
.sector_done:
290
        add     [.sector_lo+.local_vars2_size+8], 1
298
        add     [.sector_lo+.local_vars2_size+4], 1
291
        adc     [.sector_hi+.local_vars2_size+8], 0
299
        adc     [.sector_hi+.local_vars2_size+4], 0
292
; 12f. Continue the loop 12c-12e until all sectors are read.
300
; 12f. Continue the loop 12c-12e until all sectors are read.
293
        dec     dword [esp]
301
        dec     dword [esp]
294
        jnz     .store_to_cache
302
        jnz     .store_to_cache
295
.cache_error:
303
.cache_error:
296
; 12g. Restore after the loop: pop the local variable and restore edi.
304
; 12g. Restore after the loop: pop the local variable.
297
        pop     ecx
305
        pop     ecx
298
        pop     edi
-
 
299
; 12h. Release the lock.
306
; 12h. Release the lock.
300
        mov     ecx, [ebp+PARTITION.Disk]
307
        mov     ecx, [ebp+PARTITION.Disk]
301
        add     ecx, DISK.CacheLock
308
        add     ecx, DISK.CacheLock
302
        call    mutex_unlock
309
        call    mutex_unlock
303
.copy_done:
310
.copy_done:
Line 326... Line 333...
326
; sees that cache is disabled: pass corrected request to the driver
333
; sees that cache is disabled: pass corrected request to the driver
327
        lea     eax, [.num_sectors]
334
        lea     eax, [.num_sectors]
328
        push    eax             ; numsectors
335
        push    eax             ; numsectors
329
        push    [.sector_hi+4]  ; startsector
336
        push    [.sector_hi+4]  ; startsector
330
        push    [.sector_lo+8]  ; startsector
337
        push    [.sector_lo+8]  ; startsector
331
        push    edi     ; buffer
338
        push    [.buffer+12]    ; buffer
332
        mov     esi, [ebp+PARTITION.Disk]
339
        mov     esi, [ebp+PARTITION.Disk]
333
        mov     al, DISKFUNC.read
340
        mov     al, DISKFUNC.read
334
        call    disk_call_driver
341
        call    disk_call_driver
335
        test    eax, eax
342
        test    eax, eax
336
        jnz     @f
343
        jnz     @f
Line 438... Line 445...
438
        test    eax, eax
445
        test    eax, eax
439
        jnz     .cache_error
446
        jnz     .cache_error
440
; 6c. For each sector, copy data, mark the item as modified and not saved,
447
; 6c. For each sector, copy data, mark the item as modified and not saved,
441
; advance .current_buffer to the next sector.
448
; advance .current_buffer to the next sector.
442
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
449
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
-
 
450
        mov     eax, 1
-
 
451
        shl     eax, cl
443
        mov     esi, [.cur_buffer]
452
        mov     esi, [.cur_buffer]
444
        mov     edi, ecx
453
        mov     ecx, eax
445
        shl     edi, 9
454
        shr     ecx, 2
446
        add     edi, [ebx+DISKCACHE.data]
-
 
447
        mov     ecx, 512/4
-
 
448
        rep movsd
455
        rep movsd
449
        mov     [.cur_buffer], esi
456
        mov     [.cur_buffer], esi
450
; 6d. Remove the sector from the other cache.
457
; 6d. Remove the sector from the other cache.
451
; Normally it should not be there, but prefetching could put to the app cache
458
; Normally it should not be there, but prefetching could put to the app cache
452
; data that normally should belong to the sys cache and vice versa.
459
; data that normally should belong to the sys cache and vice versa.
Line 590... Line 597...
590
        call    cache_lookup_read
597
        call    cache_lookup_read
591
; If not found, go to 5.
598
; If not found, go to 5.
592
        jc      .not_found_in_cache
599
        jc      .not_found_in_cache
593
.found_in_cache:
600
.found_in_cache:
594
; 4c. Copy the data.
601
; 4c. Copy the data.
-
 
602
        mov     esi, edi
595
        mov     edi, [.buffer]
603
        mov     edi, [.buffer]
596
        mov     esi, ecx
604
        mov     eax, 1
597
        shl     esi, 9
605
        shl     eax, cl
598
        add     esi, [ebx+DISKCACHE.data]
606
        mov     ecx, eax
599
        mov     ecx, 512/4
607
        shr     ecx, 2
600
        rep movsd
608
        rep movsd
601
; 4d. Release the lock and return success.
609
; 4d. Release the lock and return success.
602
        mov     ecx, [ebp+PARTITION.Disk]
610
        mov     ecx, [ebp+PARTITION.Disk]
603
        add     ecx, DISK.CacheLock
611
        add     ecx, DISK.CacheLock
604
        call    mutex_unlock
612
        call    mutex_unlock
Line 625... Line 633...
625
; 6. Release the lock acquired at step 4a.
633
; 6. Release the lock acquired at step 4a.
626
        mov     ecx, [ebp+PARTITION.Disk]
634
        mov     ecx, [ebp+PARTITION.Disk]
627
        add     ecx, DISK.CacheLock
635
        add     ecx, DISK.CacheLock
628
        call    mutex_unlock
636
        call    mutex_unlock
629
; 7. Allocate buffer for CACHE_LEGACY_READ_SIZE sectors.
637
; 7. Allocate buffer for CACHE_LEGACY_READ_SIZE sectors.
630
        stdcall kernel_alloc, CACHE_LEGACY_READ_SIZE shl 9
638
        mov     eax, CACHE_LEGACY_READ_SIZE
-
 
639
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
-
 
640
        shl     eax, cl
-
 
641
        stdcall kernel_alloc, eax
631
; If failed, return the corresponding error code.
642
; If failed, return the corresponding error code.
632
        test    eax, eax
643
        test    eax, eax
633
        jz      .nomemory
644
        jz      .nomemory
634
; 8. Create second portion of local variables.
645
; 8. Create second portion of local variables.
635
        push    eax eax
646
        push    eax eax
Line 654... Line 665...
654
        cmp     [.num_sectors], 0
665
        cmp     [.num_sectors], 0
655
        jz      .read_error
666
        jz      .read_error
656
; 10. Copy data for the caller.
667
; 10. Copy data for the caller.
657
        mov     esi, [.allocated_buffer]
668
        mov     esi, [.allocated_buffer]
658
        mov     edi, [.buffer+.local_vars2_size]
669
        mov     edi, [.buffer+.local_vars2_size]
-
 
670
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
-
 
671
        mov     eax, 1
-
 
672
        shl     eax, cl
659
        mov     ecx, 512/4
673
        mov     ecx, eax
-
 
674
        shr     ecx, 2
660
        rep movsd
675
        rep movsd
661
; 11. Store all sectors that were successfully read to the cache.
676
; 11. Store all sectors that were successfully read to the cache.
662
; 11a. Acquire the lock.
677
; 11a. Acquire the lock.
663
        mov     ecx, [ebp+PARTITION.Disk]
678
        mov     ecx, [ebp+PARTITION.Disk]
664
        add     ecx, DISK.CacheLock
679
        add     ecx, DISK.CacheLock
Line 669... Line 684...
669
        mov     edx, [.sector_hi+.local_vars2_size]
684
        mov     edx, [.sector_hi+.local_vars2_size]
670
        call    cache_lookup_write
685
        call    cache_lookup_write
671
        test    eax, eax
686
        test    eax, eax
672
        jnz     .cache_error
687
        jnz     .cache_error
673
; 11c. Ignore sectors marked as modified: for them the cache is more recent that disk data.
688
; 11c. Ignore sectors marked as modified: for them the cache is more recent that disk data.
-
 
689
        mov     eax, 1
-
 
690
        shl     eax, cl
674
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
691
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
675
        jnz     .not_modified
692
        jnz     .not_modified
676
        add     [.current_buffer], 512
693
        add     [.current_buffer], eax
677
        jmp     .sector_done
694
        jmp     .sector_done
678
.not_modified:
695
.not_modified:
679
; 11d. For each sector, copy data, mark the item as not-modified copy of the disk,
696
; 11d. For each sector, copy data, mark the item as not-modified copy of the disk,
680
; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
697
; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
681
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
698
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
682
        mov     esi, [.current_buffer]
699
        mov     esi, [.current_buffer]
683
        mov     edi, ecx
700
        mov     ecx, eax
684
        shl     edi, 9
701
        shr     ecx, 2
685
        add     edi, [ebx+DISKCACHE.data]
-
 
686
        mov     ecx, 512/4
-
 
687
        rep movsd
702
        rep movsd
688
        mov     [.current_buffer], esi
703
        mov     [.current_buffer], esi
689
.sector_done:
704
.sector_done:
690
        add     [.sector_lo+.local_vars2_size], 1
705
        add     [.sector_lo+.local_vars2_size], 1
691
        adc     [.sector_hi+.local_vars2_size], 0
706
        adc     [.sector_hi+.local_vars2_size], 0
Line 719... Line 734...
719
; We are still holding the lock acquired at step 4a.
734
; We are still holding the lock acquired at step 4a.
720
; 13. Call the lookup function adding sector to the cache.
735
; 13. Call the lookup function adding sector to the cache.
721
        call    cache_lookup_write
736
        call    cache_lookup_write
722
        test    eax, eax
737
        test    eax, eax
723
        jnz     .floppy_cache_error
738
        jnz     .floppy_cache_error
724
        push    ecx
739
        push    esi
Line 725... Line 740...
725
 
740
 
726
; 14. Call the driver to read one sector.
741
; 14. Call the driver to read one sector.
727
        push    1
742
        push    1
728
        push    esp
743
        push    esp
729
        push    edx
744
        push    edx
730
        push    [.sector_lo+16]
-
 
731
        shl     ecx, 9
-
 
732
        add     ecx, [ebx+DISKCACHE.data]
745
        push    [.sector_lo+16]
733
        push    ecx
746
        push    edi
734
        mov     esi, [ebp+PARTITION.Disk]
747
        mov     esi, [ebp+PARTITION.Disk]
735
        mov     al, DISKFUNC.read
748
        mov     al, DISKFUNC.read
736
        call    disk_call_driver
749
        call    disk_call_driver
737
        pop     ecx
750
        pop     ecx
738
        dec     ecx
751
        dec     ecx
739
        jnz     .floppy_read_error
752
        jnz     .floppy_read_error
740
; 15. Get the slot and pointer to the cache item,
753
; 15. Get the slot and pointer to the cache item,
741
; change the status to not-modified copy of the disk
754
; change the status to not-modified copy of the disk
742
; and go to 4c.
755
; and go to 4c.
743
        pop     ecx
-
 
744
        lea     esi, [ecx*sizeof.CACHE_ITEM/4]
-
 
745
        shl     esi, 2
-
 
746
        add     esi, [ebx+DISKCACHE.pointer]
756
        pop     esi
747
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
757
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
Line 748... Line 758...
748
        jmp     .found_in_cache
758
        jmp     .found_in_cache
749
 
759
 
Line 793... Line 803...
793
; If the sector is not present, return error.
803
; If the sector is not present, return error.
794
; The caller must acquire the cache lock.
804
; The caller must acquire the cache lock.
795
; in: edx:eax = sector
805
; in: edx:eax = sector
796
; in: ebx -> DISKCACHE structure
806
; in: ebx -> DISKCACHE structure
797
; out: CF set if sector is not in cache
807
; out: CF set if sector is not in cache
798
; out: ecx = index in cache
808
; out: ecx = sector_size_log
799
; out: esi -> sector:status
809
; out: esi -> sector:status
-
 
810
; out: edi -> sector data
800
proc cache_lookup_read
811
proc cache_lookup_read
801
        mov     esi, [ebx+DISKCACHE.pointer]
812
        mov     esi, [ebx+DISKCACHE.pointer]
802
        add     esi, sizeof.CACHE_ITEM
813
        add     esi, sizeof.CACHE_ITEM
Line 803... Line 814...
803
 
814
 
Line 804... Line 815...
804
        mov     ecx, 1
815
        mov     edi, 1
Line 805... Line 816...
805
 
816
 
806
.hdreadcache:
817
.hdreadcache:
Line 807... Line 818...
807
 
818
 
808
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
819
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
809
        je      .nohdcache
820
        je      .nohdcache
810
 
821
 
-
 
822
        cmp     [esi+CACHE_ITEM.SectorLo], eax
-
 
823
        jne     .nohdcache
-
 
824
        cmp     [esi+CACHE_ITEM.SectorHi], edx
811
        cmp     [esi+CACHE_ITEM.SectorLo], eax
825
        jne     .nohdcache
812
        jne     .nohdcache
826
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
Line 813... Line 827...
813
        cmp     [esi+CACHE_ITEM.SectorHi], edx
827
        shl     edi, cl
Line 814... Line 828...
814
        jne     .nohdcache
828
        add     edi, [ebx+DISKCACHE.data]
815
        clc
829
        clc
816
        ret
830
        ret
817
 
831
 
818
.nohdcache:
832
.nohdcache:
819
 
833
 
820
        add     esi, sizeof.CACHE_ITEM
834
        add     esi, sizeof.CACHE_ITEM
Line 830... Line 844...
830
; possibly flushing data.
844
; possibly flushing data.
831
; in: edx:eax = sector
845
; in: edx:eax = sector
832
; in: ebx -> DISKCACHE structure
846
; in: ebx -> DISKCACHE structure
833
; in: ebp -> PARTITION structure
847
; in: ebp -> PARTITION structure
834
; out: eax = error code
848
; out: eax = error code
835
; out: ecx = index in cache
-
 
836
; out: esi -> sector:status
849
; out: esi -> sector:status
-
 
850
; out: edi -> sector data
837
proc cache_lookup_write
851
proc cache_lookup_write
838
        call    cache_lookup_read
852
        call    cache_lookup_read
839
        jnc     .return0
853
        jnc     .return0
840
        push    edx eax
854
        push    edx eax
841
;-----------------------------------------------------------
855
;-----------------------------------------------------------
Line 872... Line 886...
872
.found_slot:
886
.found_slot:
873
        mov     [ebx+DISKCACHE.search_start], ecx
887
        mov     [ebx+DISKCACHE.search_start], ecx
874
        popd    [esi+CACHE_ITEM.SectorLo]
888
        popd    [esi+CACHE_ITEM.SectorLo]
875
        popd    [esi+CACHE_ITEM.SectorHi]
889
        popd    [esi+CACHE_ITEM.SectorHi]
876
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
890
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
-
 
891
        mov     edi, ecx
-
 
892
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
-
 
893
        shl     edi, cl
-
 
894
        add     edi, [ebx+DISKCACHE.data]
877
.return0:
895
.return0:
878
        xor     eax, eax        ; success
896
        xor     eax, eax        ; success
879
        ret
897
        ret
880
.found_slot_access_denied:
898
.found_slot_access_denied:
881
        add     esp, 8
899
        add     esp, 8
Line 900... Line 918...
900
; one chain describes a sequential interval of sectors,
918
; one chain describes a sequential interval of sectors,
901
; they can be sequential or scattered in the cache.
919
; they can be sequential or scattered in the cache.
902
.sequential     dd      ?
920
.sequential     dd      ?
903
; boolean variable, 1 if the current chain is sequential in the cache,
921
; boolean variable, 1 if the current chain is sequential in the cache,
904
; 0 if additional buffer is needed to perform the operation
922
; 0 if additional buffer is needed to perform the operation
905
.chain_start_pos dd     ?       ; slot of chain start item
923
.chain_start_pos dd     ?       ; data of chain start item
906
.chain_start_ptr dd     ?       ; pointer to chain start item
924
.chain_start_ptr dd     ?       ; pointer to chain start item
907
.chain_size     dd      ?       ; chain size (thanks, C.O.)
925
.chain_size     dd      ?       ; chain size (thanks, C.O.)
908
.iteration_size dd      ?
926
.iteration_size dd      ?
909
; If the chain size is too large, split the operation to several iterations.
927
; If the chain size is too large, split the operation to several iterations.
910
; This is size in sectors for one iterations.
928
; This is size in sectors for one iterations.
Line 949... Line 967...
949
; Initialize chain as sequential zero-length starting at the current item.
967
; Initialize chain as sequential zero-length starting at the current item.
950
        mov     [.chain_start_ptr], esi
968
        mov     [.chain_start_ptr], esi
951
        mov     eax, [ebx+DISKCACHE.sad_size]
969
        mov     eax, [ebx+DISKCACHE.sad_size]
952
        sub     eax, [.size_left]
970
        sub     eax, [.size_left]
953
        inc     eax
971
        inc     eax
-
 
972
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
-
 
973
        shl     eax, cl
-
 
974
        add     eax, [ebx+DISKCACHE.data]
954
        mov     [.chain_start_pos], eax
975
        mov     [.chain_start_pos], eax
955
        mov     [.chain_size], 0
976
        mov     [.chain_size], 0
956
        mov     [.sequential], 1
977
        mov     [.sequential], 1
957
; 6. Expand the chain backward.
978
; 6. Expand the chain backward.
958
; Note: the main loop in step 2 looks for items sequentially,
979
; Note: the main loop in step 2 looks for items sequentially,
Line 976... Line 997...
976
; It makes the chain non-sequential.
997
; It makes the chain non-sequential.
977
; Normally, sectors come in sequential blocks, so try to look at previous items
998
; Normally, sectors come in sequential blocks, so try to look at previous items
978
; before returning to 6b; if there is a sequential block indeed, this saves some
999
; before returning to 6b; if there is a sequential block indeed, this saves some
979
; time instead of many full-fledged lookups.
1000
; time instead of many full-fledged lookups.
980
        mov     [.sequential], 0
1001
        mov     [.sequential], 0
981
        mov     [.chain_start_pos], ecx
1002
        mov     [.chain_start_pos], edi
982
.look_backward:
1003
.look_backward:
983
; 6e. For each sector, update chain start pos/ptr, decrement sector number,
1004
; 6e. For each sector, update chain start pos/ptr, decrement sector number,
984
; look at the previous item.
1005
; look at the previous item.
985
        mov     [.chain_start_ptr], esi
1006
        mov     [.chain_start_ptr], esi
986
        inc     [.chain_size]
1007
        inc     [.chain_size]
Line 999... Line 1020...
999
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
1020
        cmp     [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
1000
        jnz     .found_chain_start
1021
        jnz     .found_chain_start
1001
; ...expand the chain one sector backwards and continue the loop at 6e.
1022
; ...expand the chain one sector backwards and continue the loop at 6e.
1002
; Otherwise, advance to step 7 if the previous item describes the correct sector
1023
; Otherwise, advance to step 7 if the previous item describes the correct sector
1003
; but is not modified, and return to step 6b otherwise.
1024
; but is not modified, and return to step 6b otherwise.
-
 
1025
        mov     edi, 1
-
 
1026
        shl     edi, cl
1004
        dec     [.chain_start_pos]
1027
        sub     [.chain_start_pos], edi
1005
        jmp     .look_backward
1028
        jmp     .look_backward
1006
.found_chain_start:
1029
.found_chain_start:
1007
; 7. Expand the chain forward.
1030
; 7. Expand the chain forward.
1008
; 7a. Prepare for the loop at 7b:
1031
; 7a. Prepare for the loop at 7b:
1009
; set esi = pointer to current item, edx:eax = current sector.
1032
; set esi = pointer to current item, edx:eax = current sector.
Line 1044... Line 1067...
1044
        jz      .write_non_sequential
1067
        jz      .write_non_sequential
1045
.write_sequential:
1068
.write_sequential:
1046
; 9. Write a sequential chain to disk.
1069
; 9. Write a sequential chain to disk.
1047
; 9a. Pass the entire chain to the driver.
1070
; 9a. Pass the entire chain to the driver.
1048
        mov     eax, [.chain_start_ptr]
1071
        mov     eax, [.chain_start_ptr]
1049
        mov     edx, [.chain_start_pos]
-
 
1050
        shl     edx, 9
-
 
1051
        add     edx, [ebx+DISKCACHE.data]
-
 
1052
        lea     ecx, [.chain_size]
1072
        lea     ecx, [.chain_size]
1053
        push    ecx     ; numsectors
1073
        push    ecx     ; numsectors
1054
        pushd   [eax+CACHE_ITEM.SectorHi]       ; startsector
1074
        pushd   [eax+CACHE_ITEM.SectorHi]       ; startsector
1055
        pushd   [eax+CACHE_ITEM.SectorLo]       ; startsector
1075
        pushd   [eax+CACHE_ITEM.SectorLo]       ; startsector
1056
        push    edx     ; buffer
1076
        push    [.chain_start_pos+12]           ; buffer
1057
        mov     esi, [ebp+PARTITION.Disk]
1077
        mov     esi, [ebp+PARTITION.Disk]
1058
        mov     al, DISKFUNC.write
1078
        mov     al, DISKFUNC.write
1059
        call    disk_call_driver
1079
        call    disk_call_driver
1060
; 9b. If failed, pass the error code to the driver.
1080
; 9b. If failed, pass the error code to the driver.
1061
        test    eax, eax
1081
        test    eax, eax
Line 1086... Line 1106...
1086
        jz      .nomemory
1106
        jz      .nomemory
1087
        cmp     eax, CACHE_MAX_ALLOC_SIZE shr 12
1107
        cmp     eax, CACHE_MAX_ALLOC_SIZE shr 12
1088
        jbe     @f
1108
        jbe     @f
1089
        mov     eax, CACHE_MAX_ALLOC_SIZE shr 12
1109
        mov     eax, CACHE_MAX_ALLOC_SIZE shr 12
1090
@@:
1110
@@:
1091
        shl     eax, 12 - 9
1111
        shl     eax, 12
-
 
1112
        shr     eax, cl
-
 
1113
        jz      .nomemory
1092
        cmp     eax, [.chain_size]
1114
        cmp     eax, [.chain_size]
1093
        jbe     @f
1115
        jbe     @f
1094
        mov     eax, [.chain_size]
1116
        mov     eax, [.chain_size]
1095
@@:
1117
@@:
1096
        mov     [.iteration_size], eax
1118
        mov     [.iteration_size], eax
1097
        shl     eax, 9
1119
        shl     eax, cl
1098
        stdcall kernel_alloc, eax
1120
        stdcall kernel_alloc, eax
1099
        test    eax, eax
1121
        test    eax, eax
1100
        jz      .nomemory
1122
        jz      .nomemory
1101
        mov     [.iteration_buffer], eax
1123
        mov     [.iteration_buffer], eax
1102
.write_non_sequential_iteration:
1124
.write_non_sequential_iteration:
Line 1121... Line 1143...
1121
        push    [.iteration_size+20]    ; temporary variable
1143
        push    [.iteration_size+20]    ; temporary variable
1122
.copy_loop:
1144
.copy_loop:
1123
; 13b. For each sector, copy the data.
1145
; 13b. For each sector, copy the data.
1124
; Note that edi is advanced automatically.
1146
; Note that edi is advanced automatically.
1125
        mov     esi, [.chain_start_pos+24]
1147
        mov     esi, [.chain_start_pos+24]
-
 
1148
        mov     ecx, [ebx+DISKCACHE.sector_size_log]
-
 
1149
        mov     eax, 1
1126
        shl     esi, 9
1150
        shl     eax, cl
1127
        add     esi, [ebx+DISKCACHE.data]
1151
        mov     ecx, eax
1128
        mov     ecx, 512/4
1152
        shr     ecx, 2
1129
        rep movsd
1153
        rep movsd
-
 
1154
        mov     ecx, eax ; keep for 13e
1130
; 13c. Mark the item as not-modified.
1155
; 13c. Mark the item as not-modified.
1131
        mov     esi, [.chain_start_ptr+24]
1156
        mov     esi, [.chain_start_ptr+24]
1132
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
1157
        mov     [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
1133
; 13d. Check whether the next sector continues the chain.
1158
; 13d. Check whether the next sector continues the chain.
1134
; If so, advance to 13e. Otherwise, go to 13f.
1159
; If so, advance to 13e. Otherwise, go to 13f.
Line 1143... Line 1168...
1143
        jnz     .no_forward
1168
        jnz     .no_forward
1144
        cmp     [esi+CACHE_ITEM.SectorHi], edx
1169
        cmp     [esi+CACHE_ITEM.SectorHi], edx
1145
        jnz     .no_forward
1170
        jnz     .no_forward
1146
; 13e. Increment position/pointer to the chain and
1171
; 13e. Increment position/pointer to the chain and
1147
; continue the loop.
1172
; continue the loop.
1148
        inc     [.chain_start_pos+24]
1173
        add     [.chain_start_pos+24], ecx
1149
        mov     [.chain_start_ptr+24], esi
1174
        mov     [.chain_start_ptr+24], esi
1150
        dec     dword [esp]
1175
        dec     dword [esp]
1151
        jnz     .copy_loop
1176
        jnz     .copy_loop
1152
        jmp     .copy_done
1177
        jmp     .copy_done
1153
.no_forward:
1178
.no_forward:
1154
; 13f. Call the lookup function without adding to the cache.
1179
; 13f. Call the lookup function without adding to the cache.
1155
; Update position/pointer with returned value.
1180
; Update position/pointer with returned value.
1156
; Note: for the last sector in the chain, ecx/esi may contain
1181
; Note: for the last sector in the chain, edi/esi may contain
1157
; garbage; we are not going to use them in this case.
1182
; garbage; we are not going to use them in this case.
-
 
1183
        push    edi
1158
        call    cache_lookup_read
1184
        call    cache_lookup_read
1159
        mov     [.chain_start_pos+24], ecx
1185
        mov     [.chain_start_pos+28], edi
1160
        mov     [.chain_start_ptr+24], esi
1186
        mov     [.chain_start_ptr+28], esi
-
 
1187
        pop     edi
1161
        dec     dword [esp]
1188
        dec     dword [esp]
1162
        jnz     .copy_loop
1189
        jnz     .copy_loop
1163
.copy_done:
1190
.copy_done:
1164
; 13g. Restore the stack after 13a.
1191
; 13g. Restore the stack after 13a.
1165
        pop     ecx
1192
        pop     ecx
Line 1201... Line 1228...
1201
; driver can adjust the size. In particular, setting size to zero disables
1228
; driver can adjust the size. In particular, setting size to zero disables
1202
; caching: there is no sense in a cache for a ramdisk. In fact, such action
1229
; caching: there is no sense in a cache for a ramdisk. In fact, such action
1203
; is most useful example of a non-trivial adjustment.
1230
; is most useful example of a non-trivial adjustment.
1204
; esi = pointer to DISK structure
1231
; esi = pointer to DISK structure
1205
disk_init_cache:
1232
disk_init_cache:
-
 
1233
; 1. Verify sector size. The code requires it to be a power of 2 not less than 4.
-
 
1234
; In the name of sanity check that sector size is not too small or too large.
-
 
1235
        bsf     ecx, [esi+DISK.MediaInfo.SectorSize]
-
 
1236
        jz      .invalid_sector_size
-
 
1237
        mov     eax, 1
-
 
1238
        shl     eax, cl
-
 
1239
        cmp     eax, [esi+DISK.MediaInfo.SectorSize]
-
 
1240
        jnz     .invalid_sector_size
-
 
1241
        cmp     ecx, 6
-
 
1242
        jb      .invalid_sector_size
-
 
1243
        cmp     ecx, 14
-
 
1244
        jbe     .normal_sector_size
-
 
1245
.invalid_sector_size:
-
 
1246
        DEBUGF 1,'K : sector size %x is invalid\n',[esi+DISK.MediaInfo.SectorSize]
-
 
1247
        xor     eax, eax
-
 
1248
        ret
-
 
1249
.normal_sector_size:
-
 
1250
        mov     [esi+DISK.SysCache.sector_size_log], ecx
-
 
1251
        mov     [esi+DISK.AppCache.sector_size_log], ecx
1206
; 1. Calculate the suggested cache size.
1252
; 2. Calculate the suggested cache size.
1207
; 1a. Get the size of free physical memory in pages.
1253
; 2a. Get the size of free physical memory in pages.
1208
        mov     eax, [pg_data.pages_free]
1254
        mov     eax, [pg_data.pages_free]
1209
; 1b. Use the value to calculate the size.
1255
; 2b. Use the value to calculate the size.
1210
        shl     eax, 12 - 5     ; 1/32 of it in bytes
1256
        shl     eax, 12 - 5     ; 1/32 of it in bytes
1211
        and     eax, -8*4096    ; round down to the multiple of 8 pages
1257
        and     eax, -8*4096    ; round down to the multiple of 8 pages
1212
; 1c. Force lower and upper limits.
1258
; 2c. Force lower and upper limits.
1213
        cmp     eax, 1024*1024
1259
        cmp     eax, 1024*1024
1214
        jb      @f
1260
        jb      @f
1215
        mov     eax, 1024*1024
1261
        mov     eax, 1024*1024
1216
@@:
1262
@@:
1217
        cmp     eax, 128*1024
1263
        cmp     eax, 128*1024
1218
        ja      @f
1264
        ja      @f
1219
        mov     eax, 128*1024
1265
        mov     eax, 128*1024
1220
@@:
1266
@@:
1221
; 1d. Give a chance to the driver to adjust the size.
1267
; 2d. Give a chance to the driver to adjust the size.
1222
        push    eax
1268
        push    eax
1223
        mov     al, DISKFUNC.adjust_cache_size
1269
        mov     al, DISKFUNC.adjust_cache_size
1224
        call    disk_call_driver
1270
        call    disk_call_driver
1225
; Cache size calculated.
1271
; Cache size calculated.
1226
        mov     [esi+DISK.cache_size], eax
1272
        mov     [esi+DISK.cache_size], eax
1227
        test    eax, eax
1273
        test    eax, eax
1228
        jz      .nocache
1274
        jz      .nocache
1229
; 2. Allocate memory for the cache.
1275
; 3. Allocate memory for the cache.
1230
; 2a. Call the allocator.
1276
; 3a. Call the allocator.
1231
        stdcall kernel_alloc, eax
1277
        stdcall kernel_alloc, eax
1232
        test    eax, eax
1278
        test    eax, eax
1233
        jnz     @f
1279
        jnz     @f
1234
; 2b. If it failed, say a message and return with eax = 0.
1280
; 3b. If it failed, say a message and return with eax = 0.
1235
        dbgstr 'no memory for disk cache'
1281
        dbgstr 'no memory for disk cache'
1236
        jmp     .nothing
1282
        jmp     .nothing
1237
@@:
1283
@@:
1238
; 3. Fill two DISKCACHE structures.
1284
; 4. Fill two DISKCACHE structures.
1239
        mov     [esi+DISK.SysCache.pointer], eax
1285
        mov     [esi+DISK.SysCache.pointer], eax
1240
        lea     ecx, [esi+DISK.CacheLock]
1286
        lea     ecx, [esi+DISK.CacheLock]
1241
        call    mutex_init
1287
        call    mutex_init
1242
; The following code is inherited from getcache.inc.
1288
; The following code is inherited from getcache.inc.
1243
        mov     edx, [esi+DISK.SysCache.pointer]
1289
        mov     edx, [esi+DISK.SysCache.pointer]
Line 1250... Line 1296...
1250
        imul    eax, 7
1296
        imul    eax, 7
1251
        mov     [esi+DISK.AppCache.data_size], eax
1297
        mov     [esi+DISK.AppCache.data_size], eax
1252
        mov     [esi+DISK.AppCache.pointer], edx
1298
        mov     [esi+DISK.AppCache.pointer], edx
Line 1253... Line 1299...
1253
 
1299
 
1254
        mov     eax, [esi+DISK.SysCache.data_size]
-
 
1255
        push    ebx
1300
        mov     eax, [esi+DISK.SysCache.data_size]
1256
        call    calculate_for_hd64
-
 
1257
        pop     ebx
1301
        call    calculate_cache_slots
1258
        add     eax, [esi+DISK.SysCache.pointer]
1302
        add     eax, [esi+DISK.SysCache.pointer]
1259
        mov     [esi+DISK.SysCache.data], eax
1303
        mov     [esi+DISK.SysCache.data], eax
Line 1260... Line 1304...
1260
        mov     [esi+DISK.SysCache.sad_size], ecx
1304
        mov     [esi+DISK.SysCache.sad_size], ecx
Line 1265... Line 1309...
1265
        xor     eax, eax
1309
        xor     eax, eax
1266
        rep stosd
1310
        rep stosd
1267
        pop     edi
1311
        pop     edi
Line 1268... Line 1312...
1268
 
1312
 
1269
        mov     eax, [esi+DISK.AppCache.data_size]
-
 
1270
        push    ebx
1313
        mov     eax, [esi+DISK.AppCache.data_size]
1271
        call    calculate_for_hd64
-
 
1272
        pop     ebx
1314
        call    calculate_cache_slots
1273
        add     eax, [esi+DISK.AppCache.pointer]
1315
        add     eax, [esi+DISK.AppCache.pointer]
1274
        mov     [esi+DISK.AppCache.data], eax
1316
        mov     [esi+DISK.AppCache.data], eax
Line 1275... Line 1317...
1275
        mov     [esi+DISK.AppCache.sad_size], ecx
1317
        mov     [esi+DISK.AppCache.sad_size], ecx
Line 1279... Line 1321...
1279
        lea     ecx, [(ecx+1)*3]
1321
        lea     ecx, [(ecx+1)*3]
1280
        xor     eax, eax
1322
        xor     eax, eax
1281
        rep stosd
1323
        rep stosd
1282
        pop     edi
1324
        pop     edi
Line 1283... Line 1325...
1283
 
1325
 
1284
; 4. Return with nonzero al.
1326
; 5. Return with nonzero al.
1285
        mov     al, 1
1327
        mov     al, 1
1286
; 5. Return.
1328
; 6. Return.
1287
.nothing:
1329
.nothing:
1288
        ret
1330
        ret
1289
; No caching is required for this driver. Zero cache pointers and return with
1331
; No caching is required for this driver. Zero cache pointers and return with
1290
; nonzero al.
1332
; nonzero al.
1291
.nocache:
1333
.nocache:
1292
        mov     [esi+DISK.SysCache.pointer], eax
1334
        mov     [esi+DISK.SysCache.pointer], eax
1293
        mov     [esi+DISK.AppCache.pointer], eax
1335
        mov     [esi+DISK.AppCache.pointer], eax
1294
        mov     al, 1
1336
        mov     al, 1
Line 1295... Line 1337...
1295
        ret
1337
        ret
1296
 
1338
 
1297
calculate_for_hd64:
1339
calculate_cache_slots:
1298
        push    eax
1340
        push    eax
1299
        mov     ebx, eax
1341
        mov     ecx, [esi+DISK.MediaInfo.SectorSize]
1300
        shr     eax, 9
1342
        add     ecx, sizeof.CACHE_ITEM
1301
        lea     eax, [eax*3]
1343
        xor     edx, edx
1302
        shl     eax, 2
1344
        div     ecx
1303
        sub     ebx, eax
1345
        mov     ecx, eax
1304
        shr     ebx, 9
-
 
1305
        mov     ecx, ebx
1346
        imul    eax, [esi+DISK.MediaInfo.SectorSize]
1306
        shl     ebx, 9
-
 
1307
        pop     eax
1347
        sub     [esp], eax
1308
        sub     eax, ebx
1348
        pop     eax
Line 1309... Line 1349...
1309
        dec     ecx
1349
        dec     ecx