Subversion Repositories Kolibri OS

Rev

Rev 63 | 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                                   ;;
10
;;                                                                 ;;
65 mario79 11
;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
12
;;             to MBR, see file part_set.inc - Mario79             ;;
1 ha 13
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
14
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
15
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
16
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
17
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
18
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
19
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
20
;;  08.11.2004 rename - ATV                                        ;;
21
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
22
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
23
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
24
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
25
;;  24.5.2004  Write back buffer for File_write -VT                ;;
26
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
27
;;  30.3.2004  Error parameters at function return - VT            ;;
28
;;  01.5.2002  Bugfix in device write - VT                         ;;
29
;;  20.5.2002  Hd status check - VT                                ;;
30
;;  29.6.2002  Improved fat32 verification - VT                    ;;
31
;;                                                                 ;;
32
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
33
 
34
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
35
 
52 mikedld 36
ERROR_SUCCESS        = 0
37
ERROR_DISK_BASE      = 1
38
ERROR_UNSUPPORTED_FS = 2
39
ERROR_UNKNOWN_FS     = 3
40
ERROR_PARTITION      = 4
41
ERROR_FILE_NOT_FOUND = 5
42
ERROR_END_OF_FILE    = 6
43
ERROR_MEMORY_POINTER = 7
44
ERROR_DISK_FULL      = 8
45
ERROR_FAT_TABLE      = 9
46
ERROR_ACCESS_DENIED  = 10
1 ha 47
 
48
PUSHAD_EAX equ [esp+28]
49
PUSHAD_ECX equ [esp+24]
50
PUSHAD_EDX equ [esp+20]
51
PUSHAD_EBX equ [esp+16]
52
PUSHAD_EBP equ [esp+8]
53
PUSHAD_ESI equ [esp+4]
54
PUSHAD_EDI equ [esp+0]
55
 
56
cluster              dd 0       ; used by file_write,makedir,append
57
partition_count      dd 0       ; partitions found by set_FAT32_variables
58
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
59
longname_sec2        dd 0       ; directory sectors for delete long filename
60
 
61
hd_error             dd 0       ; set by wait_for_sector_buffer
62
hd_setup             dd 0
63
hd_wait_timeout      dd 0
64
 
65
cluster_tmp          dd 0       ; used by analyze_directory
66
                                ; and analyze_directory_to_write
67
 
68
file_size            dd 0       ; used by file_read
69
 
70
sector_tmp           dd 0       ; used by rename,append,file_write
71
entry_pos            dd 0       ; used by rename,append,file_write
72
 
73
old_filesize         dd 0       ; used by append
74
new_filepos          dd 0       ; used by append
75
bytes2write          dd 0       ; used by append
76
 
77
cache_search_start   dd 0       ; used by find_empty_slot
78
 
79
fat_in_cache         dd -1
80
fat_cache:           times 512 db 0
81
 
82
uglobal
83
 Sector512:                      ; label for dev_hdcd.inc
84
  buffer:              times 512 db 0
85
  deltree_buffer:      times 512 db 0
86
endg
87
 
88
iglobal
89
  NewDirEntry1         db ".          ",0x10
90
                     times 20 db 0
91
  NewDirEntry2         db "..         ",0x10
92
                     times 20 db 0
93
endg
94
 
95
uglobal
96
  dir_entry:           times 32 db 0
97
 
98
  startpath:           times 255 db 0
99
 
100
  fat16_root           db 0       ; flag for fat16 rootdir
101
  f_del                db 0       ; 1=overwrite fat entry
102
  fat_change           db 0       ; 1=fat has changed
103
 
104
endg
105
 
106
reserve_hd1:
107
 
108
    cli
109
    cmp   [hd1_status],0
110
    je    reserve_ok1
111
 
112
    sti
113
    call  change_task
114
    jmp   reserve_hd1
115
 
116
  reserve_ok1:
117
 
118
    push  eax
119
    mov   eax,[0x3000]
120
    shl   eax,5
121
    mov   eax,[eax+0x3000+4]
122
    mov   [hd1_status],eax
123
    pop   eax
124
    sti
125
    ret
126
 
127
 
128
clear_hd_cache:
129
 
130
    push  eax ecx edi
131
    mov   edi,0x600000
132
    mov   ecx,16384
133
    xor   eax,eax
134
    cld
135
    rep   stosd                 ; clear hd cache with 0
136
    mov   [cache_search_start],eax
137
    mov   [fat_in_cache],-1
138
    mov   [fat_change],0
139
    pop   edi ecx eax
140
    ret
141
 
142
problem_partition db 0  ; used for partitions search
143
 
65 mario79 144
include  'part_set.inc'
1 ha 145
 
146
set_FAT:
147
;--------------------------------
148
; input  : EAX = cluster
149
;          EDX = value to save
150
; output : EDX = old value
151
;--------------------------------
152
    push  eax ebx esi
153
 
154
    cmp   eax,2
155
    jb    sfc_error
156
    cmp   eax,[LAST_CLUSTER]
157
    ja    sfc_error
158
    cmp   [fat_type],16
159
    je    sfc_1
160
    add   eax,eax
161
  sfc_1:
162
    add   eax,eax
163
    mov   esi,511
164
    and   esi,eax               ; esi = position in fat sector
165
    shr   eax,9                 ; eax = fat sector
166
    add   eax,[FAT_START]
167
    mov   ebx,fat_cache
168
 
169
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
170
    je    sfc_in_cache          ; yes
171
 
172
    cmp   [fat_change],0        ; is fat changed?
173
    je    sfc_no_change         ; no
174
    call  write_fat_sector      ; yes. write it into disk
175
 
176
  sfc_no_change:
177
    mov   [fat_in_cache],eax    ; save fat sector
178
    call  hd_read
179
 
180
  sfc_in_cache:
181
    cmp   [fat_type],16
182
    jne   sfc_test32
183
 
184
    cmp   [f_del],1             ; overwrite previous value?
185
    je    sfc_set16             ; yes
186
    cmp   word [ebx+esi],0      ; is cluster free?
187
    je    sfc_set16             ; yes
188
    mov   dword [8*0x100000],0xffffff
189
    mov   edx,[ebx+esi]         ; get old value
190
    jmp   sfc_nonzero
191
 
192
  sfc_set16:
193
    xchg  [ebx+esi],dx          ; save new value and get old value
194
    jmp   sfc_write
195
 
196
  sfc_test32:
197
    mov   eax,[fatMASK]
198
    cmp   [f_del],1             ; overwrite previous value?
199
    je    sfc_set32             ; yes
200
    test  eax,[ebx+esi]         ; is cluster free?
201
    je    sfc_set32             ; yes
202
    mov   dword [8*0x100000],0xffffff
203
    mov   edx,[ebx+esi]         ; get old value
204
    jmp   sfc_nonzero
205
 
206
  sfc_set32:
207
    and   edx,eax
208
    xor   eax,-1                ; mask for high bits
209
    and   eax,[ebx+esi]         ; get high 4 bits
210
    or    eax,edx
211
    mov   edx,[ebx+esi]         ; get old value
212
    mov   [ebx+esi],eax         ; save new value
213
 
214
  sfc_write:
215
    mov   [fat_change],1        ; fat has changed
216
 
217
  sfc_nonzero:
218
    and   edx,[fatMASK]
219
 
220
  sfc_error:
221
    pop   esi ebx eax
222
    ret
223
 
224
 
225
get_FAT:
226
;--------------------------------
227
; input  : EAX = cluster
228
; output : EAX = next cluster
229
;--------------------------------
230
    push  ebx esi
231
 
232
    cmp   [fat_type],16
233
    je    gfc_1
234
    add   eax,eax
235
  gfc_1:
236
    add   eax,eax
237
    mov   esi,511
238
    and   esi,eax               ; esi = position in fat sector
239
    shr   eax,9                 ; eax = fat sector
240
    add   eax,[FAT_START]
241
    mov   ebx,fat_cache
242
 
243
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
244
    je    gfc_in_cache
245
 
246
    cmp   [fat_change],0        ; is fat changed?
247
    je    gfc_no_change         ; no
248
    call  write_fat_sector      ; yes. write it into disk
249
 
250
  gfc_no_change:
251
    mov   [fat_in_cache],eax
252
    call  hd_read
253
 
254
  gfc_in_cache:
255
    mov   eax,[ebx+esi]
256
    and   eax,[fatMASK]
257
    pop   esi ebx
258
    ret
259
 
260
 
261
get_free_FAT:
262
;-----------------------------------------------------------
263
; input  : EAX = # cluster for start the searching
264
; output : if CARRY=0 EAX = # first cluster found free
265
;          if CARRY=1 disk full
266
; Note   : for more speed need to use fat_cache directly
267
;-----------------------------------------------------------
268
    push  ecx
269
    mov   ecx,[LAST_CLUSTER]    ; counter for full disk
270
    sub   ecx,2
271
 
272
  gff_test:
273
    cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
274
    jbe   gff_in_range
275
    mov   eax,2
276
 
277
  gff_in_range:
278
    push  eax
279
    call  get_FAT               ; get cluster state
280
    test  eax,eax               ; is it free?
281
    pop   eax
282
    je    gff_found             ; yes
283
    inc   eax                   ; next cluster
284
    dec   ecx                   ; is all checked?
285
    jns   gff_test              ; no
286
 
287
  gff_not_found:
288
    pop   ecx                   ; yes. disk is full
289
    stc
290
    ret
291
 
292
  gff_found:
293
    pop   ecx
294
    clc
295
    ret
296
 
297
 
298
write_fat_sector:
299
;-----------------------------------------------------------
300
; write changed fat to disk
301
;-----------------------------------------------------------
302
    push  eax ebx ecx
303
 
304
    mov   [fat_change],0
305
    mov   eax,[fat_in_cache]
306
    cmp   eax,-1
307
    jz    write_fat_not_used
308
    mov   ebx,fat_cache
309
    mov   ecx,[NUMBER_OF_FATS]
310
 
311
  write_next_fat:
312
    call  hd_write
313
    add   eax,[SECTORS_PER_FAT]
314
    dec   ecx
315
    jnz   write_next_fat
316
 
317
  write_fat_not_used:
318
    pop   ecx ebx eax
319
    ret
320
 
321
 
322
analyze_directory:
323
;-----------------------------------------------------------
324
; input  : EAX = first cluster of the directory
325
;          EBX = pointer to filename
326
; output : IF CARRY=0 EAX = sector where th file is found
327
;                     EBX = pointer in buffer
328
;                     [buffer .. buffer+511]
329
;                     ECX,EDX,ESI,EDI not changed
330
;          IF CARRY=1 filename not found
331
; Note   : if cluster=0 it's changed to read rootdir
332
;          save 2 previous directory sectors in longname_sec
333
;-----------------------------------------------------------
334
    push  ecx edx esi edi ebx   ; ebx = [esp+0]
