Tvùrce webu je i pro tebe! Postav tøeba web. Bez grafika. Bez kodéra. Hned.
wz

INIT_HD.ASM

Initialize Hard Drives


; =============================================================================
;
;                  Litos - Initialize hard drives, real mode
;
; =============================================================================

%ifdef DEBUG
;%define	DEBUG_HD		; uncomment this to display HD info
%endif

		CODE_SECTION	16

HD_MAX		EQU	4		; maximal number of hard drives

; ------------- Extensions Drive Parameters

struc		EDP

EDP_Size:	resw	1		; 0: size of buffer
EDP_Flags:	resw	1		; 2: flags
					;    B0: 1=DMA boundary errors handled
					;    B1: C-H-S information is valid
					;    B2: removable drive
					;    B3: write with verify supported
					;    if removable drive:
					;	B4: change-line supported
					;	B5: drive can be locked
					;    B6: C-H-S info limited to max.
EDP_Cylinders:	resd	1		; 4: number of cylinders
EDP_Heads:	resd	1		; 8: number of heads
EDP_Sectors:	resd	1		; 0Ch: number of sectors per track
EDP_Total:	resd	2		; 10h: total number of sectors
EDP_SectSize:	resw	1		; 18h: bytes per sector
				; --- version 2.0, EDD configuration
EDP_Config:	resd	1		; 1Ah: address of EDD configuration
					;      parameters, -1=not available
				; --- version 3.0, Device Path Information
EDP_PathMagic:	resw	1		; 1Eh: magic 0BEDDh to indicate
					;      presence of Device Path Info
EDP_PathLength:	resb	1		; 20h: length of Device Path Info
		resb	3		; 21h: reserved (align)
EDP_PathHostBus:resb	4		; 24h: ASCIIZ name of host bus(ISA,PCI)
EDP_PathIntName:resb	8		; 28h: ASCIIZ name of interface type
					;	(ATA,ATAPI,SCSI,USB,1394,FIBRE)
EDD_PathIntPath:resb	8		; 30h: interface path
					;	ISA:	0: (1) base address
					;	PCI:	0: (1) bus number
					;		1: (1) device number
					;		2: (1) function number
EDP_PathDevPath:resb	8		; 38h: device path
					;	ATA:	0: (1) 0=master,1=slave
					;	ATAPI:	0: (1) 0=master,1=slave
					;		1: (1) log. unit number
					;	SCSI:	0: (1) log. unit number
					;	USB:	0: (1) to be determined
					;	1394:	0: (8) 64=bit GUID
					;	FIBRE:	0: (8) Word Wide Number
		resb	1		; 40h: ...reserved (=0)
EDP_PathSum:	resb	1		; 41h: checksum of bytes 1Eh-40h

endstruc				; size 42h = 66 bytes

; ------------- EDD Configuration Parameters

struc		ECP

ECP_BasePort:	resw	1		; 0: physical I/O port base address
ECP_CtrlPort:	resw	1		; 2: disk drive control port address
ECP_Flags:	resb	1		; 4: drive flags
					;    B4: 1=drive is slave
					;    B6: 1=LBA enabled
ECP_Prop:	resb	1		; 5: proprietary information
ECP_IRQ:	resb	1		; 6: IRQ for drive
					;    B0 - B3: IRQ
ECP_MultiSect:	resb	1		; 7: sectors for multi-sector transfer
ECP_DMA:	resb	1		; 8: DMA control
					;    B0 - B3: DMA channel
					;    B4 - B7: DMA type
ECP_PIO:	resb	1		; 9: I/O control
					;    B0 - B3: PIO type
ECP_Option:	resw	1		; 0Ah: drive options
					;    B0: 1=fast PIO enabled
					;    B1: 1=fast DMA enabled
					;    B2: 1=block PIO (multi) enabled
					;    B3: 1=CHS translation enabled
					;    B4: 1=LBA translation enabled
					;    B5: 1=removable media
					;    B6: ATAPI device (CD-ROM)
					;    B7: 32=bit transfer mode
		resb	2		; 0Ch: ...reserved (=0)
ECP_Revision:	resb	1		; 0Eh: extension revision level
					;	(high nibble=major, low=minor)
