LOCALS

.MODEL	SMALL


DRIVEINFOSTRUC	STRUC
	di_wSize		DW	?
	di_wFlags		DW	?
	di_dwCyls		DD	?
	di_dwHeads		DD	?
	di_dwSecsPerTrack	DD	?
	di_qwTotalSecs		DQ	?
	di_dwBytesPerSector	DW	?
DRIVEINFOSTRUC	ENDS


.DATA

szFDD_360KB	DB	'5',0F7h,'" 360кб',0
szFDD_1_2MB	DB	'5',0F7h,'" 1,2Мб',0
szFDD_720KB	DB	'3',0F6h,'" 720кб',0
szFDD_1_44MB	DB	'3',0F6h,'" 1,44Мб',0
szFDD_2_88MB	DB	'3',0F6h,'" 2,88Мб',0


.DATA?

PUBLIC	bFDD1Type
PUBLIC	bFDD2Type
PUBLIC	pszFDD1Type
PUBLIC	pszFDD2Type
PUBLIC	bHDD0_flag
PUBLIC	bHDD1_flag
PUBLIC	szHDD0Size
PUBLIC	szHDD1Size

bFDD1Type	DB	?		;тип первого дисковода
bFDD2Type	DB	?		;тип второго дисковода
pszFDD1Type	DW	?		;указатель на строку в формате ASCIIZ
					;с типом первого дисковода
pszFDD2Type	DW	?		;указатель на строку в формате ASCIIZ
					;с типом второго дисковода
bHDD0_flag	DB	?		;флаг наличия жесткого диска 0
bHDD1_flag	DB	?		;флаг наличия жесткого диска 1
szHDD0Size	DB	13 DUP(?)	;строка с объемом жесткого диска 0
szHDD1Size	DB	13 DUP(?)	;строка с объемом жесткого диска 1


.CODE

PUBLIC	GetDiskInfo

EXTRN	ReadCMOSReg:PROC
EXTRN	DWordToStr:PROC
EXTRN	StrLen:PROC

;*******************************************************************************
;GetDiskInfo	определяет основную информацию о дисках
;*******************************************************************************
;Использует:	GetDiskSize, GetFDDType, DWordToStr, StrLen
;
;Вызов:		нет
;
;Возврат:	нет
;
;Изменяемые
;  регистры:	AX,BX,CX,DX,Flags
;*******************************************************************************
GetDiskInfo	PROC

		push	es		;сохраняем регистры в стеке
		push	si
		push	di

		push	ds
		pop	es		;ES = сегмент данных

;-------------------------------------------------------------------------------
;Жесткие диски
;-------------------------------------------------------------------------------

;Размеры жестких дисков

;Жесткий диск 0
		mov	[bHDD0_flag],0

		mov	dl,80h
		call	GetDiskSize	;CF = флаг успешного/неудачного завершения
					;DX:AX = размер жесткого диска 0
					;в мегабайтах
		jc	@@HDD0_Exit

		inc	[bHDD0_flag]

		mov	di,OFFSET szHDD0Size	;ES:DI -> szHDD0Size
		call	DWordToStr

		mov	si,di		;DS:SI -> szHDD0Size
		call	StrLen		;CX = длина строки
		add	si,cx
		mov	WORD PTR [si],'бМ'
		mov	BYTE PTR [si+2],0

@@HDD0_Exit:

;Жесткий диск 1
		mov	[bHDD1_flag],0

		mov	dl,81h
		call	GetDiskSize	;CF = флаг успешного/неудачного завершения
					;DX:AX = размер жесткого диска 1
					;в мегабайтах
		jc	@@HDD1_Exit

		inc	[bHDD1_flag]

		mov	di,OFFSET szHDD1Size	;ES:DI -> szHDD1Size
		call	DWordToStr

		mov	si,di		;DS:SI -> szHDD1Size
		call	StrLen		;CX = длина строки
		add	si,cx
		mov	WORD PTR [si],'бМ'
		mov	BYTE PTR [si+2],0

@@HDD1_Exit:

;-------------------------------------------------------------------------------
;Дисководы
;-------------------------------------------------------------------------------

;Типы дисководов

		call	GetFDDType	;AL = тип первого дисковода
					;AH = тип второго дисковода
		mov	[bFDD1Type],al
		mov	[bFDD2Type],ah

		mov	cl,8
		mov	bx,OFFSET pszFDD1Type