335
    mov   [longname_sec1],0
336
    mov   [longname_sec2],0
337
 
338
  adr_new_cluster:
339
    mov   [cluster_tmp],eax
340
    mov   [fat16_root],0
341
    cmp   eax,[LAST_CLUSTER]
342
    ja    adr_not_found         ; too big cluster number, something is wrong
343
    cmp   eax,2
344
    jnb   adr_data_cluster
345
 
346
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
347
    cmp   [fat_type],16
348
    jne   adr_data_cluster
349
    mov   eax,[ROOT_START]
350
    mov   edx,[ROOT_SECTORS]
351
    mov   [fat16_root],1        ; flag for fat16 rootdir
352
    jmp   adr_new_sector
353
 
354
  adr_data_cluster:
355
    sub   eax,2
356
    mov   edx,[SECTORS_PER_CLUSTER]
357
    imul  eax,edx
358
    add   eax,[DATA_START]
359
 
360
  adr_new_sector:
361
    mov   ebx,buffer
362
    call  hd_read
363
    mov   ecx,512/32            ; count of dir entrys per sector = 16
364
 
365
  adr_analyze:
366
    mov   edi,[ebx+11]          ; file attribute
367
    and   edi,0xf
368
    cmp   edi,0xf
369
    je    adr_long_filename
370
    test  edi,0x8               ; skip over volume label
371
    jne   adr_long_filename     ; Note: label can be same name as file/dir
372
 
373
    mov   esi,[esp+0]           ; filename need to be uppercase
374
    mov   edi,ebx
375
    push  ecx
376
    mov   ecx,11
377
    cld
378
    rep   cmpsb                 ; compare 8+3 filename
379
    pop   ecx
380
    je    adr_found
381
 
382
  adr_long_filename:
383
    add   ebx,32                ; position of next dir entry
384
    dec   ecx
385
    jnz   adr_analyze
386
 
387
    mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
388
    mov   [longname_sec1],eax   ; for delete long filename
389
    mov   [longname_sec2],ecx
390
    inc   eax                   ; next sector
391
    dec   edx
392
    jne   adr_new_sector
393
    cmp   [fat16_root],1        ; end of fat16 rootdir
394
    je    adr_not_found
395
 
396
  adr_next_cluster:
397
    mov   eax,[cluster_tmp]
398
    call  get_FAT               ; get next cluster
399
    cmp   eax,2                 ; incorrect fat chain?
400
    jb    adr_not_found         ; yes
401
    cmp   eax,[fatRESERVED]     ; is it end of directory?
402
    jb    adr_new_cluster       ; no. analyse it
403
 
404
  adr_not_found:
405
    pop   edi edi esi edx ecx   ; first edi will remove ebx
406
    stc                         ; file not found
407
    ret
408
 
409
  adr_found:
410
    pop   edi edi esi edx ecx   ; first edi will remove ebx
411
    clc                         ; file found
412
    ret
413
 
414
 
415
analyze_directory_to_write:
416
;-----------------------------------------------------------
417
; input  : EAX = first cluster of the directory
418
; output : IF CARRY=0 EAX = sector where the empty pos is found
419
;                     EBX = pointer in buffer
420
;                     [buffer .. buffer+511]
421
;                     ECX,EDX,ESI,EDI not changed
422
;          IF CARRY=1 disk full or fat corrupted
423
; Note   : if cluster=0 it's changed to read rootdir
424
;-----------------------------------------------------------
425
    push  ecx edx edi
426
 
427
  adw_new_cluster:
428
    mov   [cluster_tmp],eax
429
    mov   [fat16_root],0
430
    cmp   eax,[LAST_CLUSTER]
431
    ja    adw_not_found         ; too big cluster number, something is wrong
432
    cmp   eax,2
433
    jnb   adw_data_cluster
434
 
435
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
436
    cmp   [fat_type],16
437
    jne   adw_data_cluster
438
    mov   eax,[ROOT_START]
439
    mov   edx,[ROOT_SECTORS]
440
    mov   [fat16_root],1        ; flag for fat16 rootdir
441
    jmp   adw_new_sector
442
 
443
  adw_data_cluster:
444
    sub   eax,2
445
    mov   edx,[SECTORS_PER_CLUSTER]
446
    imul  eax,edx
447
    add   eax,[DATA_START]
448
 
449
  adw_new_sector:
450
    mov   ebx,buffer
451
    call  hd_read
452
    mov   ecx,512/32            ; count of dir entrys per sector = 16
453
 
454
  adw_analyze:
455
    cmp   byte [ebx],0x00       ; is free entry?
456
    je    adw_found             ; yes
457
    cmp   byte [ebx],0xe5       ; is deleted entry?
458
    je    adw_found             ; yes
459
    add   ebx,32                ; position of next dir entry
460
    dec   ecx
461
    jnz   adw_analyze
462
 
463
    inc   eax                   ; next sector
464
    dec   edx
465
    jne   adw_new_sector
466
    cmp   [fat16_root],1        ; end of fat16 rootdir
467
    je    adw_not_found
468
 
469
    mov   eax,[cluster_tmp]
470
    call  get_FAT               ; get next cluster
471
    cmp   eax,2                 ; incorrect fat chain?
472
    jb    adw_not_found         ; yes
473
    cmp   eax,[fatRESERVED]     ; is it end of directory?
474
    jb    adw_new_cluster       ; no. analyse it
475
 
476
    mov   eax,2                 ; this block of code add a new cluster
477
    call  get_free_FAT          ; for the directory because the directory
478
    jc    adw_not_found         ; is full
479
 
480
    mov   edx,[fatEND]          ; new end for directory
481
    call  set_FAT
482
 
483
    push  eax                   ; save new cluster
484
    mov   edx,eax
485
    mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
486
    mov   [f_del],1
487
    call  set_FAT
488
    mov   [f_del],0
489
 
490
    mov   ecx,-1                ; remove 1 cluster from free disk space
491
    call  add_disk_free_space
492
 
493
    mov   ecx,512/4
494
    xor   eax,eax
495
    mov   edi,buffer
496
    cld
497
    rep   stosd                 ; clear new directory cluster
498
    pop   eax
499
 
500
    sub   eax,2
501
    mov   ecx,[SECTORS_PER_CLUSTER]
502
    imul  eax,ecx
503
    add   eax,[DATA_START]
504
    mov   ebx,buffer
505
    push  eax                   ; save sector number
506
 
507
  adw_set_empty_directory:
508
    call  hd_write
509
    inc   eax                   ; next sector
510
    dec   ecx
511
    jnz   adw_set_empty_directory
512
 
513
    pop   eax
514
 
515
  adw_found:
516
    pop   edi edx ecx
517
    clc                         ; free space found
518
    ret
519
 
520
  adw_not_found:
521
    pop   edi edx ecx
522
    stc                         ; free space not found
523
    ret
524
 
525
 
526
get_data_cluster:
527
;-----------------------------------------------------------
528
; input  : EAX = cluster
529
;          EBX = pointer to buffer
530
;          EDX = # blocks to read in buffer
531
;          ESI = # blocks to skip over
532
; output : if CARRY=0 ok EBX/EDX/ESI updated
533
;          if CARRY=1 cluster out of range
534
; Note   : if cluster=0 it's changed to read rootdir
535
;-----------------------------------------------------------
536
    push  eax ecx
537
 
538
    mov   [fat16_root],0
539
    cmp   eax,[LAST_CLUSTER]
540
    ja    gdc_error             ; too big cluster number, something is wrong
541
    cmp   eax,2
542
    jnb   gdc_cluster
543
 
544
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
545
    cmp   [fat_type],16
546
    jne   gdc_cluster
547
    mov   eax,[ROOT_START]
548
    mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
549
    mov   [fat16_root],1        ; flag for fat16 rootdir
550
    jmp   gdc_read
551
 
552
  gdc_cluster:
553
    sub   eax,2
554
    mov   ecx,[SECTORS_PER_CLUSTER]
555
    imul  eax,ecx
556
    add   eax,[DATA_START]
557
 
558
  gdc_read:
559
    test  esi,esi               ; first wanted block
560
    je    gdcl1                 ; yes, skip count is 0
561
    dec   esi
562
    jmp   gdcl2
563
 
564
  gdcl1:
565
    call  hd_read
566
    add   ebx,512               ; update pointer
567
    dec   edx
568
 
569
  gdcl2:
570
    test  edx,edx               ; is all read?
571
    je    out_of_read
572
 
573
    inc   eax                   ; next sector
574
    dec   ecx
575
    jnz   gdc_read
576
 
577
  out_of_read:
578
    pop   ecx eax
579
    clc
580
    ret
581
 
582
  gdc_error:
583
    pop   ecx eax
584
    stc
585
    ret
586
 
587
 
588
set_data_cluster:
589
;-----------------------------------------------------------
590
; input  : EAX = cluster
591
;          EBX = pointer to buffer
592
; output : if CARRY=0 ok
593
;          if CARRY=1 cluster out of range
594
;-----------------------------------------------------------
595
    push  eax ebx edx
596
 
597
    cmp   eax,[LAST_CLUSTER]
598
    ja    sdc_error             ; too big cluster number, something is wrong
599
    sub   eax,2
600
    jb    sdc_error             ; don't allow rootdir write
601
 
602
    mov   edx,[SECTORS_PER_CLUSTER]
603
    imul  eax,edx
604
    add   eax,[DATA_START]
605
 
606
  sdc_write:
607
    call  hd_write
608
    add   ebx,512               ; update pointer
609
    inc   eax
610
    dec   edx
611
    jnz   sdc_write
612
    pop   edx ebx eax
613
    clc
614
    ret
615
 
616
  sdc_error:
617
    pop   edx ebx eax
618
    stc
619
    ret
620
 
621
 
622
get_cluster_of_a_path:
623
;---------------------------------------------------------
624
; input  : EBX = pointer to a path string
625
;          (example: the path "/files/data/document" become
626
;                             "files......data.......document...0"
627
;          '.' = space char
628
;          '0' = char(0) (ASCII=0) !!! )
629
; output : if (CARRY=1) -> ERROR in the PATH
630
;          if (CARRY=0) -> EAX=cluster
631
;---------------------------------------------------------
632
    push  ebx edx
633
 
634
    mov   eax,[ROOT_CLUSTER]
635
    mov   edx,ebx
636
 
637
search_end_of_path:
638
    cmp   byte [edx],0
639
    je    found_end_of_path
640
 
641
    inc   edx ; '/'
642
    mov   ebx,edx
643
    call  analyze_directory
644
    jc    directory_not_found
645
 
646
    mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
647
    mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
648
    and   eax,[fatMASK]
649
    add   edx,11                ; 8+3 (name+extension)
650
    jmp   search_end_of_path
651
 
652
found_end_of_path:
653
    pop   edx ebx
654
    clc                         ; no errors
