Subversion Repositories Kolibri OS

Rev

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

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