Subversion Repositories Kolibri OS

Rev

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