655
    ret
656
 
657
directory_not_found:
658
    pop   edx ebx
659
    stc                         ; errors occour
660
    ret
661
 
662
 
663
bcd2bin:
664
;----------------------------------
665
; input  : AL=BCD number (eg. 0x11)
666
; output : AH=0
667
;          AL=decimal number (eg. 11)
668
;----------------------------------
669
    xor   ah,ah
670
    shl   ax,4
671
    shr   al,4
672
    aad
673
    ret
674
 
675
 
676
get_date_for_file:
677
;-----------------------------------------------------
678
; Get date from CMOS and pack day,month,year in AX
679
; DATE   bits  0..4   : day of month 0..31
680
;              5..8   : month of year 1..12
681
;              9..15  : count of years from 1980
682
;-----------------------------------------------------
683
    mov   al,0x7        ;day
684
    out   0x70,al
685
    in    al,0x71
686
    call  bcd2bin
687
    ror   eax,5
688
 
689
    mov   al,0x8        ;month
690
    out   0x70,al
691
    in    al,0x71
692
    call  bcd2bin
693
    ror   eax,4
694
 
695
    mov   al,0x9        ;year
696
    out   0x70,al
697
    in    al,0x71
698
    call  bcd2bin
699
    add   ax,20         ;because CMOS return only the two last
700
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
701
    rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
702
    ret
703
 
704
 
705
get_time_for_file:
706
;-----------------------------------------------------
707
; Get time from CMOS and pack hour,minute,second in AX
708
; TIME   bits  0..4   : second (the low bit is lost)
709
;              5..10  : minute 0..59
710
;              11..15 : hour 0..23
711
;-----------------------------------------------------
712
    mov   al,0x0        ;second
713
    out   0x70,al
714
    in    al,0x71
715
    call  bcd2bin
716
    ror   eax,6
717
 
718
    mov   al,0x2        ;minute
719
    out   0x70,al
720
    in    al,0x71
721
    call  bcd2bin
722
    ror   eax,6
723
 
724
    mov   al,0x4        ;hour
725
    out   0x70,al
726
    in    al,0x71
727
    call  bcd2bin
728
    rol   eax,11
729
    ret
730
 
731
 
732
set_current_time_for_entry:
733
;-----------------------------------------------------
734
; Set current time/date for file entry
735
; input  : ebx = file entry pointer
736
;-----------------------------------------------------
737
    push  eax
738
    call  get_time_for_file     ; update files date/time
739
    mov   [ebx+22],ax
740
    call  get_date_for_file
741
    mov   [ebx+24],ax
742
    pop   eax
743
    ret
744
 
745
 
746
makedir:
747
;-----------------------------------------------------
748
; input  : eax = directory name
749
;          edx = path
750
; output : eax = 0 - ok
751
;                3 - unknown FS
752
;                5 - file not found
753
;                8 - disk full
754
;               10 - access denied
755
; Note   : can only make one directory at time
756
;-----------------------------------------------------
757
    cmp   [fat_type],0
758
    jnz   make_dir_fat_ok
759
    mov   eax,ERROR_UNKNOWN_FS
760
    ret
761
 
762
  make_dir_fat_ok:
763
;    call  reserve_hd1
764
 
765
    pushad
766
 
767
    mov   ebx,edx
768
    call  get_cluster_of_a_path
769
    jnc   make_dir_found_path
770
 
771
  make_dir_path_not_found:
772
    popad
773
    call  update_disk           ; write all of cache and fat to hd
774
    mov   [hd1_status],0
775
    mov   eax,ERROR_FILE_NOT_FOUND
776
    ret
777
 
778
  make_dir_disk_full:
779
    popad
780
    call  update_disk           ; write all of cache and fat to hd
781
    mov   [hd1_status],0
782
    mov   eax,ERROR_DISK_FULL
783
    ret
784
 
785
  make_dir_already_exist:
786
    mov   eax,[cluster]         ; directory cluster
787
    xor   edx,edx               ; free
788
    mov   [f_del],1
789
    call  set_FAT
790
    mov   [f_del],0
791
 
792
    popad
793
    call  update_disk           ; write all of cache and fat to hd
794
    mov   [hd1_status],0
795
    mov   eax,ERROR_ACCESS_DENIED
796
    ret
797
 
798
  make_dir_found_path:
799
    cmp   eax,[ROOT_CLUSTER]
800
    jnz   make_dir_not_root
801
    xor   eax,eax
802
 
803
  make_dir_not_root:
804
    mov   ecx,eax               ; directorys start cluster
805
    mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
806
    shr   ecx,16
807
    mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
808
 
809
    push  eax                   ; save parent directory cluster
810
    mov   eax,2
811
    call  get_free_FAT
812
    mov   [cluster],eax         ; first free cluster
813
    pop   eax
814
    jc    make_dir_disk_full
815
 
816
    push  eax
817
    mov   eax,[cluster]         ; directory cluster
818
    mov   edx,[fatEND]          ; end for directory
819
    call  set_FAT
820
    pop   eax
821
 
822
    mov   ebx,PUSHAD_EAX        ; dir name
823
    push  eax
824
    call  analyze_directory     ; check if directory already exist
825
    pop   eax
826
    jnc   make_dir_already_exist ; need to free allocated cluster!
827
 
828
    call  analyze_directory_to_write
829
    jc    make_dir_already_exist ; need to free allocated cluster!
830
 
831
    mov   esi,PUSHAD_EAX        ; dir name
832
    mov   edi,ebx               ; pointer in buffer
833
    mov   ecx,11
834
    cld
835
    rep   movsb
836
 
837
    mov   dword [ebx+28],0      ; dir size is always 0
838
    mov   ecx,[cluster]
839
    mov   [ebx+26],cx           ; 16 bits low of cluster
840
    mov   word [NewDirEntry1+26],cx
841
    shr   ecx,16
842
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
843
    mov   word [NewDirEntry1+20],cx
844
    mov   byte [ebx+11],0x10    ; attribute = directory
845
 
846
    call  set_current_time_for_entry
847
    mov   ecx,[ebx+22]
848
    mov   dword [NewDirEntry1+22],ecx
849
    mov   dword [NewDirEntry2+22],ecx
850
 
851
    mov   ebx,buffer            ; save the directory name,length,cluster
852
    call  hd_write
853
 
854
    mov   ecx,512/4
855
    xor   eax,eax
856
    mov   edi,buffer
857
    cld
858
    rep   stosd                 ; clear new directory cluster
859
 
860
    mov   eax,[cluster]         ; new directory cluster
861
    sub   eax,2
862
    mov   edx,[SECTORS_PER_CLUSTER]
863
    imul  eax,edx
864
    add   eax,[DATA_START]
865
    mov   ebx,buffer
866
    add   eax,edx               ; start from last sector
867
 
868
  dir_set_empty_directory:
869
    dec   eax                   ; next sector
870
    cmp   edx,1                 ; is first directory sector?
871
    jnz   not_first_sector      ; no. write empty sector
872
    mov   esi,NewDirEntry1
873
    mov   edi,buffer
874
    mov   ecx,64/4
875
    cld
876
    rep   movsd                 ; copy 2 first directory entrys "." and ".."
877
 
878
  not_first_sector:
879
    call  hd_write
880
    dec   edx
881
    jnz   dir_set_empty_directory
882
 
883
    mov   ecx,-1                ; remove 1 cluster from free disk space
884
    call  add_disk_free_space
885
 
886
    popad
887
    call  update_disk           ; write all of cache and fat to hd
888
    mov   [hd1_status],0
889
    xor   eax,eax
890
    ret
891
 
892
 
893
removedir:
894
;-----------------------------------------------------
895
; input  : eax = file/directory name
896
;          edx = path
897
; output : eax = 0 - ok
898
;                3 - unknown FS
899
;                5 - file not found
900
;               10 - access denied
901
;-----------------------------------------------------
902
    cmp   [fat_type],0
903
    jnz   remove_dir_fat_ok
904
    mov   eax,ERROR_UNKNOWN_FS
905
    ret
906
 
907
  remove_dir_fat_ok:
908
;    call  reserve_hd1
909
 
910
    push  edi
911
    mov   edi,1                 ; allow directory remove
912
    call  file_delete
913
    pop   edi
914
 
915
    call  update_disk           ; write all of cache and fat to hd
916
    mov   [hd1_status],0
917
    ret
918
 
919
 
920
add_disk_free_space:
921
;-----------------------------------------------------
922
; input  : ecx = cluster count
923
; Note   : negative = remove clusters from free space
924
;          positive = add clusters to free space
925
;-----------------------------------------------------
926
    test  ecx,ecx               ; no change
927
    je    add_dfs_no
928
    cmp   [fat_type],32         ; free disk space only used by fat32
929
    jne   add_dfs_no
930
 
931
    push  eax ebx
932
    mov   eax,[ADR_FSINFO]
933
    mov   ebx,buffer
934
    call  hd_read
935
    cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
936
    jne   add_not_fs
937
 
938
    add   [ebx+0x1e8],ecx
939
    call  hd_write
940
 
941
  add_not_fs:
942
    pop   ebx eax
943
 
944
  add_dfs_no:
945
    ret
946
 
947
 
948
file_append:
949
;-----------------------------------------------------
950
; input  : eax = file name
951
;          edx = path
952
;          ecx = pointer to buffer
953
;          ebx = bytes to write (0 = truncate file)
954
;          esi = start position (-1 = end of file)
955
; output : eax = 0 - ok
956
;                3 - unknown FS
957
;                5 - file not found
958
;                6 - end of file
959
;                8 - disk full
960
;                9 - fat table corrupted
961
;               10 - access denied
962
;          ebx = bytes written
963
;-----------------------------------------------------
964
    cmp   [fat_type],0
965
    jnz   append_fat_ok
966
    mov   eax,ERROR_UNKNOWN_FS
967
    ret
968
 
969
  append_fat_ok:
970
;    call  reserve_hd1
971
 
972
    pushad
973
 
974
    mov   ebx,edx
975
    call  get_cluster_of_a_path
976
    jc    append_not_found
977
 
978
    mov   ebx,PUSHAD_EAX        ; file name
979
    call  analyze_directory
980
    jc    append_not_found
981
 
982
    mov   [sector_tmp],eax
983
    mov   [entry_pos],ebx
984
 
985
    test  byte [ebx+11],0x10    ; is it directory?
986
    jnz   append_access         ; yes
987
 
988
    mov   ecx,[ebx+28]          ; file size
989
    mov   edi,PUSHAD_ESI        ; write position
990
    cmp   edi,-1                ; -1 = eof
991
    jnz   append_inside_file
992
    mov   edi,ecx               ; file size
993
 
994
  append_inside_file:
995
    cmp   edi,ecx               ; start above old file size?
996
    ja    append_eof            ; yes
997
 
998
    mov   [old_filesize],ecx
