; =============================================================================
;
; 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
|