; *****************************************************************************
;
; DRVINFO2.ASM  [ TR-DOS DRV INIT Sample & DRIVE INFO Utility ]
; Copyright (c) 2004  Erdogan TAN  [ 29/01/2005 ]
;
; *****************************************************************************

; Masterboot / Partition Table at Beginning+1BEh
ptBootable       equ 0
ptBeginHead      equ 1
ptBeginSector    equ 2
ptBeginCylinder  equ 3
ptFileSystemName equ 4
ptEndHead        equ 5
ptEndSector      equ 6
ptEndCylinder    equ 7
ptStartSector    equ 8
ptSectors        equ 12

; Boot Sector Parameters at 7C00h
DataArea1     equ -4
DataArea2     equ -2
BootStart     equ 0h
OemName       equ 03h
BytesPerSec   equ 0Bh
SecPerClust   equ 0Dh
ResSectors    equ 0Eh
FATs          equ 10h
RootDirEnts   equ 11h
Sectors       equ 13h
Media         equ 15h
FATsecs       equ 16h
SecPerTrack   equ 18h
Heads         equ 1Ah 
Hidden1       equ 1Ch
Hidden2       equ 1Eh
HugeSec1      equ 20h
HugeSec2      equ 22h
DriveNumber   equ 24h
Reserved1     equ 25h
bootsignature equ 26h                 
VolumeID      equ 27h
VolumeLabel   equ 2Bh
FileSysType   equ 36h          
Reserved2     equ 3Eh                           ; Starting cluster of P2000

; FAT32 BPB Structure
FAT32_FAT_Size equ 36
FAT32_RootFClust equ 44
FAT32_FSInfoSec equ 48
FAT32_DrvNum equ 64
FAT32_Reserved1 equ 65
FAT32_BootSig equ 66
FAT32_VolID equ 67
FAT32_VolLab equ 71
FAT32_FilSysType equ 82

; BIOS Disk Parameters
DPDiskNumber  equ 0h
DPDType       equ 1h
DPReturn      equ 2h
DPHeads       equ 3h
DPCylinders   equ 4h
DPSecPerTrack equ 6h
DPDisks       equ 7h
DPTableOff    equ 8h
DPTableSeg    equ 0Ah
DPNumOfSecs   equ 0Ch

; BIOS INT 13h Extensions (LBA extensions)
; Just After DP Data (DPDiskNumber+)
DAP_PacketSize equ 10h  ; If extensions present, this byte will be >=10h
DAP_Reserved1 equ 11h   ; Reserved Byte 
DAP_NumOfBlocks equ 12h ; Value of this byte must be 0 to 127
DAP_Reserved2 equ 13h   ; Reserved Byte
DAP_Destination equ 14h ; Address of Transfer Buffer as SEGMENT:OFFSET
DAP_LBA_Address equ 18h ; LBA=(C1*H0+H1)*S0+S1-1
                        ; C1= Selected Cylinder Number
                        ; H0= Number Of Heads (Maximum Head Number + 1)
                        ; H1= Selected Head Number
                        ; S0= Maximum Sector Number
                        ; S1= Selected Sector Number
                        ; QUAD WORD
; DAP_Flat_Destination equ 20h ; 64 bit address, if value in 4h is FFFF:FFFFh
                             ; QUAD WORD (Also, value in 0h must be 18h) 
                             ; TR-DOS will not use 64 bit Flat Address

; INT 13h Function 48h "Get Enhanced Disk Drive Parameters"
; Just After DP Data (DPDiskNumber+)
GetDParams_48h equ 20h ; Word. Data Lenght, must be 26 (1Ah) for short data.
GDP_48h_InfoFlag equ 22h ; Word
; Bit 1 = 1 -> The geometry returned in bytes 4-15 is valid.
GDP_48h_NumOfPCyls equ 24h ; Double Word. Number physical cylinders.
GDP_48h_NumOfPHeads equ 28h ; Double Word. Number of physical heads.
GDP_48h_NumOfPSpT equ 2Ch ; Double word. Num of physical sectors per track.
GDP_48h_LBA_Sectors equ 30h ; 8 bytes. Number of physical/LBA sectors.
GDP_48h_BytesPerSec equ 38h ; Word. Number of bytes in a sector.

; TR-DOS Standalone Program Extensions to the DiskParams Block
; Just After DP Data (DPDiskNumber+)
TRDP_CurrentSector equ 3Ah  ; DX:AX (LBA)
TRDP_SectorCount equ 3Eh    ; CX (or Counter)

; DOS Logical Disks
LD_Name equ 0
LD_DiskType equ 1
LD_PhyDrvNo equ 2
LD_FATType equ 3
LD_FSType equ 4
LD_LBAYes equ 5
LD_BPB equ 6
LD_FATBegin equ 96
LD_ROOTBegin equ 100
LD_DATABegin equ 104
LD_StartSector equ 108
LD_TotalSectors equ 112
LD_FreeSectors equ 116
LD_Clusters equ 120
LD_PartitionEntry equ 124
LD_DParamEntry equ 125
LD_MediaChanged equ 126
LD_CDirLevel equ 127
LD_CurrentDirectory equ 128

; Valid FAT Types
FS_FAT12 equ 1
FS_FAT16_CHS equ 2
FS_FAT32_CHS equ 3
FS_FAT16_LBA equ 4
FS_FAT32_LBA equ 5

; Cursor Location
CCCpointer equ  0450h   ; BIOS data, current cursor column
; FAT Clusters EOC sign
FAT12EOC equ 0FFFh
FAT16EOC equ 0FFFFh
;FAT32EOC equ 0FFFFFFFh ; It is not direct usable for 8086 code
; BAD Cluster
FAT12BADC equ 0FF7h
FAT16BADC equ 0FFF7h
;FAT32BADC equ 0FFFFFF7h ; It is not direct usable for 8086 code
; MS-DOS FAT16 FS (Maximum Possible) Last Cluster Number= 0FFF6h 


Present segment Para 'code'

		assume CS:Present, DS:Present, ES:Present, SS:Present


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±
;±              PROCEDURE proc_start
;±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

proc_start      proc    far

                org 100h
start:
                call proc_drv_init  ; DRV_INIT.ASM

                xor dl, dl
                call floppy_drv_init
                mov al, byte ptr [Current_TRDOS_Drv]
                adc al, 0
                push ax
                mov dl, 1
                call floppy_drv_init
                pop ax
                adc al, 0
                mov byte ptr [Current_TRDOS_Drv], al

                mov si, offset Logical_DOSDisks
loc_check_trdos_drv_exists:
                cmp byte ptr [SI][LD_Name], 0
                jna short pass_current_trdos_drv

                push si

                call proc_print_drv_info

                mov si, offset Press_Any_Key
                call proc_printmsg

                pop si
                
                xor ah, ah              ; "Press any key to continue"
                int 16h                

                cmp al, 1Bh
                je short end_of_prog_drvinfo

                call proc_clear_screen

                inc byte ptr [Current_TRDOS_Drv]

pass_current_trdos_drv:
                mov al, byte ptr [Last_Dos_DiskNo]
                cmp al, byte ptr [Current_TRDOS_Drv]
                jb short end_of_prog_drvinfo
                add si, 100h
                jmp short loc_check_trdos_drv_exists

end_of_prog_drvinfo:
                mov si, offset Program_Name
                call proc_printmsg

                mov ax, word ptr [File_Size]
                mov si, offset FileSize_StrPlus5
                mov cx, 10                  
loc_wfsize_rdivide:
                dec si
                xor dx, dx
                div cx
                add dl, '0'
                mov byte Ptr [si], dl
                cmp ax,0
                ja short loc_wfsize_rdivide

                call proc_printmsg

                int 20h
                    
proc_start      endp

proc_printmsg   proc near

                mov BX, 07
loc_print:
		lodsb                           ; Load byte at DS:SI to AL
		and     AL,AL            
		je      short loc_return        ; If AL = 00h then return
		mov     AH,0Eh                  
		int     10h                     ; BIOS Service func ( ah ) = 0Eh
						; Write char as TTY
						;AL-char BH-page BL-color
		jmp     short loc_print           
loc_return:
		retn

proc_printmsg   endp


proc_clear_screen proc near

                mov ah, 0Fh 
                int 10h
                mov ah, 0
                int 10h

                retn

proc_clear_screen endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Rx_DOS  32 bit Divide                                      ;
; (Special version by Erdogan Tan)                           ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit dividend                           ;
; input -> CX = 16 bit divisor                               ;
; output -> DX_AX = 32 bit quotient                          ;
; output -> BX = 16 bit remainder                            ;
;                                                            ;
;  This procedure divides the requested 32 bit number        ;
;  and gives the result in DX, AX and BX (remainder)         ;
;                                                            ;
; Original Procedure by Michael Podanoffsky / Real Time DOS  ;
; (c) Erdogan TAN  1999                     [ RXDOSBIO.ASM ] ;
;............................................................;

Rx_Dos_Div32    proc near

		mov  bx, dx
		xchg ax, bx
		xor  dx, dx
		div  cx         ; at first, divide DX
		xchg ax, bx     ; remainder is in DX
				; now, BX has quotient
				; save remainder
		div  cx         ; so, DX_AX divided and
				; AX has quotient
				; DX has remainder
		xchg dx, bx     ; finally, BX has remainder

		retn

Rx_Dos_Div32    endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; From binary (byte) to hexadecimal (character) converter    ;
;                                                            ;
; input -> AL = byte (binary number) to be converted         ;
; output -> AH = First character of hexadecimal number       ;
; output -> AL = Second character of hexadecimal number      ;
;                                                            ;
; (c) Erdogan TAN  1998 - 1999                               ;
;............................................................;

; 1998

proc_hex        proc    near

		db 0D4h,10h                     ; Undocumented inst. AAM
						; AH = AL / 10h
						; AL = AL MOD 10h
		or AX,'00'                      ; Make it ZERO (ASCII) based

                xchg AH,AL 

; 1999
		cmp AL,'9'
		jna pass_cc_al
		add AL,7
pass_cc_al:
		cmp AH,'9'
		jna pass_cc_ah
		add AH,7
pass_cc_ah:

; 1998
		retn

proc_hex        endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; 32 bit Multiply                                            ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit multiplier                         ;
; input -> BX = 16 bit number to be multiplied by DX_AX      ;
; output -> BX_DX_AX = 48 bit (16+32 bit) result number      ;
;                                                            ;
; (c) Erdogan TAN  1999                                      ;
;............................................................;

proc_mul32    proc near

	      push cx

	      mov cx, bx
	      mov bx, dx

	      mul cx

              xchg ax, bx

	      push dx

              mul cx 

              pop cx 

              add ax, cx 
	      adc dx, 0

	      xchg bx, ax
	      xchg dx, bx

	      pop cx

	      retn

proc_mul32    endp

INCLUDE DRV_INIT.ASM  ; TRDOS Drive Initialization Procedures

proc_print_drv_info proc near
                ; input -> DS:SI = Logical Disk Parameters table
                cmp word ptr [SI][LD_BPB][FATSecs], 0
                ja short pass_FAT32_drv_info
                mov word ptr [val_fatsecs], '00'
                mov word ptr [val_fatsecs]+2, '00'
                mov al, byte ptr [SI][LD_BPB][FAT32_DrvNum]
		call proc_hex
		mov word ptr [val_drivenumber], ax
                mov al, byte ptr [SI][LD_BPB][FAT32_Reserved1]
		call proc_hex
		mov word ptr [val_reserved1], ax
                mov al, byte ptr [SI][LD_BPB][FAT32_BootSig]
		call proc_hex
		mov word ptr [val_bootsignature], ax
                mov al, byte ptr [SI][LD_BPB][FAT32_VolID]
		call proc_hex
		mov word ptr [val_volumeid]+6, ax
                mov al, byte ptr [SI][LD_BPB][FAT32_VolID]+1
		call proc_hex
		mov word ptr [val_volumeid]+4, ax
                mov al, byte ptr [SI][LD_BPB][FAT32_VolID]+2
		call proc_hex
		mov word ptr [val_volumeid]+2, ax
                mov al, byte ptr [SI][LD_BPB][FAT32_VolID]+3
		call proc_hex
		mov word ptr [val_volumeid], ax
                push si
                add si, LD_BPB + FAT32_VolLab
                mov di, offset str_volumelabel
		mov cx, 11
		rep movsb
		mov cx, 4
		mov di, offset str_filesystype
		rep movsw
		mov cx, 19
		mov di, offset str_volumelabel
