Subversion Repositories Kolibri OS

Rev

Rev 78 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;;  FAT32.INC                                                      ;;
4
;;                                                                 ;;
5
;;  FAT16/32 functions for MenuetOS                                ;;
6
;;                                                                 ;;
7
;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
8
;;                                                                 ;;
9
;;  See file COPYING for details                                   ;;
83 diamond 10
;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
75 diamond 11
;;  04.05.2006 LFN read folder - diamond                           ;;
74 mario79 12
;;  29.04.2006 Elimination of hangup after the                     ;;
13
;;             expiration hd_wait_timeout -  Mario79               ;;
75 diamond 14
;;  23.04.2006 LFN read file - diamond                             ;;
65 mario79 15
;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
16
;;             to MBR, see file part_set.inc - Mario79             ;;
1 ha 17
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
18
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
19
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
20
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
21
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
22
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
23
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
24
;;  08.11.2004 rename - ATV                                        ;;
25
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
26
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
27
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
28
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
29
;;  24.5.2004  Write back buffer for File_write -VT                ;;
30
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
31
;;  30.3.2004  Error parameters at function return - VT            ;;
32
;;  01.5.2002  Bugfix in device write - VT                         ;;
33
;;  20.5.2002  Hd status check - VT                                ;;
34
;;  29.6.2002  Improved fat32 verification - VT                    ;;
35
;;                                                                 ;;
36
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37
 
38
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
39
 
52 mikedld 40
ERROR_SUCCESS        = 0
41
ERROR_DISK_BASE      = 1
42
ERROR_UNSUPPORTED_FS = 2
43
ERROR_UNKNOWN_FS     = 3
44
ERROR_PARTITION      = 4
45
ERROR_FILE_NOT_FOUND = 5
46
ERROR_END_OF_FILE    = 6
47
ERROR_MEMORY_POINTER = 7
48
ERROR_DISK_FULL      = 8
49
ERROR_FAT_TABLE      = 9
50
ERROR_ACCESS_DENIED  = 10
1 ha 51
 
52
PUSHAD_EAX equ [esp+28]
53
PUSHAD_ECX equ [esp+24]
54
PUSHAD_EDX equ [esp+20]
55
PUSHAD_EBX equ [esp+16]
56
PUSHAD_EBP equ [esp+8]
57
PUSHAD_ESI equ [esp+4]
58
PUSHAD_EDI equ [esp+0]
59
 
60
cluster              dd 0       ; used by file_write,makedir,append
61
partition_count      dd 0       ; partitions found by set_FAT32_variables
62
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
63
longname_sec2        dd 0       ; directory sectors for delete long filename
64
 
65
hd_error             dd 0       ; set by wait_for_sector_buffer
66
hd_setup             dd 0
67
hd_wait_timeout      dd 0
68
 
69
cluster_tmp          dd 0       ; used by analyze_directory
70
                                ; and analyze_directory_to_write
71
 
72
file_size            dd 0       ; used by file_read
73
 
74
sector_tmp           dd 0       ; used by rename,append,file_write
75
entry_pos            dd 0       ; used by rename,append,file_write
76
 
77
old_filesize         dd 0       ; used by append
78
new_filepos          dd 0       ; used by append
79
bytes2write          dd 0       ; used by append
80
 
81
cache_search_start   dd 0       ; used by find_empty_slot
82
 
83
fat_in_cache         dd -1
84
fat_cache:           times 512 db 0
85
 
86
uglobal
87
 Sector512:                      ; label for dev_hdcd.inc
88
  buffer:              times 512 db 0
89
  deltree_buffer:      times 512 db 0
90
endg
91
 
92
iglobal
93
  NewDirEntry1         db ".          ",0x10
94
                     times 20 db 0
95
  NewDirEntry2         db "..         ",0x10
96
                     times 20 db 0
97
endg
98
 
99
uglobal
100
  dir_entry:           times 32 db 0
101
 
102
  startpath:           times 255 db 0
103
 
104
  fat16_root           db 0       ; flag for fat16 rootdir
105
  f_del                db 0       ; 1=overwrite fat entry
106
  fat_change           db 0       ; 1=fat has changed
107
 
108
endg
109
 
110
reserve_hd1:
111
 
112
    cli
113
    cmp   [hd1_status],0
114
    je    reserve_ok1
115
 
116
    sti
117
    call  change_task
118
    jmp   reserve_hd1
119
 
120
  reserve_ok1:
121
 
122
    push  eax
123
    mov   eax,[0x3000]
124
    shl   eax,5
125
    mov   eax,[eax+0x3000+4]
126
    mov   [hd1_status],eax
127
    pop   eax
128
    sti
129
    ret
130
 
131
 
132
clear_hd_cache:
133
 
134
    push  eax ecx edi
135
    mov   edi,0x600000
136
    mov   ecx,16384
137
    xor   eax,eax
138
    cld
139
    rep   stosd                 ; clear hd cache with 0
140
    mov   [cache_search_start],eax
141
    mov   [fat_in_cache],-1
142
    mov   [fat_change],0
143
    pop   edi ecx eax
144
    ret
145
 
146
problem_partition db 0  ; used for partitions search
147
 
65 mario79 148
include  'part_set.inc'
1 ha 149
 
150
set_FAT:
151
;--------------------------------
152
; input  : EAX = cluster
153
;          EDX = value to save
154
; output : EDX = old value
155
;--------------------------------
156
    push  eax ebx esi
157
 
158
    cmp   eax,2
159
    jb    sfc_error
160
    cmp   eax,[LAST_CLUSTER]
161
    ja    sfc_error
162
    cmp   [fat_type],16
163
    je    sfc_1
164
    add   eax,eax
165
  sfc_1:
166
    add   eax,eax
167
    mov   esi,511
168
    and   esi,eax               ; esi = position in fat sector
169
    shr   eax,9                 ; eax = fat sector
170
    add   eax,[FAT_START]
171
    mov   ebx,fat_cache
172
 
173
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
174
    je    sfc_in_cache          ; yes
175
 
176
    cmp   [fat_change],0        ; is fat changed?
177
    je    sfc_no_change         ; no
178
    call  write_fat_sector      ; yes. write it into disk
74 mario79 179
    cmp   [hd_error],0
180
    jne   sfc_error
1 ha 181
 
182
  sfc_no_change:
183
    mov   [fat_in_cache],eax    ; save fat sector
184
    call  hd_read
74 mario79 185
    cmp  [hd_error],0
186
    jne  sfc_error
187
 
1 ha 188
 
189
  sfc_in_cache:
190
    cmp   [fat_type],16
191
    jne   sfc_test32
192
 
193
    cmp   [f_del],1             ; overwrite previous value?
194
    je    sfc_set16             ; yes
195
    cmp   word [ebx+esi],0      ; is cluster free?
196
    je    sfc_set16             ; yes
197
    mov   dword [8*0x100000],0xffffff
198
    mov   edx,[ebx+esi]         ; get old value
199
    jmp   sfc_nonzero
200
 
201
  sfc_set16:
202
    xchg  [ebx+esi],dx          ; save new value and get old value
203
    jmp   sfc_write
204
 
205
  sfc_test32:
206
    mov   eax,[fatMASK]
207
    cmp   [f_del],1             ; overwrite previous value?
208
    je    sfc_set32             ; yes
209
    test  eax,[ebx+esi]         ; is cluster free?
210
    je    sfc_set32             ; yes
211
    mov   dword [8*0x100000],0xffffff
212
    mov   edx,[ebx+esi]         ; get old value
213
    jmp   sfc_nonzero
214
 
215
  sfc_set32:
216
    and   edx,eax
217
    xor   eax,-1                ; mask for high bits
218
    and   eax,[ebx+esi]         ; get high 4 bits
219
    or    eax,edx
220
    mov   edx,[ebx+esi]         ; get old value
221
    mov   [ebx+esi],eax         ; save new value
222
 
223
  sfc_write:
224
    mov   [fat_change],1        ; fat has changed
225
 
226
  sfc_nonzero:
227
    and   edx,[fatMASK]
228
 
229
  sfc_error:
230
    pop   esi ebx eax
231
    ret
232
 
233
 
234
get_FAT:
235
;--------------------------------
236
; input  : EAX = cluster
237
; output : EAX = next cluster
238
;--------------------------------
239
    push  ebx esi
240
 
241
    cmp   [fat_type],16
242
    je    gfc_1
243
    add   eax,eax
244
  gfc_1:
245
    add   eax,eax
246
    mov   esi,511
247
    and   esi,eax               ; esi = position in fat sector
248
    shr   eax,9                 ; eax = fat sector
249
    add   eax,[FAT_START]
250
    mov   ebx,fat_cache
251
 
252
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
253
    je    gfc_in_cache
254
 
255
    cmp   [fat_change],0        ; is fat changed?
256
    je    gfc_no_change         ; no
257
    call  write_fat_sector      ; yes. write it into disk
74 mario79 258
    cmp  [hd_error],0
259
    jne  hd_error_01
1 ha 260
 
261
  gfc_no_change:
262
    mov   [fat_in_cache],eax
263
    call  hd_read
74 mario79 264
    cmp  [hd_error],0
265
    jne  hd_error_01
1 ha 266
 
267
  gfc_in_cache:
268
    mov   eax,[ebx+esi]
269
    and   eax,[fatMASK]
74 mario79 270
 hd_error_01:
1 ha 271
    pop   esi ebx
272
    ret
273
 
274
 
275
get_free_FAT:
276
;-----------------------------------------------------------
277
; input  : EAX = # cluster for start the searching
278
; output : if CARRY=0 EAX = # first cluster found free
279
;          if CARRY=1 disk full
280
; Note   : for more speed need to use fat_cache directly
281
;-----------------------------------------------------------
282
    push  ecx
283
    mov   ecx,[LAST_CLUSTER]    ; counter for full disk
284
    sub   ecx,2
285
 
286
  gff_test:
287
    cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
288
    jbe   gff_in_range
289
    mov   eax,2
290
 
291
  gff_in_range:
292
    push  eax
293
    call  get_FAT               ; get cluster state
74 mario79 294
    cmp   [hd_error],0
295
    jne   gff_not_found_1
296
 
1 ha 297
    test  eax,eax               ; is it free?
298
    pop   eax
299
    je    gff_found             ; yes
300
    inc   eax                   ; next cluster
301
    dec   ecx                   ; is all checked?
302
    jns   gff_test              ; no
303
 
74 mario79 304
  gff_not_found_1:
305
    add   esp,4
1 ha 306
  gff_not_found:
307
    pop   ecx                   ; yes. disk is full
308
    stc
309
    ret
310
 
311
  gff_found:
312
    pop   ecx
313
    clc
314
    ret
315
 
316
 
317
write_fat_sector:
318
;-----------------------------------------------------------
319
; write changed fat to disk
320
;-----------------------------------------------------------
321
    push  eax ebx ecx
322
 
323
    mov   [fat_change],0
324
    mov   eax,[fat_in_cache]
325
    cmp   eax,-1
326
    jz    write_fat_not_used
327
    mov   ebx,fat_cache
328
    mov   ecx,[NUMBER_OF_FATS]
329
 
330
  write_next_fat:
331
    call  hd_write
74 mario79 332
    cmp   [hd_error],0
333
    jne   write_fat_not_used
334
 
1 ha 335
    add   eax,[SECTORS_PER_FAT]
336
    dec   ecx
337
    jnz   write_next_fat
338
 
339
  write_fat_not_used:
340
    pop   ecx ebx eax
341
    ret
342
 
343
 
344
analyze_directory:
345
;-----------------------------------------------------------
346
; input  : EAX = first cluster of the directory
347
;          EBX = pointer to filename
348
; output : IF CARRY=0 EAX = sector where th file is found
349
;                     EBX = pointer in buffer
350
;                     [buffer .. buffer+511]
351
;                     ECX,EDX,ESI,EDI not changed
352
;          IF CARRY=1 filename not found
353
; Note   : if cluster=0 it's changed to read rootdir
354
;          save 2 previous directory sectors in longname_sec
355
;-----------------------------------------------------------
356
    push  ecx edx esi edi ebx   ; ebx = [esp+0]
357
    mov   [longname_sec1],0
358
    mov   [longname_sec2],0
359
 
360
  adr_new_cluster:
361
    mov   [cluster_tmp],eax
362
    mov   [fat16_root],0
363
    cmp   eax,[LAST_CLUSTER]
364
    ja    adr_not_found         ; too big cluster number, something is wrong
365
    cmp   eax,2
366
    jnb   adr_data_cluster
367
 
368
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
369
    cmp   [fat_type],16
370
    jne   adr_data_cluster
371
    mov   eax,[ROOT_START]
372
    mov   edx,[ROOT_SECTORS]
373
    mov   [fat16_root],1        ; flag for fat16 rootdir
374
    jmp   adr_new_sector
375
 
376
  adr_data_cluster:
377
    sub   eax,2
378
    mov   edx,[SECTORS_PER_CLUSTER]
379
    imul  eax,edx
380
    add   eax,[DATA_START]
381
 
382
  adr_new_sector:
383
    mov   ebx,buffer
384
    call  hd_read
74 mario79 385
    cmp  [hd_error],0
386
    jne  adr_not_found
387
 
1 ha 388
    mov   ecx,512/32            ; count of dir entrys per sector = 16
389
 
390
  adr_analyze:
391
    mov   edi,[ebx+11]          ; file attribute
392
    and   edi,0xf
393
    cmp   edi,0xf
394
    je    adr_long_filename
395
    test  edi,0x8               ; skip over volume label
396
    jne   adr_long_filename     ; Note: label can be same name as file/dir
397
 
398
    mov   esi,[esp+0]           ; filename need to be uppercase
399
    mov   edi,ebx
400
    push  ecx
401
    mov   ecx,11
402
    cld
403
    rep   cmpsb                 ; compare 8+3 filename
404
    pop   ecx
405
    je    adr_found
406
 
407
  adr_long_filename:
408
    add   ebx,32                ; position of next dir entry
409
    dec   ecx
410
    jnz   adr_analyze
411
 
412
    mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
413
    mov   [longname_sec1],eax   ; for delete long filename
414
    mov   [longname_sec2],ecx
415
    inc   eax                   ; next sector
416
    dec   edx
417
    jne   adr_new_sector
418
    cmp   [fat16_root],1        ; end of fat16 rootdir
419
    je    adr_not_found
420
 
421
  adr_next_cluster:
422
    mov   eax,[cluster_tmp]
423
    call  get_FAT               ; get next cluster
74 mario79 424
    cmp  [hd_error],0
425
    jne  adr_not_found
426
 
1 ha 427
    cmp   eax,2                 ; incorrect fat chain?
428
    jb    adr_not_found         ; yes
429
    cmp   eax,[fatRESERVED]     ; is it end of directory?
430
    jb    adr_new_cluster       ; no. analyse it
431
 
432
  adr_not_found:
433
    pop   edi edi esi edx ecx   ; first edi will remove ebx
434
    stc                         ; file not found
435
    ret
436
 
437
  adr_found:
438
    pop   edi edi esi edx ecx   ; first edi will remove ebx
439
    clc                         ; file found
440
    ret
441
 
442
 
443
analyze_directory_to_write:
444
;-----------------------------------------------------------
445
; input  : EAX = first cluster of the directory
446
; output : IF CARRY=0 EAX = sector where the empty pos is found
447
;                     EBX = pointer in buffer
448
;                     [buffer .. buffer+511]
449
;                     ECX,EDX,ESI,EDI not changed
450
;          IF CARRY=1 disk full or fat corrupted
451
; Note   : if cluster=0 it's changed to read rootdir
452
;-----------------------------------------------------------
453
    push  ecx edx edi
454
 
455
  adw_new_cluster:
456
    mov   [cluster_tmp],eax
457
    mov   [fat16_root],0
458
    cmp   eax,[LAST_CLUSTER]
459
    ja    adw_not_found         ; too big cluster number, something is wrong
460
    cmp   eax,2
461
    jnb   adw_data_cluster
462
 
463
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
464
    cmp   [fat_type],16
465
    jne   adw_data_cluster
466
    mov   eax,[ROOT_START]
467
    mov   edx,[ROOT_SECTORS]
468
    mov   [fat16_root],1        ; flag for fat16 rootdir
469
    jmp   adw_new_sector
470
 
471
  adw_data_cluster:
472
    sub   eax,2
473
    mov   edx,[SECTORS_PER_CLUSTER]
474
    imul  eax,edx
475
    add   eax,[DATA_START]
476
 
477
  adw_new_sector:
478
    mov   ebx,buffer
479
    call  hd_read
74 mario79 480
    cmp  [hd_error],0
481
    jne  adw_not_found
482
 
1 ha 483
    mov   ecx,512/32            ; count of dir entrys per sector = 16
484
 
485
  adw_analyze:
486
    cmp   byte [ebx],0x00       ; is free entry?
487
    je    adw_found             ; yes
