Rev 2644 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2644 | Rev 5044 | ||
---|---|---|---|
1 | ; Disk driver to create FAT16/FAT32 memory-based temporary disk aka RAM disk. |
1 | ; Disk driver to create FAT16/FAT32 memory-based temporary disk aka RAM disk. |
2 | ; (c) CleverMouse |
2 | ; (c) CleverMouse |
3 | 3 | ||
4 | ; Note: in the ideal world, a disk driver should not care about a file system |
4 | ; Note: in the ideal world, a disk driver should not care about a file system |
5 | ; on it. In the current world, however, there is no way to format a disk in |
5 | ; on it. In the current world, however, there is no way to format a disk in |
6 | ; FAT, so this part of file-system-specific operations is included in the |
6 | ; FAT, so this part of file-system-specific operations is included in the |
7 | ; driver. |
7 | ; driver. |
8 | 8 | ||
9 | ; When this driver is loading, it registers itself in the system and does |
9 | ; When this driver is loading, it registers itself in the system and does |
10 | ; nothing more. When loaded, this driver controls pseudo-disk devices |
10 | ; nothing more. When loaded, this driver controls pseudo-disk devices |
11 | ; named /tmp#/, where # is a digit from 0 to 9. The driver does not create |
11 | ; named /tmp#/, where # is a digit from 0 to 9. The driver does not create |
12 | ; any device by itself, waiting for instructions from an application. |
12 | ; any device by itself, waiting for instructions from an application. |
13 | ; The driver responds to the following IOCTLs from a control application: |
13 | ; The driver responds to the following IOCTLs from a control application: |
14 | SRV_GETVERSION equ 0 ; input ignored, |
14 | SRV_GETVERSION equ 0 ; input ignored, |
15 | ; output = dword API_VERSION |
15 | ; output = dword API_VERSION |
16 | DEV_ADD_DISK equ 1 ; input = structure add_disk_struc, |
16 | DEV_ADD_DISK equ 1 ; input = structure add_disk_struc, |
17 | ; no output |
17 | ; no output |
18 | DEV_DEL_DISK equ 2 ; input = structure del_disk_struc, |
18 | DEV_DEL_DISK equ 2 ; input = structure del_disk_struc, |
19 | ; no output |
19 | ; no output |
20 | ; For all IOCTLs the driver returns one of the following error codes: |
20 | ; For all IOCTLs the driver returns one of the following error codes: |
21 | NO_ERROR equ 0 |
21 | NO_ERROR equ 0 |
22 | ERROR_INVALID_IOCTL equ 1 ; unknown IOCTL code, wrong input/output size... |
22 | ERROR_INVALID_IOCTL equ 1 ; unknown IOCTL code, wrong input/output size... |
23 | ERROR_INVALID_ID equ 2 ; .DiskId must be from 0 to 9 |
23 | ERROR_INVALID_ID equ 2 ; .DiskId must be from 0 to 9 |
24 | ERROR_SIZE_TOO_LARGE equ 3 ; .DiskSize is too large |
24 | ERROR_SIZE_TOO_LARGE equ 3 ; .DiskSize is too large |
25 | ERROR_SIZE_TOO_SMALL equ 4 ; .DiskSize is too small |
25 | ERROR_SIZE_TOO_SMALL equ 4 ; .DiskSize is too small |
26 | ERROR_NO_MEMORY equ 5 ; memory allocation failed |
26 | ERROR_NO_MEMORY equ 5 ; memory allocation failed |
- | 27 | ||
27 | 28 | include '../struct.inc' |
|
28 | 29 | ||
29 | API_VERSION equ 1 |
30 | API_VERSION equ 1 |
30 | ; Input structures: |
31 | ; Input structures: |
31 | struc add_disk_struc |
32 | struct add_disk_struc |
32 | { |
- | |
33 | .DiskSize dd ? ; disk size in sectors, 1 sector = 512 bytes |
33 | DiskSize dd ? ; disk size in sectors, 1 sector = 512 bytes |
34 | ; Note: .DiskSize is the full size, including FAT service data. |
34 | ; Note: DiskSize is the full size, including FAT service data. |
35 | ; Size for useful data is slightly less than this number. |
35 | ; Size for useful data is slightly less than this number. |
36 | .DiskId db ? ; from 0 to 9 |
36 | DiskId db ? ; from 0 to 9 |
37 | .sizeof: |
- | |
38 | } |
- | |
39 | virtual at 0 |
- | |
40 | add_disk_struc add_disk_struc |
- | |
41 | end virtual |
37 | ends |
42 | struc del_disk_struc |
38 | struct del_disk_struc |
43 | { |
- | |
44 | .DiskId db ? ; from 0 to 9 |
39 | DiskId db ? ; from 0 to 9 |
45 | .sizeof: |
- | |
46 | } |
- | |
47 | virtual at 0 |
- | |
48 | del_disk_struc del_disk_struc |
- | |
49 | end virtual |
40 | ends |
50 | 41 | ||
51 | max_num_disks equ 10 |
42 | max_num_disks equ 10 |
52 | 43 | ||
53 | ; standard driver stuff |
44 | ; standard driver stuff; version of driver model = 5 |
54 | format MS COFF |
45 | format PE DLL native 0.05 |
55 | - | ||
56 | DEBUG equ 0 |
- | |
- | 46 | ||
57 | include 'proc32.inc' |
47 | DEBUG equ 0 |
58 | include 'imports.inc' |
48 | |
59 | - | ||
60 | public START |
49 | section '.flat' code readable writable executable |
61 | public version |
- | |
62 | - | ||
63 | struc IOCTL |
- | |
64 | { |
50 | data fixups |
65 | .handle dd ? |
51 | end data |
66 | .io_code dd ? |
- | |
67 | .input dd ? |
- | |
68 | .inp_size dd ? |
- | |
69 | .output dd ? |
- | |
70 | .out_size dd ? |
- | |
71 | } |
- | |
72 | - | ||
73 | virtual at 0 |
- | |
74 | IOCTL IOCTL |
52 | entry START |
75 | end virtual |
53 | include '../proc32.inc' |
76 | 54 | include '../peimport.inc' |
|
77 | section '.flat' code readable align 16 |
55 | include '../macros.inc' |
78 | ; the start procedure (see the description above) |
56 | ; the start procedure (see the description above) |
79 | proc START |
57 | proc START |
80 | ; This procedure is called in two situations: |
58 | ; This procedure is called in two situations: |
81 | ; when the driver is loading and when the system is shutting down. |
59 | ; when the driver is loading and when the system is shutting down. |
82 | ; 1. Check that the driver is loading; do nothing unless so. |
60 | ; 1. Check that the driver is loading; do nothing unless so. |
83 | xor eax, eax ; set return value in case we will do nothing |
61 | xor eax, eax ; set return value in case we will do nothing |
84 | cmp dword [esp+4], 1 |
62 | cmp dword [esp+4], 1 |
85 | jne .nothing |
63 | jne .nothing |
86 | ; 2. Register the driver in the system. |
64 | ; 2. Register the driver in the system. |
87 | stdcall RegService, my_service, service_proc |
65 | invoke RegService, my_service, service_proc |
88 | ; 3. Return the value returned by RegService back to the system. |
66 | ; 3. Return the value returned by RegService back to the system. |
89 | .nothing: |
67 | .nothing: |
90 | retn 4 |
68 | retn |
91 | endp |
69 | endp |
92 | 70 | ||
93 | ; Service procedure for the driver - handle all IOCTL requests for the driver. |
71 | ; Service procedure for the driver - handle all IOCTL requests for the driver. |
94 | ; The description of handled IOCTLs is located in the start of this file. |
72 | ; The description of handled IOCTLs is located in the start of this file. |
95 | proc service_proc |
73 | proc service_proc |
96 | ; 1. Save used registers to be stdcall. |
74 | ; 1. Save used registers to be stdcall. |
97 | ; Note: this shifts esp, so the first parameter [esp+4] becomes [esp+16]. |
75 | ; Note: this shifts esp, so the first parameter [esp+4] becomes [esp+16]. |
98 | ; Note: edi is used not by this procedure itself, but by worker procedures. |
76 | ; Note: edi is used not by this procedure itself, but by worker procedures. |
99 | push ebx esi edi |
77 | push ebx esi edi |
100 | ; 2. Get parameter from the stack: [esp+16] is the first parameter, |
78 | ; 2. Get parameter from the stack: [esp+16] is the first parameter, |
101 | ; pointer to IOCTL structure. |
79 | ; pointer to IOCTL structure. |
102 | mov edx, [esp+16] ; edx -> IOCTL |
80 | mov edx, [esp+16] ; edx -> IOCTL |
103 | ; 3. Set the return value to 'invalid IOCTL'. |
81 | ; 3. Set the return value to 'invalid IOCTL'. |
104 | ; Now, if one of conditions for IOCTL does not met, the code |
82 | ; Now, if one of conditions for IOCTL does not met, the code |
105 | ; can simply return the value already loaded. |
83 | ; can simply return the value already loaded. |
106 | mov al, ERROR_INVALID_IOCTL |
84 | mov al, ERROR_INVALID_IOCTL |
107 | ; 4. Get request code and select a handler for the code. |
85 | ; 4. Get request code and select a handler for the code. |
108 | mov ecx, [edx+IOCTL.io_code] |
86 | mov ecx, [edx+IOCTL.io_code] |
109 | test ecx, ecx ; check for SRV_GETVERSION |
87 | test ecx, ecx ; check for SRV_GETVERSION |
110 | jnz .no.srv_getversion |
88 | jnz .no.srv_getversion |
111 | ; 4. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION. |
89 | ; 4. This is SRV_GETVERSION request, no input, 4 bytes output, API_VERSION. |
112 | ; 4a. Output size must be at least 4 bytes. |
90 | ; 4a. Output size must be at least 4 bytes. |
113 | cmp [edx+IOCTL.out_size], 4 |
91 | cmp [edx+IOCTL.out_size], 4 |
114 | jl .return |
92 | jl .return |
115 | ; 4b. Write result to the output buffer. |
93 | ; 4b. Write result to the output buffer. |
116 | mov eax, [edx+IOCTL.output] |
94 | mov eax, [edx+IOCTL.output] |
117 | mov dword [eax], API_VERSION |
95 | mov dword [eax], API_VERSION |
118 | ; 4c. Return success. |
96 | ; 4c. Return success. |
119 | xor eax, eax |
97 | xor eax, eax |
120 | jmp .return |
98 | jmp .return |
121 | .no.srv_getversion: |
99 | .no.srv_getversion: |
122 | dec ecx ; check for DEV_ADD_DISK |
100 | dec ecx ; check for DEV_ADD_DISK |
123 | jnz .no.dev_add_disk |
101 | jnz .no.dev_add_disk |
124 | ; 5. This is DEV_ADD_DISK request, input is add_disk_struc, output is 1 byte |
102 | ; 5. This is DEV_ADD_DISK request, input is add_disk_struc, output is 1 byte |
125 | ; 5a. Input size must be exactly add_disk_struc.sizeof bytes. |
103 | ; 5a. Input size must be exactly sizeof.add_disk_struc bytes. |
126 | cmp [edx+IOCTL.inp_size], add_disk_struc.sizeof |
104 | cmp [edx+IOCTL.inp_size], sizeof.add_disk_struc |
127 | jnz .return |
105 | jnz .return |
128 | ; 5b. Load input parameters and call the worker procedure. |
106 | ; 5b. Load input parameters and call the worker procedure. |
129 | mov eax, [edx+IOCTL.input] |
107 | mov eax, [edx+IOCTL.input] |
130 | movzx ebx, [eax+add_disk_struc.DiskId] |
108 | movzx ebx, [eax+add_disk_struc.DiskId] |
131 | mov esi, [eax+add_disk_struc.DiskSize] |
109 | mov esi, [eax+add_disk_struc.DiskSize] |
132 | call add_disk |
110 | call add_disk |
133 | ; 5c. Return back to the caller the value from the worker procedure. |
111 | ; 5c. Return back to the caller the value from the worker procedure. |
134 | jmp .return |
112 | jmp .return |
135 | .no.dev_add_disk: |
113 | .no.dev_add_disk: |
136 | dec ecx ; check for DEV_DEL_DISK |
114 | dec ecx ; check for DEV_DEL_DISK |
137 | jnz .return |
115 | jnz .return |
138 | ; 6. This is DEV_DEL_DISK request, input is del_disk_struc |
116 | ; 6. This is DEV_DEL_DISK request, input is del_disk_struc |
139 | ; 6a. Input size must be exactly del_disk_struc.sizeof bytes. |
117 | ; 6a. Input size must be exactly sizeof.del_disk_struc bytes. |
140 | cmp [edx+IOCTL.inp_size], del_disk_struc.sizeof |
118 | cmp [edx+IOCTL.inp_size], sizeof.del_disk_struc |
141 | jnz .return |
119 | jnz .return |
142 | ; 6b. Load input parameters and call the worker procedure. |
120 | ; 6b. Load input parameters and call the worker procedure. |
143 | mov eax, [edx+IOCTL.input] |
121 | mov eax, [edx+IOCTL.input] |
144 | movzx ebx, [eax+del_disk_struc.DiskId] |
122 | movzx ebx, [eax+del_disk_struc.DiskId] |
145 | call del_disk |
123 | call del_disk |
146 | ; 6c. Return back to the caller the value from the worker procedure. |
124 | ; 6c. Return back to the caller the value from the worker procedure. |
147 | .return: |
125 | .return: |
148 | ; 7. Exit. |
126 | ; 7. Exit. |
149 | ; 7a. The code above returns a value in al for efficiency, |
127 | ; 7a. The code above returns a value in al for efficiency, |
150 | ; propagate it to eax. |
128 | ; propagate it to eax. |
151 | movzx eax, al |
129 | movzx eax, al |
152 | ; 7b. Restore used registers to be stdcall. |
130 | ; 7b. Restore used registers to be stdcall. |
153 | pop edi esi ebx |
131 | pop edi esi ebx |
154 | ; 7c. Return, popping one argument. |
132 | ; 7c. Return, popping one argument. |
155 | retn 4 |
133 | retn 4 |
156 | endp |
134 | endp |
157 | 135 | ||
158 | ; The worker procedure for DEV_ADD_DISK request. |
136 | ; The worker procedure for DEV_ADD_DISK request. |
159 | ; Creates a memory-based disk of given size and formats it in FAT16/32. |
137 | ; Creates a memory-based disk of given size and formats it in FAT16/32. |
160 | ; Called with ebx = disk id, esi = disk size, |
138 | ; Called with ebx = disk id, esi = disk size, |
161 | ; returns error code in al. |
139 | ; returns error code in al. |
162 | proc add_disk |
140 | proc add_disk |
163 | ; 1. Check that disk id is correct and free. |
141 | ; 1. Check that disk id is correct and free. |
164 | ; Otherwise, return the corresponding error code. |
142 | ; Otherwise, return the corresponding error code. |
165 | mov al, ERROR_INVALID_ID |
143 | mov al, ERROR_INVALID_ID |
166 | cmp ebx, max_num_disks |
144 | cmp ebx, max_num_disks |
167 | jae .return |
145 | jae .return |
168 | cmp [disk_pointers+ebx*4], 0 |
146 | cmp [disk_pointers+ebx*4], 0 |
169 | jnz .return |
147 | jnz .return |
170 | ; 2. Check that the size is reasonable. |
148 | ; 2. Check that the size is reasonable. |
171 | ; Otherwise, return the corresponding error code. |
149 | ; Otherwise, return the corresponding error code. |
172 | mov al, ERROR_SIZE_TOO_LARGE |
150 | mov al, ERROR_SIZE_TOO_LARGE |
173 | cmp esi, MAX_SIZE |
151 | cmp esi, MAX_SIZE |
174 | ja .return |
152 | ja .return |
175 | mov al, ERROR_SIZE_TOO_SMALL |
153 | mov al, ERROR_SIZE_TOO_SMALL |
176 | cmp esi, MIN_FAT16_SIZE |
154 | cmp esi, MIN_FAT16_SIZE |
177 | jb .return |
155 | jb .return |
178 | ; 3. Allocate memory for the disk, store the pointer in edi. |
156 | ; 3. Allocate memory for the disk, store the pointer in edi. |
179 | ; If failed, return the corresponding error code. |
157 | ; If failed, return the corresponding error code. |
180 | mov eax, esi |
158 | mov eax, esi |
181 | shl eax, 9 |
159 | shl eax, 9 |
182 | stdcall KernelAlloc, eax |
160 | invoke KernelAlloc, eax |
183 | mov edi, eax |
161 | mov edi, eax |
184 | test eax, eax |
162 | test eax, eax |
185 | mov al, ERROR_NO_MEMORY |
163 | mov al, ERROR_NO_MEMORY |
186 | jz .return |
164 | jz .return |
187 | ; 4. Store the pointer and the size in the global variables. |
165 | ; 4. Store the pointer and the size in the global variables. |
188 | ; It is possible, though very unlikely, that two threads |
166 | ; It is possible, though very unlikely, that two threads |
189 | ; have called this function in parallel with the same id, |
167 | ; have called this function in parallel with the same id, |
190 | ; so [disk_pointers+ebx*4] could be filled by another thread. |
168 | ; so [disk_pointers+ebx*4] could be filled by another thread. |
191 | ; Play extra safe and store new value only if old value is zero. |
169 | ; Play extra safe and store new value only if old value is zero. |
192 | xor eax, eax |
170 | xor eax, eax |
193 | lock cmpxchg [disk_pointers+ebx*4], edi |
171 | lock cmpxchg [disk_pointers+ebx*4], edi |
194 | jz @f |
172 | jz @f |
195 | ; Otherwise, free the allocated memory and return the corresponding error code. |
173 | ; Otherwise, free the allocated memory and return the corresponding error code. |
196 | stdcall KernelFree, edi |
174 | invoke KernelFree, edi |
197 | mov al, ERROR_INVALID_ID |
175 | mov al, ERROR_INVALID_ID |
198 | jmp .return |
176 | jmp .return |
199 | @@: |
177 | @@: |
200 | mov [disk_sizes+ebx*4], esi |
178 | mov [disk_sizes+ebx*4], esi |
201 | ; 5. Call the worker procedure for formatting this disk. |
179 | ; 5. Call the worker procedure for formatting this disk. |
202 | ; It should not fail. |
180 | ; It should not fail. |
203 | call format_disk |
181 | call format_disk |
204 | ; 6. Register the disk in the system. |
182 | ; 6. Register the disk in the system. |
205 | ; 6a. Generate name as /tmp#, where # = ebx + '0'. Use two dwords in the stack. |
183 | ; 6a. Generate name as /tmp#, where # = ebx + '0'. Use two dwords in the stack. |
206 | push 0 |
184 | push 0 |
207 | push 'tmp' |
185 | push 'tmp' |
208 | mov eax, esp ; eax points to 'tmp' + zero byte + zero dword |
186 | mov eax, esp ; eax points to 'tmp' + zero byte + zero dword |
209 | lea ecx, [ebx+'0'] ; ecx = digit |
187 | lea ecx, [ebx+'0'] ; ecx = digit |
210 | mov [eax+3], cl ; eax points to 'tmp#' + zero dword |
188 | mov [eax+3], cl ; eax points to 'tmp#' + zero dword |
211 | ; 6b. Call the kernel API. Use disk id as 'userdata' parameter for callbacks. |
189 | ; 6b. Call the kernel API. Use disk id as 'userdata' parameter for callbacks. |
212 | stdcall DiskAdd, disk_functions, eax, ebx, 0 |
190 | invoke DiskAdd, disk_functions, eax, ebx, 0 |
213 | ; 6c. Restore the stack after 6a. |
191 | ; 6c. Restore the stack after 6a. |
214 | pop ecx ecx |
192 | pop ecx ecx |
215 | ; 6c. Check the result. If DiskAdd has failed, cleanup and return |
193 | ; 6c. Check the result. If DiskAdd has failed, cleanup and return |
216 | ; ERROR_NO_MEMORY, this is the most probable or even the only reason to fail. |
194 | ; ERROR_NO_MEMORY, this is the most probable or even the only reason to fail. |
217 | test eax, eax |
195 | test eax, eax |
218 | jnz @f |
196 | jnz @f |
219 | mov [disk_sizes+ebx*4], 0 |
197 | mov [disk_sizes+ebx*4], 0 |
220 | mov [disk_pointers+ebx*4], 0 |
198 | mov [disk_pointers+ebx*4], 0 |
221 | stdcall KernelFree, edi |
199 | invoke KernelFree, edi |
222 | mov al, ERROR_NO_MEMORY |
200 | mov al, ERROR_NO_MEMORY |
223 | jmp .return |
201 | jmp .return |
224 | @@: |
202 | @@: |
225 | push eax |
203 | push eax |
226 | ; 6d. Notify the kernel that media is inserted. |
204 | ; 6d. Notify the kernel that media is inserted. |
227 | stdcall DiskMediaChanged, eax, 1 |
205 | invoke DiskMediaChanged, eax, 1 |
228 | ; 6e. Disk is fully configured; store its handle in the global variable |
206 | ; 6e. Disk is fully configured; store its handle in the global variable |
229 | ; and return success. |
207 | ; and return success. |
230 | pop [disk_handles+ebx*4] |
208 | pop [disk_handles+ebx*4] |
231 | xor eax, eax |
209 | xor eax, eax |
232 | ; 7. Return. |
210 | ; 7. Return. |
233 | .return: |
211 | .return: |
234 | retn |
212 | retn |
235 | endp |
213 | endp |
236 | 214 | ||
237 | ; The worker procedure for DEV_DEL_DISK request. |
215 | ; The worker procedure for DEV_DEL_DISK request. |
238 | ; Deletes a previously created memory-based disk. |
216 | ; Deletes a previously created memory-based disk. |
239 | ; Called with ebx = disk id, |
217 | ; Called with ebx = disk id, |
240 | ; returns error code in al. |
218 | ; returns error code in al. |
241 | proc del_disk |
219 | proc del_disk |
242 | ; 1. Check that disk id is correct. |
220 | ; 1. Check that disk id is correct. |
243 | ; Otherwise, return the corresponding error code. |
221 | ; Otherwise, return the corresponding error code. |
244 | mov al, ERROR_INVALID_ID |
222 | mov al, ERROR_INVALID_ID |
245 | cmp ebx, max_num_disks |
223 | cmp ebx, max_num_disks |
246 | jae .return |
224 | jae .return |
247 | ; 2. Get the disk handle, simultaneously clearing the global variable. |
225 | ; 2. Get the disk handle, simultaneously clearing the global variable. |
248 | xor edx, edx |
226 | xor edx, edx |
249 | xchg edx, [disk_handles+ebx*4] |
227 | xchg edx, [disk_handles+ebx*4] |
250 | ; 3. Check that the handle is non-zero. |
228 | ; 3. Check that the handle is non-zero. |
251 | ; Otherwise, return the corresponding error code. |
229 | ; Otherwise, return the corresponding error code. |
252 | test edx, edx |
230 | test edx, edx |
253 | jz .return |
231 | jz .return |
254 | ; 4. Delete the disk from the system. |
232 | ; 4. Delete the disk from the system. |
255 | stdcall DiskDel, edx |
233 | invoke DiskDel, edx |
256 | ; 5. Return success. |
234 | ; 5. Return success. |
257 | ; Note that we can't free memory yet; it will be done in tmpdisk_close. |
235 | ; Note that we can't free memory yet; it will be done in tmpdisk_close. |
258 | xor eax, eax |
236 | xor eax, eax |
259 | .return: |
237 | .return: |
260 | retn |
238 | retn |
261 | endp |
239 | endp |
262 | 240 | ||
263 | ; Include implementation of tmpdisk_* callbacks. |
241 | ; Include implementation of tmpdisk_* callbacks. |
264 | include 'tmpdisk_work.inc' |
242 | include 'tmpdisk_work.inc' |
265 | ; Include FAT-specific code. |
243 | ; Include FAT-specific code. |
266 | include 'tmpdisk_fat.inc' |
244 | include 'tmpdisk_fat.inc' |
267 | 245 | ||
268 | ; initialized data |
246 | ; initialized data |
269 | align 4 |
247 | align 4 |
270 | disk_functions: |
248 | disk_functions: |
271 | dd disk_functions_end - disk_functions |
249 | dd disk_functions_end - disk_functions |
272 | dd tmpdisk_close |
250 | dd tmpdisk_close |
273 | dd 0 ; no need in .closemedia |
251 | dd 0 ; no need in .closemedia |
274 | dd tmpdisk_querymedia |
252 | dd tmpdisk_querymedia |
275 | dd tmpdisk_read |
253 | dd tmpdisk_read |
276 | dd tmpdisk_write |
254 | dd tmpdisk_write |
277 | dd 0 ; no need in .flush |
255 | dd 0 ; no need in .flush |
278 | dd tmpdisk_adjust_cache_size |
256 | dd tmpdisk_adjust_cache_size |
279 | disk_functions_end: |
257 | disk_functions_end: |
280 | ; disk_handles = array of values for Disk* kernel functions |
258 | ; disk_handles = array of values for Disk* kernel functions |
281 | label disk_handles dword |
259 | label disk_handles dword |
282 | times max_num_disks dd 0 |
260 | times max_num_disks dd 0 |
283 | ; disk_pointers = array of pointers to disk data |
261 | ; disk_pointers = array of pointers to disk data |
284 | label disk_pointers dword |
262 | label disk_pointers dword |
285 | times max_num_disks dd 0 |
263 | times max_num_disks dd 0 |
286 | ; disk_sizes = array of disk sizes |
264 | ; disk_sizes = array of disk sizes |
287 | label disk_sizes dword |
265 | label disk_sizes dword |
288 | times max_num_disks dd 0 |
266 | times max_num_disks dd 0 |
289 | - | ||
290 | version dd 0x00060006 |
267 | |
291 | my_service db 'tmpdisk',0 |
- | |
292 | - | ||
293 | ; uninitialized data |
- | |
294 | ; actually, not used here |
- | |
295 | ;section '.data' data readable writable align 16 ; standard driver stuff |
268 | my_service db 'tmpdisk',0 |