disk cache: support for sector sizes other than 512 bytes

git-svn-id: svn://kolibrios.org@5089 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
CleverMouse 2014-09-03 12:11:19 +00:00
parent 99959f9109
commit 9d022746fd
6 changed files with 176 additions and 125 deletions

View File

@ -108,6 +108,7 @@ struct DISKCACHE
data dd ? data dd ?
sad_size dd ? sad_size dd ?
search_start dd ? search_start dd ?
sector_size_log dd ?
ends ends
; This structure represents a disk device and its media for the kernel. ; This structure represents a disk device and its media for the kernel.
@ -271,13 +272,13 @@ disk_list_mutex MUTEX
endg endg
iglobal iglobal
; The function 'disk_scan_partitions' needs three 512-byte buffers for ; The function 'disk_scan_partitions' needs three sector-sized buffers for
; MBR, bootsector and fs-temporary sector data. It can not use the static ; MBR, bootsector and fs-temporary sector data. It can not use the static
; buffers always, since it can be called for two or more disks in parallel. ; buffers always, since it can be called for two or more disks in parallel.
; However, this case is not typical. We reserve three static 512-byte buffers ; However, this case is not typical. We reserve three static 512-byte buffers
; and a flag that these buffers are currently used. If 'disk_scan_partitions' ; and a flag that these buffers are currently used. If 'disk_scan_partitions'
; detects that the buffers are currently used, it allocates buffers from the ; detects that the buffers are currently used, it allocates buffers from the
; heap. ; heap. Also, the heap is used when sector size is other than 512.
; The flag is implemented as a global dword variable. When the static buffers ; The flag is implemented as a global dword variable. When the static buffers
; are not used, the value is -1. When the static buffers are used, the value ; are not used, the value is -1. When the static buffers are used, the value
; is normally 0 and temporarily can become greater. The function increments ; is normally 0 and temporarily can become greater. The function increments
@ -638,28 +639,25 @@ disk_scan_partitions:
; 1. Initialize .NumPartitions and .Partitions fields as zeros: empty list. ; 1. Initialize .NumPartitions and .Partitions fields as zeros: empty list.
and [esi+DISK.NumPartitions], 0 and [esi+DISK.NumPartitions], 0
and [esi+DISK.Partitions], 0 and [esi+DISK.Partitions], 0
; 2. Currently we can work only with 512-bytes sectors. Check this restriction. ; 2. Acquire the buffer for MBR and bootsector tests. See the comment before
; The only exception is 2048-bytes CD/DVD, but they are not supported yet by
; this code.
cmp [esi+DISK.MediaInfo.SectorSize], 512
jz .doscan
DEBUGF 1,'K : sector size is %d, only 512 is supported\n',[esi+DISK.MediaInfo.SectorSize]
ret
.doscan:
; 3. Acquire the buffer for MBR and bootsector tests. See the comment before
; the 'partition_buffer_users' variable. ; the 'partition_buffer_users' variable.
mov eax, [esi+DISK.MediaInfo.SectorSize]
cmp eax, 512
jnz @f
mov ebx, mbr_buffer ; assume the global buffer is free mov ebx, mbr_buffer ; assume the global buffer is free
lock inc [partition_buffer_users] lock inc [partition_buffer_users]
jz .buffer_acquired ; yes, it is free jz .buffer_acquired ; yes, it is free
lock dec [partition_buffer_users] ; no, we must allocate lock dec [partition_buffer_users] ; no, we must allocate
stdcall kernel_alloc, 512*3 @@:
lea eax, [eax*3]
stdcall kernel_alloc, eax
test eax, eax test eax, eax
jz .nothing jz .nothing
xchg eax, ebx xchg eax, ebx
.buffer_acquired: .buffer_acquired:
; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no ; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no
; more than MAX_NUM_PARTITION times. ; more than MAX_NUM_PARTITION times.
; 4. Prepare things for the loop. ; 3. Prepare things for the loop.
; ebp will hold the sector number for current MBR/EBR. ; ebp will hold the sector number for current MBR/EBR.
; [esp] will hold the sector number for current extended partition, if there ; [esp] will hold the sector number for current extended partition, if there
; is one. ; is one.
@ -668,6 +666,10 @@ disk_scan_partitions:
push MAX_NUM_PARTITIONS ; the counter of max MBRs to process push MAX_NUM_PARTITIONS ; the counter of max MBRs to process
xor ebp, ebp ; start from sector zero xor ebp, ebp ; start from sector zero
push ebp ; no extended partition yet push ebp ; no extended partition yet
; 4. MBR is 512 bytes long. If sector size is less than 512 bytes,
; assume no MBR, no partitions and go to 10.
cmp [esi+DISK.MediaInfo.SectorSize], 512
jb .notmbr
.new_mbr: .new_mbr:
; 5. Read the current sector. ; 5. Read the current sector.
; Note that 'read' callback operates with 64-bit sector numbers, so we must ; Note that 'read' callback operates with 64-bit sector numbers, so we must
@ -986,7 +988,7 @@ end virtual
; a three-sectors-sized buffer. This function saves ebx in the stack ; a three-sectors-sized buffer. This function saves ebx in the stack
; immediately before ebp. ; immediately before ebp.
mov ebx, [ebp-4] ; get buffer mov ebx, [ebp-4] ; get buffer
add ebx, 512 ; advance over MBR data to bootsector data add ebx, [esi+DISK.MediaInfo.SectorSize] ; advance over MBR data to bootsector data
add ebp, 8 ; ebp points to part of PARTITION structure add ebp, 8 ; ebp points to part of PARTITION structure
xor eax, eax ; first sector of the partition xor eax, eax ; first sector of the partition
call fs_read32_sys call fs_read32_sys
@ -997,7 +999,7 @@ end virtual
; ebp -> first three fields of PARTITION structure, .start, .length, .disk; ; ebp -> first three fields of PARTITION structure, .start, .length, .disk;
; [esp] = error code after bootsector read: 0 = ok, otherwise = failed, ; [esp] = error code after bootsector read: 0 = ok, otherwise = failed,
; ebx points to the buffer for bootsector, ; ebx points to the buffer for bootsector,
; ebx+512 points to 512-bytes buffer that can be used for anything. ; ebx+[esi+DISK.MediaInfo.SectorSize] points to sector-sized buffer that can be used for anything.
call fat_create_partition call fat_create_partition
test eax, eax test eax, eax
jnz .success jnz .success

