;******************************************************
;		   TPDISK.ASM 4.03
;		 Disk access routines
;	 Copyright (c) TurboPower Software 1987.
; Portions copyright (c) Sunny Hill Software 1985, 1986
;     and used under license to TurboPower Software
;		 All rights reserved.
;******************************************************

	INCLUDE TPCOMMON.INC		;common macros, etc.

;****************************************************** Data

DATA	SEGMENT WORD PUBLIC

	EXTRN	DosError : WORD 		;Declared in DOS unit

DATA	ENDS

;****************************************************** Code

CODE	SEGMENT BYTE PUBLIC

	ASSUME	CS:CODE,DS:DATA

	PUBLIC	NumberOfDrives, SelectDrive, DefaultDrive
	PUBLIC	ReadDiskSectors, WriteDiskSectors, GetDiskInfo

;****************************************************** NumberOfDrives

;function NumberOfDrives : Byte;
;Returns the number of logical drives

NumberOfDrives	PROC FAR

	MOV	AH,19h			;Report current drive service
	INT	21h			;Call DOS
	MOV	DL,AL			;Current drive into DL
	MOV	AH,0Eh			;Select current drive service
					;Returns drive count in AL
	INT	21h			;Call DOS
	SetZero AH			;Clear AH
	RET				;Return

NumberOfDrives	ENDP

;****************************************************** SelectDrive

;procedure SelectDrive(Drive : Char);
;Selects the specified drive as default if possible

Drive	EQU	BYTE PTR SS:[BX+4]

SelectDrive	PROC FAR

	StackFrame			;Set up stack frame
	MOV	DL,Drive		;DL = Drive
	CMP	DL,'z'                  ;Drive <= 'z'?
	JA	SelectExit		;If not, forget it
	CMP	DL,'a'                  ;Drive in 'a'..'z'?
	JB	GotDriveLetter		;If not, continue
	SUB	DL,32			;Else convert to uppercase

GotDriveLetter:
	SUB	DL,'A'                  ;Convert to drive number
	MOV	AH,0Eh			;Select current drive service
	INT	21h			;Call DOS

SelectExit:
	RET	2			;Return

SelectDrive	ENDP

;****************************************************** DefaultDrive

;function DefaultDrive : Char;
;Returns the default drive as an uppercase letter

DefaultDrive	PROC FAR

	MOV	AH,19h			;Report current drive service
	INT	21h			;Call DOS
	MOV	DL,AL			;Current drive into DL
	ADD	AL,'A'                  ;Convert drive number to char
	SetZero AH			;Clear AH
	RET				;Return

DefaultDrive	ENDP

;****************************************************** ReadWriteDiskSectors

;Primitive routine to read/write absolute disk sectors, used by
;  ReadDiskSectors and WriteDiskSectors
;On entry, DI contains 0 or 1 -- 1 to write, 0 to read

;Equates for parameters (ReadDiskSectors and WriteDiskSectors have identical
; parameter lists)

DSDrive 	EQU	BYTE PTR SS:[BX+12]
DSFirstSect	EQU	WORD PTR SS:[BX+10]
DSNumSects	EQU	WORD PTR SS:[BX+8]
DSBuffer	EQU	DWORD PTR SS:[BX+4]

ReadWriteDiskSectors	PROC FAR

	StackFrame			;Set up stack frame

	PUSH	DS			;Save DS
	PUSH	BP			;Save BP -- destroyed by DOS

	;load parameters into registers

	MOV	AL,DSDrive		;AL = Drive
	MOV	CX,DSNumSects		;CX = NumSects
	MOV	DX,DSFirstSect		;DX = FirstSect
	LDS	BX,DSBuffer		;DS:BX points to Buf

	;see if we're reading or writing

	SHR	DI,1			;Rotate DI right by one bit
	JC	DSWrite 		;Write if carry flag set
	INT	25h			;DOS interrupt for absolute disk read
	JMP	SHORT DSCheckCarry	;Check carry flag
DSWrite:
	INT	26h			;DOS interrupt for absolute disk write

DSCheckCarry:
	MOV	BX,0			;Assume failure
	JC	DSDone			;Error code in AX if carry flag set
	SetZero AX			;Otherwise, AX = 0
	INC	BX			;BX = Ord(True)
DSDone:
	POPF				;DOS leaves flags on the stack!
	POP	BP			;Restore BP
	POP	DS			;Restore DS
	MOV	DosError,AX		;Error code in DosError
	MOV	AX,BX			;Boolean result into AX
	BooleanResult			;Set zero flag
	RET	10			;Remove parameters and return

ReadWriteDiskSectors	ENDP

;****************************************************** ReadDiskSectors

;function ReadDiskSectors(Drive, FirstSect, NumSects : Word; var Buf) : Boolean;
;Read absolute disk sectors

ReadDiskSectors PROC FAR

	SetZero DI			;DI = 0 (Read)
	JMP	ReadWriteDiskSectors	;Jump to primitive read/write routine

ReadDiskSectors ENDP

;****************************************************** WriteDiskSectors

;function WriteDiskSectors(Drive, FirstSect, NumSects : Word; var Buf) : Boolean;
;Write absolute disk sectors.

WriteDiskSectors	PROC FAR

	MOV	DI,1			;DI = 1 (Write)
	JMP	ReadWriteDiskSectors	;Jump to primitive read/write routine

WriteDiskSectors	ENDP

;****************************************************** GetDiskInfo

;function GetDiskInfo(Drive : Byte; var ClustersAvailable, TotalClusters,
;		      BytesPerSector, SectorsPerCluster: Word) : Boolean;
;Return technical info about the specified drive

GDDrive 	EQU	BYTE PTR [BP+22]
GDClustAvail	EQU	DWORD PTR [BP+18]
GDTotalClust	EQU	DWORD PTR [BP+14]
GDBytesPerSec	EQU	DWORD PTR [BP+10]
GDSecPerClust	EQU	DWORD PTR [BP+6]

GetDiskInfo	PROC FAR

	StackFrameBP			;set up stack frame
	MOV	DL,GDDrive		;DL = Drive
	MOV	AH,36h			;Get disk free space
	INT	21h			;call DOS
	CMP	AX,0FFFFh		;invalid drive?
	JE	GDIerror		;error if so
	CLD				;go forward
	LES	DI,GDSecPerClust	;ES:DI => SectorsPerCluster
	STOSW				;value in AX
	LES    DI,GDBytesPerSec 	;ES:DI => BytesPerSector
	MOV    AX,CX			;value in CX
	STOSW
	LES    DI,GDTotalClust		;ES:DI => TotalClusters
	MOV    AX,DX			;value in DX
	STOSW
	LES    DI,GDClustAvail		;ES:DI => ClustersAvailable
	MOV    AX,BX			;value in BX
	STOSW
	MOV	AX,1			;set OK flag
GDIdone:
	BooleanResult			;set zero flag
	ExitCode 18			;remove parameters and return
GDIerror:
	SetZero AX			;AX = 0
	JMP SHORT GDIdone		;exit

GetDiskInfo	ENDP

CODE	ENDS

	END
