Subversion Repositories Kolibri OS

Rev

Rev 129 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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