mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-12-24 23:56:49 +03:00
145 lines
4.8 KiB
PHP
145 lines
4.8 KiB
PHP
|
; Callbacks which implement tmpdisk-specific disk functions for tmpdisk.asm.
|
||
|
|
||
|
; The first argument of every callback is .userdata = userdata arg of AddDisk.
|
||
|
; For tmpdisk, .userdata is the disk id, one of 0,...,max_num_disks-1.
|
||
|
|
||
|
DISK_STATUS_OK = 0 ; success
|
||
|
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable
|
||
|
DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters
|
||
|
DISK_STATUS_NO_MEDIA = 2 ; no media present
|
||
|
DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data
|
||
|
|
||
|
; The last function that is called for the given disk. The kernel calls it when
|
||
|
; the kernel has finished all operations with the disk and it is safe to free
|
||
|
; all driver-specific data identified by 'userdata'.
|
||
|
proc tmpdisk_close
|
||
|
virtual at esp+4
|
||
|
.userdata dd ?
|
||
|
end virtual
|
||
|
; Free the memory for disk and zero global variables.
|
||
|
mov edx, [.userdata]
|
||
|
mov [disk_sizes+edx*4], 0
|
||
|
xor eax, eax
|
||
|
xchg eax, [disk_pointers+edx*4]
|
||
|
stdcall KernelFree, eax
|
||
|
retn 4
|
||
|
endp
|
||
|
|
||
|
struc DISKMEDIAINFO
|
||
|
{
|
||
|
.flags dd ?
|
||
|
DISK_MEDIA_READONLY = 1
|
||
|
.sectorsize dd ?
|
||
|
.capacity dq ?
|
||
|
}
|
||
|
virtual at 0
|
||
|
DISKMEDIAINFO DISKMEDIAINFO
|
||
|
end virtual
|
||
|
|
||
|
; Returns information about disk media.
|
||
|
proc tmpdisk_querymedia
|
||
|
virtual at esp+4
|
||
|
.userdata dd ?
|
||
|
.info dd ?
|
||
|
end virtual
|
||
|
; Media is always present, sector size is always 512 bytes,
|
||
|
; the size of disk in sectors is stored in a global variable.
|
||
|
mov edx, [.userdata]
|
||
|
mov ecx, [.info]
|
||
|
mov [ecx+DISKMEDIAINFO.flags], 0
|
||
|
mov [ecx+DISKMEDIAINFO.sectorsize], 512
|
||
|
mov eax, [disk_sizes+edx*4]
|
||
|
mov dword [ecx+DISKMEDIAINFO.capacity], eax
|
||
|
mov dword [ecx+DISKMEDIAINFO.capacity+4], 0
|
||
|
; Return zero as an indicator of success.
|
||
|
xor eax, eax
|
||
|
retn 8
|
||
|
endp
|
||
|
|
||
|
; Reads one or more sectors from the device.
|
||
|
tmpdisk_read:
|
||
|
xor edx, edx ; 0 = reading
|
||
|
jmp tmpdisk_readwrite
|
||
|
|
||
|
; Writes one or more sectors to the device.
|
||
|
tmpdisk_write:
|
||
|
mov dl, 1 ; 1 = writing
|
||
|
; Fall through to tmpdisk_readwrite.
|
||
|
|
||
|
; Common procedure for reading and writing.
|
||
|
; dl = 0 for reading, dl = 1 for writing.
|
||
|
; Arguments of tmpdisk_read and tmpdisk_write are the same,
|
||
|
; they continue to be stack arguments of this procedure.
|
||
|
proc tmpdisk_readwrite \
|
||
|
userdata:dword, \
|
||
|
buffer:dword, \
|
||
|
start_sector:qword, \
|
||
|
numsectors_ptr:dword
|
||
|
; 1. Save used registers to be stdcall.
|
||
|
push esi edi
|
||
|
mov esi, [userdata]
|
||
|
mov edi, [numsectors_ptr]
|
||
|
; 1. Determine number of sectors to be transferred.
|
||
|
; This is either the requested number of sectors or number of sectors
|
||
|
; up to the disk boundary, depending of what is less.
|
||
|
xor ecx, ecx
|
||
|
; 1a. Test whether [start_sector] is less than [disk_sizes] for selected disk.
|
||
|
; If so, calculate number of sectors between [start_sector] and [disk_sizes].
|
||
|
; Otherwise, the actual number of sectors is zero.
|
||
|
cmp dword [start_sector+4], ecx
|
||
|
jnz .got_number
|
||
|
mov eax, [disk_sizes+esi*4]
|
||
|
sub eax, dword [start_sector]
|
||
|
jbe .got_number
|
||
|
; 1b. Get the requested number of sectors.
|
||
|
mov ecx, [edi]
|
||
|
; 1c. If it is greater than number of sectors calculated in 1a, use the value
|
||
|
; from 1a.
|
||
|
cmp ecx, eax
|
||
|
jb .got_number
|
||
|
mov ecx, eax
|
||
|
.got_number:
|
||
|
; 2. Compare the actual number of sectors with requested. If they are
|
||
|
; equal, set eax (it will be the returned value) to zero. Otherwise,
|
||
|
; use DISK_STATUS_END_OF_MEDIA.
|
||
|
xor eax, eax
|
||
|
cmp ecx, [edi]
|
||
|
jz @f
|
||
|
mov al, DISK_STATUS_END_OF_MEDIA
|
||
|
@@:
|
||
|
; 3. Store the actual number of sectors.
|
||
|
mov [edi], ecx
|
||
|
; 4. Calculate source and destination addresses.
|
||
|
mov edi, dword [start_sector]
|
||
|
shl edi, 9
|
||
|
add edi, [disk_pointers+esi*4]
|
||
|
mov esi, [buffer]
|
||
|
; 5. Calculate number of dwords to be transferred.
|
||
|
shl ecx, 9-2
|
||
|
; 6. Now esi = [buffer], edi = pointer inside disk.
|
||
|
; This is normal for write operations;
|
||
|
; exchange esi and edi for read operations.
|
||
|
test dl, dl
|
||
|
jnz @f
|
||
|
xchg esi, edi
|
||
|
@@:
|
||
|
; 7. Copy data.
|
||
|
rep movsd
|
||
|
; 8. Restore used registers to be stdcall and return.
|
||
|
; The value in eax was calculated in step 2.
|
||
|
pop edi esi
|
||
|
ret
|
||
|
endp
|
||
|
|
||
|
; The kernel calls this function when initializing cache subsystem for
|
||
|
; the media. This call allows the driver to adjust the cache size.
|
||
|
proc tmpdisk_adjust_cache_size
|
||
|
virtual at esp+4
|
||
|
.userdata dd ?
|
||
|
.suggested_size dd ?
|
||
|
end virtual
|
||
|
; Since tmpdisk does not need cache, just return 0.
|
||
|
xor eax, eax
|
||
|
retn 8
|
||
|
endp
|