Subversion Repositories Kolibri OS

Rev

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