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