; ****************************************************************************
; TRDOS386.ASM (TRDOS 386 Kernel - v2.0.0) - DRV INIT : trdosk2.s
; ----------------------------------------------------------------------------
; Last Update: 29/02/2016
; ----------------------------------------------------------------------------
; Beginning: 04/01/2016
; ----------------------------------------------------------------------------
; Assembler: NASM version 2.11 (trdos386.s)
; ----------------------------------------------------------------------------
; Derived from TRDOS Operating System v1.0 (8086) source code by Erdogan Tan
; TRDOS2.ASM (09/11/2011)
; ****************************************************************************
; DRV_INIT.ASM (c) 2009-2011 Erdogan TAN  [26/09/2009] Last Update: 07/08/2011
;

ldrv_init: ; Logical Drive Initialization
	; 12/02/2016
	; 06/01/2016
	;  	('diskinit.inc', 'diskio.inc' integration)
	; 04/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 07/08/2011
	; 20/09/2009
	; 2005
	movzx	ecx, byte [HF_NUM] ; number of fixed disks
	cmp	cl, 1
	jnb	short load_hd_partition_tables
	; No hard disks
	retn
load_hd_partition_tables:
	mov	esi, [HDPM_TBL_VEC] ; primary master disk FDPT
	mov 	edi, PTable_hd0
	mov 	dl, 80h
load_next_hd_partition_table:
	push	ecx
	push	edi
	push	esi ; FDPT (+ DPTE) address
	mov	al, [esi+20] ; DPTE offset 4
	and	al, 40h ;  LBA bit (bit 6)
	;shr	al, 6
	mov 	[HD_LBA_yes], al
	call	load_masterboot
	jc	short pass_pt_this_hard_disk

	mov	esi, PartitionTable
	mov	ebx, esi
	;mov	ecx, 16
	mov	cl, 16
	rep 	movsd
	mov 	esi, ebx 
	mov 	byte [hdc], 4 ; 4 - partition index
loc_validate_hdp_partition:
	cmp 	byte [esi+ptFileSystemID], 0
	jna	short loc_validate_next_hdp_partition2
	push	esi ; Masterboot partition table offset
	push	edx ; dl = Physical drive number 
	inc	byte [PP_Counter]
        xor	edi, edi ; 0  
	; Input -> ESI = PartitionTable offset
	; DL = Hard disk drive number 
	; EDI = 0 -> Primary Partition
	; EDI > 0 -> Extended Partition's Start Sector   
	call 	validate_hd_fat_partition
	jnc 	short loc_set_valid_hdp_partition_entry
	;pop	edx
	;push	edx
	mov	edx, [esp] 
	call	validate_hd_fs_partition
	jc	short loc_validate_next_hdp_partition1
loc_set_valid_hdp_partition_entry:
	mov 	cl, [Last_DOS_DiskNo] 
	add 	cl, 'A'
	; ESI = Logical dos drive description table address
	mov	[esi+LD_Name], cl
	mov	ah, [esi+LD_PhyDrvNo]
	mov	al, ah ; Physical drive number
	sub	al, 80h
	shl	al, 2
	add	al, 4 ; 0 Based
	sub	al, [hdc] ; 4 - partition index
	; AL = Partition entry/index, 0 based
	;  0 -> hd 0, Partition Table offset = 0
	; 15 -> hd 3, Partition Table offset = 3
	;mov	[esi+LD_PartitionEntry], al 
	sub 	ah, 7Eh
	; AH = Physical drive index, zero based
	;  0 for drive A:, 2 for drive C:
	;mov 	[esi+LD_DParamEntry], ah 
	mov 	[esi+LD_PartitionEntry], ax
loc_validate_next_hdp_partition1:
	pop 	edx ; dl = Physical drive number 
	pop	esi ; Masterboot partition table offset
loc_validate_next_hdp_partition2:
	; ESI = PartitionTable offset
	; DL = Hard/Fixed disk drive number
	dec	byte [hdc] ; 4 - partition index
	jz	short pass_pt_this_hard_disk
	add	esi, 16 ; 10h
	jmp	short loc_validate_hdp_partition
loc_next_hd_partition_table:
	inc	dl
	add	esi, 32 ; next FDPT address
	add	edi, 64 ; next partition table destination
        jmp     load_next_hd_partition_table
pass_pt_this_hard_disk:
	pop	esi ; FDPT (+ DPTE) address
	pop	edi ; Ptable_hd?
	pop	ecx
	loop	loc_next_hd_partition_table
	cmp	byte [PP_Counter], 1
	jnb	short load_extended_dos_partitions
	; Empty partition table
	retn 
load_extended_dos_partitions:
	mov	esi, PTable_hd0
	mov	edi, PTable_ep0
	mov	byte [hdc], 80h
next_hd_extd_partition:
	push	esi ; PTable_hd? offset
	push	edi ; PTable_ep?
	;mov	ecx, 4
	mov	cl, 4
	mov	dl, byte [hdc]
hd_check_fs_id_05h:
	mov	al, [esi+ptFileSystemID]
	cmp	al, 05h ; Is it an extended dos partition ?
	je	short loc_set_ep_start_sector
	cmp	al, 0Fh ; Is it an extended win4 (LBA mode) partition ?
	jne	short continue_to_check_ep
loc_set_ep_start_sector:
	inc	byte [EP_Counter]
	mov	ah, dl ; byte [hdc]
	xchg	ah, al ; al = Drv Number, ah = Partition Identifier
	push	eax 
	xor	ah, ah  
	sub	al, 80h
	push	eax
	shl	al, 2 ; al = al * 4
	movzx	ebx, al
	add	ebx, EP_StartSector
	mov	eax, [esi+ptStartSector]
        ; EAX = Extended partition's start sector
        mov	[ebx], eax
	pop	eax ; AL = Drv number - 80h, AH = 0 
	pop	edx ; DL = Drv number, DH = Partition ID
	mov	ebx, MasterBootBuff
	cmp	byte [HD_LBA_yes], 1 ; LBA ready = Yes
	jb	short loc_hd_load_ep_05h
	cmp	dh, 05h
	je	short loc_hd_load_ep_05h
loc_hd_load_ep_0Fh:
	; 04/01/2016
	push	ecx
	mov	ecx, [esi+ptStartSector] ; sector number
	;mov	ebx, MasterBootBuff ; buffer address
	; LBA read/write (with private LBA function) 
	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
	mov	ah, 1Bh ; LBA read
	mov	al, 1 ; sector count
	call	int13h
	pop	ecx
	jnc	short loc_hd_move_ep_table
continue_to_check_ep:
	add	esi, 16
	loop	hd_check_fs_id_05h
continue_check_ep_next_disk:
	pop	edi ; PTable_ep?
	pop	esi ; PTable_hd?
	mov	al, [HF_NUM] ; number of hard disks
	add	al, 7Fh
	cmp	[hdc], al
	jnb	loc_validating_hd_partitions_ok
	add	esi, 64
	add	edi, 64
	inc	byte [hdc]
	jmp	next_hd_extd_partition
loc_hd_load_ep_05h:
	push	ecx 
	mov	dh, [esi+ptBeginHead]
        mov     cx, word [esi+ptBeginSector]
	mov	ax, 0201h ; Read 1 sector
	;mov	ebx, MasterBootBuff
	call	int13h
	pop	ecx  
	jc	short continue_to_check_ep
loc_hd_move_ep_table:
        ;pop	edi
	;push	edi  ; PTable_ep?
	mov	edi, [esp]        
        mov	esi, PartitionTable ; Extended
	mov	ebx, esi
	;mov	ecx, 16
	mov	cl, 16
       	rep	movsd
	mov	esi, ebx 
loc_set_hde_sub_partition_count:
	mov	byte [PP_Counter], 4
loc_validate_hde_partition:
	cmp	byte [esi+ptFileSystemID], 0
	jna	short loc_validate_next_hde_partition2
	push	esi ; Extended partition table offset
	mov	dl, byte [hdc]
	movzx	eax, dl
	sub	al, 80h
	shl	al, 2
	; 06/01/2016 
	; (TRDOS v1.0 had a bug here, in 'DRV_INIT.ASM')
	; BUGFIX *
	;mov	ecx, eax
	mov	cl, al
	add	cl, 4
	sub	cl, [PP_Counter] ; 4 to 1
	; CL = Partition entry/index, 0 based
        ;  0 -> hd 0, Partition Table offset = 0
        ; 15 -> hd 3, Partition Table offset = 3
      	mov	ch, dl   
	sub	ch, 7Eh ;
	; CH = Physical drive index, zero based
	;  0 for drive A:, 2 for drive C:	
	; BUGFIX *
	push	ecx ; *
	mov	edi, EP_StartSector
	add	edi, eax
	; Input -> ESI = PartitionTable offset
	; DL = Hard disk drive number   
	; EDI = Extended partition start sector pointer
	call	validate_hd_fat_partition
	pop	ecx ; *
	jc	short loc_validate_next_hde_partition1
loc_set_valid_hde_partition_entry:
	; 06/01/2016 (TRDOS v2.0)
	; BUGFIX *
	;mov	[esi+LD_PartitionEntry], cl 
	;mov	[esi+LD_DParamEntry], ch 
	mov	[esi+LD_PartitionEntry], cx 
	;
	mov	cl, [Last_DOS_DiskNo] 
	add	cl, 'A'
	mov	[esi+LD_Name], cl
loc_validate_next_hde_partition1:
	pop	esi ; Extended partition table offset
loc_validate_next_hde_partition2:
	; ESI = Extended partition table offset
	; DL = Hard disk drive number
	dec	byte [PP_Counter]
	jz	continue_check_ep_next_disk
	add 	esi, 16 ; 10h
	jmp	short loc_validate_hde_partition
loc_validating_hd_partitions_ok:
	mov	al, [Last_DOS_DiskNo]
loc_drv_init_retn:
	retn

validate_hd_fat_partition:
	; 12/02/2016
	; 07/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 07/08/2011
	; 23/07/2011
	; Input
	;   DL = Hard/Fixed Disk Drive Number
	;   ESI = PartitionTable offset
	;   EDI = Extend. Part. Start Sector Pointer
	;   EDI = 0 -> Primary Partition 
	;   byte [Last_DOS_DiskNo]
 	; Output
	;  cf=0 -> Validated
	;   ESI = Logical dos drv desc. table
	;   EBX = FAT boot sector buffer
	;   byte [Last_DOS_DiskNo]
	;  cf=1 -> Not a valid FAT partition
	; EAX, EDX, ECX, EDI -> changed 
	
	;mov 	esi, PartitionTable
	mov 	ah, [esi+ptFileSystemID]
	cmp 	ah, 06h ; FAT16 CHS partition
	; 12/02/2016
	;jb	short loc_not_a_valid_fat_partition2
 	jnb	short vhdp_FAT16_32
	;
	cmp	ah, 04h ; FAT16 CHS partition (< 32MB)		
	jne	short loc_not_a_valid_fat_partition1
vhdp_FAT16_32:
	mov	al, 2
	je	short loc_set_valid_hd_partition_params
	cmp	ah, 0Eh ; FAT16 LBA partition
	ja	short loc_not_a_valid_fat_partition1
	je	short loc_set_valid_hd_partition_params

	inc	al ; 3
	cmp	ah, 0Bh ; FAT32 CHS partition 
	je	short loc_set_valid_hd_partition_params
	jb	short loc_not_a_valid_fat_partition2
	cmp	ah, 0Ch ; FAT32 LBA partition
	je	short loc_set_valid_hd_partition_params
loc_not_a_valid_fat_partition1:
	stc
loc_not_a_valid_fat_partition2:
	retn

