Subversion Repositories Kolibri OS

Rev

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