488
    cmp   byte [ebx],0xe5       ; is deleted entry?
489
    je    adw_found             ; yes
490
    add   ebx,32                ; position of next dir entry
491
    dec   ecx
492
    jnz   adw_analyze
493
 
494
    inc   eax                   ; next sector
495
    dec   edx
496
    jne   adw_new_sector
497
    cmp   [fat16_root],1        ; end of fat16 rootdir
498
    je    adw_not_found
499
 
500
    mov   eax,[cluster_tmp]
501
    call  get_FAT               ; get next cluster
74 mario79 502
    cmp   [hd_error],0
503
    jne   adw_not_found
504
 
1 ha 505
    cmp   eax,2                 ; incorrect fat chain?
506
    jb    adw_not_found         ; yes
507
    cmp   eax,[fatRESERVED]     ; is it end of directory?
508
    jb    adw_new_cluster       ; no. analyse it
509
 
510
    mov   eax,2                 ; this block of code add a new cluster
511
    call  get_free_FAT          ; for the directory because the directory
512
    jc    adw_not_found         ; is full
513
 
514
    mov   edx,[fatEND]          ; new end for directory
515
    call  set_FAT
74 mario79 516
    cmp  [hd_error],0
517
    jne  adw_not_found
1 ha 518
 
519
    push  eax                   ; save new cluster
520
    mov   edx,eax
521
    mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
522
    mov   [f_del],1
523
    call  set_FAT
74 mario79 524
    cmp  [hd_error],0
525
    jne  adw_not_found_1
526
 
1 ha 527
    mov   [f_del],0
528
 
529
    mov   ecx,-1                ; remove 1 cluster from free disk space
530
    call  add_disk_free_space
74 mario79 531
    cmp  [hd_error],0
532
    jne    adw_not_found_1
1 ha 533
 
534
    mov   ecx,512/4
535
    xor   eax,eax
536
    mov   edi,buffer
537
    cld
538
    rep   stosd                 ; clear new directory cluster
539
    pop   eax
540
 
541
    sub   eax,2
542
    mov   ecx,[SECTORS_PER_CLUSTER]
543
    imul  eax,ecx
544
    add   eax,[DATA_START]
545
    mov   ebx,buffer
546
    push  eax                   ; save sector number
547
 
548
  adw_set_empty_directory:
549
    call  hd_write
74 mario79 550
    cmp   [hd_error],0
551
    jne   adw_not_found_1
552
 
1 ha 553
    inc   eax                   ; next sector
554
    dec   ecx
555
    jnz   adw_set_empty_directory
556
 
557
    pop   eax
558
 
559
  adw_found:
560
    pop   edi edx ecx
561
    clc                         ; free space found
562
    ret
74 mario79 563
  adw_not_found_1:
564
    add  esp,4
1 ha 565
  adw_not_found:
566
    pop   edi edx ecx
567
    stc                         ; free space not found
568
    ret
569
 
570
 
571
get_data_cluster:
572
;-----------------------------------------------------------
573
; input  : EAX = cluster
574
;          EBX = pointer to buffer
575
;          EDX = # blocks to read in buffer
576
;          ESI = # blocks to skip over
577
; output : if CARRY=0 ok EBX/EDX/ESI updated
578
;          if CARRY=1 cluster out of range
579
; Note   : if cluster=0 it's changed to read rootdir
580
;-----------------------------------------------------------
581
    push  eax ecx
582
 
583
    mov   [fat16_root],0
584
    cmp   eax,[LAST_CLUSTER]
585
    ja    gdc_error             ; too big cluster number, something is wrong
586
    cmp   eax,2
587
    jnb   gdc_cluster
588
 
589
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
590
    cmp   [fat_type],16
591
    jne   gdc_cluster
592
    mov   eax,[ROOT_START]
593
    mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
594
    mov   [fat16_root],1        ; flag for fat16 rootdir
595
    jmp   gdc_read
596
 
597
  gdc_cluster:
598
    sub   eax,2
599
    mov   ecx,[SECTORS_PER_CLUSTER]
600
    imul  eax,ecx
601
    add   eax,[DATA_START]
602
 
603
  gdc_read:
604
    test  esi,esi               ; first wanted block
605
    je    gdcl1                 ; yes, skip count is 0
606
    dec   esi
607
    jmp   gdcl2
608
 
609
  gdcl1:
610
    call  hd_read
74 mario79 611
    cmp  [hd_error],0
612
    jne  gdc_error
613
 
1 ha 614
    add   ebx,512               ; update pointer
615
    dec   edx
616
 
617
  gdcl2:
618
    test  edx,edx               ; is all read?
619
    je    out_of_read
620
 
621
    inc   eax                   ; next sector
622
    dec   ecx
623
    jnz   gdc_read
624
 
625
  out_of_read:
626
    pop   ecx eax
627
    clc
628
    ret
629
 
630
  gdc_error:
631
    pop   ecx eax
632
    stc
633
    ret
634
 
635
 
636
set_data_cluster:
637
;-----------------------------------------------------------
638
; input  : EAX = cluster
639
;          EBX = pointer to buffer
640
; output : if CARRY=0 ok
641
;          if CARRY=1 cluster out of range
642
;-----------------------------------------------------------
643
    push  eax ebx edx
644
 
645
    cmp   eax,[LAST_CLUSTER]
646
    ja    sdc_error             ; too big cluster number, something is wrong
647
    sub   eax,2
648
    jb    sdc_error             ; don't allow rootdir write
649
 
650
    mov   edx,[SECTORS_PER_CLUSTER]
651
    imul  eax,edx
652
    add   eax,[DATA_START]
653
 
654
  sdc_write:
655
    call  hd_write
74 mario79 656
    cmp   [hd_error],0
657
    jne   sdc_error
658
 
1 ha 659
    add   ebx,512               ; update pointer
660
    inc   eax
661
    dec   edx
662
    jnz   sdc_write
663
    pop   edx ebx eax
664
    clc
665
    ret
666
 
667
  sdc_error:
668
    pop   edx ebx eax
669
    stc
670
    ret
671
 
672
 
673
get_cluster_of_a_path:
674
;---------------------------------------------------------
675
; input  : EBX = pointer to a path string
676
;          (example: the path "/files/data/document" become
677
;                             "files......data.......document...0"
678
;          '.' = space char
679
;          '0' = char(0) (ASCII=0) !!! )
680
; output : if (CARRY=1) -> ERROR in the PATH
681
;          if (CARRY=0) -> EAX=cluster
682
;---------------------------------------------------------
683
    push  ebx edx
684
 
685
    mov   eax,[ROOT_CLUSTER]
686
    mov   edx,ebx
687
 
688
search_end_of_path:
689
    cmp   byte [edx],0
690
    je    found_end_of_path
691
 
692
    inc   edx ; '/'
693
    mov   ebx,edx
694
    call  analyze_directory
695
    jc    directory_not_found
696
 
697
    mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
698
    mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
699
    and   eax,[fatMASK]
700
    add   edx,11                ; 8+3 (name+extension)
701
    jmp   search_end_of_path
702
 
703
found_end_of_path:
704
    pop   edx ebx
705
    clc                         ; no errors
706
    ret
707
 
708
directory_not_found:
709
    pop   edx ebx
710
    stc                         ; errors occour
711
    ret
712
 
713
 
714
bcd2bin:
715
;----------------------------------
716
; input  : AL=BCD number (eg. 0x11)
717
; output : AH=0
718
;          AL=decimal number (eg. 11)
719
;----------------------------------
720
    xor   ah,ah
721
    shl   ax,4
722
    shr   al,4
723
    aad
724
    ret
725
 
726
 
727
get_date_for_file:
728
;-----------------------------------------------------
729
; Get date from CMOS and pack day,month,year in AX
730
; DATE   bits  0..4   : day of month 0..31
731
;              5..8   : month of year 1..12
732
;              9..15  : count of years from 1980
733
;-----------------------------------------------------
734
    mov   al,0x7        ;day
735
    out   0x70,al
736
    in    al,0x71
737
    call  bcd2bin
738
    ror   eax,5
739
 
740
    mov   al,0x8        ;month
741
    out   0x70,al
742
    in    al,0x71
743
    call  bcd2bin
744
    ror   eax,4
745
 
746
    mov   al,0x9        ;year
747
    out   0x70,al
748
    in    al,0x71
749
    call  bcd2bin
750
    add   ax,20         ;because CMOS return only the two last
751
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
752
    rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
753
    ret
754
 
755
 
756
get_time_for_file:
757
;-----------------------------------------------------
758
; Get time from CMOS and pack hour,minute,second in AX
759
; TIME   bits  0..4   : second (the low bit is lost)
760
;              5..10  : minute 0..59
761
;              11..15 : hour 0..23
762
;-----------------------------------------------------
763
    mov   al,0x0        ;second
764
    out   0x70,al
765
    in    al,0x71
766
    call  bcd2bin
767
    ror   eax,6
768
 
769
    mov   al,0x2        ;minute
770
    out   0x70,al
771
    in    al,0x71
772
    call  bcd2bin
773
    ror   eax,6
774
 
775
    mov   al,0x4        ;hour
776
    out   0x70,al
777
    in    al,0x71
778
    call  bcd2bin
779
    rol   eax,11
780
    ret
781
 
782
 
783
set_current_time_for_entry:
784
;-----------------------------------------------------
785
; Set current time/date for file entry
786
; input  : ebx = file entry pointer
787
;-----------------------------------------------------
788
    push  eax
789
    call  get_time_for_file     ; update files date/time
790
    mov   [ebx+22],ax
791
    call  get_date_for_file
792
    mov   [ebx+24],ax
793
    pop   eax
794
    ret
795
 
796
 
797
makedir:
798
;-----------------------------------------------------
799
; input  : eax = directory name
800
;          edx = path
801
; output : eax = 0 - ok
802
;                3 - unknown FS
803
;                5 - file not found
804
;                8 - disk full
805
;               10 - access denied
806
; Note   : can only make one directory at time
807
;-----------------------------------------------------
808
    cmp   [fat_type],0
809
    jnz   make_dir_fat_ok
810
    mov   eax,ERROR_UNKNOWN_FS
811
    ret
812
 
813
  make_dir_fat_ok:
814
;    call  reserve_hd1
815
 
816
    pushad
817
 
818
    mov   ebx,edx
819
    call  get_cluster_of_a_path
820
    jnc   make_dir_found_path
74 mario79 821
    cmp   [hd_error],0
822
    jne   make_dir_error_1
1 ha 823
 
824
  make_dir_path_not_found:
825
    popad
826
    call  update_disk           ; write all of cache and fat to hd
74 mario79 827
    cmp   [hd_error],0
828
    jne   make_dir_error_2
829
 
1 ha 830
    mov   [hd1_status],0
831
    mov   eax,ERROR_FILE_NOT_FOUND
832
    ret
833
 
834
  make_dir_disk_full:
74 mario79 835
    cmp  [hd_error],0
836
    jne   make_dir_error_1
1 ha 837
    popad
838
    call  update_disk           ; write all of cache and fat to hd
74 mario79 839
    cmp   [hd_error],0
840
    jne   make_dir_error_2
841
 
1 ha 842
    mov   [hd1_status],0
843
    mov   eax,ERROR_DISK_FULL
844
    ret
845
 
846
  make_dir_already_exist:
74 mario79 847
    cmp  [hd_error],0
848
    jne   make_dir_error_1
1 ha 849
    mov   eax,[cluster]         ; directory cluster
850
    xor   edx,edx               ; free
851
    mov   [f_del],1
852
    call  set_FAT
74 mario79 853
    cmp  [hd_error],0
854
    jne   make_dir_error_1
855
 
1 ha 856
    mov   [f_del],0
857
 
858
    popad
859
    call  update_disk           ; write all of cache and fat to hd
74 mario79 860
  make_dir_error_2:
1 ha 861
    mov   [hd1_status],0
862
    mov   eax,ERROR_ACCESS_DENIED
863
    ret
864
 
74 mario79 865
  make_dir_error_1:
866
    popad
867
    jmp   make_dir_error_2
868
 
869
  make_dir_error_3:
870
    add  esp,4
871
    jmp   make_dir_error_1
872
 
1 ha 873
  make_dir_found_path:
874
    cmp   eax,[ROOT_CLUSTER]
875
    jnz   make_dir_not_root
876
    xor   eax,eax
877
 
878
  make_dir_not_root:
879
    mov   ecx,eax               ; directorys start cluster
880
    mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
881
    shr   ecx,16
882
    mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
883
 
884
    push  eax                   ; save parent directory cluster
885
    mov   eax,2
886
    call  get_free_FAT
887
    mov   [cluster],eax         ; first free cluster
888
    pop   eax
889
    jc    make_dir_disk_full
890
 
891
    push  eax
892
    mov   eax,[cluster]         ; directory cluster
893
    mov   edx,[fatEND]          ; end for directory
894
    call  set_FAT
74 mario79 895
    cmp  [hd_error],0
896
    jne   make_dir_error_3
1 ha 897
    pop   eax
898
 
899
    mov   ebx,PUSHAD_EAX        ; dir name
900
    push  eax
901
    call  analyze_directory     ; check if directory already exist
74 mario79 902
    cmp   [hd_error],0
903
    jne   make_dir_error_1
904
 
1 ha 905
    pop   eax
906
    jnc   make_dir_already_exist ; need to free allocated cluster!
907
 
908
    call  analyze_directory_to_write
909
    jc    make_dir_already_exist ; need to free allocated cluster!
910
 
911
    mov   esi,PUSHAD_EAX        ; dir name
912
    mov   edi,ebx               ; pointer in buffer
913
    mov   ecx,11
914
    cld
915
    rep   movsb
916
 
917
    mov   dword [ebx+28],0      ; dir size is always 0
918
    mov   ecx,[cluster]
919
    mov   [ebx+26],cx           ; 16 bits low of cluster
920
    mov   word [NewDirEntry1+26],cx
921
    shr   ecx,16
922
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
923
    mov   word [NewDirEntry1+20],cx
924
    mov   byte [ebx+11],0x10    ; attribute = directory
925
 
926
    call  set_current_time_for_entry
927
    mov   ecx,[ebx+22]
928
    mov   dword [NewDirEntry1+22],ecx
929
    mov   dword [NewDirEntry2+22],ecx
930
 
931
    mov   ebx,buffer            ; save the directory name,length,cluster
932
    call  hd_write
74 mario79 933
    cmp   [hd_error],0
934
    jne   make_dir_error_1
1 ha 935
 
936
    mov   ecx,512/4
937
    xor   eax,eax
938
    mov   edi,buffer
939
    cld
940
    rep   stosd                 ; clear new directory cluster
941
 
942
    mov   eax,[cluster]         ; new directory cluster
943
    sub   eax,2
944
    mov   edx,[SECTORS_PER_CLUSTER]
945
    imul  eax,edx
946
    add   eax,[DATA_START]
947
    mov   ebx,buffer
948
    add   eax,edx               ; start from last sector
949
 
950
  dir_set_empty_directory:
951
    dec   eax                   ; next sector
952
    cmp   edx,1                 ; is first directory sector?
953
    jnz   not_first_sector      ; no. write empty sector
954
    mov   esi,NewDirEntry1
955
    mov   edi,buffer
956
    mov   ecx,64/4
957
    cld
958
    rep   movsd                 ; copy 2 first directory entrys "." and ".."
959
 
960
  not_first_sector:
961
    call  hd_write
74 mario79 962
    cmp   [hd_error],0
963
    jne   make_dir_error_1
964
 
1 ha 965
    dec   edx
966
    jnz   dir_set_empty_directory
967
 
968
    mov   ecx,-1                ; remove 1 cluster from free disk space
969
    call  add_disk_free_space
74 mario79 970
    cmp  [hd_error],0
971
    jne   make_dir_error_1
1 ha 972
 
973
    popad
974
    call  update_disk           ; write all of cache and fat to hd
74 mario79 975
    cmp   [hd_error],0
976
    jne   make_dir_error_2
1 ha 977
    mov   [hd1_status],0
978
    xor   eax,eax
979
    ret
980
 
981
 
982
removedir:
983
;-----------------------------------------------------
984
; input  : eax = file/directory name
985
;          edx = path
986
; output : eax = 0 - ok
987
;                3 - unknown FS
988
;                5 - file not found
989
;               10 - access denied
990
;-----------------------------------------------------
991
    cmp   [fat_type],0
992
    jnz   remove_dir_fat_ok
993
    mov   eax,ERROR_UNKNOWN_FS
994
    ret
995
 
996
  remove_dir_fat_ok:
997
;    call  reserve_hd1
998
 
999
    push  edi
1000
    mov   edi,1                 ; allow directory remove
1001
    call  file_delete
74 mario79 1002
    cmp   [hd_error],0
1003
    jne   @f
1004
 
1 ha 1005
    pop   edi
1006
 
1007
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1008
  @@:
1 ha 1009
    mov   [hd1_status],0