ECP_CheckSum:	resb	1		; 0Fh: 2's complement checksum
					;   (8-bit sum of 00h-0Fh should = 0)

endstruc				; size 10h = 16 bytes


; ------------- Hard Drive Parameters

struc		HDP

HDP_DriveFlags:
HDP_Drive:	resb	1		; 0: BIOS drive number (80h,...)
HDP_Flags:	resb	1		; 1: flags
					;	B0=HDP_EDP is valid
					;	B1=HDP_ECP is valid
HDP_Sectors:	resw	1		; 2: std. number of sectors per track
HDP_Heads:	resw	1		; 4: std. number of heads
HDP_Cylinders:	resw	1		; 6: std. number of cylinders
HDP_Total:	resd	1		; 8: std. total number of sectors
HDP_EDP:	resb	EDP_size	; 0Ch: Extensions Drive Parameters, EDP
HDP_ECP:	resb	ECP_size	; 4Eh: EDD Configuration Parameters

endstruc				; size 5Eh = 94 bytes

; -----------------------------------------------------------------------------
;                Call Int 13h interrupt with saving registers
; -----------------------------------------------------------------------------

; ------------- Push registers

Int13:		push	si		; push SI
		push	di		; push DI
		push	bp		; push BP
		push	ds		; push DS
		push	es		; push ES

; ------------- Call INT 13h

		stc			; preset error flag(due to some BIOSes)
		int	13h		; call INT 13h
		sti			; enable interrupt (due to some BIOSes)

; ------------- Pop registers

		pop	es		; pop ES
		pop	ds		; pop DS
		pop	bp		; pop BP
		pop	di		; pop DI
		pop	si		; pop SI
		ret

; -----------------------------------------------------------------------------
;                  Init drive parameters with standard BIOS
; -----------------------------------------------------------------------------
; INPUT:	DL = hard drive number
;		ES:DI = hard drive parameter table, HDPT
; OUTPUT:	CY = error
; DESTROYS:	AX, BX
; -----------------------------------------------------------------------------

; ------------- Push registers

InitHDPar:	push	dx		; push DX

; ------------- Get hard drive parameters

		mov	ah,8		; AH <- function code
		xor	cx,cx		; CX <- 0 preset zero number of sectors
		call	Int13		; get drive parameters		
		jc	InitHDPar8	; error

; ------------- Number of sectors per track

		mov	al,cl		; AL <- maximum sector number
		and	ax,3fh		; mask maximum sector number
		stc			; preset error flag
		jz	InitHDPar8	; error
		mov	[es:di+HDP_Sectors],ax; store sectors per track
		push	ax		; push AX (sectors per track)
		
; ------------- Number of heads

		mov	al,dh		; AL <- maximum head number
		mov	ah,0		; AH <- 0
		inc	ax		; AX <- number of heads
		mov	[es:di+HDP_Heads],ax ; store number of heads
		xchg	ax,dx		; DX <- store number of heads

; ------------- Number of cylinders

		xchg	ax,cx		; AH <- cylinder LOW, AL <- HIGH
		shr	al,6		; AL <- cylinder HIGH
		xchg	al,ah		; AL <- cylinder LOW, AH <- HIGH
		inc	ax		; AX <- number of cylinders
		mov	[es:di+HDP_Cylinders],ax ; store number of cylinders

; ------------- Calculate total number of sectors

		xchg	ax,cx		; CX <- store number of cylinders
		pop	ax		; pop AX (sectors per track)
		mul	dx		; AX <- sectors per cylinder
		mul	cx		; DX:AX <- sectors total
		mov	[es:di+HDP_Total],ax ; store total sectors LOW
		mov	[es:di+HDP_Total+2],dx ; store total sectors HIGH
		clc			; clear error flag
	
; ------------- Pop registers

InitHDPar8:	pop	dx		; pop DX
		ret

; -----------------------------------------------------------------------------
;                   Init drive parameters with BIOS extension
; -----------------------------------------------------------------------------
; INPUT:	DL = hard drive number
;		ES:DI = hard drive parameter table, HDP
;		DS = data segment
; OUTPUT:	CY = error
; DESTROYS:	AX, BX, CX, SI
; -----------------------------------------------------------------------------