loop_scan_str_FAT32vlabel:
		cmp byte ptr [DI], 0
                jne short pass_i_str_FAT32vlabel
		mov byte ptr [DI], 20h
pass_i_str_FAT32vlabel:
		inc di
                loop loop_scan_str_FAT32vlabel
                pop si
                jmp short pass_FAT16_drv_info
pass_FAT32_drv_info:
                mov al, byte ptr [SI][LD_BPB][FATsecs]
		call proc_hex
		mov word ptr [val_fatsecs]+2, ax
                mov al, byte ptr [SI][LD_BPB][FATsecs]+1
		call proc_hex
		mov word ptr [val_fatsecs], ax
                mov al, byte ptr [SI][LD_BPB][DriveNumber]
		call proc_hex
		mov word ptr [val_drivenumber], ax
                mov al, byte ptr [SI][LD_BPB][Reserved1]
		call proc_hex
		mov word ptr [val_reserved1], ax
                mov al, byte ptr [SI][LD_BPB][bootsignature]
		call proc_hex
		mov word ptr [val_bootsignature], ax
                mov al, byte ptr [SI][LD_BPB][VolumeID]
		call proc_hex
		mov word ptr [val_volumeid]+6, ax
                mov al, byte ptr [SI][LD_BPB][VolumeID]+1
		call proc_hex
		mov word ptr [val_volumeid]+4, ax
                mov al, byte ptr [SI][LD_BPB][VolumeID]+2
		call proc_hex
		mov word ptr [val_volumeid]+2, ax
                mov al, byte ptr [SI][LD_BPB][VolumeID]+3
		call proc_hex
		mov word ptr [val_volumeid], ax
                push si
                add si, LD_BPB + VolumeLabel
		mov di, offset str_volumelabel
		mov cx, 11
		rep movsb
		mov cx, 4
		mov di, offset str_filesystype
		rep movsw
		mov cx, 19
		mov di, offset str_volumelabel
loop_scan_str_volumelabel:
		cmp byte ptr [DI], 0
		jne short pass_i_str_volumelabel
		mov byte ptr [DI], 20h
pass_i_str_volumelabel:
		inc di
		loop loop_scan_str_volumelabel
                pop si
pass_FAT16_drv_info:
                mov al, byte ptr [SI][LD_Name]
		mov byte ptr [str_info_drv_name], al
                push si
                add si, LD_BPB + OemName
		mov di, offset str_oemname
		mov cx, 4
		rep movsw
		mov cx, 8
		mov di, offset str_oemname
loop_scan_str_oemname:
		cmp byte ptr [DI], 0
		jne short pass_i_str_oemname
		mov byte ptr [DI], 20h