1010
    ret
74 mario79 1011
 
1 ha 1012
 
1013
add_disk_free_space:
1014
;-----------------------------------------------------
1015
; input  : ecx = cluster count
1016
; Note   : negative = remove clusters from free space
1017
;          positive = add clusters to free space
1018
;-----------------------------------------------------
1019
    test  ecx,ecx               ; no change
1020
    je    add_dfs_no
1021
    cmp   [fat_type],32         ; free disk space only used by fat32
1022
    jne   add_dfs_no
1023
 
1024
    push  eax ebx
1025
    mov   eax,[ADR_FSINFO]
1026
    mov   ebx,buffer
1027
    call  hd_read
74 mario79 1028
    cmp  [hd_error],0
1029
    jne  add_not_fs
1030
 
1 ha 1031
    cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
1032
    jne   add_not_fs
1033
 
1034
    add   [ebx+0x1e8],ecx
1035
    call  hd_write
74 mario79 1036
    cmp   [hd_error],0
1037
    jne   add_not_fs
1 ha 1038
 
1039
  add_not_fs:
1040
    pop   ebx eax
1041
 
1042
  add_dfs_no:
1043
    ret
1044
 
1045
 
1046
file_append:
1047
;-----------------------------------------------------
1048
; input  : eax = file name
1049
;          edx = path
1050
;          ecx = pointer to buffer
1051
;          ebx = bytes to write (0 = truncate file)
1052
;          esi = start position (-1 = end of file)
1053
; output : eax = 0 - ok
1054
;                3 - unknown FS
1055
;                5 - file not found
1056
;                6 - end of file
1057
;                8 - disk full
1058
;                9 - fat table corrupted
1059
;               10 - access denied
1060
;          ebx = bytes written
1061
;-----------------------------------------------------
1062
    cmp   [fat_type],0
1063
    jnz   append_fat_ok
1064
    mov   eax,ERROR_UNKNOWN_FS
1065
    ret
1066
 
1067
  append_fat_ok:
1068
;    call  reserve_hd1
1069
 
1070
    pushad
1071
 
1072
    mov   ebx,edx
1073
    call  get_cluster_of_a_path
1074
    jc    append_not_found
1075
 
1076
    mov   ebx,PUSHAD_EAX        ; file name
1077
    call  analyze_directory
1078
    jc    append_not_found
1079
 
1080
    mov   [sector_tmp],eax
1081
    mov   [entry_pos],ebx
1082
 
1083
    test  byte [ebx+11],0x10    ; is it directory?
1084
    jnz   append_access         ; yes
1085
 
1086
    mov   ecx,[ebx+28]          ; file size
1087
    mov   edi,PUSHAD_ESI        ; write position
1088
    cmp   edi,-1                ; -1 = eof
1089
    jnz   append_inside_file
1090
    mov   edi,ecx               ; file size
1091
 
1092
  append_inside_file:
1093
    cmp   edi,ecx               ; start above old file size?
1094
    ja    append_eof            ; yes
1095
 
1096
    mov   [old_filesize],ecx
1097
    mov   [new_filepos],edi
1098
 
1099
    mov   ecx,PUSHAD_EBX        ; bytes to write
1100
    test  ecx,ecx               ; truncate?
1101
    jz    append_truncate       ; yes
1102
 
1103
    mov   [bytes2write],ecx     ; bytes to write
1104
    mov   esi,PUSHAD_ECX        ; pointer to buffer
1105
    mov   eax,[ebx+20-2]        ; FAT entry
1106
    mov   ax,[ebx+26]
1107
    and   eax,[fatMASK]
1108
    jnz   append_find_pos       ; first cluster <> 0
1109
 
1110
    mov   eax,2
1111
    call  get_free_FAT
1112
    jc    append_disk_full
1113
    mov   ecx,eax               ; set files first cluster
1114
    mov   [ebx+26],cx           ; 16 bits low of cluster
1115
    shr   ecx,16
1116
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1117
    mov   edx,[fatEND]          ; new end for cluster chain
1118
    call  set_FAT
74 mario79 1119
    cmp  [hd_error],0
1120
    jne   append_access
1 ha 1121
 
1122
    push  eax                   ; save first cluster
1123
    mov   eax,[sector_tmp]
1124
    mov   ebx,buffer
1125
    call  hd_write              ; write new file entry back to disk
74 mario79 1126
    cmp   [hd_error],0
1127
    jne   append_access_1
1128
 
1 ha 1129
    pop   eax
1130
 
1131
  append_remove_free:
1132
    mov   ecx,-1                ; remove 1 cluster from free disk space
1133
    call  add_disk_free_space   ; Note: uses buffer
74 mario79 1134
    cmp  [hd_error],0
1135
    jne   append_access
1 ha 1136
 
1137
  append_found_cluster:
1138
    mov   [cluster],eax
1139
    sub   eax,2
1140
    mov   ecx,[SECTORS_PER_CLUSTER]
1141
    imul  eax,ecx
1142
    add   eax,[DATA_START]
1143
    xor   edi,edi
1144
 
1145
  append_new_sector:
74 mario79 1146
    cmp   [hd_error],0
1147
    jne   append_access
1 ha 1148
    push  ecx
1149
    mov   ecx,[bytes2write]     ; bytes left in buffer
1150
    mov   ebx,512
1151
    sub   ebx,edi               ; bytes left in sector
1152
    cmp   ecx,ebx
1153
    jb    append_bytes_ok
1154
    mov   ecx,ebx
1155
 
1156
  append_bytes_ok:
1157
    cmp   ecx,512               ; overwrite full sector?
1158
    jz    append_full_sector    ; yes
1159
    mov   ebx,buffer            ; overwrite part of sector
1160
    call  hd_read               ; read old sector
74 mario79 1161
    cmp  [hd_error],0
1162
    jne  append_access_1
1 ha 1163
 
1164
  append_full_sector:
1165
    sub   [bytes2write],ecx
1166
    add   [new_filepos],ecx
1167
    add   edi,buffer
1168
    cld
1169
    rep   movsb
1170
    pop   ecx
1171
 
1172
    mov   ebx,buffer
1173
    call  hd_write
74 mario79 1174
    cmp   [hd_error],0
1175
    jne   append_access
1176
 
1 ha 1177
    cmp   [bytes2write],0       ; is all done?
1178
    jz    append_done
1179
    xor   edi,edi
1180
    inc   eax
1181
    dec   ecx
1182
    jnz   append_new_sector
1183
 
1184
    mov   eax,[cluster]
1185
    call  get_FAT
74 mario79 1186
    cmp   [hd_error],0
1187
    jne   append_access
1188
 
1 ha 1189
    cmp   eax,2
1190
    jb    append_fat
1191
    cmp   eax,[LAST_CLUSTER]
1192
    jbe   append_found_cluster
1193
 
1194
  append_alloc_cluster:
1195
    mov   eax,2                 ; ToDo: use temp array to keep track
1196
    call  get_free_FAT          ;       of last free cluster
1197
    jc    append_disk_full
1198
    push  eax                   ; save new cluster
1199
    mov   edx,[fatEND]          ; new end for cluster chain
1200
    call  set_FAT
74 mario79 1201
    cmp  [hd_error],0
1202
    jne  append_access_1
1203
 
1 ha 1204
    mov   edx,eax
1205
    mov   eax,[cluster]
1206
    mov   [f_del],1
1207
    call  set_FAT               ; update previous cluster
74 mario79 1208
    cmp  [hd_error],0
1209
    jne  append_access_1
1210
 
1 ha 1211
    mov   [f_del],0
1212
    pop   eax
1213
    jmp   append_remove_free
1214
 
1215
  append_find_pos:
1216
    call  find_filepos
1217
    mov   [cluster],ebx
1218
    jnc   append_new_sector
1219
    test  edi,edi
1220
    jz    append_alloc_cluster
1221
 
1222
  append_fat:
1223
    mov   eax,ERROR_FAT_TABLE
1224
    jmp   append_ret_code
74 mario79 1225
 
1 ha 1226
  append_disk_full:
74 mario79 1227
    cmp  [hd_error],0
1228
    jne  append_access
1 ha 1229
    mov   eax,ERROR_DISK_FULL
1230
    jmp   append_ret_code
1231
 
1232
  append_done:
1233
    xor   eax,eax
1234
 
1235
  append_ret_code:
1236
    mov   PUSHAD_EAX,eax        ; return code
1237
 
1238
    mov   eax,[sector_tmp]      ; update directory entry
1239
    mov   ebx,buffer
1240
    call  hd_read
74 mario79 1241
    cmp  [hd_error],0
1242
    jne  append_access
1243
 
1 ha 1244
    mov   ebx,[entry_pos]
1245
    mov   ecx,[new_filepos]
1246
    cmp   ecx,[old_filesize]    ; is file pos above old size?
1247
    jbe   append_size_ok        ; no
1248
    mov   [ebx+28],ecx          ; new file size
1249
 
1250
  append_size_ok:
1251
    call  set_current_time_for_entry
1252
    mov   ebx,buffer
1253
    call  hd_write              ; write new file entry back to disk
74 mario79 1254
    cmp   [hd_error],0
1255
    jne   append_access
1 ha 1256
 
1257
    sub   ecx,PUSHAD_ESI        ; start position
1258
    mov   PUSHAD_EBX,ecx        ; bytes written
1259
    popad
1260
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1261
    cmp   [hd_error],0
1262
    jne   append_access_2
1263
 
1 ha 1264
    mov   [hd1_status],0
1265
    ret
1266
 
1267
  append_eof:
1268
    popad
1269
    mov   [hd1_status],0
1270
    xor   ebx,ebx
1271
    mov   eax,ERROR_END_OF_FILE
1272
    ret
1273
 
1274
  append_not_found:
74 mario79 1275
    cmp  [hd_error],0
1276
    jne   append_access
1 ha 1277
    popad
1278
    mov   [hd1_status],0
1279
    xor   ebx,ebx
1280
    mov   eax,ERROR_FILE_NOT_FOUND
74 mario79 1281
    ret
1282
  append_access_1:
1283
    add   esp,4
1 ha 1284
  append_access:
1285
    popad
74 mario79 1286
  append_access_2:
1 ha 1287
    mov   [hd1_status],0
1288
    xor   ebx,ebx
1289
    mov   eax,ERROR_ACCESS_DENIED
1290
    ret
1291
 
1292
  append_truncate:
1293
    mov   edx,[ebx+20-2]        ; FAT entry
1294
    mov   dx,[ebx+26]
1295
    and   edx,[fatMASK]
1296
    mov   [ebx+28],edi          ; set new file size
1297
    test  edi,edi               ; 0 length file?
1298
    jnz   truncate_save_size    ; no
1299
    mov   [ebx+20],di           ; FAT entry = 0
1300
    mov   [ebx+26],di
1301
 
1302
  truncate_save_size:
1303
    call  set_current_time_for_entry
1304
    mov   ebx,buffer
1305
    call  hd_write
74 mario79 1306
    cmp   [hd_error],0
1307
    jne   append_access
1308
 
1 ha 1309
    mov   eax,edx               ; first cluster
1310
    test  edi,edi               ; 0 length file?
1311
    jz    truncate_clear_chain
1312
 
1313
    imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
1314
 
1315
  truncate_new_cluster:
1316
    cmp   eax,2                 ; incorrect fat chain?
1317
    jb    truncate_eof          ; yes
1318
    cmp   eax,[fatRESERVED]     ; is it end of file?
1319
    jnb   truncate_eof          ; yes
1320
    sub   edi,esi
1321
    jbe   truncate_pos_found
1322
    call  get_FAT               ; get next cluster
74 mario79 1323
    cmp   [hd_error],0
1324
    jne   append_access
1325
 
1 ha 1326
    jmp   truncate_new_cluster
1327
 
1328
  truncate_pos_found:
1329
    mov   edx,[fatEND]          ; new end for cluster chain
1330
    mov   [f_del],1
1331
    call  set_FAT
74 mario79 1332
    cmp  [hd_error],0
1333
    jne  append_access
1334
 
1 ha 1335
    mov   [f_del],0
1336
    mov   eax,edx               ; clear rest of chain
1337
 
1338
  truncate_clear_chain:
1339
    call  clear_cluster_chain
74 mario79 1340
    cmp  [hd_error],0
1341
    jne  append_access
1 ha 1342
 
1343
  truncate_eof:
1344
    popad
1345
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1346
    cmp   [hd_error],0
1347
    jne   append_access_2
1348
 
1 ha 1349
    mov   [hd1_status],0
1350
    xor   ebx,ebx
1351
    xor   eax,eax
1352
    ret
1353
 
1354
 
1355
find_filepos:
1356
;-----------------------------------------------------
1357
; input  : eax = first cluster
1358
;          edi = bytes to skip over (start position)
1359
; output : if CARRY=0 file position found
1360
;          if CARRY=1 end of file found
1361
;          eax = current file sector
1362
;          ebx = last cluster
1363
;          ecx = sector count in last cluster
1364
;          edi = bytes to skip over (sector position)
1365
;-----------------------------------------------------
1366
    push  esi
1367
    mov   ecx,[SECTORS_PER_CLUSTER]
1368
    imul  esi,ecx,512           ; esi = cluster size in bytes
1369
    mov   ebx,eax
1370
 
1371
  filepos_new_cluster:
1372
    cmp   eax,2                 ; incorrect fat chain?
1373
    jb    filepos_eof           ; yes
1374
    cmp   eax,[fatRESERVED]     ; is it end of file?
1375
    jnb   filepos_eof           ; yes
1376
 
1377
    mov   ebx,eax
1378
    cmp   edi,esi               ; skip over full cluster?
1379
    jb    filepos_cluster_ok    ; no
1380
 
1381
    sub   edi,esi
1382
    call  get_FAT               ; get next cluster
74 mario79 1383
    cmp   [hd_error],0
1384
    jne   filepos_eof
1385
 
1 ha 1386
    jmp   filepos_new_cluster
1387
 
1388
  filepos_cluster_ok:
1389
    sub   eax,2
1390
    imul  eax,ecx
1391
    add   eax,[DATA_START]
1392
 
1393
  filepos_new_sector:
1394
    cmp   edi,512               ; skip over full sector?
1395
    jb    filepos_sector_ok     ; no
1396
    sub   edi,512
1397
    inc   eax
1398
    dec   ecx
1399
    jnz   filepos_new_sector
1400
 
1401
  filepos_eof:
1402
    pop   esi
1403
    stc
1404
    ret
1405
 
1406
  filepos_sector_ok:
1407
    pop   esi
1408
    clc
1409
    ret
1410
 
1411
 
1412
file_write:
1413
;--------------------------------------------------------------------------
1414
;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
1415
;
1416
;            EAX        EDI            system call to write    /
1417
;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
1418
;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
1419
;            ECX        EBX   (PAR2)   file size               PAR2
1420
;            ESI        EDX   (PAR3)   pointer to path         PAR3
1421
;
1422
; output : eax = 0 - ok
1423
;                3 - unknown FS
1424
;                5 - file not found
1425
;                8 - disk full
1426
;               10 - access denied
1427
;--------------------------------------------------------------------------
1428
    cmp   [fat_type],0
1429
    jnz   fat_ok_for_writing
1430
    mov   eax,ERROR_UNKNOWN_FS
1431
    ret
1432
 
1433
  fat_ok_for_writing:
1434
;    call  reserve_hd1
1435
 
1436
    pushad
1437
 
1438
    xor   edi,edi               ; don't allow directory remove
1439
    call  file_delete           ; try to delete the file first
74 mario79 1440
    cmp   [hd_error],0
1441
    jne   exit_write_access_1
1442
 
1 ha 1443
    test  eax,eax
1444
    jz    old_deleted           ; deleted ok
1445
    cmp   eax,ERROR_FILE_NOT_FOUND
1446
    jnz   exit_write_access     ; it exist but can't delete
1447
 
1448
  old_deleted:
1449
    mov   ebx,PUSHAD_EDX
1450
    call  get_cluster_of_a_path
1451
    jnc   found_directory_for_writing
74 mario79 1452
    cmp   [hd_error],0
1453
    jne   exit_write_access
1 ha 1454
 
1455
  exit_writing_with_error:
1456
    popad
1457
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1458
    cmp   [hd_error],0
1459
    jne   exit_write_access_2
1460
 
1 ha 1461
    mov   [hd1_status],0
1462
    mov   eax,ERROR_FILE_NOT_FOUND
1463
    ret
1464
 
1465
  exit_writing_disk_full_clear:
74 mario79 1466
    cmp  [hd_error],0
1467
    jne  exit_write_access_1
1 ha 1468
    mov   eax,[sector_tmp]
1469
    mov   ebx,buffer
1470
    call  hd_read               ; read directory sector
74 mario79 1471
    cmp  [hd_error],0
1472
    jne  exit_write_access_1
1473
 
1 ha 1474
    mov   edx,[entry_pos]
