Rev 2120 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2120 | Rev 2129 | ||
---|---|---|---|
Line 117... | Line 117... | ||
117 | ; Another reference is taken during any filesystem operation for this disk. |
117 | ; Another reference is taken during any filesystem operation for this disk. |
118 | ; One reference is added if media is inserted. |
118 | ; One reference is added if media is inserted. |
119 | ; The structure is destroyed when the reference count decrements to zero: |
119 | ; The structure is destroyed when the reference count decrements to zero: |
120 | ; this usually occurs in 'disk_del', but can be delayed to the end of last |
120 | ; this usually occurs in 'disk_del', but can be delayed to the end of last |
121 | ; filesystem operation, if one is active. |
121 | ; filesystem operation, if one is active. |
122 | .MediaLock dd ? |
122 | .MediaLock MUTEX |
123 | ; Lock to protect the MEDIA structure. See the description after |
123 | ; Lock to protect the MEDIA structure. See the description after |
124 | ; 'disk_list_mutex' for the locking strategy. |
124 | ; 'disk_list_mutex' for the locking strategy. |
125 | ; Fields of media object |
125 | ; Fields of media object |
126 | .MediaInserted db ? |
126 | .MediaInserted db ? |
127 | ; 0 if media is not inserted, nonzero otherwise. |
127 | ; 0 if media is not inserted, nonzero otherwise. |
Line 196... | Line 196... | ||
196 | dd disk_list |
196 | dd disk_list |
197 | dd disk_list |
197 | dd disk_list |
198 | endg |
198 | endg |
199 | uglobal |
199 | uglobal |
200 | ; This mutex guards all operations with the global list of DISK structures. |
200 | ; This mutex guards all operations with the global list of DISK structures. |
201 | disk_list_mutex dd 0 |
201 | disk_list_mutex MUTEX |
202 | ; * There are two dependent objects, a disk and a media. In the simplest case |
202 | ; * There are two dependent objects, a disk and a media. In the simplest case |
203 | ; disk and media are both non-removable. However, in the general case both |
203 | ; disk and media are both non-removable. However, in the general case both |
204 | ; can be removed at any time, simultaneously or only media, this makes things |
204 | ; can be removed at any time, simultaneously or only media, this makes things |
205 | ; complicated. |
205 | ; complicated. |
206 | ; * For efficiency, both disk and media objects are located in the one |
206 | ; * For efficiency, both disk and media objects are located in the one |
Line 343... | Line 343... | ||
343 | mov eax, [esp+16+8] |
343 | mov eax, [esp+16+8] |
344 | mov [ebx+DISK.DriverFlags], eax |
344 | mov [ebx+DISK.DriverFlags], eax |
345 | ; 4. Initialize other fields of the DISK structure. |
345 | ; 4. Initialize other fields of the DISK structure. |
346 | ; Media is not inserted, initialized state of mutex is zero, |
346 | ; Media is not inserted, initialized state of mutex is zero, |
347 | ; reference counter is 1. |
347 | ; reference counter is 1. |
- | 348 | lea ecx, [ebx+DISK.MediaLock] |
|
- | 349 | call mutex_init |
|
348 | xor eax, eax |
350 | xor eax, eax |
349 | mov dword [ebx+DISK.MediaInserted], eax |
351 | mov dword [ebx+DISK.MediaInserted], eax |
350 | mov [ebx+DISK.MediaLock], eax |
- | |
351 | inc eax |
352 | inc eax |
352 | mov [ebx+DISK.RefCount], eax |
353 | mov [ebx+DISK.RefCount], eax |
353 | ; The DISK structure is initialized. |
354 | ; The DISK structure is initialized. |
354 | ; 5. Insert the new structure to the global list. |
355 | ; 5. Insert the new structure to the global list. |
355 | xchg eax, ebx ; now eax = pointer to DISK |
- | |
356 | ; 5a. Acquire the mutex. |
356 | ; 5a. Acquire the mutex. |
357 | mov ebx, disk_list_mutex |
357 | mov ecx, disk_list_mutex |
358 | call wait_mutex |
358 | call mutex_lock |
359 | ; 5b. Insert item to the tail of double-linked list. |
359 | ; 5b. Insert item to the tail of double-linked list. |
360 | mov edx, disk_list |
360 | mov edx, disk_list |
361 | mov ecx, [edx+DISK.Prev] |
361 | list_add_tail ebx, edx ;ebx= new edx= list head |
362 | mov [eax+DISK.Prev], ecx |
- | |
363 | mov [eax+DISK.Next], edx |
- | |
364 | mov [edx+DISK.Prev], eax |
- | |
365 | mov [ecx+DISK.Next], eax |
- | |
366 | ; 5c. Release the mutex. |
362 | ; 5c. Release the mutex. |
367 | mov dword [ebx], 0 |
363 | call mutex_unlock |
368 | ; 6. Return with eax = pointer to DISK. |
364 | ; 6. Return with eax = pointer to DISK. |
- | 365 | xchg eax, ebx |
|
369 | jmp .nothing |
366 | jmp .nothing |
370 | .free: |
367 | .free: |
371 | ; Memory allocation for DISK structure succeeded, but for disk name failed. |
368 | ; Memory allocation for DISK structure succeeded, but for disk name failed. |
372 | ; 7. Free the DISK structure. |
369 | ; 7. Free the DISK structure. |
373 | xchg eax, ebx |
370 | xchg eax, ebx |
Line 386... | Line 383... | ||
386 | ; - dereferencing the DISK structure and possibly destroying it. |
383 | ; - dereferencing the DISK structure and possibly destroying it. |
387 | ; Parameters: |
384 | ; Parameters: |
388 | ; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. |
385 | ; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. |
389 | ; Return value: none. |
386 | ; Return value: none. |
390 | disk_del: |
387 | disk_del: |
391 | push ebx esi ; save used registers to be stdcall |
388 | push esi ; save used registers to be stdcall |
392 | ; 1. Force media to be removed. If the media is already removed, the |
389 | ; 1. Force media to be removed. If the media is already removed, the |
393 | ; call does nothing. |
390 | ; call does nothing. |
394 | mov esi, [esp+4+8] ; esi = handle of the disk |
391 | mov esi, [esp+4+8] ; esi = handle of the disk |
395 | stdcall disk_media_changed, esi, 0 |
392 | stdcall disk_media_changed, esi, 0 |
396 | ; 2. Delete the structure from the global list. |
393 | ; 2. Delete the structure from the global list. |
397 | ; 2a. Acquire the mutex. |
394 | ; 2a. Acquire the mutex. |
398 | mov ebx, disk_list_mutex |
395 | mov ecx, disk_list_mutex |
399 | call wait_mutex |
396 | call mutex_lock |
400 | ; 2b. Delete item from double-linked list. |
397 | ; 2b. Delete item from double-linked list. |
401 | mov eax, [esi+DISK.Next] |
398 | mov eax, [esi+DISK.Next] |
402 | mov edx, [esi+DISK.Prev] |
399 | mov edx, [esi+DISK.Prev] |
403 | mov [eax+DISK.Prev], edx |
400 | mov [eax+DISK.Prev], edx |
404 | mov [edx+DISK.Next], eax |
401 | mov [edx+DISK.Next], eax |
405 | ; 2c. Release the mutex. |
402 | ; 2c. Release the mutex. |
406 | mov dword [ebx], 0 |
403 | call mutex_unlock |
407 | ; 3. The structure still has one reference created in disk_add. Remove this |
404 | ; 3. The structure still has one reference created in disk_add. Remove this |
408 | ; reference. If there are no other references, disk_dereference will free the |
405 | ; reference. If there are no other references, disk_dereference will free the |
409 | ; structure. |
406 | ; structure. |
410 | call disk_dereference |
407 | call disk_dereference |
411 | ; 4. Return. |
408 | ; 4. Return. |
412 | pop esi ebx ; restore used registers to be stdcall |
409 | pop esi ; restore used registers to be stdcall |
413 | ret 4 ; purge 1 dword argument to be stdcall |
410 | ret 4 ; purge 1 dword argument to be stdcall |
Line 414... | Line 411... | ||
414 | 411 | ||
415 | ; This is an internal function which removes a previously obtained reference |
412 | ; This is an internal function which removes a previously obtained reference |
416 | ; to the disk. If this is the last reference, this function lets the driver |
413 | ; to the disk. If this is the last reference, this function lets the driver |
Line 500... | Line 497... | ||
500 | ; required for checking. |
497 | ; required for checking. |
501 | cmp [esi+DISK.MediaInserted], 0 |
498 | cmp [esi+DISK.MediaInserted], 0 |
502 | jz .noremove |
499 | jz .noremove |
503 | ; We really need to remove the media. |
500 | ; We really need to remove the media. |
504 | ; 1b. Acquire mutex. |
501 | ; 1b. Acquire mutex. |
505 | lea ebx, [esi+DISK.MediaLock] |
502 | lea ecx, [esi+DISK.MediaLock] |
506 | call wait_mutex |
503 | call mutex_lock |
507 | ; 1c. Clear the flag. |
504 | ; 1c. Clear the flag. |
508 | mov [esi+DISK.MediaInserted], 0 |
505 | mov [esi+DISK.MediaInserted], 0 |
509 | ; 1d. Release mutex. |
506 | ; 1d. Release mutex. |
510 | mov dword [ebx], 0 |
507 | call mutex_unlock |
511 | ; 1e. Remove the "lifetime" reference and possibly destroy the structure. |
508 | ; 1e. Remove the "lifetime" reference and possibly destroy the structure. |
512 | call disk_media_dereference |
509 | call disk_media_dereference |
513 | .noremove: |
510 | .noremove: |
514 | ; 2. Test whether there is new media. |
511 | ; 2. Test whether there is new media. |
515 | cmp dword [esp+8+12], 0 |
512 | cmp dword [esp+8+12], 0 |
Line 966... | Line 963... | ||
966 | ; but instead pop return address and return directly to the caller |
963 | ; but instead pop return address and return directly to the caller |
967 | ; otherwise simply return |
964 | ; otherwise simply return |
968 | dyndisk_handler: |
965 | dyndisk_handler: |
969 | push ebx edi ; save registers used in file_system_lfn |
966 | push ebx edi ; save registers used in file_system_lfn |
970 | ; 1. Acquire the mutex. |
967 | ; 1. Acquire the mutex. |
971 | mov ebx, disk_list_mutex |
968 | mov ecx, disk_list_mutex |
972 | call wait_mutex |
969 | call mutex_lock |
973 | ; 2. Loop over the list of DISK structures. |
970 | ; 2. Loop over the list of DISK structures. |
974 | ; 2a. Initialize. |
971 | ; 2a. Initialize. |
975 | mov ecx, disk_list |
972 | mov ebx, disk_list |
976 | .scan: |
973 | .scan: |
977 | ; 2b. Get the next item. |
974 | ; 2b. Get the next item. |
978 | mov ecx, [ecx+DISK.Next] |
975 | mov ebx, [ebx+DISK.Next] |
979 | ; 2c. Check whether the list is done. If so, go to 3. |
976 | ; 2c. Check whether the list is done. If so, go to 3. |
980 | cmp ecx, disk_list |
977 | cmp ebx, disk_list |
981 | jz .notfound |
978 | jz .notfound |
982 | ; 2d. Compare names. If names match, go to 5. |
979 | ; 2d. Compare names. If names match, go to 5. |
983 | mov edi, [ecx+DISK.Name] |
980 | mov edi, [ebx+DISK.Name] |
984 | push esi |
981 | push esi |
985 | @@: |
982 | @@: |
986 | ; esi points to the name from fs operation; it is terminated by zero or slash. |
983 | ; esi points to the name from fs operation; it is terminated by zero or slash. |
987 | lodsb |
984 | lodsb |
988 | test al, al |
985 | test al, al |
Line 1003... | Line 1000... | ||
1003 | pop esi |
1000 | pop esi |
1004 | jmp .scan |
1001 | jmp .scan |
1005 | .notfound: |
1002 | .notfound: |
1006 | ; The loop is done and no name matches. |
1003 | ; The loop is done and no name matches. |
1007 | ; 3. Release the mutex. |
1004 | ; 3. Release the mutex. |
1008 | mov dword [ebx], 0 |
1005 | call mutex_unlock |
1009 | ; 4. Return normally. |
1006 | ; 4. Return normally. |
1010 | pop edi ebx ; restore registers used in file_system_lfn |
1007 | pop edi ebx ; restore registers used in file_system_lfn |
1011 | ret |
1008 | ret |
1012 | ; part of 2d: the name matches partially, but we must check that this is full |
1009 | ; part of 2d: the name matches partially, but we must check that this is full |
1013 | ; equality. |
1010 | ; equality. |
Line 1016... | Line 1013... | ||
1016 | .eoin: |
1013 | .eoin: |
1017 | cmp byte [edi], 0 |
1014 | cmp byte [edi], 0 |
1018 | jnz .wrongname |
1015 | jnz .wrongname |
1019 | ; We found the addressed DISK structure. |
1016 | ; We found the addressed DISK structure. |
1020 | ; 5. Reference the disk. |
1017 | ; 5. Reference the disk. |
1021 | lock inc [ecx+DISK.RefCount] |
1018 | lock inc [ebx+DISK.RefCount] |
1022 | ; 6. Now we are sure that the DISK structure is not going to die at least |
1019 | ; 6. Now we are sure that the DISK structure is not going to die at least |
1023 | ; while we are working with it, so release the global mutex. |
1020 | ; while we are working with it, so release the global mutex. |
1024 | mov dword [ebx], 0 |
1021 | call mutex_unlock |
1025 | ; 7. Acquire the mutex for media object. |
1022 | ; 7. Acquire the mutex for media object. |
1026 | pop edi ; restore edi |
1023 | pop edi ; restore edi |
1027 | lea ebx, [ecx+DISK.MediaLock] |
1024 | lea ecx, [ebx+DISK.MediaLock] |
1028 | call wait_mutex |
1025 | call mutex_lock |
1029 | ; 8. Get the media object. If it is not NULL, reference it. |
1026 | ; 8. Get the media object. If it is not NULL, reference it. |
1030 | xor edx, edx |
1027 | xor edx, edx |
1031 | cmp [ecx+DISK.MediaInserted], dl |
1028 | cmp [ebx+DISK.MediaInserted], dl |
1032 | jz @f |
1029 | jz @f |
1033 | mov edx, ecx |
1030 | mov edx, ebx |
1034 | inc [ecx+DISK.MediaRefCount] |
1031 | inc [ebx+DISK.MediaRefCount] |
1035 | @@: |
1032 | @@: |
1036 | ; 9. Now we are sure that the media object, if it exists, is not going to die |
1033 | ; 9. Now we are sure that the media object, if it exists, is not going to die |
1037 | ; at least while we are working with it, so release the mutex for media object. |
1034 | ; at least while we are working with it, so release the mutex for media object. |
- | 1035 | call mutex_unlock |
|
1038 | mov dword [ebx], 0 |
1036 | mov ecx, ebx |
1039 | pop ebx eax ; restore ebx, pop return address |
1037 | pop ebx eax ; restore ebx, pop return address |
1040 | ; 10. Check whether the fs operation wants to enumerate partitions (go to 11) |
1038 | ; 10. Check whether the fs operation wants to enumerate partitions (go to 11) |
1041 | ; or work with some concrete partition (go to 12). |
1039 | ; or work with some concrete partition (go to 12). |
1042 | cmp byte [esi], 0 |
1040 | cmp byte [esi], 0 |
1043 | jnz .haspartition |
1041 | jnz .haspartition |
Line 1150... | Line 1148... | ||
1150 | test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION |
1148 | test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION |
1151 | jz .deverror |
1149 | jz .deverror |
1152 | ; if the driver does not support insert notifications and we are the only fs |
1150 | ; if the driver does not support insert notifications and we are the only fs |
1153 | ; operation with this disk, issue the fake insert notification; if media is |
1151 | ; operation with this disk, issue the fake insert notification; if media is |
1154 | ; still not inserted, 'disk_media_changed' will detect this and do nothing |
1152 | ; still not inserted, 'disk_media_changed' will detect this and do nothing |
1155 | push ebx |
1153 | ;;; push ebx |
1156 | lea ebx, [edx+DISK.MediaLock] |
1154 | lea ecx, [edx+DISK.MediaLock] |
1157 | call wait_mutex |
1155 | call mutex_lock |
1158 | cmp [edx+DISK.MediaRefCount], 1 |
1156 | cmp [edx+DISK.MediaRefCount], 1 |
1159 | jnz .noluck |
1157 | jnz .noluck |
1160 | mov dword [ebx], 0 |
1158 | call mutex_unlock |
1161 | push edx |
1159 | push edx |
1162 | stdcall disk_media_changed, edx, 1 |
1160 | stdcall disk_media_changed, edx, 1 |
1163 | pop edx |
1161 | pop edx |
- | 1162 | lea ecx, [edx+DISK.MediaLock] |
|
1164 | call wait_mutex |
1163 | call mutex_lock |
1165 | cmp [edx+DISK.MediaInserted], 0 |
1164 | cmp [edx+DISK.MediaInserted], 0 |
1166 | jz .noluck |
1165 | jz .noluck |
1167 | lock inc [edx+DISK.MediaRefCount] |
1166 | lock inc [edx+DISK.MediaRefCount] |
1168 | mov dword [ebx], 0 |
1167 | call mutex_unlock |
1169 | xor ecx, ecx |
1168 | xor ecx, ecx |
1170 | jmp .main |
1169 | jmp .main |
1171 | .noluck: |
1170 | .noluck: |
1172 | mov dword [ebx], 0 |
1171 | call mutex_unlock |
1173 | .deverror: |
1172 | .deverror: |
1174 | mov dword [esp+32], ERROR_DEVICE |
1173 | mov dword [esp+32], ERROR_DEVICE |
1175 | mov esi, edx |
1174 | mov esi, edx |
1176 | call disk_dereference |
1175 | call disk_dereference |
1177 | ret |
1176 | ret |
Line 1183... | Line 1182... | ||
1183 | ; in: eax = 0 for first call, previously returned value for subsequent calls |
1182 | ; in: eax = 0 for first call, previously returned value for subsequent calls |
1184 | ; out: eax = 0 => no more items |
1183 | ; out: eax = 0 => no more items |
1185 | ; eax != 0 => buffer pointed to by edi contains name of item |
1184 | ; eax != 0 => buffer pointed to by edi contains name of item |
1186 | dyndisk_enum_root: |
1185 | dyndisk_enum_root: |
1187 | push ebx ; save register used in file_system_lfn |
1186 | push ebx ; save register used in file_system_lfn |
1188 | mov ebx, disk_list_mutex ; it will be useful |
1187 | mov ecx, disk_list_mutex ; it will be useful |
1189 | ; 1. If this is the first call, acquire the mutex and initialize. |
1188 | ; 1. If this is the first call, acquire the mutex and initialize. |
1190 | test eax, eax |
1189 | test eax, eax |
1191 | jnz .notfirst |
1190 | jnz .notfirst |
1192 | call wait_mutex |
1191 | call mutex_lock |
1193 | mov eax, disk_list |
1192 | mov eax, disk_list |
1194 | .notfirst: |
1193 | .notfirst: |
1195 | ; 2. Get next item. |
1194 | ; 2. Get next item. |
1196 | mov eax, [eax+DISK.Next] |
1195 | mov eax, [eax+DISK.Next] |
1197 | ; 3. If there are no more items, go to 6. |
1196 | ; 3. If there are no more items, go to 6. |
Line 1209... | Line 1208... | ||
1209 | ; 5. Return with eax = item. |
1208 | ; 5. Return with eax = item. |
1210 | pop ebx ; restore register used in file_system_lfn |
1209 | pop ebx ; restore register used in file_system_lfn |
1211 | ret |
1210 | ret |
1212 | .last: |
1211 | .last: |
1213 | ; 6. Release the mutex and return with eax = 0. |
1212 | ; 6. Release the mutex and return with eax = 0. |
- | 1213 | call mutex_unlock |
|
1214 | xor eax, eax |
1214 | xor eax, eax |
1215 | mov dword [ebx], eax |
- | |
1216 | pop ebx ; restore register used in file_system_lfn |
1215 | pop ebx ; restore register used in file_system_lfn |
1217 | ret |
1216 | ret |