View File

@ -118,7 +118,6 @@ end virtual
add [.sector_lo], eax add [.sector_lo], eax
adc [.sector_hi], edx adc [.sector_hi], edx
; 5. If the cache is disabled, pass the request directly to the driver. ; 5. If the cache is disabled, pass the request directly to the driver.
mov edi, [.buffer]
cmp [ebx+DISKCACHE.pointer], 0 cmp [ebx+DISKCACHE.pointer], 0
jz .nocache jz .nocache
; 6. Look for sectors in the cache, sequentially from the beginning. ; 6. Look for sectors in the cache, sequentially from the beginning.
@ -137,13 +136,15 @@ end virtual
; release the lock and go to 7. ; release the lock and go to 7.
jc .not_found_in_cache jc .not_found_in_cache
; The sector is found in cache. ; The sector is found in cache.
; 6d. Copy data for the caller. ; 6d. Copy data for the caller, advance [.buffer].
; Note that buffer in edi is advanced automatically. mov esi, edi
mov esi, ecx mov edi, [.buffer]
shl esi, 9 mov eax, 1
add esi, [ebx+DISKCACHE.data] shl eax, cl
mov ecx, 512/4 mov ecx, eax
shr ecx, 2
rep movsd rep movsd
mov [.buffer], edi
; 6e. Advance the sector. ; 6e. Advance the sector.
add [.sector_lo], 1 add [.sector_lo], 1
adc [.sector_hi], 0 adc [.sector_hi], 0
@ -177,6 +178,7 @@ end virtual
; However, for extra-large requests make an upper limit: ; However, for extra-large requests make an upper limit:
; do not use more than half of the free memory ; do not use more than half of the free memory
; or more than CACHE_MAX_ALLOC_SIZE bytes. ; or more than CACHE_MAX_ALLOC_SIZE bytes.
mov ecx, [ebx+DISKCACHE.sector_size_log]
mov ebx, [pg_data.pages_free] mov ebx, [pg_data.pages_free]
shr ebx, 1 shr ebx, 1
jz .nomemory jz .nomemory
@ -184,13 +186,15 @@ end virtual
jbe @f jbe @f
mov ebx, CACHE_MAX_ALLOC_SIZE shr 12 mov ebx, CACHE_MAX_ALLOC_SIZE shr 12
@@: @@:
shl ebx, 12 - 9 shl ebx, 12
shr ebx, cl
jz .nomemory
cmp ebx, [.num_sectors] cmp ebx, [.num_sectors]
jbe @f jbe @f
mov ebx, [.num_sectors] mov ebx, [.num_sectors]
@@: @@:
mov eax, ebx mov eax, ebx
shl eax, 9 shl eax, cl
stdcall kernel_alloc, eax stdcall kernel_alloc, eax
; If failed, return the appropriate error code. ; If failed, return the appropriate error code.
test eax, eax test eax, eax
@ -233,28 +237,31 @@ end virtual
jz @f jz @f
mov [.error_code+.local_vars2_size], eax mov [.error_code+.local_vars2_size], eax
@@: @@:
; 11. Copy data for the caller. ; 11. Copy data for the caller, advance .buffer.
; Note that buffer in edi is advanced automatically.
cmp [.current_num_sectors], 0 cmp [.current_num_sectors], 0
jz .copy_done jz .copy_done
mov ecx, [.current_num_sectors] mov ebx, [.cache+.local_vars2_size]
shl ecx, 9-2 mov eax, [.current_num_sectors]
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl eax, cl
mov esi, [.allocated_buffer] mov esi, [.allocated_buffer]
mov edi, [.buffer+.local_vars2_size]
mov ecx, eax
shr ecx, 2
rep movsd rep movsd
mov [.buffer+.local_vars2_size], edi
; 12. Copy data to the cache. ; 12. Copy data to the cache.
; 12a. Acquire the lock. ; 12a. Acquire the lock.
mov ebx, [.cache+.local_vars2_size]
mov ecx, [ebp+PARTITION.Disk] mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock add ecx, DISK.CacheLock
call mutex_lock call mutex_lock
; 12b. Prepare for the loop: save edi and create a local variable that ; 12b. Prepare for the loop: create a local variable that
; stores number of sectors to be copied. ; stores number of sectors to be copied.
push edi push [.current_num_sectors]
push [.current_num_sectors+4]
.store_to_cache: .store_to_cache:
; 12c. For each sector, call the lookup function with adding to the cache, if not yet. ; 12c. For each sector, call the lookup function with adding to the cache, if not yet.
mov eax, [.sector_lo+.local_vars2_size+8] mov eax, [.sector_lo+.local_vars2_size+4]
mov edx, [.sector_hi+.local_vars2_size+8] mov edx, [.sector_hi+.local_vars2_size+4]
call cache_lookup_write call cache_lookup_write
test eax, eax test eax, eax
jnz .cache_error jnz .cache_error
@ -263,39 +270,39 @@ end virtual
; so rewrite data for the caller from the cache. ; so rewrite data for the caller from the cache.
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .not_modified jnz .not_modified
mov esi, ecx mov esi, edi
shl esi, 9 mov edi, [.buffer+.local_vars2_size+4]
add esi, [ebx+DISKCACHE.data] mov eax, [esp]
mov edi, [esp+4] shl eax, cl
mov ecx, [esp] sub edi, eax
shl ecx, 9-2 mov eax, 1
sub edi, ecx shl eax, cl
mov ecx, 512/4 mov ecx, eax
shr ecx, 2
rep movsd rep movsd
add [.current_buffer+8], 512 add [.current_buffer+4], eax
jmp .sector_done jmp .sector_done
.not_modified: .not_modified:
; 12e. For each not-modified sector, ; 12e. For each not-modified sector,
; copy data, mark the item as not-modified copy of the disk, ; copy data, mark the item as not-modified copy of the disk,
; advance .current_buffer and .sector_hi:.sector_lo to the next sector. ; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
mov esi, [.current_buffer+8] mov eax, 1
mov edi, ecx shl eax, cl
shl edi, 9 mov esi, [.current_buffer+4]
add edi, [ebx+DISKCACHE.data] mov ecx, eax
mov ecx, 512/4 shr ecx, 2
rep movsd rep movsd
mov [.current_buffer+8], esi mov [.current_buffer+4], esi
.sector_done: .sector_done:
add [.sector_lo+.local_vars2_size+8], 1 add [.sector_lo+.local_vars2_size+4], 1
adc [.sector_hi+.local_vars2_size+8], 0 adc [.sector_hi+.local_vars2_size+4], 0
; 12f. Continue the loop 12c-12e until all sectors are read. ; 12f. Continue the loop 12c-12e until all sectors are read.
dec dword [esp] dec dword [esp]
jnz .store_to_cache jnz .store_to_cache
.cache_error: .cache_error:
; 12g. Restore after the loop: pop the local variable and restore edi. ; 12g. Restore after the loop: pop the local variable.
pop ecx pop ecx
pop edi
; 12h. Release the lock. ; 12h. Release the lock.
mov ecx, [ebp+PARTITION.Disk] mov ecx, [ebp+PARTITION.Disk]
add ecx, DISK.CacheLock add ecx, DISK.CacheLock
@ -328,7 +335,7 @@ end virtual
push eax ; numsectors push eax ; numsectors
push [.sector_hi+4] ; startsector push [.sector_hi+4] ; startsector
push [.sector_lo+8] ; startsector push [.sector_lo+8] ; startsector
push edi ; buffer push [.buffer+12] ; buffer
mov esi, [ebp+PARTITION.Disk] mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read mov al, DISKFUNC.read
call disk_call_driver call disk_call_driver
@ -440,11 +447,11 @@ end virtual
; 6c. For each sector, copy data, mark the item as modified and not saved, ; 6c. For each sector, copy data, mark the item as modified and not saved,
; advance .current_buffer to the next sector. ; advance .current_buffer to the next sector.
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED mov [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
mov eax, 1
shl eax, cl
mov esi, [.cur_buffer] mov esi, [.cur_buffer]
mov edi, ecx mov ecx, eax
shl edi, 9 shr ecx, 2
add edi, [ebx+DISKCACHE.data]
mov ecx, 512/4
rep movsd rep movsd
mov [.cur_buffer], esi mov [.cur_buffer], esi
; 6d. Remove the sector from the other cache. ; 6d. Remove the sector from the other cache.
@ -592,11 +599,12 @@ end virtual
jc .not_found_in_cache jc .not_found_in_cache
.found_in_cache: .found_in_cache:
; 4c. Copy the data. ; 4c. Copy the data.
mov esi, edi
mov edi, [.buffer] mov edi, [.buffer]
mov esi, ecx mov eax, 1
shl esi, 9 shl eax, cl
add esi, [ebx+DISKCACHE.data] mov ecx, eax
mov ecx, 512/4 shr ecx, 2
rep movsd rep movsd
; 4d. Release the lock and return success. ; 4d. Release the lock and return success.
mov ecx, [ebp+PARTITION.Disk] mov ecx, [ebp+PARTITION.Disk]
@ -627,7 +635,10 @@ end virtual
add ecx, DISK.CacheLock add ecx, DISK.CacheLock
call mutex_unlock call mutex_unlock
; 7. Allocate buffer for CACHE_LEGACY_READ_SIZE sectors. ; 7. Allocate buffer for CACHE_LEGACY_READ_SIZE sectors.
stdcall kernel_alloc, CACHE_LEGACY_READ_SIZE shl 9 mov eax, CACHE_LEGACY_READ_SIZE
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl eax, cl
stdcall kernel_alloc, eax
; If failed, return the corresponding error code. ; If failed, return the corresponding error code.
test eax, eax test eax, eax
jz .nomemory jz .nomemory
@ -656,7 +667,11 @@ end virtual
; 10. Copy data for the caller. ; 10. Copy data for the caller.
mov esi, [.allocated_buffer] mov esi, [.allocated_buffer]
mov edi, [.buffer+.local_vars2_size] mov edi, [.buffer+.local_vars2_size]
mov ecx, 512/4 mov ecx, [ebx+DISKCACHE.sector_size_log]
mov eax, 1
shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd rep movsd
; 11. Store all sectors that were successfully read to the cache. ; 11. Store all sectors that were successfully read to the cache.
; 11a. Acquire the lock. ; 11a. Acquire the lock.
@ -671,19 +686,19 @@ end virtual
test eax, eax test eax, eax
jnz .cache_error jnz .cache_error
; 11c. Ignore sectors marked as modified: for them the cache is more recent that disk data. ; 11c. Ignore sectors marked as modified: for them the cache is more recent that disk data.
mov eax, 1
shl eax, cl
cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED cmp [esi+CACHE_ITEM.Status], CACHE_ITEM_MODIFIED
jnz .not_modified jnz .not_modified
add [.current_buffer], 512 add [.current_buffer], eax
jmp .sector_done jmp .sector_done
.not_modified: .not_modified:
; 11d. For each sector, copy data, mark the item as not-modified copy of the disk, ; 11d. For each sector, copy data, mark the item as not-modified copy of the disk,
; advance .current_buffer and .sector_hi:.sector_lo to the next sector. ; advance .current_buffer and .sector_hi:.sector_lo to the next sector.
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
mov esi, [.current_buffer] mov esi, [.current_buffer]
mov edi, ecx mov ecx, eax
shl edi, 9 shr ecx, 2
add edi, [ebx+DISKCACHE.data]
mov ecx, 512/4
rep movsd rep movsd
mov [.current_buffer], esi mov [.current_buffer], esi
.sector_done: .sector_done:
@ -721,16 +736,14 @@ end virtual
call cache_lookup_write call cache_lookup_write
test eax, eax test eax, eax
jnz .floppy_cache_error jnz .floppy_cache_error
push ecx push esi
; 14. Call the driver to read one sector. ; 14. Call the driver to read one sector.
push 1 push 1
push esp push esp
push edx push edx
push [.sector_lo+16] push [.sector_lo+16]
shl ecx, 9 push edi
add ecx, [ebx+DISKCACHE.data]
push ecx
mov esi, [ebp+PARTITION.Disk] mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.read mov al, DISKFUNC.read
call disk_call_driver call disk_call_driver
@ -740,10 +753,7 @@ end virtual
; 15. Get the slot and pointer to the cache item, ; 15. Get the slot and pointer to the cache item,
; change the status to not-modified copy of the disk ; change the status to not-modified copy of the disk
; and go to 4c. ; and go to 4c.
pop ecx pop esi
lea esi, [ecx*sizeof.CACHE_ITEM/4]
shl esi, 2
add esi, [ebx+DISKCACHE.pointer]
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
jmp .found_in_cache jmp .found_in_cache
@ -795,13 +805,14 @@ fs_write32_app:
; in: edx:eax = sector ; in: edx:eax = sector
; in: ebx -> DISKCACHE structure ; in: ebx -> DISKCACHE structure
; out: CF set if sector is not in cache ; out: CF set if sector is not in cache
; out: ecx = index in cache ; out: ecx = sector_size_log
; out: esi -> sector:status ; out: esi -> sector:status
; out: edi -> sector data
proc cache_lookup_read proc cache_lookup_read
mov esi, [ebx+DISKCACHE.pointer] mov esi, [ebx+DISKCACHE.pointer]
add esi, sizeof.CACHE_ITEM add esi, sizeof.CACHE_ITEM
mov ecx, 1 mov edi, 1
.hdreadcache: .hdreadcache:
@ -812,14 +823,17 @@ proc cache_lookup_read
jne .nohdcache jne .nohdcache
cmp [esi+CACHE_ITEM.SectorHi], edx cmp [esi+CACHE_ITEM.SectorHi], edx
jne .nohdcache jne .nohdcache
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl edi, cl
add edi, [ebx+DISKCACHE.data]
clc clc
ret ret
.nohdcache: .nohdcache:
add esi, sizeof.CACHE_ITEM add esi, sizeof.CACHE_ITEM
inc ecx inc edi
cmp ecx, [ebx+DISKCACHE.sad_size] cmp edi, [ebx+DISKCACHE.sad_size]
jbe .hdreadcache jbe .hdreadcache
stc stc
ret ret
@ -832,8 +846,8 @@ endp
; in: ebx -> DISKCACHE structure ; in: ebx -> DISKCACHE structure
; in: ebp -> PARTITION structure ; in: ebp -> PARTITION structure
; out: eax = error code ; out: eax = error code
; out: ecx = index in cache
; out: esi -> sector:status ; out: esi -> sector:status
; out: edi -> sector data
proc cache_lookup_write proc cache_lookup_write
call cache_lookup_read call cache_lookup_read
jnc .return0 jnc .return0
@ -874,6 +888,10 @@ proc cache_lookup_write
popd [esi+CACHE_ITEM.SectorLo] popd [esi+CACHE_ITEM.SectorLo]
popd [esi+CACHE_ITEM.SectorHi] popd [esi+CACHE_ITEM.SectorHi]
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY mov [esi+CACHE_ITEM.Status], CACHE_ITEM_EMPTY
mov edi, ecx
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl edi, cl
add edi, [ebx+DISKCACHE.data]
.return0: .return0:
xor eax, eax ; success xor eax, eax ; success
ret ret
@ -902,7 +920,7 @@ virtual at esp
.sequential dd ? .sequential dd ?
; boolean variable, 1 if the current chain is sequential in the cache, ; boolean variable, 1 if the current chain is sequential in the cache,
; 0 if additional buffer is needed to perform the operation ; 0 if additional buffer is needed to perform the operation
.chain_start_pos dd ? ; slot of chain start item .chain_start_pos dd ? ; data of chain start item
.chain_start_ptr dd ? ; pointer to chain start item .chain_start_ptr dd ? ; pointer to chain start item
.chain_size dd ? ; chain size (thanks, C.O.) .chain_size dd ? ; chain size (thanks, C.O.)
.iteration_size dd ? .iteration_size dd ?
@ -951,6 +969,9 @@ end virtual
mov eax, [ebx+DISKCACHE.sad_size] mov eax, [ebx+DISKCACHE.sad_size]
sub eax, [.size_left] sub eax, [.size_left]
inc eax inc eax
mov ecx, [ebx+DISKCACHE.sector_size_log]
shl eax, cl
add eax, [ebx+DISKCACHE.data]
mov [.chain_start_pos], eax mov [.chain_start_pos], eax
mov [.chain_size], 0 mov [.chain_size], 0
mov [.sequential], 1 mov [.sequential], 1
@ -978,7 +999,7 @@ end virtual
; before returning to 6b; if there is a sequential block indeed, this saves some ; before returning to 6b; if there is a sequential block indeed, this saves some
; time instead of many full-fledged lookups. ; time instead of many full-fledged lookups.
mov [.sequential], 0 mov [.sequential], 0
mov [.chain_start_pos], ecx mov [.chain_start_pos], edi
.look_backward: .look_backward:
; 6e. For each sector, update chain start pos/ptr, decrement sector number, ; 6e. For each sector, update chain start pos/ptr, decrement sector number,
; look at the previous item. ; look at the previous item.
@ -1001,7 +1022,9 @@ end virtual
; ...expand the chain one sector backwards and continue the loop at 6e. ; ...expand the chain one sector backwards and continue the loop at 6e.
; Otherwise, advance to step 7 if the previous item describes the correct sector ; Otherwise, advance to step 7 if the previous item describes the correct sector
; but is not modified, and return to step 6b otherwise. ; but is not modified, and return to step 6b otherwise.
dec [.chain_start_pos] mov edi, 1
shl edi, cl
sub [.chain_start_pos], edi
jmp .look_backward jmp .look_backward
.found_chain_start: .found_chain_start:
; 7. Expand the chain forward. ; 7. Expand the chain forward.
@ -1046,14 +1069,11 @@ end virtual
; 9. Write a sequential chain to disk. ; 9. Write a sequential chain to disk.
; 9a. Pass the entire chain to the driver. ; 9a. Pass the entire chain to the driver.
mov eax, [.chain_start_ptr] mov eax, [.chain_start_ptr]
mov edx, [.chain_start_pos]
shl edx, 9
add edx, [ebx+DISKCACHE.data]
lea ecx, [.chain_size] lea ecx, [.chain_size]
push ecx ; numsectors push ecx ; numsectors
pushd [eax+CACHE_ITEM.SectorHi] ; startsector pushd [eax+CACHE_ITEM.SectorHi] ; startsector
pushd [eax+CACHE_ITEM.SectorLo] ; startsector pushd [eax+CACHE_ITEM.SectorLo] ; startsector
push edx ; buffer push [.chain_start_pos+12] ; buffer
mov esi, [ebp+PARTITION.Disk] mov esi, [ebp+PARTITION.Disk]
mov al, DISKFUNC.write mov al, DISKFUNC.write
call disk_call_driver call disk_call_driver
@ -1088,13 +1108,15 @@ end virtual
jbe @f jbe @f
mov eax, CACHE_MAX_ALLOC_SIZE shr 12 mov eax, CACHE_MAX_ALLOC_SIZE shr 12
@@: @@:
shl eax, 12 - 9 shl eax, 12
shr eax, cl
jz .nomemory
cmp eax, [.chain_size] cmp eax, [.chain_size]
jbe @f jbe @f
mov eax, [.chain_size] mov eax, [.chain_size]
@@: @@:
mov [.iteration_size], eax mov [.iteration_size], eax
shl eax, 9 shl eax, cl
stdcall kernel_alloc, eax stdcall kernel_alloc, eax
test eax, eax test eax, eax
jz .nomemory jz .nomemory
@ -1123,10 +1145,13 @@ end virtual
; 13b. For each sector, copy the data. ; 13b. For each sector, copy the data.
; Note that edi is advanced automatically. ; Note that edi is advanced automatically.
mov esi, [.chain_start_pos+24] mov esi, [.chain_start_pos+24]
shl esi, 9 mov ecx, [ebx+DISKCACHE.sector_size_log]
add esi, [ebx+DISKCACHE.data] mov eax, 1
mov ecx, 512/4 shl eax, cl
mov ecx, eax
shr ecx, 2
rep movsd rep movsd
mov ecx, eax ; keep for 13e
; 13c. Mark the item as not-modified. ; 13c. Mark the item as not-modified.
mov esi, [.chain_start_ptr+24] mov esi, [.chain_start_ptr+24]
mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY mov [esi+CACHE_ITEM.Status], CACHE_ITEM_COPY
@ -1145,7 +1170,7 @@ end virtual
jnz .no_forward jnz .no_forward
; 13e. Increment position/pointer to the chain and ; 13e. Increment position/pointer to the chain and
; continue the loop. ; continue the loop.
inc [.chain_start_pos+24] add [.chain_start_pos+24], ecx
mov [.chain_start_ptr+24], esi mov [.chain_start_ptr+24], esi
dec dword [esp] dec dword [esp]
jnz .copy_loop jnz .copy_loop
@ -1153,11 +1178,13 @@ end virtual
.no_forward: .no_forward:
; 13f. Call the lookup function without adding to the cache. ; 13f. Call the lookup function without adding to the cache.
; Update position/pointer with returned value. ; Update position/pointer with returned value.
; Note: for the last sector in the chain, ecx/esi may contain ; Note: for the last sector in the chain, edi/esi may contain
; garbage; we are not going to use them in this case. ; garbage; we are not going to use them in this case.
push edi
call cache_lookup_read call cache_lookup_read
mov [.chain_start_pos+24], ecx mov [.chain_start_pos+28], edi
mov [.chain_start_ptr+24], esi mov [.chain_start_ptr+28], esi
pop edi
dec dword [esp] dec dword [esp]
jnz .copy_loop jnz .copy_loop
.copy_done: .copy_done:
@ -1203,13 +1230,32 @@ endp
; is most useful example of a non-trivial adjustment. ; is most useful example of a non-trivial adjustment.
; esi = pointer to DISK structure ; esi = pointer to DISK structure
disk_init_cache: disk_init_cache:
; 1. Calculate the suggested cache size. ; 1. Verify sector size. The code requires it to be a power of 2 not less than 4.
; 1a. Get the size of free physical memory in pages. ; In the name of sanity check that sector size is not too small or too large.
bsf ecx, [esi+DISK.MediaInfo.SectorSize]
jz .invalid_sector_size
mov eax, 1
shl eax, cl
cmp eax, [esi+DISK.MediaInfo.SectorSize]
jnz .invalid_sector_size
cmp ecx, 6
jb .invalid_sector_size
cmp ecx, 14
jbe .normal_sector_size
.invalid_sector_size:
DEBUGF 1,'K : sector size %x is invalid\n',[esi+DISK.MediaInfo.SectorSize]
xor eax, eax
ret
.normal_sector_size:
mov [esi+DISK.SysCache.sector_size_log], ecx
mov [esi+DISK.AppCache.sector_size_log], ecx
; 2. Calculate the suggested cache size.
; 2a. Get the size of free physical memory in pages.
mov eax, [pg_data.pages_free] mov eax, [pg_data.pages_free]
; 1b. Use the value to calculate the size. ; 2b. Use the value to calculate the size.
shl eax, 12 - 5 ; 1/32 of it in bytes shl eax, 12 - 5 ; 1/32 of it in bytes
and eax, -8*4096 ; round down to the multiple of 8 pages and eax, -8*4096 ; round down to the multiple of 8 pages
; 1c. Force lower and upper limits. ; 2c. Force lower and upper limits.
cmp eax, 1024*1024 cmp eax, 1024*1024
jb @f jb @f
mov eax, 1024*1024 mov eax, 1024*1024
@ -1218,7 +1264,7 @@ disk_init_cache:
ja @f ja @f
mov eax, 128*1024 mov eax, 128*1024
@@: @@:
; 1d. Give a chance to the driver to adjust the size. ; 2d. Give a chance to the driver to adjust the size.
push eax push eax
mov al, DISKFUNC.adjust_cache_size mov al, DISKFUNC.adjust_cache_size
call disk_call_driver call disk_call_driver
@ -1226,16 +1272,16 @@ disk_init_cache:
mov [esi+DISK.cache_size], eax mov [esi+DISK.cache_size], eax
test eax, eax test eax, eax
jz .nocache jz .nocache
; 2. Allocate memory for the cache. ; 3. Allocate memory for the cache.
; 2a. Call the allocator. ; 3a. Call the allocator.
stdcall kernel_alloc, eax stdcall kernel_alloc, eax
test eax, eax test eax, eax
jnz @f jnz @f
; 2b. If it failed, say a message and return with eax = 0. ; 3b. If it failed, say a message and return with eax = 0.
dbgstr 'no memory for disk cache' dbgstr 'no memory for disk cache'
jmp .nothing jmp .nothing
@@: @@:
; 3. Fill two DISKCACHE structures. ; 4. Fill two DISKCACHE structures.
mov [esi+DISK.SysCache.pointer], eax mov [esi+DISK.SysCache.pointer], eax
lea ecx, [esi+DISK.CacheLock] lea ecx, [esi+DISK.CacheLock]
call mutex_init call mutex_init
@ -1252,9 +1298,7 @@ disk_init_cache:
mov [esi+DISK.AppCache.pointer], edx mov [esi+DISK.AppCache.pointer], edx
mov eax, [esi+DISK.SysCache.data_size] mov eax, [esi+DISK.SysCache.data_size]
push ebx call calculate_cache_slots
call calculate_for_hd64
pop ebx
add eax, [esi+DISK.SysCache.pointer] add eax, [esi+DISK.SysCache.pointer]
mov [esi+DISK.SysCache.data], eax mov [esi+DISK.SysCache.data], eax
mov [esi+DISK.SysCache.sad_size], ecx mov [esi+DISK.SysCache.sad_size], ecx
@ -1267,9 +1311,7 @@ disk_init_cache:
pop edi pop edi
mov eax, [esi+DISK.AppCache.data_size] mov eax, [esi+DISK.AppCache.data_size]
push ebx call calculate_cache_slots
call calculate_for_hd64
pop ebx
add eax, [esi+DISK.AppCache.pointer] add eax, [esi+DISK.AppCache.pointer]
mov [esi+DISK.AppCache.data], eax mov [esi+DISK.AppCache.data], eax
mov [esi+DISK.AppCache.sad_size], ecx mov [esi+DISK.AppCache.sad_size], ecx
@ -1281,9 +1323,9 @@ disk_init_cache:
rep stosd rep stosd
pop edi pop edi
; 4. Return with nonzero al. ; 5. Return with nonzero al.
mov al, 1 mov al, 1
; 5. Return. ; 6. Return.
.nothing: .nothing:
ret ret
; No caching is required for this driver. Zero cache pointers and return with ; No caching is required for this driver. Zero cache pointers and return with
@ -1294,18 +1336,16 @@ disk_init_cache:
mov al, 1 mov al, 1
ret ret
calculate_for_hd64: calculate_cache_slots:
push eax push eax
mov ebx, eax mov ecx, [esi+DISK.MediaInfo.SectorSize]
shr eax, 9 add ecx, sizeof.CACHE_ITEM
lea eax, [eax*3] xor edx, edx
shl eax, 2 div ecx
sub ebx, eax mov ecx, eax
shr ebx, 9 imul eax, [esi+DISK.MediaInfo.SectorSize]
mov ecx, ebx sub [esp], eax
shl ebx, 9
pop eax pop eax
sub eax, ebx
dec ecx dec ecx
ret ret

View File

@ -59,6 +59,8 @@ endp
;--------------------------------------------------------------------- ;---------------------------------------------------------------------
proc ext2_create_partition proc ext2_create_partition
push ebx push ebx
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .fail
mov eax, 2 ; Superblock starts at 1024-bytes. mov eax, 2 ; Superblock starts at 1024-bytes.
add ebx, 512 ; Get pointer to fs-specific buffer. add ebx, 512 ; Get pointer to fs-specific buffer.

View File

@ -154,6 +154,9 @@ fat_create_partition.return0:
xor eax, eax xor eax, eax
ret ret
fat_create_partition: fat_create_partition:
; sector size must be 512
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .return0
; bootsector must have been successfully read ; bootsector must have been successfully read
cmp dword [esp+4], 0 cmp dword [esp+4], 0
jnz .return0 jnz .return0

View File

@ -152,6 +152,8 @@ ntfs_test_bootsec:
ret ret
proc ntfs_create_partition proc ntfs_create_partition
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .nope
mov edx, dword [ebp+PARTITION.Length] mov edx, dword [ebp+PARTITION.Length]
cmp dword [esp+4], 0 cmp dword [esp+4], 0
jz .boot_read_ok jz .boot_read_ok

View File

@ -25,6 +25,8 @@ include 'xfs.inc'
; returns 0 (not XFS or invalid) / pointer to partition structure ; returns 0 (not XFS or invalid) / pointer to partition structure
xfs_create_partition: xfs_create_partition:
push ebx ecx edx esi edi push ebx ecx edx esi edi
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .error
cmp dword[ebx + xfs_sb.sb_magicnum], XFS_SB_MAGIC ; signature cmp dword[ebx + xfs_sb.sb_magicnum], XFS_SB_MAGIC ; signature
jne .error jne .error