pass_i_str_oemname:
		inc di
		loop loop_scan_str_oemname
		pop si
                mov al, byte ptr [SI][LD_BPB][BytesPerSec]
		call proc_hex
		mov word ptr [val_bytespersec]+2, ax
                mov al, byte ptr [SI][LD_BPB][BytesPerSec]+1
		call proc_hex
		mov word ptr [val_bytespersec], ax
                mov al, byte ptr [SI][LD_BPB][SecPerClust]
		call proc_hex
		mov word ptr [val_secperclust], ax
                mov al, byte ptr [SI][LD_BPB][ResSectors]
		call proc_hex
		mov word ptr [val_ressectors]+2, ax
                mov al, byte ptr [SI][LD_BPB][ResSectors]+1
		call proc_hex
		mov word ptr [val_ressectors], ax
                mov al, byte ptr [SI][LD_BPB][FATs]
		call proc_hex
		mov word ptr [val_fats], ax
                mov al, byte ptr [SI][LD_BPB][RootDirEnts]
		call proc_hex
		mov word ptr [val_rootdirents]+2, ax
                mov al, byte ptr [SI][LD_BPB][RootDirEnts]+1
		call proc_hex
		mov word ptr [val_rootdirents], ax
                mov al, byte ptr [SI][LD_BPB][Sectors]
		call proc_hex
		mov word ptr [val_sectors]+2, ax
                mov al, byte ptr [SI][LD_BPB][Sectors]+1
		call proc_hex
		mov word ptr [val_sectors], ax
                mov al, byte ptr [SI][LD_BPB][Media]
		call proc_hex
		mov word ptr [val_media], ax
                mov al, byte ptr [SI][LD_BPB][SecPerTrack]
		call proc_hex
		mov word ptr [val_secpertrack]+2, ax
                mov al, byte ptr [SI][LD_BPB][SecPerTrack]+1
		call proc_hex
		mov word ptr [val_secpertrack], ax
                mov al, byte ptr [SI][LD_BPB][Heads]
		call proc_hex
		mov word ptr [val_heads]+2, ax
                mov al, byte ptr [SI][LD_BPB][Heads]+1
		call proc_hex
		mov word ptr [val_heads], ax
                mov al, byte ptr [SI][LD_BPB][Hidden1]
		call proc_hex
		mov word ptr [val_hidden1]+2, ax
                mov al, byte ptr [SI][LD_BPB][Hidden1]+1
		call proc_hex
		mov word ptr [val_hidden1], ax
                mov al, byte ptr [SI][LD_BPB][Hidden2]
		call proc_hex
		mov word ptr [val_hidden2]+2, ax
                mov al, byte ptr [SI][LD_BPB][Hidden2]+1
		call proc_hex
		mov word ptr [val_hidden2], ax
                mov al, byte ptr [SI][LD_BPB][HugeSec1]
		call proc_hex
		mov word ptr [val_hugesec1]+2, ax
                mov al, byte ptr [SI][LD_BPB][HugeSec1]+1
		call proc_hex
		mov word ptr [val_hugesec1], ax
                mov al, byte ptr [SI][LD_BPB][HugeSec2]
		call proc_hex
		mov word ptr [val_hugesec2]+2, ax
                mov al, byte ptr [SI][LD_BPB][HugeSec2]+1
		call proc_hex
		mov word ptr [val_hugesec2], ax

		mov si, offset msg_drive_info
		call proc_printmsg
		retn

proc_print_drv_info endp

Msg_drive_info:
                   db 7
                   db "[ TR-DOS DRIVE ] "
str_info_drv_name: db "0:"
                   db  0Dh, 0Ah
                   db  0Dh, 0Ah
                   db "OEM Name :  "
str_oemname:       db 8 dup(20h)
                   db 0Dh, 0Ah
                   db "Bytes Per Sector :  "
val_bytespersec:   dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Sectors Per Cluster :  "
val_secperclust:   dw 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Reserved Sectors :  "
val_ressectors:    dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Number Of FATs :  "
val_fats:          dw 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Root Directory Entries :  "
val_rootdirents:   dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Total Sectors :  "
val_sectors:       dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Media :  "
val_media:         dw 0
                   db "h"
                   db 0Dh, 0Ah
                   db "FAT Sectors :  "
val_fatsecs:       dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Sectors Per Track :  "
val_secpertrack:   dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Heads :  "
val_heads:         dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Hidden Sectors :  "
val_hidden2:       dd 0
val_hidden1:       dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Total Sectors (Huge) :  "
val_hugesec2:      dd 0
val_hugesec1:      dd 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Drive Number :  "
val_drivenumber:   dw 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Reserved Byte :  "
val_reserved1:     dw 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Boot Signature :  "
val_bootsignature: dw 0
                   db "h"
                   db 0Dh, 0Ah
                   db "Volume ID :  "
val_volumeid:      dd 0
                   dd 0
                   db 0Dh, 0Ah
                   db "Volume Label :  "
str_volumelabel:   db 11 dup(20h)
                   db 0Dh, 0Ah
                   db "File System :  "
str_filesystype:   db 8 dup (20h)
                   db 0Dh, 0Ah
                   db 0Dh, 0Ah
                   db 0
Magic_Bytes:
                   db 4
                   db 1
Press_Any_Key:
                db 0Dh, 0Ah 
                db "Press any key to continue ..."
                db 0Dh, 0Ah, 0
Program_Name:
                   db 7
                   db "[TRDOS] DRIVE INFO "
Version_Str:       db "v2.0  ¸ Erdogan Tan 2004-2005"
                   db 0Dh, 0Ah
                   db "File Size = "
                   db 6 dup(0)
FileSize_StrPlus5: db " bytes"
                   db 0Dh, 0Ah
                   db 0

Current_TRDOS_Drv: db 0
Logical_DOSDisks:  dw 3328 dup(0)
File_Size:         dw $-254

Present            ends

                   end  start