999
    mov   [new_filepos],edi
1000
 
1001
    mov   ecx,PUSHAD_EBX        ; bytes to write
1002
    test  ecx,ecx               ; truncate?
1003
    jz    append_truncate       ; yes
1004
 
1005
    mov   [bytes2write],ecx     ; bytes to write
1006
    mov   esi,PUSHAD_ECX        ; pointer to buffer
1007
    mov   eax,[ebx+20-2]        ; FAT entry
1008
    mov   ax,[ebx+26]
1009
    and   eax,[fatMASK]
1010
    jnz   append_find_pos       ; first cluster <> 0
1011
 
1012
    mov   eax,2
1013
    call  get_free_FAT
1014
    jc    append_disk_full
1015
    mov   ecx,eax               ; set files first cluster
1016
    mov   [ebx+26],cx           ; 16 bits low of cluster
1017
    shr   ecx,16
1018
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1019
    mov   edx,[fatEND]          ; new end for cluster chain
1020
    call  set_FAT
1021
 
1022
    push  eax                   ; save first cluster
1023
    mov   eax,[sector_tmp]
1024
    mov   ebx,buffer
1025
    call  hd_write              ; write new file entry back to disk
1026
    pop   eax
1027
 
1028
  append_remove_free:
1029
    mov   ecx,-1                ; remove 1 cluster from free disk space
1030
    call  add_disk_free_space   ; Note: uses buffer
1031
 
1032
  append_found_cluster:
1033
    mov   [cluster],eax
1034
    sub   eax,2
1035
    mov   ecx,[SECTORS_PER_CLUSTER]
1036
    imul  eax,ecx
1037
    add   eax,[DATA_START]
1038
    xor   edi,edi
1039
 
1040
  append_new_sector:
1041
    push  ecx
1042
    mov   ecx,[bytes2write]     ; bytes left in buffer
1043
    mov   ebx,512
1044
    sub   ebx,edi               ; bytes left in sector
1045
    cmp   ecx,ebx
1046
    jb    append_bytes_ok
1047
    mov   ecx,ebx
1048
 
1049
  append_bytes_ok:
1050
    cmp   ecx,512               ; overwrite full sector?
1051
    jz    append_full_sector    ; yes
1052
    mov   ebx,buffer            ; overwrite part of sector
1053
    call  hd_read               ; read old sector
1054
 
1055
  append_full_sector:
1056
    sub   [bytes2write],ecx
1057
    add   [new_filepos],ecx
1058
    add   edi,buffer
1059
    cld
1060
    rep   movsb
1061
    pop   ecx
1062
 
1063
    mov   ebx,buffer
1064
    call  hd_write
1065
    cmp   [bytes2write],0       ; is all done?
1066
    jz    append_done
1067
    xor   edi,edi
1068
    inc   eax
1069
    dec   ecx
1070
    jnz   append_new_sector
1071
 
1072
    mov   eax,[cluster]
1073
    call  get_FAT
1074
    cmp   eax,2
1075
    jb    append_fat
1076
    cmp   eax,[LAST_CLUSTER]
1077
    jbe   append_found_cluster
1078
 
1079
  append_alloc_cluster:
1080
    mov   eax,2                 ; ToDo: use temp array to keep track
1081
    call  get_free_FAT          ;       of last free cluster
1082
    jc    append_disk_full
1083
    push  eax                   ; save new cluster
1084
    mov   edx,[fatEND]          ; new end for cluster chain
1085
    call  set_FAT
1086
    mov   edx,eax
1087
    mov   eax,[cluster]
1088
    mov   [f_del],1
1089
    call  set_FAT               ; update previous cluster
1090
    mov   [f_del],0
1091
    pop   eax
1092
    jmp   append_remove_free
1093
 
1094
  append_find_pos:
1095
    call  find_filepos
1096
    mov   [cluster],ebx
1097
    jnc   append_new_sector
1098
    test  edi,edi
1099
    jz    append_alloc_cluster
1100
 
1101
  append_fat:
1102
    mov   eax,ERROR_FAT_TABLE
1103
    jmp   append_ret_code
1104
 
1105
  append_disk_full:
1106
    mov   eax,ERROR_DISK_FULL
1107
    jmp   append_ret_code
1108
 
1109
  append_done:
1110
    xor   eax,eax
1111
 
1112
  append_ret_code:
1113
    mov   PUSHAD_EAX,eax        ; return code
1114
 
1115
    mov   eax,[sector_tmp]      ; update directory entry
1116
    mov   ebx,buffer
1117
    call  hd_read
1118
    mov   ebx,[entry_pos]
1119
    mov   ecx,[new_filepos]
1120
    cmp   ecx,[old_filesize]    ; is file pos above old size?
1121
    jbe   append_size_ok        ; no
1122
    mov   [ebx+28],ecx          ; new file size
1123
 
1124
  append_size_ok:
1125
    call  set_current_time_for_entry
1126
    mov   ebx,buffer
1127
    call  hd_write              ; write new file entry back to disk
1128
 
1129
    sub   ecx,PUSHAD_ESI        ; start position
1130
    mov   PUSHAD_EBX,ecx        ; bytes written
1131
    popad
1132
    call  update_disk           ; write all of cache and fat to hd
1133
    mov   [hd1_status],0
1134
    ret
1135
 
1136
  append_eof:
1137
    popad
1138
    mov   [hd1_status],0
1139
    xor   ebx,ebx
1140
    mov   eax,ERROR_END_OF_FILE
1141
    ret
1142
 
1143
  append_not_found:
1144
    popad
1145
    mov   [hd1_status],0
1146
    xor   ebx,ebx
1147
    mov   eax,ERROR_FILE_NOT_FOUND
1148
    ret
1149
 
1150
  append_access:
1151
    popad
1152
    mov   [hd1_status],0
1153
    xor   ebx,ebx
1154
    mov   eax,ERROR_ACCESS_DENIED
1155
    ret
1156
 
1157
  append_truncate:
1158
    mov   edx,[ebx+20-2]        ; FAT entry
1159
    mov   dx,[ebx+26]
1160
    and   edx,[fatMASK]
1161
    mov   [ebx+28],edi          ; set new file size
1162
    test  edi,edi               ; 0 length file?
1163
    jnz   truncate_save_size    ; no
1164
    mov   [ebx+20],di           ; FAT entry = 0
1165
    mov   [ebx+26],di
1166
 
1167
  truncate_save_size:
1168
    call  set_current_time_for_entry
1169
    mov   ebx,buffer
1170
    call  hd_write
1171
    mov   eax,edx               ; first cluster
1172
    test  edi,edi               ; 0 length file?
1173
    jz    truncate_clear_chain
1174
 
1175
    imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
1176
 
1177
  truncate_new_cluster:
1178
    cmp   eax,2                 ; incorrect fat chain?
1179
    jb    truncate_eof          ; yes
1180
    cmp   eax,[fatRESERVED]     ; is it end of file?
1181
    jnb   truncate_eof          ; yes
1182
    sub   edi,esi
1183
    jbe   truncate_pos_found
1184
    call  get_FAT               ; get next cluster
1185
    jmp   truncate_new_cluster
1186
 
1187
  truncate_pos_found:
1188
    mov   edx,[fatEND]          ; new end for cluster chain
1189
    mov   [f_del],1
1190
    call  set_FAT
1191
    mov   [f_del],0
1192
    mov   eax,edx               ; clear rest of chain
1193
 
1194
  truncate_clear_chain:
1195
    call  clear_cluster_chain
1196
 
1197
  truncate_eof:
1198
    popad
1199
    call  update_disk           ; write all of cache and fat to hd
1200
    mov   [hd1_status],0
1201
    xor   ebx,ebx
1202
    xor   eax,eax
1203
    ret
1204
 
1205
 
1206
find_filepos:
1207
;-----------------------------------------------------
1208
; input  : eax = first cluster
1209
;          edi = bytes to skip over (start position)
1210
; output : if CARRY=0 file position found
1211
;          if CARRY=1 end of file found
1212
;          eax = current file sector
1213
;          ebx = last cluster
1214
;          ecx = sector count in last cluster
1215
;          edi = bytes to skip over (sector position)
1216
;-----------------------------------------------------
1217
    push  esi
1218
    mov   ecx,[SECTORS_PER_CLUSTER]
1219
    imul  esi,ecx,512           ; esi = cluster size in bytes
1220
    mov   ebx,eax
1221
 
1222
  filepos_new_cluster:
1223
    cmp   eax,2                 ; incorrect fat chain?
1224
    jb    filepos_eof           ; yes
1225
    cmp   eax,[fatRESERVED]     ; is it end of file?
1226
    jnb   filepos_eof           ; yes
1227
 
1228
    mov   ebx,eax
1229
    cmp   edi,esi               ; skip over full cluster?
1230
    jb    filepos_cluster_ok    ; no
1231
 
1232
    sub   edi,esi
1233
    call  get_FAT               ; get next cluster
1234
    jmp   filepos_new_cluster
1235
 
1236
  filepos_cluster_ok:
1237
    sub   eax,2
1238
    imul  eax,ecx
1239
    add   eax,[DATA_START]
1240
 
1241
  filepos_new_sector:
1242
    cmp   edi,512               ; skip over full sector?
1243
    jb    filepos_sector_ok     ; no
1244
    sub   edi,512
1245
    inc   eax
1246
    dec   ecx
1247
    jnz   filepos_new_sector
1248
 
1249
  filepos_eof:
1250
    pop   esi
1251
    stc
1252
    ret
1253
 
1254
  filepos_sector_ok:
1255
    pop   esi
1256
    clc
1257
    ret
1258
 
1259
 
1260
file_write:
1261
;--------------------------------------------------------------------------
1262
;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
1263
;
1264
;            EAX        EDI            system call to write    /
1265
;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
1266
;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
1267
;            ECX        EBX   (PAR2)   file size               PAR2
1268
;            ESI        EDX   (PAR3)   pointer to path         PAR3
1269
;
1270
; output : eax = 0 - ok
1271
;                3 - unknown FS
1272
;                5 - file not found
1273
;                8 - disk full
1274
;               10 - access denied
1275
;--------------------------------------------------------------------------
1276
    cmp   [fat_type],0
1277
    jnz   fat_ok_for_writing
1278
    mov   eax,ERROR_UNKNOWN_FS
1279
    ret
1280
 
1281
  fat_ok_for_writing:
1282
;    call  reserve_hd1
1283
 
1284
    pushad
1285
 
1286
    xor   edi,edi               ; don't allow directory remove
1287
    call  file_delete           ; try to delete the file first
1288
    test  eax,eax
1289
    jz    old_deleted           ; deleted ok
1290
    cmp   eax,ERROR_FILE_NOT_FOUND
1291
    jnz   exit_write_access     ; it exist but can't delete
1292
 
1293
  old_deleted:
