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] |
invoke 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 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |