Subversion Repositories Kolibri OS

Rev

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