kolibrios/kernel/trunk/drivers/tmpdisk_work.inc
CleverMouse ccb3bac301 driver for managing temporary memory-based disks
git-svn-id: svn://kolibrios.org@2644 a494cfbc-eb01-0410-851d-a64ba20cac60
2012-04-23 09:23:53 +00:00

145 lines
4.7 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