; *****************************************************************************
;
; DRV_INIT2.ASM  [ TRDOS Kernel Drive Initialization Procedures ]
; 25/06/2009
; DRV_INIT.ASM
; Copyright (C) 2005 Erdogan TAN  [ 29/01/2005 ]
;
; TRDOS.ASM (include drv_init.asm)
;
; *****************************************************************************

; TRFS

bs_FS_JmpBoot equ 0 ; jmp short bsBootCode
                ; db 0EBh, db 3Fh, db 90h
bs_FS_Identifier equ 3  ; db 'FS', db 0
bs_FS_BytesPerSec equ 6 ; dw 512
bs_FS_MediaAttrib equ 8 ; db 3
bs_FS_PartitionId equ 9 ; db 0A1h
bs_FS_VersionMaj equ 10 ; db 01h
bs_FS_VersionMin equ 11 ; db 0
bs_FS_BeginSector equ 12   ; dd 0 
bs_FS_VolumeSize equ 16 ; dd 2880
bs_FS_StartupFD equ 20 ; dd 0
bs_FS_MATLocation equ 24 ; dd 1
bs_FS_RootDirD equ 28 ; dd 8
bs_FS_SystemConfFD equ 32 ; dd 0
bs_FS_SwapFD equ 36 ; dd 0
bs_FS_UnDelDirD equ 40 ; dd 0
bs_FS_DriveNumber equ 44 ; db 0
bs_FS_LBA_Ready equ 45 ; db 0
bs_FS_MagicWord equ 46 
bs_FS_SecPerTrack equ 46 ; db 0A1h
bs_FS_Heads equ 47 ; db 01h 
bs_FS_OperationSys equ 48 ; db "TR-SINGLIX v1.0b"
bs_FS_Terminator equ 64 ; db 0
bs_FS_BootCode equ 65 

FS_MAT_DATLocation equ 12
FS_MAT_DATScount equ 16
FS_MAT_FreeSectors equ 20
FS_MAT_FirstFreeSector equ 24
FS_RDT_VolumeSerialNo equ 28
FS_RDT_VolumeName equ 64

; FAT12 + FAT16 + FAT32
BS_JmpBoot equ 0
BS_OEMName equ 3
BPB_BytsPerSec equ 11
BPB_SecPerClust equ 13
BPB_RsvdSecCnt equ 14
BPB_NumFATs equ 16
BPB_RootEntCnt equ 17
BPB_TotalSec16 equ 19
BPB_Media equ 21
BPB_FATSz16 equ 22
BPB_SecPerTrk equ 24
BPB_NumHeads equ 26
BPB_HiddSec equ 28
BPB_TotalSec32 equ 32

; FAT12 and FAT16 only
BS_DrvNum equ 36
BS_Reserved1 equ 37
BS_BootSig equ 38
BS_VolID equ 39
BS_VolLab equ 43
BS_FilSysType equ 54 ; 8 bytes
BS_BootCode equ 62

; FAT32 only
BPB_FATSz32 equ 36 ; FAT32, 4 bytes
BPB_ExtFlags equ 40 ; FAT32, 2 bytes
BPB_FSVer equ 42 ; FAT32, 2 bytes
BPB_RootClus equ 44 ; FAT32, 4 bytes
BPB_FSInfo equ 48 ; FAT 32, 2 bytes 
BPB_BkBootSec equ 50 ; FAT32, 2 bytes
BPB_Reserved equ 52 ; FAT32, 12 bytes
BS_FAT32_DrvNum equ 64 ; FAT32, 1 byte
BS_FAT32_Reserved1 equ 65 ; FAT32, 1 byte
BS_FAT32_BootSig equ 66 ; FAT32, 1 byte
BS_FAT32_VolID equ 67 ; FAT32, 4 bytes
BS_FAT32_VolLab equ 71 ; FAT32, 11 bytes
BS_FAT32_FilSysType equ 82 ; FAT32, 8 bytes
BS_FAT32_BootCode equ 90

BS_Validation equ 510


proc_drv_init   proc    near

                xor dl,dl
                mov si, offset DiskParams
dparam_read:
                call proc_dparam
                mov dl, byte ptr [SI][DPDisks]
                add si, 40h
                cmp dl, 2
                jne short pass_floppy1
                dec dl
                call proc_dparam
pass_floppy1:
                mov dl, 80h
                add si, 40h
                call proc_dparam
                jnc short pass_hd_15h_error
                mov word ptr [si][DPNumOfSecs], 0
                mov word ptr [si][DPNumOfSecs]+2,0
pass_hd_15h_error:
                mov ah, byte ptr [SI][DPDisks]
                mov byte ptr [HDCounter], ah
next_hard_disk:
                dec byte ptr [HDCounter]
                cmp byte ptr [HDCounter], 0
                jna short load_hd_partition_tables
                inc dl
                add si, 40h
                call proc_dparam
                jnc short next_hard_disk
                mov word ptr [si][DPNumOfSecs], 0
                mov word ptr [si][DPNumOfSecs]+2,0
                jmp short next_hard_disk
load_hd_partition_tables:
                mov si, offset Disk_hd0
                mov di, offset PTable_hd0
                push ds
                pop es
                mov dl, 80h
                mov cx, 4
load_next_hd_partition_table:
                push cx
                push dx
                push si
                push di
                cmp byte ptr [SI]+1, 03h
                jne short pass_pt_this_hard_disk
                call proc_load_masterboot
                jc short pass_pt_this_hard_disk
                pop di
                push di
                mov si, offset PartitionTable
                mov cx, 32
                rep movsw
pass_pt_this_hard_disk:
                pop di
                pop si
                pop dx
                pop cx
                inc dl
                add si, 40h
                add di, 40h
                loop load_next_hd_partition_table
load_extended_dos_partitions:
                mov si, Offset PTable_hd0
                mov di, Offset PTable_ep0
                mov byte ptr [HDCounter], 80h
next_hd_extd_partition:
                push si
                mov cx, 4
hd_check_fs_id_05h:
                mov al, byte ptr [SI][ptFileSystemName]
                cmp al, 05h ; Is it an extended dos partition ?
                je short pass_hd_check_05h
                cmp al, 0Fh ; Is it an extended win4 (LBA mode) partition ?
                je short pass_hd_check_0Fh 
continue_to_check_ep:
                add si, 10h
                loop hd_check_fs_id_05h
continue_check_ep_next_disk:
                pop si
                add si, 40h
                add di, 40h
                cmp byte ptr [HDCounter], 83h
                jnb logical_drv_init
                inc byte ptr [HDCounter]
                jmp short next_hd_extd_partition
pass_hd_check_05h:
                push cx
                mov ax, word ptr [SI][ptStartSector]
                mov dx, word ptr [SI][ptStartSector]+2
                xor bh,bh
                mov bl, byte ptr [HDCounter]
                push bx
                sub bl, 80h
                shl bl, 1
                shl bl, 1
                mov word ptr [Val_StartSector][BX],ax
                mov word ptr [Val_StartSector][BX]+2,dx
                pop dx
                mov dh, byte ptr [SI][ptBeginHead]
                mov cx, word ptr [SI][ptBeginSector]
                mov ax, 0201h    ; Read 1 sector
                mov bx, offset MasterBootBuff
                push ds
                pop es
                int 13h
                pop cx
                jc short continue_to_check_ep
                push si
                push di
                push cx
                mov si, offset PartitionTable
                mov cx, 32
                rep movsw
                pop cx
                pop di
                pop si
                jmp short continue_check_ep_next_disk
pop_di_check_next_ep:
                pop di
                jmp continue_to_check_ep
pass_hd_check_0Fh:
                mov ax, word ptr [SI][ptStartSector]
                mov dx, word ptr [SI][ptStartSector]+2
                xor bh,bh
                mov bl, byte ptr [HDCounter]
                sub bl, 80h
                push bx
                shl bl, 1
                shl bl, 1
                mov word ptr [Val_StartSector][BX],ax
                mov word ptr [Val_StartSector][BX]+2,dx
                pop ax
                push di
                mov ah, 40h
                mul ah
                mov di, offset Disk_hd0
                add di, ax
ep_mov_dap_parameters:
                push ds
                pop es
                cmp byte ptr [DI][DAP_PacketSize], 10h
                jne short pop_di_check_next_ep
                mov word ptr [DI][DAP_Destination], offset MasterBootBuff
                push ds
                pop word ptr [DI][DAP_Destination]+2
                mov byte ptr [DI][DAP_NumOfBlocks],1
                push si
                push di
                add si, ptStartSector
                add di, DAP_LBA_Address
                movsw
                movsw
                pop si  
                add si, DAP_PacketSize ; DS:SI= DAP Location
                mov ah, 42h  ; Extended Disk Read - LBA Read
                mov dl, byte ptr [HDCounter]
                int 13h
                pop si
                pop di
                jc continue_to_check_ep
                push di
                push si
                push cx
                mov si, offset PartitionTable
                mov cx, 32
                rep movsw
                pop cx
                pop si
                pop di
                jmp continue_check_ep_next_disk
logical_drv_init:
                mov byte ptr [Hard_Disk], 80h
                mov cx, 4
                xor al, al
                mov si, offset PTable_Buffer
                mov di, offset Logical_DOSDisks + 200h
                mov byte ptr [Last_DOS_DiskNo], 1
ldrv_init_next_hdp:
                push si
                push cx
                push ax
                push di
                cmp byte ptr [SI][ptFileSystemName], 06h
                jne short pass_this_is_FAT16_CHS_disk
                mov byte ptr [DI][LD_DiskType], 2
                mov dl, byte ptr [Hard_Disk]
                mov byte ptr [DI][LD_PhyDrvNo], dl
                mov byte ptr [DI][LD_FATType], 2
                mov byte ptr [DI][LD_FSType], 06h
                mov bl, dl
                sub bl, 80h
                xor bh, bh
                mov ah, byte ptr [HD_LBAYes][BX]
                mov byte ptr [DI][LD_LBAYes], ah
                mov byte ptr [DI][LD_PartitionEntry],al
                mov ah, dl
                sub ah, 7Eh
                mov byte ptr [DI][LD_DParamEntry], ah
                mov dh, byte ptr [SI][ptBeginHead]
                mov cx, word ptr [SI][ptBeginSector]
                mov ax, 0201h    ; Read 1 sector
                mov bx, offset DOSBootSectorBuff
                int 13h
                jc pass_this_is_FAT32_LBA_disk
                jmp hdp_boot_validation
pass_this_is_FAT16_CHS_disk:
                cmp byte ptr [SI][ptFileSystemName], 0Eh
                jne pass_this_is_FAT16_LBA_disk
                mov byte ptr [DI][LD_DiskType], 2
                mov dl, byte ptr [Hard_Disk]
                mov byte ptr [DI][LD_PhyDrvNo], dl
                mov byte ptr [DI][LD_FATType], 2
                mov byte ptr [DI][LD_FSType], 0Eh
                mov byte ptr [DI][LD_LBAYes], 1
                mov byte ptr [DI][LD_PartitionEntry],al
                mov ah, dl
                sub ah, 7Eh
                mov byte ptr [DI][LD_DParamEntry], ah
                mov al, 40h
                mul ah
                add ax, offset Disk_fd0
                mov di, ax
                cmp byte ptr [DI][DAP_PacketSize], 10h
                jne pass_this_is_FAT32_LBA_disk
                mov word ptr [DI][DAP_Destination], offset DOSBootSectorBuff
                push ds
                pop word ptr [DI][DAP_Destination]+2
                mov byte ptr [DI][DAP_NumOfBlocks],1
                push di
                add si, ptStartSector
                add di, DAP_LBA_Address
                movsw
                movsw
                pop si  
                add si, DAP_PacketSize ; DS:SI= DAP Location
                mov ah, 42h  ; Extended Disk Read - LBA Read
                mov dl, byte ptr [Hard_Disk]
                int 13h
                jc pass_this_is_FAT32_LBA_disk
hdp_boot_validation:
                mov si, offset DOSBootSectorBuff
                cmp word ptr [SI][BS_Validation], 0AA55h
                jne pass_this_is_FAT32_LBA_disk
                ; Singlix FS Extensions to TR-DOS 7/6/2009 
                cmp word ptr [SI][bs_FS_Identifier], 'SF'
                jne pass_singlix_fd_hd_validation_check
                ; 'A1h' check is not necessary if 'FS' check is passed as OK/Yes.
                cmp byte ptr [SI][bs_FS_PartitionID], 0A1h
                jne pass_singlix_fd_hd_validation_check

                pop di
                mov al, byte ptr [SI][bs_FS_LBA_Ready]
                mov byte ptr [DI][LD_FS_LBAYes], al
                mov ax, word ptr [SI][bs_FS_BytesPerSec]
                mov word ptr [DI][LD_FS_BytesPerSec], ax
                mov ax, word ptr [SI][bs_FS_MediaAttrib]
                mov word ptr [DI][LD_FS_MediaAttrib], ax
		mov ax, word ptr [SI][bs_FS_SecPerTrack]
                mov word ptr [DI][LD_FS_SecPerTrack], ax
                mov ax, word ptr [SI][bs_FS_UnDelDirD]
                mov dx, word ptr [SI][bs_FS_UnDelDirD]+2
                mov word ptr [DI][LD_FS_UnDelDirD], ax
                mov word ptr [DI][LD_FS_UnDelDirD]+2, dx
                mov ax, word ptr [SI][bs_FS_MATLocation]
                mov dx, word ptr [SI][bs_FS_MATLocation]+2
                mov word ptr [DI][LD_FS_MATLocation], ax
                mov word ptr [DI][LD_FS_MATLocation]+2, dx
                mov ax, word ptr [SI][bs_FS_RootDirD]
 		mov dx, word ptr [SI][bs_FS_RootDirD]+2
                mov word ptr [DI][LD_FS_RootDirD], ax
                mov word ptr [DI][LD_FS_RootDirD]+2, dx
 		mov ax, word ptr [SI][bs_FS_BeginSector]
 		mov dx, word ptr [SI][bs_FS_BeginSector]+2
                mov word ptr [DI][LD_FS_BeginSector], ax
                mov word ptr [DI][LD_FS_BeginSector]+2, dx  
                mov ax, word ptr [SI][bs_FS_VolumeSize]
 		mov dx, word ptr [SI][bs_FS_VolumeSize]+2
                mov word ptr [DI][LD_FS_VolumeSize], ax
                mov word ptr [DI][LD_FS_VolumeSize]+2, dx
                push di 
                
                mov si, di
                
                mov ax, word ptr [SI][LD_FS_MATLocation]
                mov dx, word ptr [SI][LD_FS_MATLocation]+2
                add ax, word ptr [SI][LD_FS_BeginSector]
                adc dx, word ptr [SI][LD_FS_BeginSector]+2  
read_hd_MAT_sector_again:
               ;mov bx, offset DOSBootSectorBuff
                mov cx, 1
                call proc_disk_read
                jc pass_this_is_Singlix_FS_disk
                mov si, bx 
use_hdfs_mat_sector_params:
 		mov ax, word ptr [SI][FS_MAT_DATLocation]
                mov dx, word ptr [SI][FS_MAT_DATLocation]+2                                  
 		mov word ptr [DI][LD_FS_DATLocation], ax
                mov word ptr [DI][LD_FS_DATLOcation]+2, dx

		mov ax, word ptr [SI][FS_MAT_DATScount]
                mov dx, word ptr [SI][FS_MAT_DATScount]+2                                  
 		mov word ptr [DI][LD_FS_DATSectors], ax
                mov word ptr [DI][LD_FS_DATSectors]+2, dx

                mov ax, word ptr [SI][FS_MAT_FreeSectors]
                mov dx, word ptr [SI][FS_MAT_FreeSectors]+2                                  
 		mov word ptr [DI][LD_FS_FreeSectors], ax
                mov word ptr [DI][LD_FS_FreeSectors]+2, dx

 		mov ax, word ptr [SI][FS_MAT_FirstFreeSector]
                mov dx, word ptr [SI][FS_MAT_FirstFreeSector]+2                                  
 		mov word ptr [DI][LD_FS_FirstFreeSector], ax
                mov word ptr [DI][LD_FS_FirstFreeSector]+2, dx

              	mov si, di
 		mov ax, word ptr [SI][LD_FS_RootDirD]
                mov dx, word ptr [SI][LD_FS_RootDirD]+2
                add ax, word ptr [SI][LD_FS_BeginSector]
                adc dx, word ptr [SI][LD_FS_BeginSector]+2   
read_hd_RDT_sector_again:
                ;mov bx, offset DOSBootSectorBuff
            	mov cx, 1
                call proc_disk_read
                jc pass_this_is_Singlix_FS_disk
                mov si, bx 
use_hdfs_RDT_sector_params:
                mov ax, word ptr [SI][FS_RDT_VolumeSerialNo]
                mov dx, word ptr [SI][FS_RDT_VolumeSerialNo]+2                                  
                mov word ptr [DI][LD_FS_VolumeSerial], ax
                mov word ptr [DI][LD_FS_VolumeSerial]+2, dx

                push di
                mov cx, 32
                add si, FS_RDT_VolumeName
                add di, LD_FS_VolumeName
                rep movsw
                pop si
                
                inc byte ptr [Last_DOS_DiskNo]
                mov al, 'A'
                add al, byte ptr [Last_DOS_DiskNo]
                mov byte ptr [SI][LD_FS_Name], al

                mov byte ptr [SI][LD_FS_MediaChanged],1  ; What for !?
                
                pop di
                add di, 100h
                push di

                jmp pass_this_is_Singlix_FS_disk

pass_singlix_fd_hd_validation_check:
                cmp byte ptr [SI][BPB_Media], 0F8h
                jne pass_this_is_FAT32_LBA_disk
                cmp word ptr [SI][BPB_FATSz16], 0
                ja short pass_FAT32_BPB
                cmp byte ptr [SI][BS_FAT32_BootSig], 29h
                jne pass_this_is_FAT32_LBA_disk
                mov cx, 45
                jmp short loc_move_hd_BPB
pass_FAT32_BPB:
                cmp byte ptr [SI][BS_BootSig], 29h
                jne pass_this_is_FAT32_LBA_disk
                mov cx, 32
loc_move_hd_BPB:
                pop di
                push di
                push di
                add di, LD_BPB
                rep movsw 
                pop si
                pop di
                add di, 100h
                push di
                inc byte ptr [Last_DOS_DiskNo]
                mov al, 'A'
                add al, byte ptr [Last_DOS_DiskNo]
                mov byte ptr [SI][LD_Name], al

                cmp byte ptr [Now_EP_Drives], 0
                jna short ld_StartSector_set1
                cmp byte ptr [SI][LD_FsType], 0Bh
                jne short ld_StartSector_set1
                mov ax, word ptr [SI][LD_StartSector]
                mov dx, word ptr [SI][LD_StartSector]+2
                jmp short ld_StartSector_set2
ld_StartSector_set1:
                mov AX,Word Ptr [SI][LD_BPB][Hidden1]
                mov DX,Word Ptr [SI][LD_BPB][Hidden2]
                mov word ptr [SI][LD_StartSector],AX
                mov word ptr [SI][LD_StartSector]+2,DX
ld_StartSector_set2:
                add AX,Word Ptr [SI][LD_BPB][ResSectors]
                adc DX,0

                mov Word Ptr [SI][LD_FATBegin], AX
                mov Word Ptr [SI][LD_FATBegin]+2, DX
                cmp byte ptr [SI][LD_FATType], 3
                jne short pass_FAT32_RootDirLoc
                mov ax, Word Ptr [SI][LD_BPB][FAT32_FAT_Size]
                mov dx, Word Ptr [SI][LD_BPB][FAT32_FAT_Size]+2
                xor bh,bh
                mov bl,Byte Ptr [SI][LD_BPB][FATs]
                call proc_mul32
                add ax, Word Ptr [SI][LD_FATBegin]
                adc dx, Word Ptr [SI][LD_FATBegin]+2
                mov Word Ptr [SI][LD_DATABegin], AX
                mov Word Ptr [SI][LD_DATABegin]+2, DX
                mov Word Ptr [SI][LD_ROOTBegin], AX
                mov Word Ptr [SI][LD_ROOTBegin]+2, DX
                jmp short pass_FAT_FS_Locations
pass_FAT32_RootDirLoc:
                mov AL,Byte Ptr [SI][LD_BPB][FATs]
                cbw                             
                mul Word Ptr [SI][LD_BPB][FATSecs]
                add AX,Word Ptr [SI][LD_FATBegin]
                adc DX,Word Ptr [SI][LD_FATBegin]+2
                mov Word Ptr [SI][LD_ROOTBegin], AX
                mov Word Ptr [SI][LD_ROOTBegin]+2, DX
                mov Word Ptr [SI][LD_DATABegin], AX 
                mov Word Ptr [SI][LD_DATABegin]+2, DX
                mov AX,20h       ; Size of a directory entry
                mul Word Ptr [SI][LD_BPB][RootDirEnts]
                add AX,511
              ; adc dx, 0
                mov cx, 512
                div cx
                add Word Ptr [SI][LD_DATABegin],AX 
                adc Word Ptr [SI][LD_DATABegin]+2,0
pass_FAT_FS_Locations:
                mov ax,Word Ptr [SI][LD_BPB][HugeSec1]
                mov Word Ptr [SI][LD_TotalSectors], AX
                mov dx,Word Ptr [SI][LD_BPB][HugeSec2]
                mov Word Ptr [SI][LD_TotalSectors]+2, dx
                add ax,Word Ptr [SI][LD_StartSector]
                adc dx,Word Ptr [SI][LD_StartSector]+2
                sub ax,Word Ptr [SI][LD_DATABegin]
                sbb dx,Word Ptr [SI][LD_DATABegin]+2
                xor ch,ch
                mov cl,Byte Ptr [SI][LD_BPB][SecPerClust]
                call Rx_Dos_Div32 
                mov word ptr [SI][LD_Clusters], AX
                mov word ptr [SI][LD_Clusters]+2, DX
                    ; Maximum Valid Cluster Number= DX:AX +1
                    ; with 2 reserved clusters= DX:AX +2
               ;mov word ptr [SI][LD_FreeSectors],0
               ;mov word ptr [SI][LD_FreeSectors]+2,0

                call get_free_FAT_sectors
                jc pass_this_is_FAT32_LBA_disk
               
 		inc byte ptr [Last_DOS_DiskNo]
                mov al, 'A'
                add al, byte ptr [Last_DOS_DiskNo]
                mov byte ptr [SI][LD_FS_Name], al

                jmp pass_this_is_FAT32_LBA_disk

pass_this_is_FAT16_LBA_disk:
                cmp byte ptr [SI][ptFileSystemName], 0Bh
                jne short pass_this_is_FAT32_CHS_disk
                mov byte ptr [DI][LD_DiskType], 2
                mov bl, byte ptr [Hard_Disk]
                mov byte ptr [DI][LD_PhyDrvNo], bl
                mov byte ptr [DI][LD_FATType], 3
                mov byte ptr [DI][LD_FSType], 0Bh
                sub bl, 80h
                xor bh, bh
                mov ah, byte ptr [HD_LBAYes][BX]
                mov byte ptr [DI][LD_LBAYes],ah
                mov byte ptr [DI][LD_PartitionEntry],al
                mov ah, bl
                add ah, 2
                mov byte ptr [DI][LD_DParamEntry], ah
                mov ax, word ptr [SI][ptStartSector]
                mov dx, word ptr [SI][ptStartSector]+2
                cmp byte ptr [Now_EP_Drives],0
                jna short pass_0Bh_ext_part_start_fixup
                shl bl, 1
                shl bl, 1
                add ax, word ptr [Val_StartSector][BX]
                adc dx, word ptr [Val_StartSector][BX]+2
                mov word ptr [DI][LD_StartSector], ax
                mov word ptr [DI][LD_StartSector]+2, dx
pass_0Bh_ext_part_start_fixup:
                push ax
                mov ah, byte ptr [Hard_Disk]
                sub ah, 7Eh
                mov al, 40h
                mul ah
                add ax, offset Disk_fd0
                mov di, ax
                pop ax
                cmp byte ptr [DI][DAP_PacketSize], 10h
                jne pass_this_is_FAT32_LBA_disk
                mov word ptr [DI][DAP_LBA_Address], ax
                mov word ptr [DI][DAP_LBA_Address]+2, dx
                jmp short loc_fixup_8GB_CHS_to_LBA
pass_val_startsec_check:
                mov dh, byte ptr [SI][ptBeginHead]
                mov cx, word ptr [SI][ptBeginSector]
                mov ax, 0201h    ; Read 1 sector
                mov bx, offset DOSBootSectorBuff
                int 13h
                jc pass_this_is_FAT32_LBA_disk
                jmp hdp_boot_validation
pass_this_is_FAT32_CHS_disk:
                cmp byte ptr [SI][ptFileSystemName], 0Ch
                jne check_this_is_Singlix_FS_disk
                mov byte ptr [DI][LD_DiskType], 2
                mov ah, byte ptr [Hard_Disk]
                mov byte ptr [DI][LD_PhyDrvNo], ah
                mov byte ptr [DI][LD_FATType], 3
                mov byte ptr [DI][LD_FSType], 0Ch
                mov byte ptr [DI][LD_LBAYes], 1
                mov byte ptr [DI][LD_PartitionEntry],al
                sub ah, 7Eh
                mov byte ptr [DI][LD_DParamEntry], ah
                mov al, 40h
                mul ah
                add ax, offset Disk_fd0
                mov di, ax
                cmp byte ptr [DI][DAP_PacketSize], 10h
                jne pass_this_is_FAT32_LBA_disk
                push word ptr [SI][ptStartSector]
                pop word ptr [DI][DAP_LBA_Address]
                push word ptr [SI][ptStartSector]+2
                pop word ptr [DI][DAP_LBA_Address]+2
loc_fixup_8GB_CHS_to_LBA:
                mov word ptr [DI][DAP_Destination], offset DOSBootSectorBuff
                push ds
                pop word ptr [DI][DAP_Destination]+2
                mov byte ptr [DI][DAP_NumOfBlocks],1
                push di
                pop si  
                add si, DAP_PacketSize ; DS:SI= DAP Location
                mov ah, 42h  ; Extended Disk Read - LBA Read
                mov dl, byte ptr [Hard_Disk]
                int 13h
                jnc hdp_boot_validation
pass_this_is_FAT32_LBA_disk:
; 7/6/2009
pass_this_is_Singlix_FS_disk:
                pop di
                pop ax
                pop cx
                pop si
                add si, 10h
                inc al
                dec cx
                cmp cx, 0
                ja  ldrv_init_next_hdp
                cmp byte ptr [Hard_Disk], 83h
                jnb short pass_init_primary_dos_partitions
                mov cx, 4
                inc byte ptr [Hard_Disk]
                jmp ldrv_init_next_hdp
pass_init_primary_dos_partitions:
                cmp byte ptr [Now_EP_Drives], 0
                ja short loc_drv_init_retn
                mov byte ptr [Now_EP_Drives], 1
                mov si, offset PTable_ep0
                mov byte ptr [Hard_Disk], 80h
                mov ah, byte ptr [Last_DOS_DiskNo]
                inc ah
                xor al,al
                mov di, offset Logical_DOSDisks
                add di, ax
                mov al, 16
                mov cx, 4
                jmp ldrv_init_next_hdp
check_this_is_Singlix_FS_disk:
                ; 7/6/2009 SINGLIX FS Extensions to TR-DOS DRV_INIT
 		cmp byte ptr [SI][ptFileSystemName], 0A1h
                jne short pass_this_is_Singlix_FS_disk
                mov byte ptr [DI][LD_FS_DiskType], 2
                mov ah, byte ptr [Hard_Disk]
                mov byte ptr [DI][LD_FS_PhyDrvNo], ah
               ;mov byte ptr [DI][LD_FS_FATType], 0
                mov byte ptr [DI][LD_FS_FSType], 0A1h
               ;mov byte ptr [DI][LD_FS_LBAYes], 1
                mov byte ptr [DI][LD_PartitionEntry],al
                sub ah, 7Eh
                mov byte ptr [DI][LD_DParamEntry], ah
                mov al, 40h
                mul ah
                add ax, offset Disk_fd0
                mov di, ax
                cmp byte ptr [DI][DAP_PacketSize], 10h
                jne pass_this_is_FAT32_LBA_disk
                push word ptr [SI][ptStartSector]
                pop word ptr [DI][DAP_LBA_Address]
                push word ptr [SI][ptStartSector]+2
                pop word ptr [DI][DAP_LBA_Address]+2
                jmp loc_fixup_8GB_CHS_to_LBA

