Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ; Callbacks which implement tmpdisk-specific disk functions for tmpdisk.asm.
  2.  
  3. ; The first argument of every callback is .userdata = userdata arg of AddDisk.
  4. ; For tmpdisk, .userdata is the disk id, one of 0,...,max_num_disks-1.
  5.  
  6. DISK_STATUS_OK              = 0 ; success
  7. DISK_STATUS_GENERAL_ERROR   = -1; if no other code is suitable
  8. DISK_STATUS_INVALID_CALL    = 1 ; invalid input parameters
  9. DISK_STATUS_NO_MEDIA        = 2 ; no media present
  10. DISK_STATUS_END_OF_MEDIA    = 3 ; end of media while reading/writing data
  11.  
  12. ; The last function that is called for the given disk. The kernel calls it when
  13. ; the kernel has finished all operations with the disk and it is safe to free
  14. ; all driver-specific data identified by 'userdata'.
  15. proc tmpdisk_close
  16.   virtual at esp+4
  17.     .userdata dd ?
  18.   end virtual
  19. ; Free the memory for disk and zero global variables.
  20.         mov     edx, [.userdata]
  21.         mov     [disk_sizes+edx*4], 0
  22.         xor     eax, eax
  23.         xchg    eax, [disk_pointers+edx*4]
  24.         stdcall KernelFree, eax
  25.         retn    4
  26. endp
  27.  
  28. struc DISKMEDIAINFO
  29. {
  30.   .flags      dd ?
  31. DISK_MEDIA_READONLY = 1
  32.   .sectorsize dd ?
  33.   .capacity   dq ?
  34. }
  35. virtual at 0
  36. DISKMEDIAINFO DISKMEDIAINFO
  37. end virtual
  38.  
  39. ; Returns information about disk media.
  40. proc tmpdisk_querymedia
  41.   virtual at esp+4
  42.     .userdata dd ?
  43.     .info dd ?
  44.   end virtual
  45. ; Media is always present, sector size is always 512 bytes,
  46. ; the size of disk in sectors is stored in a global variable.
  47.         mov     edx, [.userdata]
  48.         mov     ecx, [.info]
  49.         mov     [ecx+DISKMEDIAINFO.flags], 0
  50.         mov     [ecx+DISKMEDIAINFO.sectorsize], 512
  51.         mov     eax, [disk_sizes+edx*4]
  52.         mov     dword [ecx+DISKMEDIAINFO.capacity], eax
  53.         mov     dword [ecx+DISKMEDIAINFO.capacity+4], 0
  54. ; Return zero as an indicator of success.
  55.         xor     eax, eax
  56.         retn    8
  57. endp
  58.  
  59. ; Reads one or more sectors from the device.
  60. tmpdisk_read:
  61.         xor     edx, edx ; 0 = reading
  62.         jmp     tmpdisk_readwrite
  63.  
  64. ; Writes one or more sectors to the device.
  65. tmpdisk_write:
  66.         mov     dl, 1 ; 1 = writing
  67. ; Fall through to tmpdisk_readwrite.
  68.  
  69. ; Common procedure for reading and writing.
  70. ; dl = 0 for reading, dl = 1 for writing.
  71. ; Arguments of tmpdisk_read and tmpdisk_write are the same,
  72. ; they continue to be stack arguments of this procedure.
  73. proc tmpdisk_readwrite \
  74.   userdata:dword, \
  75.   buffer:dword, \
  76.   start_sector:qword, \
  77.   numsectors_ptr:dword
  78. ; 1. Save used registers to be stdcall.
  79.         push    esi edi
  80.         mov     esi, [userdata]
  81.         mov     edi, [numsectors_ptr]
  82. ; 1. Determine number of sectors to be transferred.
  83. ; This is either the requested number of sectors or number of sectors
  84. ; up to the disk boundary, depending of what is less.
  85.         xor     ecx, ecx
  86. ; 1a. Test whether [start_sector] is less than [disk_sizes] for selected disk.
  87. ; If so, calculate number of sectors between [start_sector] and [disk_sizes].
  88. ; Otherwise, the actual number of sectors is zero.
  89.         cmp     dword [start_sector+4], ecx
  90.         jnz     .got_number
  91.         mov     eax, [disk_sizes+esi*4]
  92.         sub     eax, dword [start_sector]
  93.         jbe     .got_number
  94. ; 1b. Get the requested number of sectors.
  95.         mov     ecx, [edi]
  96. ; 1c. If it is greater than number of sectors calculated in 1a, use the value
  97. ; from 1a.
  98.         cmp     ecx, eax
  99.         jb      .got_number
  100.         mov     ecx, eax
  101. .got_number:
  102. ; 2. Compare the actual number of sectors with requested. If they are
  103. ; equal, set eax (it will be the returned value) to zero. Otherwise,
  104. ; use DISK_STATUS_END_OF_MEDIA.
  105.         xor     eax, eax
  106.         cmp     ecx, [edi]
  107.         jz      @f
  108.         mov     al, DISK_STATUS_END_OF_MEDIA
  109. @@:
  110. ; 3. Store the actual number of sectors.
  111.         mov     [edi], ecx
  112. ; 4. Calculate source and destination addresses.
  113.         mov     edi, dword [start_sector]
  114.         shl     edi, 9
  115.         add     edi, [disk_pointers+esi*4]
  116.         mov     esi, [buffer]
  117. ; 5. Calculate number of dwords to be transferred.
  118.         shl     ecx, 9-2
  119. ; 6. Now esi = [buffer], edi = pointer inside disk.
  120. ; This is normal for write operations;
  121. ; exchange esi and edi for read operations.
  122.         test    dl, dl
  123.         jnz     @f
  124.         xchg    esi, edi
  125. @@:
  126. ; 7. Copy data.
  127.         rep movsd
  128. ; 8. Restore used registers to be stdcall and return.
  129. ; The value in eax was calculated in step 2.
  130.         pop     edi esi
  131.         ret
  132. endp
  133.  
  134. ; The kernel calls this function when initializing cache subsystem for
  135. ; the media. This call allows the driver to adjust the cache size.
  136. proc tmpdisk_adjust_cache_size
  137.   virtual at esp+4
  138.     .userdata dd ?
  139.     .suggested_size dd ?
  140.   end virtual
  141. ; Since tmpdisk does not need cache, just return 0.
  142.         xor     eax, eax
  143.         retn    8
  144. endp
  145.