1294
    mov   ebx,PUSHAD_EDX
1295
    call  get_cluster_of_a_path
1296
    jnc   found_directory_for_writing
1297
 
1298
  exit_writing_with_error:
1299
    popad
1300
    call  update_disk           ; write all of cache and fat to hd
1301
    mov   [hd1_status],0
1302
    mov   eax,ERROR_FILE_NOT_FOUND
1303
    ret
1304
 
1305
  exit_writing_disk_full_clear:
1306
    mov   eax,[sector_tmp]
1307
    mov   ebx,buffer
1308
    call  hd_read               ; read directory sector
1309
    mov   edx,[entry_pos]
1310
    mov   byte [edx],0xe5       ; mark as deleted
1311
    call  hd_write
1312
    mov   eax,[edx+20-2]        ; FAT entry
1313
    mov   ax,[edx+26]
1314
    and   eax,[fatMASK]
1315
    call  clear_cluster_chain
1316
 
1317
  exit_writing_disk_full:
1318
    popad
1319
    call  update_disk           ; write all of cache and fat to hd
1320
    mov   [hd1_status],0
1321
    mov   eax,ERROR_DISK_FULL
1322
    ret
1323
 
1324
  exit_write_access:
1325
    popad
1326
    call  update_disk           ; write all of cache and fat to hd
1327
    mov   [hd1_status],0
1328
    mov   eax,ERROR_ACCESS_DENIED
1329
    ret
1330
 
1331
found_directory_for_writing:
1332
    call  analyze_directory_to_write
1333
    jc    exit_writing_disk_full
1334
 
1335
    mov   [sector_tmp],eax
1336
    mov   [entry_pos],ebx
1337
    push  eax                   ; save directory sector
1338
    mov   eax,2
1339
    call  get_free_FAT
1340
    mov   [cluster],eax         ; first free cluster
1341
    pop   eax
1342
    jc    exit_writing_disk_full
1343
 
1344
    mov   esi,PUSHAD_EAX        ; file name
1345
    mov   edi,ebx               ; pointer in buffer
1346
    mov   ecx,11
1347
    cld
1348
    rep   movsb
1349
 
1350
    mov   esi,PUSHAD_EBX        ; file size (bytes left)
1351
    mov   [ebx+28],esi          ; file size
1352
    mov   ecx,[cluster]
1353
    mov   [ebx+26],cx           ; 16 bits low of cluster
1354
    shr   ecx,16
1355
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1356
    mov   byte [ebx+11],0x20    ; attribute = archive
1357
 
1358
    call  set_current_time_for_entry
1359
 
1360
    mov   ebx,buffer            ; save the directory name,length,cluster
1361
    call  hd_write
1362
 
1363
    imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
1364
    xor   ecx,ecx               ; cluster count
1365
    mov   ebx,PUSHAD_ECX        ; ebx = buffer
1366
 
1367
hd_new_block_write:
1368
 
1369
    mov   eax,[cluster]         ; eax = block
1370
    call  set_data_cluster
1371
 
1372
    sub   esi,edi               ; sub wrote bytes
1373
    jbe   file_saved_OK         ; end if all done
1374
    add   ebx,edi               ; update buffer position
1375
 
1376
    inc   eax
1377
    call  get_free_FAT          ; next free in FAT
1378
    jc    exit_writing_disk_full_clear
1379
 
1380
    mov   edx,eax
1381
    xchg  eax,[cluster]         ; get old cluster and save new cluster
1382
    call  set_FAT               ; add it in cluster chain
1383
    dec   ecx                   ; update cluster count
1384
    jmp   hd_new_block_write
1385
 
1386
file_saved_OK:
1387
 
1388
    mov   edx,[fatEND]          ; new end for cluster chain
1389
    call  set_FAT
1390
    dec   ecx                   ; update cluster count
1391
 
1392
    call  add_disk_free_space   ; remove clusters from free disk space
1393
 
1394
    popad
1395
    call  update_disk           ; write all of cache and fat to hd
1396
    mov   [hd1_status],0
1397
    xor   eax,eax
1398
    ret
1399
 
1400
 
1401
file_read:
1402
;--------------------------------------------------------------------------
1403
;   INPUT :  user-register register-in-this  meaning         symbol-in-this
1404
;
1405
;            EAX           EDI               system call to write   /
1406
;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
1407
;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
1408
;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
1409
;            ESI           EDX   (PAR3)      pointer to path        PAR3
1410
;            EDI           ESI            vt first 512 block to read
1411
;                          EDI               if 0 - read root
1412
;
1413
; output : eax = 0 - ok
1414
;                3 - unknown FS
1415
;                5 - file not found
1416
;                6 - end of file
1417
;                9 - fat table corrupted
1418
;          ebx = size of file/directory
1419
;--------------------------------------------------------------------------
1420
    cmp   [fat_type],0
1421
    jnz   fat_ok_for_reading
1422
    xor   ebx,ebx
1423
    mov   eax,ERROR_UNKNOWN_FS
63 halyavin 1424
    mov   [hd1_status], ebx
1 ha 1425
    ret
1426
 
1427
  fat_ok_for_reading:
1428
;    call  reserve_hd1
1429
 
1430
    pushad
1431
 
1432
    mov   ebx,edx
1433
    call  get_cluster_of_a_path
1434
    jc    file_to_read_not_found
1435
 
1436
    test  edi,edi               ; read rootdir
1437
    jne   no_read_root
1438
 
1439
    xor   eax,eax
1440
    call  get_dir_size          ; return rootdir size
1441
    mov   [file_size],eax
1442
    mov   eax,[ROOT_CLUSTER]
1443
    jmp   file_read_start
1444
 
1445
  no_read_root:
1446
    mov   ebx,PUSHAD_EAX        ; file name
1447
    call  analyze_directory
1448
    jc    file_to_read_not_found
1449
 
1450
    mov   eax,[ebx+28]          ; file size
1451
    test  byte [ebx+11],0x10    ; is it directory?
1452
    jz    read_set_size         ; no
1453
 
1454
    mov   eax,[ebx+20-2]        ; FAT entry
1455
    mov   ax,[ebx+26]
1456
    and   eax,[fatMASK]
1457
    call  get_dir_size
1458
 
1459
  read_set_size:
1460
    mov   [file_size],eax
1461
 
1462
    mov   eax,[ebx+20-2]        ; FAT entry
1463
    mov   ax,[ebx+26]
1464
    and   eax,[fatMASK]
1465
 
1466
  file_read_start:
1467
    mov   ebx,PUSHAD_ECX        ; pointer to buffer
1468
    mov   edx,PUSHAD_EBX        ; file blocks to read
1469
    mov   esi,PUSHAD_ESI        ; first 512 block to read
1470
 
1471
  file_read_new_cluster:
1472
    call  get_data_cluster
1473
    jc    file_read_eof         ; end of file or cluster out of range
1474
 
1475
    test  edx,edx               ; is all read?
1476
    je    file_read_OK          ; yes
1477
 
1478
    call  get_FAT               ; get next cluster
1479
    cmp   eax,[fatRESERVED]     ; end of file
1480
    jnb   file_read_eof
1481
    cmp   eax,2                 ; incorrect fat chain
1482
    jnb   file_read_new_cluster
1483
 
1484
    popad
1485
    mov   [hd1_status],0
1486
    mov   ebx,[file_size]
1487
    mov   eax,ERROR_FAT_TABLE
1488
    ret
1489
 
1490
  file_read_eof:
1491
    popad
1492
    mov   [hd1_status],0
1493
    mov   ebx,[file_size]
1494
    mov   eax,ERROR_END_OF_FILE
1495
    ret
1496
 
1497
  file_read_OK:
1498
    popad
1499
    mov   [hd1_status],0
1500
    mov   ebx,[file_size]
1501
    xor   eax,eax
1502
    ret
1503
 
1504
  file_to_read_not_found:
1505
    popad
1506
    mov   [hd1_status],0
1507
    xor   ebx,ebx
1508
    mov   eax,ERROR_FILE_NOT_FOUND
1509
    ret
1510
 
1511
 
1512
get_dir_size:
1513
;-----------------------------------------------------
1514
; input  : eax = first cluster (0=rootdir)
1515
; output : eax = directory size in bytes
1516
;-----------------------------------------------------
1517
    push  edx
1518
    xor   edx,edx               ; count of directory clusters
1519
    test  eax,eax
1520
    jnz   dir_size_next
1521
 
1522
    mov   eax,[ROOT_SECTORS]
1523
    shl   eax,9                 ; fat16 rootdir size in bytes
1524
    cmp   [fat_type],16
1525
    je    dir_size_ret
1526
    mov   eax,[ROOT_CLUSTER]
1527
 
1528
  dir_size_next:
1529
    cmp   eax,2                 ; incorrect fat chain
1530
    jb    dir_size_end
1531
    cmp   eax,[fatRESERVED]     ; end of directory
1532
    ja    dir_size_end
1533
    call  get_FAT               ; get next cluster
1534
    inc   edx
1535
    jmp   dir_size_next
1536
 
1537
  dir_size_end:
1538
    imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
1539
    imul  eax,edx
1540
 
1541
  dir_size_ret:
1542
    pop   edx
1543
    ret
1544
 
1545
 
1546
file_delete:
1547
;-----------------------------------------------------
1548
; input  : eax = file/directory name
1549
;          edx = path
1550
;          edi = 1 - allow directory remove else don't remove directory
1551
; output : eax = 0 - ok
1552
;                3 - unknown FS
1553
;                5 - file not found
1554
;               10 - access denied
1555
;-----------------------------------------------------
1556
    cmp   [fat_type],0
1557
    jnz   file_del_fat_ok
1558
    mov   eax,ERROR_UNKNOWN_FS
1559
    ret
1560
 
1561
  file_del_fat_ok:
1562
    pushad
1563
 
1564
    mov   ebx,edx
1565
    call  get_cluster_of_a_path
1566
    jc    file_to_delete_not_found
1567
 
1568
    mov   ebx,PUSHAD_EAX        ; file/directory name
1569
    call  analyze_directory
1570
    jc    file_to_delete_not_found
1571
 
1572
    test  byte [ebx+11],0x10    ; is it directory?
1573
    jz    delete_notdir         ; no. it's file
1574
    cmp   edi,1                 ; allow directory remove
1575
    jnz   delete_no_access      ; no
1576
 
1577
    push  eax                   ; save directory sector
1578
    mov   eax,[ebx+20-2]        ; first cluster of file
1579
    mov   ax,[ebx+26]           ; 0 length files start cluster = 0
1580
    and   eax,[fatMASK]
1581
    xor   ebp,ebp               ; counter for directory deepnes
1582
    call  clear_directory
1583
    pop   eax
1584
    jc    delete_no_access
1585
 
1586
    push  ebx                   ; save directory pointer in buffer
1587
    mov   ebx,buffer
