forked from KolibriOS/kolibrios
merge trunk
git-svn-id: svn://kolibrios.org@2142 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
7df91a3195
commit
3c8db1907e
@ -5,6 +5,8 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
$Revision: 2140 $
|
||||||
|
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
; ================================= Constants =================================
|
; ================================= Constants =================================
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
@ -76,6 +78,11 @@ struct DISKFUNC
|
|||||||
; Note that read/write are called by the cache manager, so a driver should not
|
; Note that read/write are called by the cache manager, so a driver should not
|
||||||
; create a software cache. This function is implemented for flushing a hardware
|
; create a software cache. This function is implemented for flushing a hardware
|
||||||
; cache, if it exists.
|
; cache, if it exists.
|
||||||
|
.adjust_cache_size dd ?
|
||||||
|
; The pointer to the function which returns the cache size for this device.
|
||||||
|
; Optional, may be NULL.
|
||||||
|
; unsigned int adjust_cache_size(unsigned int suggested_size);
|
||||||
|
; Return value: 0 = disable cache, otherwise = used cache size in bytes.
|
||||||
ends
|
ends
|
||||||
|
|
||||||
; This structure holds an information about a media.
|
; This structure holds an information about a media.
|
||||||
@ -90,6 +97,20 @@ struct DISKMEDIAINFO
|
|||||||
; Size of the media in sectors.
|
; Size of the media in sectors.
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
; This structure represents disk cache. To follow the old implementation,
|
||||||
|
; there are two distinct caches for a disk, one for "system" data, other
|
||||||
|
; for "application" data.
|
||||||
|
struct DISKCACHE
|
||||||
|
.Lock MUTEX
|
||||||
|
; Lock to protect the cache.
|
||||||
|
; The following fields are inherited from data32.inc:cache_ideX.
|
||||||
|
.pointer rd 1
|
||||||
|
.data_size rd 1 ; not use
|
||||||
|
.data rd 1
|
||||||
|
.sad_size rd 1
|
||||||
|
.search_start rd 1
|
||||||
|
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.
|
||||||
; This structure is allocated by the kernel in the 'disk_add' function,
|
; This structure is allocated by the kernel in the 'disk_add' function,
|
||||||
; freed in the 'disk_dereference' function.
|
; freed in the 'disk_dereference' function.
|
||||||
@ -146,6 +167,11 @@ struct DISK
|
|||||||
; Number of partitions on this media.
|
; Number of partitions on this media.
|
||||||
.Partitions dd ?
|
.Partitions dd ?
|
||||||
; Pointer to array of .NumPartitions pointers to PARTITION structures.
|
; Pointer to array of .NumPartitions pointers to PARTITION structures.
|
||||||
|
.cache_size dd ?
|
||||||
|
; inherited from cache_ideX_size
|
||||||
|
.SysCache DISKCACHE
|
||||||
|
.AppCache DISKCACHE
|
||||||
|
; Two caches for the disk.
|
||||||
ends
|
ends
|
||||||
|
|
||||||
; This structure represents one partition for the kernel. This is a base
|
; This structure represents one partition for the kernel. This is a base
|
||||||
@ -156,6 +182,8 @@ struct PARTITION
|
|||||||
; First sector of the partition.
|
; First sector of the partition.
|
||||||
.Length dq ?
|
.Length dq ?
|
||||||
; Length of the partition in sectors.
|
; Length of the partition in sectors.
|
||||||
|
.Disk dd ?
|
||||||
|
; Pointer to parent DISK structure.
|
||||||
.FSUserFunctions dd ?
|
.FSUserFunctions dd ?
|
||||||
; Handlers for the sysfunction 70h. This field is a pointer to the following
|
; Handlers for the sysfunction 70h. This field is a pointer to the following
|
||||||
; array. The first dword is a number of supported subfunctions, other dwords
|
; array. The first dword is a number of supported subfunctions, other dwords
|
||||||
@ -242,12 +270,13 @@ disk_list_mutex MUTEX
|
|||||||
endg
|
endg
|
||||||
|
|
||||||
iglobal
|
iglobal
|
||||||
; The function 'disk_scan_partitions' needs two 512-byte buffers for
|
; The function 'disk_scan_partitions' needs three 512-byte buffers for
|
||||||
; MBR and bootsectors data. It can not use the static buffers always,
|
; MBR, bootsector and fs-temporary sector data. It can not use the static
|
||||||
; since it can be called for two or more disks in parallel. However, this
|
; buffers always, since it can be called for two or more disks in parallel.
|
||||||
; case is not typical. We reserve two static 512-byte buffers and a flag
|
; However, this case is not typical. We reserve three static 512-byte buffers
|
||||||
; that these buffers are currently used. If 'disk_scan_partitions' detects that
|
; and a flag that these buffers are currently used. If 'disk_scan_partitions'
|
||||||
; the buffers are currently used, it allocates buffers from the heap.
|
; detects that the buffers are currently used, it allocates buffers from the
|
||||||
|
; heap.
|
||||||
; 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
|
||||||
@ -258,10 +287,11 @@ iglobal
|
|||||||
partition_buffer_users dd -1
|
partition_buffer_users dd -1
|
||||||
endg
|
endg
|
||||||
uglobal
|
uglobal
|
||||||
; The static buffers for MBR and bootsectors data.
|
; The static buffers for MBR, bootsector and fs-temporary sector data.
|
||||||
align 16
|
align 16
|
||||||
mbr_buffer rb 512
|
mbr_buffer rb 512
|
||||||
bootsect_buffer rb 512
|
bootsect_buffer rb 512
|
||||||
|
fs_tmp_buffer rb 512
|
||||||
endg
|
endg
|
||||||
|
|
||||||
iglobal
|
iglobal
|
||||||
@ -276,6 +306,7 @@ disk_default_callbacks:
|
|||||||
dd disk_default_read
|
dd disk_default_read
|
||||||
dd disk_default_write
|
dd disk_default_write
|
||||||
dd disk_default_flush
|
dd disk_default_flush
|
||||||
|
dd disk_default_adjust_cache_size
|
||||||
endg
|
endg
|
||||||
|
|
||||||
; =============================================================================
|
; =============================================================================
|
||||||
@ -312,45 +343,44 @@ disk_add:
|
|||||||
jz .nothing
|
jz .nothing
|
||||||
; 2. Copy disk name to the DISK structure.
|
; 2. Copy disk name to the DISK structure.
|
||||||
; 2a. Get length of the name, including the terminating zero.
|
; 2a. Get length of the name, including the terminating zero.
|
||||||
mov esi, [esp+8+8] ; esi = pointer to name
|
mov ebx, [esp+8+8] ; ebx = pointer to name
|
||||||
push eax ; save allocated pointer to DISK
|
push eax ; save allocated pointer to DISK
|
||||||
xor eax, eax ; the argument of malloc() is in eax
|
xor eax, eax ; the argument of malloc() is in eax
|
||||||
@@:
|
@@:
|
||||||
inc eax
|
inc eax
|
||||||
cmp byte [esi+eax-1], 0
|
cmp byte [ebx+eax-1], 0
|
||||||
jnz @b
|
jnz @b
|
||||||
; 2b. Call the heap manager.
|
; 2b. Call the heap manager.
|
||||||
call malloc
|
call malloc
|
||||||
; 2c. Check the result. If allocation failed, go to 7.
|
; 2c. Check the result. If allocation failed, go to 7.
|
||||||
pop ebx ; restore allocated pointer to DISK
|
pop esi ; restore allocated pointer to DISK
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .free
|
jz .free
|
||||||
; 2d. Store the allocated pointer to the DISK structure.
|
; 2d. Store the allocated pointer to the DISK structure.
|
||||||
mov [ebx+DISK.Name], eax
|
mov [esi+DISK.Name], eax
|
||||||
; 2e. Copy the name.
|
; 2e. Copy the name.
|
||||||
@@:
|
@@:
|
||||||
mov dl, [esi]
|
mov dl, [ebx]
|
||||||
mov [eax], dl
|
mov [eax], dl
|
||||||
inc esi
|
inc ebx
|
||||||
inc eax
|
inc eax
|
||||||
test dl, dl
|
test dl, dl
|
||||||
jnz @b
|
jnz @b
|
||||||
; 3. Copy other arguments of the function to the DISK structure.
|
; 3. Copy other arguments of the function to the DISK structure.
|
||||||
mov eax, [esp+4+8]
|
mov eax, [esp+4+8]
|
||||||
mov [ebx+DISK.Functions], eax
|
mov [esi+DISK.Functions], eax
|
||||||
mov eax, [esp+12+8]
|
mov eax, [esp+12+8]
|
||||||
mov [ebx+DISK.UserData], eax
|
mov [esi+DISK.UserData], eax
|
||||||
mov eax, [esp+16+8]
|
mov eax, [esp+16+8]
|
||||||
mov [ebx+DISK.DriverFlags], eax
|
mov [esi+DISK.DriverFlags], eax
|
||||||
; 4. Initialize other fields of the DISK structure.
|
; 4. Initialize other fields of the DISK structure.
|
||||||
; Media is not inserted, initialized state of mutex is zero,
|
; Media is not inserted, reference counter is 1.
|
||||||
; reference counter is 1.
|
lea ecx, [esi+DISK.MediaLock]
|
||||||
lea ecx, [ebx+DISK.MediaLock]
|
|
||||||
call mutex_init
|
call mutex_init
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov dword [ebx+DISK.MediaInserted], eax
|
mov dword [esi+DISK.MediaInserted], eax
|
||||||
inc eax
|
inc eax
|
||||||
mov [ebx+DISK.RefCount], eax
|
mov [esi+DISK.RefCount], eax
|
||||||
; The DISK structure is initialized.
|
; The DISK structure is initialized.
|
||||||
; 5. Insert the new structure to the global list.
|
; 5. Insert the new structure to the global list.
|
||||||
; 5a. Acquire the mutex.
|
; 5a. Acquire the mutex.
|
||||||
@ -358,16 +388,16 @@ disk_add:
|
|||||||
call mutex_lock
|
call mutex_lock
|
||||||
; 5b. Insert item to the tail of double-linked list.
|
; 5b. Insert item to the tail of double-linked list.
|
||||||
mov edx, disk_list
|
mov edx, disk_list
|
||||||
list_add_tail ebx, edx ;ebx= new edx= list head
|
list_add_tail esi, edx ;esi= new edx= list head
|
||||||
; 5c. Release the mutex.
|
; 5c. Release the mutex.
|
||||||
call mutex_unlock
|
call mutex_unlock
|
||||||
; 6. Return with eax = pointer to DISK.
|
; 6. Return with eax = pointer to DISK.
|
||||||
xchg eax, ebx
|
xchg eax, esi
|
||||||
jmp .nothing
|
jmp .nothing
|
||||||
.free:
|
.free:
|
||||||
; Memory allocation for DISK structure succeeded, but for disk name failed.
|
; Memory allocation for DISK structure succeeded, but for disk name failed.
|
||||||
; 7. Free the DISK structure.
|
; 7. Free the DISK structure.
|
||||||
xchg eax, ebx
|
xchg eax, esi
|
||||||
call free
|
call free
|
||||||
; 8. Return with eax = 0.
|
; 8. Return with eax = 0.
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -474,10 +504,12 @@ lock dec [esi+DISK.MediaRefCount]
|
|||||||
jnz .freeloop
|
jnz .freeloop
|
||||||
.nofree:
|
.nofree:
|
||||||
pop edi esi
|
pop edi esi
|
||||||
; 3b. Call the driver.
|
; 3b. Free the cache.
|
||||||
|
call disk_free_cache
|
||||||
|
; 3c. Call the driver.
|
||||||
mov al, DISKFUNC.closemedia
|
mov al, DISKFUNC.closemedia
|
||||||
stdcall disk_call_driver
|
stdcall disk_call_driver
|
||||||
; 3c. Clear the flag.
|
; 3d. Clear the flag.
|
||||||
mov [esi+DISK.MediaUsed], 0
|
mov [esi+DISK.MediaUsed], 0
|
||||||
.nothing:
|
.nothing:
|
||||||
ret
|
ret
|
||||||
@ -525,12 +557,16 @@ disk_media_changed:
|
|||||||
; 3b. Check the result of the callback. Abort if it failed.
|
; 3b. Check the result of the callback. Abort if it failed.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .noinsert
|
jnz .noinsert
|
||||||
; 3c. Acquire the lifetime reference for the media object.
|
; 3c. Allocate the cache unless disabled by the driver. Abort if failed.
|
||||||
|
call disk_init_cache
|
||||||
|
test al, al
|
||||||
|
jz .noinsert
|
||||||
|
; 3d. Acquire the lifetime reference for the media object.
|
||||||
inc [esi+DISK.MediaRefCount]
|
inc [esi+DISK.MediaRefCount]
|
||||||
; 3d. Scan for partitions. Ignore result; the list of partitions is valid even
|
; 3e. Scan for partitions. Ignore result; the list of partitions is valid even
|
||||||
; on errors.
|
; on errors.
|
||||||
call disk_scan_partitions
|
call disk_scan_partitions
|
||||||
; 3e. Media is inserted and available for use.
|
; 3f. Media is inserted and available for use.
|
||||||
inc [esi+DISK.MediaInserted]
|
inc [esi+DISK.MediaInserted]
|
||||||
.noinsert:
|
.noinsert:
|
||||||
; 4. Return.
|
; 4. Return.
|
||||||
@ -586,6 +622,11 @@ disk_default_flush:
|
|||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret 4
|
ret 4
|
||||||
|
|
||||||
|
; The default implementation of DISKFUNC.adjust_cache_size.
|
||||||
|
disk_default_adjust_cache_size:
|
||||||
|
mov eax, [esp+4]
|
||||||
|
ret 4
|
||||||
|
|
||||||
; This is an internal function called from 'disk_media_changed' when new media
|
; This is an internal function called from 'disk_media_changed' when new media
|
||||||
; is detected. It creates the list of partitions for the media.
|
; is detected. It creates the list of partitions for the media.
|
||||||
; If media is not partitioned, then the list consists of one partition which
|
; If media is not partitioned, then the list consists of one partition which
|
||||||
@ -609,7 +650,7 @@ disk_scan_partitions:
|
|||||||
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, 1024
|
stdcall kernel_alloc, 512*3
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz .nothing
|
jz .nothing
|
||||||
xchg eax, ebx
|
xchg eax, ebx
|
||||||
@ -712,6 +753,7 @@ lock dec [partition_buffer_users] ; no, we must allocate
|
|||||||
; compatibility problems.
|
; compatibility problems.
|
||||||
pop eax ; load extended partition
|
pop eax ; load extended partition
|
||||||
add ebp, eax
|
add ebp, eax
|
||||||
|
jc .mbr_failed
|
||||||
; 12c. If extended partition has not yet started, start it.
|
; 12c. If extended partition has not yet started, start it.
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz @f
|
jnz @f
|
||||||
@ -849,7 +891,7 @@ proc disk_add_partition stdcall uses ebx edi, start:qword, length:qword
|
|||||||
; The range [.FirstSector, .FirstSector+.Length) must be either entirely to
|
; The range [.FirstSector, .FirstSector+.Length) must be either entirely to
|
||||||
; the left of [start, start+length) or entirely to the right.
|
; the left of [start, start+length) or entirely to the right.
|
||||||
; 2c. Subtract .FirstSector - start. The possible overflow distinguish between
|
; 2c. Subtract .FirstSector - start. The possible overflow distinguish between
|
||||||
; cases "to the left" (2?) and "to the right" (2d).
|
; cases "to the left" (2e) and "to the right" (2d).
|
||||||
mov eax, dword [ecx+PARTITION.FirstSector]
|
mov eax, dword [ecx+PARTITION.FirstSector]
|
||||||
mov edx, dword [ecx+PARTITION.FirstSector+4]
|
mov edx, dword [ecx+PARTITION.FirstSector+4]
|
||||||
sub eax, dword [start]
|
sub eax, dword [start]
|
592
kernel/branches/Kolibri-acpi/blkdev/disk_cache.inc
Normal file
592
kernel/branches/Kolibri-acpi/blkdev/disk_cache.inc
Normal file
@ -0,0 +1,592 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2011. All rights reserved. ;;
|
||||||
|
;; Distributed under terms of the GNU General Public License ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
$Revision: 2140 $
|
||||||
|
|
||||||
|
; This function is intended to replace the old 'hd_read' function when
|
||||||
|
; [hdd_appl_data] = 0, so its input/output parameters are the same, except
|
||||||
|
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
|
||||||
|
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
|
||||||
|
; eax is relative to partition start
|
||||||
|
; out: eax = error code; 0 = ok
|
||||||
|
fs_read32_sys:
|
||||||
|
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
|
||||||
|
; this request should be processed by hd_read.
|
||||||
|
cmp [ebp+PARTITION.Disk], 'old'
|
||||||
|
jnz @f
|
||||||
|
mov [hdd_appl_data], 0
|
||||||
|
call hd_read
|
||||||
|
mov [hdd_appl_data], 1 ; restore to default state
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
; In the normal case, save ecx, set ecx to SysCache and let the common part
|
||||||
|
; do its work.
|
||||||
|
push ecx
|
||||||
|
mov ecx, [ebp+PARTITION.Disk]
|
||||||
|
add ecx, DISK.SysCache
|
||||||
|
jmp fs_read32_common
|
||||||
|
|
||||||
|
; This function is intended to replace the old 'hd_read' function when
|
||||||
|
; [hdd_appl_data] = 1, so its input/output parameters are the same, except
|
||||||
|
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
|
||||||
|
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
|
||||||
|
; eax is relative to partition start
|
||||||
|
; out: eax = error code; 0 = ok
|
||||||
|
fs_read32_app:
|
||||||
|
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
|
||||||
|
; this request should be processed by hd_read.
|
||||||
|
cmp [ebp+PARTITION.Disk], 'old'
|
||||||
|
jnz @f
|
||||||
|
mov [hdd_appl_data], 1
|
||||||
|
jmp hd_read
|
||||||
|
@@:
|
||||||
|
; In the normal case, save ecx, set ecx to AppCache and let the common part
|
||||||
|
; do its work.
|
||||||
|
push ecx
|
||||||
|
mov ecx, [ebp+PARTITION.Disk]
|
||||||
|
add ecx, DISK.AppCache
|
||||||
|
|
||||||
|
; This label is the common part of fs_read32_sys and fs_read32_app.
|
||||||
|
fs_read32_common:
|
||||||
|
; 1. Check that the required sector is inside the partition. If no, return
|
||||||
|
; DISK_STATUS_END_OF_MEDIA.
|
||||||
|
cmp dword [ebp+PARTITION.Length+4], 0
|
||||||
|
jnz @f
|
||||||
|
cmp dword [ebp+PARTITION.Length], eax
|
||||||
|
ja @f
|
||||||
|
mov eax, DISK_STATUS_END_OF_MEDIA
|
||||||
|
pop ecx
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
; 2. Get the absolute sector on the disk.
|
||||||
|
push edx
|
||||||
|
xor edx, edx
|
||||||
|
add eax, dword [ebp+PARTITION.FirstSector]
|
||||||
|
adc edx, dword [ebp+PARTITION.FirstSector+4]
|
||||||
|
; 3. If there is no cache for this disk, just pass the request to the driver.
|
||||||
|
cmp [ecx+DISKCACHE.pointer], 0
|
||||||
|
jnz .scancache
|
||||||
|
push 1
|
||||||
|
push esp ; numsectors
|
||||||
|
push edx ; startsector
|
||||||
|
push eax ; startsector
|
||||||
|
push ebx ; buffer
|
||||||
|
mov al, DISKFUNC.read
|
||||||
|
call disk_call_driver
|
||||||
|
pop ecx
|
||||||
|
pop edx
|
||||||
|
pop ecx
|
||||||
|
ret
|
||||||
|
.scancache:
|
||||||
|
; 4. Scan the cache.
|
||||||
|
push esi edi ecx ; scan cache
|
||||||
|
push edx eax
|
||||||
|
virtual at esp
|
||||||
|
.sector_lo dd ?
|
||||||
|
.sector_hi dd ?
|
||||||
|
.cache dd ?
|
||||||
|
end virtual
|
||||||
|
; The following code is inherited from hd_read. The differences are:
|
||||||
|
; all code is protected by the cache lock; instead of static calls
|
||||||
|
; to hd_read_dma/hd_read_pio/bd_read the dynamic call to DISKFUNC.read is used;
|
||||||
|
; sector is 64-bit, not 32-bit.
|
||||||
|
call mutex_lock
|
||||||
|
mov eax, [.sector_lo]
|
||||||
|
mov edx, [.sector_hi]
|
||||||
|
mov esi, [ecx+DISKCACHE.pointer]
|
||||||
|
mov ecx, [ecx+DISKCACHE.sad_size]
|
||||||
|
add esi, 12
|
||||||
|
|
||||||
|
mov edi, 1
|
||||||
|
|
||||||
|
.hdreadcache:
|
||||||
|
|
||||||
|
cmp dword [esi+8], 0 ; empty
|
||||||
|
je .nohdcache
|
||||||
|
|
||||||
|
cmp [esi], eax ; correct sector
|
||||||
|
jne .nohdcache
|
||||||
|
cmp [esi+4], edx ; correct sector
|
||||||
|
je .yeshdcache
|
||||||
|
|
||||||
|
.nohdcache:
|
||||||
|
|
||||||
|
add esi, 12
|
||||||
|
inc edi
|
||||||
|
dec ecx
|
||||||
|
jnz .hdreadcache
|
||||||
|
|
||||||
|
mov esi, [.cache]
|
||||||
|
call find_empty_slot64 ; ret in edi
|
||||||
|
test eax, eax
|
||||||
|
jnz .read_done
|
||||||
|
|
||||||
|
push 1
|
||||||
|
push esp
|
||||||
|
push edx
|
||||||
|
push [.sector_lo+12]
|
||||||
|
mov ecx, [.cache]
|
||||||
|
mov eax, edi
|
||||||
|
shl eax, 9
|
||||||
|
add eax, [ecx+DISKCACHE.data]
|
||||||
|
push eax
|
||||||
|
mov esi, [ebp+PARTITION.Disk]
|
||||||
|
mov al, DISKFUNC.read
|
||||||
|
call disk_call_driver
|
||||||
|
pop ecx
|
||||||
|
dec ecx
|
||||||
|
jnz .read_done
|
||||||
|
|
||||||
|
mov ecx, [.cache]
|
||||||
|
lea eax, [edi*3]
|
||||||
|
mov esi, [ecx+DISKCACHE.pointer]
|
||||||
|
lea esi, [eax*4+esi]
|
||||||
|
|
||||||
|
mov eax, [.sector_lo]
|
||||||
|
mov edx, [.sector_hi]
|
||||||
|
mov [esi], eax ; sector number
|
||||||
|
mov [esi+4], edx ; sector number
|
||||||
|
mov dword [esi+8], 1; hd read - mark as same as in hd
|
||||||
|
|
||||||
|
.yeshdcache:
|
||||||
|
|
||||||
|
mov esi, edi
|
||||||
|
mov ecx, [.cache]
|
||||||
|
shl esi, 9
|
||||||
|
add esi, [ecx+DISKCACHE.data]
|
||||||
|
|
||||||
|
mov edi, ebx
|
||||||
|
mov ecx, 512/4
|
||||||
|
rep movsd ; move data
|
||||||
|
xor eax, eax ; successful read
|
||||||
|
.read_done:
|
||||||
|
mov ecx, [.cache]
|
||||||
|
push eax
|
||||||
|
call mutex_unlock
|
||||||
|
pop eax
|
||||||
|
add esp, 12
|
||||||
|
pop edi esi edx ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
; This function is intended to replace the old 'hd_write' function when
|
||||||
|
; [hdd_appl_data] = 0, so its input/output parameters are the same, except
|
||||||
|
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
|
||||||
|
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
|
||||||
|
; eax is relative to partition start
|
||||||
|
; out: eax = error code; 0 = ok
|
||||||
|
fs_write32_sys:
|
||||||
|
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
|
||||||
|
; this request should be processed by hd_write.
|
||||||
|
cmp [ebp+PARTITION.Disk], 'old'
|
||||||
|
jnz @f
|
||||||
|
mov [hdd_appl_data], 0
|
||||||
|
call hd_write
|
||||||
|
mov [hdd_appl_data], 1 ; restore to default state
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
; In the normal case, save ecx, set ecx to SysCache and let the common part
|
||||||
|
; do its work.
|
||||||
|
push ecx
|
||||||
|
mov ecx, [ebp+PARTITION.Disk]
|
||||||
|
add ecx, DISK.SysCache
|
||||||
|
jmp fs_write32_common
|
||||||
|
|
||||||
|
; This function is intended to replace the old 'hd_write' function when
|
||||||
|
; [hdd_appl_data] = 1, so its input/output parameters are the same, except
|
||||||
|
; that it can't use the global variables 'hd_error' and 'hdd_appl_data'.
|
||||||
|
; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure
|
||||||
|
; eax is relative to partition start
|
||||||
|
; out: eax = error code; 0 = ok
|
||||||
|
fs_write32_app:
|
||||||
|
; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure,
|
||||||
|
; this request should be processed by hd_write.
|
||||||
|
cmp [ebp+PARTITION.Disk], 'old'
|
||||||
|
jnz @f
|
||||||
|
mov [hdd_appl_data], 1
|
||||||
|
jmp hd_write
|
||||||
|
@@:
|
||||||
|
; In the normal case, save ecx, set ecx to AppCache and let the common part
|
||||||
|
; do its work.
|
||||||
|
push ecx
|
||||||
|
mov ecx, [ebp+PARTITION.Disk]
|
||||||
|
add ecx, DISK.AppCache
|
||||||
|
|
||||||
|
; This label is the common part of fs_read32_sys and fs_read32_app.
|
||||||
|
fs_write32_common:
|
||||||
|
; 1. Check that the required sector is inside the partition. If no, return
|
||||||
|
; DISK_STATUS_END_OF_MEDIA.
|
||||||
|
cmp dword [ebp+PARTITION.Length+4], 0
|
||||||
|
jnz @f
|
||||||
|
cmp dword [ebp+PARTITION.Length], eax
|
||||||
|
ja @f
|
||||||
|
mov eax, DISK_STATUS_END_OF_MEDIA
|
||||||
|
pop ecx
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
|
push edx
|
||||||
|
; 2. Get the absolute sector on the disk.
|
||||||
|
xor edx, edx
|
||||||
|
add eax, dword [ebp+PARTITION.FirstSector]
|
||||||
|
adc edx, dword [ebp+PARTITION.FirstSector+4]
|
||||||
|
; 3. If there is no cache for this disk, just pass request to the driver.
|
||||||
|
cmp [ecx+DISKCACHE.pointer], 0
|
||||||
|
jnz .scancache
|
||||||
|
push 1
|
||||||
|
push esp ; numsectors
|
||||||
|
push edx ; startsector
|
||||||
|
push eax ; startsector
|
||||||
|
push ebx ; buffer
|
||||||
|
mov al, DISKFUNC.write
|
||||||
|
call disk_call_driver
|
||||||
|
pop ecx
|
||||||
|
pop edx
|
||||||
|
pop ecx
|
||||||
|
ret
|
||||||
|
.scancache:
|
||||||
|
; 4. Scan the cache.
|
||||||
|
push esi edi ecx ; scan cache
|
||||||
|
push edx eax
|
||||||
|
virtual at esp
|
||||||
|
.sector_lo dd ?
|
||||||
|
.sector_hi dd ?
|
||||||
|
.cache dd ?
|
||||||
|
end virtual
|
||||||
|
; The following code is inherited from hd_write. The differences are:
|
||||||
|
; all code is protected by the cache lock;
|
||||||
|
; sector is 64-bit, not 32-bit.
|
||||||
|
call mutex_lock
|
||||||
|
|
||||||
|
; check if the cache already has the sector and overwrite it
|
||||||
|
mov eax, [.sector_lo]
|
||||||
|
mov edx, [.sector_hi]
|
||||||
|
mov esi, [ecx+DISKCACHE.pointer]
|
||||||
|
mov ecx, [ecx+DISKCACHE.sad_size]
|
||||||
|
add esi, 12
|
||||||
|
|
||||||
|
mov edi, 1
|
||||||
|
|
||||||
|
.hdwritecache:
|
||||||
|
cmp dword [esi+8], 0 ; if cache slot is empty
|
||||||
|
je .not_in_cache_write
|
||||||
|
|
||||||
|
cmp [esi], eax ; if the slot has the sector
|
||||||
|
jne .not_in_cache_write
|
||||||
|
cmp [esi+4], edx ; if the slot has the sector
|
||||||
|
je .yes_in_cache_write
|
||||||
|
|
||||||
|
.not_in_cache_write:
|
||||||
|
|
||||||
|
add esi, 12
|
||||||
|
inc edi
|
||||||
|
dec ecx
|
||||||
|
jnz .hdwritecache
|
||||||
|
|
||||||
|
; sector not found in cache
|
||||||
|
; write the block to a new location
|
||||||
|
|
||||||
|
mov esi, [.cache]
|
||||||
|
call find_empty_slot64 ; ret in edi
|
||||||
|
test eax, eax
|
||||||
|
jne .hd_write_access_denied
|
||||||
|
|
||||||
|
mov ecx, [.cache]
|
||||||
|
lea eax, [edi*3]
|
||||||
|
mov esi, [ecx+DISKCACHE.pointer]
|
||||||
|
lea esi, [eax*4+esi]
|
||||||
|
|
||||||
|
mov eax, [.sector_lo]
|
||||||
|
mov edx, [.sector_hi]
|
||||||
|
mov [esi], eax ; sector number
|
||||||
|
mov [esi+4], edx ; sector number
|
||||||
|
|
||||||
|
.yes_in_cache_write:
|
||||||
|
|
||||||
|
mov dword [esi+4], 2 ; write - differs from hd
|
||||||
|
|
||||||
|
shl edi, 9
|
||||||
|
mov ecx, [.cache]
|
||||||
|
add edi, [ecx+DISKCACHE.data]
|
||||||
|
|
||||||
|
mov esi, ebx
|
||||||
|
mov ecx, 512/4
|
||||||
|
rep movsd ; move data
|
||||||
|
xor eax, eax ; success
|
||||||
|
.hd_write_access_denied:
|
||||||
|
mov ecx, [.cache]
|
||||||
|
push eax
|
||||||
|
call mutex_unlock
|
||||||
|
pop eax
|
||||||
|
add esp, 12
|
||||||
|
pop edi esi edx ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
; This internal function is called from fs_read32_* and fs_write32_*. It is the
|
||||||
|
; analogue of find_empty_slot for 64-bit sectors.
|
||||||
|
find_empty_slot64:
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
; find empty or read slot, flush cache if next 12.5% is used by write
|
||||||
|
; output : edi = cache slot
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
.search_again:
|
||||||
|
mov ecx, [esi+DISKCACHE.sad_size]
|
||||||
|
mov edi, [esi+DISKCACHE.search_start]
|
||||||
|
shr ecx, 3
|
||||||
|
.search_for_empty:
|
||||||
|
inc edi
|
||||||
|
cmp edi, [esi+DISKCACHE.sad_size]
|
||||||
|
jbe .inside_cache
|
||||||
|
mov edi, 1
|
||||||
|
.inside_cache:
|
||||||
|
lea eax, [edi*3]
|
||||||
|
shl eax, 2
|
||||||
|
add eax, [esi+DISKCACHE.pointer]
|
||||||
|
cmp dword [eax+8], 2
|
||||||
|
jb .found_slot ; it's empty or read
|
||||||
|
dec ecx
|
||||||
|
jnz .search_for_empty
|
||||||
|
call write_cache64 ; no empty slots found, write all
|
||||||
|
test eax, eax
|
||||||
|
jne .found_slot_access_denied
|
||||||
|
jmp .search_again ; and start again
|
||||||
|
.found_slot:
|
||||||
|
mov [esi+DISKCACHE.search_start], edi
|
||||||
|
xor eax, eax ; success
|
||||||
|
.found_slot_access_denied:
|
||||||
|
ret
|
||||||
|
|
||||||
|
; This function is intended to replace the old 'write_cache' function.
|
||||||
|
proc write_cache64 uses ecx edx esi edi
|
||||||
|
locals
|
||||||
|
cache_chain_started dd ?
|
||||||
|
cache_chain_size dd ?
|
||||||
|
cache_chain_pos dd ?
|
||||||
|
cache_chain_ptr dd ?
|
||||||
|
endl
|
||||||
|
; If there is no cache for this disk, nothing to do.
|
||||||
|
cmp [esi+DISKCACHE.pointer], 0
|
||||||
|
jz .flush
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
; write all changed sectors to disk
|
||||||
|
;-----------------------------------------------------------
|
||||||
|
|
||||||
|
; write difference ( 2 ) from cache to DISK
|
||||||
|
mov ecx, [esi+DISKCACHE.sad_size]
|
||||||
|
mov esi, [esi+DISKCACHE.pointer]
|
||||||
|
add esi, 12
|
||||||
|
mov edi, 1
|
||||||
|
.write_cache_more:
|
||||||
|
cmp dword [esi+8], 2 ; if cache slot is not different
|
||||||
|
jne .write_chain
|
||||||
|
mov dword [esi+8], 1 ; same as in hd
|
||||||
|
mov eax, [esi]
|
||||||
|
mov edx, [esi+4] ; edx:eax = sector to write
|
||||||
|
; Îáúåäèíÿåì çàïèñü öåïî÷êè ïîñëåäîâàòåëüíûõ ñåêòîðîâ â îäíî îáðàùåíèå ê äèñêó
|
||||||
|
cmp ecx, 1
|
||||||
|
jz .nonext
|
||||||
|
cmp dword [esi+12+8], 2
|
||||||
|
jnz .nonext
|
||||||
|
push eax edx
|
||||||
|
add eax, 1
|
||||||
|
adc edx, 0
|
||||||
|
cmp eax, [esi+12]
|
||||||
|
jnz @f
|
||||||
|
cmp edx, [esi+12+4]
|
||||||
|
@@:
|
||||||
|
pop edx eax
|
||||||
|
jnz .nonext
|
||||||
|
cmp [cache_chain_started], 1
|
||||||
|
jz @f
|
||||||
|
mov [cache_chain_started], 1
|
||||||
|
mov [cache_chain_size], 0
|
||||||
|
mov [cache_chain_pos], edi
|
||||||
|
mov [cache_chain_ptr], esi
|
||||||
|
@@:
|
||||||
|
inc [cache_chain_size]
|
||||||
|
cmp [cache_chain_size], 16
|
||||||
|
jnz .continue
|
||||||
|
jmp .write_chain
|
||||||
|
.nonext:
|
||||||
|
call .flush_cache_chain
|
||||||
|
test eax, eax
|
||||||
|
jnz .nothing
|
||||||
|
mov [cache_chain_size], 1
|
||||||
|
mov [cache_chain_ptr], esi
|
||||||
|
call .write_cache_sector
|
||||||
|
test eax, eax
|
||||||
|
jnz .nothing
|
||||||
|
jmp .continue
|
||||||
|
.write_chain:
|
||||||
|
call .flush_cache_chain
|
||||||
|
test eax, eax
|
||||||
|
jnz .nothing
|
||||||
|
.continue:
|
||||||
|
add esi, 12
|
||||||
|
inc edi
|
||||||
|
dec ecx
|
||||||
|
jnz .write_cache_more
|
||||||
|
call .flush_cache_chain
|
||||||
|
test eax, eax
|
||||||
|
jnz .nothing
|
||||||
|
.flush:
|
||||||
|
mov esi, [ebp]
|
||||||
|
mov esi, [esi+PARTITION.Disk]
|
||||||
|
mov al, DISKFUNC.flush
|
||||||
|
call disk_call_driver
|
||||||
|
.nothing:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.flush_cache_chain:
|
||||||
|
xor eax, eax
|
||||||
|
cmp [cache_chain_started], eax
|
||||||
|
jz @f
|
||||||
|
call .write_cache_chain
|
||||||
|
mov [cache_chain_started], 0
|
||||||
|
@@:
|
||||||
|
retn
|
||||||
|
|
||||||
|
.write_cache_sector:
|
||||||
|
mov [cache_chain_size], 1
|
||||||
|
mov [cache_chain_pos], edi
|
||||||
|
.write_cache_chain:
|
||||||
|
pusha
|
||||||
|
mov edi, [cache_chain_pos]
|
||||||
|
mov ecx, [ebp-12]
|
||||||
|
shl edi, 9
|
||||||
|
add edi, [ecx+DISKCACHE.data]
|
||||||
|
mov ecx, [cache_chain_size]
|
||||||
|
push ecx
|
||||||
|
push esp ; numsectors
|
||||||
|
mov eax, [cache_chain_ptr]
|
||||||
|
pushd [eax+4]
|
||||||
|
pushd [eax] ; startsector
|
||||||
|
push edi ; buffer
|
||||||
|
mov esi, [ebp]
|
||||||
|
mov esi, [esi+PARTITION.Disk]
|
||||||
|
mov al, DISKFUNC.write
|
||||||
|
call disk_call_driver
|
||||||
|
pop ecx
|
||||||
|
mov [esp+28], eax
|
||||||
|
popa
|
||||||
|
retn
|
||||||
|
endp
|
||||||
|
|
||||||
|
; This internal function is called from disk_add to initialize the caching for
|
||||||
|
; a new DISK.
|
||||||
|
; The algorithm is inherited from getcache.inc: take 1/32 part of the available
|
||||||
|
; physical memory, round down to 8 pages, limit by 128K from below and by 1M
|
||||||
|
; from above. Reserve 1/8 part of the cache for system data and 7/8 for app
|
||||||
|
; data.
|
||||||
|
; After the size is calculated, but before the cache is allocated, the device
|
||||||
|
; driver can adjust the size. In particular, setting size to zero disables
|
||||||
|
; caching: there is no sense in a cache for a ramdisk. In fact, such action
|
||||||
|
; is most useful example of a non-trivial adjustment.
|
||||||
|
; esi = pointer to DISK structure
|
||||||
|
disk_init_cache:
|
||||||
|
; 1. Calculate the suggested cache size.
|
||||||
|
; 1a. Get the size of free physical memory in pages.
|
||||||
|
mov eax, [pg_data.pages_free]
|
||||||
|
; 1b. Use the value to calculate the size.
|
||||||
|
shl eax, 12 - 5 ; 1/32 of it in bytes
|
||||||
|
and eax, -8*4096 ; round down to the multiple of 8 pages
|
||||||
|
; 1c. Force lower and upper limits.
|
||||||
|
cmp eax, 1024*1024
|
||||||
|
jb @f
|
||||||
|
mov eax, 1024*1024
|
||||||
|
@@:
|
||||||
|
cmp eax, 128*1024
|
||||||
|
ja @f
|
||||||
|
mov eax, 128*1024
|
||||||
|
@@:
|
||||||
|
; 1d. Give a chance to the driver to adjust the size.
|
||||||
|
push eax
|
||||||
|
mov al, DISKFUNC.adjust_cache_size
|
||||||
|
call disk_call_driver
|
||||||
|
; Cache size calculated.
|
||||||
|
mov [esi+DISK.cache_size], eax
|
||||||
|
test eax, eax
|
||||||
|
jz .nocache
|
||||||
|
; 2. Allocate memory for the cache.
|
||||||
|
; 2a. Call the allocator.
|
||||||
|
stdcall kernel_alloc, eax
|
||||||
|
test eax, eax
|
||||||
|
jnz @f
|
||||||
|
; 2b. If it failed, say a message and return with eax = 0.
|
||||||
|
dbgstr 'no memory for disk cache'
|
||||||
|
jmp .nothing
|
||||||
|
@@:
|
||||||
|
; 3. Fill two DISKCACHE structures.
|
||||||
|
mov [esi+DISK.SysCache.pointer], eax
|
||||||
|
lea ecx, [esi+DISK.SysCache.Lock]
|
||||||
|
call mutex_init
|
||||||
|
lea ecx, [esi+DISK.AppCache.Lock]
|
||||||
|
call mutex_init
|
||||||
|
; The following code is inherited from getcache.inc.
|
||||||
|
mov edx, [esi+DISK.SysCache.pointer]
|
||||||
|
and [esi+DISK.SysCache.search_start], 0
|
||||||
|
and [esi+DISK.AppCache.search_start], 0
|
||||||
|
mov eax, [esi+DISK.cache_size]
|
||||||
|
shr eax, 3
|
||||||
|
mov [esi+DISK.SysCache.data_size], eax
|
||||||
|
add edx, eax
|
||||||
|
imul eax, 7
|
||||||
|
mov [esi+DISK.AppCache.data_size], eax
|
||||||
|
mov [esi+DISK.AppCache.pointer], edx
|
||||||
|
|
||||||
|
mov eax, [esi+DISK.SysCache.data_size]
|
||||||
|
push ebx
|
||||||
|
call calculate_for_hd
|
||||||
|
pop ebx
|
||||||
|
add eax, [esi+DISK.SysCache.pointer]
|
||||||
|
mov [esi+DISK.SysCache.data], eax
|
||||||
|
mov [esi+DISK.SysCache.sad_size], ecx
|
||||||
|
|
||||||
|
push edi
|
||||||
|
mov edi, [esi+DISK.SysCache.pointer]
|
||||||
|
lea ecx, [ecx*3]
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd
|
||||||
|
pop edi
|
||||||
|
|
||||||
|
mov eax, [esi+DISK.AppCache.data_size]
|
||||||
|
push ebx
|
||||||
|
call calculate_for_hd
|
||||||
|
pop ebx
|
||||||
|
add eax, [esi+DISK.AppCache.pointer]
|
||||||
|
mov [esi+DISK.AppCache.data], eax
|
||||||
|
mov [esi+DISK.AppCache.sad_size], ecx
|
||||||
|
|
||||||
|
push edi
|
||||||
|
mov edi, [esi+DISK.AppCache.pointer]
|
||||||
|
lea ecx, [ecx*3]
|
||||||
|
xor eax, eax
|
||||||
|
rep stosd
|
||||||
|
pop edi
|
||||||
|
|
||||||
|
; 4. Return with nonzero al.
|
||||||
|
mov al, 1
|
||||||
|
; 5. Return.
|
||||||
|
.nothing:
|
||||||
|
ret
|
||||||
|
; No caching is required for this driver. Zero cache pointers and return with
|
||||||
|
; nonzero al.
|
||||||
|
.nocache:
|
||||||
|
mov [esi+DISK.SysCache.pointer], eax
|
||||||
|
mov [esi+DISK.AppCache.pointer], eax
|
||||||
|
mov al, 1
|
||||||
|
ret
|
||||||
|
|
||||||
|
; This internal function is called from disk_media_dereference to free the
|
||||||
|
; allocated cache, if there is one.
|
||||||
|
; esi = pointer to DISK structure
|
||||||
|
disk_free_cache:
|
||||||
|
; The algorithm is straightforward.
|
||||||
|
mov eax, [esi+DISK.SysCache.pointer]
|
||||||
|
test eax, eax
|
||||||
|
jz .nothing
|
||||||
|
stdcall kernel_free, eax
|
||||||
|
.nothing:
|
||||||
|
ret
|
302
kernel/branches/Kolibri-acpi/boot/boot_fat12.asm
Normal file
302
kernel/branches/Kolibri-acpi/boot/boot_fat12.asm
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
; FAT12 boot sector for Kolibri OS
|
||||||
|
;
|
||||||
|
; Copyright (C) Alex Nogueira Teixeira
|
||||||
|
; Copyright (C) Diamond
|
||||||
|
; Copyright (C) Dmitry Kartashov aka shurf
|
||||||
|
;
|
||||||
|
; Distributed under GPL, see file COPYING for details
|
||||||
|
;
|
||||||
|
; Version 1.0
|
||||||
|
|
||||||
|
lf equ 0ah
|
||||||
|
cr equ 0dh
|
||||||
|
|
||||||
|
pos_read_tmp equ 0700h ;position for temporary read
|
||||||
|
boot_program equ 07c00h ;position for boot code
|
||||||
|
seg_read_kernel equ 01000h ;segment to kernel read
|
||||||
|
|
||||||
|
jmp start_program
|
||||||
|
nop
|
||||||
|
|
||||||
|
; Boot Sector and BPB Structure
|
||||||
|
BS_OEMName db 'KOLIBRI ' ; db 8
|
||||||
|
BPB_BytsPerSec dw 512 ; bytes per sector
|
||||||
|
BPB_SecPerClus db 1 ; sectors per cluster
|
||||||
|
BPB_RsvdSecCnt dw 1 ; number of reserver sectors
|
||||||
|
BPB_NumFATs db 2 ; count of FAT data structures
|
||||||
|
BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors)
|
||||||
|
BPB_TotSec16 dw 2880 ; count of sectors on the volume (2880 for 1.44 mbytes disk)
|
||||||
|
BPB_Media db 0f0h ; f0 - used for removable media
|
||||||
|
BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT
|
||||||
|
BPB_SecPerTrk dw 18 ; sectors per track
|
||||||
|
BPB_NumHeads dw 2 ; number of heads
|
||||||
|
BPB_HiddSec dd 0 ; count of hidden sectors
|
||||||
|
BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535)
|
||||||
|
BS_DrvNum db 0 ; int 13h drive number
|
||||||
|
BS_Reserved db 0 ; reserved
|
||||||
|
BS_BootSig db 29h ; Extended boot signature
|
||||||
|
BS_VolID dd 0 ; Volume serial number
|
||||||
|
BS_VolLab db 'KOLIBRI ' ; Volume label (db 11)
|
||||||
|
BS_FilSysType db 'FAT12 ' ; file system type (db 8)
|
||||||
|
|
||||||
|
start_program:
|
||||||
|
|
||||||
|
xor ax,ax
|
||||||
|
mov ss,ax
|
||||||
|
mov sp,boot_program
|
||||||
|
push ss
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
; print loading string
|
||||||
|
mov si,loading+boot_program
|
||||||
|
loop_loading:
|
||||||
|
lodsb
|
||||||
|
or al,al
|
||||||
|
jz read_root_directory
|
||||||
|
mov ah,0eh
|
||||||
|
mov bx,7
|
||||||
|
int 10h
|
||||||
|
jmp loop_loading
|
||||||
|
|
||||||
|
read_root_directory:
|
||||||
|
push ss
|
||||||
|
pop es
|
||||||
|
|
||||||
|
; calculate some disk parameters
|
||||||
|
; - beginning sector of RootDir
|
||||||
|
mov ax,word [BPB_FATSz16+boot_program]
|
||||||
|
xor cx,cx
|
||||||
|
mov cl,byte [BPB_NumFATs+boot_program]
|
||||||
|
mul cx
|
||||||
|
add ax,word [BPB_RsvdSecCnt+boot_program]
|
||||||
|
mov word [FirstRootDirSecNum+boot_program],ax ; 19
|
||||||
|
mov si,ax
|
||||||
|
|
||||||
|
; - count of sectors in RootDir
|
||||||
|
mov bx,word [BPB_BytsPerSec+boot_program]
|
||||||
|
mov cl,5 ; divide ax by 32
|
||||||
|
shr bx,cl ; bx = directory entries per sector
|
||||||
|
mov ax,word [BPB_RootEntCnt+boot_program]
|
||||||
|
xor dx,dx
|
||||||
|
div bx
|
||||||
|
mov word [RootDirSecs+boot_program],ax ; 14
|
||||||
|
|
||||||
|
; - data start
|
||||||
|
add si,ax ; add beginning sector of RootDir and count sectors in RootDir
|
||||||
|
mov word [data_start+boot_program],si ; 33
|
||||||
|
; reading root directory
|
||||||
|
; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!!
|
||||||
|
mov ah,2 ; read
|
||||||
|
push ax
|
||||||
|
|
||||||
|
mov ax,word [FirstRootDirSecNum+boot_program]
|
||||||
|
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector)
|
||||||
|
pop ax
|
||||||
|
mov bx,pos_read_tmp ; es:bx read buffer
|
||||||
|
call read_sector
|
||||||
|
|
||||||
|
mov si,bx ; read buffer address: es:si
|
||||||
|
mov ax,[RootDirSecs+boot_program]
|
||||||
|
mul word [BPB_BytsPerSec+boot_program]
|
||||||
|
add ax,si ; AX = end of root dir. in buffer pos_read_tmp
|
||||||
|
|
||||||
|
; find kernel file in root directory
|
||||||
|
loop_find_dir_entry:
|
||||||
|
push si
|
||||||
|
mov cx,11
|
||||||
|
mov di,kernel_name+boot_program
|
||||||
|
rep cmpsb ; compare es:si and es:di, cx bytes long
|
||||||
|
pop si
|
||||||
|
je found_kernel_file
|
||||||
|
add si,32 ; next dir. entry
|
||||||
|
cmp si,ax ; end of directory
|
||||||
|
jb loop_find_dir_entry
|
||||||
|
|
||||||
|
file_error_message:
|
||||||
|
mov si,error_message+boot_program
|
||||||
|
|
||||||
|
loop_error_message:
|
||||||
|
lodsb
|
||||||
|
or al,al
|
||||||
|
jz freeze_pc
|
||||||
|
mov ah,0eh
|
||||||
|
mov bx,7
|
||||||
|
int 10h
|
||||||
|
jmp loop_error_message
|
||||||
|
|
||||||
|
freeze_pc:
|
||||||
|
jmp $ ; endless loop
|
||||||
|
|
||||||
|
; === KERNEL FOUND. LOADING... ===
|
||||||
|
|
||||||
|
found_kernel_file:
|
||||||
|
mov bp,[si+01ah] ; first cluster of kernel file
|
||||||
|
; <diamond>
|
||||||
|
mov [cluster1st+boot_program],bp ; starting cluster of kernel file
|
||||||
|
; <\diamond>
|
||||||
|
|
||||||
|
; reading first FAT table
|
||||||
|
mov ax,word [BPB_RsvdSecCnt+boot_program] ; begin first FAT abs sector number
|
||||||
|
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector)
|
||||||
|
mov bx,pos_read_tmp ; es:bx read position
|
||||||
|
mov ah,2 ; ah=2 (read)
|
||||||
|
mov al, byte [BPB_FATSz16+boot_program] ; FAT size in sectors (TODO: max 255 sectors)
|
||||||
|
call read_sector
|
||||||
|
jc file_error_message ; read error
|
||||||
|
|
||||||
|
mov ax,seg_read_kernel
|
||||||
|
mov es,ax
|
||||||
|
xor bx,bx ; es:bx = 1000h:0000h
|
||||||
|
|
||||||
|
|
||||||
|
; reading kernel file
|
||||||
|
loop_obtains_kernel_data:
|
||||||
|
; read one cluster of file
|
||||||
|
call obtain_cluster
|
||||||
|
jc file_error_message ; read error
|
||||||
|
|
||||||
|
; add one cluster length to segment:offset
|
||||||
|
push bx
|
||||||
|
mov bx,es
|
||||||
|
mov ax,word [BPB_BytsPerSec+boot_program] ;\
|
||||||
|
movsx cx,byte [BPB_SecPerClus+boot_program] ; | !!! TODO: !!!
|
||||||
|
mul cx ; | out this from loop !!!
|
||||||
|
shr ax,4 ;/
|
||||||
|
add bx,ax
|
||||||
|
mov es,bx
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
mov di,bp
|
||||||
|
shr di,1
|
||||||
|
pushf
|
||||||
|
add di,bp ; di = bp * 1.5
|
||||||
|
add di,pos_read_tmp
|
||||||
|
mov ax,[di] ; read next entry from FAT-chain
|
||||||
|
popf
|
||||||
|
jc move_4_right
|
||||||
|
and ax,0fffh
|
||||||
|
jmp verify_end_sector
|
||||||
|
move_4_right:
|
||||||
|
mov cl,4
|
||||||
|
shr ax,cl
|
||||||
|
verify_end_sector:
|
||||||
|
cmp ax,0ff8h ; last cluster
|
||||||
|
jae execute_kernel
|
||||||
|
mov bp,ax
|
||||||
|
jmp loop_obtains_kernel_data
|
||||||
|
|
||||||
|
execute_kernel:
|
||||||
|
; <diamond>
|
||||||
|
mov ax,'KL'
|
||||||
|
push 0
|
||||||
|
pop ds
|
||||||
|
mov si,loader_block+boot_program
|
||||||
|
; </diamond>
|
||||||
|
push word seg_read_kernel
|
||||||
|
push word 0
|
||||||
|
retf ; jmp far 1000:0000
|
||||||
|
|
||||||
|
|
||||||
|
;------------------------------------------
|
||||||
|
; loading cluster from file to es:bx
|
||||||
|
obtain_cluster:
|
||||||
|
; bp - cluster number to read
|
||||||
|
; carry = 0 -> read OK
|
||||||
|
; carry = 1 -> read ERROR
|
||||||
|
|
||||||
|
; print one dot
|
||||||
|
push bx
|
||||||
|
mov ax,0e2eh ; ah=0eh (teletype), al='.'
|
||||||
|
xor bh,bh
|
||||||
|
int 10h
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
writesec:
|
||||||
|
; convert cluster number to sector number
|
||||||
|
mov ax,bp ; data cluster to read
|
||||||
|
sub ax,2
|
||||||
|
xor dx,dx
|
||||||
|
mov dl,byte [BPB_SecPerClus+boot_program]
|
||||||
|
mul dx
|
||||||
|
add ax,word [data_start+boot_program]
|
||||||
|
|
||||||
|
call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector)
|
||||||
|
patchhere:
|
||||||
|
mov ah,2 ; ah=2 (read)
|
||||||
|
mov al,byte [BPB_SecPerClus+boot_program] ; al=(one cluster)
|
||||||
|
call read_sector
|
||||||
|
retn
|
||||||
|
;------------------------------------------
|
||||||
|
|
||||||
|
;------------------------------------------
|
||||||
|
; read sector from disk
|
||||||
|
read_sector:
|
||||||
|
push bp
|
||||||
|
mov bp,20 ; try 20 times
|
||||||
|
newread:
|
||||||
|
dec bp
|
||||||
|
jz file_error_message
|
||||||
|
push ax bx cx dx
|
||||||
|
int 13h
|
||||||
|
pop dx cx bx ax
|
||||||
|
jc newread
|
||||||
|
pop bp
|
||||||
|
retn
|
||||||
|
;------------------------------------------
|
||||||
|
; convert abs. sector number (AX) to BIOS T:H:S
|
||||||
|
; sector number = (abs.sector%BPB_SecPerTrk)+1
|
||||||
|
; pre.track number = (abs.sector/BPB_SecPerTrk)
|
||||||
|
; head number = pre.track number%BPB_NumHeads
|
||||||
|
; track number = pre.track number/BPB_NumHeads
|
||||||
|
; Return: cl - sector number
|
||||||
|
; ch - track number
|
||||||
|
; dl - drive number (0 = a:)
|
||||||
|
; dh - head number
|
||||||
|
conv_abs_to_THS:
|
||||||
|
push bx
|
||||||
|
mov bx,word [BPB_SecPerTrk+boot_program]
|
||||||
|
xor dx,dx
|
||||||
|
div bx
|
||||||
|
inc dx
|
||||||
|
mov cl, dl ; cl = sector number
|
||||||
|
mov bx,word [BPB_NumHeads+boot_program]
|
||||||
|
xor dx,dx
|
||||||
|
div bx
|
||||||
|
; !!!!!!! ax = track number, dx = head number
|
||||||
|
mov ch,al ; ch=track number
|
||||||
|
xchg dh,dl ; dh=head number
|
||||||
|
mov dl,0 ; dl=0 (drive 0 (a:))
|
||||||
|
pop bx
|
||||||
|
retn
|
||||||
|
;------------------------------------------
|
||||||
|
|
||||||
|
loading db cr,lf,'Starting system ',00h
|
||||||
|
error_message db 13,10
|
||||||
|
kernel_name db 'KERNEL MNT ?',cr,lf,00h
|
||||||
|
FirstRootDirSecNum dw ?
|
||||||
|
RootDirSecs dw ?
|
||||||
|
data_start dw ?
|
||||||
|
|
||||||
|
; <diamond>
|
||||||
|
write1st:
|
||||||
|
push cs
|
||||||
|
pop ds
|
||||||
|
mov byte [patchhere+1+boot_program], 3 ; change ah=2 to ah=3
|
||||||
|
mov bp,[cluster1st+boot_program]
|
||||||
|
push 1000h
|
||||||
|
pop es
|
||||||
|
xor bx,bx
|
||||||
|
call writesec
|
||||||
|
mov byte [patchhere+1+boot_program], 2 ; change back ah=3 to ah=2
|
||||||
|
retf
|
||||||
|
cluster1st dw ?
|
||||||
|
loader_block:
|
||||||
|
db 1
|
||||||
|
dw 0
|
||||||
|
dw write1st+boot_program
|
||||||
|
dw 0
|
||||||
|
; <\diamond>
|
||||||
|
|
||||||
|
times 0x1fe-$ db 00h
|
||||||
|
|
||||||
|
db 55h,0aah ;boot signature
|
@ -167,6 +167,13 @@ kernel_export:
|
|||||||
dd szStrchr , strchr
|
dd szStrchr , strchr
|
||||||
dd szStrrchr , strrchr
|
dd szStrrchr , strrchr
|
||||||
|
|
||||||
|
dd szDiskAdd , disk_add
|
||||||
|
dd szDiskDel , disk_del
|
||||||
|
dd szDiskMediaChanged, disk_media_changed
|
||||||
|
|
||||||
|
dd szTimerHS , timer_hs
|
||||||
|
dd szCancelTimerHS , cancel_timer_hs
|
||||||
|
|
||||||
exp_lfb:
|
exp_lfb:
|
||||||
dd szLFBAddress , 0
|
dd szLFBAddress , 0
|
||||||
dd 0 ;terminator, must be zero
|
dd 0 ;terminator, must be zero
|
||||||
|
@ -53,6 +53,10 @@ struc DISKFUNC
|
|||||||
; Flushes the hardware cache, if it exists. Note that a driver should not
|
; Flushes the hardware cache, if it exists. Note that a driver should not
|
||||||
; implement a software cache for read/write, since they are called from the
|
; implement a software cache for read/write, since they are called from the
|
||||||
; kernel cache manager.
|
; kernel cache manager.
|
||||||
|
.adjust_cache_size dd ?
|
||||||
|
; unsigned int adjust_cache_size(unsigned int suggested_size);
|
||||||
|
; Optional.
|
||||||
|
; Returns the cache size for this device in bytes. 0 = disable cache.
|
||||||
}
|
}
|
||||||
struc DISKMEDIAINFO
|
struc DISKMEDIAINFO
|
||||||
{
|
{
|
||||||
|
@ -432,3 +432,4 @@ proc test_cpu
|
|||||||
endp
|
endp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -905,8 +905,6 @@ first_app_found:
|
|||||||
push 1
|
push 1
|
||||||
pop dword [CURRENT_TASK] ; set OS task fisrt
|
pop dword [CURRENT_TASK] ; set OS task fisrt
|
||||||
|
|
||||||
; stdcall enable_irq, 1
|
|
||||||
|
|
||||||
; SET KEYBOARD PARAMETERS
|
; SET KEYBOARD PARAMETERS
|
||||||
mov al, 0xf6 ; reset keyboard, scan enabled
|
mov al, 0xf6 ; reset keyboard, scan enabled
|
||||||
call kb_write
|
call kb_write
|
||||||
@ -1048,6 +1046,7 @@ osloop:
|
|||||||
call checkidle
|
call checkidle
|
||||||
call check_fdd_motor_status
|
call check_fdd_motor_status
|
||||||
call check_ATAPI_device_event
|
call check_ATAPI_device_event
|
||||||
|
call check_timers
|
||||||
jmp osloop
|
jmp osloop
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
; ;
|
; ;
|
||||||
|
@ -235,7 +235,8 @@ include "gui/button.inc"
|
|||||||
|
|
||||||
; file system
|
; file system
|
||||||
|
|
||||||
include "fs/disk.inc" ; support for plug-n-play disks
|
include "blkdev/disk.inc" ; support for plug-n-play disks
|
||||||
|
include "blkdev/disk_cache.inc" ; caching for plug-n-play disks
|
||||||
include "fs/fs.inc" ; syscall
|
include "fs/fs.inc" ; syscall
|
||||||
include "fs/fat32.inc" ; read / write for fat32 filesystem
|
include "fs/fat32.inc" ; read / write for fat32 filesystem
|
||||||
include "fs/ntfs.inc" ; read / write for ntfs filesystem
|
include "fs/ntfs.inc" ; read / write for ntfs filesystem
|
||||||
|
Loading…
Reference in New Issue
Block a user