Now_EP_Drives:  db 0

Val_StartSector: dd 0
                 dd 0
                 dd 0
                 dd 0

loc_drv_init_retn:
                retn

proc_drv_init   endp


proc_dparam   proc near
              ; input
              ; dl = Disk Drive Number
              ; ds:si = Parameters Table Buffer
              ; output
              ; ah = error number (0 = No Error if C flag is ZERO)
              mov byte ptr [si][DPDiskNumber], dl
              mov byte ptr [si][DPDType], 0
              push dx
              mov ah, 08h
              int 13h
              mov byte ptr [si][DPReturn], ah
              jnc short dparam_no_error
              pop dx
              retn
dparam_no_error:
              mov byte ptr [si][DPDType], bl
              mov byte ptr [si][DPDisks], dl
              inc dh
              mov byte ptr [si][DPHeads], dh
              push cx
              and cl, 3Fh
              mov byte ptr [si][DPSecPerTrack], cl
              pop cx
              shr cl,1
              shr cl,1
              shr cl,1
              shr cl,1
              shr cl,1
              shr cl,1
              xchg ch,cl
              inc cx
              mov word ptr [si][DPCylinders], cx
              mov word ptr [si][DPTableOff], di
              push es
              pop word ptr [si][DPTableSeg]

              cmp byte ptr [si][DPDiskNumber], 80h
              jb short dparam_15h_return

              mov dl, byte ptr [si][DPDiskNumber]
              mov byte ptr [Hard_Disk], dl
              mov byte ptr [si][DPDType], 0
              mov ah, 15h
              int 13h
              jc short dparam_15h_return
              mov byte ptr [si][DPDType], ah
              mov word ptr [si][DPNumOfSecs], cx
              mov word ptr [si][DPNumOfSecs]+2, dx
dparam_15h_return:
              pop dx ; dl = Drive Number
              mov byte ptr [SI][DAP_PacketSize], 0 ; Reset (No DAP)
              mov ah, 41h ; Check Extensions Present
              mov bx, 55AAh
              int 13h
              jc short dparam_48h_return
              cmp bx, 0AA55h
              jne short dparam_48h_return
              test cx, 01h ; Fixed Disk Access Subset - is LBA ready ? 
              jz short dparam_48h_return
              xor bh,bh
              mov bl, byte ptr [Hard_Disk]
              sub bl, 80h
              mov byte ptr [HD_LBAYes][BX],1
              mov byte ptr [SI][DAP_PacketSize], 10h
dparam_41h_return:
              push si
              add si, GetDParams_48h
              mov word ptr [SI], 0026 ; GDP Data Lenght - Set
            ; DS:SI= Address of Result Buffer
            ; DL (Drive Number) must be not changed before here...
              mov ah, 48h  ; Get Enhanced Disk Drive Parameters
              int 13h
              pop si
              jc short dparam_48h_return
              mov word ptr [SI][GetDParams_48h], 0 ; GDP Data Lenght - Reset
dparam_48h_return:
              xor ah,ah
              retn
proc_dparam   endp

proc_load_masterboot proc near
                ; input -> dl = drive number
                xor ah,ah
                int 13h
                jnc short pass_reset_error
harddisk_error:
                retn
pass_reset_error:
                mov bx, offset MasterBootBuff
                mov ax,0201h
                mov cx,1
                xor dh,dh
                push ds
                pop es
                int 13h
                jc short harddisk_error

                cmp word ptr [MBIDCode],0AA55h
                jnz short loc_not_masterboot
                retn
loc_not_masterboot:
                stc
                retn

proc_load_masterboot endp


get_free_FAT_sectors proc near
                ; INPUT: DS:SI = Logical DOS Drv Parameters Table
                ; OUTPUT: STC => Error
                ; clc and DX:AX = Free FAT sectors
                ; Also, related parameters and FAT buffer will be reset and updated
                ; Erdogan Tan, 21-06-2009
   
		mov ax, word ptr [SI][LD_BPB][BPB_HiddSec]
		mov dx, word ptr [SI][LD_BPB][BPB_HiddSec]+2
                add ax, word ptr [SI][LD_BPB][BPB_RsvdSecCnt]
                adc dx, 0
                push dx
                push ax 
                mov al, byte ptr [SI][LD_BPB][BPB_NumFATs] 
                cbw                             
                mul word ptr [SI][LD_BPB][BPB_FATSz16]
                pop cx
                add ax, cx
                pop cx
                adc dx, cx
                push dx
                push ax
                mov ax, 20h   ; Size of a directory entry
                mul word ptr [SI][LD_BPB][BPB_RootEntCnt]
                add ax, 511
               ;adc dx, 0  
                mov cx, 512
                div cx
                pop cx
                add ax, cx
                pop dx
                adc dx, 0
                
                mov cx, word ptr [SI][LD_BPB][BPB_TotalSec16]
                cmp cx, 0
                jna short pass_gfc_use_TotalSec16
                sub ax, cx
                sbb dx, 0
                jmp short pass_gfc_use_TotalSec32 
pass_gfc_use_TotalSec16:
                mov cx, word ptr [SI][LD_BPB][BPB_TotalSec32]
                sub ax, cx
                mov cx, word ptr [SI][LD_BPB][BPB_TotalSec32]+2
                sbb dx, cx 
pass_gfc_use_TotalSec32:                
                xor ch, ch
                mov cl, byte ptr [SI][LD_BPB][BPB_SecPerClust]
                call Rx_Dos_Div32
                mov word ptr [SI][LD_Clusters], ax
                mov word ptr [SI][LD_Clusters]+2, dx 
                
                cmp byte ptr [SI][LD_FATType], 2
                jna short loc_gfc_get_fat_free_clusters

                mov ax, word ptr [SI][LD_StartSector]
                mov dx, word ptr [SI][LD_StartSector]+2
                add ax, word ptr [SI][LD_BPB][FAT32_FSInfoSec]
                adc dx, 0
               ;push ds
               ;pop es
                mov bx, offset DOSBootSectorBuff
                mov cx, 1
                call proc_disk_read
                jnc short loc_gfc_check_fsinfo_signs
retn_gfc_get_fsinfo_sec:
                retn
retn_gfc_get_fsinfo_stc:
                stc
                retn