1588
    call  hd_read               ; read directory sector
1589
    pop   ebx
1590
 
1591
  delete_notdir:
1592
    call  delete_entry_name
1593
    mov   eax,ecx               ; first cluster of file
1594
    call  clear_cluster_chain
1595
    popad
1596
    xor   eax,eax
1597
    ret
1598
 
1599
  delete_no_access:
1600
    popad
1601
    mov   eax,ERROR_ACCESS_DENIED
1602
    ret
1603
 
1604
  file_to_delete_not_found:
1605
    popad
1606
    mov   eax,ERROR_FILE_NOT_FOUND
1607
    ret
1608
 
1609
 
1610
clear_cluster_chain:
1611
;-----------------------------------------------------
1612
; input  : eax = first cluster
1613
;-----------------------------------------------------
1614
    push  eax ecx edx
1615
    xor   ecx,ecx               ; cluster count
1616
    mov   [f_del],1             ; delete on
1617
 
1618
  clean_new_chain:
1619
    cmp   eax,[LAST_CLUSTER]    ; end of file
1620
    ja    delete_OK
1621
    cmp   eax,2                 ; unfinished fat chain or zero length file
1622
    jb    delete_OK
1623
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1624
    jz    delete_OK
1625
 
1626
    xor   edx,edx
1627
    call  set_FAT               ; clear fat entry
1628
    inc   ecx                   ; update cluster count
1629
    mov   eax,edx               ; old cluster
1630
    jmp   clean_new_chain
1631
 
1632
  delete_OK:
1633
    call  add_disk_free_space   ; add clusters to free disk space
1634
    mov   [f_del],0
1635
    pop   edx ecx eax
1636
    ret
1637
 
1638
 
1639
clear_directory:
1640
;-----------------------------------------------------
1641
; input  : eax = directory cluster
1642
;          ebp = directory deepnes
1643
; Note   : use recursive call
1644
;-----------------------------------------------------
1645
    pushad
1646
    inc   ebp
1647
    cmp   ebp,64                ; if over 63 directory deep
1648
    jnb   clear_error           ; something must be wrong
1649
 
1650
  clear_new_cluster:
1651
    cmp   eax,[LAST_CLUSTER]
1652
    ja    clear_end
1653
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1654
    jz    clear_end
1655
    mov   esi,eax               ; esi = current directory cluster
1656
    sub   eax,2
1657
    jb    clear_end
1658
    mov   ecx,[SECTORS_PER_CLUSTER]
1659
    imul  eax,ecx
1660
    add   eax,[DATA_START]
1661
 
1662
  clear_new_sector:
1663
    mov   edi,eax               ; edi = current directory sector
1664
    mov   ebx,deltree_buffer
1665
    call  hd_read
1666
    mov   edx,512/32            ; count of dir entrys per sector = 16
1667
 
1668
  clear_analyze:
1669
    mov   al,[ebx+11]           ; file attribute
1670
    and   al,0xf
1671
    cmp   al,0xf
1672
    je    clear_long_filename
1673
 
1674
    cmp   byte [ebx],'.'        ; parent or current directory
1675
    je    clear_next_entry
1676
    cmp   byte [ebx],0xe5       ; deleted
1677
    je    clear_next_entry
1678
    cmp   byte [ebx],0          ; empty
1679
    je    clear_write_last
1680
    ;je    clear_next_entry
1681
 
1682
    mov   eax,[ebx+20-2]        ; first cluster of entry
1683
    mov   ax,[ebx+26]
1684
    and   eax,[fatMASK]
1685
 
1686
    test  byte [ebx+11],0x10    ; is it directory?
1687
    jz    clear_file            ; no
1688
 
1689
    push  eax ebx
1690
    mov   eax,edi
1691
    mov   ebx,deltree_buffer    ; save buffer over recursive call
1692
    call  hd_write              ; write directory sector to disk
1693
    pop   ebx eax
1694
 
1695
    call  clear_directory       ; recursive call !!!
1696
    jc    clear_error           ; exit if error found
1697
 
1698
    push  eax ebx
1699
    mov   eax,edi
1700
    mov   ebx,deltree_buffer
1701
    call  hd_read               ; read directory sector again
1702
    pop   ebx eax
1703
 
1704
  clear_file:
1705
    call  clear_cluster_chain
1706
 
1707
  clear_long_filename:
1708
    mov   byte [ebx],0xe5
1709
 
1710
  clear_next_entry:
1711
    add   ebx,32                ; position of next dir entry
1712
    dec   edx
1713
    jnz   clear_analyze
1714
 
1715
    mov   eax,edi
1716
    mov   ebx,deltree_buffer
1717
    call  hd_write              ; write directory sector to disk
1718
 
1719
    inc   eax                   ; next sector
1720
    dec   ecx
1721
    jnz   clear_new_sector
1722
 
1723
    mov   eax,esi
1724
    call  get_FAT               ; get next cluster
1725
    jmp   clear_new_cluster     ; clear it
1726
 
1727
  clear_write_last:
1728
    mov   eax,edi
1729
    mov   ebx,deltree_buffer
1730
    call  hd_write              ; write directory sector to disk
1731
 
1732
  clear_end:
1733
    popad
1734
    clc
1735
    ret
1736
 
1737
  clear_error:
1738
    popad
1739
    stc
1740
    ret
1741
 
1742
 
1743
delete_entry_name:
1744
;-----------------------------------------------------
1745
; input  : eax = directory sector
1746
;          ebx = directory pointer in buffer
1747
;          longname_sec = 2 previous directory sectors
1748
; output : ecx = first cluster
1749
; change : eax,ebx,edx
1750
;-----------------------------------------------------
1751
    mov   byte [ebx],0xe5
1752
    mov   ecx,[ebx+20-2]        ; first cluster of file
1753
    mov   cx,[ebx+26]           ; 0 length files start cluster = 0
1754
    and   ecx,[fatMASK]
1755
 
1756
  delete_empty:
1757
    sub   ebx,32
1758
    cmp   ebx,buffer
1759
    jnb   delete_test_long
1760
 
1761
    mov   ebx,buffer
1762
    call  hd_write              ; write directory sector back
1763
    xor   eax,eax
1764
    xchg  eax,[longname_sec2]
1765
    xchg  eax,[longname_sec1]
1766
    test  eax,eax               ; is there previous directory sector?
1767
    jz    delete_name_end       ; no
1768
 
1769
    mov   ebx,buffer
1770
    call  hd_read               ; read previous sector
1771
    mov   ebx,buffer+0x1e0      ; start from last entry
1772
 
1773
  delete_test_long:
1774
    mov   dh,[ebx+11]           ; file attribute
1775
    and   dh,0xf
1776
    cmp   dh,0xf
1777
    jne   delete_write_buffer
1778
 
1779
    cmp   byte [ebx],0x40       ; end of long dir entry?
1780
    mov   byte [ebx],0xe5
1781
    jb    delete_empty
1782
 
1783
  delete_write_buffer:
1784
    mov   ebx,buffer
1785
    call  hd_write              ; write directory sector back
1786
 
1787
  delete_name_end:
1788
    ret
1789
 
1790
 
1791
rename:
1792
;-----------------------------------------------------------
1793
; input  : eax = source directory name
1794
;          edx = source path
1795
;          ebx = dest directory name
1796
;          edi = dest path
1797
; output : eax = 0 - ok
1798
;                3 - unknown FS
1799
;                5 - file not found
1800
;                8 - disk full
1801
;               10 - access denied
1802
;-----------------------------------------------------------
1803
    cmp   [fat_type],0
1804
    jnz   fat_ok_for_rename
1805
    mov   eax,ERROR_UNKNOWN_FS
1806
    ret
1807
 
1808
  fat_ok_for_rename:
1809
;    call  reserve_hd1
1810
 
1811
    pushad
1812
 
1813
    mov   ebx,edx               ; source path
1814
    call  get_cluster_of_a_path
1815
    jc    rename_entry_not_found
1816
 
1817
    mov   ebx,PUSHAD_EAX        ; source directory name
1818
    call  analyze_directory
1819
    jc    rename_entry_not_found
1820
 
1821
    mov   [sector_tmp],eax      ; save source sector
1822
    mov   [entry_pos],ebx
1823
    mov   esi,ebx
1824
    mov   edi,dir_entry
1825
    mov   ecx,32/4
1826
    cld
1827
    rep   movsd                 ; save entry
1828
 
1829
    mov   ebx,PUSHAD_EDI        ; dest path
1830
    call  get_cluster_of_a_path
1831
    jc    rename_entry_not_found
1832
 
1833
    mov   edx,eax               ; save dest directory cluster
1834
    mov   ebx,PUSHAD_EBX        ; dest directory name
1835
    push  [longname_sec1]
1836
    push  [longname_sec2]
1837
    call  analyze_directory     ; check if entry already exist
1838
    pop   [longname_sec2]
1839
    pop   [longname_sec1]
1840
    jnc   rename_entry_already_exist
1841
 
1842
    mov   eax,edx
1843
    call  analyze_directory_to_write
1844
    jc    rename_disk_full
1845
 
1846
    mov   esi,dir_entry
1847
    mov   edi,ebx
1848
    mov   ecx,32/4
1849
    cld
1850
    rep   movsd                 ; copy entry
1851
    mov   esi,PUSHAD_EBX        ; dest directory name
1852
    mov   edi,ebx
1853
    mov   ecx,11
1854
    rep   movsb                 ; copy name
1855
 
1856
    mov   ebx,buffer            ; save the directory name,length,cluster
1857
    call  hd_write
1858
 
1859
    test  byte [dir_entry+11],0x10 ; is it directory?
1860
    jz    rename_not_dir           ; no
1861
    mov   eax,[dir_entry+20-2]     ; FAT entry
1862
    mov   ax,[dir_entry+26]
1863
    and   eax,[fatMASK]
1864
    call  change_2dot_cluster
1865
 
1866
  rename_not_dir:
1867
    mov   eax,[sector_tmp]
1868
    mov   ebx,buffer
1869
    call  hd_read               ; read source directory sector
1870
 
1871
    mov   ebx,[entry_pos]
1872
    call  delete_entry_name
1873
 
1874
    popad
1875
    call  update_disk           ; write all of cache and fat to hd
1876
    mov   [hd1_status],0
1877
    xor   eax,eax
1878
    ret
1879
 
1880
  rename_entry_not_found:
1881
    popad
1882
    mov   [hd1_status],0
1883
    mov   eax,ERROR_FILE_NOT_FOUND
1884
    ret
1885
 
1886
  rename_entry_already_exist:
1887
    popad
1888
    mov   [hd1_status],0
1889
    mov   eax,ERROR_ACCESS_DENIED
1890
    ret
1891
 
1892
  rename_disk_full:
1893
    popad
1894
    mov   [hd1_status],0
1895
    mov   eax,ERROR_DISK_FULL
