Subversion Repositories Kolibri OS

Rev

Rev 3598 | Rev 5057 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2013. All rights reserved.      ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;; RAMDISK functions                                            ;;
  7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  8.  
  9. $Revision: 4273 $
  10.  
  11. iglobal
  12. align 4
  13. ramdisk_functions:
  14.         dd      .size
  15.         dd      0       ; no close() function
  16.         dd      0       ; no closemedia() function
  17.         dd      ramdisk_querymedia
  18.         dd      ramdisk_read
  19.         dd      ramdisk_write
  20.         dd      0       ; no flush() function
  21.         dd      ramdisk_adjust_cache_size
  22. .size = $ - ramdisk_functions
  23. endg
  24.  
  25. ; See memmap.inc.
  26. ; Currently size of memory allocated for the ramdisk is fixed.
  27. ; This should be revisited when/if memory map would become more dynamic.
  28. RAMDISK_CAPACITY = 2880 ; in sectors
  29.  
  30. iglobal
  31. align 4
  32. ramdisk_actual_size     dd      RAMDISK_CAPACITY
  33. endg
  34.  
  35. ; This function is called early in boot process.
  36. ; It creates filesystem /rd/1 based on raw image data loaded by somebody before
  37. ; to memory named as RAMDISK with max size RAMDISK_CAPACITY, may be less.
  38. proc ramdisk_init
  39. iglobal
  40. ramdisk_name    db      'rd',0
  41. endg
  42.         push    ebx esi ; save used registers to be stdcall
  43. ; 1. Register the device and the (always inserted) media in the disk subsystem.
  44.         stdcall disk_add, ramdisk_functions, ramdisk_name, 0, 0
  45.         test    eax, eax
  46.         jz      .fail
  47.         mov     ebx, eax
  48.         stdcall disk_media_changed, eax, 1
  49. ; 2. We don't know actual size of loaded image,
  50. ; so try to calculate it using partition structure,
  51. ; assuming that file systems fill the real size based on contents of the partition.
  52. ; 2a. Prepare for loop over partitions.
  53.         xor     ecx, ecx
  54.         xor     edx, edx
  55. ; 2b. Check that at least one partition was recognized.
  56.         cmp     [ebx+DISK.NumPartitions], ecx
  57.         jz      .fail
  58. ; 2c. Loop over partitions.
  59. .partitions:
  60. ; For every partition, set edx to maximum between edx and end of partition.
  61.         mov     esi, [ebx+DISK.Partitions]
  62.         mov     esi, [esi+ecx*4]
  63.         mov     eax, dword [esi+PARTITION.FirstSector]
  64.         add     eax, dword [esi+PARTITION.Length]
  65.         cmp     eax, edx
  66.         jb      @f
  67.         mov     edx, eax
  68. @@:
  69.         inc     ecx
  70.         cmp     ecx, [ebx+DISK.NumPartitions]
  71.         jb      .partitions
  72. ; 3. Reclaim unused memory, if any.
  73.         mov     [ramdisk_actual_size], edx
  74.         add     edx, 7  ; aligning up
  75.         shr     edx, 3  ; 512-byte sectors -> 4096-byte pages
  76.         mov     esi, RAMDISK_CAPACITY / 8       ; aligning down
  77.         sub     esi, edx
  78.         jbe     .no_reclaim
  79.         shl     edx, 12
  80.         add     edx, RAMDISK - OS_BASE
  81. @@:
  82.         mov     eax, edx
  83.         call    free_page
  84.         add     edx, 0x1000
  85.         dec     esi
  86.         jnz     @b
  87. .no_reclaim:
  88.         pop     esi ebx ; restore used registers to be stdcall
  89.         ret
  90. .fail:
  91.         dbgstr 'Failed to initialize ramdisk'
  92.         pop     esi ebx ; restore used registers to be stdcall
  93.         ret
  94. endp
  95.  
  96. ; Returns information about disk media.
  97. proc ramdisk_querymedia
  98.   virtual at esp+4
  99.     .userdata dd ?
  100.     .info dd ?
  101.   end virtual
  102. ; Media is always present, sector size is always 512 bytes.
  103.         mov     edx, [.userdata]
  104.         mov     ecx, [.info]
  105.         mov     [ecx+DISKMEDIAINFO.Flags], 0
  106.         mov     [ecx+DISKMEDIAINFO.SectorSize], 512
  107.         mov     eax, [ramdisk_actual_size]
  108.         mov     dword [ecx+DISKMEDIAINFO.Capacity], eax
  109.         mov     dword [ecx+DISKMEDIAINFO.Capacity+4], 0
  110. ; Return zero as an indicator of success.
  111.         xor     eax, eax
  112.         retn    8
  113. endp
  114.  
  115. ; Common procedure for reading and writing.
  116. ; operation = 0 for reading, operation = 1 for writing.
  117. ; Arguments of ramdisk_read and ramdisk_write are the same.
  118. macro ramdisk_read_write operation
  119. {
  120.         push    esi edi         ; save used registers to be stdcall
  121.         mov     esi, [userdata]
  122.         mov     edi, [numsectors_ptr]
  123. ; 1. Determine number of sectors to be transferred.
  124. ; This is either the requested number of sectors or number of sectors
  125. ; up to the disk boundary, depending of what is less.
  126.         xor     ecx, ecx
  127. ; 1a. Test whether [start_sector] is less than RAMDISK_CAPACITY.
  128. ; If so, calculate number of sectors between [start_sector] and RAMDISK_CAPACITY.
  129. ; Otherwise, the actual number of sectors is zero.
  130.         cmp     dword [start_sector+4], ecx
  131.         jnz     .got_number
  132.         mov     eax, [ramdisk_actual_size]
  133.         sub     eax, dword [start_sector]
  134.         jbe     .got_number
  135. ; 1b. Get the requested number of sectors.
  136.         mov     ecx, [edi]
  137. ; 1c. If it is greater than number of sectors calculated in 1a, use the value
  138. ; from 1a.
  139.         cmp     ecx, eax
  140.         jb      .got_number
  141.         mov     ecx, eax
  142. .got_number:
  143. ; 2. Compare the actual number of sectors with requested. If they are
  144. ; equal, set eax (it will be the returned value) to zero. Otherwise,
  145. ; use DISK_STATUS_END_OF_MEDIA.
  146.         xor     eax, eax
  147.         cmp     ecx, [edi]
  148.         jz      @f
  149.         mov     al, DISK_STATUS_END_OF_MEDIA
  150. @@:
  151. ; 3. Store the actual number of sectors.
  152.         mov     [edi], ecx
  153. ; 4. Calculate source and destination addresses.
  154. if operation = 0 ; reading?
  155.         mov     esi, dword [start_sector]
  156.         shl     esi, 9
  157.         add     esi, RAMDISK
  158.         mov     edi, [buffer]
  159. else ; writing?
  160.         mov     edi, dword [start_sector]
  161.         shl     edi, 9
  162.         add     edi, RAMDISK
  163.         mov     esi, [buffer]
  164. end if
  165. ; 5. Calculate number of dwords to be transferred.
  166.         shl     ecx, 9-2
  167. ; 6. Copy data.
  168.         rep movsd
  169. ; 7. Return. The value in eax was calculated in step 2.
  170.         pop     edi esi         ; restore used registers to be stdcall
  171. }
  172.  
  173. ; Reads one or more sectors from the device.
  174. proc ramdisk_read userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
  175.         ramdisk_read_write 0
  176.         ret
  177. endp
  178.  
  179. ; Writes one or more sectors to the device.
  180. proc ramdisk_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword
  181.         ramdisk_read_write 1
  182.         ret
  183. endp
  184.  
  185. ; The kernel calls this function when initializing cache subsystem for
  186. ; the media. This call allows the driver to adjust the cache size.
  187. proc ramdisk_adjust_cache_size
  188.   virtual at esp+4
  189.     .userdata dd ?
  190.     .suggested_size dd ?
  191.   end virtual
  192. ; Since ramdisk does not need cache, just return 0.
  193.         xor     eax, eax
  194.         retn    8
  195. endp
  196.