Subversion Repositories Kolibri OS

Rev

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