loc_gfc_check_FSINFO_signs:
                cmp word ptr [DOSBootSectorBuff], 5252h
                jne short retn_gfc_get_fsinfo_stc
                mov word ptr [DOSBootSectorBuff]+2, 4161h
                jne short retn_gfc_get_fsinfo_stc
                mov bx, offset DOSBootSectorBuff
                add bx, 484
                cmp word ptr [BX], 7272h
                jne short retn_gfc_get_fsinfo_stc
                cmp word ptr [BX]+2, 6141h
                jne short retn_gfc_get_fsinfo_stc
                add bx, 4
                push word ptr [BX]
                pop ax
                push word ptr [BX]+2
                pop dx

	       ;mov word ptr [SI][LD_FreeSectors], ax
	       ;mov word ptr [SI][LD_FreeSectors]+2, dx

                jmp short retn_from_get_free_fat32_clusters

loc_gfc_get_fat_free_clusters:
                or dx, dx
                jnz short retn_gfc_get_fsinfo_stc
                mov ax, 2
                mov word ptr [FAT_CurrentCluster], ax
                mov word ptr [FAT_CurrentCluster]+2, dx

gfc_allocate_FAT_buffer:                
                mov byte ptr [FAT_BuffValidData], 0
                mov byte ptr [FAT_BuffDrvName], 0
                mov word ptr [FAT_BuffSector], 0
                mov word ptr [FAT_BuffSector]+2, 0  
               
                mov bx, word ptr [FAT_Buffer]
                cmp bx, 0
                ja short gfc_pass_allocate_FAT_buffer
                
                ; bx = 0 => Allocate the first free segment
                mov cx, 1536 ; FAT Buffer contains 3 FAT sectors 
                mov ax, 0103h ; Buffer, AL= 3, buffer allocation
                call proc_allocate_memory
                jc short pass_get_free_sectors_calc
                mov word ptr [FAT_Buffer], bx

gfc_pass_allocate_FAT_buffer:
                mov es, bx
                xor bx, bx 
read_gfc_FAT_sectors_again:
		mov ax, word ptr [SI][LD_BPB][BPB_HiddSec]
		mov dx, word ptr [SI][LD_BPB][BPB_HiddSec]+2
                add ax, word ptr [SI][LD_BPB][BPB_RsvdSecCnt]
                adc dx, 0
                mov cx, 3
                call proc_disk_read
                jnc short loc_gfc_FAT_start
                push ds
                pop es
pass_get_free_sectors_calc:
                retn            

loc_gfc_FAT_start:
                xor ax, ax
		mov word ptr [SI][LD_FreeSectors], ax
                mov word ptr [SI][LD_FreeSectors]+2, ax

 		mov ax, word ptr [FAT_CurrentCluster]
                mov dx, word ptr [FAT_CurrentCluster]+2

loc_gfc_loop_get_next_cluster:
                call proc_get_next_cluster
                jnc short loc_gfc_free_fat_clusters_cont
                cmp ax, 0
                jna short loc_gfc_pass_inc_free_cluster_count
 
retn_from_get_free_fat_clusters:
                mov ax, word ptr [SI][LD_FreeSectors]
                mov dx, word ptr [SI][LD_FreeSectors]+2
retn_from_get_free_fat32_clusters:
                xor bh, bh
                mov bl, byte ptr [SI][LD_BPB][BPB_SecPerClust]
                call proc_Mul32
                mov word ptr [SI][LD_FreeSectors], ax
		mov word ptr [SI][LD_FreeSectors]+2, dx

                push ds
                pop es

                retn

loc_gfc_free_fat_clusters_cont:
                cmp ax, 0
                ja short loc_gfc_pass_inc_free_cluster_count
                inc word ptr [SI][LD_FreeSectors]
                 
loc_gfc_pass_inc_free_cluster_count:
                mov ax, word ptr [FAT_CurrentCluster]
                mov dx, word ptr [FAT_CurrentCluster]+2
                
                cmp dx, word ptr [SI][LD_Clusters]+2
                ja short short retn_from_get_free_fat_clusters
                jb short pass_gfc_last_cluster_ax_check
                cmp ax, word ptr [SI][LD_Clusters]
                ja short short retn_from_get_free_fat_clusters
pass_gfc_last_cluster_ax_check:
                add ax, 1
                adc dx, 0
                mov word ptr [FAT_CurrentCluster], ax
                mov word ptr [FAT_CurrentCluster]+2, dx
                jmp short loc_gfc_loop_get_next_cluster

get_free_FAT_sectors endp


floppy_drv_init proc near
                ; 6-6-2009 
                ; INPUT -> dl = Drive Number (0,1)
                ; OUTPUT -> al = drive name,
                ;           ah = drive number
                mov byte ptr [fd_init_drv], dl
                mov si, offset Disk_fd0
                mov di, offset Logical_DOSDisks
                xor dh, dh
                test dl, dl
                jz short pass_drv_init_fd1
                add si, 40h
                add di, 100h
pass_drv_init_fd1:
                mov byte ptr [DI][LD_MediaChanged],0
                cmp byte ptr [SI][DPDType], 1
                jb short read_fd_boot_sector_retn
read_fd_boot_sector:
                push ds
                pop es
                mov cx, 4 ; Retry Count
read_fd_boot_sector_again:
                push cx
                mov cx, 1
                mov ax, 0201h    ; Read 1 sector
                mov bx, offset DOSBootSectorBuff
                int 13h
                pop cx
                jnc short use_fd_boot_sector_params
                loop read_fd_boot_sector_again
read_fd_boot_sector_stc_retn:
                stc
read_fd_boot_sector_retn:
                retn
use_fd_boot_sector_params:
               ;mov si, offset DOSBootSectorBuff
                mov si, bx

                cmp word ptr [SI][BS_Validation], 0AA55h
                jne short read_fd_boot_sector_stc_retn
                cmp word ptr [SI][bs_FS_Identifier], 'SF'
                jne pass_use_fsfd_boot_sector_params

                mov al, byte ptr [SI][bs_FS_LBA_Ready]
                mov byte ptr [DI][LD_FS_LBAYes], al
                mov ax, word ptr [SI][bs_FS_BytesPerSec]
                mov word ptr [DI][LD_FS_BytesPerSec], ax
                mov ax, word ptr [SI][bs_FS_MediaAttrib]
                mov word ptr [DI][LD_FS_MediaAttrib], ax
		mov ax, word ptr [SI][bs_FS_SecPerTrack]
                mov word ptr [DI][LD_FS_SecPerTrack], ax
                mov ax, word ptr [SI][bs_FS_UnDelDirD]
                mov dx, word ptr [SI][bs_FS_UnDelDirD]+2
                mov word ptr [DI][LD_FS_UnDelDirD], ax
                mov word ptr [DI][LD_FS_UnDelDirD]+2, dx
                mov ax, word ptr [SI][bs_FS_MATLocation]
                mov dx, word ptr [SI][bs_FS_MATLocation]+2
                mov word ptr [DI][LD_FS_MATLocation], ax
                mov word ptr [DI][LD_FS_MATLocation]+2, dx
                mov ax, word ptr [SI][bs_FS_RootDirD]
 		mov dx, word ptr [SI][bs_FS_RootDirD]+2
                mov word ptr [DI][LD_FS_RootDirD], ax
                mov word ptr [DI][LD_FS_RootDirD]+2, dx
 		mov ax, word ptr [SI][bs_FS_BeginSector]
 		mov dx, word ptr [SI][bs_FS_BeginSector]+2
                mov word ptr [DI][LD_FS_BeginSector], ax
                mov word ptr [DI][LD_FS_BeginSector]+2, dx  
                mov ax, word ptr [SI][bs_FS_VolumeSize]
 		mov dx, word ptr [SI][bs_FS_VolumeSize]+2
                mov word ptr [DI][LD_FS_VolumeSize], ax
                mov word ptr [DI][LD_FS_VolumeSize]+2, dx
		mov al, byte ptr [SI][bs_FS_SecPerTrack]
 		cbw
                mov word ptr [DI][LD_BPB][BPB_SecPerTrk], ax
                mov al, byte ptr [SI][bs_FS_Heads]
                mov word ptr [DI][LD_BPB][BPB_NumHeads], ax

                mov si, di
 		mov ax, word ptr [SI][LD_FS_MATLocation]
                mov dx, word ptr [SI][LD_FS_MATLocation]+2