1475
    mov   byte [edx],0xe5       ; mark as deleted
1476
    call  hd_write
74 mario79 1477
    cmp   [hd_error],0
1478
    jne   exit_write_access_1
1479
 
1 ha 1480
    mov   eax,[edx+20-2]        ; FAT entry
1481
    mov   ax,[edx+26]
1482
    and   eax,[fatMASK]
1483
    call  clear_cluster_chain
1484
 
1485
  exit_writing_disk_full:
74 mario79 1486
    cmp  [hd_error],0
1487
    jne  exit_write_access_1
1 ha 1488
    popad
1489
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1490
    cmp   [hd_error],0
1491
    jne   exit_write_access_2
1 ha 1492
    mov   [hd1_status],0
1493
    mov   eax,ERROR_DISK_FULL
1494
    ret
1495
 
1496
  exit_write_access:
1497
    popad
1498
    call  update_disk           ; write all of cache and fat to hd
1499
    mov   [hd1_status],0
1500
    mov   eax,ERROR_ACCESS_DENIED
1501
    ret
1502
 
74 mario79 1503
  exit_write_access_1:
1504
    popad
1505
  exit_write_access_2:
1506
    mov   [hd1_status],0
1507
    mov   eax,ERROR_ACCESS_DENIED
1508
    ret
1509
 
1 ha 1510
found_directory_for_writing:
1511
    call  analyze_directory_to_write
1512
    jc    exit_writing_disk_full
1513
 
1514
    mov   [sector_tmp],eax
1515
    mov   [entry_pos],ebx
1516
    push  eax                   ; save directory sector
1517
    mov   eax,2
1518
    call  get_free_FAT
1519
    mov   [cluster],eax         ; first free cluster
1520
    pop   eax
1521
    jc    exit_writing_disk_full
1522
 
1523
    mov   esi,PUSHAD_EAX        ; file name
1524
    mov   edi,ebx               ; pointer in buffer
1525
    mov   ecx,11
1526
    cld
1527
    rep   movsb
1528
 
1529
    mov   esi,PUSHAD_EBX        ; file size (bytes left)
1530
    mov   [ebx+28],esi          ; file size
1531
    mov   ecx,[cluster]
1532
    mov   [ebx+26],cx           ; 16 bits low of cluster
1533
    shr   ecx,16
1534
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1535
    mov   byte [ebx+11],0x20    ; attribute = archive
1536
 
1537
    call  set_current_time_for_entry
1538
 
1539
    mov   ebx,buffer            ; save the directory name,length,cluster
1540
    call  hd_write
74 mario79 1541
    cmp   [hd_error],0
1542
    jne   exit_write_access_1
1 ha 1543
 
1544
    imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
1545
    xor   ecx,ecx               ; cluster count
1546
    mov   ebx,PUSHAD_ECX        ; ebx = buffer
1547
 
1548
hd_new_block_write:
1549
 
1550
    mov   eax,[cluster]         ; eax = block
1551
    call  set_data_cluster
74 mario79 1552
    cmp   [hd_error],0
1553
    jne   exit_write_access_1
1 ha 1554
 
1555
    sub   esi,edi               ; sub wrote bytes
1556
    jbe   file_saved_OK         ; end if all done
1557
    add   ebx,edi               ; update buffer position
1558
 
1559
    inc   eax
1560
    call  get_free_FAT          ; next free in FAT
1561
    jc    exit_writing_disk_full_clear
1562
 
1563
    mov   edx,eax
1564
    xchg  eax,[cluster]         ; get old cluster and save new cluster
1565
    call  set_FAT               ; add it in cluster chain
74 mario79 1566
    cmp  [hd_error],0
1567
    jne   exit_write_access_1
1568
 
1 ha 1569
    dec   ecx                   ; update cluster count
1570
    jmp   hd_new_block_write
1571
 
1572
file_saved_OK:
1573
 
1574
    mov   edx,[fatEND]          ; new end for cluster chain
1575
    call  set_FAT
74 mario79 1576
    cmp  [hd_error],0
1577
    jne   exit_write_access_1
1578
 
1 ha 1579
    dec   ecx                   ; update cluster count
1580
 
1581
    call  add_disk_free_space   ; remove clusters from free disk space
74 mario79 1582
    cmp  [hd_error],0
1583
    jne   exit_write_access_1
1 ha 1584
 
1585
    popad
1586
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1587
    cmp   [hd_error],0
1588
    jne   exit_write_access_2
1 ha 1589
    mov   [hd1_status],0
1590
    xor   eax,eax
1591
    ret
1592
 
1593
 
1594
file_read:
1595
;--------------------------------------------------------------------------
1596
;   INPUT :  user-register register-in-this  meaning         symbol-in-this
1597
;
1598
;            EAX           EDI               system call to write   /
1599
;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
1600
;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
1601
;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
1602
;            ESI           EDX   (PAR3)      pointer to path        PAR3
1603
;            EDI           ESI            vt first 512 block to read
1604
;                          EDI               if 0 - read root
1605
;
1606
; output : eax = 0 - ok
1607
;                3 - unknown FS
1608
;                5 - file not found
1609
;                6 - end of file
1610
;                9 - fat table corrupted
74 mario79 1611
;               10 - access denied
1 ha 1612
;          ebx = size of file/directory
1613
;--------------------------------------------------------------------------
1614
    cmp   [fat_type],0
1615
    jnz   fat_ok_for_reading
1616
    xor   ebx,ebx
1617
    mov   eax,ERROR_UNKNOWN_FS
63 halyavin 1618
    mov   [hd1_status], ebx
1 ha 1619
    ret
1620
 
1621
  fat_ok_for_reading:
1622
;    call  reserve_hd1
1623
 
1624
    pushad
1625
 
1626
    mov   ebx,edx
1627
    call  get_cluster_of_a_path
1628
    jc    file_to_read_not_found
1629
 
1630
    test  edi,edi               ; read rootdir
1631
    jne   no_read_root
1632
 
1633
    xor   eax,eax
1634
    call  get_dir_size          ; return rootdir size
74 mario79 1635
    cmp   [hd_error],0
1636
    jne   file_access_denied
1637
 
1 ha 1638
    mov   [file_size],eax
1639
    mov   eax,[ROOT_CLUSTER]
1640
    jmp   file_read_start
1641
 
1642
  no_read_root:
1643
    mov   ebx,PUSHAD_EAX        ; file name
1644
    call  analyze_directory
1645
    jc    file_to_read_not_found
1646
 
1647
    mov   eax,[ebx+28]          ; file size
1648
    test  byte [ebx+11],0x10    ; is it directory?
1649
    jz    read_set_size         ; no
1650
 
1651
    mov   eax,[ebx+20-2]        ; FAT entry
1652
    mov   ax,[ebx+26]
1653
    and   eax,[fatMASK]
1654
    call  get_dir_size
74 mario79 1655
    cmp   [hd_error],0
1656
    jne   file_access_denied
1 ha 1657
 
1658
  read_set_size:
1659
    mov   [file_size],eax
1660
 
1661
    mov   eax,[ebx+20-2]        ; FAT entry
1662
    mov   ax,[ebx+26]
1663
    and   eax,[fatMASK]
1664
 
1665
  file_read_start:
1666
    mov   ebx,PUSHAD_ECX        ; pointer to buffer
1667
    mov   edx,PUSHAD_EBX        ; file blocks to read
1668
    mov   esi,PUSHAD_ESI        ; first 512 block to read
1669
 
1670
  file_read_new_cluster:
1671
    call  get_data_cluster
1672
    jc    file_read_eof         ; end of file or cluster out of range
1673
 
1674
    test  edx,edx               ; is all read?
1675
    je    file_read_OK          ; yes
1676
 
1677
    call  get_FAT               ; get next cluster
74 mario79 1678
    cmp   [hd_error],0
1679
    jne   file_access_denied
1680
 
1 ha 1681
    cmp   eax,[fatRESERVED]     ; end of file
1682
    jnb   file_read_eof
1683
    cmp   eax,2                 ; incorrect fat chain
1684
    jnb   file_read_new_cluster
1685
 
1686
    popad
1687
    mov   [hd1_status],0
1688
    mov   ebx,[file_size]
1689
    mov   eax,ERROR_FAT_TABLE
1690
    ret
1691
 
1692
  file_read_eof:
74 mario79 1693
    cmp   [hd_error],0
1694
    jne   file_access_denied
1 ha 1695
    popad
1696
    mov   [hd1_status],0
1697
    mov   ebx,[file_size]
1698
    mov   eax,ERROR_END_OF_FILE
1699
    ret
1700
 
1701
  file_read_OK:
1702
    popad
1703
    mov   [hd1_status],0
1704
    mov   ebx,[file_size]
1705
    xor   eax,eax
1706
    ret
1707
 
1708
  file_to_read_not_found:
74 mario79 1709
    cmp   [hd_error],0
1710
    jne   file_access_denied
1 ha 1711
    popad
1712
    mov   [hd1_status],0
1713
    xor   ebx,ebx
1714
    mov   eax,ERROR_FILE_NOT_FOUND
1715
    ret
1716
 
74 mario79 1717
  file_access_denied:
1718
    popad
1719
    mov   [hd1_status],0
1720
    xor   ebx,ebx
1721
    mov   eax,ERROR_ACCESS_DENIED
1722
    ret
1 ha 1723
 
1724
get_dir_size:
1725
;-----------------------------------------------------
1726
; input  : eax = first cluster (0=rootdir)
1727
; output : eax = directory size in bytes
1728
;-----------------------------------------------------
1729
    push  edx
1730
    xor   edx,edx               ; count of directory clusters
1731
    test  eax,eax
1732
    jnz   dir_size_next
1733
 
1734
    mov   eax,[ROOT_SECTORS]
1735
    shl   eax,9                 ; fat16 rootdir size in bytes
1736
    cmp   [fat_type],16
1737
    je    dir_size_ret
1738
    mov   eax,[ROOT_CLUSTER]
1739
 
1740
  dir_size_next:
1741
    cmp   eax,2                 ; incorrect fat chain
1742
    jb    dir_size_end
1743
    cmp   eax,[fatRESERVED]     ; end of directory
1744
    ja    dir_size_end
1745
    call  get_FAT               ; get next cluster
74 mario79 1746
    cmp   [hd_error],0
1747
    jne   dir_size_ret
1748
 
1 ha 1749
    inc   edx
1750
    jmp   dir_size_next
1751
 
1752
  dir_size_end:
1753
    imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
1754
    imul  eax,edx
1755
 
1756
  dir_size_ret:
1757
    pop   edx
1758
    ret
1759
 
1760
 
1761
file_delete:
1762
;-----------------------------------------------------
1763
; input  : eax = file/directory name
1764
;          edx = path
1765
;          edi = 1 - allow directory remove else don't remove directory
1766
; output : eax = 0 - ok
1767
;                3 - unknown FS
1768
;                5 - file not found
1769
;               10 - access denied
1770
;-----------------------------------------------------
1771
    cmp   [fat_type],0
1772
    jnz   file_del_fat_ok
1773
    mov   eax,ERROR_UNKNOWN_FS
1774
    ret
1775
 
1776
  file_del_fat_ok:
1777
    pushad
1778
 
1779
    mov   ebx,edx
1780
    call  get_cluster_of_a_path
1781
    jc    file_to_delete_not_found
1782
 
1783
    mov   ebx,PUSHAD_EAX        ; file/directory name
1784
    call  analyze_directory
1785
    jc    file_to_delete_not_found
1786
 
1787
    test  byte [ebx+11],0x10    ; is it directory?
1788
    jz    delete_notdir         ; no. it's file
1789
    cmp   edi,1                 ; allow directory remove
1790
    jnz   delete_no_access      ; no
1791
 
1792
    push  eax                   ; save directory sector
1793
    mov   eax,[ebx+20-2]        ; first cluster of file
1794
    mov   ax,[ebx+26]           ; 0 length files start cluster = 0
1795
    and   eax,[fatMASK]
1796
    xor   ebp,ebp               ; counter for directory deepnes
1797
    call  clear_directory
1798
    pop   eax
1799
    jc    delete_no_access
1800
 
1801
    push  ebx                   ; save directory pointer in buffer
1802
    mov   ebx,buffer
1803
    call  hd_read               ; read directory sector
74 mario79 1804
    cmp  [hd_error],0
1805
    jne  delete_no_access_1
1 ha 1806
    pop   ebx
1807
 
1808
  delete_notdir:
1809
    call  delete_entry_name
74 mario79 1810
    cmp   [hd_error],0
1811
    jne   delete_no_access
1812
 
1 ha 1813
    mov   eax,ecx               ; first cluster of file
1814
    call  clear_cluster_chain
74 mario79 1815
    cmp   [hd_error],0
1816
    jne   delete_no_access
1817
 
1 ha 1818
    popad
1819
    xor   eax,eax
1820
    ret
1821
 
74 mario79 1822
  delete_no_access_1:
1823
     add esp,4
1 ha 1824
  delete_no_access:
1825
    popad
1826
    mov   eax,ERROR_ACCESS_DENIED
1827
    ret
1828
 
1829
  file_to_delete_not_found:
74 mario79 1830
    cmp  [hd_error],0
1831
    jne  delete_no_access
1 ha 1832
    popad
1833
    mov   eax,ERROR_FILE_NOT_FOUND
1834
    ret
1835
 
1836
 
1837
clear_cluster_chain:
1838
;-----------------------------------------------------
1839
; input  : eax = first cluster
1840
;-----------------------------------------------------
1841
    push  eax ecx edx
1842
    xor   ecx,ecx               ; cluster count
1843
    mov   [f_del],1             ; delete on
1844
 
1845
  clean_new_chain:
1846
    cmp   eax,[LAST_CLUSTER]    ; end of file
1847
    ja    delete_OK
1848
    cmp   eax,2                 ; unfinished fat chain or zero length file
1849
    jb    delete_OK
1850
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1851
    jz    delete_OK
1852
 
1853
    xor   edx,edx
1854
    call  set_FAT               ; clear fat entry
74 mario79 1855
    cmp  [hd_error],0
1856
    jne  access_denied_01
1857
 
1 ha 1858
    inc   ecx                   ; update cluster count
1859
    mov   eax,edx               ; old cluster
1860
    jmp   clean_new_chain
1861
 
1862
  delete_OK:
1863
    call  add_disk_free_space   ; add clusters to free disk space
74 mario79 1864
  access_denied_01:
1 ha 1865
    mov   [f_del],0
1866
    pop   edx ecx eax
1867
    ret
1868
 
1869
 
1870
clear_directory:
1871
;-----------------------------------------------------
1872
; input  : eax = directory cluster
1873
;          ebp = directory deepnes
1874
; Note   : use recursive call
1875
;-----------------------------------------------------
1876
    pushad
1877
    inc   ebp
1878
    cmp   ebp,64                ; if over 63 directory deep
1879
    jnb   clear_error           ; something must be wrong
1880
 
1881
  clear_new_cluster:
1882
    cmp   eax,[LAST_CLUSTER]
1883
    ja    clear_end
1884
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1885
    jz    clear_end
1886
    mov   esi,eax               ; esi = current directory cluster
1887
    sub   eax,2
1888
    jb    clear_end
1889
    mov   ecx,[SECTORS_PER_CLUSTER]
1890
    imul  eax,ecx
1891
    add   eax,[DATA_START]
1892
 
1893
  clear_new_sector:
1894
    mov   edi,eax               ; edi = current directory sector
1895
    mov   ebx,deltree_buffer
1896
    call  hd_read
74 mario79 1897
    cmp  [hd_error],0
1898
    jne  clear_error
1899
 
1 ha 1900
    mov   edx,512/32            ; count of dir entrys per sector = 16
1901
 
1902
  clear_analyze:
1903
    mov   al,[ebx+11]           ; file attribute
1904
    and   al,0xf
1905
    cmp   al,0xf
1906
    je    clear_long_filename
1907
 
1908
    cmp   byte [ebx],'.'        ; parent or current directory
1909
    je    clear_next_entry
1910
    cmp   byte [ebx],0xe5       ; deleted
1911
    je    clear_next_entry
1912
    cmp   byte [ebx],0          ; empty
1913
    je    clear_write_last
1914
    ;je    clear_next_entry
1915
 
1916
    mov   eax,[ebx+20-2]        ; first cluster of entry
1917
    mov   ax,[ebx+26]
1918
    and   eax,[fatMASK]
1919
 
1920
    test  byte [ebx+11],0x10    ; is it directory?
1921
    jz    clear_file            ; no
1922
 
1923
    push  eax ebx
1924
    mov   eax,edi
1925
    mov   ebx,deltree_buffer    ; save buffer over recursive call
1926
    call  hd_write              ; write directory sector to disk
74 mario79 1927
    cmp   [hd_error],0
1928
    jne   clear_error
1929
 
1 ha 1930
    pop   ebx eax
1931
 
1932
    call  clear_directory       ; recursive call !!!
1933
    jc    clear_error           ; exit if error found
1934
 
1935
    push  eax ebx
1936
    mov   eax,edi
1937
    mov   ebx,deltree_buffer
1938
    call  hd_read               ; read directory sector again
74 mario79 1939
    cmp  [hd_error],0
1940
    jne   clear_error_1
1941
 
1 ha 1942
    pop   ebx eax
1943
 
1944
  clear_file:
1945
    call  clear_cluster_chain
74 mario79 1946
    cmp  [hd_error],0
1947
    jne   clear_error
1 ha 1948
 
1949
  clear_long_filename:
1950
    mov   byte [ebx],0xe5
1951
 
1952
  clear_next_entry:
1953
    add   ebx,32                ; position of next dir entry
1954
    dec   edx
1955
    jnz   clear_analyze
1956
 
1957
    mov   eax,edi
1958
    mov   ebx,deltree_buffer
1959
    call  hd_write              ; write directory sector to disk
74 mario79 1960
    cmp   [hd_error],0
1961
    jne   clear_error
1 ha 1962
 
1963
    inc   eax                   ; next sector
1964
    dec   ecx
1965
    jnz   clear_new_sector
1966
 
1967
    mov   eax,esi
1968
    call  get_FAT               ; get next cluster
74 mario79 1969
    cmp   [hd_error],0
1970
    jne   clear_error
1971
 
1 ha 1972
    jmp   clear_new_cluster     ; clear it
1973
 
1974
  clear_write_last:
1975
    mov   eax,edi
1976
    mov   ebx,deltree_buffer
1977
    call  hd_write              ; write directory sector to disk
74 mario79 1978
    cmp   [hd_error],0
1979
    jne   clear_error
1 ha 1980
 
1981
  clear_end:
1982
    popad
1983
    clc
1984
    ret
74 mario79 1985
clear_error_1:
1986
    add  esp,8
1 ha 1987
  clear_error:
1988
    popad
1989
    stc
1990
    ret
1991
 
1992
 
1993
delete_entry_name:
1994
;-----------------------------------------------------
1995
; input  : eax = directory sector
1996
;          ebx = directory pointer in buffer
1997
;          longname_sec = 2 previous directory sectors
1998
; output : ecx = first cluster
1999
; change : eax,ebx,edx
2000
;-----------------------------------------------------
2001
    mov   byte [ebx],0xe5
2002
    mov   ecx,[ebx+20-2]        ; first cluster of file
2003
    mov   cx,[ebx+26]           ; 0 length files start cluster = 0
2004
    and   ecx,[fatMASK]
2005
 
2006
  delete_empty:
2007
    sub   ebx,32
2008
    cmp   ebx,buffer
2009
    jnb   delete_test_long
2010
 
2011
    mov   ebx,buffer
2012
    call  hd_write              ; write directory sector back
74 mario79 2013
    cmp   [hd_error],0
2014
    jne   delete_name_end
2015
 
1 ha 2016
    xor   eax,eax
2017
    xchg  eax,[longname_sec2]
2018
    xchg  eax,[longname_sec1]
2019
    test  eax,eax               ; is there previous directory sector?
2020
    jz    delete_name_end       ; no
2021
 
2022
    mov   ebx,buffer
2023
    call  hd_read               ; read previous sector
74 mario79 2024
    cmp  [hd_error],0
2025
    jne  delete_name_end
2026
 
1 ha 2027
    mov   ebx,buffer+0x1e0      ; start from last entry
2028
 
2029
  delete_test_long:
2030
    mov   dh,[ebx+11]           ; file attribute
2031
    and   dh,0xf
2032
    cmp   dh,0xf
2033
    jne   delete_write_buffer
2034
 
2035
    cmp   byte [ebx],0x40       ; end of long dir entry?
2036
    mov   byte [ebx],0xe5
2037
    jb    delete_empty
2038
 
2039
  delete_write_buffer:
2040
    mov   ebx,buffer
2041
    call  hd_write              ; write directory sector back
2042
 
2043
  delete_name_end:
2044
    ret
2045
 
2046
 
2047
rename:
2048
;-----------------------------------------------------------
2049
; input  : eax = source directory name
2050
;          edx = source path
2051
;          ebx = dest directory name
2052
;          edi = dest path
2053
; output : eax = 0 - ok
2054
;                3 - unknown FS
2055
;                5 - file not found
2056
;                8 - disk full
2057
;               10 - access denied
2058
;-----------------------------------------------------------
2059
    cmp   [fat_type],0
2060
    jnz   fat_ok_for_rename
2061
    mov   eax,ERROR_UNKNOWN_FS
2062
    ret
2063
 
2064
  fat_ok_for_rename:
2065
;    call  reserve_hd1
2066
 
2067
    pushad
2068
 
2069
    mov   ebx,edx               ; source path
2070
    call  get_cluster_of_a_path
2071
    jc    rename_entry_not_found
2072
 
2073
    mov   ebx,PUSHAD_EAX        ; source directory name
2074
    call  analyze_directory
2075
    jc    rename_entry_not_found
2076
 
2077
    mov   [sector_tmp],eax      ; save source sector
2078
    mov   [entry_pos],ebx
2079
    mov   esi,ebx
2080
    mov   edi,dir_entry
2081
    mov   ecx,32/4
2082
    cld
2083
    rep   movsd                 ; save entry
2084
 
2085
    mov   ebx,PUSHAD_EDI        ; dest path
2086
    call  get_cluster_of_a_path
2087
    jc    rename_entry_not_found
2088
 
2089
    mov   edx,eax               ; save dest directory cluster
2090
    mov   ebx,PUSHAD_EBX        ; dest directory name
2091
    push  [longname_sec1]
2092
    push  [longname_sec2]
2093
    call  analyze_directory     ; check if entry already exist
74 mario79 2094
    cmp  [hd_error],0
2095
    jne  rename_entry_already_exist_1
2096
 
1 ha 2097
    pop   [longname_sec2]
2098
    pop   [longname_sec1]
2099
    jnc   rename_entry_already_exist
2100
 
2101
    mov   eax,edx
2102
    call  analyze_directory_to_write
2103
    jc    rename_disk_full
2104
 
2105
    mov   esi,dir_entry
2106
    mov   edi,ebx
2107
    mov   ecx,32/4
2108
    cld
2109
    rep   movsd                 ; copy entry
2110
    mov   esi,PUSHAD_EBX        ; dest directory name
2111
    mov   edi,ebx
2112
    mov   ecx,11
2113
    rep   movsb                 ; copy name
2114
 
2115
    mov   ebx,buffer            ; save the directory name,length,cluster
2116
    call  hd_write
2117
 
2118
    test  byte [dir_entry+11],0x10 ; is it directory?
2119
    jz    rename_not_dir           ; no
2120
    mov   eax,[dir_entry+20-2]     ; FAT entry
2121
    mov   ax,[dir_entry+26]
2122
    and   eax,[fatMASK]
2123
    call  change_2dot_cluster
74 mario79 2124
    cmp   [hd_error],0
2125
    jne   rename_entry_already_exist
1 ha 2126
 
2127
  rename_not_dir:
74 mario79 2128
    cmp   [hd_error],0
2129
    jne   rename_entry_already_exist
1 ha 2130
    mov   eax,[sector_tmp]
2131
    mov   ebx,buffer
2132
    call  hd_read               ; read source directory sector
74 mario79 2133
    cmp  [hd_error],0
2134
    jne  rename_entry_already_exist
1 ha 2135
 
2136
    mov   ebx,[entry_pos]
2137
    call  delete_entry_name
74 mario79 2138
    cmp   [hd_error],0
2139
    jne   rename_entry_already_exist
1 ha 2140
 
2141
    popad
2142
    call  update_disk           ; write all of cache and fat to hd
74 mario79 2143
    cmp   [hd_error],0
2144
    jne   rename_entry_already_exist_2
1 ha 2145
    mov   [hd1_status],0
2146
    xor   eax,eax
2147
    ret
2148
 
2149
  rename_entry_not_found:
74 mario79 2150
    cmp  [hd_error],0
2151
    jne  rename_entry_already_exist
1 ha 2152
    popad
2153
    mov   [hd1_status],0
2154
    mov   eax,ERROR_FILE_NOT_FOUND
2155
    ret
2156
 
74 mario79 2157
  rename_entry_already_exist_1:
2158
    add   esp,8
1 ha 2159
  rename_entry_already_exist:
2160
    popad
74 mario79 2161
  rename_entry_already_exist_2:
1 ha 2162
    mov   [hd1_status],0
2163
    mov   eax,ERROR_ACCESS_DENIED
2164
    ret
2165
 
2166
  rename_disk_full:
74 mario79 2167
    cmp  [hd_error],0
2168
    jne  rename_entry_already_exist
1 ha 2169
    popad
2170
    mov   [hd1_status],0
2171
    mov   eax,ERROR_DISK_FULL
2172
    ret
2173
 
2174
 
2175
change_2dot_cluster:
2176
;-----------------------------------------------------------
2177
; input  : eax = directory cluster
2178
;          edx = value to save
2179
; change : eax,ebx,edx
2180
;-----------------------------------------------------------
2181
    cmp   eax,[LAST_CLUSTER]
2182
    ja    not_2dot              ; too big cluster number, something is wrong
2183
    sub   eax,2
2184
    jb    not_2dot
2185
 
2186
    imul  eax,[SECTORS_PER_CLUSTER]
2187
    add   eax,[DATA_START]
2188
    mov   ebx,buffer
2189
    call  hd_read
74 mario79 2190
    cmp  [hd_error],0
2191
    jne  not_2dot
1 ha 2192
 
2193
    cmp   dword [ebx+32],'..  '
2194
    jnz   not_2dot
2195
 
2196
    cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
2197
    jne   not_2dot_root
2198
    xor   edx,edx               ; yes. set it zero
2199
 
2200
  not_2dot_root:
2201
    mov   [ebx+32+26],dx        ; 16 bits low of cluster
2202
    shr   edx,16
2203
    mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
2204
    call  hd_write
2205
 
2206
  not_2dot:
2207
    ret
2208
 
2209
 
2210
get_filesize:
2211
;-----------------------------------------------------------
2212
; input  : eax = file name
2213
;          edx = path
2214
;          edi = if 0 - read rootdir else normal dir/file size
2215
; output : eax = 0 - ok
2216
;                3 - unknown FS
2217
;                5 - file not found
74 mario79 2218
;               10 - access denied
1 ha 2219
;          ebx = file size
2220
;-----------------------------------------------------------
2221
    cmp   [fat_type],0
2222
    jnz   get_filesize_fat_ok
2223
    xor   ebx,ebx
2224
    mov   eax,ERROR_UNKNOWN_FS
2225
    ret
2226
 
2227
  get_filesize_fat_ok:
2228
;    call  reserve_hd1
2229
 
2230
    pushad
2231
    xor   eax,eax
2232
    test  edi,edi               ; is read rootdir?
2233
    je    get_filesize_dirsize  ; yes
2234
 
2235
  get_filesize_no_root:
2236
    mov   ebx,edx
2237
    call  get_cluster_of_a_path
2238
    jc    get_filesize_not_found
2239
 
2240
    mov   ebx,PUSHAD_EAX        ; file name
2241
    call  analyze_directory
2242
    jc    get_filesize_not_found
2243
 
2244
    mov   eax,[ebx+28]          ; file size
2245
    test  byte [ebx+11],0x10    ; is it directory?
2246
    jz    get_filesize_set_size ; no
2247
 
2248
    mov   eax,[ebx+20-2]        ; FAT entry
2249
    mov   ax,[ebx+26]
2250
    and   eax,[fatMASK]
2251
 
2252
  get_filesize_dirsize:
2253
    call  get_dir_size
74 mario79 2254
    cmp   [hd_error],0
2255
    jne   get_filesize_access_denied
1 ha 2256
 
2257
  get_filesize_set_size:
2258
    mov   PUSHAD_EBX,eax
2259
    popad
2260
    mov   [hd1_status],0
2261
    xor   eax,eax
2262
    ret
2263
 
2264
  get_filesize_not_found:
74 mario79 2265
    cmp   [hd_error],0
2266
    jne   get_filesize_access_denied
1 ha 2267
    popad
2268
    mov   [hd1_status],0
2269
    xor   ebx,ebx
2270
    mov   eax,ERROR_FILE_NOT_FOUND
2271
    ret
2272
 
74 mario79 2273
  get_filesize_access_denied:
2274
    popad
2275
    mov   [hd1_status],0
2276
    xor   ebx,ebx
2277
    mov   eax,ERROR_ACCESS_DENIED
2278
    ret
1 ha 2279
 
2280
get_fileattr:
2281
;-----------------------------------------------------------
2282
; input  : eax = file name
2283
;          edx = path
2284
; output : eax = 0 - ok
2285
;                3 - unknown FS
2286
;                5 - file not found
74 mario79 2287
;               10 - access denied
1 ha 2288
;          ebx = file attribute
2289
;-----------------------------------------------------------
2290
    cmp   [fat_type],0
2291
    jnz   get_fileattr_fat_ok
2292
    xor   ebx,ebx
2293
    mov   eax,ERROR_UNKNOWN_FS
2294
    ret
2295
 
2296
  get_fileattr_fat_ok:
2297
;    call  reserve_hd1
2298
 
2299
    pushad
2300
    mov   ebx,edx
2301
    call  get_cluster_of_a_path
2302
    jc    get_fileattr_not_found
2303
 
2304
    mov   ebx,PUSHAD_EAX        ; file name
2305
    call  analyze_directory
2306
    jc    get_fileattr_not_found
2307
 
2308
    movzx eax,byte [ebx+11]     ; file attribute
2309
    mov   PUSHAD_EBX,eax
2310
    popad
2311
    mov   [hd1_status],0
2312
    xor   eax,eax
2313
    ret
2314
 
2315
  get_fileattr_not_found:
74 mario79 2316
    cmp   [hd_error],0
2317
    jne   get_fileattr_access_denied
1 ha 2318
    popad
2319
    mov   [hd1_status],0
2320
    xor   ebx,ebx
2321
    mov   eax,ERROR_FILE_NOT_FOUND
2322
    ret
2323
 
74 mario79 2324
  get_fileattr_access_denied:
2325
    popad
2326
    mov   [hd1_status],0
2327
    xor   ebx,ebx
2328
    mov   eax,ERROR_ACCESS_DENIED
2329
    ret
1 ha 2330
 
2331
get_filedate:
2332
;-----------------------------------------------------------
2333
; input  : eax = file name
2334
;          edx = path
2335
; output : eax = 0 - ok
2336
;                3 - unknown FS
2337
;                5 - file not found
74 mario79 2338
;               10 - access denied
1 ha 2339
;          ebx = file date/time
2340
;                bits 31..25 = year-1980
2341
;                bits 24..21 = month
2342
;                bits 20..16 = day
2343
;                bits 15..11 = hour
2344
;                bits 10..5  = minute
2345
;                bits 4..0   = second/2
2346
;-----------------------------------------------------------
2347
    cmp   [fat_type],0
2348
    jnz   get_filedate_fat_ok
2349
    xor   ebx,ebx
2350
    mov   eax,ERROR_UNKNOWN_FS
2351
    ret
2352
 
2353
  get_filedate_fat_ok:
2354
;    call  reserve_hd1
2355
 
2356
    pushad
2357
    mov   ebx,edx
2358
    call  get_cluster_of_a_path
2359
    jc    get_filedate_not_found
2360
 
2361
    mov   ebx,PUSHAD_EAX        ; file name
2362
    call  analyze_directory
2363
    jc    get_filedate_not_found
2364
 
2365
    mov   eax,[ebx+22]          ; file date/time
2366
    mov   PUSHAD_EBX,eax
2367
    popad
2368
    mov   [hd1_status],0
2369
    xor   eax,eax
2370
    ret
2371
 
2372
  get_filedate_not_found:
74 mario79 2373
    cmp   [hd_error],0
2374
    jne   get_filedate_access_denied
1 ha 2375
    popad
2376
    mov   [hd1_status],0
2377
    xor   ebx,ebx
2378
    mov   eax,ERROR_FILE_NOT_FOUND
2379
    ret
2380
 
74 mario79 2381
  get_filedate_access_denied:
2382
    popad
2383
    mov   [hd1_status],0
2384
    xor   ebx,ebx
2385
    mov   eax,ERROR_ACCESS_DENIED
2386
    ret
1 ha 2387
 
2388
get_hd_info:
2389
;-----------------------------------------------------------
2390
; output : eax = 0 - ok
2391
;                3 - unknown FS
74 mario79 2392
;               10 - access denied
1 ha 2393
;          edx = cluster size in bytes
2394
;          ebx = total clusters on disk
2395
;          ecx = free clusters on disk
2396
;-----------------------------------------------------------
2397
    cmp   [fat_type],0
2398
    jnz   info_fat_ok
2399
    xor   edx,edx
