Rev 3598 | Rev 5057 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2288 | clevermous | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
4273 | clevermous | 3 | ;; Copyright (C) KolibriOS team 2013. All rights reserved. ;; |
2288 | clevermous | 4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
||
6 | ;; RAMDISK functions ;; |
||
7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
8 | |||
9 | $Revision: 4273 $ |
||
10 | |||
4273 | clevermous | 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 |
||
2288 | clevermous | 24 | |
4273 | clevermous | 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 |
||
2288 | clevermous | 29 | |
4273 | clevermous | 30 | iglobal |
31 | align 4 |
||
32 | ramdisk_actual_size dd RAMDISK_CAPACITY |
||
2288 | clevermous | 33 | endg |
34 | |||
4273 | clevermous | 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 |
||
2288 | clevermous | 39 | iglobal |
4273 | clevermous | 40 | ramdisk_name db 'rd',0 |
2288 | clevermous | 41 | endg |
4273 | clevermous | 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. |
||
2288 | clevermous | 53 | xor ecx, ecx |
4273 | clevermous | 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 |
||
2288 | clevermous | 68 | @@: |
69 | inc ecx |
||
4273 | clevermous | 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 |
||
2288 | clevermous | 81 | @@: |
4273 | clevermous | 82 | mov eax, edx |
83 | call free_page |
||
84 | add edx, 0x1000 |
||
85 | dec esi |
||
2288 | clevermous | 86 | jnz @b |
4273 | clevermous | 87 | .no_reclaim: |
88 | pop esi ebx ; restore used registers to be stdcall |
||
2288 | clevermous | 89 | ret |
4273 | clevermous | 90 | .fail: |
91 | dbgstr 'Failed to initialize ramdisk' |
||
92 | pop esi ebx ; restore used registers to be stdcall |
||
2288 | clevermous | 93 | ret |
4273 | clevermous | 94 | endp |
2288 | clevermous | 95 | |
4273 | clevermous | 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. |
||
2288 | clevermous | 111 | xor eax, eax |
4273 | clevermous | 112 | retn 8 |
113 | endp |
||
2288 | clevermous | 114 | |
4273 | clevermous | 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. |
||
2288 | clevermous | 126 | xor ecx, ecx |
4273 | clevermous | 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. |
||
2288 | clevermous | 139 | cmp ecx, eax |
4273 | clevermous | 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. |
||
3525 | clevermous | 146 | xor eax, eax |
4273 | clevermous | 147 | cmp ecx, [edi] |
3525 | clevermous | 148 | jz @f |
4273 | clevermous | 149 | mov al, DISK_STATUS_END_OF_MEDIA |
3525 | clevermous | 150 | @@: |
4273 | clevermous | 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] |
||
2288 | clevermous | 161 | shl edi, 9 |
4273 | clevermous | 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. |
||
2288 | clevermous | 168 | rep movsd |
4273 | clevermous | 169 | ; 7. Return. The value in eax was calculated in step 2. |
170 | pop edi esi ; restore used registers to be stdcall |
||
171 | } |
||
2288 | clevermous | 172 | |
4273 | clevermous | 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 |
||
2288 | clevermous | 176 | ret |
4273 | clevermous | 177 | endp |
2288 | clevermous | 178 | |
4273 | clevermous | 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 |
||
2288 | clevermous | 182 | ret |
4273 | clevermous | 183 | endp |
2288 | clevermous | 184 | |
4273 | clevermous | 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. |
||
2288 | clevermous | 193 | xor eax, eax |
4273 | clevermous | 194 | retn 8 |
195 | endp |