forked from KolibriOS/kolibrios
driver for managing temporary memory-based disks
git-svn-id: svn://kolibrios.org@2644 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
144
kernel/trunk/drivers/tmpdisk_work.inc
Normal file
144
kernel/trunk/drivers/tmpdisk_work.inc
Normal file
@@ -0,0 +1,144 @@
|
||||
; 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
|
Reference in New Issue
Block a user