L21:		or	al,al
		jz	L22

		mov	WORD PTR [bx],OFFSET szFDD_360KB
		cmp	al,1
		je	L22

		mov	WORD PTR [bx],OFFSET szFDD_1_2MB
		cmp	al,2
		je	L22

		mov	WORD PTR [bx],OFFSET szFDD_720KB
		cmp	al,3
		je	L22

		mov	WORD PTR [bx],OFFSET szFDD_1_44MB
		cmp	al,4
		je	L22

		mov	WORD PTR [bx],OFFSET szFDD_2_88MB

L22:		mov	bx,OFFSET pszFDD2Type
		shr	ax,cl
		jnz	L21

		pop	di		;восстанавливаем регистры
		pop	si
		pop	es

		ret

GetDiskInfo	ENDP

;*******************************************************************************
;GetDiskSize	определяет размер диска
;*******************************************************************************
;Использует:	int 13h
;
;Вызов:		DL = номер дисковода
;
;Возврат:	CF = флаг успешного/неудачного завершения
;		DX:AX = размер диска в мегабайтах
;
;Изменяемые
;  регистры:	AX,BL,CX,DX,Flags
;*******************************************************************************
GetDiskSize	PROC
		LOCAL	@@DriveInfo:DRIVEINFOSTRUC = LOCAL_SIZE

		push	bp		;сохраняем регистры в стеке
		mov	bp,sp
		sub	sp,LOCAL_SIZE	;стековое пространство для локальных
					;переменных
		push	ds
		push	es
		push	si
		push	di

		mov	[@@DriveInfo.di_wSize],SIZE DRIVEINFOSTRUC

		push	ss
		pop	ds
		lea	si,[@@DriveInfo];DS:SI -> буфер для параметров дисковода

		mov	ah,48h		;AH=48h (получить параметры дисковода)
		int	13h		;CF = флаг успешного/неудачного завершения
		jc	@@Old

		test	BYTE PTR [@@DriveInfo.di_wFlags],2	;корректные
								;значения?
		jz	@@Old

		mov	ax,WORD PTR [@@DriveInfo.di_dwHeads]
		mul	WORD PTR [@@DriveInfo.di_dwSecsPerTrack]
		mul	WORD PTR [@@DriveInfo.di_dwCyls];DX:AX = количество
							;секторов на диске
		jmp	@@GetSize

@@Old:		xor	di,di
		mov	es,di		;ES:DI = 0000h:0000h

		mov	ah,8		;AH=8 (получить параметры дисковода)
		int	13h		;CF = флаг успешного/неудачного завершения
					;CH = биты 0-7 максимального номера
					;цилиндра
					;CL (биты 0-5) = максимальный номер
					;сектора
					;CL (биты 6-7) = биты 8-9 максимального
					;номера цилиндра
					;DH = максимальный номер головки
		jc	@@Exit

		mov	al,cl
		and	al,3Fh		;AL = максимальный номер сектора
					;(число секторов на дорожке)

		rol	cl,1
		rol	cl,1
		and	cl,3
		xchg	cl,ch		;CX = максимальный номер цилиндра
		inc	cx		;CX = количество цилиндров

		inc	dh		;DH = количество головок

		mul	dh
		mul	cx		;DX:AX = количество секторов на диске

@@GetSize:	mov	cx,11

@@Del_Loop:	shr	dx,1
		rcr	ax,1
		loop	@@Del_Loop

		clc			;CF=0

@@Exit:		pop	di		;восстанавливаем регистры
		pop	si
		pop	es
		pop	ds
		mov	sp,bp
		pop	bp

		ret

GetDiskSize	ENDP

;*******************************************************************************
;GetFDDType	возвращает типы дисководов флоппи-дисков
;*******************************************************************************
;Использует:	нет
;
;Вызов:		ReadCMOSReg
;
;Возврат:	AL = тип первого дисковода:
;		AH = тип второго дисковода:
;			00h = нет дисковода
;			01h = DSDD  48 TPI (360кб, 5.25")
;			02h = DSHD  96 TPI (1.2Мб, 5.25")
;			03h = DSDD 135 TPI (720кб,  3.5")
;			04h = DSHD 135 TPI (1.44Мб, 3.5")
;			05h = DSED 135 TPI (2.88Мб, 3.5")
;
;Изменяемые
;  регистры:	AX,CL,Flags
;*******************************************************************************
GetFDDType	PROC

		mov	ax,10h		;AL=10h	(номер регистра RT/CMOS)
		call	ReadCMOSReg	;AL = байт с информацией о дисководах
					;флоппи-дисков
		mov	cl,10h
		div	cl		;AL = тип первого дисковода
					;AH = тип второго дисковода

		ret

GetFDDType	ENDP


END