; ------------- Push registers

InitEDPPar:	push	dx		; push DX
		push	di		; push DI
		push	ds		; push DS

; ------------- Check BIOS extension

		mov	ah,41h		; AH <- function code
		mov	bx,55aah	; BX <- magic number
		xor	cx,cx		; CX <- 0 preset flags
		push	dx		; push DX
		call	Int13		; check LBA extensions
		pop	dx		; pop DX
		jc	InitEDPPar8	; error	
		cmp	bx,0aa55h	; check magic
		stc			; preset error flag
		jne	InitEDPPar8	; magic is not OK
		test	cl,B0		; extended functions supported?
		stc			; preset error flag
		jz	InitEDPPar8	; extended functions not supported
		mov	byte [HDExtVer],ah ; store extensions version
		mov	byte [HDExtSupport],cl ; extensions supported functions

; ------------- Get drive parameters

		push	es		; push ES
		pop	ds		; DS <- ES, HDP table
		lea	si,[di+HDP_EDP]	; SI <- offset of EDP table
		mov	word [si+EDP_Size],EDP_size ; set EDP size
		mov	ah,48h		; AH <- function code
		call	Int13		; get drive parameters
		jc	InitEDPPar8	; error

; ------------- Check if EDP table is valid

		mov	ax,[si+EDP_Size] ; AX <- size of data in table
		cmp	ax,EDP_Config	; check EDP size
		jb	InitEDPPar8	; error
		mov	byte [di+HDP_Flags],B0 ; HDP_EDP is valid

; ------------- Check EDD configuration table

		cmp	ax,EDP_PathMagic ; is config table present?
		jb	InitEDPPar6	; config table is not present
		lds	si,[si+EDP_Config] ; DS:SI <- configuration table
		mov	ax,ds		; AX <- segment of table
		inc	ax		; is table valid?
		jz	InitEDPPar6	; table is not valid

; ------------- Copy EDD configuration table

		mov	byte [es:di+HDP_Flags],B0+B1 ; HDP_EDP + HDP_EDD valid
		add	di,byte HDP_ECP	; DI <- ECP table
		mov	cx,ECP_size	; CX <- size of ECP table
		cld			; direction up
		rep	movsb		; copy ECP table
InitEDPPar6:	clc			; clear error flag

; ------------- Pop registers

InitEDPPar8:	pop	ds		; pop DS
		pop	di		; pop DI
		pop	dx		; pop DX
		ret

; -----------------------------------------------------------------------------
;                            Init hard drives
; -----------------------------------------------------------------------------
; INPUT:	DS = data segment
; DESTROYS:	All registers except DS
; -----------------------------------------------------------------------------

; ------------- Prepare hard drive parameters address

InitHD:		mov	eax,HardDrivePar-SYSTEM_ADDR ; EAX<-hard drive table
		shr	eax,4		; EAX <- segment of hard drive table
		mov	es,ax		; ES <- segment
		xor	di,di		; DI <- offset of hard drive table

; ------------- Store drive number

		mov	dx,80h		; DL <- first hard drive, DH <- 0 flags
InitHD2:	mov	[es:di+HDP_DriveFlags],dx ; store drive number and flags

; ------------- Init drive parameters with BIOS extension

		call	InitEDPPar	; init drive parameters with BIOS ext.
		jnc	InitHD6		; parameters OK

; ------------- Init drive parameters with standard BIOS

		call	InitHDPar	; init drive parameters with std. BIOS
		jc	InitHD8		; error, invalid drive

; ------------- Hard drive is valid

InitHD6:	inc	byte [HardDriveNum] ; increase counter of hard drives
		add	di,byte HDP_size; increase table pointer

; ------------- Next drive

InitHD8:	inc	dx		; increase hard drive number
		cmp	dl,80h+HD_MAX	; check max. drive number
		jb	InitHD2		; next drive
InitHD9:

; ------------- Debug display HD info
%ifdef DEBUG_HD
		call	DebInitHD	; debug display HD info
%endif
		ret

; -----------------------------------------------------------------------------
;                           Debug display HD info
; -----------------------------------------------------------------------------
%ifdef DEBUG_HD
; ------------- Display title