read_fd_MAT_sector_again:
                ;mov bx, offset DOSBootSectorBuff
                mov cx, 1
                call proc_disk_read
                mov si, bx
                jnc short use_fdfs_mat_sector_params
                retn
                ;jc short read_fd_boot_sector_retn
use_fdfs_mat_sector_params:
 		mov ax, word ptr [SI][FS_MAT_DATLocation]
                mov dx, word ptr [SI][FS_MAT_DATLocation]+2                                  
 		mov word ptr [DI][LD_FS_DATLocation], ax
                mov word ptr [DI][LD_FS_DATLOcation]+2, dx

		mov ax, word ptr [SI][FS_MAT_DATScount]
                mov dx, word ptr [SI][FS_MAT_DATScount]+2                                  
 		mov word ptr [DI][LD_FS_DATSectors], ax
                mov word ptr [DI][LD_FS_DATSectors]+2, dx

                mov ax, word ptr [SI][FS_MAT_FreeSectors]
                mov dx, word ptr [SI][FS_MAT_FreeSectors]+2                                  
 		mov word ptr [DI][LD_FS_FreeSectors], ax
                mov word ptr [DI][LD_FS_FreeSectors]+2, dx

 		mov ax, word ptr [SI][FS_MAT_FirstFreeSector]
                mov dx, word ptr [SI][FS_MAT_FirstFreeSector]+2                                  
 		mov word ptr [DI][LD_FS_FirstFreeSector], ax
                mov word ptr [DI][LD_FS_FirstFreeSector]+2, dx

              	mov si, di
 		mov ax, word ptr [SI][LD_FS_RootDirD]
                mov dx, word ptr [SI][LD_FS_RootDirD]+2
read_fd_RDT_sector_again:
                ;mov bx, offset DOSBootSectorBuff
            	mov cx, 1
                call proc_disk_read
                mov si, bx
                jnc short use_fdfs_RDT_sector_params
                retn
                ;jc read_fd_boot_sector_retn
use_fdfs_RDT_sector_params:
                mov ax, word ptr [SI][FS_RDT_VolumeSerialNo]
                mov dx, word ptr [SI][FS_RDT_VolumeSerialNo]+2                                  
                mov word ptr [DI][LD_FS_VolumeSerial], ax
                mov word ptr [DI][LD_FS_VolumeSerial]+2, dx

                push di
                mov cx, 32
                add si, FS_RDT_VolumeName
                add di, LD_FS_VolumeName
                rep movsw
                pop si

                mov byte ptr [SI][LD_FATType], 0
                mov byte ptr [SI][LD_FSType], 0A1h  
                
                jmp loc_cont_use_fd_boot_sector_params

pass_use_fsfd_boot_sector_params:
		cmp byte ptr [SI][BS_BootSig], 29h
                jne read_fd_boot_sector_stc_retn
                cmp byte ptr [SI][BPB_Media], 0F0h
                jb  read_fd_boot_sector_retn

                push di
                add di, LD_BPB
                mov cx, 32
                rep movsw 
                pop si
                xor ax, ax
                mov Word Ptr [SI][LD_StartSector], AX
                mov Word Ptr [SI][LD_StartSector]+2,AX
                mov AX,Word Ptr [SI][LD_BPB][BPB_RsvdSecCnt]
                mov Word Ptr [SI][LD_FATBegin], AX
                mov Word Ptr [SI][LD_FATBegin]+2, 0
                mov AL,Byte Ptr [SI][LD_BPB][BPB_NumFATs] 
                cbw                             
                mul Word Ptr [SI][LD_BPB][BPB_FATSz16]
                add AX,Word Ptr [SI][LD_FATBegin]
                mov Word Ptr [SI][LD_ROOTBegin], AX
                mov Word Ptr [SI][LD_ROOTBegin]+2, 0
                mov Word Ptr [SI][LD_DATABegin], AX 
                mov Word Ptr [SI][LD_DATABegin]+2, 0
                mov AX,20h   ; Size of a directory entry
                mul Word Ptr [SI][LD_BPB][BPB_RootEntCnt]
                add AX,511
                mov cx,512
                div cx
                add Word Ptr [SI][LD_DATABegin], AX 
                adc Word Ptr [SI][LD_DATABegin]+2, 0 
                mov AX,Word Ptr [SI][LD_BPB][BPB_TotalSec16]
                mov Word Ptr [SI][LD_TotalSectors], AX
                mov Word Ptr [SI][LD_TotalSectors]+2,0
                sub ax,Word Ptr [SI][LD_DATABegin]
                xor dx,dx
                xor ch,ch
                mov cl,Byte Ptr [SI][LD_BPB][BPB_SecPerClust]
                div cx 
                mov word ptr [SI][LD_Clusters], AX
                mov word ptr [SI][LD_Clusters]+2, 0
                    ; Maximum Valid Cluster Number= AX +1
                    ; with 2 reserved clusters= AX +2
               
allocate_FAT12_buffer:                
                mov byte ptr [FAT_BuffValidData], 0
                mov byte ptr [FAT_BuffDrvName], 0
                mov word ptr [FAT_BuffSector], 0
                mov word ptr [FAT_BuffSector]+2, 0  
               
                mov bx, word ptr [FAT_Buffer]
                cmp bx, 0
                ja short pass_allocate_FAT12_buffer
                
                ; bx = 0 => Allocate the first free segment
                mov cx, 1536 ; FAT Buffer contains 3 FAT sectors 
                mov ax, 0103h ; Buffer, AL= 3, buffer allocation
                call proc_allocate_memory
                jc read_fd_boot_sector_retn
                mov word ptr [FAT_Buffer], bx

pass_allocate_FAT12_buffer:
                mov es, bx
                xor bx, bx 
read_fd_FAT_sectors_again:
                mov ax, word ptr [SI][LD_BPB][BPB_RsvdSecCnt]
                xor dx, dx
                mov cx, 3
                call proc_disk_read
                jnc short use_fd_FAT_sectors
                push ds
                pop es
                retn            
use_fd_FAT_sectors:
                call fd_init_calculate_free_clusters
                push ds
                pop es
                jnc short loc_cont_use_fd_boot_sector_params_FAT

                test ax, ax
                jz short loc_cont_use_fd_boot_sector_params_FAT
                stc
                retn 
                