1896
    ret
1897
 
1898
 
1899
change_2dot_cluster:
1900
;-----------------------------------------------------------
1901
; input  : eax = directory cluster
1902
;          edx = value to save
1903
; change : eax,ebx,edx
1904
;-----------------------------------------------------------
1905
    cmp   eax,[LAST_CLUSTER]
1906
    ja    not_2dot              ; too big cluster number, something is wrong
1907
    sub   eax,2
1908
    jb    not_2dot
1909
 
1910
    imul  eax,[SECTORS_PER_CLUSTER]
1911
    add   eax,[DATA_START]
1912
    mov   ebx,buffer
1913
    call  hd_read
1914
 
1915
    cmp   dword [ebx+32],'..  '
1916
    jnz   not_2dot
1917
 
1918
    cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
1919
    jne   not_2dot_root
1920
    xor   edx,edx               ; yes. set it zero
1921
 
1922
  not_2dot_root:
1923
    mov   [ebx+32+26],dx        ; 16 bits low of cluster
1924
    shr   edx,16
1925
    mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
1926
    call  hd_write
1927
 
1928
  not_2dot:
1929
    ret
1930
 
1931
 
1932
get_filesize:
1933
;-----------------------------------------------------------
1934
; input  : eax = file name
1935
;          edx = path
1936
;          edi = if 0 - read rootdir else normal dir/file size
1937
; output : eax = 0 - ok
1938
;                3 - unknown FS
1939
;                5 - file not found
1940
;          ebx = file size
1941
;-----------------------------------------------------------
1942
    cmp   [fat_type],0
1943
    jnz   get_filesize_fat_ok
1944
    xor   ebx,ebx
1945
    mov   eax,ERROR_UNKNOWN_FS
1946
    ret
1947
 
1948
  get_filesize_fat_ok:
1949
;    call  reserve_hd1
1950
 
1951
    pushad
1952
    xor   eax,eax
1953
    test  edi,edi               ; is read rootdir?
1954
    je    get_filesize_dirsize  ; yes
1955
 
1956
  get_filesize_no_root:
1957
    mov   ebx,edx
1958
    call  get_cluster_of_a_path
1959
    jc    get_filesize_not_found
1960
 
1961
    mov   ebx,PUSHAD_EAX        ; file name
1962
    call  analyze_directory
1963
    jc    get_filesize_not_found
1964
 
1965
    mov   eax,[ebx+28]          ; file size
1966
    test  byte [ebx+11],0x10    ; is it directory?
1967
    jz    get_filesize_set_size ; no
1968
 
1969
    mov   eax,[ebx+20-2]        ; FAT entry
1970
    mov   ax,[ebx+26]
1971
    and   eax,[fatMASK]
1972
 
1973
  get_filesize_dirsize:
1974
    call  get_dir_size
1975
 
1976
  get_filesize_set_size:
1977
    mov   PUSHAD_EBX,eax
1978
    popad
1979
    mov   [hd1_status],0
1980
    xor   eax,eax
1981
    ret
1982
 
1983
  get_filesize_not_found:
1984
    popad
1985
    mov   [hd1_status],0
1986
    xor   ebx,ebx
1987
    mov   eax,ERROR_FILE_NOT_FOUND
1988
    ret
1989
 
1990
 
1991
get_fileattr:
1992
;-----------------------------------------------------------
1993
; input  : eax = file name
1994
;          edx = path
1995
; output : eax = 0 - ok
1996
;                3 - unknown FS
1997
;                5 - file not found
1998
;          ebx = file attribute
1999
;-----------------------------------------------------------
2000
    cmp   [fat_type],0
2001
    jnz   get_fileattr_fat_ok
2002
    xor   ebx,ebx
2003
    mov   eax,ERROR_UNKNOWN_FS
2004
    ret
2005
 
2006
  get_fileattr_fat_ok:
2007
;    call  reserve_hd1
2008
 
2009
    pushad
2010
    mov   ebx,edx
2011
    call  get_cluster_of_a_path
2012
    jc    get_fileattr_not_found
2013
 
2014
    mov   ebx,PUSHAD_EAX        ; file name
2015
    call  analyze_directory
2016
    jc    get_fileattr_not_found
2017
 
2018
    movzx eax,byte [ebx+11]     ; file attribute
2019
    mov   PUSHAD_EBX,eax
2020
    popad
2021
    mov   [hd1_status],0
2022
    xor   eax,eax
2023
    ret
2024
 
2025
  get_fileattr_not_found:
2026
    popad
2027
    mov   [hd1_status],0
2028
    xor   ebx,ebx
2029
    mov   eax,ERROR_FILE_NOT_FOUND
2030
    ret
2031
 
2032
 
2033
get_filedate:
2034
;-----------------------------------------------------------
2035
; input  : eax = file name
2036
;          edx = path
2037
; output : eax = 0 - ok
2038
;                3 - unknown FS
2039
;                5 - file not found
2040
;          ebx = file date/time
2041
;                bits 31..25 = year-1980
2042
;                bits 24..21 = month
2043
;                bits 20..16 = day
2044
;                bits 15..11 = hour
2045
;                bits 10..5  = minute
2046
;                bits 4..0   = second/2
2047
;-----------------------------------------------------------
2048
    cmp   [fat_type],0
2049
    jnz   get_filedate_fat_ok
2050
    xor   ebx,ebx
2051
    mov   eax,ERROR_UNKNOWN_FS
2052
    ret
2053
 
2054
  get_filedate_fat_ok:
2055
;    call  reserve_hd1
2056
 
2057
    pushad
2058
    mov   ebx,edx
2059
    call  get_cluster_of_a_path
2060
    jc    get_filedate_not_found
2061
 
2062
    mov   ebx,PUSHAD_EAX        ; file name
2063
    call  analyze_directory
2064
    jc    get_filedate_not_found
2065
 
2066
    mov   eax,[ebx+22]          ; file date/time
2067
    mov   PUSHAD_EBX,eax
2068
    popad
2069
    mov   [hd1_status],0
2070
    xor   eax,eax
2071
    ret
2072
 
2073
  get_filedate_not_found:
2074
    popad
2075
    mov   [hd1_status],0
2076
    xor   ebx,ebx
2077
    mov   eax,ERROR_FILE_NOT_FOUND
2078
    ret
2079
 
2080
 
2081
get_hd_info:
2082
;-----------------------------------------------------------
2083
; output : eax = 0 - ok
2084
;                3 - unknown FS
2085
;          edx = cluster size in bytes
2086
;          ebx = total clusters on disk
2087
;          ecx = free clusters on disk
2088
;-----------------------------------------------------------
2089
    cmp   [fat_type],0
2090
    jnz   info_fat_ok
2091
    xor   edx,edx
2092
    xor   ebx,ebx
2093
    xor   ecx,ecx
2094
    mov   eax,ERROR_UNKNOWN_FS
2095
    ret
2096
 
2097
  info_fat_ok:
2098
;    call  reserve_hd1
2099
 
2100
    xor   ecx,ecx               ; count of free clusters
2101
    mov   eax,2
2102
    mov   ebx,[LAST_CLUSTER]
2103
 
2104
  info_cluster:
2105
    push  eax
2106
    call  get_FAT               ; get cluster info
2107
    test  eax,eax               ; is it free?
2108
    jnz   info_used             ; no
2109
    inc   ecx
2110
 
2111
  info_used:
2112
    pop   eax
2113
    inc   eax
2114
    cmp   eax,ebx               ; is above last cluster?
2115
    jbe   info_cluster          ; no. test next cluster
2116
 
2117
    dec   ebx                   ; cluster count
2118
    imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
2119
    mov   [hd1_status],0
2120
    xor   eax,eax
2121
    ret
2122
 
2123
 
2124
update_disk:
2125
;-----------------------------------------------------------
2126
; write changed fat and cache to disk
2127
;-----------------------------------------------------------
2128
    cmp   [fat_change],0        ; is fat changed?
2129
    je    upd_no_change
2130
 
2131
    call  write_fat_sector
2132
 
2133
  upd_no_change:
2134
 
2135
    call  write_cache
2136
    ret
2137
 
2138
 
2139
;**************************************************************************
2140
;
2141
;   0x600008  - first entry in cache list
2142
;
2143
;            +0   - lba sector
2144
;            +4   - state of cache sector
2145
;                   0 = empty
2146
;                   1 = used for read  ( same as in hd )
2147
;                   2 = used for write ( differs from hd )
2148
;
2149
;      +65536 - cache entries
2150
;
2151
;**************************************************************************
2152
 
2153
 
2154
hd_read:
2155
;-----------------------------------------------------------
2156
; input  : eax = block to read
2157
;          ebx = destination
2158
;-----------------------------------------------------------
2159
    push  ecx esi edi           ; scan cache
2160
 
2161
    mov   ecx,cache_max         ; entries in cache
2162
    mov   esi,0x600000+8
2163
    mov   edi,1
2164
 
2165
  hdreadcache:
2166
 
2167
    cmp   dword [esi+4],0       ; empty
2168
    je    nohdcache
2169
 
2170
    cmp   [esi],eax             ; correct sector
2171
    je    yeshdcache
2172
 
2173
  nohdcache:
2174
 
2175
    add   esi,8
2176
    inc   edi
2177
    dec   ecx
2178
    jnz   hdreadcache
2179
 
2180
    call  find_empty_slot       ; ret in edi
2181
 
2182
    call  wait_for_hd_idle
2183
    push  eax edx
2184
 
2185
    cli
2186
    xor   eax,eax
2187
    mov   edx,[hdbase]
2188
    inc   edx
2189
    out   dx,al   ; ATAFeatures ðåãèñòð "îñîáåííîñòåé"
2190
    inc   edx
2191
    inc   eax
2192
    out   dx,al   ; ATASectorCount ñ÷åò÷èê ñåêòîðîâ
2193
    inc   edx
2194
    mov   eax,[esp+4]
2195
    out   dx,al   ; ATASectorNumber ðåãèñòð íîìåðà ñåêòîðà
2196
    shr   eax,8
2197
    inc   edx
2198
    out   dx,al   ; ATACylinder íîìåð öèëèíäðà (ìëàäøèé áàéò)
2199
    shr   eax,8
2200
    inc   edx
2201
    out   dx,al   ; íîìåð öèëèíäðà (ñòàðøèé áàéò)
2202
    shr   eax,8
2203
    inc   edx
2204
    and   al,1+2+4+8
2205
    add   al,byte [hdid]
2206
    add   al,128+64+32
2207
    out   dx,al   ; íîìåð ãîëîâêè/íîìåð äèñêà
2208
    inc   edx
2209
    mov   al,20h
2210
    out   dx,al   ; ATACommand ðåãèñòð êîìàíä
2211
    sti
2212
 
2213
    call  wait_for_sector_buffer
2214
 
2215
    cmp   [hd_error],0