loc_set_valid_hd_partition_params:
	inc 	byte [Last_DOS_DiskNo] ; > 1
	;
	xor	ebx, ebx
	mov	bh, [Last_DOS_DiskNo] ; * 256	
	add	ebx, Logical_DOSDisks
	;
	mov	byte [ebx+LD_DiskType], 2
	mov	byte [ebx+LD_PhyDrvNo], dl
	;mov	byte [ebx+LD_FATType], al ; 2 or 3
	;mov	byte [ebx+LD_FSType], ah ; 06h, 0Eh, 0Bh, 0Ch
	mov	word [ebx+LD_FATType], ax
	;
	mov	ecx, [esi+ptStartSector]
	or	edi, edi 
	jz	short pass_hd_FAT_ep_start_sector_adding
loc_add_hd_FAT_ep_start_sector:
	add	ecx, [edi]
pass_hd_FAT_ep_start_sector_adding:
	mov	[ebx+LD_StartSector], ecx
loc_hd_FAT_logical_drv_init:
	mov	ebp, ebx
	;mov	dl, [ebx+LD_PhyDrvNo]
	mov	al, [HD_LBA_yes] ; 07/01/2016
	mov	[ebx+LD_LBAYes], al
	mov	ebx, DOSBootSectorBuff ; buffer address
	or	al, al
	jz	short loc_hd_FAT_drv_init_load_bs_chs
loc_hd_FAT_drv_init_load_bs_lba:
	; DL = Physical drive number
   	;mov	ecx, [esi+ptStartSector] ; sector number
	;mov	ebx, DOSBootSectorBuff ; buffer address
	; LBA read/write (with private LBA function) 
	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
	mov	ah, 1Bh ; LBA read
	mov	al, 1 ; sector count
	call	int13h
	jnc	short loc_hd_drv_FAT_boot_validation
loc_not_a_valid_fat_partition3:
	retn
loc_hd_FAT_drv_init_load_bs_chs:
	mov	dh, [esi+ptBeginHead]
	mov	cx, [esi+ptBeginSector]
	mov	ax, 0201h ; Read 1 sector
	;mov	ebx, DOSBootSectorBuff
	call	int13h
	jc	short loc_not_a_valid_fat_partition3
loc_hd_drv_FAT_boot_validation:
	;mov	esi, DOSBootSectorBuff
	mov	esi, ebx
	cmp	word [esi+BS_Validation], 0AA55h
	jne	short loc_not_a_valid_fat_partition4
	cmp	byte [esi+BPB_Media], 0F8h
	jne	short loc_not_a_valid_fat_partition4
	cmp	word [esi+BPB_FATSz16], 0
	ja	short loc_hd_FAT16_BPB
	cmp	byte [esi+BS_FAT32_BootSig], 29h
	jne	short loc_not_a_valid_fat_partition4
loc_hd_FAT32_BPB:
	mov	ecx, 45
	jmp	short loc_hd_move_FAT_BPB
	;
loc_not_a_valid_fat_partition4:
	stc
	retn
	;
loc_hd_FAT16_BPB:
	cmp	byte [esi+BS_BootSig], 29h
	jne	short loc_not_a_valid_fat_partition4
	mov	ecx, 32
loc_hd_move_FAT_BPB:
	mov 	edi, ebp
	;mov	esi, ebx ; Boot sector
	push	edi
	add	edi, LD_BPB
	rep	movsw 
	pop	esi
	movzx	eax, word [esi+LD_BPB+BPB_RsvdSecCnt]
	add	eax, [esi+LD_StartSector]
	mov	[esi+LD_FATBegin], eax
	cmp	byte [esi+LD_FATType], 3
	jb	short loc_set_FAT16_RootDirLoc
loc_set_FAT32_RootDirLoc:
	mov	eax, [esi+LD_BPB+BPB_FATSz32]
        movzx	ebx, byte [esi+LD_BPB+BPB_NumFATs]
	mul	ebx
	add	eax, [esi+LD_FATBegin]
loc_set_FAT32_data_begin:
	mov	[esi+LD_DATABegin], eax
	mov	[esi+LD_ROOTBegin], eax
	; If Root Directory Cluster <> 2 then
	; change the beginning sector value 
	; of the root dir by adding sector offset.
	mov	eax, [esi+LD_BPB+BPB_RootClus]
	sub	eax, 2
	jz	short short loc_set_32bit_FAT_total_sectors  
	;movzx	ebx, byte [esi+LD_BPB+BPB_SecPerClust]
	mov	bl, byte [esi+LD_BPB+BPB_SecPerClust] 
	mul	ebx
	add	[esi+LD_ROOTBegin], eax
	jmp	short loc_set_32bit_FAT_total_sectors
	;
loc_set_FAT16_RootDirLoc:
	movzx	eax, byte [esi+LD_BPB+BPB_NumFATs]
	movzx	edx, word [esi+LD_BPB+BPB_FATSz16]
	mul	edx
	add	eax, [esi+LD_FATBegin]  
	mov	[esi+LD_ROOTBegin], eax
loc_set_FAT16_data_begin:
	mov	[esi+LD_DATABegin], eax 
	mov	eax, 20h  ; Size of a directory entry
	;movzx	edx, word [esi+LD_BPB+BPB_RootEntCnt]
        mov     dx, [esi+LD_BPB+BPB_RootEntCnt]
        mul	edx
	;mov	ecx, 511
	mov	cx, 511
	add	eax, ecx
	inc	ecx ; 512
	div	ecx
	add	[esi+LD_DATABegin], eax
	movzx	eax, word [esi+LD_BPB+BPB_TotalSec16]
	test	ax, ax
	jz	short loc_set_32bit_FAT_total_sectors
loc_set_16bit_FAT_total_sectors:
	mov	[esi+LD_TotalSectors], eax
	jmp	short loc_set_hd_FAT_cluster_count