2400
    xor   ebx,ebx
2401
    xor   ecx,ecx
2402
    mov   eax,ERROR_UNKNOWN_FS
2403
    ret
2404
 
2405
  info_fat_ok:
2406
;    call  reserve_hd1
2407
 
2408
    xor   ecx,ecx               ; count of free clusters
2409
    mov   eax,2
2410
    mov   ebx,[LAST_CLUSTER]
2411
 
2412
  info_cluster:
2413
    push  eax
2414
    call  get_FAT               ; get cluster info
74 mario79 2415
    cmp   [hd_error],0
2416
    jne   info_access_denied
2417
 
1 ha 2418
    test  eax,eax               ; is it free?
2419
    jnz   info_used             ; no
2420
    inc   ecx
2421
 
2422
  info_used:
2423
    pop   eax
2424
    inc   eax
2425
    cmp   eax,ebx               ; is above last cluster?
2426
    jbe   info_cluster          ; no. test next cluster
2427
 
2428
    dec   ebx                   ; cluster count
2429
    imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
2430
    mov   [hd1_status],0
2431
    xor   eax,eax
2432
    ret
2433
 
74 mario79 2434
  info_access_denied:
2435
    add   esp,4
2436
    xor   edx,edx
2437
    xor   ebx,ebx
2438
    xor   ecx,ecx
2439
    mov   eax,ERROR_ACCESS_DENIED
2440
    ret
1 ha 2441
 
2442
update_disk:
2443
;-----------------------------------------------------------
2444
; write changed fat and cache to disk
2445
;-----------------------------------------------------------
2446
    cmp   [fat_change],0        ; is fat changed?
2447
    je    upd_no_change
2448
 
2449
    call  write_fat_sector
74 mario79 2450
    cmp   [hd_error],0
2451
    jne   update_disk_acces_denied
1 ha 2452
 
2453
  upd_no_change:
2454
 
2455
    call  write_cache
74 mario79 2456
  update_disk_acces_denied:
1 ha 2457
    ret
2458
 
2459
 
2460
;**************************************************************************
2461
;
2462
;   0x600008  - first entry in cache list
2463
;
2464
;            +0   - lba sector
2465
;            +4   - state of cache sector
2466
;                   0 = empty
2467
;                   1 = used for read  ( same as in hd )
2468
;                   2 = used for write ( differs from hd )
2469
;
2470
;      +65536 - cache entries
2471
;
2472
;**************************************************************************
2473
 
2474
 
2475
hd_read:
2476
;-----------------------------------------------------------
2477
; input  : eax = block to read
2478
;          ebx = destination
2479
;-----------------------------------------------------------
2480
    push  ecx esi edi           ; scan cache
2481
 
2482
    mov   ecx,cache_max         ; entries in cache
2483
    mov   esi,0x600000+8
2484
    mov   edi,1
2485
 
2486
  hdreadcache:
2487
 
2488
    cmp   dword [esi+4],0       ; empty
2489
    je    nohdcache
2490
 
2491
    cmp   [esi],eax             ; correct sector
2492
    je    yeshdcache
2493
 
2494
  nohdcache:
2495
 
2496
    add   esi,8
2497
    inc   edi
2498
    dec   ecx
2499
    jnz   hdreadcache
2500
 
2501
    call  find_empty_slot       ; ret in edi
74 mario79 2502
    cmp   [hd_error],0
2503
    jne   return_01
1 ha 2504
 
2505
    push  eax edx
2506
 
74 mario79 2507
    call  wait_for_hd_idle
2508
    cmp   [hd_error],0
2509
    jne   hd_read_error
2510
 
1 ha 2511
    cli
2512
    xor   eax,eax
2513
    mov   edx,[hdbase]
2514
    inc   edx
74 mario79 2515
    out   dx,al   ; ATAFeatures  ¥£ð¡¢  "®¡®¡¥­­®¡¢¥©"
1 ha 2516
    inc   edx
2517
    inc   eax
74 mario79 2518
    out   dx,al   ; ATASectorCount ¡§¥¢§ðª ¡¥ª¢® ®¢
1 ha 2519
    inc   edx
2520
    mov   eax,[esp+4]
74 mario79 2521
    out   dx,al   ; ATASectorNumber  ¥£ð¡¢  ­®¬¥   ¡¥ª¢®  
1 ha 2522
    shr   eax,8
2523
    inc   edx
74 mario79 2524
    out   dx,al   ; ATACylinder ­®¬¥  ¦ð«ð­¤   (¬« ¤¨ð© ¡ ©¢)
1 ha 2525
    shr   eax,8
2526
    inc   edx
74 mario79 2527
    out   dx,al   ; ­®¬¥  ¦ð«ð­¤   (¡¢  ¨ð© ¡ ©¢)
1 ha 2528
    shr   eax,8
2529
    inc   edx
2530
    and   al,1+2+4+8
2531
    add   al,byte [hdid]
2532
    add   al,128+64+32
74 mario79 2533
    out   dx,al   ; ­®¬¥  £®«®¢ªð/­®¬¥  ¤ð¡ª 
1 ha 2534
    inc   edx
2535
    mov   al,20h
74 mario79 2536
    out   dx,al   ; ATACommand  ¥£ð¡¢  ª®¬ ­¤
1 ha 2537
    sti
2538
 
2539
    call  wait_for_sector_buffer
2540
 
2541
    cmp   [hd_error],0
2542
    jne   hd_read_error
2543
 
2544
    cli
2545
    push  edi
2546
    shl   edi,9
2547
    add   edi,0x600000+65536
2548
    mov   ecx,256
2549
    mov   edx,[hdbase]
2550
    cld
2551
    rep   insw
2552
    pop   edi
2553
    sti
2554
 
2555
    pop   edx eax
2556
 blok_read_2:
2557
    lea   esi,[edi*8+0x600000]
2558
    mov   [esi],eax             ; sector number
2559
    mov   dword [esi+4],1       ; hd read - mark as same as in hd
2560
 
2561
  yeshdcache:
2562
 
2563
    mov   esi,edi
2564
    shl   esi,9
2565
    add   esi,0x600000+65536
2566
    mov   edi,ebx
2567
    mov   ecx,512/4
2568
    cld
2569
    rep   movsd                 ; move data
74 mario79 2570
 return_01:
1 ha 2571
    pop   edi esi ecx
2572
    ret
2573
 
2574
 
2575
hd_write:
2576
;-----------------------------------------------------------
2577
; input  : eax = block
2578
;          ebx = pointer to memory
2579
;-----------------------------------------------------------
2580
    push  ecx esi edi
2581
 
2582
    ; check if the cache already has the sector and overwrite it
2583
 
2584
    mov   ecx,cache_max
2585
    mov   esi,0x600000+8
2586
    mov   edi,1
2587
 
2588
  hdwritecache:
2589
 
2590
    cmp   dword [esi+4],0       ; if cache slot is empty
2591
    je    not_in_cache_write
2592
 
2593
    cmp   [esi],eax             ; if the slot has the sector
2594
    je    yes_in_cache_write
2595
 
2596
  not_in_cache_write:
2597
 
2598
    add   esi,8
2599
    inc   edi
2600
    dec   ecx
2601
    jnz   hdwritecache
2602
 
2603
    ; sector not found in cache
2604
    ; write the block to a new location
2605
 
2606
    call  find_empty_slot       ; ret in edi
74 mario79 2607
    cmp   [hd_error],0
2608
    jne   hd_write_access_denied
1 ha 2609
 
2610
    lea   esi,[edi*8+0x600000]
2611
    mov   [esi],eax             ; sector number
2612
 
2613
  yes_in_cache_write:
2614
 
2615
    mov   dword [esi+4],2       ; write - differs from hd
2616
 
2617
    shl   edi,9
2618
    add   edi,0x600000+65536
2619
    mov   esi,ebx
2620
    mov   ecx,512/4
2621
    cld
2622
    rep   movsd                 ; move data
74 mario79 2623
 hd_write_access_denied:
1 ha 2624
    pop   edi esi ecx
2625
    ret
2626
 
2627
 
2628
write_cache:
2629
;-----------------------------------------------------------
2630
; write all changed sectors to disk
2631
;-----------------------------------------------------------
2632
    push  eax ecx edx esi edi
2633
 
2634
    ; write difference ( 2 ) from cache to hd
2635
 
2636
    mov   ecx,cache_max
2637
    mov   esi,0x600000+8
2638
    mov   edi,1
2639
 
2640
  write_cache_more:
2641
 
2642
    cmp   dword [esi+4],2       ; if cache slot is not different
2643
    jne   does_not_need_writing
2644
 
2645
    mov   dword [esi+4],1       ; same as in hd
2646
    mov   eax,[esi]             ; eax = sector to write
2647
 
2648
    cmp   eax,[PARTITION_START]
2649
    jb    danger
2650
    cmp   eax,[PARTITION_END]
2651
    ja    danger
2652
 
2653
    call  wait_for_hd_idle
74 mario79 2654
    cmp   [hd_error],0
2655
    jne   hd_write_error
1 ha 2656
 
2657
    cli
2658
    xor   eax,eax
2659
    mov   edx,[hdbase]
2660
    inc   edx
2661
    out   dx,al
2662
    inc   edx
2663
    inc   eax
2664
    out   dx,al
2665
    inc   edx
2666
    mov   eax,[esi]             ; eax = sector to write
2667
    out   dx,al
2668
    shr   eax,8
2669
    inc   edx
2670
    out   dx,al
2671
    shr   eax,8
2672
    inc   edx
2673
    out   dx,al
2674
    shr   eax,8
2675
    inc   edx
2676
    and   al,1+2+4+8
2677
    add   al,byte [hdid]
2678
    add   al,128+64+32
2679
    out   dx,al
2680
    inc   edx
2681
    mov   al,30h
2682
    out   dx,al
2683
    sti
2684
 
2685
    call  wait_for_sector_buffer
2686
 
2687
    cmp   [hd_error],0
2688
    jne   hd_write_error
2689
 
2690
    push  ecx esi
2691
 
2692
    cli
2693
    mov   esi,edi
2694
    shl   esi,9
2695
    add   esi,0x600000+65536    ; esi = from memory position
2696
    mov   ecx,256
2697
    mov   edx,[hdbase]
2698
    cld
2699
    rep   outsw
2700
    sti
2701
 
2702
    pop   esi ecx
2703
 
2704
  danger:
2705
  does_not_need_writing:
2706
 
2707
    add   esi,8
2708
    inc   edi
2709
    dec   ecx
2710
    jnz   write_cache_more
74 mario79 2711
 return_02:
1 ha 2712
    pop   edi esi edx ecx eax
2713
    ret
2714
 
2715
 
2716
find_empty_slot:
2717
;-----------------------------------------------------------
2718
; find empty or read slot, flush cache if next 10% is used by write
2719
; output : edi = cache slot
2720
;-----------------------------------------------------------
2721
    push  ecx esi
2722
 
2723
  search_again:
2724
 
2725
    mov   ecx,cache_max*10/100
2726
    mov   edi,[cache_search_start]
2727
 
2728
  search_for_empty:
2729
 
2730
    inc   edi
2731
    cmp   edi,cache_max
2732
    jbe   inside_cache
2733
    mov   edi,1
2734
 
2735
  inside_cache:
2736
 
2737
    cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
2738
    jb    found_slot                    ; it's empty or read
2739
    dec   ecx
2740
    jnz   search_for_empty
2741
 
2742
    call  write_cache                   ; no empty slots found, write all
74 mario79 2743
    cmp   [hd_error],0
2744
    jne   found_slot_access_denied
2745
 
1 ha 2746
    jmp   search_again                  ; and start again
2747
 
2748
  found_slot:
2749
 
2750
    mov   [cache_search_start],edi
74 mario79 2751
  found_slot_access_denied:
1 ha 2752
    pop   esi ecx
2753
    ret
2754
 
2755
 
2756
save_hd_wait_timeout:
2757
 
2758
    push  eax
2759
    mov   eax,[timer_ticks];[0xfdf0]
2760
    add   eax,300               ; 3 sec timeout
2761
    mov   [hd_wait_timeout],eax
2762
    pop   eax
2763
    ret
2764
 
2765
 
2766
check_hd_wait_timeout:
2767
 
2768
    push  eax
2769
    mov   eax,[hd_wait_timeout]
2770
    cmp   [timer_ticks], eax ;[0xfdf0],eax
2771
    jg    hd_timeout_error
2772
    pop   eax
74 mario79 2773
    mov   [hd_error],0
1 ha 2774
    ret
2775
 
2776
iglobal
2777
  hd_timeout_str   db 'K : FS - HD timeout',13,10,0
2778
  hd_read_str      db 'K : FS - HD read error',13,10,0
2779
  hd_write_str     db 'K : FS - HD write error',13,10,0
74 mario79 2780
  hd_lba_str       db 'K : FS - HD LBA error',13,10,0
1 ha 2781
endg
2782
 
2783
hd_timeout_error:
2784
 
2785
    call  clear_hd_cache
2786
    call  clear_application_table_status
2787
    mov   esi,hd_timeout_str
2788
    call  sys_msg_board_str
74 mario79 2789
;    jmp   $
2790
    mov   [hd_error],1
2791
    pop   eax
2792
    ret
1 ha 2793
 
2794
hd_read_error:
2795
 
2796
    call  clear_hd_cache
2797
    call  clear_application_table_status
2798
    mov   esi,hd_read_str
2799
    call  sys_msg_board_str
74 mario79 2800
    pop   edx eax
2801
    jmp    return_01
2802
;    jmp   $
1 ha 2803
 
2804
hd_write_error:
2805
 
2806
    call  clear_hd_cache
2807
    call  clear_application_table_status
2808
    mov   esi,hd_write_str
2809
    call  sys_msg_board_str
74 mario79 2810
    jmp    return_02
2811
;    jmp   $
1 ha 2812
 
74 mario79 2813
hd_lba_error:
2814
    call  clear_hd_cache
2815
    call  clear_application_table_status
2816
    mov   esi,hd_lba_str
2817
    call  sys_msg_board_str
2818
    jmp   LBA_read_ret
1 ha 2819
 
2820
 
2821
wait_for_hd_idle:
2822
 
2823
    push  eax edx
2824
 
2825
    call  save_hd_wait_timeout
2826
 
2827
    mov   edx,[hdbase]
2828
    add   edx,0x7
2829
 
2830
  wfhil1:
2831
 
2832
    call  check_hd_wait_timeout
74 mario79 2833
    cmp   [hd_error],0
2834
    jne   @f
1 ha 2835
 
2836
    in    al,dx
2837
    test  al,128
2838
    jnz   wfhil1
74 mario79 2839
 
2840
 @@:
1 ha 2841
 
2842
    pop   edx eax
2843
    ret
2844
 
2845
 
74 mario79 2846
 
1 ha 2847
wait_for_sector_buffer:
2848
 
2849
    push  eax edx
2850
 
2851
    mov   edx,[hdbase]
2852
    add   edx,0x7
2853
 
2854
    call  save_hd_wait_timeout
2855
 
2856
  hdwait_sbuf:                  ; wait for sector buffer to be ready
2857
 
2858
    call  check_hd_wait_timeout
74 mario79 2859
    cmp   [hd_error],0
2860
    jne   @f
1 ha 2861
 
2862
    in    al,dx
2863
    test  al,8
2864
    jz    hdwait_sbuf
2865
 
2866
    mov   [hd_error],0
2867
 
2868
    cmp   [hd_setup],1          ; do not mark error for setup request
2869
    je    buf_wait_ok
2870
 
2871
    test  al,1                  ; previous command ended up with an error
2872
    jz    buf_wait_ok
74 mario79 2873
 @@:
1 ha 2874
    mov   [hd_error],1
2875
 
2876
  buf_wait_ok:
2877
 
2878
    pop   edx eax
2879
    ret
2880
 
2881
 
2882
 
2883
read_hd_file:
2884
;-----------------------------------------------------------------
2885
;
2886
; Converting old reading function for hd-application start.
2887
;
2888
; IN:
2889
;
2890
; eax - pointer to file (0 = read only first sector of drive: eg 'label')
2891
; ebx - file lenght
2892
; ecx - start 512 byte block number
2893
; edx - number of blocks to read
2894
; esi - pointer to return/work area (atleast 20 000 bytes)
2895
;
2896
; For new read function
2897
;
2898
; EAX   (PAR0)      pointer to file-name
2899
; ECX   (PAR1)      pointer to buffer
2900
; EBX   (PAR2)   vt file blocks to read
2901
; EDX   (PAR3)      pointer to path
2902
; ESI            vt first 512 block to read
2903
; EDI               if 0 - return root
2904
;--------------------------------------------------------------------------
2905
 
2906
    push  ecx esi edi
2907
    mov   esi,eax
2908
    mov   edi,startpath
2909
    mov   ecx,250
2910
    cld
2911
    rep   movsb
2912
    pop   edi esi ecx
