; 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