loc_set_32bit_FAT_total_sectors:
	mov	eax, [esi+LD_BPB+BPB_TotalSec32]
	mov	[esi+LD_TotalSectors], eax
loc_set_hd_FAT_cluster_count:
	mov	edx, [esi+LD_DATABegin]
	sub	edx, [esi+LD_StartSector]
	sub	eax, edx
	xor	edx, edx ; 0
        movzx   ecx, byte [esi+LD_BPB+BPB_SecPerClust]
        div	ecx 
	mov	[esi+LD_Clusters], eax
	; Maximum Valid Cluster Number= EAX +1
	; with 2 reserved clusters= EAX +2
loc_set_hd_FAT_fs_free_sectors:
	;mov	dword [esi+LD_FreeSectors], 0
	call	get_free_FAT_sectors
	jc	short loc_validate_hd_FAT_partition_retn
	mov	[esi+LD_FreeSectors], eax
	mov	byte [esi+LD_MediaChanged], 6  ; Volume Name Reset
	;mov	cl, [Last_DOS_DiskNo] 
	;add	cl, 'A'
	;mov	[esi+LD_FS_Name], cl

loc_validate_hd_FAT_partition_retn:         
	retn

validate_hd_fs_partition:
	; 13/02/2016
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 29/01/2011
	; 23/07/2011
	; Input
	;   DL = Hard/Fixed Disk Drive Number
	;   ESI = PartitionTable offset
	;   byte [Last_DOS_DiskNo]
	; Output
	;  cf=0 -> Validated
	;   ESI = Logical dos drv desc. table
	;   EBX = Singlix FS boot sector buffer
	;   byte [Last_DOS_DiskNo]
	;  cf=1 -> Not a valid 'Singlix FS' partition
	; EAX, EDX, ECX, EDI -> changed 

	;mov	esi, PartitionTable
	mov	ah, [esi+ptFileSystemID]
	cmp	ah, 0A1h ; SINGLIX FS1 (trfs1) partition
	jne	short loc_validate_hd_fs_partition_stc_retn
loc_set_valid_hd_fs_partition_params:
	inc	byte [Last_DOS_DiskNo] ; > 1
	xor	al, al ; mov al, 0
	;mov	[drv], dl
	sub	ebx, ebx ; 0
	mov	bh, [Last_DOS_DiskNo] 
	add	ebx, Logical_DOSDisks
	mov	byte [ebx+LD_DiskType], 2
	mov	[ebx+LD_PhyDrvNo], dl
	;mov	[ebx+LD_FATType], al ; 0
	;mov	[ebx+LD_FSType], ah
	mov	[ebx+LD_FATType], ax
	;mov	eax, [esi+ptStartSector]
	;mov	[ebx+LD_StartSector], eax
loc_hd_fs_logical_drv_init:
	mov	ebp, ebx ; 10/01/2016
	;mov	dl, [ebx+LD_PhyDrvNo]
	mov	al, [HD_LBA_yes] ; 10/01/2016
	mov	[ebx+LD_LBAYes], al
	mov	esi, ebx
	mov	ebx, DOSBootSectorBuff ; buffer addressh
	or	al, al
	jnz	short loc_hd_fs_drv_init_load_bs_lba
loc_hd_fs_drv_init_load_bs_chs:
	mov	dh, [esi+ptBeginHead]
	mov	cx, [esi+ptBeginSector]
	mov	ax, 0201h ; Read 1 sector
	;mov	ebx, DOSBootSectorBuff
	call	int13h
	jnc	short loc_hd_drv_fs_boot_validation
loc_validate_hd_fs_partition_err_retn:
	retn
loc_validate_hd_fs_partition_stc_retn:
	stc
	retn
loc_hd_fs_drv_init_load_bs_lba:
	; DL = Physical drive number
	;mov	esi, ebx
   	mov	ecx, [esi+ptStartSector] ; sector number
	;mov	ebx, DOSBootSectorBuff ; buffer address
	; LBA read/write (with private LBA function) 
	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
	mov	ah, 1Bh ; LBA read
	mov	al, 1 ; sector count
	call	int13h
	jc	short loc_validate_hd_fs_partition_err_retn
loc_hd_drv_fs_boot_validation:
	;mov	esi, DOSBootSectorBuff
	mov	esi, ebx ; Boot sector buffer
	cmp	word [esi+BS_Validation], 0AA55h
	jne	short loc_validate_hd_fs_partition_stc_retn
        ;
	;Singlix FS Extensions to TR-DOS (7/6/2009) 
	cmp	word [esi+bs_FS_Identifier], 'SF'
	jne	short loc_validate_hd_fs_partition_stc_retn
        ;'A1h' check is not necessary
	;  if 'FS' check is passed as OK/Yes.
	cmp	byte [esi+bs_FS_PartitionID], 0A1h
	jne	short loc_validate_hd_fs_partition_stc_retn
	;
	mov	edi, ebp ; 10/01/2016
	;
	mov	al, byte [esi+bs_FS_LBA_Ready]
	mov	[edi+LD_FS_LBAYes], al
	;
	; 03/01/2010 CHS -> DOS FAT/BPB compatibility fix
	mov	al, [esi+bs_FS_MediaAttrib]
	mov	byte [edi+LD_FS_MediaAttrib], al
	;
	mov	al, [esi+bs_FS_VersionMaj]
	mov	[edi+LD_FS_VersionMajor], al
	;
	mov	ax, [esi+bs_FS_BytesPerSec]
	mov	[edi+LD_FS_BytesPerSec], ax
	mov	al, [esi+bs_FS_SecPerTrack]
	cbw
	mov	[edi+LD_FS_SecPerTrack], ax
	mov	al, [esi+bs_FS_Heads]
	;cbw
	mov	[edi+LD_FS_NumHeads], ax
	;
	mov	eax, [esi+bs_FS_UnDelDirD]
	mov	[edi+LD_FS_UnDelDirD], eax
	mov	edx, [esi+bs_FS_MATLocation]
	mov	[edi+LD_FS_MATLocation], edx
	mov	eax, [esi+bs_FS_RootDirD]
	mov	[edi+LD_FS_RootDirD], eax
	mov	eax, [esi+bs_FS_BeginSector]
	mov	[edi+LD_FS_BeginSector], eax
	mov	eax, [edi+bs_FS_VolumeSize]
	mov	[edi+LD_FS_VolumeSize], eax
	;
	mov	eax, edx ; [edi+LD_FS_MATLocation]
	add	eax, [edi+LD_FS_BeginSector]
	mov	esi, edi
mread_hd_fs_MAT_sector:
       ;mov	ebx, DOSBootSectorBuff
	mov	ecx, 1
	call	disk_read
	jc	short loc_validate_hd_fs_partition_retn
	; EDI will not be changed
	mov	esi, ebx
use_hdfs_mat_sector_params:
	mov	eax, [esi+FS_MAT_DATLocation]
	mov	[edi+LD_FS_DATLocation], eax
	mov	eax, [esi+FS_MAT_DATScount]
	mov	[edi+LD_FS_DATSectors], eax
	mov	eax, [esi+FS_MAT_FreeSectors]
        mov     [edi+LD_FS_FreeSectors], eax
	mov	eax, [esi+FS_MAT_FirstFreeSector]
	mov	[edi+LD_FS_FirstFreeSector], eax
	mov	eax, [edi+LD_FS_RootDirD]
	add	eax, [edi+LD_FS_BeginSector]
	mov	esi, edi   
read_hd_fs_RDT_sector:
	mov	ebx, DOSBootSectorBuff
	;mov	ecx, 1
	mov	cl, 1
	call	disk_read
	jc	short loc_validate_hd_fs_partition_retn
	; EDI will not be changed
	mov	esi, ebx
use_hdfs_RDT_sector_params:
	mov	eax, [esi+FS_RDT_VolumeSerialNo]
	mov	[edi+LD_FS_VolumeSerial], eax
	push	edi
	;mov	ecx, 16
	mov	cl, 16
	add	esi, FS_RDT_VolumeName
	add	edi, LD_FS_VolumeName
	rep	movsd ; 64 bytes
	pop	esi
		; Volume Name Reset
        mov     byte [esi+LD_FS_MediaChanged], 6
	;
        ;mov	cl, [Last_DOS_DiskNo] 
	;add	cl, 'A'
	;mov	[esi+LD_FS_Name], cl

loc_validate_hd_fs_partition_retn:
	retn

load_masterboot:
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 2005 - 2011
	; input -> DL = drive number
	mov	ah, 0Dh ; Alternate disk reset
	call	int13h
	jnc	short pass_reset_error
harddisk_error:
  	retn
pass_reset_error:
	mov	ebx, MasterBootBuff
	mov	ax, 0201h
	mov	cx, 1
	xor	dh, dh
 	call	int13h
	jc	short harddisk_error
	;
	cmp	word [MBIDCode], 0AA55h
	je	short load_masterboot_ok
	stc
load_masterboot_ok:
	retn

get_free_FAT_sectors:
	; 29/02/2016
	; 13/02/2016
	; 04/02/2016
	; 07/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 11/07/2010
	; 21/06/2009
	; INPUT: ESI = Logical DOS Drive Description Table address
	; OUTPUT: STC => Error
        ;	cf = 0 and EAX = Free FAT sectors
	; Also, related parameters and FAT buffer will be reset and updated

	xor	eax, eax
	;mov	[esi+LD_FreeSectors], eax ; Reset
	
        cmp     byte [esi+LD_FATType], 2
	jna	short loc_gfc_get_fat_free_clusters

	; 29/02/2016
	dec	eax ; 0FFFFFFFFh
	mov	[esi+LD_BPB+BPB_Reserved], eax ; Free cluster count (reset)
	mov	[esi+LD_BPB+BPB_Reserved+4], eax ; First Free Cluster (reset)
	inc	eax ; 0
	;
	mov	ax, [esi+LD_BPB+BPB_FSInfo]
	add	eax, [esi+LD_StartSector]

	mov	ebx, DOSBootSectorBuff
	mov	ecx, 1
 	call	disk_read
	jnc	short loc_gfc_check_fsinfo_signs
retn_gfc_get_fsinfo_sec:
	retn

loc_gfc_check_fsinfo_signs:
	mov 	ebx, DOSBootSectorBuff ; 13/02/2016
        cmp     dword [ebx], 41615252h
	jne	short retn_gfc_get_fsinfo_stc
	;add	ebx, 484
	;cmp	dword [ebx], 61417272h
	cmp	dword [ebx+484], 61417272h
	jne	short retn_gfc_get_fsinfo_stc
	;add	ebx, 4
	;mov	eax, [ebx]
	mov	eax, [ebx+488]
	; 29/02/2016
	mov	[esi+LD_BPB+BPB_Reserved], eax ; Free cluster count
	mov	edx,  [ebx+492] 
	mov	[esi+LD_BPB+BPB_Reserved+4], eax ; First Free Cluster
	;
	jmp	short retn_from_get_free_fat32_clusters

retn_gfc_get_fsinfo_stc:
	stc
	retn

loc_gfc_get_fat_free_clusters:
	;mov	eax, 2
	mov	al, 2
	;mov	[FAT_CurrentCluster], eax
loc_gfc_loop_get_next_cluster:
	call	get_next_cluster
	jnc	short loc_gfc_free_fat_clusters_cont
	and	eax, eax
	jz	short loc_gfc_pass_inc_free_cluster_count
 
retn_from_get_free_fat_clusters:
	mov	eax, [esi+LD_FreeSectors] ; Free clusters !
retn_from_get_free_fat32_clusters:
        movzx	ebx, byte [esi+LD_BPB+BPB_SecPerClust]
      	mul	ebx
	;mov	[esi+LD_FreeSectors], eax ; Free sectors