2216
    jne   hd_read_error
2217
 
2218
    cli
2219
    push  edi
2220
    shl   edi,9
2221
    add   edi,0x600000+65536
2222
    mov   ecx,256
2223
    mov   edx,[hdbase]
2224
    cld
2225
    rep   insw
2226
    pop   edi
2227
    sti
2228
 
2229
    pop   edx eax
2230
 blok_read_2:
2231
    lea   esi,[edi*8+0x600000]
2232
    mov   [esi],eax             ; sector number
2233
    mov   dword [esi+4],1       ; hd read - mark as same as in hd
2234
 
2235
  yeshdcache:
2236
 
2237
    mov   esi,edi
2238
    shl   esi,9
2239
    add   esi,0x600000+65536
2240
    mov   edi,ebx
2241
    mov   ecx,512/4
2242
    cld
2243
    rep   movsd                 ; move data
2244
; blok_read_2:
2245
    pop   edi esi ecx
2246
    ret
2247
 
2248
 
2249
hd_write:
2250
;-----------------------------------------------------------
2251
; input  : eax = block
2252
;          ebx = pointer to memory
2253
;-----------------------------------------------------------
2254
    push  ecx esi edi
2255
 
2256
    ; check if the cache already has the sector and overwrite it
2257
 
2258
    mov   ecx,cache_max
2259
    mov   esi,0x600000+8
2260
    mov   edi,1
2261
 
2262
  hdwritecache:
2263
 
2264
    cmp   dword [esi+4],0       ; if cache slot is empty
2265
    je    not_in_cache_write
2266
 
2267
    cmp   [esi],eax             ; if the slot has the sector
2268
    je    yes_in_cache_write
2269
 
2270
  not_in_cache_write:
2271
 
2272
    add   esi,8
2273
    inc   edi
2274
    dec   ecx
2275
    jnz   hdwritecache
2276
 
2277
    ; sector not found in cache
2278
    ; write the block to a new location
2279
 
2280
    call  find_empty_slot       ; ret in edi
2281
 
2282
    lea   esi,[edi*8+0x600000]
2283
    mov   [esi],eax             ; sector number
2284
 
2285
  yes_in_cache_write:
2286
 
2287
    mov   dword [esi+4],2       ; write - differs from hd
2288
 
2289
    shl   edi,9
2290
    add   edi,0x600000+65536
2291
    mov   esi,ebx
2292
    mov   ecx,512/4
2293
    cld
2294
    rep   movsd                 ; move data
2295
 
2296
    pop   edi esi ecx
2297
    ret
2298
 
2299
 
2300
write_cache:
2301
;-----------------------------------------------------------
2302
; write all changed sectors to disk
2303
;-----------------------------------------------------------
2304
    push  eax ecx edx esi edi
2305
 
2306
    ; write difference ( 2 ) from cache to hd
2307
 
2308
    mov   ecx,cache_max
2309
    mov   esi,0x600000+8
2310
    mov   edi,1
2311
 
2312
  write_cache_more:
2313
 
2314
    cmp   dword [esi+4],2       ; if cache slot is not different
2315
    jne   does_not_need_writing
2316
 
2317
    mov   dword [esi+4],1       ; same as in hd
2318
    mov   eax,[esi]             ; eax = sector to write
2319
 
2320
    cmp   eax,[PARTITION_START]
2321
    jb    danger
2322
    cmp   eax,[PARTITION_END]
2323
    ja    danger
2324
 
2325
    call  wait_for_hd_idle
2326
 
2327
    cli
2328
    xor   eax,eax
2329
    mov   edx,[hdbase]
2330
    inc   edx
2331
    out   dx,al
2332
    inc   edx
2333
    inc   eax
2334
    out   dx,al
2335
    inc   edx
2336
    mov   eax,[esi]             ; eax = sector to write
2337
    out   dx,al
2338
    shr   eax,8
2339
    inc   edx
2340
    out   dx,al
2341
    shr   eax,8
2342
    inc   edx
2343
    out   dx,al
2344
    shr   eax,8
2345
    inc   edx
2346
    and   al,1+2+4+8
2347
    add   al,byte [hdid]
2348
    add   al,128+64+32
2349
    out   dx,al
2350
    inc   edx
2351
    mov   al,30h
2352
    out   dx,al
2353
    sti
2354
 
2355
    call  wait_for_sector_buffer
2356
 
2357
    cmp   [hd_error],0
2358
    jne   hd_write_error
2359
 
2360
    push  ecx esi
2361
 
2362
    cli
2363
    mov   esi,edi
2364
    shl   esi,9
2365
    add   esi,0x600000+65536    ; esi = from memory position
2366
    mov   ecx,256
2367
    mov   edx,[hdbase]
2368
    cld
2369
    rep   outsw
2370
    sti
2371
 
2372
    pop   esi ecx
2373
 
2374
  danger:
2375
  does_not_need_writing:
2376
 
2377
    add   esi,8
2378
    inc   edi
2379
    dec   ecx
2380
    jnz   write_cache_more
2381
 
2382
    pop   edi esi edx ecx eax
2383
    ret
2384
 
2385
 
2386
find_empty_slot:
2387
;-----------------------------------------------------------
2388
; find empty or read slot, flush cache if next 10% is used by write
2389
; output : edi = cache slot
2390
;-----------------------------------------------------------
2391
    push  ecx esi
2392
 
2393
  search_again:
2394
 
2395
    mov   ecx,cache_max*10/100
2396
    mov   edi,[cache_search_start]
2397
 
2398
  search_for_empty:
2399
 
2400
    inc   edi
2401
    cmp   edi,cache_max
2402
    jbe   inside_cache
2403
    mov   edi,1
2404
 
2405
  inside_cache:
2406
 
2407
    cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
2408
    jb    found_slot                    ; it's empty or read
2409
    dec   ecx
2410
    jnz   search_for_empty
2411
 
2412
    call  write_cache                   ; no empty slots found, write all
2413
    jmp   search_again                  ; and start again
2414
 
2415
  found_slot:
2416
 
2417
    mov   [cache_search_start],edi
2418
 
2419
    pop   esi ecx
2420
    ret
2421
 
2422
 
2423
save_hd_wait_timeout:
2424
 
2425
    push  eax
2426
    mov   eax,[timer_ticks];[0xfdf0]
2427
    add   eax,300               ; 3 sec timeout
2428
    mov   [hd_wait_timeout],eax
2429
    pop   eax
2430
    ret
2431
 
2432
 
2433
check_hd_wait_timeout:
2434
 
2435
    push  eax
2436
    mov   eax,[hd_wait_timeout]
2437
    cmp   [timer_ticks], eax ;[0xfdf0],eax
2438
    jg    hd_timeout_error
2439
    pop   eax
2440
    ret
2441
 
2442
iglobal
2443
  hd_timeout_str   db 'K : FS - HD timeout',13,10,0
2444
  hd_read_str      db 'K : FS - HD read error',13,10,0
2445
  hd_write_str     db 'K : FS - HD write error',13,10,0
2446
endg
2447
 
2448
hd_timeout_error:
2449
 
2450
    call  clear_hd_cache
2451
    call  clear_application_table_status
2452
    mov   esi,hd_timeout_str
2453
    call  sys_msg_board_str
2454
    jmp   $
2455
 
2456
 
2457
hd_read_error:
2458
 
2459
    call  clear_hd_cache
2460
    call  clear_application_table_status
2461
    mov   esi,hd_read_str
2462
    call  sys_msg_board_str
2463
    jmp   $
2464
 
2465
hd_write_error:
2466
 
2467
    call  clear_hd_cache
2468
    call  clear_application_table_status
2469
    mov   esi,hd_write_str
2470
    call  sys_msg_board_str
2471
    jmp   $
2472
 
2473
 
2474
 
2475
 
2476
wait_for_hd_idle:
2477
 
2478
    push  eax edx
2479
 
2480
    call  save_hd_wait_timeout
2481
 
2482
    mov   edx,[hdbase]
2483
    add   edx,0x7
2484
 
2485
  wfhil1:
2486
 
2487
    call  check_hd_wait_timeout
2488
 
2489
    in    al,dx
2490
    test  al,128
2491
    jnz   wfhil1
2492
 
2493
    pop   edx eax
2494
    ret
2495
 
2496
 
2497
wait_for_sector_buffer:
2498
 
2499
    push  eax edx
2500
 
2501
    mov   edx,[hdbase]
2502
    add   edx,0x7
2503
 
2504
    call  save_hd_wait_timeout
2505
 
2506
  hdwait_sbuf:                  ; wait for sector buffer to be ready
2507
 
2508
    call  check_hd_wait_timeout
2509
 
2510
    in    al,dx
2511
    test  al,8
2512
    jz    hdwait_sbuf
2513
 
2514
    mov   [hd_error],0
2515
 
2516
    cmp   [hd_setup],1          ; do not mark error for setup request
2517
    je    buf_wait_ok
2518
 
2519
    test  al,1                  ; previous command ended up with an error
2520
    jz    buf_wait_ok
2521
    mov   [hd_error],1
2522
 
2523
  buf_wait_ok:
2524
 
2525
    pop   edx eax
2526
    ret
2527
 
2528
 
2529
 
2530
read_hd_file:
2531
;-----------------------------------------------------------------
2532
;
2533
; Converting old reading function for hd-application start.
2534
;
2535
; IN:
2536
;
2537
; eax - pointer to file (0 = read only first sector of drive: eg 'label')
2538
; ebx - file lenght
2539
; ecx - start 512 byte block number
2540
; edx - number of blocks to read
2541
; esi - pointer to return/work area (atleast 20 000 bytes)
2542
;
2543
; For new read function
2544
;
2545
; EAX   (PAR0)      pointer to file-name
2546
; ECX   (PAR1)      pointer to buffer
2547
; EBX   (PAR2)   vt file blocks to read
2548
; EDX   (PAR3)      pointer to path
2549
; ESI            vt first 512 block to read
2550
; EDI               if 0 - return root
2551
;--------------------------------------------------------------------------
2552
 
2553
    push  ecx esi edi
2554
    mov   esi,eax
2555
    mov   edi,startpath
2556
    mov   ecx,250
2557
    cld
2558
    rep   movsb
2559
    pop   edi esi ecx
2560
 
2561
    mov   eax,startpath
2562
    mov   [eax+ebx-12],byte 0
2563
 
2564
    push  eax ebx ecx edx esi
2565
 
2566
    pop   ecx ; pointer to buffer
2567
    add   ecx,1024
2568
    pop   ebx ; number of blocks to read
2569
    pop   esi ; first block to read
2570
    dec   esi
2571
    pop   eax ; file length
2572
    pop   edx ; pointer to path
2573
 
2574
    mov   edi,12
2575
    lea   eax,[eax+edx-12+1]
2576
    call  file_read
2577
 
2578
    ret
2579