loc_cont_use_fd_boot_sector_params_FAT:
                mov byte ptr [SI][LD_FATType], 1
                mov byte ptr [SI][LD_FSType], 1  
loc_cont_use_fd_boot_sector_params:
                mov al, byte ptr [fd_init_drv]
                mov byte ptr [SI][LD_DParamEntry], al
                mov byte ptr [SI][LD_PhyDrvNo], al
                mov ah, al
                add al, 'A'
                mov byte ptr [SI][LD_Name], al
                mov byte ptr [SI][LD_DiskType], 1
                mov byte ptr [SI][LD_LBAYes], 0
                mov byte ptr [SI][LD_PartitionEntry], 0
                mov byte ptr [SI][LD_MediaChanged], 1

                retn

fd_init_calculate_free_clusters:

                mov ax, word ptr [SI][LD_BPB][BPB_RsvdSecCnt]
                push ax
                mov al, byte ptr [SI][LD_BPB][BPB_NumFATs] 
                cbw                             
                mul word ptr [SI][LD_BPB][BPB_FATSz16]
                pop dx
                add dx, ax
                push dx
                mov ax, 20h   ; Size of a directory entry
                mul word ptr [SI][LD_BPB][BPB_RootEntCnt]
                add ax, 511
                mov cx, 512
                div cx
                pop dx
                add dx, ax 
                mov ax, word ptr [SI][LD_BPB][BPB_TotalSec16]
                sub ax, dx
                xor dx, dx
                xor ch, ch
                mov cl, byte ptr [SI][LD_BPB][BPB_SecPerClust]
                div cx 
                mov word ptr [SI][LD_Clusters], ax ; Clusters

                mov ax, 2
              ; mov dx, 0
                xor dx, dx 

                mov word ptr [FAT_CurrentCluster]+2, dx
               
fd_init_loop_get_next_cluster:
                call fd_init_get_next_cluster
		jnc short fd_init_free_fat_clusters
                cmp ax, 0
                jna short fd_init_pass_inc_free_cluster_count
 
retn_from_fd_init_calculate_free_clusters:

                mov ax, word ptr [SI][LD_FreeSectors]
                xor ch, ch
                mov cl, byte ptr [SI][LD_BPB][BPB_SecPerClust]
                mul cx
                mov word ptr [SI][LD_FreeSectors], ax

                retn

fd_init_free_fat_clusters:
                cmp ax, 0
                ja short fd_init_pass_inc_free_cluster_count
                inc word ptr [SI][LD_FreeSectors]
            
fd_init_pass_inc_free_cluster_count:
                mov ax, word ptr [FAT_CurrentCluster]
                mov dx, word ptr [FAT_CurrentCluster]+2
                
                cmp ax, word ptr [SI][LD_Clusters]
                ja short short retn_from_fd_init_calculate_free_clusters

                inc ax
                jmp short fd_init_loop_get_next_cluster

fd_init_get_next_cluster:
 		mov word ptr [FAT_CurrentCluster], ax
 
  		mov bx, 400h ;1024
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Buffer Entry Offset
                push ax
                mov ax, 3
                mul dx    ; Multiply by 3
                shr ax, 1 ; Divide by 2
                mov dx, ax
                pop ax
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Buffer Byte Offset
                ; AX = FAT Beginning Sector
                ; DX = 0
                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna load_FAT_sectors0
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne load_FAT_sectors0
                cmp ax, word ptr [FAT_BuffSector]
                jne load_FAT_sectors1

                mov ax, word ptr [FAT_CurrentCluster]
                shr ax, 1
                mov ax, word ptr [FAT_Buffer][BX]
                jnc get_FAT12_nc_even
                shr ax, 1
                shr ax, 1
                shr ax, 1
                shr ax, 1

fd_init_gnc_eoc_check:
                cmp al, 0F6h
                jna short fd_init_pass_gnc_eoc_check
                cmp ah, 0Fh
                jb short fd_init_pass_gnc_eoc_check
                xor ax, ax 
                stc
                retn
fd_init_pass_gnc_eoc_check:
                clc
                retn

fd_init_gnc_even:
                and ah,0Fh
                jmp short fd_init_gnc_eoc_check

fd_init_load_FAT_sectors0:
                mov byte ptr [FAT_BuffDrvName], cl
fd_init_load_FAT_sectors1:
                mov word ptr [FAT_BuffSector]+2, dx
                mov word ptr [FAT_BuffSector], ax
                add ax, word ptr [SI][LD_FATbegin]
               ;adc dx, word ptr [SI][LD_FATbegin]+2
               ;xor dx, dx 
                mov bx, word ptr [FAT_Buffer]
                mov es, bx
                xor bx, bx 
                mov cx, word ptr [SI][LD_BPB][FATsecs]
                sub cx, word ptr [FAT_BuffSector]
             
                and cx, 03h
                call proc_disk_read
                jnc short fd_init_FAT_sectors_no_load_error
                mov byte ptr [FAT_BuffValidData], 0
                mov ax, 1 ; Read Error
                ;mov dx, 0
                ;xor dx, dx 
                retn
fd_init_FAT_sectors_no_load_error:
                mov byte ptr [FAT_BuffValidData], 1
                mov ax, word ptr [FAT_CurrentCluster]
               ;mov dx, word ptr [FAT_CurrentCluster]+2
                jmp fd_init_get_next_cluster

fd_init_drv:   db 0

floppy_drv_init endp

HDCounter:     db 1

MasterBootBuff:
MasterBootCode: db 1BEh dup (?)
PartitionTable: db 64 dup (?)
MBIDCode: dw ?

PTable_Buffer:
PTable_hd0: db 64 dup (0)
PTable_hd1: db 64 dup (0)
PTable_hd2: db 64 dup (0)
PTable_hd3: db 64 dup (0)
PTable_ep0: db 64 dup (0)
PTable_ep1: db 64 dup (0)
PTable_ep2: db 64 dup (0)
PTable_ep3: db 64 dup (0)

DiskParams:
Disk_fd0: db 16 dup (0)
DAP_fd0: db 16 dup(0)
GDP_fd0: db 26 dup(0)
TRDP_fd0: db 6 dup(0)
Disk_fd1: db 16 dup (0)
DAP_fd1: db 16 dup(0)
GDP_fd1: db 26 dup(0)
TRDP_fd1: db 6 dup(0)
Disk_hd0: db 16 dup (0)
DAP_hd0: db 16 dup(0)
GDP_hd0: db 26 dup(0)
TRDP_hd0: db 6 dup(0)
Disk_hd1: db 16 dup (0)
DAP_hd1: db 16 dup(0)
GDP_hd1: db 26 dup(0)
TRDP_hd1: db 6 dup(0)
Disk_hd2: db 16 dup (0)
DAP_hd2: db 16 dup(0)
GDP_hd2: db 26 dup(0)
TRDP_hd2: db 6 dup(0)
Disk_hd3: db 16 dup (0)
DAP_hd3: db 16 dup(0)
GDP_hd3: db 26 dup(0)
TRDP_hd3: db 6 dup(0)
end_of_dparams_buff:

DOSBootSectorBuff:
db 512 dup(0)

Hard_Disk:         db 80h
Last_DOS_DiskNo:   db 0
HD_LBAYes:         dd 0

