Subversion Repositories Kolibri OS

Rev

Rev 71 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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