Rev 5363 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5363 | Rev 8064 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2013-2015. 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: 5363 $ |
9 | $Revision: 8064 $ |
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 eax, eax |
|
48 | xor ecx, ecx |
49 | xor ecx, ecx |
49 | xor edx, edx |
50 | xor edx, edx |
50 | ; 2b. Check that at least one partition was recognized. |
51 | ; 2b. Check that at least one partition was recognized. |
51 | cmp [ebx+DISK.NumPartitions], ecx |
52 | cmp [ebx+DISK.NumPartitions], ecx |
52 | jz .fail |
53 | jz .fail |
53 | ; 2c. Loop over partitions. |
54 | ; 2c. Loop over partitions. |
54 | .partitions: |
55 | .partitions: |
55 | ; For every partition, set edx to maximum between edx and end of partition. |
56 | ; For every partition, set edx to maximum between edx and end of partition. |
56 | mov esi, [ebx+DISK.Partitions] |
57 | mov esi, [ebx+DISK.Partitions] |
57 | mov esi, [esi+ecx*4] |
58 | mov esi, [esi+ecx*4] |
58 | mov eax, dword [esi+PARTITION.FirstSector] |
59 | mov eax, dword [esi+PARTITION.FirstSector] |
59 | add eax, dword [esi+PARTITION.Length] |
60 | add eax, dword [esi+PARTITION.Length] |
60 | cmp eax, edx |
61 | cmp eax, edx |
61 | jb @f |
62 | jb @f |
62 | mov edx, eax |
63 | mov edx, eax |
63 | @@: |
64 | @@: |
64 | inc ecx |
65 | inc ecx |
65 | cmp ecx, [ebx+DISK.NumPartitions] |
66 | cmp ecx, [ebx+DISK.NumPartitions] |
66 | jb .partitions |
67 | jb .partitions |
67 | ; 3. Reclaim unused memory, if any. |
68 | ; 3. Reclaim unused memory, if any. |
68 | mov [ramdisk_actual_size], edx |
69 | mov [ramdisk_actual_size], edx |
69 | add edx, 7 ; aligning up |
70 | add edx, 7 ; aligning up |
70 | shr edx, 3 ; 512-byte sectors -> 4096-byte pages |
71 | shr edx, 3 ; 512-byte sectors -> 4096-byte pages |
71 | mov esi, RAMDISK_CAPACITY / 8 ; aligning down |
72 | mov esi, RAMDISK_CAPACITY / 8 ; aligning down |
72 | sub esi, edx |
73 | sub esi, edx |
73 | jbe .no_reclaim |
74 | jbe .no_reclaim |
74 | shl edx, 12 |
75 | shl edx, 12 |
75 | add edx, RAMDISK - OS_BASE |
76 | add edx, RAMDISK - OS_BASE |
76 | @@: |
77 | @@: |
77 | mov eax, edx |
78 | mov eax, edx |
78 | call free_page |
79 | call free_page |
79 | add edx, 0x1000 |
80 | add edx, 0x1000 |
80 | dec esi |
81 | dec esi |
81 | jnz @b |
82 | jnz @b |
82 | .no_reclaim: |
83 | .no_reclaim: |
- | 84 | mov eax, ebx |
|
83 | pop esi ebx ; restore used registers to be stdcall |
85 | pop esi ebx ; restore used registers to be stdcall |
84 | ret |
86 | ret |
85 | .fail: |
87 | .fail: |
86 | dbgstr 'Failed to initialize ramdisk' |
88 | dbgstr 'Failed to initialize ramdisk' |
87 | pop esi ebx ; restore used registers to be stdcall |
89 | pop esi ebx ; restore used registers to be stdcall |
88 | ret |
90 | ret |
89 | endp |
91 | endp |
90 | 92 | ||
91 | ; Returns information about disk media. |
93 | ; Returns information about disk media. |
92 | proc ramdisk_querymedia |
94 | proc ramdisk_querymedia |
93 | virtual at esp+4 |
95 | virtual at esp+4 |
94 | .userdata dd ? |
96 | .userdata dd ? |
95 | .info dd ? |
97 | .info dd ? |
96 | end virtual |
98 | end virtual |
97 | ; Media is always present, sector size is always 512 bytes. |
99 | ; Media is always present, sector size is always 512 bytes. |
98 | mov edx, [.userdata] |
100 | mov edx, [.userdata] |
99 | mov ecx, [.info] |
101 | mov ecx, [.info] |
100 | mov [ecx+DISKMEDIAINFO.Flags], 0 |
102 | mov [ecx+DISKMEDIAINFO.Flags], 0 |
101 | mov [ecx+DISKMEDIAINFO.SectorSize], 512 |
103 | mov [ecx+DISKMEDIAINFO.SectorSize], 512 |
102 | mov eax, [ramdisk_actual_size] |
104 | mov eax, [ramdisk_actual_size] |
103 | mov dword [ecx+DISKMEDIAINFO.Capacity], eax |
105 | mov dword [ecx+DISKMEDIAINFO.Capacity], eax |
104 | mov dword [ecx+DISKMEDIAINFO.Capacity+4], 0 |
106 | mov dword [ecx+DISKMEDIAINFO.Capacity+4], 0 |
105 | ; Return zero as an indicator of success. |
107 | ; Return zero as an indicator of success. |
106 | xor eax, eax |
108 | xor eax, eax |
107 | retn 8 |
109 | retn 8 |
108 | endp |
110 | endp |
109 | 111 | ||
110 | ; Common procedure for reading and writing. |
112 | ; Common procedure for reading and writing. |
111 | ; operation = 0 for reading, operation = 1 for writing. |
113 | ; operation = 0 for reading, operation = 1 for writing. |
112 | ; Arguments of ramdisk_read and ramdisk_write are the same. |
114 | ; Arguments of ramdisk_read and ramdisk_write are the same. |
113 | macro ramdisk_read_write operation |
115 | macro ramdisk_read_write operation |
114 | { |
116 | { |
115 | push esi edi ; save used registers to be stdcall |
117 | push esi edi ; save used registers to be stdcall |
116 | mov esi, [userdata] |
118 | mov esi, [userdata] |
117 | mov edi, [numsectors_ptr] |
119 | mov edi, [numsectors_ptr] |
118 | ; 1. Determine number of sectors to be transferred. |
120 | ; 1. Determine number of sectors to be transferred. |
119 | ; This is either the requested number of sectors or number of sectors |
121 | ; This is either the requested number of sectors or number of sectors |
120 | ; up to the disk boundary, depending of what is less. |
122 | ; up to the disk boundary, depending of what is less. |
121 | xor ecx, ecx |
123 | xor ecx, ecx |
122 | ; 1a. Test whether [start_sector] is less than RAMDISK_CAPACITY. |
124 | ; 1a. Test whether [start_sector] is less than RAMDISK_CAPACITY. |
123 | ; If so, calculate number of sectors between [start_sector] and RAMDISK_CAPACITY. |
125 | ; If so, calculate number of sectors between [start_sector] and RAMDISK_CAPACITY. |
124 | ; Otherwise, the actual number of sectors is zero. |
126 | ; Otherwise, the actual number of sectors is zero. |
125 | cmp dword [start_sector+4], ecx |
127 | cmp dword [start_sector+4], ecx |
126 | jnz .got_number |
128 | jnz .got_number |
127 | mov eax, [ramdisk_actual_size] |
129 | mov eax, [ramdisk_actual_size] |
128 | sub eax, dword [start_sector] |
130 | sub eax, dword [start_sector] |
129 | jbe .got_number |
131 | jbe .got_number |
130 | ; 1b. Get the requested number of sectors. |
132 | ; 1b. Get the requested number of sectors. |
131 | mov ecx, [edi] |
133 | mov ecx, [edi] |
132 | ; 1c. If it is greater than number of sectors calculated in 1a, use the value |
134 | ; 1c. If it is greater than number of sectors calculated in 1a, use the value |
133 | ; from 1a. |
135 | ; from 1a. |
134 | cmp ecx, eax |
136 | cmp ecx, eax |
135 | jb .got_number |
137 | jb .got_number |
136 | mov ecx, eax |
138 | mov ecx, eax |
137 | .got_number: |
139 | .got_number: |
138 | ; 2. Compare the actual number of sectors with requested. If they are |
140 | ; 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, |
141 | ; equal, set eax (it will be the returned value) to zero. Otherwise, |
140 | ; use DISK_STATUS_END_OF_MEDIA. |
142 | ; use DISK_STATUS_END_OF_MEDIA. |
141 | xor eax, eax |
143 | xor eax, eax |
142 | cmp ecx, [edi] |
144 | cmp ecx, [edi] |
143 | jz @f |
145 | jz @f |
144 | mov al, DISK_STATUS_END_OF_MEDIA |
146 | mov al, DISK_STATUS_END_OF_MEDIA |
145 | @@: |
147 | @@: |
146 | ; 3. Store the actual number of sectors. |
148 | ; 3. Store the actual number of sectors. |
147 | mov [edi], ecx |
149 | mov [edi], ecx |
148 | ; 4. Calculate source and destination addresses. |
150 | ; 4. Calculate source and destination addresses. |
149 | if operation = 0 ; reading? |
151 | if operation = 0 ; reading? |
150 | mov esi, dword [start_sector] |
152 | mov esi, dword [start_sector] |
151 | shl esi, 9 |
153 | shl esi, 9 |
152 | add esi, RAMDISK |
154 | add esi, RAMDISK |
153 | mov edi, [buffer] |
155 | mov edi, [buffer] |
154 | else ; writing? |
156 | else ; writing? |
155 | mov edi, dword [start_sector] |
157 | mov edi, dword [start_sector] |
156 | shl edi, 9 |
158 | shl edi, 9 |
157 | add edi, RAMDISK |
159 | add edi, RAMDISK |
158 | mov esi, [buffer] |
160 | mov esi, [buffer] |
159 | end if |
161 | end if |
160 | ; 5. Calculate number of dwords to be transferred. |
162 | ; 5. Calculate number of dwords to be transferred. |
161 | shl ecx, 9-2 |
163 | shl ecx, 9-2 |
162 | ; 6. Copy data. |
164 | ; 6. Copy data. |
163 | rep movsd |
165 | rep movsd |
164 | ; 7. Return. The value in eax was calculated in step 2. |
166 | ; 7. Return. The value in eax was calculated in step 2. |
165 | pop edi esi ; restore used registers to be stdcall |
167 | pop edi esi ; restore used registers to be stdcall |
166 | } |
168 | } |
167 | 169 | ||
168 | ; Reads one or more sectors from the device. |
170 | ; Reads one or more sectors from the device. |
169 | proc ramdisk_read userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword |
171 | proc ramdisk_read userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword |
170 | ramdisk_read_write 0 |
172 | ramdisk_read_write 0 |
171 | ret |
173 | ret |
172 | endp |
174 | endp |
173 | 175 | ||
174 | ; Writes one or more sectors to the device. |
176 | ; Writes one or more sectors to the device. |
175 | proc ramdisk_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword |
177 | proc ramdisk_write userdata:dword, buffer:dword, start_sector:qword, numsectors_ptr:dword |
176 | ramdisk_read_write 1 |
178 | ramdisk_read_write 1 |
177 | ret |
179 | ret |
178 | endp |
180 | endp |
179 | 181 | ||
180 | ; The kernel calls this function when initializing cache subsystem for |
182 | ; The kernel calls this function when initializing cache subsystem for |
181 | ; the media. This call allows the driver to adjust the cache size. |
183 | ; the media. This call allows the driver to adjust the cache size. |
182 | proc ramdisk_adjust_cache_size |
184 | proc ramdisk_adjust_cache_size |
183 | virtual at esp+4 |
185 | virtual at esp+4 |
184 | .userdata dd ? |
186 | .userdata dd ? |
185 | .suggested_size dd ? |
187 | .suggested_size dd ? |
186 | end virtual |
188 | end virtual |
187 | ; Since ramdisk does not need cache, just return 0. |
189 | ; Since ramdisk does not need cache, just return 0. |
188 | xor eax, eax |
190 | xor eax, eax |
189 | retn 8 |
191 | retn 8 |
190 | endp |
192 | endp |