Subversion Repositories Kolibri OS

Rev

Rev 2 | 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.     ret
  1675.  
  1676.   fat_ok_for_reading:
  1677. ;    call  reserve_hd1
  1678.  
  1679.     pushad
  1680.  
  1681.     mov   ebx,edx
  1682.     call  get_cluster_of_a_path
  1683.     jc    file_to_read_not_found
  1684.  
  1685.     test  edi,edi               ; read rootdir
  1686.     jne   no_read_root
  1687.  
  1688.     xor   eax,eax
  1689.     call  get_dir_size          ; return rootdir size
  1690.     mov   [file_size],eax
  1691.     mov   eax,[ROOT_CLUSTER]
  1692.     jmp   file_read_start
  1693.  
  1694.   no_read_root:
  1695.     mov   ebx,PUSHAD_EAX        ; file name
  1696.     call  analyze_directory
  1697.     jc    file_to_read_not_found
  1698.  
  1699.     mov   eax,[ebx+28]          ; file size
  1700.     test  byte [ebx+11],0x10    ; is it directory?
  1701.     jz    read_set_size         ; no
  1702.  
  1703.     mov   eax,[ebx+20-2]        ; FAT entry
  1704.     mov   ax,[ebx+26]
  1705.     and   eax,[fatMASK]
  1706.     call  get_dir_size
  1707.  
  1708.   read_set_size:
  1709.     mov   [file_size],eax
  1710.  
  1711.     mov   eax,[ebx+20-2]        ; FAT entry
  1712.     mov   ax,[ebx+26]
  1713.     and   eax,[fatMASK]
  1714.  
  1715.   file_read_start:
  1716.     mov   ebx,PUSHAD_ECX        ; pointer to buffer
  1717.     mov   edx,PUSHAD_EBX        ; file blocks to read
  1718.     mov   esi,PUSHAD_ESI        ; first 512 block to read
  1719.  
  1720.   file_read_new_cluster:
  1721.     call  get_data_cluster
  1722.     jc    file_read_eof         ; end of file or cluster out of range
  1723.  
  1724.     test  edx,edx               ; is all read?
  1725.     je    file_read_OK          ; yes
  1726.  
  1727.     call  get_FAT               ; get next cluster
  1728.     cmp   eax,[fatRESERVED]     ; end of file
  1729.     jnb   file_read_eof
  1730.     cmp   eax,2                 ; incorrect fat chain
  1731.     jnb   file_read_new_cluster
  1732.  
  1733.     popad
  1734.     mov   [hd1_status],0
  1735.     mov   ebx,[file_size]
  1736.     mov   eax,ERROR_FAT_TABLE
  1737.     ret
  1738.  
  1739.   file_read_eof:
  1740.     popad
  1741.     mov   [hd1_status],0
  1742.     mov   ebx,[file_size]
  1743.     mov   eax,ERROR_END_OF_FILE
  1744.     ret
  1745.  
  1746.   file_read_OK:
  1747.     popad
  1748.     mov   [hd1_status],0
  1749.     mov   ebx,[file_size]
  1750.     xor   eax,eax
  1751.     ret
  1752.  
  1753.   file_to_read_not_found:
  1754.     popad
  1755.     mov   [hd1_status],0
  1756.     xor   ebx,ebx
  1757.     mov   eax,ERROR_FILE_NOT_FOUND
  1758.     ret
  1759.  
  1760.  
  1761. get_dir_size:
  1762. ;-----------------------------------------------------
  1763. ; input  : eax = first cluster (0=rootdir)
  1764. ; output : eax = directory size in bytes
  1765. ;-----------------------------------------------------
  1766.     push  edx
  1767.     xor   edx,edx               ; count of directory clusters
  1768.     test  eax,eax
  1769.     jnz   dir_size_next
  1770.  
  1771.     mov   eax,[ROOT_SECTORS]
  1772.     shl   eax,9                 ; fat16 rootdir size in bytes
  1773.     cmp   [fat_type],16
  1774.     je    dir_size_ret
  1775.     mov   eax,[ROOT_CLUSTER]
  1776.  
  1777.   dir_size_next:
  1778.     cmp   eax,2                 ; incorrect fat chain
  1779.     jb    dir_size_end
  1780.     cmp   eax,[fatRESERVED]     ; end of directory
  1781.     ja    dir_size_end
  1782.     call  get_FAT               ; get next cluster
  1783.     inc   edx
  1784.     jmp   dir_size_next
  1785.  
  1786.   dir_size_end:
  1787.     imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  1788.     imul  eax,edx
  1789.  
  1790.   dir_size_ret:
  1791.     pop   edx
  1792.     ret
  1793.  
  1794.  
  1795. file_delete:
  1796. ;-----------------------------------------------------
  1797. ; input  : eax = file/directory name
  1798. ;          edx = path
  1799. ;          edi = 1 - allow directory remove else don't remove directory
  1800. ; output : eax = 0 - ok
  1801. ;                3 - unknown FS
  1802. ;                5 - file not found
  1803. ;               10 - access denied
  1804. ;-----------------------------------------------------
  1805.     cmp   [fat_type],0
  1806.     jnz   file_del_fat_ok
  1807.     mov   eax,ERROR_UNKNOWN_FS
  1808.     ret
  1809.  
  1810.   file_del_fat_ok:
  1811.     pushad
  1812.  
  1813.     mov   ebx,edx
  1814.     call  get_cluster_of_a_path
  1815.     jc    file_to_delete_not_found
  1816.  
  1817.     mov   ebx,PUSHAD_EAX        ; file/directory name
  1818.     call  analyze_directory
  1819.     jc    file_to_delete_not_found
  1820.  
  1821.     test  byte [ebx+11],0x10    ; is it directory?
  1822.     jz    delete_notdir         ; no. it's file
  1823.     cmp   edi,1                 ; allow directory remove
  1824.     jnz   delete_no_access      ; no
  1825.  
  1826.     push  eax                   ; save directory sector
  1827.     mov   eax,[ebx+20-2]        ; first cluster of file
  1828.     mov   ax,[ebx+26]           ; 0 length files start cluster = 0
  1829.     and   eax,[fatMASK]
  1830.     xor   ebp,ebp               ; counter for directory deepnes
  1831.     call  clear_directory
  1832.     pop   eax
  1833.     jc    delete_no_access
  1834.  
  1835.     push  ebx                   ; save directory pointer in buffer
  1836.     mov   ebx,buffer
  1837.     call  hd_read               ; read directory sector
  1838.     pop   ebx
  1839.  
  1840.   delete_notdir:
  1841.     call  delete_entry_name
  1842.     mov   eax,ecx               ; first cluster of file
  1843.     call  clear_cluster_chain
  1844.     popad
  1845.     xor   eax,eax
  1846.     ret
  1847.  
  1848.   delete_no_access:
  1849.     popad
  1850.     mov   eax,ERROR_ACCESS_DENIED
  1851.     ret
  1852.  
  1853.   file_to_delete_not_found:
  1854.     popad
  1855.     mov   eax,ERROR_FILE_NOT_FOUND
  1856.     ret
  1857.  
  1858.  
  1859. clear_cluster_chain:
  1860. ;-----------------------------------------------------
  1861. ; input  : eax = first cluster
  1862. ;-----------------------------------------------------
  1863.     push  eax ecx edx
  1864.     xor   ecx,ecx               ; cluster count
  1865.     mov   [f_del],1             ; delete on
  1866.  
  1867.   clean_new_chain:
  1868.     cmp   eax,[LAST_CLUSTER]    ; end of file
  1869.     ja    delete_OK
  1870.     cmp   eax,2                 ; unfinished fat chain or zero length file
  1871.     jb    delete_OK
  1872.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1873.     jz    delete_OK
  1874.  
  1875.     xor   edx,edx
  1876.     call  set_FAT               ; clear fat entry
  1877.     inc   ecx                   ; update cluster count
  1878.     mov   eax,edx               ; old cluster
  1879.     jmp   clean_new_chain
  1880.  
  1881.   delete_OK:
  1882.     call  add_disk_free_space   ; add clusters to free disk space
  1883.     mov   [f_del],0
  1884.     pop   edx ecx eax
  1885.     ret
  1886.  
  1887.  
  1888. clear_directory:
  1889. ;-----------------------------------------------------
  1890. ; input  : eax = directory cluster
  1891. ;          ebp = directory deepnes
  1892. ; Note   : use recursive call
  1893. ;-----------------------------------------------------
  1894.     pushad
  1895.     inc   ebp
  1896.     cmp   ebp,64                ; if over 63 directory deep
  1897.     jnb   clear_error           ; something must be wrong
  1898.  
  1899.   clear_new_cluster:
  1900.     cmp   eax,[LAST_CLUSTER]
  1901.     ja    clear_end
  1902.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1903.     jz    clear_end
  1904.     mov   esi,eax               ; esi = current directory cluster
  1905.     sub   eax,2
  1906.     jb    clear_end
  1907.     mov   ecx,[SECTORS_PER_CLUSTER]
  1908.     imul  eax,ecx
  1909.     add   eax,[DATA_START]
  1910.  
  1911.   clear_new_sector:
  1912.     mov   edi,eax               ; edi = current directory sector
  1913.     mov   ebx,deltree_buffer
  1914.     call  hd_read
  1915.     mov   edx,512/32            ; count of dir entrys per sector = 16
  1916.  
  1917.   clear_analyze:
  1918.     mov   al,[ebx+11]           ; file attribute
  1919.     and   al,0xf
  1920.     cmp   al,0xf
  1921.     je    clear_long_filename
  1922.  
  1923.     cmp   byte [ebx],'.'        ; parent or current directory
  1924.     je    clear_next_entry
  1925.     cmp   byte [ebx],0xe5       ; deleted
  1926.     je    clear_next_entry
  1927.     cmp   byte [ebx],0          ; empty
  1928.     je    clear_write_last
  1929.     ;je    clear_next_entry
  1930.  
  1931.     mov   eax,[ebx+20-2]        ; first cluster of entry
  1932.     mov   ax,[ebx+26]
  1933.     and   eax,[fatMASK]
  1934.  
  1935.     test  byte [ebx+11],0x10    ; is it directory?
  1936.     jz    clear_file            ; no
  1937.  
  1938.     push  eax ebx
  1939.     mov   eax,edi
  1940.     mov   ebx,deltree_buffer    ; save buffer over recursive call
  1941.     call  hd_write              ; write directory sector to disk
  1942.     pop   ebx eax
  1943.  
  1944.     call  clear_directory       ; recursive call !!!
  1945.     jc    clear_error           ; exit if error found
  1946.  
  1947.     push  eax ebx
  1948.     mov   eax,edi
  1949.     mov   ebx,deltree_buffer
  1950.     call  hd_read               ; read directory sector again
  1951.     pop   ebx eax
  1952.  
  1953.   clear_file:
  1954.     call  clear_cluster_chain
  1955.  
  1956.   clear_long_filename:
  1957.     mov   byte [ebx],0xe5
  1958.  
  1959.   clear_next_entry:
  1960.     add   ebx,32                ; position of next dir entry
  1961.     dec   edx
  1962.     jnz   clear_analyze
  1963.  
  1964.     mov   eax,edi
  1965.     mov   ebx,deltree_buffer
  1966.     call  hd_write              ; write directory sector to disk
  1967.  
  1968.     inc   eax                   ; next sector
  1969.     dec   ecx
  1970.     jnz   clear_new_sector
  1971.  
  1972.     mov   eax,esi
  1973.     call  get_FAT               ; get next cluster
  1974.     jmp   clear_new_cluster     ; clear it
  1975.  
  1976.   clear_write_last:
  1977.     mov   eax,edi
  1978.     mov   ebx,deltree_buffer
  1979.     call  hd_write              ; write directory sector to disk
  1980.  
  1981.   clear_end:
  1982.     popad
  1983.     clc
  1984.     ret
  1985.  
  1986.   clear_error:
  1987.     popad
  1988.     stc
  1989.     ret
  1990.  
  1991.  
  1992. delete_entry_name:
  1993. ;-----------------------------------------------------
  1994. ; input  : eax = directory sector
  1995. ;          ebx = directory pointer in buffer
  1996. ;          longname_sec = 2 previous directory sectors
  1997. ; output : ecx = first cluster
  1998. ; change : eax,ebx,edx
  1999. ;-----------------------------------------------------
  2000.     mov   byte [ebx],0xe5
  2001.     mov   ecx,[ebx+20-2]        ; first cluster of file
  2002.     mov   cx,[ebx+26]           ; 0 length files start cluster = 0
  2003.     and   ecx,[fatMASK]
  2004.  
  2005.   delete_empty:
  2006.     sub   ebx,32
  2007.     cmp   ebx,buffer
  2008.     jnb   delete_test_long
  2009.  
  2010.     mov   ebx,buffer
  2011.     call  hd_write              ; write directory sector back
  2012.     xor   eax,eax
  2013.     xchg  eax,[longname_sec2]
  2014.     xchg  eax,[longname_sec1]
  2015.     test  eax,eax               ; is there previous directory sector?
  2016.     jz    delete_name_end       ; no
  2017.  
  2018.     mov   ebx,buffer
  2019.     call  hd_read               ; read previous sector
  2020.     mov   ebx,buffer+0x1e0      ; start from last entry
  2021.  
  2022.   delete_test_long:
  2023.     mov   dh,[ebx+11]           ; file attribute
  2024.     and   dh,0xf
  2025.     cmp   dh,0xf
  2026.     jne   delete_write_buffer
  2027.  
  2028.     cmp   byte [ebx],0x40       ; end of long dir entry?
  2029.     mov   byte [ebx],0xe5
  2030.     jb    delete_empty
  2031.  
  2032.   delete_write_buffer:
  2033.     mov   ebx,buffer
  2034.     call  hd_write              ; write directory sector back
  2035.  
  2036.   delete_name_end:
  2037.     ret
  2038.  
  2039.  
  2040. rename:
  2041. ;-----------------------------------------------------------
  2042. ; input  : eax = source directory name
  2043. ;          edx = source path
  2044. ;          ebx = dest directory name
  2045. ;          edi = dest path
  2046. ; output : eax = 0 - ok
  2047. ;                3 - unknown FS
  2048. ;                5 - file not found
  2049. ;                8 - disk full
  2050. ;               10 - access denied
  2051. ;-----------------------------------------------------------
  2052.     cmp   [fat_type],0
  2053.     jnz   fat_ok_for_rename
  2054.     mov   eax,ERROR_UNKNOWN_FS
  2055.     ret
  2056.  
  2057.   fat_ok_for_rename:
  2058. ;    call  reserve_hd1
  2059.  
  2060.     pushad
  2061.  
  2062.     mov   ebx,edx               ; source path
  2063.     call  get_cluster_of_a_path
  2064.     jc    rename_entry_not_found
  2065.  
  2066.     mov   ebx,PUSHAD_EAX        ; source directory name
  2067.     call  analyze_directory
  2068.     jc    rename_entry_not_found
  2069.  
  2070.     mov   [sector_tmp],eax      ; save source sector
  2071.     mov   [entry_pos],ebx
  2072.     mov   esi,ebx
  2073.     mov   edi,dir_entry
  2074.     mov   ecx,32/4
  2075.     cld
  2076.     rep   movsd                 ; save entry
  2077.  
  2078.     mov   ebx,PUSHAD_EDI        ; dest path
  2079.     call  get_cluster_of_a_path
  2080.     jc    rename_entry_not_found
  2081.  
  2082.     mov   edx,eax               ; save dest directory cluster
  2083.     mov   ebx,PUSHAD_EBX        ; dest directory name
  2084.     push  [longname_sec1]
  2085.     push  [longname_sec2]
  2086.     call  analyze_directory     ; check if entry already exist
  2087.     pop   [longname_sec2]
  2088.     pop   [longname_sec1]
  2089.     jnc   rename_entry_already_exist
  2090.  
  2091.     mov   eax,edx
  2092.     call  analyze_directory_to_write
  2093.     jc    rename_disk_full
  2094.  
  2095.     mov   esi,dir_entry
  2096.     mov   edi,ebx
  2097.     mov   ecx,32/4
  2098.     cld
  2099.     rep   movsd                 ; copy entry
  2100.     mov   esi,PUSHAD_EBX        ; dest directory name
  2101.     mov   edi,ebx
  2102.     mov   ecx,11
  2103.     rep   movsb                 ; copy name
  2104.  
  2105.     mov   ebx,buffer            ; save the directory name,length,cluster
  2106.     call  hd_write
  2107.  
  2108.     test  byte [dir_entry+11],0x10 ; is it directory?
  2109.     jz    rename_not_dir           ; no
  2110.     mov   eax,[dir_entry+20-2]     ; FAT entry
  2111.     mov   ax,[dir_entry+26]
  2112.     and   eax,[fatMASK]
  2113.     call  change_2dot_cluster
  2114.  
  2115.   rename_not_dir:
  2116.     mov   eax,[sector_tmp]
  2117.     mov   ebx,buffer
  2118.     call  hd_read               ; read source directory sector
  2119.  
  2120.     mov   ebx,[entry_pos]
  2121.     call  delete_entry_name
  2122.  
  2123.     popad
  2124.     call  update_disk           ; write all of cache and fat to hd
  2125.     mov   [hd1_status],0
  2126.     xor   eax,eax
  2127.     ret
  2128.  
  2129.   rename_entry_not_found:
  2130.     popad
  2131.     mov   [hd1_status],0
  2132.     mov   eax,ERROR_FILE_NOT_FOUND
  2133.     ret
  2134.  
  2135.   rename_entry_already_exist:
  2136.     popad
  2137.     mov   [hd1_status],0
  2138.     mov   eax,ERROR_ACCESS_DENIED
  2139.     ret
  2140.  
  2141.   rename_disk_full:
  2142.     popad
  2143.     mov   [hd1_status],0
  2144.     mov   eax,ERROR_DISK_FULL
  2145.     ret
  2146.  
  2147.  
  2148. change_2dot_cluster:
  2149. ;-----------------------------------------------------------
  2150. ; input  : eax = directory cluster
  2151. ;          edx = value to save
  2152. ; change : eax,ebx,edx
  2153. ;-----------------------------------------------------------
  2154.     cmp   eax,[LAST_CLUSTER]
  2155.     ja    not_2dot              ; too big cluster number, something is wrong
  2156.     sub   eax,2
  2157.     jb    not_2dot
  2158.  
  2159.     imul  eax,[SECTORS_PER_CLUSTER]
  2160.     add   eax,[DATA_START]
  2161.     mov   ebx,buffer
  2162.     call  hd_read
  2163.  
  2164.     cmp   dword [ebx+32],'..  '
  2165.     jnz   not_2dot
  2166.  
  2167.     cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
  2168.     jne   not_2dot_root
  2169.     xor   edx,edx               ; yes. set it zero
  2170.  
  2171.   not_2dot_root:
  2172.     mov   [ebx+32+26],dx        ; 16 bits low of cluster
  2173.     shr   edx,16
  2174.     mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
  2175.     call  hd_write
  2176.  
  2177.   not_2dot:
  2178.     ret
  2179.  
  2180.  
  2181. get_filesize:
  2182. ;-----------------------------------------------------------
  2183. ; input  : eax = file name
  2184. ;          edx = path
  2185. ;          edi = if 0 - read rootdir else normal dir/file size
  2186. ; output : eax = 0 - ok
  2187. ;                3 - unknown FS
  2188. ;                5 - file not found
  2189. ;          ebx = file size
  2190. ;-----------------------------------------------------------
  2191.     cmp   [fat_type],0
  2192.     jnz   get_filesize_fat_ok
  2193.     xor   ebx,ebx
  2194.     mov   eax,ERROR_UNKNOWN_FS
  2195.     ret
  2196.  
  2197.   get_filesize_fat_ok:
  2198. ;    call  reserve_hd1
  2199.  
  2200.     pushad
  2201.     xor   eax,eax
  2202.     test  edi,edi               ; is read rootdir?
  2203.     je    get_filesize_dirsize  ; yes
  2204.  
  2205.   get_filesize_no_root:
  2206.     mov   ebx,edx
  2207.     call  get_cluster_of_a_path
  2208.     jc    get_filesize_not_found
  2209.  
  2210.     mov   ebx,PUSHAD_EAX        ; file name
  2211.     call  analyze_directory
  2212.     jc    get_filesize_not_found
  2213.  
  2214.     mov   eax,[ebx+28]          ; file size
  2215.     test  byte [ebx+11],0x10    ; is it directory?
  2216.     jz    get_filesize_set_size ; no
  2217.  
  2218.     mov   eax,[ebx+20-2]        ; FAT entry
  2219.     mov   ax,[ebx+26]
  2220.     and   eax,[fatMASK]
  2221.  
  2222.   get_filesize_dirsize:
  2223.     call  get_dir_size
  2224.  
  2225.   get_filesize_set_size:
  2226.     mov   PUSHAD_EBX,eax
  2227.     popad
  2228.     mov   [hd1_status],0
  2229.     xor   eax,eax
  2230.     ret
  2231.  
  2232.   get_filesize_not_found:
  2233.     popad
  2234.     mov   [hd1_status],0
  2235.     xor   ebx,ebx
  2236.     mov   eax,ERROR_FILE_NOT_FOUND
  2237.     ret
  2238.  
  2239.  
  2240. get_fileattr:
  2241. ;-----------------------------------------------------------
  2242. ; input  : eax = file name
  2243. ;          edx = path
  2244. ; output : eax = 0 - ok
  2245. ;                3 - unknown FS
  2246. ;                5 - file not found
  2247. ;          ebx = file attribute
  2248. ;-----------------------------------------------------------
  2249.     cmp   [fat_type],0
  2250.     jnz   get_fileattr_fat_ok
  2251.     xor   ebx,ebx
  2252.     mov   eax,ERROR_UNKNOWN_FS
  2253.     ret
  2254.  
  2255.   get_fileattr_fat_ok:
  2256. ;    call  reserve_hd1
  2257.  
  2258.     pushad
  2259.     mov   ebx,edx
  2260.     call  get_cluster_of_a_path
  2261.     jc    get_fileattr_not_found
  2262.  
  2263.     mov   ebx,PUSHAD_EAX        ; file name
  2264.     call  analyze_directory
  2265.     jc    get_fileattr_not_found
  2266.  
  2267.     movzx eax,byte [ebx+11]     ; file attribute
  2268.     mov   PUSHAD_EBX,eax
  2269.     popad
  2270.     mov   [hd1_status],0
  2271.     xor   eax,eax
  2272.     ret
  2273.  
  2274.   get_fileattr_not_found:
  2275.     popad
  2276.     mov   [hd1_status],0
  2277.     xor   ebx,ebx
  2278.     mov   eax,ERROR_FILE_NOT_FOUND
  2279.     ret
  2280.  
  2281.  
  2282. get_filedate:
  2283. ;-----------------------------------------------------------
  2284. ; input  : eax = file name
  2285. ;          edx = path
  2286. ; output : eax = 0 - ok
  2287. ;                3 - unknown FS
  2288. ;                5 - file not found
  2289. ;          ebx = file date/time
  2290. ;                bits 31..25 = year-1980
  2291. ;                bits 24..21 = month
  2292. ;                bits 20..16 = day
  2293. ;                bits 15..11 = hour
  2294. ;                bits 10..5  = minute
  2295. ;                bits 4..0   = second/2
  2296. ;-----------------------------------------------------------
  2297.     cmp   [fat_type],0
  2298.     jnz   get_filedate_fat_ok
  2299.     xor   ebx,ebx
  2300.     mov   eax,ERROR_UNKNOWN_FS
  2301.     ret
  2302.  
  2303.   get_filedate_fat_ok:
  2304. ;    call  reserve_hd1
  2305.  
  2306.     pushad
  2307.     mov   ebx,edx
  2308.     call  get_cluster_of_a_path
  2309.     jc    get_filedate_not_found
  2310.  
  2311.     mov   ebx,PUSHAD_EAX        ; file name
  2312.     call  analyze_directory
  2313.     jc    get_filedate_not_found
  2314.  
  2315.     mov   eax,[ebx+22]          ; file date/time
  2316.     mov   PUSHAD_EBX,eax
  2317.     popad
  2318.     mov   [hd1_status],0
  2319.     xor   eax,eax
  2320.     ret
  2321.  
  2322.   get_filedate_not_found:
  2323.     popad
  2324.     mov   [hd1_status],0
  2325.     xor   ebx,ebx
  2326.     mov   eax,ERROR_FILE_NOT_FOUND
  2327.     ret
  2328.  
  2329.  
  2330. get_hd_info:
  2331. ;-----------------------------------------------------------
  2332. ; output : eax = 0 - ok
  2333. ;                3 - unknown FS
  2334. ;          edx = cluster size in bytes
  2335. ;          ebx = total clusters on disk
  2336. ;          ecx = free clusters on disk
  2337. ;-----------------------------------------------------------
  2338.     cmp   [fat_type],0
  2339.     jnz   info_fat_ok
  2340.     xor   edx,edx
  2341.     xor   ebx,ebx
  2342.     xor   ecx,ecx
  2343.     mov   eax,ERROR_UNKNOWN_FS
  2344.     ret
  2345.  
  2346.   info_fat_ok:
  2347. ;    call  reserve_hd1
  2348.  
  2349.     xor   ecx,ecx               ; count of free clusters
  2350.     mov   eax,2
  2351.     mov   ebx,[LAST_CLUSTER]
  2352.  
  2353.   info_cluster:
  2354.     push  eax
  2355.     call  get_FAT               ; get cluster info
  2356.     test  eax,eax               ; is it free?
  2357.     jnz   info_used             ; no
  2358.     inc   ecx
  2359.  
  2360.   info_used:
  2361.     pop   eax
  2362.     inc   eax
  2363.     cmp   eax,ebx               ; is above last cluster?
  2364.     jbe   info_cluster          ; no. test next cluster
  2365.  
  2366.     dec   ebx                   ; cluster count
  2367.     imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  2368.     mov   [hd1_status],0
  2369.     xor   eax,eax
  2370.     ret
  2371.  
  2372.  
  2373. update_disk:
  2374. ;-----------------------------------------------------------
  2375. ; write changed fat and cache to disk
  2376. ;-----------------------------------------------------------
  2377.     cmp   [fat_change],0        ; is fat changed?
  2378.     je    upd_no_change
  2379.  
  2380.     call  write_fat_sector
  2381.  
  2382.   upd_no_change:
  2383.  
  2384.     call  write_cache
  2385.     ret
  2386.  
  2387.  
  2388. ;**************************************************************************
  2389. ;
  2390. ;   0x600008  - first entry in cache list
  2391. ;
  2392. ;            +0   - lba sector
  2393. ;            +4   - state of cache sector
  2394. ;                   0 = empty
  2395. ;                   1 = used for read  ( same as in hd )
  2396. ;                   2 = used for write ( differs from hd )
  2397. ;
  2398. ;      +65536 - cache entries
  2399. ;
  2400. ;**************************************************************************
  2401.  
  2402.  
  2403. hd_read:
  2404. ;-----------------------------------------------------------
  2405. ; input  : eax = block to read
  2406. ;          ebx = destination
  2407. ;-----------------------------------------------------------
  2408.     push  ecx esi edi           ; scan cache
  2409.  
  2410.     mov   ecx,cache_max         ; entries in cache
  2411.     mov   esi,0x600000+8
  2412.     mov   edi,1
  2413.  
  2414.   hdreadcache:
  2415.  
  2416.     cmp   dword [esi+4],0       ; empty
  2417.     je    nohdcache
  2418.  
  2419.     cmp   [esi],eax             ; correct sector
  2420.     je    yeshdcache
  2421.  
  2422.   nohdcache:
  2423.  
  2424.     add   esi,8
  2425.     inc   edi
  2426.     dec   ecx
  2427.     jnz   hdreadcache
  2428.  
  2429.     call  find_empty_slot       ; ret in edi
  2430.  
  2431.     call  wait_for_hd_idle
  2432.     push  eax edx
  2433.  
  2434.     cli
  2435.     xor   eax,eax
  2436.     mov   edx,[hdbase]
  2437.     inc   edx
  2438.     out   dx,al   ; ATAFeatures ðåãèñòð "îñîáåííîñòåé"
  2439.     inc   edx
  2440.     inc   eax
  2441.     out   dx,al   ; ATASectorCount ñ÷åò÷èê ñåêòîðîâ
  2442.     inc   edx
  2443.     mov   eax,[esp+4]
  2444.     out   dx,al   ; ATASectorNumber ðåãèñòð íîìåðà ñåêòîðà
  2445.     shr   eax,8
  2446.     inc   edx
  2447.     out   dx,al   ; ATACylinder íîìåð öèëèíäðà (ìëàäøèé áàéò)
  2448.     shr   eax,8
  2449.     inc   edx
  2450.     out   dx,al   ; íîìåð öèëèíäðà (ñòàðøèé áàéò)
  2451.     shr   eax,8
  2452.     inc   edx
  2453.     and   al,1+2+4+8
  2454.     add   al,byte [hdid]
  2455.     add   al,128+64+32
  2456.     out   dx,al   ; íîìåð ãîëîâêè/íîìåð äèñêà
  2457.     inc   edx
  2458.     mov   al,20h
  2459.     out   dx,al   ; ATACommand ðåãèñòð êîìàíä
  2460.     sti
  2461.  
  2462.     call  wait_for_sector_buffer
  2463.  
  2464.     cmp   [hd_error],0
  2465.     jne   hd_read_error
  2466.  
  2467.     cli
  2468.     push  edi
  2469.     shl   edi,9
  2470.     add   edi,0x600000+65536
  2471.     mov   ecx,256
  2472.     mov   edx,[hdbase]
  2473.     cld
  2474.     rep   insw
  2475.     pop   edi
  2476.     sti
  2477.  
  2478.     pop   edx eax
  2479.  blok_read_2:
  2480.     lea   esi,[edi*8+0x600000]
  2481.     mov   [esi],eax             ; sector number
  2482.     mov   dword [esi+4],1       ; hd read - mark as same as in hd
  2483.  
  2484.   yeshdcache:
  2485.  
  2486.     mov   esi,edi
  2487.     shl   esi,9
  2488.     add   esi,0x600000+65536
  2489.     mov   edi,ebx
  2490.     mov   ecx,512/4
  2491.     cld
  2492.     rep   movsd                 ; move data
  2493. ; blok_read_2:
  2494.     pop   edi esi ecx
  2495.     ret
  2496.    
  2497.  
  2498. hd_write:
  2499. ;-----------------------------------------------------------
  2500. ; input  : eax = block
  2501. ;          ebx = pointer to memory
  2502. ;-----------------------------------------------------------
  2503.     push  ecx esi edi
  2504.  
  2505.     ; check if the cache already has the sector and overwrite it
  2506.  
  2507.     mov   ecx,cache_max
  2508.     mov   esi,0x600000+8
  2509.     mov   edi,1
  2510.  
  2511.   hdwritecache:
  2512.  
  2513.     cmp   dword [esi+4],0       ; if cache slot is empty
  2514.     je    not_in_cache_write
  2515.  
  2516.     cmp   [esi],eax             ; if the slot has the sector
  2517.     je    yes_in_cache_write
  2518.  
  2519.   not_in_cache_write:
  2520.  
  2521.     add   esi,8
  2522.     inc   edi
  2523.     dec   ecx
  2524.     jnz   hdwritecache
  2525.  
  2526.     ; sector not found in cache
  2527.     ; write the block to a new location
  2528.  
  2529.     call  find_empty_slot       ; ret in edi
  2530.  
  2531.     lea   esi,[edi*8+0x600000]
  2532.     mov   [esi],eax             ; sector number
  2533.  
  2534.   yes_in_cache_write:
  2535.  
  2536.     mov   dword [esi+4],2       ; write - differs from hd
  2537.  
  2538.     shl   edi,9
  2539.     add   edi,0x600000+65536
  2540.     mov   esi,ebx
  2541.     mov   ecx,512/4
  2542.     cld
  2543.     rep   movsd                 ; move data
  2544.  
  2545.     pop   edi esi ecx
  2546.     ret
  2547.  
  2548.  
  2549. write_cache:
  2550. ;-----------------------------------------------------------
  2551. ; write all changed sectors to disk
  2552. ;-----------------------------------------------------------
  2553.     push  eax ecx edx esi edi
  2554.  
  2555.     ; write difference ( 2 ) from cache to hd
  2556.  
  2557.     mov   ecx,cache_max
  2558.     mov   esi,0x600000+8
  2559.     mov   edi,1
  2560.  
  2561.   write_cache_more:
  2562.  
  2563.     cmp   dword [esi+4],2       ; if cache slot is not different
  2564.     jne   does_not_need_writing
  2565.  
  2566.     mov   dword [esi+4],1       ; same as in hd
  2567.     mov   eax,[esi]             ; eax = sector to write
  2568.  
  2569.     cmp   eax,[PARTITION_START]
  2570.     jb    danger
  2571.     cmp   eax,[PARTITION_END]
  2572.     ja    danger
  2573.  
  2574.     call  wait_for_hd_idle
  2575.  
  2576.     cli
  2577.     xor   eax,eax
  2578.     mov   edx,[hdbase]
  2579.     inc   edx
  2580.     out   dx,al
  2581.     inc   edx
  2582.     inc   eax
  2583.     out   dx,al
  2584.     inc   edx
  2585.     mov   eax,[esi]             ; eax = sector to write
  2586.     out   dx,al
  2587.     shr   eax,8
  2588.     inc   edx
  2589.     out   dx,al
  2590.     shr   eax,8
  2591.     inc   edx
  2592.     out   dx,al
  2593.     shr   eax,8
  2594.     inc   edx
  2595.     and   al,1+2+4+8
  2596.     add   al,byte [hdid]
  2597.     add   al,128+64+32
  2598.     out   dx,al
  2599.     inc   edx
  2600.     mov   al,30h
  2601.     out   dx,al
  2602.     sti
  2603.  
  2604.     call  wait_for_sector_buffer
  2605.  
  2606.     cmp   [hd_error],0
  2607.     jne   hd_write_error
  2608.  
  2609.     push  ecx esi
  2610.  
  2611.     cli
  2612.     mov   esi,edi
  2613.     shl   esi,9
  2614.     add   esi,0x600000+65536    ; esi = from memory position
  2615.     mov   ecx,256
  2616.     mov   edx,[hdbase]
  2617.     cld
  2618.     rep   outsw
  2619.     sti
  2620.  
  2621.     pop   esi ecx
  2622.  
  2623.   danger:
  2624.   does_not_need_writing:
  2625.  
  2626.     add   esi,8
  2627.     inc   edi
  2628.     dec   ecx
  2629.     jnz   write_cache_more
  2630.  
  2631.     pop   edi esi edx ecx eax
  2632.     ret
  2633.  
  2634.  
  2635. find_empty_slot:
  2636. ;-----------------------------------------------------------
  2637. ; find empty or read slot, flush cache if next 10% is used by write
  2638. ; output : edi = cache slot
  2639. ;-----------------------------------------------------------
  2640.     push  ecx esi
  2641.  
  2642.   search_again:
  2643.  
  2644.     mov   ecx,cache_max*10/100
  2645.     mov   edi,[cache_search_start]
  2646.  
  2647.   search_for_empty:
  2648.  
  2649.     inc   edi
  2650.     cmp   edi,cache_max
  2651.     jbe   inside_cache
  2652.     mov   edi,1
  2653.  
  2654.   inside_cache:
  2655.  
  2656.     cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
  2657.     jb    found_slot                    ; it's empty or read
  2658.     dec   ecx
  2659.     jnz   search_for_empty
  2660.  
  2661.     call  write_cache                   ; no empty slots found, write all
  2662.     jmp   search_again                  ; and start again
  2663.  
  2664.   found_slot:
  2665.  
  2666.     mov   [cache_search_start],edi
  2667.  
  2668.     pop   esi ecx
  2669.     ret
  2670.  
  2671.  
  2672. save_hd_wait_timeout:
  2673.  
  2674.     push  eax
  2675.     mov   eax,[timer_ticks];[0xfdf0]
  2676.     add   eax,300               ; 3 sec timeout
  2677.     mov   [hd_wait_timeout],eax
  2678.     pop   eax
  2679.     ret
  2680.  
  2681.  
  2682. check_hd_wait_timeout:
  2683.  
  2684.     push  eax
  2685.     mov   eax,[hd_wait_timeout]
  2686.     cmp   [timer_ticks], eax ;[0xfdf0],eax
  2687.     jg    hd_timeout_error
  2688.     pop   eax
  2689.     ret
  2690.  
  2691. iglobal
  2692.   hd_timeout_str   db 'K : FS - HD timeout',13,10,0
  2693.   hd_read_str      db 'K : FS - HD read error',13,10,0
  2694.   hd_write_str     db 'K : FS - HD write error',13,10,0
  2695. endg
  2696.  
  2697. hd_timeout_error:
  2698.  
  2699.     call  clear_hd_cache
  2700.     call  clear_application_table_status
  2701.     mov   esi,hd_timeout_str
  2702.     call  sys_msg_board_str
  2703.     jmp   $
  2704.  
  2705.  
  2706. hd_read_error:
  2707.  
  2708.     call  clear_hd_cache
  2709.     call  clear_application_table_status
  2710.     mov   esi,hd_read_str
  2711.     call  sys_msg_board_str
  2712.     jmp   $
  2713.  
  2714. hd_write_error:
  2715.  
  2716.     call  clear_hd_cache
  2717.     call  clear_application_table_status
  2718.     mov   esi,hd_write_str
  2719.     call  sys_msg_board_str
  2720.     jmp   $
  2721.  
  2722.  
  2723.  
  2724.  
  2725. wait_for_hd_idle:
  2726.  
  2727.     push  eax edx
  2728.  
  2729.     call  save_hd_wait_timeout
  2730.  
  2731.     mov   edx,[hdbase]
  2732.     add   edx,0x7
  2733.  
  2734.   wfhil1:
  2735.  
  2736.     call  check_hd_wait_timeout
  2737.  
  2738.     in    al,dx
  2739.     test  al,128
  2740.     jnz   wfhil1
  2741.  
  2742.     pop   edx eax
  2743.     ret
  2744.  
  2745.  
  2746. wait_for_sector_buffer:
  2747.  
  2748.     push  eax edx
  2749.  
  2750.     mov   edx,[hdbase]
  2751.     add   edx,0x7
  2752.  
  2753.     call  save_hd_wait_timeout
  2754.  
  2755.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  2756.  
  2757.     call  check_hd_wait_timeout
  2758.  
  2759.     in    al,dx
  2760.     test  al,8
  2761.     jz    hdwait_sbuf
  2762.  
  2763.     mov   [hd_error],0
  2764.  
  2765.     cmp   [hd_setup],1          ; do not mark error for setup request
  2766.     je    buf_wait_ok
  2767.  
  2768.     test  al,1                  ; previous command ended up with an error
  2769.     jz    buf_wait_ok
  2770.     mov   [hd_error],1
  2771.  
  2772.   buf_wait_ok:
  2773.  
  2774.     pop   edx eax
  2775.     ret
  2776.  
  2777.  
  2778.  
  2779. read_hd_file:
  2780. ;-----------------------------------------------------------------
  2781. ;
  2782. ; Converting old reading function for hd-application start.
  2783. ;
  2784. ; IN:
  2785. ;
  2786. ; eax - pointer to file (0 = read only first sector of drive: eg 'label')
  2787. ; ebx - file lenght
  2788. ; ecx - start 512 byte block number
  2789. ; edx - number of blocks to read
  2790. ; esi - pointer to return/work area (atleast 20 000 bytes)
  2791. ;
  2792. ; For new read function
  2793. ;
  2794. ; EAX   (PAR0)      pointer to file-name
  2795. ; ECX   (PAR1)      pointer to buffer
  2796. ; EBX   (PAR2)   vt file blocks to read
  2797. ; EDX   (PAR3)      pointer to path
  2798. ; ESI            vt first 512 block to read
  2799. ; EDI               if 0 - return root
  2800. ;--------------------------------------------------------------------------
  2801.  
  2802.     push  ecx esi edi
  2803.     mov   esi,eax
  2804.     mov   edi,startpath
  2805.     mov   ecx,250
  2806.     cld
  2807.     rep   movsb
  2808.     pop   edi esi ecx
  2809.  
  2810.     mov   eax,startpath
  2811.     mov   [eax+ebx-12],byte 0
  2812.  
  2813.     push  eax ebx ecx edx esi
  2814.  
  2815.     pop   ecx ; pointer to buffer
  2816.     add   ecx,1024
  2817.     pop   ebx ; number of blocks to read
  2818.     pop   esi ; first block to read
  2819.     dec   esi
  2820.     pop   eax ; file length
  2821.     pop   edx ; pointer to path
  2822.  
  2823.     mov   edi,12
  2824.     lea   eax,[eax+edx-12+1]
  2825.     call  file_read
  2826.  
  2827.     ret
  2828.  
  2829.