2913
 
2914
    mov   eax,startpath
2915
    mov   [eax+ebx-12],byte 0
2916
 
2917
    push  eax ebx ecx edx esi
2918
 
2919
    pop   ecx ; pointer to buffer
2920
    add   ecx,1024
2921
    pop   ebx ; number of blocks to read
2922
    pop   esi ; first block to read
2923
    dec   esi
2924
    pop   eax ; file length
2925
    pop   edx ; pointer to path
2926
 
2927
    mov   edi,12
2928
    lea   eax,[eax+edx-12+1]
2929
    call  file_read
2930
 
2931
    ret
2932
 
71 diamond 2933
; \begin{diamond}
2934
hd_find_lfn:
2935
; in: esi->name
2936
; out: CF=1 - file not found
2937
;      else CF=0 and edi->direntry
83 diamond 2938
; destroys eax
2939
        push    esi edi
2940
        push    0
2941
        push    0
2942
        push    fat16_root_first
2943
        push    fat16_root_next
2944
        mov     eax, [ROOT_CLUSTER]
2945
        cmp     [fat_type], 32
2946
        jz      .fat32
2947
.loop:
2948
        call    fat_find_lfn
2949
        jc      .notfound
2950
        cmp     byte [esi], 0
2951
        jz      .found
2952
        test    byte [edi+11], 10h
2953
        jz      .notfound
2954
        and     dword [esp+12], 0
2955
        movzx   eax, word [edi+26]      ; cluster
2956
.fat32:
2957
        mov     [esp+8], eax
2958
        mov     dword [esp+4], fat_notroot_first
2959
        mov     dword [esp], fat_notroot_next
2960
        jmp     .loop
71 diamond 2961
.notfound:
83 diamond 2962
        add     esp, 16
2963
        pop     edi esi
2964
        stc
2965
        ret
71 diamond 2966
.found:
83 diamond 2967
        add     esp, 20         ; CF=0
2968
        pop     esi
2969
        ret
74 mario79 2970
 
71 diamond 2971
;----------------------------------------------------------------
2972
;
2973
;  fs_HdRead - LFN variant for reading hard disk
2974
;
2975
;  esi  points to filename
2976
;  ebx  pointer to 64-bit number = first wanted byte, 0+
2977
;       may be ebx=0 - start from first byte
2978
;  ecx  number of bytes to read, 0+
2979
;  edx  mem location to return data
2980
;
77 diamond 2981
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 2982
;      eax = 0 ok read or other = errormsg
2983
;
2984
;--------------------------------------------------------------
2985
fs_HdRead:
74 mario79 2986
    cmp    [fat_type], 0
2987
    jnz    @f
2988
    or    ebx, -1
2989
    mov    eax, ERROR_UNKNOWN_FS
2990
    ret
71 diamond 2991
@@:
74 mario79 2992
    push    edi
2993
    cmp    byte [esi], 0
2994
    jnz    @f
71 diamond 2995
.noaccess:
74 mario79 2996
    pop    edi
2997
.noaccess_2:
2998
    or    ebx, -1
2999
    mov    eax, ERROR_ACCESS_DENIED
3000
    ret
3001
 
3002
.noaccess_3:
3003
    add esp,4
3004
.noaccess_1:
3005
    add esp,4
3006
.noaccess_4:
3007
    add esp,4*5
3008
    jmp  .noaccess_2
3009
 
71 diamond 3010
@@:
74 mario79 3011
    call    hd_find_lfn
3012
    jnc    .found
3013
    pop    edi
3014
    cmp   [hd_error],0
3015
    jne   .noaccess_2
3016
    or    ebx, -1
3017
    mov    eax, ERROR_FILE_NOT_FOUND
3018
    ret
3019
 
71 diamond 3020
.found:
74 mario79 3021
    test    byte [edi+11], 0x10    ; do not allow read directories
3022
    jnz    .noaccess
3023
    test    ebx, ebx
3024
    jz    .l1
3025
    cmp    dword [ebx+4], 0
3026
    jz    @f
77 diamond 3027
        xor     ebx, ebx
71 diamond 3028
.reteof:
74 mario79 3029
    mov    eax, 6
3030
    pop    edi
3031
    ret
71 diamond 3032
@@:
74 mario79 3033
    mov    ebx, [ebx]
71 diamond 3034
.l1:
77 diamond 3035
        push    ecx edx
3036
        push    0
3037
        mov     eax, [edi+28]
3038
        sub     eax, ebx
3039
        jb      .eof
3040
        cmp     eax, ecx
3041
        jae     @f
3042
        mov     ecx, eax
3043
        mov     byte [esp], 6
3044
@@:
74 mario79 3045
    mov    eax, [edi+20-2]
3046
    mov    ax, [edi+26]
71 diamond 3047
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
3048
.new_cluster:
74 mario79 3049
    jecxz    .new_sector
3050
    test    eax, eax
3051
    jz    .eof
3052
    cmp    eax, [fatRESERVED]
3053
    jae    .eof
3054
    mov    [cluster_tmp], eax
3055
    dec    eax
3056
    dec    eax
3057
    mov    edi, [SECTORS_PER_CLUSTER]
3058
    imul    eax, edi
3059
    add    eax, [DATA_START]
71 diamond 3060
.new_sector:
74 mario79 3061
    test    ecx, ecx
3062
    jz    .done
3063
    sub    ebx, 512
3064
    jae    .skip
3065
    add    ebx, 512
3066
    jnz    .force_buf
3067
    cmp    ecx, 512
3068
    jb    .force_buf
71 diamond 3069
; we may read directly to given buffer
74 mario79 3070
    push    ebx
3071
    mov    ebx, edx
3072
    call    hd_read
3073
    cmp  [hd_error],0
3074
    jne  .noaccess_1
3075
    pop    ebx
3076
    add    edx, 512
3077
    sub    ecx, 512
3078
    jmp    .skip
71 diamond 3079
.force_buf:
3080
; we must read sector to temporary buffer and then copy it to destination
74 mario79 3081
    push    eax ebx
3082
    mov    ebx, buffer
3083
    call    hd_read
3084
    cmp  [hd_error],0
3085
    jne  .noaccess_3
3086
 
3087
    mov    eax, ebx
3088
    pop    ebx
3089
    add    eax, ebx
3090
    push    ecx
3091
    add    ecx, ebx
3092
    cmp    ecx, 512
3093
    jbe    @f
3094
    mov    ecx, 512
71 diamond 3095
@@:
74 mario79 3096
    sub    ecx, ebx
3097
    mov    ebx, edx
3098
    call    memmove
3099
    add    edx, ecx
3100
    sub    [esp], ecx
3101
    pop    ecx
3102
    pop    eax
3103
    xor    ebx, ebx
71 diamond 3104
.skip:
74 mario79 3105
    inc    eax
3106
    dec    edi
3107
    jnz    .new_sector
3108
    mov    eax, [cluster_tmp]
3109
    call    get_FAT
3110
    cmp   [hd_error],0
3111
    jne   .noaccess_4
3112
 
3113
    jmp    .new_cluster
71 diamond 3114
.done:
77 diamond 3115
        mov     ebx, edx
3116
        pop     eax edx ecx edi
3117
        sub     ebx, edx
3118
        ret
71 diamond 3119
.eof:
77 diamond 3120
        mov     ebx, edx
3121
        pop     eax edx ecx
3122
        sub     ebx, edx
3123
        jmp     .reteof
75 diamond 3124
 
3125
;----------------------------------------------------------------
3126
;
3127
;  fs_HdReadFolder - LFN variant for reading hard disk folder
3128
;
3129
;  esi  points to filename
78 diamond 3130
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
3131
;                          & flags (bitfields)
3132
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 3133
;  ecx  number of blocks to read, 0+
3134
;  edx  mem location to return data
3135
;
77 diamond 3136
;  ret ebx = blocks read or 0xffffffff folder not found
75 diamond 3137
;      eax = 0 ok read or other = errormsg
3138
;
3139
;--------------------------------------------------------------
3140
fs_HdReadFolder:
3141
        mov     eax, [ROOT_CLUSTER]
3142
        push    edi
3143
        cmp     byte [esi], 0
3144
        jz      .doit
3145
        call    hd_find_lfn
3146
        jnc     .found
3147
        pop     edi
3148
        or      ebx, -1
3149
        mov     eax, ERROR_FILE_NOT_FOUND
3150
        ret
3151
.found:
3152
        test    byte [edi+11], 0x10     ; do not allow read files
3153
        jnz     .found_dir
3154
        pop     edi
3155
        or      ebx, -1
3156
        mov     eax, ERROR_ACCESS_DENIED
3157
        ret
3158
.found_dir:
3159
        mov     eax, [edi+20-2]
3160
        mov     ax, [edi+26]    ; eax=cluster
3161
.doit:
3162
        push    esi ecx
3163
        push    ebp
3164
        sub     esp, 262*2      ; reserve space for LFN
3165
        mov     ebp, esp
78 diamond 3166
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
3167
        mov     ebx, [ebx]
75 diamond 3168
; init header
3169
        push    eax ecx
3170
        mov     edi, edx
3171
        mov     ecx, 32/4
3172
        xor     eax, eax
3173
        rep     stosd
3174
        pop     ecx eax
3175
        mov     byte [edx], 1   ; version
3176
        mov     esi, edi        ; esi points to BDFE
3177
.new_cluster:
3178
        mov     [cluster_tmp], eax
3179
        test    eax, eax
3180
        jnz     @f
3181
        cmp     [fat_type], 32
3182
        jz      .notfound
3183
        mov     eax, [ROOT_START]
3184
        push    [ROOT_SECTORS]
3185
        push    ebx
3186
        jmp     .new_sector
3187
@@:
3188
        dec     eax
3189
        dec     eax
3190
        imul    eax, [SECTORS_PER_CLUSTER]
3191
        push    [SECTORS_PER_CLUSTER]
3192
        add     eax, [DATA_START]
3193
        push    ebx
3194
.new_sector:
3195
        mov     ebx, buffer
3196
        mov     edi, ebx
3197
        call    hd_read
3198
        cmp     [hd_error], 0
3199
        jnz     .notfound2
3200
        add     ebx, 512
3201
        push    eax
3202
.l1:
3203
        call    fat_get_name
3204
        jc      .l2
3205
        cmp     byte [edi+11], 0xF
3206
        jnz     .do_bdfe
3207
        add     edi, 0x20
3208
        cmp     edi, ebx
3209
        jb      .do_bdfe
3210
        pop     eax
3211
        inc     eax
3212
        dec     dword [esp+4]
3213
        jnz     @f
3214
        mov     eax, [cluster_tmp]
3215
        test    eax, eax
3216
        jz      .done
3217
        call    get_FAT
3218
        cmp     [hd_error], 0
3219
        jnz     .notfound2
3220
        cmp     eax, 2
3221
        jb      .done
3222
        cmp     eax, [fatRESERVED]
3223
        jae     .done
3224
        push    eax
3225
        mov     eax, [SECTORS_PER_CLUSTER]
3226
        mov     [esp+8], eax
3227
        pop     eax
3228
        mov     [cluster_tmp], eax
3229
        dec     eax
3230
        dec     eax
3231
        imul    eax, [SECTORS_PER_CLUSTER]
3232
        add     eax, [DATA_START]
3233
@@:
3234
        mov     ebx, buffer
3235
        mov     edi, ebx
3236
        call    hd_read
3237
        cmp     [hd_error], 0
3238
        jnz     .notfound2
3239
        add     ebx, 512
3240
        push    eax
3241
.do_bdfe:
3242
        inc     dword [edx+8]   ; new file found
3243
        dec     dword [esp+4]
3244
        jns     .l2
3245
        dec     ecx
3246
        js      .l2
3247
        inc     dword [edx+4]   ; new file block copied
3248
        call    fat_entry_to_bdfe
3249
.l2:
3250
        add     edi, 0x20
3251
        cmp     edi, ebx
3252
        jb      .l1
3253
        pop     eax
3254
        inc     eax
3255
        dec     dword [esp+4]
3256
        jnz     .new_sector
3257
        mov     eax, [cluster_tmp]
3258
        test    eax, eax
3259
        jz      .done
3260
        call    get_FAT
3261
        cmp     [hd_error], 0
3262
        jnz     .notfound2
3263
        cmp     eax, 2
3264
        jb      .done
3265
        cmp     eax, [fatRESERVED]
3266
        jae     .done
3267
        push    eax
3268
        mov     eax, [SECTORS_PER_CLUSTER]
3269
        mov     [esp+8], eax
3270
        pop     eax
3271
        pop     ebx
3272
        add     esp, 4
3273
        jmp     .new_cluster
3274
.notfound2:
3275
        add     esp, 8
3276
.notfound:
3277
        add     esp, 262*2+4
3278
        pop     ebp ecx esi edi
3279
        mov     eax, ERROR_FILE_NOT_FOUND
3280
        or      ebx, -1
3281
        ret
3282
.done:
3283
        add     esp, 262*2+4+8
3284
        pop     ebp
77 diamond 3285
        mov     ebx, [edx+4]
75 diamond 3286
        xor     eax, eax
3287
        dec     ecx
3288
        js      @f
3289
        mov     al, ERROR_END_OF_FILE
3290
@@:
3291
        pop     ecx esi edi
3292
        ret
3293
 
83 diamond 3294
fat16_root_next:
3295
        cmp     edi, buffer+0x200-0x20
3296
        jae     fat16_root_next_sector
3297
        add     edi, 0x20
3298
        ret     ; CF=0
3299
fat16_root_next_sector:
3300
; read next sector
3301
        push    ecx
3302
        mov     ecx, [eax+4]
3303
        inc     ecx
3304
        mov     [eax+4], ecx
3305
        cmp     ecx, [ROOT_SECTORS]
3306
        pop     ecx
3307
        jae     fat16_root_first.readerr
3308
fat16_root_first:
3309
        mov     eax, [eax+4]
3310
        add     eax, [ROOT_START]
3311
        push    ebx
3312
        mov     edi, buffer
3313
        mov     ebx, edi
3314
        call    hd_read
3315
        pop     ebx
3316
        cmp     [hd_error], 0
3317
        jnz     .readerr
3318
        ret     ; CF=0
3319
.readerr:
3320
        stc
3321
        ret
3322
fat16_root_begin_write:
3323
        push    edi eax
3324
        call    fat16_root_first
3325
        pop     eax edi
3326
        ret
3327
fat16_root_end_write:
3328
        pusha
3329
        mov     eax, [eax+4]
3330
        add     eax, [ROOT_START]
3331
        mov     ebx, buffer
3332
        call    hd_write
3333
        popa
3334
        ret
3335
fat16_root_next_write:
3336
        cmp     edi, buffer+0x200
3337
        jae     @f
3338
        ret
3339
@@:
3340
        call    fat16_root_end_write
3341
        jmp     fat16_root_next_sector
3342
fat16_root_extend_dir:
3343
        stc
3344
        ret
3345
 
3346
fat_notroot_next:
3347
        cmp     edi, buffer+0x200-0x20
3348
        jae     fat_notroot_next_sector
3349
        add     edi, 0x20
3350
        ret     ; CF=0
3351
fat_notroot_next_sector:
3352
        push    ecx
3353
        mov     ecx, [eax+4]
3354
        inc     ecx
3355
        cmp     ecx, [SECTORS_PER_CLUSTER]
3356
        jae     fat_notroot_next_cluster
3357
        mov     [eax+4], ecx
3358
        jmp     @f
3359
fat_notroot_next_cluster:
3360
        push    eax
3361
        mov     eax, [eax]
3362
        call    get_FAT
3363
        mov     ecx, eax
3364
        pop     eax
3365
        cmp     [hd_error], 0
3366
        jnz     fat_notroot_next_err
3367
        cmp     ecx, [fatRESERVED]
3368
        jae     fat_notroot_next_err
3369
        mov     [eax], ecx
3370
        and     dword [eax+4], 0
3371
@@:
3372
        pop     ecx
3373
fat_notroot_first:
3374
        call    fat_get_sector
3375
        push    ebx
3376
        mov     edi, buffer
3377
        mov     ebx, edi
3378
        call    hd_read
3379
        pop     ebx
3380
        cmp     [hd_error], 0
3381
        jnz     @f
3382
        ret     ; CF=0
3383
fat_notroot_next_err:
3384
        pop     ecx
3385
@@:
3386
        stc
3387
        ret
3388
fat_notroot_begin_write:
3389
        push    eax edi
3390
        call    fat_notroot_first
3391
        pop     edi eax
3392
        ret
3393
fat_notroot_end_write:
3394
        call    fat_get_sector
3395
        push    ebx
3396
        mov     ebx, buffer
3397
        call    hd_write
3398
        pop     ebx
3399
        ret
3400
fat_notroot_next_write:
3401
        cmp     edi, buffer+0x200
3402
        jae     @f
3403
        ret
3404
@@:
3405
        push    eax