DebInitHD:	mov	si,HardDriveMsg	; SI <- debug text
		call	BIOSDispText	; display message

; ------------- Prepare hard drive parameters address (-> ES:DI)

		mov	eax,HardDrivePar-SYSTEM_ADDR ; EAX <- addr. of table
		shr	eax,4		; EAX <- segment of table
		mov	es,ax		; ES <- segment of table
		xor	di,di		; DI <- 0 offset of table

; ------------- Number of hard drives (-> CX)

		movzx	cx,[HardDriveNum] ; CX <- number of hard drives
		jcxz	DebInitHD9	; no hard drive

; ------------- Number of hard drive

DebInitHD2:	push	cx		; push CX
		mov	al,[es:di+HDP_Drive] ; AL <- hard drive number
		call	BIOSDispHexByte ; display hard drive number

; ------------- ECP parameters

		test	byte [es:di+HDP_Flags],B1 ; ECP?
		jz	DebInitHD4	; no ECP parameters
		mov	si,HardDriveMsg2 ; SI <- debug text ECP
		call	BIOSDispText	; display message

; ------------- LBA

		test	byte [es:di+HDP_ECP+ECP_Flags],B6 ; LBA?
		jz	DebInitHD4	; no LBA
		mov	si,HardDriveMsg3 ; SI <- debug text LBA
		call	BIOSDispText	; display message

; ------------- Number of sectors

DebInitHD4:	mov     eax,[es:di+HDP_Total] ; EAX <- std. total sectors
		xor	edx,edx		; EDX <- 0
		test	byte [es:di+HDP_Flags],B0 ; EDP?
		jz	DebInitHD6	; no EDP parameters
		mov	si,HardDriveMsg4 ; SI <- debug text EDP
		call	BIOSDispText	; display message
                mov     eax,[es:di+HDP_EDP+EDP_Total] ; EAX <- total LOW
                mov     edx,[es:di+HDP_EDP+EDP_Total+4] ; EDX <- total HIGH

; ------------- Size of hard drive (in GB)

DebInitHD6:	mov	ecx,2*1024*1024	; ECX <- sectors per GB
                div     ecx		; calculate drive size in GB
		call	BIOSDispSpc	; display space
		call    BIOSDispNum	; display drive size in GB
		mov	si,HardDriveMsg5 ; SI <- debug text GB
		call	BIOSDispText	; display message

; ------------- Next drive

		add	di,byte HDP_size; increase table pointer
		pop	cx		; pop CX
		loop	DebInitHD2	; next drive
DebInitHD9:	call	BIOSDispNewLine	; display new line
		ret
%endif
; -----------------------------------------------------------------------------
;                                   Data
; -----------------------------------------------------------------------------

		DATA_SECTION

; ------------- Boot disk

BootDisk:	db	0		; boot disk (0=A:, 1=B:, 80h=C:, ...)

; ------------- Hard drives

HardDriveNum:	db	0		; number of hard drives

HDExtVer:	db	0		; hard drive BIOS extensions version
					;	0 = no extensions
					;	1 = 1.x
					;	20h = 2.0 (EDD 1.0)
					;	21h = 2.1 (EDD 1.1)
					;	30h = EDD 3.0

HDExtSupport:	db	0		; hard drive BIOS extensions functions
					;	B0: 1=extended disk access
					;           (42h-44h, 47h, 48h)
					;	B1: 1=removable drive
					;	    (45h, 46h, 48h, 49h)
					;	B2: 1=enhanced disk drive EDD
					;	    (48h, 4Eh)

; ------------- Debug messages
%ifdef DEBUG_HD
HardDriveMsg:	db	13,10,'--- Hard Drives:',13,10,0
HardDriveMsg2:	db	' ECP',0
HardDriveMsg3:	db	' LBA',0
HardDriveMsg4:	db	' EDP',0
HardDriveMsg5:	db	' GB',13,10,0
%endif
; -----------------------------------------------------------------------------
;                            Uninitialized data
; -----------------------------------------------------------------------------

		BSS_SECTION

; ------------- Hard drive parameters (376 bytes if HD_MAX=4 drives)

		align	16, resb 1
HardDrivePar:	resb	HD_MAX*HDP_size	; hard drive parameters

Back to source browser