retn_get_free_sectors_calc:
	retn

loc_gfc_free_fat_clusters_cont:
	or	eax, eax
	jnz	short loc_gfc_pass_inc_free_cluster_count
	inc	dword [esi+LD_FreeSectors] ; Free clusters !
   
loc_gfc_pass_inc_free_cluster_count:
	;mov	eax, [FAT_CurrentCluster]
	mov	eax, ecx ; [FAT_CurrentCluster]
	cmp	eax, [esi+LD_Clusters]
	ja	short retn_from_get_free_fat_clusters
	inc	eax
	;mov	[FAT_CurrentCluster], eax
	jmp	short loc_gfc_loop_get_next_cluster

floppy_drv_init:
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 24/07/2011
	; 04/07/2009
	; INPUT ->
	;	DL = Drive number (0,1)
	; OUTPUT ->
	;	BL = drive name
	;	BH = drive number
	;	ESI = Logical DOS drv description table
	;	EAX = Volume serial number
 
	mov	esi, fd0_type ; 10/01/2016
	mov	edi, Logical_DOSDisks
	or	dl, dl
	jz	short loc_drv_init_fd0_fd1
	add	edi, 100h
	inc	esi ; fd1_type ; 10/01/2016
loc_drv_init_fd0_fd1:
	mov	byte [edi+LD_MediaChanged], 0
	cmp	byte [esi], 1 ; type (>0 if it is existing) 
		; 4 = 1.44 MB, 80 track, 3 1/2"
	jb	short read_fd_boot_sector_retn
	mov	[edi+LD_PhyDrvNo], dl
read_fd_boot_sector:
	xor	dh, dh
	mov	ecx, 4 ; Retry Count
read_fd_boot_sector_again:
	push 	ecx
	;mov	cx, 1
	mov	cl, 1
	mov	ax, 0201h ; Read 1 sector
	mov	ebx, DOSBootSectorBuff
	call	int13h
	pop	ecx
	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	esi, DOSBootSectorBuff
	mov	esi, ebx
	cmp	word [esi+BS_Validation], 0AA55h
	jne	short read_fd_boot_sector_stc_retn
        cmp     word [esi+bs_FS_Identifier], 'SF'
        jne     use_fd_fatfs_boot_sector_params
	;
	mov	al, [esi+bs_FS_LBA_Ready]
	mov	[edi+LD_FS_LBAYes], al
	;
	; 03/01/2010 CHS -> DOS FAT/BPB compatibility fix
	mov	al, [esi+bs_FS_MediaAttrib]
	mov	[edi+LD_FS_MediaAttrib], al
	;
        mov	al, [esi+bs_FS_VersionMaj]
	mov	byte [edi+LD_FS_VersionMajor], al
	mov	ax, [esi+bs_FS_BytesPerSec]
	mov	[edi+LD_FS_BytesPerSec], ax
	mov	al, [esi+bs_FS_SecPerTrack]
	cbw
	mov	[edi+LD_FS_SecPerTrack], ax
	mov	al, [esi+bs_FS_Heads]
	;cbw
	mov	[edi+LD_FS_NumHeads], ax
	;
	mov	eax, [esi+bs_FS_UnDelDirD]
	mov	[edi+LD_FS_UnDelDirD], eax
	mov	eax, [esi+bs_FS_MATLocation]
	mov	[edi+LD_FS_MATLocation], eax
	mov	eax, [esi+bs_FS_RootDirD]
	mov	[edi+LD_FS_RootDirD], eax
	mov	eax, [esi+bs_FS_BeginSector]
	mov	[edi+LD_FS_BeginSector], eax
	mov	eax, [esi+bs_FS_VolumeSize]
	mov	[edi+LD_FS_VolumeSize], eax
	;		
	mov	esi, edi
 	mov	eax, [esi+LD_FS_MATLocation]
	;add	eax, [edi+LD_FS_BeginSector]
read_fd_MAT_sector_again:
	;mov	ebx, DOSBootSectorBuff
	;mov	ecx, 1
	mov	cl, 1
	call	chs_read
	mov	esi, ebx
	jnc	short use_fdfs_mat_sector_params
	;jmp	short read_fd_boot_sector_retn
	retn
use_fdfs_mat_sector_params:
	mov	eax, [esi+FS_MAT_DATLocation]
	mov	[edi+LD_FS_DATLocation], eax
	mov	eax, [esi+FS_MAT_DATScount]
	mov	[edi+LD_FS_DATSectors], eax
	mov	eax, [edi+FS_MAT_FreeSectors]
	mov	[edi+LD_FS_FreeSectors], eax
	mov	eax, [esi+FS_MAT_FirstFreeSector]
	mov	[edi+LD_FS_FirstFreeSector], eax
	;
	mov	esi, edi
 	mov	eax, [esi+LD_FS_RootDirD]
read_fd_RDT_sector_again:
	;mov	ebx, DOSBootSectorBuff
	;mov	cx, 1
	mov	cl, 1
	call	chs_read
	mov	esi, ebx
	jc	short read_fd_RDT_sector_retn
use_fdfs_RDT_sector_params:
	mov	eax, [esi+FS_RDT_VolumeSerialNo]
	mov	[edi+LD_FS_VolumeSerial], eax
	push	edi
	;mov	ecx, 16
	mov	cl, 16	
	add	esi, FS_RDT_VolumeName
	add	edi, LD_FS_VolumeName
	rep	movsd ; 64 bytes
	pop	esi
	mov	byte [esi+LD_FATType], 0
	mov	byte [esi+LD_FSType], 0A1h  
        jmp     loc_cont_use_fd_boot_sector_params

read_fd_RDT_sector_stc_retn:
	stc
read_fd_RDT_sector_retn:
	retn