3406
        call    fat_notroot_end_write
3407
        pop     eax
3408
        jmp     fat_notroot_next_sector
3409
fat_notroot_extend_dir:
3410
        push    eax
3411
        mov     eax, [eax]
3412
        call    get_free_FAT
3413
        jnc     .found
3414
        pop     eax
3415
        ret     ; CF=1
3416
.found:
3417
        push    edx
3418
        mov     edx, [fatEND]
3419
        call    set_FAT
3420
        mov     edx, eax
3421
        mov     eax, [esp+4]
3422
        mov     eax, [eax]
3423
        push    edx
3424
        mov     [f_del], 1
3425
        call    set_FAT
3426
        pop     edx
3427
        cmp     [hd_error], 0
3428
        jz      @f
3429
        pop     edx
3430
        pop     eax
3431
        stc
3432
        ret
3433
@@:
3434
        push    ecx
3435
        or      ecx, -1
3436
        call    add_disk_free_space
3437
; zero new cluster
3438
        mov     ecx, 512/4
3439
        mov     edi, buffer
3440
        push    edi
3441
        xor     eax, eax
3442
        rep     stosd
3443
        pop     edi
3444
        pop     ecx
3445
        mov     eax, [esp+4]
3446
        mov     [eax], edx
3447
        and     dword [eax+4], 0
3448
        pop     edx
3449
        mov     eax, [eax]
3450
        dec     eax
3451
        dec     eax
3452
        push    ebx ecx
3453
        mov     ecx, [SECTORS_PER_CLUSTER]
3454
        imul    eax, ecx
3455
        add     eax, [DATA_START]
3456
        mov     ebx, edi
3457
@@:
3458
        call    hd_write
3459
        inc     eax
3460
        loop    @b
3461
        pop     ecx ebx eax
3462
        clc
3463
        ret
3464
 
3465
fat_get_sector:
3466
        push    ecx
3467
        mov     ecx, [eax]
3468
        dec     ecx
3469
        dec     ecx
3470
        imul    ecx, [SECTORS_PER_CLUSTER]
3471
        add     ecx, [DATA_START]
3472
        add     ecx, [eax+4]
3473
        mov     eax, ecx
3474
        pop     ecx
3475
        ret
3476
 
3477
;----------------------------------------------------------------
3478
;
3479
;  fs_HdRewrite - LFN variant for writing hard disk
3480
;
3481
;  esi  points to filename
3482
;  ebx  ignored (reserved)
3483
;  ecx  number of bytes to write, 0+
3484
;  edx  mem location to data
3485
;
3486
;  ret ebx = number of written bytes
3487
;      eax = 0 ok read or other = errormsg
3488
;
3489
;--------------------------------------------------------------
3490
fshrad:
3491
        mov     eax, ERROR_ACCESS_DENIED
3492
        xor     ebx, ebx
3493
        ret
3494
fshrfs:
3495
        mov     eax, ERROR_UNKNOWN_FS
3496
        xor     ebx, ebx
3497
        ret
3498
 
3499
fs_HdRewrite:
3500
        cmp     [fat_type], 0
3501
        jz      fshrfs
3502
        cmp     byte [esi], 0
3503
        jz      fshrad
3504
        pushad
3505
        xor     ebp, ebp
3506
        push    esi
3507
@@:
3508
        lodsb
3509
        test    al, al
3510
        jz      @f
3511
        cmp     al, '/'
3512
        jnz     @b
3513
        lea     ebp, [esi-1]
3514
        jmp     @b
3515
@@:
3516
        pop     esi
3517
        test    ebp, ebp
3518
        jnz     .noroot
3519
        mov     ebp, [ROOT_CLUSTER]
3520
        cmp     [fat_type], 32
3521
        jz      .pushnotroot
3522
        push    fat16_root_extend_dir
3523
        push    fat16_root_end_write
3524
        push    fat16_root_next_write
3525
        push    fat16_root_begin_write
3526
        xor     ebp, ebp
3527
        push    ebp
3528
        push    ebp
3529
        push    fat16_root_first
3530
        push    fat16_root_next
3531
        jmp     .common1
3532
.noroot:
3533
; check existence
3534
        mov     byte [ebp], 0
3535
        call    hd_find_lfn
3536
        mov     byte [ebp], '/'
3537
        lea     esi, [ebp+1]
3538
        jnc     @f
3539
        mov     eax, ERROR_FILE_NOT_FOUND
3540
.ret1:
3541
        mov     [esp+28], eax
3542
        popad
3543
        xor     ebx, ebx
3544
        ret
3545
@@:
3546
        test    byte [edi+11], 0x10     ; must be directory
3547
        mov     eax, ERROR_ACCESS_DENIED
3548
        jz      .ret1
3549
        mov     ebp, [edi+20-2]
3550
        mov     bp, [edi+26]            ; ebp=cluster
3551
        mov     eax, ERROR_FAT_TABLE
3552
        cmp     ebp, 2
3553
        jb      .ret1
3554
.pushnotroot:
3555
        push    fat_notroot_extend_dir
3556
        push    fat_notroot_end_write
3557
        push    fat_notroot_next_write
3558
        push    fat_notroot_begin_write
3559
        push    0
3560
        push    ebp
3561
        push    fat_notroot_first
3562
        push    fat_notroot_next
3563
.common1:
3564
        call    fat_find_lfn
3565
        jc      .notfound
3566
; found, delete FAT chain
3567
        push    edi
3568
        xor     eax, eax
3569
        mov     dword [edi+28], eax     ; zero size
3570
        xor     ecx, ecx
3571
        mov     eax, [edi+20-2]
3572
        mov     ax, [edi+26]
3573
        mov     word [edi+20], cx
3574
        mov     word [edi+26], cx
3575
        test    eax, eax
3576
        jz      .done1
3577
        mov     [f_del], 1
3578
@@:
3579
        cmp     eax, [fatRESERVED]
3580
        jae     .done1
3581
        push    edx
3582
        xor     edx, edx
3583
        call    set_FAT
3584
        mov     eax, edx
3585
        pop     edx
3586
        inc     ecx
3587
        jmp     @b
3588
.done1:
3589
        pop     edi
3590
        call    get_time_for_file
3591
        mov     [edi+22], ax
3592
        call    get_date_for_file
3593
        mov     [edi+24], ax
3594
        mov     [edi+18], ax
3595
        or      byte [edi+11], 20h      ; set 'archive' attribute
3596
        jmp     .doit
3597
.notfound:
3598
; file is not found; generate short name
3599
        call    fat_name_is_legal
3600
        jc      @f
3601
        add     esp, 32
3602
        popad
3603
        mov     eax, ERROR_FILE_NOT_FOUND
3604
        xor     ebx, ebx
3605
        ret
3606
@@:
3607
        sub     esp, 12
3608
        mov     edi, esp
3609
        call    fat_gen_short_name
3610
.test_short_name_loop:
3611
        push    esi edi ecx
3612
        mov     esi, edi
3613
        lea     eax, [esp+12+12+8]
3614
        mov     [eax], ebp
3615
        and     dword [eax+4], 0
3616
        call    dword [eax-4]
3617
        jc      .found
3618
.test_short_name_entry:
3619
        cmp     byte [edi+11], 0xF
3620
        jz      .test_short_name_cont
3621
        mov     ecx, 11
3622
        push    esi edi
3623
        repz    cmpsb
3624
        pop     edi esi
3625
        jz      .short_name_found
3626
.test_short_name_cont:
3627
        lea     eax, [esp+12+12+8]
3628
        call    dword [eax-8]
3629
        jnc     .test_short_name_entry
3630
        jmp     .found
3631
.short_name_found:
3632
        pop     ecx edi esi
3633
        call    fat_next_short_name
3634
        jnc     .test_short_name_loop
3635
.disk_full:
3636
        add     esp, 12+32
3637
        popa
3638
        mov     eax, ERROR_DISK_FULL
3639
        xor     ebx, ebx
3640
        ret
3641
.found:
3642
        pop     ecx edi esi
3643
; now find space in directory
3644
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
3645
        mov     al, '~'
3646
        push    ecx edi
3647
        mov     ecx, 8
3648
        repnz   scasb
3649
        push    1
3650
        pop     eax     ; 1 entry
3651
        jnz     .notilde
3652
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
3653
        xor     eax, eax
3654
@@:
3655
        cmp     byte [esi], 0
3656
        jz      @f
3657
        inc     esi
3658
        inc     eax
3659
        jmp     @b
3660
@@:
3661
        sub     esi, eax
3662
        add     eax, 12+13
3663
        mov     ecx, 13
3664
        push    edx
3665
        cdq
3666
        div     ecx
3667
        pop     edx
3668
.notilde:
3669
        push    -1
3670
        push    -1
3671
        push    -1
3672
; find  successive entries in directory
3673
        xor     ecx, ecx
3674
        push    eax
3675
        lea     eax, [esp+16+8+12+8]
3676
        mov     [eax], ebp
3677
        and     dword [eax+4], 0
3678
        call    dword [eax-4]
3679
        pop     eax
3680
        jnc     .scan_dir
3681
.fsfrfe3:
3682
        add     esp, 12+8+12+32
3683
        popad
3684
        mov     eax, 11
3685
        xor     ebx, ebx
3686
        ret
3687
.scan_dir:
3688
        cmp     byte [edi], 0
3689
        jz      .free
3690
        cmp     byte [edi], 0xE5
3691
        jz      .free
3692
        xor     ecx, ecx
3693
.scan_cont:
3694
        push    eax
3695
        lea     eax, [esp+16+8+12+8]
3696
        call    dword [eax-8]
3697
        pop     eax
3698
        jnc     .scan_dir
3699
        cmp     [hd_error], 0
3700
        jnz     .fsfrfe3
3701
        push    eax
3702
        lea     eax, [esp+16+8+12+8]
3703
        call    dword [eax+20]          ; extend directory
3704
        pop     eax
3705
        jnc     .scan_dir
3706
        add     esp, 12+8+12+32
3707
        popad
3708
        mov     eax, ERROR_DISK_FULL
3709
        xor     ebx, ebx
3710
        ret
3711
.free:
3712
        test    ecx, ecx
3713
        jnz     @f
3714
        mov     [esp], edi
3715
        mov     ecx, [esp+12+8+12+8]
3716
        mov     [esp+4], ecx
3717
        mov     ecx, [esp+12+8+12+12]
3718
        mov     [esp+8], ecx
3719
        xor     ecx, ecx
3720
@@:
3721
        inc     ecx
3722
        cmp     ecx, eax
3723
        jb      .scan_cont
3724
; found!
3725
; calculate name checksum
3726
        push    esi ecx
3727
        mov     esi, [esp+8+12]
3728
        mov     ecx, 11
3729
        xor     eax, eax
3730
@@:
3731
        ror     al, 1
3732
        add     al, [esi]
3733
        inc     esi
3734
        loop    @b
3735
        pop     ecx esi
3736
        pop     edi
3737
        pop     dword [esp+8+12+12]
3738
        pop     dword [esp+8+12+12]
3739
; edi points to first entry in free chunk
3740
        dec     ecx
3741
        jz      .nolfn
3742
        push    esi
3743
        push    eax
3744
        lea     eax, [esp+8+8+12+8]
3745
        call    dword [eax+8]         ; begin write
3746
        mov     al, 40h
3747
.writelfn:
3748
        or      al, cl
3749
        mov     esi, [esp+4]
3750
        push    ecx
3751
        dec     ecx
3752
        imul    ecx, 13
3753
        add     esi, ecx
3754
        stosb
3755
        mov     cl, 5
3756
        call    fs_RamdiskRewrite.read_symbols
3757
        mov     ax, 0xF
3758
        stosw
3759
        mov     al, [esp+4]
3760
        stosb
3761
        mov     cl, 6
3762
        call    fs_RamdiskRewrite.read_symbols
3763
        xor     eax, eax
3764
        stosw
3765
        mov     cl, 2
3766
        call    fs_RamdiskRewrite.read_symbols
3767
        pop     ecx
3768
        lea     eax, [esp+8+8+12+8]
3769
        call    dword [eax+12]         ; next write
3770
        xor     eax, eax
3771
        loop    .writelfn
3772
        pop     eax
3773
        pop     esi
3774
;        lea     eax, [esp+8+12+8]
3775
;        call    dword [eax+16]          ; end write
3776
.nolfn:
3777
        xchg    esi, [esp]
3778
        mov     ecx, 11
3779
        rep     movsb
3780
        mov     word [edi], 20h         ; attributes
3781
        sub     edi, 11
3782
        pop     esi ecx
3783
        add     esp, 12
3784
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
3785
        call    get_time_for_file
3786
        mov     [edi+14], ax            ; creation time
3787
        mov     [edi+22], ax            ; last write time
3788
        call    get_date_for_file
3789
        mov     [edi+16], ax            ; creation date
3790
        mov     [edi+24], ax            ; last write date
3791
        mov     [edi+18], ax            ; last access date
3792
        xor     ecx, ecx
3793
        mov     word [edi+20], cx       ; high word of cluster
3794
        mov     word [edi+26], cx       ; low word of cluster - to be filled
3795
        mov     dword [edi+28], ecx     ; file size - to be filled
3796
.doit:
3797
        lea     eax, [esp+8]
3798
        call    dword [eax+16]  ; flush directory
3799
        push    ecx
3800
        mov     ecx, [esp+4+32+24]
3801
        push    ecx
3802
        push    edi
3803
        mov     esi, edx
3804
        test    ecx, ecx
3805
        jz      .done
3806
        mov     eax, 2
3807
        call    get_free_FAT
3808
        jc      .diskfull
3809
        push    eax
3810
        mov     [edi+26], ax
3811
        shr     eax, 16
3812
        mov     [edi+20], ax
3813
        lea     eax, [esp+16+8]
3814
        call    dword [eax+16]  ; flush directory
3815
        pop     eax
3816
        push    edx
3817
        mov     edx, [fatEND]
3818
        call    set_FAT
3819
        pop     edx
3820
.write_cluster:
3821
        push    eax
3822
        dec     eax
3823
        dec     eax
3824
        mov     ebp, [SECTORS_PER_CLUSTER]
3825
        imul    eax, ebp
3826
        add     eax, [DATA_START]
3827
; write data
3828
.write_sector:
3829
        mov     ecx, 512
3830
        cmp     dword [esp+8], ecx
3831
        jb      .writeshort
3832
; we can write directly from given buffer
3833
        mov     ebx, esi
3834
        add     esi, ecx
3835
        jmp     .writecommon
3836
.writeshort:
3837
        mov     ecx, [esp+8]
3838
        push    ecx
3839
        mov     edi, buffer
3840
        mov     ebx, edi
3841
        rep     movsb
3842
        mov     ecx, buffer+0x200
3843
        sub     ecx, edi
3844
        push    eax
3845
        xor     eax, eax
3846
        rep     stosb
3847
        pop     eax
3848
        pop     ecx
3849
.writecommon:
3850
        call    hd_write
3851
        cmp     [hd_error], 0
3852
        jnz     .writeerr
3853
        inc     eax
3854
        sub     dword [esp+8], ecx
3855
        jz      .writedone
3856
        dec     ebp
3857
        jnz     .write_sector
3858
; allocate new cluster
3859
        pop     eax
3860
        mov     ecx, eax
3861
        call    get_free_FAT
3862
        jc      .diskfull
3863
        mov     [f_del], 1
3864
        push    edx
3865
        mov     edx, [fatEND]
3866
        call    set_FAT
3867
        xchg    eax, ecx
3868
        mov     edx, ecx
3869
        call    set_FAT
3870
        pop     edx
3871
        xchg    eax, ecx
3872
        jmp     .write_cluster
3873
.diskfull:
3874
        mov     eax, ERROR_DISK_FULL
3875
        jmp     .ret
3876
.writeerr:
3877
        pop     eax
3878
        sub     esi, ecx
3879
        mov     eax, 11
3880
        jmp     .ret
3881
.writedone:
3882
        pop     eax
3883
.done:
3884
        xor     eax, eax
3885
.ret:
3886
        pop     edi ecx
3887
        mov     ebx, esi
3888
        sub     ebx, edx
3889
        pop     ebp
3890
        mov     [esp+32+28], eax
3891
        lea     eax, [esp+8]
3892
        call    dword [eax+8]
3893
        mov     [edi+28], ebx
3894
        call    dword [eax+16]
3895
        mov     [esp+32+16], ebx
3896
        lea     eax, [ebx+511]
3897
        shr     eax, 9
3898
        mov     ecx, [SECTORS_PER_CLUSTER]
3899
        lea     eax, [eax+ecx-1]
3900
        xor     edx, edx
3901
        div     ecx
3902
        mov     ecx, ebp
3903
        sub     ecx, eax
3904
        call    add_disk_free_space
3905
        add     esp, 32
3906
        call    update_disk
3907
        popad
3908
        ret
3909
 
74 mario79 3910
; \end{diamond}