Rev 2129 | Rev 2145 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2129 | Rev 2140 | ||
---|---|---|---|
Line 3... | Line 3... | ||
3 | ;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2011. 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 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Line -... | Line 7... | ||
- | 7 | ||
- | 8 | $Revision: 2140 $ |
|
7 | 9 | ||
8 | ; ============================================================================= |
10 | ; ============================================================================= |
9 | ; ================================= Constants ================================= |
11 | ; ================================= Constants ================================= |
10 | ; ============================================================================= |
12 | ; ============================================================================= |
11 | ; Error codes for callback functions. |
13 | ; Error codes for callback functions. |
Line 74... | Line 76... | ||
74 | ; int flush(void* userdata); |
76 | ; int flush(void* userdata); |
75 | ; Return value: one of DISK_STATUS_* |
77 | ; Return value: one of DISK_STATUS_* |
76 | ; Note that read/write are called by the cache manager, so a driver should not |
78 | ; Note that read/write are called by the cache manager, so a driver should not |
77 | ; create a software cache. This function is implemented for flushing a hardware |
79 | ; create a software cache. This function is implemented for flushing a hardware |
78 | ; cache, if it exists. |
80 | ; cache, if it exists. |
- | 81 | .adjust_cache_size dd ? |
|
- | 82 | ; The pointer to the function which returns the cache size for this device. |
|
- | 83 | ; Optional, may be NULL. |
|
- | 84 | ; unsigned int adjust_cache_size(unsigned int suggested_size); |
|
- | 85 | ; Return value: 0 = disable cache, otherwise = used cache size in bytes. |
|
79 | ends |
86 | ends |
Line 80... | Line 87... | ||
80 | 87 | ||
81 | ; This structure holds an information about a media. |
88 | ; This structure holds an information about a media. |
82 | ; Objects with this structure are allocated by the kernel as a part of DISK |
89 | ; Objects with this structure are allocated by the kernel as a part of DISK |
Line 88... | Line 95... | ||
88 | ; Size of the sector. |
95 | ; Size of the sector. |
89 | .Capacity dq ? |
96 | .Capacity dq ? |
90 | ; Size of the media in sectors. |
97 | ; Size of the media in sectors. |
91 | ends |
98 | ends |
Line -... | Line 99... | ||
- | 99 | ||
- | 100 | ; This structure represents disk cache. To follow the old implementation, |
|
- | 101 | ; there are two distinct caches for a disk, one for "system" data, other |
|
- | 102 | ; for "application" data. |
|
- | 103 | struct DISKCACHE |
|
- | 104 | .Lock MUTEX |
|
- | 105 | ; Lock to protect the cache. |
|
- | 106 | ; The following fields are inherited from data32.inc:cache_ideX. |
|
- | 107 | .pointer rd 1 |
|
- | 108 | .data_size rd 1 ; not use |
|
- | 109 | .data rd 1 |
|
- | 110 | .sad_size rd 1 |
|
- | 111 | .search_start rd 1 |
|
- | 112 | ends |
|
92 | 113 | ||
93 | ; This structure represents a disk device and its media for the kernel. |
114 | ; This structure represents a disk device and its media for the kernel. |
94 | ; This structure is allocated by the kernel in the 'disk_add' function, |
115 | ; This structure is allocated by the kernel in the 'disk_add' function, |
95 | ; freed in the 'disk_dereference' function. |
116 | ; freed in the 'disk_dereference' function. |
96 | struct DISK |
117 | struct DISK |
Line 144... | Line 165... | ||
144 | ; This field keeps an information about the current media. |
165 | ; This field keeps an information about the current media. |
145 | .NumPartitions dd ? |
166 | .NumPartitions dd ? |
146 | ; Number of partitions on this media. |
167 | ; Number of partitions on this media. |
147 | .Partitions dd ? |
168 | .Partitions dd ? |
148 | ; Pointer to array of .NumPartitions pointers to PARTITION structures. |
169 | ; Pointer to array of .NumPartitions pointers to PARTITION structures. |
- | 170 | .cache_size dd ? |
|
- | 171 | ; inherited from cache_ideX_size |
|
- | 172 | .SysCache DISKCACHE |
|
- | 173 | .AppCache DISKCACHE |
|
- | 174 | ; Two caches for the disk. |
|
149 | ends |
175 | ends |
Line 150... | Line 176... | ||
150 | 176 | ||
151 | ; This structure represents one partition for the kernel. This is a base |
177 | ; This structure represents one partition for the kernel. This is a base |
152 | ; template, the actual contents after common fields is determined by the |
178 | ; template, the actual contents after common fields is determined by the |
153 | ; file system code for this partition. |
179 | ; file system code for this partition. |
154 | struct PARTITION |
180 | struct PARTITION |
155 | .FirstSector dq ? |
181 | .FirstSector dq ? |
156 | ; First sector of the partition. |
182 | ; First sector of the partition. |
157 | .Length dq ? |
183 | .Length dq ? |
- | 184 | ; Length of the partition in sectors. |
|
- | 185 | .Disk dd ? |
|
158 | ; Length of the partition in sectors. |
186 | ; Pointer to parent DISK structure. |
159 | .FSUserFunctions dd ? |
187 | .FSUserFunctions dd ? |
160 | ; Handlers for the sysfunction 70h. This field is a pointer to the following |
188 | ; Handlers for the sysfunction 70h. This field is a pointer to the following |
161 | ; array. The first dword is a number of supported subfunctions, other dwords |
189 | ; array. The first dword is a number of supported subfunctions, other dwords |
162 | ; point to handlers of corresponding subfunctions. |
190 | ; point to handlers of corresponding subfunctions. |
Line 240... | Line 268... | ||
240 | ; filesystem operations are referencing the same filesystem data, this is |
268 | ; filesystem operations are referencing the same filesystem data, this is |
241 | ; better resolved at the level of the filesystem. |
269 | ; better resolved at the level of the filesystem. |
242 | endg |
270 | endg |
Line 243... | Line 271... | ||
243 | 271 | ||
244 | iglobal |
272 | iglobal |
245 | ; The function 'disk_scan_partitions' needs two 512-byte buffers for |
273 | ; The function 'disk_scan_partitions' needs three 512-byte buffers for |
246 | ; MBR and bootsectors data. It can not use the static buffers always, |
274 | ; MBR, bootsector and fs-temporary sector data. It can not use the static |
247 | ; since it can be called for two or more disks in parallel. However, this |
275 | ; buffers always, since it can be called for two or more disks in parallel. |
248 | ; case is not typical. We reserve two static 512-byte buffers and a flag |
276 | ; However, this case is not typical. We reserve three static 512-byte buffers |
249 | ; that these buffers are currently used. If 'disk_scan_partitions' detects that |
277 | ; and a flag that these buffers are currently used. If 'disk_scan_partitions' |
- | 278 | ; detects that the buffers are currently used, it allocates buffers from the |
|
250 | ; the buffers are currently used, it allocates buffers from the heap. |
279 | ; heap. |
251 | ; The flag is implemented as a global dword variable. When the static buffers |
280 | ; The flag is implemented as a global dword variable. When the static buffers |
252 | ; are not used, the value is -1. When the static buffers are used, the value |
281 | ; are not used, the value is -1. When the static buffers are used, the value |
253 | ; is normally 0 and temporarily can become greater. The function increments |
282 | ; is normally 0 and temporarily can become greater. The function increments |
254 | ; this value. If the resulting value is zero, it uses the buffers and |
283 | ; this value. If the resulting value is zero, it uses the buffers and |
255 | ; decrements the value when the job is done. Otherwise, it immediately |
284 | ; decrements the value when the job is done. Otherwise, it immediately |
256 | ; decrements the value and uses buffers from the heap, allocated in the |
285 | ; decrements the value and uses buffers from the heap, allocated in the |
257 | ; beginning and freed in the end. |
286 | ; beginning and freed in the end. |
258 | partition_buffer_users dd -1 |
287 | partition_buffer_users dd -1 |
259 | endg |
288 | endg |
260 | uglobal |
289 | uglobal |
261 | ; The static buffers for MBR and bootsectors data. |
290 | ; The static buffers for MBR, bootsector and fs-temporary sector data. |
262 | align 16 |
291 | align 16 |
263 | mbr_buffer rb 512 |
292 | mbr_buffer rb 512 |
- | 293 | bootsect_buffer rb 512 |
|
264 | bootsect_buffer rb 512 |
294 | fs_tmp_buffer rb 512 |
Line 265... | Line 295... | ||
265 | endg |
295 | endg |
266 | 296 | ||
267 | iglobal |
297 | iglobal |
Line 274... | Line 304... | ||
274 | dd disk_default_closemedia |
304 | dd disk_default_closemedia |
275 | dd disk_default_querymedia |
305 | dd disk_default_querymedia |
276 | dd disk_default_read |
306 | dd disk_default_read |
277 | dd disk_default_write |
307 | dd disk_default_write |
278 | dd disk_default_flush |
308 | dd disk_default_flush |
- | 309 | dd disk_default_adjust_cache_size |
|
279 | endg |
310 | endg |
Line 280... | Line 311... | ||
280 | 311 | ||
281 | ; ============================================================================= |
312 | ; ============================================================================= |
282 | ; ================================= Functions ================================= |
313 | ; ================================= Functions ================================= |
Line 310... | Line 341... | ||
310 | ; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0. |
341 | ; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0. |
311 | test eax, eax |
342 | test eax, eax |
312 | jz .nothing |
343 | jz .nothing |
313 | ; 2. Copy disk name to the DISK structure. |
344 | ; 2. Copy disk name to the DISK structure. |
314 | ; 2a. Get length of the name, including the terminating zero. |
345 | ; 2a. Get length of the name, including the terminating zero. |
315 | mov esi, [esp+8+8] ; esi = pointer to name |
346 | mov ebx, [esp+8+8] ; ebx = pointer to name |
316 | push eax ; save allocated pointer to DISK |
347 | push eax ; save allocated pointer to DISK |
317 | xor eax, eax ; the argument of malloc() is in eax |
348 | xor eax, eax ; the argument of malloc() is in eax |
318 | @@: |
349 | @@: |
319 | inc eax |
350 | inc eax |
320 | cmp byte [esi+eax-1], 0 |
351 | cmp byte [ebx+eax-1], 0 |
321 | jnz @b |
352 | jnz @b |
322 | ; 2b. Call the heap manager. |
353 | ; 2b. Call the heap manager. |
323 | call malloc |
354 | call malloc |
324 | ; 2c. Check the result. If allocation failed, go to 7. |
355 | ; 2c. Check the result. If allocation failed, go to 7. |
325 | pop ebx ; restore allocated pointer to DISK |
356 | pop esi ; restore allocated pointer to DISK |
326 | test eax, eax |
357 | test eax, eax |
327 | jz .free |
358 | jz .free |
328 | ; 2d. Store the allocated pointer to the DISK structure. |
359 | ; 2d. Store the allocated pointer to the DISK structure. |
329 | mov [ebx+DISK.Name], eax |
360 | mov [esi+DISK.Name], eax |
330 | ; 2e. Copy the name. |
361 | ; 2e. Copy the name. |
331 | @@: |
362 | @@: |
332 | mov dl, [esi] |
363 | mov dl, [ebx] |
333 | mov [eax], dl |
364 | mov [eax], dl |
334 | inc esi |
365 | inc ebx |
335 | inc eax |
366 | inc eax |
336 | test dl, dl |
367 | test dl, dl |
337 | jnz @b |
368 | jnz @b |
338 | ; 3. Copy other arguments of the function to the DISK structure. |
369 | ; 3. Copy other arguments of the function to the DISK structure. |
339 | mov eax, [esp+4+8] |
370 | mov eax, [esp+4+8] |
340 | mov [ebx+DISK.Functions], eax |
371 | mov [esi+DISK.Functions], eax |
341 | mov eax, [esp+12+8] |
372 | mov eax, [esp+12+8] |
342 | mov [ebx+DISK.UserData], eax |
373 | mov [esi+DISK.UserData], eax |
343 | mov eax, [esp+16+8] |
374 | mov eax, [esp+16+8] |
344 | mov [ebx+DISK.DriverFlags], eax |
375 | mov [esi+DISK.DriverFlags], eax |
345 | ; 4. Initialize other fields of the DISK structure. |
376 | ; 4. Initialize other fields of the DISK structure. |
346 | ; Media is not inserted, initialized state of mutex is zero, |
377 | ; Media is not inserted, reference counter is 1. |
347 | ; reference counter is 1. |
- | |
348 | lea ecx, [ebx+DISK.MediaLock] |
378 | lea ecx, [esi+DISK.MediaLock] |
349 | call mutex_init |
379 | call mutex_init |
350 | xor eax, eax |
380 | xor eax, eax |
351 | mov dword [ebx+DISK.MediaInserted], eax |
381 | mov dword [esi+DISK.MediaInserted], eax |
352 | inc eax |
382 | inc eax |
353 | mov [ebx+DISK.RefCount], eax |
383 | mov [esi+DISK.RefCount], eax |
354 | ; The DISK structure is initialized. |
384 | ; The DISK structure is initialized. |
355 | ; 5. Insert the new structure to the global list. |
385 | ; 5. Insert the new structure to the global list. |
356 | ; 5a. Acquire the mutex. |
386 | ; 5a. Acquire the mutex. |
357 | mov ecx, disk_list_mutex |
387 | mov ecx, disk_list_mutex |
358 | call mutex_lock |
388 | call mutex_lock |
359 | ; 5b. Insert item to the tail of double-linked list. |
389 | ; 5b. Insert item to the tail of double-linked list. |
360 | mov edx, disk_list |
390 | mov edx, disk_list |
361 | list_add_tail ebx, edx ;ebx= new edx= list head |
391 | list_add_tail esi, edx ;esi= new edx= list head |
362 | ; 5c. Release the mutex. |
392 | ; 5c. Release the mutex. |
363 | call mutex_unlock |
393 | call mutex_unlock |
364 | ; 6. Return with eax = pointer to DISK. |
394 | ; 6. Return with eax = pointer to DISK. |
365 | xchg eax, ebx |
395 | xchg eax, esi |
366 | jmp .nothing |
396 | jmp .nothing |
367 | .free: |
397 | .free: |
368 | ; Memory allocation for DISK structure succeeded, but for disk name failed. |
398 | ; Memory allocation for DISK structure succeeded, but for disk name failed. |
369 | ; 7. Free the DISK structure. |
399 | ; 7. Free the DISK structure. |
370 | xchg eax, ebx |
400 | xchg eax, esi |
371 | call free |
401 | call free |
372 | ; 8. Return with eax = 0. |
402 | ; 8. Return with eax = 0. |
373 | xor eax, eax |
403 | xor eax, eax |
374 | .nothing: |
404 | .nothing: |
375 | ; 9. Return. |
405 | ; 9. Return. |
Line 472... | Line 502... | ||
472 | call free |
502 | call free |
473 | dec edi |
503 | dec edi |
474 | jnz .freeloop |
504 | jnz .freeloop |
475 | .nofree: |
505 | .nofree: |
476 | pop edi esi |
506 | pop edi esi |
- | 507 | ; 3b. Free the cache. |
|
- | 508 | call disk_free_cache |
|
477 | ; 3b. Call the driver. |
509 | ; 3c. Call the driver. |
478 | mov al, DISKFUNC.closemedia |
510 | mov al, DISKFUNC.closemedia |
479 | stdcall disk_call_driver |
511 | stdcall disk_call_driver |
480 | ; 3c. Clear the flag. |
512 | ; 3d. Clear the flag. |
481 | mov [esi+DISK.MediaUsed], 0 |
513 | mov [esi+DISK.MediaUsed], 0 |
482 | .nothing: |
514 | .nothing: |
483 | ret |
515 | ret |
Line 484... | Line 516... | ||
484 | 516 | ||
Line 523... | Line 555... | ||
523 | mov al, DISKFUNC.querymedia |
555 | mov al, DISKFUNC.querymedia |
524 | stdcall disk_call_driver, edx |
556 | stdcall disk_call_driver, edx |
525 | ; 3b. Check the result of the callback. Abort if it failed. |
557 | ; 3b. Check the result of the callback. Abort if it failed. |
526 | test eax, eax |
558 | test eax, eax |
527 | jnz .noinsert |
559 | jnz .noinsert |
- | 560 | ; 3c. Allocate the cache unless disabled by the driver. Abort if failed. |
|
- | 561 | call disk_init_cache |
|
- | 562 | test al, al |
|
- | 563 | jz .noinsert |
|
528 | ; 3c. Acquire the lifetime reference for the media object. |
564 | ; 3d. Acquire the lifetime reference for the media object. |
529 | inc [esi+DISK.MediaRefCount] |
565 | inc [esi+DISK.MediaRefCount] |
530 | ; 3d. Scan for partitions. Ignore result; the list of partitions is valid even |
566 | ; 3e. Scan for partitions. Ignore result; the list of partitions is valid even |
531 | ; on errors. |
567 | ; on errors. |
532 | call disk_scan_partitions |
568 | call disk_scan_partitions |
533 | ; 3e. Media is inserted and available for use. |
569 | ; 3f. Media is inserted and available for use. |
534 | inc [esi+DISK.MediaInserted] |
570 | inc [esi+DISK.MediaInserted] |
535 | .noinsert: |
571 | .noinsert: |
536 | ; 4. Return. |
572 | ; 4. Return. |
537 | pop edi esi ebx ; restore used registers to be stdcall |
573 | pop edi esi ebx ; restore used registers to be stdcall |
538 | ret 8 ; purge 2 dword arguments to be stdcall |
574 | ret 8 ; purge 2 dword arguments to be stdcall |
Line 584... | Line 620... | ||
584 | disk_default_closemedia: |
620 | disk_default_closemedia: |
585 | disk_default_flush: |
621 | disk_default_flush: |
586 | xor eax, eax |
622 | xor eax, eax |
587 | ret 4 |
623 | ret 4 |
Line -... | Line 624... | ||
- | 624 | ||
- | 625 | ; The default implementation of DISKFUNC.adjust_cache_size. |
|
- | 626 | disk_default_adjust_cache_size: |
|
- | 627 | mov eax, [esp+4] |
|
- | 628 | ret 4 |
|
588 | 629 | ||
589 | ; This is an internal function called from 'disk_media_changed' when new media |
630 | ; This is an internal function called from 'disk_media_changed' when new media |
590 | ; is detected. It creates the list of partitions for the media. |
631 | ; is detected. It creates the list of partitions for the media. |
591 | ; If media is not partitioned, then the list consists of one partition which |
632 | ; If media is not partitioned, then the list consists of one partition which |
592 | ; covers all the media. |
633 | ; covers all the media. |
Line 607... | Line 648... | ||
607 | ; the 'partition_buffer_users' variable. |
648 | ; the 'partition_buffer_users' variable. |
608 | mov ebx, mbr_buffer ; assume the global buffer is free |
649 | mov ebx, mbr_buffer ; assume the global buffer is free |
609 | lock inc [partition_buffer_users] |
650 | lock inc [partition_buffer_users] |
610 | jz .buffer_acquired ; yes, it is free |
651 | jz .buffer_acquired ; yes, it is free |
611 | lock dec [partition_buffer_users] ; no, we must allocate |
652 | lock dec [partition_buffer_users] ; no, we must allocate |
612 | stdcall kernel_alloc, 1024 |
653 | stdcall kernel_alloc, 512*3 |
613 | test eax, eax |
654 | test eax, eax |
614 | jz .nothing |
655 | jz .nothing |
615 | xchg eax, ebx |
656 | xchg eax, ebx |
616 | .buffer_acquired: |
657 | .buffer_acquired: |
617 | ; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no |
658 | ; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no |
Line 710... | Line 751... | ||
710 | ; are most likely partitioned with GPT, not MBR scheme, since the precise |
751 | ; are most likely partitioned with GPT, not MBR scheme, since the precise |
711 | ; calculation here would increase limit just twice at the price of big |
752 | ; calculation here would increase limit just twice at the price of big |
712 | ; compatibility problems. |
753 | ; compatibility problems. |
713 | pop eax ; load extended partition |
754 | pop eax ; load extended partition |
714 | add ebp, eax |
755 | add ebp, eax |
- | 756 | jc .mbr_failed |
|
715 | ; 12c. If extended partition has not yet started, start it. |
757 | ; 12c. If extended partition has not yet started, start it. |
716 | test eax, eax |
758 | test eax, eax |
717 | jnz @f |
759 | jnz @f |
718 | mov eax, ebp |
760 | mov eax, ebp |
719 | @@: |
761 | @@: |
Line 847... | Line 889... | ||
847 | mov ecx, [edi] |
889 | mov ecx, [edi] |
848 | add edi, 4 |
890 | add edi, 4 |
849 | ; The range [.FirstSector, .FirstSector+.Length) must be either entirely to |
891 | ; The range [.FirstSector, .FirstSector+.Length) must be either entirely to |
850 | ; the left of [start, start+length) or entirely to the right. |
892 | ; the left of [start, start+length) or entirely to the right. |
851 | ; 2c. Subtract .FirstSector - start. The possible overflow distinguish between |
893 | ; 2c. Subtract .FirstSector - start. The possible overflow distinguish between |
852 | ; cases "to the left" (2?) and "to the right" (2d). |
894 | ; cases "to the left" (2e) and "to the right" (2d). |
853 | mov eax, dword [ecx+PARTITION.FirstSector] |
895 | mov eax, dword [ecx+PARTITION.FirstSector] |
854 | mov edx, dword [ecx+PARTITION.FirstSector+4] |
896 | mov edx, dword [ecx+PARTITION.FirstSector+4] |
855 | sub eax, dword [start] |
897 | sub eax, dword [start] |
856 | sbb edx, dword [start+4] |
898 | sbb edx, dword [start+4] |
857 | jb .less |
899 | jb .less |