use_fd_fatfs_boot_sector_params:
	cmp	byte [esi+BS_BootSig], 29h
	jne	short read_fd_RDT_sector_stc_retn
	cmp	byte [esi+BPB_Media], 0F0h
	jb	short read_fd_RDT_sector_retn
	push	edi
	add	edi, LD_BPB
	;mov	ecx, 16
	mov	cl, 16
	rep	movsd ; 64 bytes 
	pop	esi
	xor	eax, eax
	mov	[esi+LD_StartSector], eax ; 0
	mov	ax, [esi+LD_BPB+BPB_FATSz16]
	mov	cl, [esi+LD_BPB+BPB_NumFATs] 
  	mul	ecx
	; edx = 0 !
	mov	dx, [esi+LD_BPB+BPB_RsvdSecCnt]
	mov	[esi+LD_FATBegin], dx
	;add	eax, edx
	add	ax, dx
	mov	[esi+LD_ROOTBegin], eax
	mov	[esi+LD_DATABegin], eax 
	mov	dx, [esi+LD_BPB+BPB_RootEntCnt]
	;shl	edx, 5 ; * 32 (Size of a directory entry)
	shl	dx, 5
	;add	edx, 511
	add	dx, 511
	;shr	edx, 9 ; edx = ((edx*32)+511) / 512
	shr	dx, 9
	add 	[esi+LD_DATABegin], edx
	;movzx	eax, word [esi+LD_BPB+BPB_TotalSec16]
	mov	ax, [esi+LD_BPB+BPB_TotalSec16]
	mov	[esi+LD_TotalSectors], eax
	sub	eax, [esi+LD_DATABegin]
  	;movzx	ecx, byte [esi+LD_BPB+BPB_SecPerClust]
	mov	cl, [esi+LD_BPB+BPB_SecPerClust]  
	cmp	cl, 1
	jna	short save_fd_fatfs_cluster_count
	;sub	edx, edx
	sub	dx, dx ; 0
	div	ecx
save_fd_fatfs_cluster_count:
	mov	[esi+LD_Clusters], eax

      ; Maximum Valid Cluster Number = EAX +1
      ; with 2 reserved clusters= EAX +2
 
reset_FAT_buffer_decriptors:
	sub	eax, eax ; 0  
	mov	[FAT_BuffValidData], al ; 0
	mov	[FAT_BuffDrvName], al ; 0
	mov	[FAT_BuffSector], eax ; 0

read_fd_FAT_sectors:
  	mov	ebx, FAT_Buffer
	mov	ax, [esi+LD_BPB+BPB_RsvdSecCnt]
	;mov	ecx, 3
	mov	cl, 3 ; 3 sectors
	call	chs_read
	jc	short read_fd_FAT_sectors_retn
use_fd_FAT_sectors:
	mov	al, [esi+LD_PhyDrvNo]
	add	al, 'A' 
	mov	[FAT_BuffDrvName], al 
 	mov	byte [FAT_BuffValidData], 1
	call	fd_init_calculate_free_clusters
	jc	short read_fd_FAT_sectors_retn
  
loc_use_fd_boot_sector_params_FAT:
	mov	byte [esi+LD_FATType], 1 ; FAT 12
	mov	byte [esi+LD_FSType], 1
        mov     eax, [esi+LD_BPB+VolumeID]
loc_cont_use_fd_boot_sector_params:
	mov	bh, [esi+LD_PhyDrvNo]
	mov	[esi+LD_DParamEntry], bh
	mov	bl, bh
	add	bl, 'A'
	mov	byte [esi+LD_Name], bl
	mov	byte [esi+LD_DiskType], 1
	mov	byte [esi+LD_LBAYes], 0
	mov	byte [esi+LD_PartitionEntry], 0
	mov	byte [esi+LD_MediaChanged], 6 ; Volume Name Reset

read_fd_FAT_sectors_retn:
	retn   

fd_init_calculate_free_clusters:
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 04/07/2009
	; INPUT ->
	;     ESI = Logical DOS drive description table address
	; OUTPUT ->
	;    [ESI+LD_FreeSectors] will be set
	
	sub	eax, eax
	mov	[esi+LD_FreeSectors], eax ; 0
	mov	al, 2 ; eax = 2

fd_init_loop_get_next_cluster:
	call	fd_init_get_next_cluster
	jc	short fd_init_calculate_free_clusters_retn

fd_init_free_fat_clusters:
	;cmp 	eax, 0
	;ja	short fd_init_pass_inc_free_cluster_count
	;and	eax, eax
	;jnz	short fd_init_pass_inc_free_cluster_count
	and	ax, ax
	jnz	short fd_init_pass_inc_free_cluster_count
	;inc	dword [esi+LD_FreeSectors]
        inc	word [esi+LD_FreeSectors]
    
fd_init_pass_inc_free_cluster_count:
  	;mov	eax, [FAT_CurrentCluster]
	mov	ax, [FAT_CurrentCluster]
	;cmp	eax, [esi+LD_Clusters]
	cmp	ax, [esi+LD_Clusters]
	ja	short short retn_from_fd_init_calculate_free_clusters
	;inc	eax
	inc	ax
	jmp	short fd_init_loop_get_next_cluster

retn_from_fd_init_calculate_free_clusters:
  	mov	al, [esi+LD_BPB+BPB_SecPerClust]
  	cmp	al, 1
	jna	short fd_init_calculate_free_clusters_retn
	;movzx	eax, al
	cbw
	;mov	ecx, [esi+LD_FreeSectors]
	mov	cx, [esi+LD_FreeSectors] ; Count of free clusters
  	;mul	ecx
	mul	cx
	;mov	[esi+LD_FreeSectors], eax
	mov	[esi+LD_FreeSectors], ax
fd_init_calculate_free_clusters_retn:
	retn

fd_init_get_next_cluster:
	; 04/02/2016
	; 02/02/2016
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 04/07/2009
	; INPUT ->
	;    EAX = Current cluster
	;    ESI = Logical DOS drive description table address
	;    EDX = 0
	; OUTPUT ->
	;    EAX = Next cluster

	mov	[FAT_CurrentCluster], eax
fd_init_get_next_cluster_readnext:
	sub	edx, edx ; 0
  	mov	ebx, 1024 ; 400h
  	div	ebx
  	; EAX = Count of 3 FAT sectors
  	; EDX = Buffer entry index
	mov	ecx, eax
	;mov	eax, 3
	mov	al, 3
	mul	edx ; Multiply by 3
	shr	ax, 1 ; Divide by 2
	mov	ebx, eax ; Buffer byte offset
	add	ebx, FAT_Buffer
	mov	eax, ecx
	;mov	edx, 3
	mov	dx, 3
	mul	edx 
  	; EAX = FAT Beginning Sector
	; EDX = 0
	mov	cl, [esi+LD_Name]
	;cmp	byte [FAT_BuffValidData], 0
	;jna	short fd_init_load_FAT_sectors0
	cmp	cl, [FAT_BuffDrvName]
	jne	short fd_init_load_FAT_sectors0
	cmp	eax, [FAT_BuffSector]
	jne	short fd_init_load_FAT_sectors1
	;mov	eax, [FAT_CurrentCluster]
	mov	al, [FAT_CurrentCluster]
	;shr	eax, 1
	shr	al, 1
	mov	ax, [ebx]
  	jnc	short fd_init_gnc_even
	shr	ax, 4
fd_init_gnc_clc_retn:
	clc
	retn

fd_init_gnc_even:
	and	ah, 0Fh
	retn

fd_init_load_FAT_sectors0:
	mov 	[FAT_BuffDrvName], cl
fd_init_load_FAT_sectors1:
	mov	byte [FAT_BuffValidData], 0
	mov	[FAT_BuffSector], eax
	add	eax, [esi+LD_FATBegin]
 	mov	ebx, FAT_Buffer
	;movzx	ecx, word [esi+LD_BPB+BPB_FATSz16]
	mov	cx, [esi+LD_BPB+BPB_FATSz16]
	sub	cx, [FAT_BuffSector]
        ;cmp	ecx, 3
	cmp	cx, 3
	jna	short fdinit_pass_fix_sector_count_3
	;mov	ecx, 3
	mov	ecx, 3
fdinit_pass_fix_sector_count_3:  
	call	chs_read
	jnc	short fd_init_FAT_sectors_no_load_error
	mov	byte [FAT_BuffValidData], 0
		; Drv not ready or read Error !
	mov	eax, ERR_DRV_NOT_RDY ; 15
	;xor	edx, edx
	retn

fd_init_FAT_sectors_no_load_error:
	mov	byte [FAT_BuffValidData], 1
	mov	eax, [FAT_CurrentCluster]
        jmp     fd_init_get_next_cluster_readnext

get_FAT_volume_name:
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 12/09/2009
	; INPUT ->
	;	BH = Logical DOS drive number (0,1,2,3,4 ...)
	;       BL = 0
	; OUTPUT ->
	;	CF = 0 -> ESI = Volume name address
	; 	CF = 1 -> Root volume name not found

	;mov 	ah, 0FFh
	;mov 	al, [Last_Dos_DiskNo]
	;cmp 	al, bh
	;jb     short loc_gfvn_dir_load_err

	mov	esi, ebx
	and	esi, 0FF00h ; esi = bh
	add	esi, Logical_DOSDisks
	mov     al, [esi+LD_Name]
	mov     ah, [esi+LD_FATType]
	cmp     ah, 1
	jb    	short loc_gfvn_dir_load_err
	cmp 	al, 'A'
	jb      short loc_gfvn_dir_load_err
	cmp 	ah, 2 
	ja      short get_FAT32_root_cluster
	
	call    load_FAT_root_directory
	jnc     short loc_get_volume_name

loc_gfvn_dir_load_err:
	retn

get_FAT32_root_cluster:
	mov	eax, [esi+LD_BPB+BPB_RootClus]
	call    load_FAT_sub_directory
	jc	short loc_get_volume_name_retn

loc_get_volume_name:
        mov     esi, Directory_Buffer
	xor	cx, cx ; 0
check_root_volume_name:
	mov	al, [esi]
	or      al, al
	jz      short loc_get_volume_name_retn
	cmp     byte [esi+0Bh], 08h
	je      short loc_get_volume_name_retn
	cmp     cx, [DirBuff_LastEntry]
	jnb     short pass_check_root_volume_name
	inc     cx
	add     esi, 32
	jmp     short check_root_volume_name

loc_get_volume_name_retn:
	retn
    
pass_check_root_volume_name:
	cmp	byte [DirBuff_FATType], 3
	jb	short loc_get_volume_name_retn_xor

	mov	ebx, FAT_Buffer
	mov	esi, Logical_DOSDisks
	xor	eax, eax
	mov	ah, [DirBuff_DRV]
	sub	ah, 'A' 
	add	esi, eax
	mov	eax, [DirBuff_Cluster]
	call	get_next_cluster
	jnc 	short loc_gfvn_load_FAT32_dir_cluster
  	
	cmp     eax, 1
	cmc
	retn
  
loc_gfvn_load_FAT32_dir_cluster:
	call	load_FAT_sub_directory
	jnc	short loc_get_volume_name
	retn

loc_get_volume_name_retn_xor:
	xor 	eax, eax
	retn

get_media_change_status:
	; 10/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 09/09/2009
	; INPUT:
	;     DL = Drive number (physical)
	; OUTPUT: clc & AH = 6 media changed
	;     clc & AH = 0 media not changed         
	;     stc -> Drive not ready or an error 
  
	mov	ah, 16h
  	call	int13h
	cmp	ah, 06h
	je	short loc_gmc_status_retn
	or	ah, ah
	jz	short loc_gmc_status_retn
loc_gmc_status_stc_retn:    
	stc
loc_gmc_status_retn:
	retn
