;	[]===========================================================[]
;
;	NOTICE: THIS PROGRAM BELONGS TO AWARD SOFTWARE INTERNATIONAL(R)
;	        INC. IT IS CONSIDERED A TRADE SECRET AND IS NOT TO BE 	
;	        DIVULGED OR USED BY PARTIES WHO HAVE NOT RECEIVED	
;	        WRITTEN AUTHORIZATION FROM THE OWNER.
;
; 	[]===========================================================[]
;
;----------------------------------------------------------------------------
;Rev	Date	  Name	Description
;----------------------------------------------------------------------------
;R58B	03/23/99 KVN	Cancel all R58 relate coding.That will cause IDE HDD
;			and CDROM opterate abnormally.
;R58A	03/22/99 KVN	Fixed HDD initial waste long time by R58 if channel
;			disabled
;R58	03/20/99 KVN	Fixed HDD LED of M/B turn on a long time after reset
;			IDE controller.Now we send a NOP command for each
;			ATAPI device after reset IDE that can solve this problem.
;R57A	01/28/99 KVN	Fixed always read data from IDE HDD when system boot
;			from IDE and connected both IDE and SCSI of HDD.
;R57	12/21/98 KVN	Fixed Iomage Jaz device boot fail.That is SCSI has no
;			asign driver letter for Jaz when have IDE drive to be
;			installed before SCSI looking for jaz.So we asign
;			SCSI drive letter ahead of IDE if boot sequence is
;			"SCSI,A,C" or "SCSI,C,A".
;R56	12/02/98 KVN	Support IDE DMA transfer function
;R55A	11/26/98 KVN	Fixed HDD boot fail when HDD connected to primary and
;			LS120/ZIP connected to secondary by R33 coding
;R55	11/16/98 KVN	Fixed system hang within NT5.0 CDROM boot process.The
;			CDROM model is Acer 632A [firmware=322P]
;R54	09/11/98 KVN	Mask used IRQ of HDD if define "MASK_USED_HDD_IRQ" to
;			instead mask all IRQ (14&15) by old code
;R53	09/09/98 KVN	Don't show virus warning message in graphics mode to
;			avoid system hang up during Win 95/98 setup progressing
;R52	07/20/98 KVN	Add "INT13_Func08_Cylinder_Sub_1" option for fixing
;			AMIDiags IDE read verify test fail in last Cylinder.
;R46B	07/15/98 KVN	Fixed access wrong sector in large mode by R46 start.
;			That will cause can't read file on Phoenix formatted HDD
;R51A	06/18/98 BAR    Added a Define to support Update EDDS to Ver 3.0 
;			 "Support_EDDS30".
;R51	06/15/98 BAR    Update EDDS to Ver 3.0 
;R50	04/08/98 MAX	Remove INT13_Extensions code to 0F8000-0FFFFF from
;			0F0000-0F7FFF to fix WIN95 hang problem if config.sys
;			add 'device=EMM386.exe highscan noems'
;R48A	03/20/98 KVN	Fixed SCSI boot failure if connect both IDE and SCSI
;			HDD and boot sequence is SCSI boot first then boot will
;			process error
;R49	03/06/98 RCH	More modifications for Trend ChipAway anti-virus 
;			support, Skip BIOS virus warning if ChipAway is used
;R48	02/20/98 KVN	Fixed system hang in windows95 command prompt (not in
;			win 95 system)when repeat to copy files of large size
;			and spent long time (over 2 hours maybe).
;R47	02/18/98 KVN	Report function 08h new cylinder to match function-48h
;			return parameter to fixed DOS6.22 fdisk.exe size not
;			match with WIN95 OS-R2 of fdisk.exe
;R46A	10/22/97 KVN	Force set LBA access method in int13 extention
;			(to fixed GHOST tool problem)
;R41D	10/14/97 KVN	Exactly report parameter of EDD table in Int13
;			extension function 48h.otherwise will cause system
;			error while execute FDISK.EXE in Windows 95
;R46	09/02/97 KVN	Support LBA access method in int13 extention if define
;			"ExtInt13_LBA"
;R37E	08/13/97 KVN	Remove R37D add code to fixed ROM disk card boot fail
;R45	07/04/97 KVN	Fixed HDD(WDC AC21600H) detect fail if connect to slave
;			single
;R37D	07/01/97 KVN	Fixed MO boot fail.Asign SCSI driver letter ahead
;R44	06/13/97 KVN	Support HDD_write_protect function by setup option
;R43	05/02/97 KVN	Support HDD access of Phoenix method, PTL translate
;			the LBA with divide the cylinder number by 2 until
;			the number below than 1024 to match BIOS limitation.
;R42	03/13/97 KVN	Fixed wait FUJITSU MO (Model-NO : M2541B) ready spent
;			too much time during reset it.This is connect it to
;			secondary channel (test BIOS is 2A59GG0B)
;R41C	02/25/97 KVN	Fixed system hang at EMM386.exe add HIGHSCAN parameter
;			if BIOS include "Int13_Extensions" function
;R41B	12/05/96 KVN	Fixed R41 coding mistake that cause coretest testing
;			failure
;R41A	11/21/96 KVN	Fixed R41 coding mistake
;R41	11/15/96 KVN	Added IDE HDD Int13 Extensions function
;R30B	11/14/96 KVN	Fixed R30 coding mistake that will cause sector not
;			found error
;R40	11/06/96 KVN	Fixed some PCMCIA ROM card emulate boot to C error
;R37C	10/23/96 KVN	Prevent reentry Int 13h from SCSI ISR to fixed NCR v4.0
;			booting hang
;R39	10/22/96 KVN	Fixed function 15h return error
;R38	10/21/96 KVN	Packet virus code become a subroutine
;R37B	10/17/96 KVN	Fixed IDE HDD drive C can't boot if connect it on
;			secondary channel master and exist SCSI HDD
;R37A	10/08/96 KVN	Fixed coding mistake, it cause SCSI/HDD can not boot
;			if define CD_ROM
;R37	10/04/96 KVN	Added boot HDD selectable function
;R36A	09/23/96 KVN	Fixed NT 4.0 no emulation CD install to SCSI HDD fail
;R36	09/17/96 KVN	Add bootable CDROM no emulation support
;R35	07/24/96 KVN	Remove "Set_HDD_Standby_Timer" subrotine code to PMKERNAL.ASM
;			for reduce 0F0000h runtime code size
;R29B	07/18/96 KVN	Fixed coding mistake that cause send HDD power down command
;			error
;R34	06/21/96 KVN	Fixed master and slave drive both connect [QUANTUM-FIREBALL 1280A]
;			HDD then slave sometimes will access fail (Main Board
;			is GIGABYTE Triton-Vx)
;R29A	06/13/96 KVN	Fixed coding mistake that cause primary slave HDD and
;			secondary master HDD set timer error(i.e. if HDD connect
;			to secondary master then set HDD timer command will set
;			to primary slave)
;R33	06/12/96 KVN	Fixed system hang at MSCDEX.EXE if system none HDD only
;			plug SCSI and MITSUMI CDROM drive then hook mitsumi
;			driver in config.sys and autoexec.bat. Because PM_INIT
;			send HDD standby command to CDROM
;R32	06/07/96 KVN	Fixed can't format 1024 bytes/sector use 1024fmt.exe
;			utility because this program will call reset floppy
;			but DL above 80h (0A3h) then BIOS must return no error
;R31	05/17/96 KVN	Fixed system hang during install "Wing IV" game when
;			CDROM is [MITSUMI CRMC-FX400D] and config.sys hook
;			EMM386.EXE driver
;R30A	05/03/96 KVN	Fixed R30 coding mistake that will cause invalid function
;			execute unknow routine
;R30	05/02/96 KVN	Added heads park function (FUN19) and fixed some bug
;			when input DL over disk number but return no error
;R29	05/01/96 KVN	Support any drive boot
;R28	04/12/96 KVN	It will cause some HDD error on secondary channel if
;			master connect MAXTOR-7850AV and slave connect WDAC32500
;			so don't reset secondary channel at any time
;R25B	02/14/95 KVN	Fix CD-ROM can't found when plug Buslogic BT-956C card
;R27	01/17/95 RAY	To prevent some HDD seek error under system over 133Mhz
;R26	11/03/95 KVN	Modify G_RAM position
;R25A	10/26/95 KVN	Fixed Seagate ST-3660A plug on CH0 master and ST-51080A
;			plug on CH1 master then can't boot from HDD
;R25	10/13/95 KVN	Fix CD-ROM can't found when plug Buslogic BT-956C card
;R24C	09/21/95 KVN	Fixed R24 code bug
;R24B	09/19/95 KVN	Fixed Quantum 540AT HDD failure
;R24A	09/18/95 KVN	Fixed Quantum LP105A HDD failure if plug PCI VGA and
;			booting from floppy
;R24	09/15/95 KVN	Fixed Seagate ST32140A HDD access failure after set
;			standby timer
;R23	09/07/95 KVN	Added check port for ABIT HDD reset failure question
;R19A	08/03/95 RAY	No_Support_4_IDE should placed after "include bios.cfg"
;R22	07/04/95 KVN	Fixed code mistake cause LBA mode run WINSTONE error
;R21	06/20/95 KVN	Fixed code mistake
;R20	06/15/95 RCH	Fixed some HDDs (like CONNER) can not boot problem
;R19	06/14/95 KVN	Open Support_4_IDE feature become standard feature
;R18	05/08/95 KVN	Add CD-ROM bootable feature
;R17	03/22/95 KVN	Support HDD 32Bit access auto detect
;R16	03/20/95 BEN	Declar routine Detect_LBA_Mode public for Notebook
;			0V suspend support LBA HDD.
;R15	02/17/95 KVN	Fixed Block mode error when controller retry enable
;R08A	02/17/95 KVN	Fixed secondary master drive is SONY-CDU55E CD-ROM
;			then primary master ide initial error
;R14	02/17/95 KVN	Fixed windows 32 bits disk-access error bug
;R13	01/25/95 RCH	Move routine "Set_HDD_Standby_Timer" from pmkernal.asm
;R12	01/25/95 RCH	Enable 32bit for first channel only for some M/Bs
;R11	01/21/95 KVN	Adjust HDD parmeter for WD IDE SPEC.
;R10	01/19/95 DNL	Added IDE FIFO function support
;R09	01/05/95 KVN	Fixed FUN08 return DL(disk number) error when total
;			have 3 drive and drive 1 is absent.
;R08	12/15/94 KVN	Fixed primary slave drive is CD-ROM (e.g. PHILIP) then
;			reset error
;R07	12/07/94 KVN	FIXED LARGE MODE CAN NOT INSTALL OS/2. Because Cyl.
;			modulate error
;R05	10/18/94 RCH	Added alignment for all procedures
;R04	08/19/94 KVN	Fixed up FDISK not found drive when drive 1 is absent
;R03	08/11/94 KVN	Support new HDD structure if DRIVE 1 absent
;R02	08/04/94 RCH	Added IDE 32bit transfer support
;R01	06/08/94 KVN	For IBM SPEC
;R00	06/02/94 KVN	Initial Revision for HDD LBA/LARGE mode & 4 IDE

		PAGE	63,132
		TITLE	AHDSK  -- HARD DISK AT ROM BIOS
;R56.386
.386P						;R56

;LOCATION AT 40:

; Byte 0:442-448H is used as hard disk command block. HDC_CMD
; Byte 0:474H is hard disk status byte. DISK_STAT
; Byte 0:475H is number of hard disks on controller. NUMHDSKS
; Byte 0:476H is hard disk control byte for heads. HDC_CNTL
; Byte 0:48CH is hard disk status results. HDC_STAT_RES
; Byte 0:48DH is hard disk error results. HDC_ERR_RES
; Byte 0:48EH is hard disk interrupt flag. When FFH interrupt done, when 0
; awaiting interrupt. HDC_INT
; Byte 0:48FH is 1 when combo floppy/hard disk card present, otherwise 0.
; DCAPABILITY

; MINIMIZE SEGMENT 0 ACCESS IN PROTECTED MODE (EXCEPTION 5)

SEG_0		SEGMENT	USE16 AT 1
		INCLUDE	SEG_0.INC
SEG_0		ENDS

G_RAM		SEGMENT	USE16 AT 40H
		INCLUDE	G_RAM.INC
G_RAM		ENDS


DGROUP		GROUP	FCODE

;R56 start
ifdef	IDE_DMA_Transfer
		extrn	IDE_DMA_Flag:byte
		extrn	IDE_DMA_BMIBA:word
endif	;IDE_DMA_Transfer
;R56 end

		EXTRN	RESETDRIVES:NEAR
		extrn	PM_Before_HDD:near	;routine in PMU.ASM
		extrn	PM_After_HDD:near
;R10 - start
ifdef	IDE_FIFO_Support
		extrn	Enable_FIFO:near
		extrn	Fetch_Read:near
		extrn	Disable_FIFO:near
endif	;IDE_FIFO_Support
;R10 - end
;R24C		extrn	Reset_HDD_controller:near		;R24
;R24C		extrn	Post_call_proc:near			;R24
		extrn	SCSI_Drive_Max_Num:byte			;R37
		extrn	IDE_Drive_Max_Num:byte			;R36A
		extrn	Int13_original_address:dword		;R36A
;R58B		extrn	IDE_drive_Type:word	;R58A
ifdef Support_EDDS30						;R51A
		extrn 	Host_Bus_type:near			;R51
endif; Support_EDDS30						;R51A

;R50;R41 start
;R50ifdef	Int13_Extensions
;R50		extrn	EXTEND_FUNC_MAX:ABS
;R50		extrn	EXTEND_FUNC:near
;R50		extrn	GET_DAP_VALUE:near
;R50endif	;Int13_Extensions
;R50;R41 end

;R05 FCODE		SEGMENT	USE16 DWORD PUBLIC 'CODE'
FCODE		SEGMENT	USE16 PARA PUBLIC 'CODE'		;R05
		ASSUME	CS:DGROUP

IDE_LBA_MODE_SUPPORT	EQU	1
;R19A ifndef	No_Support_4_IDE				;R19
;R19A Support_4_IDE		EQU	1			;R19
;R19A endif	;No_Support_4_IDE				;R19
.XLIST
ExtInt13_LBA		equ	1				;R46A
	INCLUDE	BIOS.CFG

ifndef	No_Support_4_IDE					;R19A
Support_4_IDE		EQU	1				;R19A
endif	;No_Support_4_IDE					;R19A

	INCLUDE COMMON.EQU

	INCLUDE 8259.EQU
	INCLUDE HDISK.EQU
	INCLUDE CMOS.EQU
	INCLUDE AHDSK.EQU

	INCLUDE POST.EXT
	INCLUDE ADISK.EXT
	INCLUDE ATORGS.EXT

	INCLUDE COMMON.MAC
	INCLUDE SETSPEED.EXT
	include	bsetup.inc			;R33

.LIST

		PAGE

;[]---------------------------------------------------------------------[]
;
; Check_Award_CMOS
;	This routine will perform a checksum to a few specified locations
;	in the CMOS RAM area.
;
; Saves:  All except carry flag
;
; Input:  None
; Output: None
;
; Note: Since the CMOS locations have not been identified at this time,
;       this routine will always return with carry flag set.
;
; Author: Jay Judoprasetijo
; Date:	  May 4, 1990
;
; Rev	| Name 	| Date     | TPR#  | Description
; ------------------------------------------------------------------------
; 00	: JJ	| 05/04/90 | NEW   | Initial revision
;
;[]=====================================================================[]
		align	4			;R05
		PUBLIC	Check_Award_CMOS

Check_Award_CMOS PROC	NEAR

		stc
		ret

Check_Award_CMOS ENDP

		PAGE

		PUBLIC	HRDSKIO			; *
		ALIGN	4
HRDSKIO		PROC	FAR

		STI
		CMP	DL,80H			; is this a fixed disk access
		JAE	SHORT IS_HRD		; yes, jump to fixed disk bios
						; no, call INT 40 (floppy code)
		PUSH	AX			; CREATE SPACE FOR FAR RET TO INT 40
		PUSH	AX
		PUSH	BP			; SET UP BP AS PTR TO SPACE
		MOV	BP,SP
		PUSH	AX
		PUSH	DS
		MOV	AX,SEG_0		; 303C
		MOV	DS,AX
		ASSUME	DS:SEG_0
		MOV	AX,WORD PTR SEG_0:INT40
		MOV	[BP+2],AX		; PUT INT 40 VECTOR ON STACK
		MOV	AX,WORD PTR SEG_0:INT40+2
		MOV	[BP+4],AX
		POP	DS
		ASSUME	DS:NOTHING
		POP	AX
		POP	BP
		RET				; FAR RET TO INT 40 VECTOR

; THE ABOVE ACTION IS TAKEN TO ELIMINATE THE 3 WORDS OF STACK USED
; TO PERFORM THE INT 40 DIRECTLY

		ALIGN	4			; N3.03
IS_HRD:

;R18 start
;R37IFDEF CD_ROM
;------------------- check for CD emulation of C: --------------
	push	dx	;R36A
    push  ds
    push  ax
    mov   ax,G_RAM
    mov   ds,ax
    assume ds:G_RAM
IFDEF CD_ROM	;R37
	mov	al,byte ptr G_RAM:[CDROM_ALLOCATE]
	and	al,0fh
	shr	al,2
;R36 start
	cmp	al,NO_EMUL	;No emulating mode?
	jne	short @F
;R36A	pop	ax
;R36A	pop	ds
	cmp	dl,CDROM_EMUL_NUM	;Is Emulate drive number
	jne	short no_cd_c
	jmp	short Call_Int13x
@@:
;R36 end
    cmp   al,CD_DRVC		; emulating drive c?
;R36A    pop   ax
;R36A    pop   ds
    jne   short no_cd_c
    cmp   dl,80h		; drive C?
;R36A    jne   short no_cd_c
	je	short Call_Int13x	;R36A
	dec	dl			;R36A
	jmp	short no_cd_c		;R36A
; calling drive 80 (the CD)
Call_Int13x:				;R36
	pop	ax	;R36A
	pop	ds	;R36A
	pop	dx	;R36A
	extrn	std_atapi:near
	call	std_atapi
    retf  2
no_cd_c:
;R36A start
ENDIF	;CD_ROM	;R37
;R37	pop	ax
;R37	pop	ds
;R37	cmp	dl,cs:[IDE_Drive_Max_Num]		;drive number handleable?
;R37	jb	short @F				;Yes,continue
ifdef Replace_Int13_to_AHDSK				;R37
	cmp	word ptr cs:[Int13_original_address+2],0ffffh;INT 13 replaced by SCSI ?
;R37	je	short @F
;R37 start
;R57	je	short Go_IDE_HDD      		;no , go normal INT 13H
	je	Go_IDE_HDD      		;R57 no , go normal INT 13H
	test	G_RAM:[CDROM_ALLOCATE],Call_SCSI_Subroutine	;call from SCSI ISR? 		;R37C
;R57	jnz	short Go_IDE_HDD      				;Yes , go normal INT 13H	;R37C
	jnz	Go_IDE_HDD      		;R57 Yes , go normal INT 13H

	;INT 13H was replaced by SCSI or other controller
	mov	al,G_RAM:[NUMHDSKS]   		;check max. drives number
	add	al,80h
	cmp	dl,al				;input driver NO. too big
	jae	short Go_IDE_HDD		;yes, go normal INT 13H

;R57 start
	mov	al,cs:[SCSI_Drive_Max_Num]
	dec	al
	mov	ah,dl
	test	byte ptr ds:[CDROM_ALLOCATE],Enable_SCSI_Boot;SCSI boot first ?
	jnz	short @F			;no, go normal boot from IDE
	mov	al,cs:[IDE_Drive_Max_Num]	;get max. IDE drives no.
;R57A	sub	dl,al				;
;R57A	add	dl,80h				;
	xchg	al,ah
@@:
	cmp	al,ah				;AH is input drive no.
	jb	short Go_IDE_HDD
	jmp	short Go_SCSI_Routine
Not_SCSI_First:
;R57 end
	mov	al,cs:[IDE_Drive_Max_Num]	;get max. IDE drives no.
;R37A	cmp	al,80h
;R37A	jbe	short @F
	dec	al
;R37A@@:
	mov	ah,dl
	test	byte ptr ds:[CDROM_ALLOCATE],Enable_SCSI_Boot;SCSI boot first ?
	jz	short @F			;no, go normal boot from IDE
	mov	al,cs:[SCSI_Drive_Max_Num]
	xchg	al,ah
	sub	dl,80h
	add	dl,cs:[IDE_Drive_Max_Num]
@@:
	cmp	al,ah				;AH is input drive no.
	jae	short Go_IDE_HDD
Go_SCSI_Routine:				;R57
	or	ds:[CDROM_ALLOCATE],Call_SCSI_Subroutine	;R37C
	pop	ax
	pop	ds
	push	dx
;R37 end
	pushf
	call	dword ptr cs:[Int13_original_address];call replaced INT 13H
;R57 - start
;------ push flag to stack for iret -------
	push	ax
	pushf
	pop	ax
	xchg	sp,bp
	mov	[bp+10],ax
	xchg	sp,bp
	pop	ax
;R57 - end
;R37C start
;R57	pushf					;R48
	push	ds
	push	G_RAM
	pop	ds
	and	ds:[CDROM_ALLOCATE],not Call_SCSI_Subroutine
	pop	ds
;R37C end
;R37 start
	cli					;R48
	;check if needed to return value in DX
	xchg	bp,sp
;R48A	cmp	dl,[bp]				;check return value not change with original?
	cmp	dl,[bp+2]			;R48A check return value not change with original?
	xchg	bp,sp
	je	short DX_equal			;Yes,jump , don't return value
;R57	popf					;R48
	add	sp,4				;balance stack
;R57	retf	2
	iret					;R57
DX_equal:
;R57	popf					;R48
	pop	dx
;R37 end
	pop	dx
;R57	retf	2
	iret					;R57
;R37@@:
;R37 start
Go_IDE_HDD:
endif ;Replace_Int13_to_AHDSK
	pop	ax
	pop	ds
;R37 end
	pop	dx
;R36A end

;R37ENDIF	;CD_ROM
;R18 end
		call	PM_Before_HDD

		push	dx
		push	cx
		PUSH	SI
		PUSH	DS
		PUSH	ES
		PUSH	DI
		CLD
		PUSH	DX
		PUSH	CX
		PUSH	BX
		PUSH	AX


		PUSH	BP
		MOV	BP,SP

IFNDEF	   NSS
IFDEF	   SLOWDOWN_HDRV_IO
		push	ax
		mov	al,CMOS_INFO
		call	get_cmos
		test	al,00000001b		; slow hard disk feature set?
		jz	short hd_slow_done
		XOR	AL,AL			; default to low speed
;R21		POST_FUNC_CALL	XSPEED			; do it
		CALL	XSPEED			;R21
hd_slow_done:
		pop	ax
ENDIF	;SLOWDOWN_HDRV_IO
ENDIF	;NSS

		OR	WORD PTR +26[BP],200H
						; CODE AT 70:XXXX
;R41		SUB	SP,6
;R56		SUB	SP,7	;R41
		SUB	SP,AHDSK_Reserve_Stk_Buf	;R56

;R41A start
;R56ifdef	Int13_Extensions
		push	eax
		push	ebx
		push	ecx
		push	edx
;R56endif	;Int13_Extensions
;R41A end

		MOV	NUMSECS,AL
		MOV	BX,CS
		MOV	DS,BX			; set ds=cs
		ASSUME	DS:DGROUP
		MOV	BX,G_RAM
		MOV	ES,BX			; set es=0
		ASSUME	ES:G_RAM
		MOV	BL,ES:[NUMHDSKS]	; G_RAM
;R37 start
ifdef Replace_Int13_to_AHDSK
	cmp	word ptr cs:[Int13_original_address+2],0ffffh	;R40
	je	short @F					;R40
	test	byte ptr es:[CDROM_ALLOCATE],Enable_SCSI_Boot
	jz	short @F
	add	bl,80h
	sub	bl,cs:[SCSI_Drive_Max_Num]
	sub	dl,cs:[SCSI_Drive_Max_Num]
	add	dl,80h
@@:
endif ;Replace_Int13_to_AHDSK
;R37 end
;R18 start
IFDEF	CD_ROM
	mov	al,byte ptr es:[CDROM_ALLOCATE]
	and	al,0fh
	shr	al,2
	cmp	al,CD_DRVC		; emulating drive c?
	jne	short @F
	dec	dl
	dec	bl
@@:
ENDIF	;CD_ROM
;R18 end
		MOV	NUMDSKS,BL		; SS:BP PARAMETER

		SUB	DL,80H			; drive = ((dx & 0xff) - 0x80);
		or	ah,ah			;R32
		jz	short @F		;R32
		cmp	dl,bl			;R30 Compare DL is invalid
		jae	FUN10_2			;R30 Yes,jump
@@:						;R32
;R29 start
		mov	cl,dl
		shl	cl,1
		mov	al,byte ptr HDD_Drive_Port
		shr	al,cl
		and	al,3
		sub	al,dl
		add	NUMDSKS,al
		add	dl,al
;R29 end
;R29;R03 start
;R29ifdef	Support_4_IDE
;R29		test	byte ptr es:POST_FLAG,DRIVE1_ABSENT
;R29		jz	short Drive1_Present
;R29		or	dl,dl
;R29		jz	short @F
;R29		inc	dl
;R29Is_fun00:
;R29		inc	NUMDSKS
;R29		jmp	short Drive1_Present
;R29@@:
;R29		or	ah,ah
;R29		jz	short Is_fun00
;R29Drive1_Present:
;R29endif;	Support_4_IDE
;R29;R03 end
		MOV	DRIVE,DL

;R43comment %							;R07
;R43		push	ax
;R43		call	Detect_LARGE_Mode
;R43		jne	short Not_LGA_Mode
;R43		shl	byte ptr +7[BP],1
;R43		jnc	short @F
;R43		add	byte ptr +6[BP],40h
;R43@@:
;R43		mov	al,2
;R43		call	GETHPARM
;R43		shr	al,1			;div 2 = physical head
;R43		cmp	+9[BP],al		;head < physical head?
;R43		jb	short Not_LGA_Mode	;Yes, jump
;R43		sub	+9[BP],al		;head modulate correct
;R43		inc	byte ptr +7[BP]		;increase low cylinder bits
;R43		jnz	short Not_LGA_Mode	;no carry then jump
;R43		add	byte ptr +6[BP],40h	;increase high cylinder bits
;R43Not_LGA_Mode:
;R43		pop	ax
;R43%					;R07

		mov	PORT_MODULATE,0
	ifdef	Support_4_IDE
		cmp	dl,2
		jb	short @F
		mov	PORT_MODULATE,80h
	@@:
	endif	;Support_4_IDE

		mov	al,es:[SECTOR_PER_BLOCK_0]
		or	dl,dl			;Is drive 0 ?
		jz	short @F		;Yes,jump
		mov	al,es:[SECTOR_PER_BLOCK_1]
	ifdef	Support_4_IDE
		cmp	dl,1			;Is drive 1 ?
		je	short @F		;Yes,jump
		mov	al,es:[SECTOR_PER_BLOCK_2]
		cmp	dl,2			;Is drive 2 ?
		je	short @F		;Yes,jump
		mov	al,es:[SECTOR_PER_BLOCK_3]
	endif	;Support_4_IDE
@@:
		mov	SECTOR_PER_BLOCK,al

		MOV	HD_CMD,AH		; don't discriminate drive
;R41 start
ifdef	Int13_Extensions
Extend_Func_Start	equ	41h
		mov	FUNC_CMD,ah		; don't discriminate drive
		cmp	ah,Extend_Func_MAX+Extend_Func_Start
else	;Int13_Extensions
;R41 end
		cmp	ah,Func_MAX		;R30
endif	;Int13_Extensions			;R41
;R30A		jae	short INT13_6		;R30
		jae	short FUN10_2		;R30A
		OR	AH,AH			; number for reset
		JNE	SHORT INT13_2

INT13_1:
;R29		MOV	DRIVE,0
		JMP	SHORT INT13_5

INT13_2:
		CMP	AH,8
		JE	SHORT INT13_6

;R30		CMP	AH,21
;R30;R25B		JE	SHORT INT13_6
;R30		ja	SHORT INT13_6		;R25B

		CMP	AH,1			; if( o == 1)
		JE	SHORT INT13_6		; goto get_old_status

INT13_5:	MOV	DL,DRIVE		; SET OPTIONS
		MOV	AL,8
		CALL	GETHPARM

		MOV	DX,DISK_STAT_PORTB
		sub	dl,PORT_MODULATE	;R14
		OUT	DX,AL

		AND	AL,0C0H			; temp |= 0c0h
		OR	BYTE PTR ES:[HDC_CNTL],AL	; CONTROL BYTE

		call	Select_Drive		;R42
;R42		mov	al,0a0h			;R18
;R42		test	drive,1			;R18
;R42		jz	short @F		;R18
;R42		mov	al,0b0h			;R18
;R42@@:						;R18
;R42		call	Detect_LBA_Mode		;R22
;R42		jne	short @F		;R22
;R42		or	al,40h			;R22
;R42@@:						;R22
;R42		mov	dx,1f6h			;R18
;R42		sub	dl,PORT_MODULATE	;R18
;R42		out	dx,al			;R18
INT13_6:					;R18
;R30		MOV	AL,DRIVE		; if(drive >= numdsks)
;R30		CMP	AL,NUMDSKS
;R30		JAE	SHORT FUN10_2

;R18 INT13_6:
		MOV	AL,HD_CMD			; switch(o)
;R30		CMP	AL,21
;R30		JA	SHORT FUN10_2		; bad command

;R41 start
		lea	di,FUN_S0
ifdef	Int13_Extensions
		cmp	al,Func_MAX
		jb	short @F
		cmp	al,Extend_Func_Start
		jb	short FUN10_2
		sub	al,Extend_Func_Start
		lea	di,Extend_Func
@@:
endif	;Int13_Extensions
;R41 end
		MOV	AH,0
		SHL	AX,1
		add	di,ax			;R41
		jmp	word ptr cs:[di]	;R41
;R41		MOV	DI,AX
;R41		JMP	WORD PTR CS:[DI+OFFSET FUN_S0]

		public	FUN10_2			;R41
FUN10_2:	MOV	WORD PTR +2[BP],256	; DEFAULT ST_BADCMD
		JMP	ERROR_RET

;R42 start
Select_Drive:
		mov	al,0a0h
		test	drive,1
		jz	short @F
		mov	al,0b0h
@@:
		call	Detect_LBA_Mode
		jne	short @F
		or	al,40h
@@:
		mov	dx,1f6h
		sub	dl,PORT_MODULATE
		out	dx,al
		retn
;R42 end

		EVEN				; TABLE
FUN_S0:		DW	OFFSET  FUN00		;FUN00
		DW	OFFSET  FUN01		;FUN01
		DW	OFFSET	FUN02		;FUN02
		DW	OFFSET	FUN03		;FUN03
		DW	OFFSET	FUN04		;FUN04
		DW	OFFSET	FUN05		;FUN05
		DW	OFFSET	FUN10_2		;FUN06
		DW	OFFSET	FUN10_2		;FUN07
		DW	OFFSET	FUN08		;FUN08
		DW	OFFSET	FUN09		;FUN09
		DW	OFFSET	FUN0A		;FUN0A
		DW	OFFSET	FUN0B		;FUN0B
		DW	OFFSET	FUN0C		;FUN0C
		DW	OFFSET	FUN0D		;FUN0D
		DW	OFFSET	FUN10_2		;FUN0E
		DW	OFFSET	FUN10_2		;FUN0F
		DW	OFFSET	FUN10_1		;FUN10
		DW	OFFSET	FUN11		;FUN11
		DW	OFFSET	FUN10_2		;FUN12
		DW	OFFSET	FUN10_2		;FUN13
		DW	OFFSET	FUN14		;FUN14
		DW	OFFSET	FUN15		;FUN15
;R30 start
		DW	OFFSET	FUN10_2		;FUN16
		DW	OFFSET	FUN10_2		;FUN17
		DW	OFFSET	FUN10_2		;FUN18
		DW	OFFSET	FUN19		;FUN19
Func_MAX	EQU	($-offset FUN_S0)/2
;R30 end

		PAGE
;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Reset
;Entry:  	INT 13H
;Input:  	ah=0
;                dl=80-81H for hard disks
;Output: 	none
;Description:
;
;Disk_IO_Reset will:
;1. 	save environment
;2. 	Indicate drives need recalibration. Reset controller. Update
;        memory values. For hard disk reset drive parameters and recalibrate
;        drive.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN00:

		xor	dl,dl		;R32
		int	40H		;floppy reset, AH is already a 0!

		xor	dx,dx
FUN00_3:
		push	dx		;R29
;R37B start
ifdef Replace_Int13_to_AHDSK
		mov	cl,cs:[IDE_Drive_Max_Num]
		sub	cl,80h
		cmp	dl,cl
else ;Replace_Int13_to_AHDSK
;R37B end
		cmp	dl,NUMHDSKS	;R29
endif ;Replace_Int13_to_AHDSK		;R37B
;R29		mov	DRIVE,dl
;R29		CMP	DL,NUMDSKS
		jb	short @F
Reset_Ret:
		jmp	FUN00_4
@@:
		mov	PORT_MODULATE,0
;R29 start
		mov	cl,dl
		shl	cl,1
		mov	dl,byte ptr HDD_Drive_Port
		shr	dl,cl
		and	dl,3
		mov	DRIVE,dl
;R29 end
ifdef	Support_4_IDE
;R29;R03 start
;R29		cmp	dl,1
;R29		jne	short @F
;R29		test	byte ptr es:POST_FLAG,DRIVE1_ABSENT
;R29		jz	short @F
;R29		inc	dl
;R29		mov	DRIVE,dl
;R29@@:
;R29;R03 end
		cmp	dl,2
		jb	short @F
		mov	PORT_MODULATE,80h
@@:
endif	;Support_4_IDE
;R28		test	dl,1
		or	dl,dl			;R28
		jnz	short fun00_2

		MOV	AL,8
		CALL	GETHPARM

		MOV	AH,AL			; ah = temp
		MOV	DX,DISK_STAT_PORTB
		sub	dl,PORT_MODULATE
		OUT	DX,AL
		CLI
		IODELAY
		IN	AL,B8259+1
		IODELAY
;R54 start
ifdef MASK_USED_HDD_IRQ
		mov	bl,not 40h		;enable IRQ 14 for primary channel
		cmp	PORT_MODULATE,0
		je	short @F
		mov	bl,not 80h		;enable IRQ 15 for second channel
@@:
		and	al,bl
else ;MASK_USED_HDD_IRQ
;R54 end
	ifdef	Support_4_IDE
		AND	AL,3FH
	else	;Support_4_IDE
		AND	AL,0BFH
	endif	;Support_4_IDE
endif ;MASK_USED_HDD_IRQ			;R54
		OUT	B8259+1,AL
		STI
		MOV	AL,4			; outportb(hdreg,4)
		OUT	DX,AL			; dx still 3F6H

		XOR	BX,BX
;R34		MOV	CX,WAITCPU_RESET_ON	; 40uSEC
;R34		ALIGN	4			; N3.03
;R34		LOOP	SHORT $
		mov	cx,24h			;R34
		call	WAIT_REFRESH		;R34

		MOV	AL,AH			; outportb(hdreg,temp & 0xf)
		AND	AL,0FH
		OUT	DX,AL			; dx is still 3F6H

		call	Select_Drive		;R42
		CALL	CTLR_BUSY		; if(ctlr_busy() ||(inportb(0x1f1)!+1))
		JNE	SHORT FUN00_1

		MOV	DX,1F1H
		sub	dl,PORT_MODULATE
		mov	cx,10				;R23
@@:							;R23
		IN	AL,DX
;R23		mov	dl,DRIVE
		CMP	AL,1
		JE	SHORT FUN00_2
		loop	short @B				;R23
;R08A		or	al,al				;R08
;R08A		jz	short FUN00_2			;R08

FUN00_1:
		MOV	WORD PTR +2[BP],1280
		JMP	SHORT FUN00_5
FUN00_2:
		call	Select_Drive		;R42
		xor	dh,dh				;R23
		mov	dl,DRIVE			;R23

;R34		PUSH	DX
;R34		CALL	INIT_DRIVE		; init_drive(temp)
;R34		POP	DX

		PUSH	DX
		CALL	RECAL_DRIVE		; recal_drive(temp)
		POP	DX
		PUSH	DX			;R34
		CALL	INIT_DRIVE		;R34
		POP	DX			;R34

;R26		test	byte ptr es:FDD_VERIFY_CMD_FLAG,80h
		test	byte ptr es:POST_FLAG,IDE_Block_Mode	;R26
		jz	short Not_Support_Multi			; Yes,jump and not set multiple command
		mov	al,es:SECTOR_PER_BLOCK_0
		or	dl,dl
		jz	short @F
		mov	al,es:SECTOR_PER_BLOCK_1
		cmp	dl,1			;Is drive 1 ?
		je	short @F		;Yes,jump
		mov	al,es:[SECTOR_PER_BLOCK_2]
		cmp	dl,2			;Is drive 2 ?
		je	short @F		;Yes,jump
		mov	al,es:[SECTOR_PER_BLOCK_3]
@@:
		mov	SECTOR_PER_BLOCK,al
		call	set_multiple				; check multiple mode
		or	ax,ax					; have any error?
		jz	short Support_Multi			; Yes,jump and not set multiple command
Not_Support_Multi:
		or	dl,dl
		jnz	short @F
		mov	es:SECTOR_PER_BLOCK_0,1
		jmp	short Set_block_error_end
@@:
		cmp	dl,1
		jne	short @F
		mov	es:SECTOR_PER_BLOCK_1,1
		jmp	short Set_block_error_end
@@:
		cmp	dl,2
		jne	short @F
		mov	es:SECTOR_PER_BLOCK_2,1
		jmp	short Set_block_error_end
@@:
		mov	es:SECTOR_PER_BLOCK_3,1

Set_block_error_end:

Support_Multi:
		pop	dx	;R29
		inc	dl	;R29
;R29		INC	DX
		JMP	FUN00_3
FUN00_4:
;R58B		call	Send_ATAPI_NOP_CMD			;R58
		MOV	WORD PTR +2[BP],0	; ax = 0

FUN00_5:
		pop	dx	;R29
		JMP	INT13_RET

		PAGE
;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Status
;Entry:  	INT 13H
;Input:  	ah=1
;                dl=0-1 for diskette
;                dl=80-81H for hard disk
;Output: 	al=status
;                    Values are:
;                    CCH write fault on drive
;                    BBH unknown error occured
;                    AAH drive not ready
;                    80H time out
;                    40H bad seek
;                    20H bad controller
;                    11H data corrected on transfer
;                    10H bad ECC or CRC
;                     BH bad track found
;                     AH bad sector flag found
;                     9H dma boundary error (transfer across 64K bank)
;                     8H bad dma transfer occured
;                     7H drive failed
;                     6H media removed
;                     5H reset failed
;                     4H sector not found
;                     3H write attempted on write protected media
;                     2H data address mark not found
;                     1H bad command
;                     0H no error found
;Description:
;
;Disk_IO_Status will:
;1. 	save environment
;2. 	Return indicated status byte.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN01:		XOR	AX,AX			; ax = getd(hdisk_status,0)
		MOV	AL,BYTE PTR ES:[DISK_STAT]
		MOV	+2[BP],AX
		JMP	GOOD_RET

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Read
;Entry:  	INT 13H
;Input:  	ah=2
;                al=number of sectors
;                dl=drive number (0-1 for diskette, 80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;                es:bx=transfer address
;
;Output: 	ah=status (see function 1 above)
;                cy=1 if error, cy=0 if ok.
;Description:
;
;Disk_IO_Read will:
;1. 	save environment
;2. 	Read in requested number of sectors starting at ES:BX.
;	Update data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN02:		MOV	HD_CMD,20H
		JMP	CONT_CMD

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Write
;Entry:  	INT 13H
;Input:  	ah=3
;                al=number of sectors
;                dl=drive number (0-1 for diskette, 80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;                es:bx=transfer address
;
;Output: 	ah=status (see function 1 above)
;                cy=1 if error, cy=0 if ok.
;Description:
;
;Disk_IO_Write will:
;1. 	save environment
;2. 	Write out requested number of sectors starting at ES:BX.
;	Update data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN03:
;R44 start
ifdef	Support_HDD_Write_Protect
		mov	byte ptr +3[bp],3
		test	byte ptr G_RAM:POST_FLAG,HDD_Wt_Protect
		jnz	Error_Ret
endif	;Support_HDD_Write_Protect
;R44 end
ifndef	Trend_AntiVirus					;R49
		call	Check_Write_Protect		;R38
endif;	Trend_AntiVirus					;R49
		MOV	HD_CMD,30H
		JMP	CONT_CMD

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Verify
;Entry:  	INT 13H
;Input:  	ah=4
;                al=number of sectors
;                dl=drive number (0-1 for diskette, 80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;
;Output: 	ah=status (see above)
;                cy=1 if error, cy=0 if ok.
;Description:
;
;Disk_IO_Verify will:
;1. 	save environment
;2. 	see hard disk spec.
;3. 	Verify the requested number of sectors. Update data values 0:4??H as
;        needed.
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN04:		MOV	HD_CMD,40H
		JMP	CONT_CMD

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Format
;Entry:  	INT 13H
;Input:  	ah=5
;                al=number of sectors
;                dl=drive number (0-1 for diskette, 80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;                es:bx=transfer address
;                    if hard drive then es:bx points to 512 byte buffer with
;                     n pairs of {f,s}.
;                     where n is number of sectors
;                           f is flag 0 is good sector, 80H is bad sector
;                           s is sector number
;                    if diskette drive then es:bx points to 512 byte buffer
;                     n pairs of (c,h,s,l)
;                     where n is number of sectors
;                           c is cylinder number
;                           h is head number
;                           s is sector number
;                           l is sector length (l = 0 is 128, l = 1 is 256
;                                l = 2 is 512, l = 3 is 1024).
;Output: 	ah=status (see above)
;                cy=1 if error, cy=0 if ok.
;Description:
;
;Disk_IO_Format will
;1. 	save environment
;2.  	Check DMA boundary conditions,setup DMA chip for transfer. Format
;        track given sector pattern starting at ES:BX. Update data values at
;        0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN05:		MOV	HD_CMD,50H

		MOV	DL,DRIVE
		MOV	AL,14
		CALL	GETHPARM
		MOV	NUMSECS,AL
		JMP	CONT_CMD

		PAGE

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_DriveParams
;Entry:  	INT 13H
;Input:  	ah=8
;                dl=80-81H for hard disk
;Output: 	if hard drive for dl
;                 cy = 0, al = 0
;                  dl=number of consecutive drives attached
;                  dh=maximum head number - bits 0-5
;BUG!
;                  ch=maximum usable cylinder value (low 8 bits)
;                  cl=maximum usable sector value (bits 0-5) and
;                    the high (bits 6-7) cylinder value bits (always < 1023)
;               else cy = 1, al = 1
;
;Description:
;
;Disk_IO_DriveParams will:
;1. 	save environment
;2. 	set regs as shown obtained from table pointered to by INT 41 and 46H.
;3. 	restore environment
;4. 	return to POI
;
; TRY THIS
;                dl=drive number (80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;[]------------------------------------------------------------------------[]

		PUBLIC	FUN08
FUN08:		MOV	DL,DRIVE
		cmp	dl,NUMDSKS
		JB	SHORT FUN08_1		; OK DRIVE 0 OR 1

		JMP	FUN08_ERR		; ERROR : MORE THAN 2 DRIVES

FUN08_1:
IFNDEF		HDEXTRA
		MOV	AL,2			; dl = DRIVE
		CALL	GETHPARM
		SUB	AL,1
		MOV	AH,AL
;R18 start
IFDEF	CD_ROM
	mov	al,byte ptr es:[CDROM_ALLOCATE]
	and	al,0fh
	shr	al,2
	cmp	al,CD_DRVC		; emulating drive c?
	jne	short @F
	inc	NUMDSKS
@@:
ENDIF	;CD_ROM
;R18 end
;R29		MOV	AL,NUMDSKS
;R29;R04 start
;R29		cmp	dl,2
;R29;R09		jne	short @F
;R29		jb	short @F		;R09
;R29		test	byte ptr es:POST_FLAG,DRIVE1_ABSENT
;R29		jz	short @F
;R29		dec	al
;R29@@:
;R29;R04 end
		MOV	AL,es:NUMHDSKS	;R29
		MOV	+8[BP],AX
ENDIF						; HDEXTRA

		MOV	AL,0			; dl = DRIVE
		CALL	GETHPARM

IFNDEF		HDEXTRA
		CMP	AX,1024			; only allow max cylinders >
		JB	SHORT FUN08_1A		; 1024
		MOV	AX,1024

ENDIF						; HDEXTRA

FUN08_1A:
;R47		SUB	AX,2
		dec	ax			;R47
;R52 - start
ifdef	INT13_Func08_Cylinder_Sub_1
		dec	ax
endif;	INT13_Func08_Cylinder_Sub_1
;R52 - end
		MOV	CX,AX			; temp = cx = ax

IFDEF	HDEXTRA
		PUSH	AX			; SAVE MAXIMUM CYLINDERS FOR LATER USE
ENDIF	;HDEXTRA

		AND	CX,0300H
		SHR	CX,1
		SHR	CX,1
		MOV	CH,AL

		MOV	AL,14			; dl = DRIVE
		CALL	GETHPARM

		OR	CL,AL
IFDEF	HDEXTRA

		MOV	+6[BP],CX		; SAVE CX VALUE

		MOV	AL,2			; dl = DRIVE
		CALL	GETHPARM
		SUB	AL,1
		MOV	AH,AL
;R29		MOV	AL,NUMDSKS
;R29;R04 start
;R29		cmp	dl,2
;R29;R09		jne	short @F
;R29		jb	short @F		;R09
;R29		test	byte ptr es:POST_FLAG,DRIVE1_ABSENT
;R29		jz	short @F
;R29		dec	al
;R29@@:
;R29;R04 end
		MOV	AL,es:NUMHDSKS	;R29
		POP	BX			; RESTORE MAXIMUM CYLINDERS
		AND	BX,0C00H		; ISOLATE CYLINDER BITS 10 AND 11
		MOV	CL,4H
		SHR	BX,CL			; SHIFT TO BIT POSITIONS 6 AND 7
		OR	AL,BL			; <OR> IN TO DRIVE NUMBER
		MOV	+8[BP],AX

		MOV	WORD PTR +2[BP],0	; ax=0
		JMP	SHORT FUN08_2		; RETURN

FUN08_ERR:	XOR	AX,AX
		MOV	+8[BP],AX
		MOV	+6[BP],AX
		MOV	WORD PTR +2[BP],1792	; ax = ST_INITFAIL

FUN08_2:	JMP	INT13_RET

ELSE

		MOV	+6[BP],CX

		MOV	WORD PTR +2[BP],0	; ax=0
		JMP	SHORT FUN08_2		; RETURN

FUN08_ERR:	XOR	AX,AX
		MOV	+8[BP],AX
		MOV	+6[BP],AX
		MOV	WORD PTR +2[BP],1792	; ax = ST_INITFAIL

FUN08_2:	JMP	INT13_RET
ENDIF						; HDEXTRA

		PAGE

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_InitParams
;Entry:  	INT 13H
;Input:  	ah=9
;                dl=drive (80H-81H)
;Output: 	ah=status (see above)
;                if hard drive present
;                  cy=1, al=1 if error, cy=0, al=0 if ok.
;Description:
;
;Disk_IO_InitParams will
;1. 	save environment
;2. 	If dl = 80H init drive params from parameter vector 41H
;       if dl = 81H init drive params from parameter vector 46H
;       otherwise set error. Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN09:		MOV	DL,DRIVE
		CALL	INIT_DRIVE
		MOV	+2[BP],AX
		JMP	INT13_RET

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_ReadLong
;Entry:  	INT 13H
;Input:  	ah=AH
;                al=number of sectors
;                dl=drive number (80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;                es:bx=transfer address
;
;Output: 	ah=status (see above)
;                cy=1 if error, cy=0 if ok.
;Description:
;
;Disk_IO_ReadLong will:
;1. 	save environment
;2. 	If hard disk Read in requested number of sectors including ECC bytes.
;        If diskette set error al = 1, cy = 1
;        Update data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN0A:		MOV	HD_CMD,34
		JMP	CONT_CMD

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_WriteLong
;Entry:  	INT 13H
;Input:  	ah=BH
;                al=number of sectors
;                dl=drive number (80-81H for hard disk)
;                dh=head number - bits 0-5
;		    bits 6-7 are the extended high cylinder (cyls > 1024)
;                ch=cylinder number - low 8 bits
;                cl=sector number - bits 0-5
;                   bits 6-7 are high 2 cylinder bits
;                es:bx=transfer address
;
;Output: 	ah=status (see above)
;                cy=1 if error, cy=0 if ok.
;Description:
;
;Disk_IO_WriteLong will:
;1. 	save environment
;2. 	If hard disk Write out requested number of sectors including ECC bytes.
;        If diskette set error al=1, cy=1
;        Update data values at 0:4??H as neccessary.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN0B:		MOV	HD_CMD,50
		JMP	CONT_CMD

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Seek
;Entry:  	INT 13H
;Input:  	ah=CH
;                dl=drive (80H-81H)
;Output: 	ah=status (see above)
;                if hard drive present
;                  cy=1, al=1 if error, cy=0, al=0 if ok.
;Description:
;
;Disk_IO_Seek will
;1. 	save environment
;2. 	If hard disk seek to specified cylinder
;        If diskette return error al=1, cy=1
;        Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN0C:		MOV	HD_CMD,70H
		JMP	CONT_CMD

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Alt_Reset
;Entry:  	INT 13H
;Input:  	ah=DH
;                dl=drive (80H-81H)
;Output: 	ah=status (see above)
;                if hard drive present
;                  cy=1, al=1 if error, cy=0, al=0 if ok.
;Description:
;
;Disk_IO_Alt_Reset will
;1. 	save environment
;2. 	If hard disk reset only the specified drive
;        If diskette return error al=1, cy=1
;        Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN0D:		JMP	FUN00

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Test_Ready
;Entry:  	INT 13H
;Input:  	ah=10H
;                dl=drive (80H-81H)
;Output: 	ah=status (see above)
;                if hard drive present
;                  cy=1,al=status if error or not ready, cy=0,al=0 if ready.
;Description:
;
;Disk_IO_Test_Ready will
;1. 	save environment
;2. 	If hard disk specified ready then set status else return error
;        If diskette return error al=1, cy=1
;        Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN10_1:	MOV	AL,DRIVE
		and	al,1
		MOV	CL,4
		SHL	AL,CL
		OR	AL,0A0H
		MOV	DH,+9[BP]
		call	large_mode_head_adjust           ;R07
		AND	DH,0FH
		OR	AL,DH
		call	Detect_LBA_Mode		;R22
		jne	short @F		;R22
		or	al,40h			;R22
@@:						;R22
		CALL	CKDRIVERDY
		MOV	+2[BP],AX
		JMP	INT13_RET

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Recalib
;Entry:  	INT 13H
;Input:  	ah=11H
;                dl=drive (80H-81H)
;Output: 	ah=status (see above)
;                if hard drive present
;                  cy=1,al=status if error or not recalibrated,
;                  cy=0,al=0 if recalibreated.
;Description:
;
;Disk_IO_Recalib will
;1. 	save environment
;2. 	If hard disk specified recalibrated then set status else return error
;        If diskette return error al=1, cy=1
;        Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN11:		MOV	DH,+9[BP]
		call	large_mode_head_adjust       ;R07
		MOV	DL,DRIVE
		CALL	RECAL_DRIVE
		MOV	+2[BP],AX
		JMP	INT13_RET

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Diagnosis
;Entry:  	INT 13H
;Input:  	ah=14H
;                dl=drive (80H-81H)
;Output: 	ah=status (see above)
;                if hard drive present
;                  cy=1,al=status if error on diagnosis,
;                  cy=0,al=0 if pass diagnosis.
;Description:
;
;Disk_IO_Diagnosis will
;1. 	save environment
;2. 	If hard disk specified passes internal controller diagnosis
;         then set status else return error
;        If diskette return error al=1, cy=1
;        Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN14:		CALL	RUN_DIAGS
		MOV	+2[BP],AX
		JMP	INT13_RET

		PAGE

;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_Read_DASD
;Entry:  	INT 13H
;Input:  	ah=15H
;                dl=drive (0-1 diskette, 80H-81H hard)
;Output: 	ah=0 not present
;                  =1 diskette - no change line available
;                  =2 diskette - change line available
;                  =3 hard
;                cy=0 unless drive specified out of bounds. Then cy=1, al=1
;Description:
;
;Disk_IO_Read_DASD will
;1. 	save environment
;2. 	If drive in bounds then set ah as indicated above else set error.
;        Set data values at 0:4??H as needed.
;3. 	restore environment
;4. 	return to POI
;
;[]------------------------------------------------------------------------[]

FUN15:		MOV	DL,DRIVE
		MOV	AL,NUMDSKS
		CMP	AL,DL
		JBE	SHORT FUN15_2

		MOV	AL,0			; dl = drive
		CALL	GETHPARM
		SUB	AX,1
		MOV	CX,AX

		MOV	AL,14			; dl = drive
		CALL	GETHPARM
		MOV	BX,AX

		MOV	AL,2			; dl = drive
		CALL	GETHPARM

		MUL	BL
		XOR	DX,DX
		MUL	CX
		MOV	+8[BP],AX
		MOV	+6[BP],DX
		MOV	WORD PTR +2[BP],0300H	; ax = 0x300
		JMP	SHORT FUN15_3

FUN15_2:	XOR	AX,AX
		MOV	+8[BP],AX
		MOV	+6[BP],AX
		MOV	+2[BP],AX

FUN15_3:	JMP	GOOD_RET

;R30 start
		PAGE
;[]------------------------------------------------------------------------[]
;Name:   	Disk_IO_PARK_HEADS
;Entry:  	INT 13h
;Input:  	AH = 19h
;               DL = Drive No.(80h is dirve 0,81h is drive1 ....)
;Output: 	CF = 0 no error
;		   = 1 error
;		AH = Status
;Description:
;
;[]------------------------------------------------------------------------[]
FUN19:
		mov	ah,70h			;Seek command
		mov	HD_CMD,ah
		mov	al,0A0h			;assume master drive
		mov	dl,DRIVE
		test	dl,1
		jz	short @F
		mov	al,0B0h			;set slave drive
@@:
		push	ax			;for SDH & command register value
		mov	al,0ch			;get LANDZONE value
		call	GETHPARM
		push	ax			;for Cylinder LOW & HIGH register value
;R30B		xor	ax,ax
;R30B		push	ax			;for Sector count & number register value
		push	100h			;R30B set Sector count=0 & sector number=1
		jmp	LBA_is_enable
;R30 end
		PAGE
		ALIGN	4
		public	CONT_CMD			;R41
CONT_CMD:
;SEND A COMMAND TO THE CONTROLER

		CMP	HD_CMD,64			; if(HD_CMD < 0x40)
;R56		JAE	SHORT CMD_1
		jae	cmd_1				;R56

		test	HD_CMD,2			; test is long mode operator
		jnz	short Is_Long_Cmd		; Yes,jump and no check multiple mode
;R56 start
ifdef	IDE_DMA_Transfer
		mov	ch,1				;assume drive 0 flag
		mov	cl,drive			;get drive no.
		shl	ch,cl				;set to appropriate bit
		test	cs:[IDE_DMA_Flag],ch		;DMA support?
		jz	short No_DMA_Support

 		smsw	ax
		test	al,1
		jnz	short No_DMA_Support		;Yes,skip

		shr	HD_CMD,3
		add	HD_CMD,0c4h			;read = 0c8h/write = 0cah
		jmp	short Is_Long_Cmd
No_DMA_Support:
endif	;IDE_DMA_Transfer
;R56 end
		cmp	SECTOR_PER_BLOCK,1
		jbe	short Is_Long_Cmd
		shr	HD_CMD,4
		add	HD_CMD,0c2h			; read = 0c4h/write = 0c5h
Is_Long_Cmd:
		MOV	BX,WORD PTR +4[BP]	; if(ax = ck_dma(o,numsecs,buffer & 0xf))
		AND	BX,+15			; MASM5 REMOVED

;R41 start
ifdef	Int13_Extensions
		push	bx			;R41B
		cmp	byte ptr FUNC_CMD,41h	;R41C;function call(AH) below 41h
		jb	short @F		;R41C;Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Block_Count
		call	Get_DAP_Value
		jc	short @F
		mov	NUMSECS,al
@@:
		pop	bx			;R41B
endif	;Int13_Extensions
;R41 end
		MOV	AL,NUMSECS
		MOV	AH,HD_CMD
		CALL	CK_DMA
		MOV	WORD PTR +2[BP],AX
		OR	AX,AX
		JE	SHORT CMD_1

		JMP	ERROR_RET

CMD_1:
;R41 start
ifdef	Int13_Extensions
		cmp	byte ptr FUNC_CMD,41h	;R41C;function call(AH) below 41h
;R46		jb	short Standard_Int13	;R41C;Yes,standard call
		jb	Standard_Int13		;R46Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Packet_Size
		call	Get_DAP_Value
;R46		jc	short Standard_Int13		;Yes,standard call
		jc	Standard_Int13		;R46Yes,standard call
		cmp	al,10h
		jb	FUN10_2

;R46Bifndef ExtInt13_LBA				;R46
;R46B	mov	cx,20eh
;R46Bendif ;ExtInt13_LBA				;R46
ifdef IDE_LBA_MODE_SUPPORT
	call	Detect_LBA_Mode			;check LBA mode support?
	jne	short @F			;No,jump to standard HDD
;R46Bifndef ExtInt13_LBA				;R46
;R46B	mov	cx,0b04h
;R46B;R46 start
;R46Belse ;ExtInt13_LBA
ifdef ExtInt13_LBA				;R46B
		mov	bx,offset Disk_Address_Pkt.DAP_Lo_Block_Number
		call	Get_DAP_Value
		mov	edx,eax
		mov	bh,HD_CMD
		mov	bl,DRIVE
		and	bl,1
		shl	bl,4
		or	bl,0e0h			;set LBA flag
		shr	edx,24			;get LBA bits 24-27
		and	dl,0fh
		or	bl,dl
		push	bx			;push command and SDH register value
		mov	edx,eax
		shr	eax,8			;get LBA bits 8-23
		push	ax			;push cylinder low and high
		mov	bx,offset Disk_Address_Pkt.DAP_Block_Count
		call	Get_DAP_Value
		mov	ah,dl
		push	ax			;push sector number and counter
		jmp	LBA_is_enable
endif ;ExtInt13_LBA
;R46 end
@@:
endif; IDE_LBA_MODE_SUPPORT
;R46B;R46 start
;R46Bifdef ExtInt13_LBA
;R46B	mov	cx,20eh
;R46Bendif ;ExtInt13_LBA
;R46B;R46 end
;;R46B start
	mov	cx,0b04h
ifdef IDE_LBA_MODE_SUPPORT
	call	Detect_LBA_Mode			;check LBA mode support?
	je	short @F			;No,jump to standard HDD
endif ;IDE_LBA_MODE_SUPPORT
	call	Detect_LARGE_Mode			;check LBA mode support?
	je	short @F			;No,jump to standard HDD
	mov	cx,20eh
@@:
;R46B end

		mov	al,cl
		mov	dl,DRIVE
		call	GETHPARM		;get sectors per track
		mov	cl,al
		push	cx
		mov	al,ch
		mov	dl,DRIVE
		call	GETHPARM		;get heads
		mul	cl
		movzx	ecx,ax
		mov	bx,offset Disk_Address_Pkt.DAP_Hi_Block_Number
		call	Get_DAP_Value
		mov	edx,eax
		mov	bx,offset Disk_Address_Pkt.DAP_Lo_Block_Number
		call	Get_DAP_Value
		div	ecx
		pop	cx
		push	ax
		movzx	cx,cl
		mov	ax,dx
		shr	edx,16
		div	cx

		mov	ch,HD_CMD
		mov	cl,DRIVE
		and	cl,1
		shl	cl,4
		or	cl,0a0h
		and	al,0fh
		or	cl,al
		pop	bx
		push	cx			;push command and SDH register value
		push	bx			;push cylinder register value
		inc	dl			;sector number start 1
		mov	bx,offset Disk_Address_Pkt.DAP_Block_Count
		call	Get_DAP_Value
		mov	ah,dl			;restore AH
		push	ax			;push sector number and count register value
		jmp	LBA_is_enable
Standard_Int13:
endif	;Int13_Extensions
;R41 end
ifdef IDE_LBA_MODE_SUPPORT
;R31		call	Set_LBA_Reg
;R31		jnc	short LBA_is_enable
;R31 start

;LBA = [(Cylinder * "# of Heads") + Head] * Sectors/Track + Sector - 1
;Because (Cylinder * "# of Heads") maybe overflow 65535 so that can't
;multiplication (Sectors/Track).
;Solution : LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track + Sector - 1

		call	Detect_LBA_Mode
		jne	short LBA_Is_Disable
		mov	al,2
		mov	dl,DRIVE
		call	GETHPARM		;get "# of Heads"
		mov	cl,al			;store
		mov	al,14
		call	GETHPARM		;get Sectors/Track
		push	ax
		mul	cl			;"# of Heads" * Sectors/Track
		mov	cx,ax			;store
		mov	ax,+6[BP]		;cylinder and sector
		xchg	al,ah
		shr	ah,6
		mul	cx			;"# of Heads" * Sectors/Track * Cylinder
		pop	cx
		push	dx
		push	ax
		mov	al,+9[BP]		;head
		mul	cl
		mov	bx,ax
		pop	ax
		pop	dx
		add	ax,bx
		adc	dx,0
		mov	cl,+6[BP]		;get start sector
		and	cl,3fh
		dec	cl
		xor	ch,ch
		add	ax,cx
		adc	dx,0
		mov	ch,HD_CMD
		mov	cl,DRIVE
		shl	cl,4
		or	cl,dh
		or	cl,0e0h
		push	cx
		mov	dh,dl
		mov	dl,ah
		push	dx
		mov	ah,al
		mov	al,NUMSECS
		push	ax
		jmp	short LBA_is_enable
LBA_Is_Disable:
;R31 end
endif; IDE_LBA_MODE_SUPPORT
		MOV	AH,HD_CMD
		MOV	AL,DRIVE
		and	al,1
		MOV	CL,4
		SHL	AL,CL
		OR	AL,0A0H
		MOV	DX,WORD PTR +8[BP]	; get head
		call	large_mode_head_adjust             ;R07
		MOV	CH,DH			; get
		AND	CH,0C0H			; bits 10,11 of cylinder.

		AND	DH,0FH			; head - dh
		OR	AL,DH
		PUSH	AX			; ah=O, al=(head&0FH)|drive<<4|0A0H

		MOV	DX,WORD PTR +6[BP]	; cx
		AND	DL,0C0H			; isolate bits 8,9 of cyl
		MOV	CL,2
		SHR	DL,CL			; make room for bits 10,11
		OR	CH,DL			; combine bit 8,9 with 10,11.
		MOV	CL,4			; move to low bits for
		SHR	CH,CL			; port 1f5h.
		MOV	CL,DH			; cl=bits 0-7 of cylinder.
;R07 start
; in case of large mode adjust cx - the cylinder number    		
    call	Detect_LARGE_Mode
		jne	short @F
;R43    shl cx,1
;R43    mov al,2
;R43    mov dl,DRIVE
;R43    call GETHPARM
;R43    shr al,1            ; get physical head
;R43    cmp +9[BP],al
;R43    jb short @F
;R43    inc cx     ; adjust cylinder
;R43 start
		mov	al,11			;get physical heads
		mov	dl,DRIVE
		call	GETHPARM
		push	ax			;store AL for physiical heads
		mov	dh,al
		mov	al,2			;get max heads number
		mov	dl,DRIVE
		call	GETHPARM
		xor	ah,ah
		div	dh			;get times of head
		xor	ah,ah
		mul	cx
		mov	cx,ax
		pop	ax			;restore physiical heads to AL
		mov	ah,byte ptr +9[BP]	;get input heads
Large_Head0:
		cmp	ah,al
		jb	short @F
		inc	cx
		sub	ah,al
		jmp	short Large_Head0
;R43 end
@@:
;R07 ends
		PUSH	CX			; go for it

		MOV	AH,BYTE PTR +6[BP]	; Starting sector to AH
		AND	AH,NOT 0C0H		; clear cyl bits 8,9
		MOV	AL,NUMSECS
		PUSH	AX
LBA_is_enable:
;R56 start
ifdef	IDE_DMA_Transfer
		cmp	HD_CMD,0c8h
		jb	short No_DMA_Support1
		cmp	HD_CMD,0cbh
		jbe	IDE_DMA_Function
No_DMA_Support1:
endif	;IDE_DMA_Transfer
;R56 end
		CALL	SEND_CMD
		ADD	SP,6
		MOV	+2[BP],AX
		OR	AX,AX
		JE	SHORT CMD_2

		CMP	AX,4000H		; is this a seek not finished - V2.09
		JNE	SHORT CMD_1_1		; if not continue
		CMP	HD_CMD,70H		; is this a seek command
		JNE	SHORT CMD_1_1		; if not continue
		MOV	HD_CMD,71H   		; change command so that error is not igmored
CMD_1_1:
		JMP	INT13_RET

CMD_2:		CMP	HD_CMD,70H		; if(HD_CMD == 0x70)
		JNE	SHORT CMD_3

		JMP	CMD_17			; goto no_xfer

CMD_3:
;ifdef	IDE_BLOCK_MODE
                cmp     HD_CMD,0c4h         	; read multiple command?
                je      pre_cmd_11
                cmp     HD_CMD,0c5h         	; write multiple command?
                je      short Wt_multi_cmd
;endif;	IDE_BLOCK_MODE
		TEST	HD_CMD,16		; if(HD_CMD & 0x10)
		JE	CMD_10
Wt_multi_cmd:

		PUSH	DS			; SAVE DATA SEGMENT
;R41		MOV	AX,+4[BP]		; ax=writeop(o,buffer&0xf,segment+(buffer>>4))
;R41 start
ifdef	Int13_Extensions
		cmp	byte ptr FUNC_CMD,41h	;R41C;function call(AH) below 41h
		jb	short @F		;R41C;Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Buffer_Address
		call	Get_DAP_Value
		jnc	short Standard_Int13_OutData
@@:						;R41C
endif	;Int13_Extensions
		mov	ax,+4[BP]
Standard_Int13_OutData:
;R41 end
		AND	AX,WORD PTR 15
		MOV	SI,AX			; SEGMENT JUSTIFY SOURCE BUFFER OFFSET
		CALL	GETDRQ			; WAIT FOR CNTRLR TO REQUEST DATA
		OR	AX,AX
		JNZ	CMD_7

CMD_4:
		mov	cx,100h
		cmp	SECTOR_PER_BLOCK,1
		jbe	short Out_Byte_OK
		mov	ax,G_RAM
		mov	ds,ax
		ASSUME	DS:G_RAM
		mov	al,SECTOR_PER_BLOCK
		cmp	al,NUMSECS
		jbe	short Full_Block_Out
		mov	ch,NUMSECS
		mov	NUMSECS,0
		jmp	short Out_Byte_OK
Full_Block_Out:
		mov	ch,al
		sub	NUMSECS,al
Out_Byte_OK:
;endif;	IDE_BLOCK_MODE
;R41 start
ifdef	Int13_Extensions
		cmp	byte ptr FUNC_CMD,41h		;R41C;function call(AH) below 41h
		jb	short Standard_Int13_OutData1	;R41C;Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Buffer_Address
		call	Get_DAP_Value
		jc	short Standard_Int13_OutData1
		mov	dx,ax
		shr	dx,4
		shr	eax,16
		add	ax,dx
		jmp	short Set_DS_for_Wt
Standard_Int13_OutData1:
endif	;Int13_Extensions
;R41 end
		MOV	AX,+4[BP]		; SET UP SOURCE SEGMENT
		SHR	AX,4
		ADD	AX,+12[BP]
Set_DS_for_Wt:					;R41
		MOV	DS,AX
		ASSUME	DS:NOTHING
		MOV	DX,1F0H
		sub	dl,PORT_MODULATE
		CLD				; DO THE TRANSFER
		CLI

;R17 ifdef	IDE_ACCELERATOR_CONTROL
;R17 ifdef	IDE_32BIT_SUPPORT			;R02
;R17 ifdef	NO_32BIT_FOR_2ND_IDE			;R12
;R17 		cmp	dl,70H	;2nd channel ?	;R12
;R17 		je	short @F		;R12
;R17 endif;	NO_32BIT_FOR_2ND_IDE			;R12
		push	es
		MOV	AX,G_RAM
		MOV	ES,AX
		ASSUME	ES:G_RAM
;R17		test	byte ptr es:POST_FLAG,IDE_32BIT_MODE	;32bit access?
		mov	al,IDE_CH0_32BIT_MODE			;R17
		cmp	dl,70h			;2nd channel ?	;R17
		jne	short @F		;No,jump	;R17
		mov	al,IDE_CH1_32BIT_MODE			;R17
@@:								;R17
		test	byte ptr es:POST_FLAG,al;32bit access?	;R17
		pop	es
		jz	short @F				;no, 16bit
		shr	cx,1
		REP	OUTSD
		jmp	short Tran_ok1
@@:
;R17 endif ;IDE_32BIT_SUPPORT			;R02
		REP	OUTSW			; DO THE TRANSFER N3.03
Tran_ok1:
;R17 else	;IDE_ACCELERATOR_CONTROL
;R17 		REP	OUTSW			; DO THE TRANSFER N3.03
;R17 endif	;IDE_ACCELERATOR_CONTROL

		STI
		TEST	HD_CMD,2		; ECC NEEDED ?
		JZ	SHORT CMD_6

		CALL	GETDRQ
		OR	AX,AX
		JNZ	SHORT CMD_7

		MOV	DX,1F0H
		sub	dl,PORT_MODULATE
		MOV	CX,4

		ALIGN	4
CMD_5:		OUTSB
		PUSH	AX
		POP	AX
		LOOP	SHORT CMD_5

CMD_6:
		POP	DS			; RECOVER DS FOR SUBROUTINES
		PUSH	SI			; SAVE SI IN CASE WE HAVE TO WRITE MORE
		CALL	WAIT_INT		; WAIT FOR CNTRLR TO FINISH WRITE
		OR	AX,AX
		JNZ	SHORT CMD_9

		CALL	CK_STATUS		; MAKE SURE EVERYTHINGS HUNKY-DORY
		OR	AX,AX
		JNZ	SHORT CMD_9

		POP	SI
		PUSH	DS
		MOV	DX,DISK_STAT_PORT	; MORE TO TRANSFER ?
		sub	dl,PORT_MODULATE
		IN	AL,DX
		AND	AX,WORD PTR 8
;;		JNZ	SHORT CMD_4
		JNZ	CMD_4

CMD_7:		POP	DS

CMD_8:		MOV	WORD PTR +2[BP],AX
		JMP	INT13_RET

CMD_9:		POP	SI
		JMP	SHORT CMD_8

CMD_10:		TEST	HD_CMD,32	       	; if(HD_CMD & 0x20)
		JNZ	SHORT PRE_CMD_11
		JMP	CMD_17
PRE_CMD_11:

;R41		MOV	DI, 000FH
;R41		AND	DI, [BP+4]
;R41 start
ifdef	Int13_Extensions
		cmp	byte ptr FUNC_CMD,41h		;R41C;function call(AH) below 41h
		jb	short @F			;R41C;Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Buffer_Address
		call	Get_DAP_Value
		jnc	short Standard_Int13_InData
@@:							;R41C
endif	;Int13_Extensions
		mov	ax,+4[bp]
Standard_Int13_InData:
		and	ax,0fh
		mov	di,ax
;R41 end
		XOR	AX,AX			; SUCCESS RETURN CODE
		PUSH	AX

CMD_11:
		PUSH	DI
		CALL	WAIT_INT		; WAIT FOR CNTRLR
		POP	DI
		OR	AX,AX
		JNZ	CMD_15

		CALL	CK_STATUS
		or	ax,ax
		jnz	CMD_15

CMD_11_11:
		TEST	AX, AX
		JZ	SHORT KEEP_PREV_STAT

		POP	BX
		PUSH	AX
KEEP_PREV_STAT:

		mov	cx,100h
		cmp	SECTOR_PER_BLOCK,1
		jbe	short In_Byte_OK
		mov	ax,G_RAM
		mov	es,ax
		ASSUME	ES:G_RAM
		mov	al,SECTOR_PER_BLOCK
		cmp	al,NUMSECS
		jbe	short Full_Block_In
		mov	ch,NUMSECS
		mov	NUMSECS,1
		jmp	short In_Byte_OK
Full_Block_In:
		mov	ch,al
		dec	al
		sub	NUMSECS,al
In_Byte_OK:

;R41 start
ifdef	Int13_Extensions
		cmp	byte ptr FUNC_CMD,41h		;R41C;function call(AH) below 41h
		jb	short Standard_Int13_InData1	;R41C;Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Buffer_Address
		call	Get_DAP_Value
		jc	short Standard_Int13_InData1
		mov	dx,ax
		shr	dx,4
		shr	eax,16
		add	ax,dx
		jmp	short Set_DS_for_Rd
Standard_Int13_InData1:
endif	;Int13_Extensions
;R41 end
		MOV	AX,+4[BP]		; SET UP DESTINATION SEGMENT
		SHR	AX,4
		ADD	AX,+12[BP]
Set_DS_for_Rd:					;R41
		MOV	ES,AX
		ASSUME	ES:NOTHING
		MOV	DX,1F0H
		sub	dl,PORT_MODULATE
		CLD
		CLI

;R17 ifdef	IDE_ACCELERATOR_CONTROL
;R17 ifdef	IDE_32BIT_SUPPORT			;R02
;R17 ifdef	NO_32BIT_FOR_2ND_IDE			;R12
;R17 		cmp	dl,70H	;2nd channel ?	;R12
;R17 		je	short @F		;R12
;R17 endif;	NO_32BIT_FOR_2ND_IDE			;R12
		push	es
		MOV	AX,G_RAM
		MOV	ES,AX
		ASSUME	ES:G_RAM
;R17		test	byte ptr es:POST_FLAG,IDE_32BIT_MODE	;32bit access?
		mov	al,IDE_CH0_32BIT_MODE			;R17
		cmp	dl,70h			;2nd channel ?	;R17
		jne	short @F		;No,jump	;R17
		mov	al,IDE_CH1_32BIT_MODE			;R17
@@:								;R17
		test	byte ptr es:POST_FLAG,al;32bit access?	;R17
		pop	es
		jz	short @F
		shr	cx,1
;R10 - start
ifdef	IDE_FIFO_Support
		push	cx
		MOV	cl,DRIVE
		mov	al,01h
		shl	al,cl
		push	es
		mov	cx,G_RAM
		mov	es,cx
		ASSUME	ES:G_RAM
		test	byte ptr es:HDD_FIFO_FLAG,al
		pop	es
		pop	cx
		jz	short _11

		Call	Enable_FIFO		;FIFO enable
_11:
endif	;IDE_FIFO_Support
;R10 - end
		REP	INSD
;R10 - start
ifdef	IDE_FIFO_Support
		push	cx
		MOV	cl,DRIVE
		mov	al,01h
		shl	al,cl
		push	es
		mov	cx,G_RAM
		mov	es,cx
		ASSUME	ES:G_RAM
		test	byte ptr es:HDD_FIFO_FLAG,al
		pop	es
		pop	cx
		jz	short _22

		Call	Fetch_Read		;FIFO enable, disable fetch
						;read and read left 2 dword
		Call	Disable_FIFO		;FIFO disable
_22:
endif	;IDE_FIFO_Support
;R10 - end
		jmp	short Tran_ok
@@:
;R17 endif ;IDE_32BIT_SUPPORT			;R02
		REP	INSW			; DO THE TRANSFER
Tran_ok:
;R17 else	;IDE_ACCELERATOR_CONTROL
;R17 		REP	INSW			; DO THE TRANSFER
;R17 endif	;IDE_ACCELERATOR_CONTROL

		TEST	BYTE PTR HD_CMD,2	; ECC BYTES ?
		JZ	SHORT CMD_13

		STI
		CALL	GETDRQ
		OR	AX,AX
		JNZ	SHORT CMD_15

		CLI
		MOV	CX,4

CMD_12:		INSB				; GET ECC BYTES N3.03
		PUSH	AX			; delay
		POP	AX
		LOOP	SHORT CMD_12

CMD_13:
		POP	AX
		PUSH	AX
		OR	AX,AX
		JZ	SHORT CMD_14

		CMP	AX,1100H		; CONTINUE IF DATACORRECTED
		JNE	SHORT CMD_15

		POP	BX			; DISCARD SUCCESS RETURN CODE
		PUSH	AX			; PUSH DC ERROR

CMD_14:
		DEC	NUMSECS
		JNZ	CMD_11


		POP	AX
		JMP	SHORT CMD_16

CMD_15:		POP	BX			; POP SUCCESS CODE CAUSE THERE WAS AN ERROR

CMD_16:
		STI
		MOV	+2[BP],AX
		MOV	AX,G_RAM
		MOV	ES,AX
		ASSUME	ES:G_RAM
		JMP	SHORT INT13_RET

CMD_17:		CALL	WAIT_INT		; if(!(ax = wait_int()))
		MOV	+2[BP],AX
		OR	AX,AX
		JNE	SHORT INT13_RET

CMD_18:		CALL	CK_STATUS		; ax = ck_status()
		MOV	WORD PTR +2[BP],AX

INT13_RET:	CMP	HD_CMD,70H		; if((HD_CMD == 0x70) && (ax == ST_BADSEEK))
		JNE	SHORT INT13_RET_1

		CMP	WORD PTR +2[BP],4000H	; N3.03
		JNE	SHORT INT13_RET_1

		MOV	WORD PTR +2[BP],0	; ax = 0
		JMP	SHORT GOOD_RET

INT13_RET_1:	CMP	WORD PTR +2[BP],0FFH	; if(ax > 0xff)
		JBE	SHORT GOOD_RET

		public	AHDSK_ERROR_RET			;R41D
AHDSK_ERROR_RET:					;R41D
ERROR_RET:	MOV	AX,+2[BP]
		MOV	ES:[DISK_STAT],AH
		OR	WORD PTR +26[BP],+1
		JMP	SHORT INT13_RET_2

		public	GOOD_RET			;R41
GOOD_RET:	MOV	BYTE PTR ES:[DISK_STAT],0
		AND	WORD PTR +26[BP],0FFFEH

INT13_RET_2:

IFNDEF	   NSS
IFDEF	   SLOWDOWN_HDRV_IO
		mov	al,CMOS_INFO
		call	get_cmos
		test	al,00000001b		; slow hard disk feature set?
		jz	short hd_slow_exit

		MOV	AX,G_RAM		; retrieve speed G_RAM
		MOV	DS,AX
		ASSUME	DS:G_RAM
		XOR	AL,AL			; assume slow speed
		TEST	INIT_ERR_FLG,80H	; speed switch
		JZ	SHORT SET_SP
		MOV	AL,1			; set hi speed
SET_SP:
;R12		POST_FUNC_CALL	XSPEED
		CALL	XSPEED			;R12
hd_slow_exit:
ENDIF	   ; SLOWDOWN_HDRV_IO
ENDIF	   ; NSS

;R41A start
;R56ifdef	Int13_Extensions
		pop	edx
		pop	ecx
		pop	ebx
		pop	eax
;R56endif	;Int13_Extensions
;R41A end

		MOV	SP,BP
		xor	al,al		;R39 CX and DX is useful in stack
		cmp	HD_CMD,8
;R39 start
		je	short @F
		cmp	HD_CMD,15h
		je	short @F
ifdef	Int13_Extensions		;R41A
		cmp	FUNC_CMD,41h	;R41A
		je	short @F	;R41A
endif	;Int13_Extensions		;R41A
;R41A		cmp	HD_CMD,41h	;R41
;R41A		je	short @F	;R41
		mov	al,1		;restore CX and DX
@@:
		or	al,al
;R39 end
		POP	BP
		POP	AX
		POP	BX
		POP	CX
		POP	DX
		POP	DI
		POP	ES
		POP	DS
		POP	SI

		je	short @F
		pop	cx
		pop	dx
		jmp	short Func_Ret
@@:
		add	sp,4
Func_Ret:
		call	PM_After_HDD

		IRET

HRDSKIO		ENDP

		PAGE

CK_DMA:
; MODIFIED 5-20-85 TO RECEIVE OPCODE IN AH,COUNT IN AL, AND OFFSET IN bl.
; ALSO USES DX FOR n,AND CL FOR over, AND CH FOR limit

		XOR	DX,DX			; UI n = 0
		MOV	CX,8000H		; ch=80h cl=0
		TEST	AH,2			; if(opcode & 2)
		JE	SHORT .D5F4

		DEC	CH			; ; limit--
		MOV	CL,4			; ; over = 4

.D5F4:		CMP	AL,CH
		JA	SHORT .D60E		; count > limit
		JNE	SHORT .D638		; count < limit

		CMP	BL,CL			; count = limit
		JBE	SHORT .D638		; offset < over

.D60E:		MOV	DX,2304
.D638:		MOV	AX,DX
		RET

		PAGE

		align	4			;R05
SEND_CMD	PROC	NEAR
; MODIFIED 5-20-85 TO USE bx FOR k AND ax FOR n

		PUSH	BP
		MOV	SI,SP
		XOR	BX,BX

.D64B:		CMP	BX,WAITCPU_NO_SEEK	; increase time for check if
		JAE	SHORT .D688		; drive ready - V2.09

		or	al,80h			;R45
		newiodelay			;R45
		newiodelay			;R45
		MOV	AX,SS:[SI+8]
		CALL	CKDRIVERDY
		OR	AX,AX			; if((!(n=ckdriverdy(hd_dr)))||(n== ST_TIMEOUT))
		JE	SHORT .D68F

		INC	BX
		CMP	AX,-32768
		JNE	SHORT .D64B

		MOV	AX,8192

.D688:
		MOV	SP,SI
		POP	BP
		RET
SEND_CMD	ENDP

.D68F:
		MOV	BYTE PTR ES:[HDC_INT],0	; reset int flag

		CLI				; turn off ints during mask change - V3.00
		MOV	DX,0A1H			; enable interrupt chip
		IN	AL,DX
		IODELAY
;R54 start
ifdef MASK_USED_HDD_IRQ
		mov	bl,not 40h		;enable IRQ 14 for primary channel
		cmp	PORT_MODULATE,0
		je	short @F
		mov	bl,not 80h		;enable IRQ 15 for second channel
@@:
		and	al,bl
else ;MASK_USED_HDD_IRQ
;R54 end
	ifdef	Support_4_IDE
		AND	AL,3FH
	else	;Support_4_IDE
		AND	AL,0BFH
	endif	;Support_4_IDE
endif ;MASK_USED_HDD_IRQ			;R54 end
		OUT	DX,AL
		IODELAY

		MOV	DL,21H
		IN	AL,DX
		IODELAY
		AND	AL,0FBH
		OUT	DX,AL
		STI				; enable ints - V3.00

		MOV	DH,SS:[SI+9]

		MOV	DL,SS:[SI+8]
		AND	DL,010H
		MOV	CL,4
		SHR	DL,CL			; dl = drive number
		cmp	dh,91h
		je	short .d6fd_1
;R15 start
		cmp	dh,0c4h
		je	short .D6FD
		cmp	dh,0c5h
		je	short .D6FD
		cmp	dh,0c6h
		je	short .D6FD
;R15 end
		TEST	BYTE PTR ES:[HDC_CNTL],0C0H	; test for retry suppression
		JE	SHORT .D6FD		; from head control byte

		AND	DH,0F0H			; get rid of first nibble
		CMP	DH,40H			; is command read, write,
		JA	SHORT .D6FD		; or verify

		CMP	DH,20H
		JB	SHORT .D6FD

		OR	DH,1			; suppress retries by controller
		JMP	SHORT .D6FD_1

.D6FD:		CMP	DH,70H			; is this a seek command? - V3.00
		JE	SHORT STEP_TEST
		CMP	DH,10H			; is this a recalibrate?
		JNE	SHORT .D6FD_1

STEP_TEST:	MOV	AL,CMOS_AWARD_2	NMI_ON	; get param from CMOS N3.03
		CLI
		CALL	CHECK_AWARD_CMOS
		STI
		JC	SHORT .D6FD_1		; invalid data, use 0 step rate

		test	dl,1
		jz	short STEP_CONT		;data is in low nibble


		SHR	AL,CL			; get high nibble into low (cl = 4)

STEP_CONT:	AND	AL,0FH			; clear out high nibble
		OR	DH,AL			; set step rate into opcode

.D6FD_1:
		MOV	SS:[SI+9],DH

		MOV	AL,5			; dl = drive number
		CALL	GETHPARM

		MOV	CL,2			; divide by 4 for port 1f1
		SHR	AX,CL
		CLD
		MOV	DX,1F1H			; PORT FOR FIRST BYTE OF CMD BLK
		sub	dl,PORT_MODULATE
		mov	bx,4
;R34		MOV	CX,7			; 7 bytes to send.
		mov	cx,6			;R34 send date to 1x1h-1x6h
		cli				;R34

		ALIGN	4			; N3.03
SC_OUT_LP:	OUT	DX,AL
		IODELAY
		mov	al,ss:[bx+si]
		inc	bx
		INC	DX			; point to next port
		LOOP	SHORT SC_OUT_LP
;R34 start
		push	dx
		push	ax
		call	CTLR_BUSY
		pop	ax
		pop	dx
		out	dx,al
		iodelay
		sti
;R34 end
doneout:
		MOV	AX,0
		MOV	SP,SI
		POP	BP
		RET

		PAGE

CKDRIVERDY:
; MODIFIED 5-17-85 TO RECEIVE PARM IN AL AND USE ax FOR n

		PUSH	AX			; SAVE OUT BYTE
		CALL	CTLR_BUSY		; if(ctlr_busy())
		POP	AX			; RECOVER DRIVE BYTE
		JE	SHORT .D7AF

		MOV	AX,-32768		; n = ST_TIMEOUT
		JMP	SHORT .D7D6

.D7AF:		MOV	DX,502
		sub	dl,PORT_MODULATE
		OUT	DX,AL
		call	CTLR_BUSY		;R34

		CALL	CKST			; if(((n=ckst())== 1)||(n ==ST_DATACORRECTED))
		CMP	AX,1
		JE	SHORT .D7D0

.D7C9:		CMP	AX,4352
		JNE	SHORT .D7D6

.D7D0:		XOR	AX,AX
.D7D6:		RET

		PAGE

		align	4			;R05
CTLR_BUSY	PROC	NEAR
; Changed to return zero flag when done

		PUSH	BX			; check if necessary???

		MOV	DX,DISK_STAT_PORT
		sub	dl,PORT_MODULATE
		MOV	AX,8000H		; wait for top bit to be 0
		MOV	BH,CS:[WAIT_HDU_CTLR_BUSY_HI]
		MOV	CX,CS:[WAIT_HDU_CTLR_BUSY_LO]
		CALL	WAIT_FOR_PORT
		XOR	AL,AL			; assume no timeout
		OR	AH,AH
		JZ	SHORT .D7FC
		MOV	AL,1			; timeout occurred.

.D7FC:		OR	AL,AL
		POP	BX
		RET
CTLR_BUSY	ENDP

		PAGE

		align	4			;R05
		public	WAIT_INT		;R55
WAIT_INT	PROC	NEAR
; MODIFIED 5-20-85 TO USE DX FOR O,BL FOR NUMDSKS,CX FOR TEMP


		STI
		MOV	AX,9000H
		INT	15H
		MOV	AX,8000H		; n = ST_TIMEOUT
		JC	SHORT .D887

		sti
		MOV	CX,G_RAM		; es:di points to
		MOV	ES,CX			; flag variable.
		ASSUME	ES:G_RAM
		MOV	DI,OFFSET HDC_INT
;R01		MOV	AH,01H			; wait for bit 0 set.
;R55A		MOV	AH,80h			;R01
;R55A		mov	cl,DRIVE
;R55A		shr	cl,1
;R55A		shr	ah,cl
		mov	ah,0c0h			;R55A
		MOV	BH,CS:[WAIT_HDU_INT_HI]
		MOV	CX,CS:[WAIT_HDU_INT_LO]
		CALL	WAIT_FOR_MEM		; returns ah=80h if timeout.
		XOR	AL,AL			; al=0
		OR	AH,AH			; if timeout, don't clear
		JNE	SHORT .D887		; flag: recalibrate case.

.D875:		MOV	BYTE PTR ES:[DI],0	; interrupt occurred

.D887:
		CLI
		RET
WAIT_INT	ENDP

CK_STATUS:	CALL	CKST
		CMP	AX,1
		JNE	SHORT .D8A5

		CALL	CKERR

.D8A5:		RET

		PAGE

CKST:
; MODIFIED 5-20-85 TO USE cx FOR n, AL FOR temp

		MOV	AX,G_RAM
		MOV	ES,AX
		ASSUME	ES:G_RAM
		MOV	DX,DISK_STAT_PORT
		sub	dl,PORT_MODULATE
		IN	AL,DX
		NEWIODELAY			;R27

		MOV	ES:[HDC_STAT_RES],AL	; OFFSET

		TEST	AL,80H
		JNE	SHORT .D96A

		TEST	AL,20H
		MOV	CX,-13312		; n = ST_WRITEFAULT
		JNE	SHORT .D97B

		TEST	AL,40H
		MOV	CX,-22016
		JE	SHORT .D97B

		TEST	AL,10H
		MOV	CX,16384
		JE	SHORT .D97B

;R20		TEST	AL,4
;R20		MOV	CX,4352
;R20		JNE	SHORT .D97B

.D96A:		MOV	CX,AX
		AND	CL,1

.D97B:		MOV	AX,CX
		RET

		PAGE

CKERR:
; MODIFIED 5-20-85 TO USE BX FOR TEMP,AL FOR O,AH FOR index CL FOR template

		MOV	BX,-8192

		MOV	DX,1F1H
		sub	dl,PORT_MODULATE
		IN	AL,DX

		MOV	ES:[HDC_ERR_RES],AL	; ERROR RESULTS

		MOV	AH,8
		MOV	CL,80H

.D9BD:		CMP	AH,1
		JBE	SHORT .DA29

		TEST	AL,CL
		JNE	SHORT .DA03

		DEC	AH
		SHR	CL,1
		JMP	SHORT .D9BD

.DA03:		LEA	SI,HDERRORS		; n = HDERRORS[index]
		MOV	DL,AH
		XOR	DH,DH
		SHL	DX,1
		ADD	SI,DX
;R56		MOV	BX,[SI]
		MOV	BX,cs:[SI]		;R56

.DA29:		MOV	AX,BX			; return(n)
		RET

		PAGE

;ifdef	IDE_BLOCK_MODE
;************************************************************************
;	Set read/write is multiple mode.
;  input  : none
;  output : ax (=0 is OK , >100h is not support multiple mode)
;************************************************************************
		align	4			;R05
Set_multiple	PROC	NEAR
		push	dx			; save drive no.
		mov	ah,HD_CMD
    		mov     al,NUMSECS
		push	ax
		mov	al,dl			; get drive number
		and	al,1
		MOV	CL,4
		SHL	AL,CL
		OR	AL,0A0H

ifdef IDE_LBA_MODE_SUPPORT
		call	Detect_LBA_Mode
		jne	short @F
		or	al,40h
@@:
endif; IDE_LBA_MODE_SUPPORT

		MOV	DX,WORD PTR +8[BP]	; get head
		call	large_mode_head_adjust               ;R07
		AND	DH,0FH			; head - dh
		OR	AL,DH
                mov     ah,0c6h			; set multiple command
		PUSH	AX

		XOR	AX,AX
		PUSH	AX

		mov	al,SECTOR_PER_BLOCK
		xor	ah,ah
		PUSH	AX
                call    SEND_CMD
		add	sp,6
		or	ax,ax
		jnz	short multi_err_ret
                call    WAIT_INT
                or      ax,ax
                jnz     short multi_err_ret
                call    Ck_status
multi_err_ret:
		pop	bx
		mov	NUMSECS,bl
                mov     HD_CMD,bh
		pop	dx			;restore drive no.
		ret
Set_multiple	ENDP
;endif;	IDE_BLOCK_MODE

		align	4			;R05
RUN_DIAGS	PROC	NEAR
; MODIFIED 5-20-85 TO USE BX FOR O,AND CL FOR NUMDSKS

		IN	AL,B8259+1
		IODELAY

;R54 start
ifdef MASK_USED_HDD_IRQ
		mov	bl,not 40h		;enable IRQ 14 for primary channel
		cmp	PORT_MODULATE,0
		je	short @F
		mov	bl,not 80h		;enable IRQ 15 for second channel
@@:
		and	al,bl
else ;MASK_USED_HDD_IRQ
;R54 end
	ifdef	Support_4_IDE
		AND	AX,03FH
	else	;Support_4_IDE
		AND	AX,0BFH
	endif	;Support_4_IDE
endif ;MASK_USED_HDD_IRQ			;R54

		OUT	B8259+1,AL
		IODELAY

		IN	AL,A8259+1
		IODELAY
		AND	AX,0FBH			; WORD PTR 251
		OUT	A8259+1,AL

		CALL	CTLR_BUSY		; if(ctlr_busy())
		JNE	SHORT .DACD

.DA7C:
		MOV	DX,DISK_STAT_PORT
		sub	dl,PORT_MODULATE
		MOV	AL,144
		OUT	DX,AL
		IODELAY

		CALL	CTLR_BUSY		; if(ctlr_busy())
		MOV	AX,-32768
		JNE	SHORT .DAD3

.DA99:		MOV	DX,1F1H
		sub	dl,PORT_MODULATE
		IN	AL,DX
		MOV	G_RAM:[HDC_ERR_RES],AL	; ERROR RESULTS
		TEST	AL,1
		MOV	AX,0
		JNE	SHORT .DAD3

.DACD:		MOV	AX,2000H		; 8192
.DAD3:		RET

RUN_DIAGS	ENDP

		PAGE

INIT_DRIVE:
; MODIFIED 5-17 TO RECEIVE DRIVE NUMBER IN DL AND TO USE ax FOR temp

;R43		MOV	AL,2

ifdef IDE_LBA_MODE_SUPPORT
;R43		call	Detect_LBA_Mode
;R43		jne	short @F
		mov	al,11
;R43 start
		call	Detect_LBA_Mode
		je	short @F
		call	Detect_LARGE_Mode
		je	short @F
		MOV	AL,2
;R43 end
@@:
endif; IDE_LBA_MODE_SUPPORT

		CALL	GETHPARM
;R43		call	Detect_LARGE_Mode
;R43		jne	short @F
;R43		shr	al,1
;R43@@:
		SUB	AL,1
		OR	AL,0A0H

		MOV	AH,DL
		and	ah,1
		MOV	CL,4
		SHL	AH,CL
		OR	AL,AH
		MOV	AH,145			; ah=145 al=drive<<4|0A0H|gethparm(2,drive)-1
		PUSH	AX

		XOR	AX,AX
		PUSH	AX

;R43		MOV	AL,14

ifdef IDE_LBA_MODE_SUPPORT
;R43		call	Detect_LBA_Mode
;R43		jne	short @F
		mov	al,4
;R43 start
		call	Detect_LBA_Mode
		je	short @F
		call	Detect_LARGE_Mode
		je	short @F
		MOV	AL,14
;R43 end
@@:
endif; IDE_LBA_MODE_SUPPORT

		CALL	GETHPARM
		XOR	AH,AH
		PUSH	AX

		CALL	SEND_CMD
		ADD	SP,6
		OR	AX,AX
		JNE	SHORT .DB3B

		CALL	CTLR_BUSY
		MOV	AX,-32768
		JNE	SHORT .DB3B

		CALL	CK_STATUS

.DB3B:		RET

		PAGE

		align	4			;R05
RECAL_DRIVE	PROC	NEAR
; modified 9-5-85 to receive head in dh, DRIVE # IN DL AND TO USE BX FOR NUMDSKS

		MOV	AL,-96
		MOV	CL,4
		and	dl,1
		SHL	DL,CL
		OR	AL,DL
		AND	DH,0FH
		OR	AL,DH
		MOV	AH,16			; ah=16 al=0A0h|drive>>4|head&0Fh
		PUSH	AX

		XOR	AX,AX
		PUSH	AX
		PUSH	AX

		CALL	SEND_CMD
		ADD	SP,6
		OR	AX,AX
		JNE	SHORT .DB8D

		CALL	WAIT_INT
		OR	AH,AH
		JZ	SHORT RD_CHECK_STATUS

		CALL	WAIT_INT
		OR	AH,AH
		JZ	SHORT RD_CHECK_STATUS

		CALL	WAIT_INT		; if(!(temp = wait_int()))
		OR	AX,AX
		JNE	SHORT .DB8D
No_Wait_Int:
;R05endif;	NO_WAIT_HDD_INT

RD_CHECK_STATUS:
		CALL	CK_STATUS		; if((temp = ck_status()) == ST_BADSEEK)
		CMP	AX,16384
		JNE	SHORT .DB8D

		MOV	AX,0

.DB8D:		RET
RECAL_DRIVE	ENDP

;WAIT FOR CNTRLR TO REQUEST DATA

		ALIGN	4
GETDRQ		PROC	NEAR
		PUSH	DX
		PUSH	BX

		MOV	DX,DISK_STAT_PORT
		sub	dl,PORT_MODULATE
		MOV	AX,0808H		; wait for bit 3 to be set.
		MOV	BH,CS:[WAIT_HDU_DRQ_HI]
		MOV	CX,CS:[WAIT_HDU_DRQ_LO]
		CALL	WAIT_FOR_PORT		; returns ah=80h if timeout.
		XOR	AL,AL			; ax=0 or 8000h	N3.03

		POP	BX
		POP	DX
		RET
GETDRQ		ENDP

		PAGE

;[]------------------------------------------------------------------------[]
; gethparm      -       get hard disk param
; al is index in table
; dl is drive
; CHANGE THIS TO DS:SI BASE
;[]------------------------------------------------------------------------[]

		public	GETHPARM
		ALIGN	4			; N3.03
GETHPARM	PROC	NEAR
		PUSH	DS
		PUSH	SI

;R29ifdef	Support_4_IDE
;R29		cmp	dl,2
;R29		jb	short @F
;128k		MOV	SI,DGROUP
		MOV	SI,0f000h	;128k
		MOV	DS,SI
;128k		ASSUME	DS:DGROUP
;R29		push	dx
;R29		xor	dh,dh
;R29		mov	si,dx
;R29		pop	dx
;R29		sub	si,2
		movzx	si,dl
;R11		xor	si,1		;reverse drive 2 & 3
		shl	si,4
;R29		add	si,offset DGROUP:DRV2
		add	si,offset DGROUP:DRV0	;R29
;R29		jmp	short GETH1
;R29@@:
;R29endif	;Support_4_IDE
;R29
;R29		MOV	SI,SEG_0		; add low mem
;R29		MOV	DS,SI
;R29		ASSUME	DS:SEG_0
;R29		OR	DL,DL			; 0?
;R29		JNZ	SHORT GETDRIVE1		; NO
;R29		LDS	SI,SEG_0:[DR0VECTOR]	; YES, get drive 0 vector
;R29		JMP	SHORT GETH1
;R29GETDRIVE1:	LDS	SI,SEG_0:[DR1VECTOR]	; get drive 1 vector
;R29GETH1:
		XOR	AH,AH
		ADD	SI,AX			; now set index
		CMP	AL,12			; see if load word
		JE	SHORT LODW
		JA	SHORT LODB
;R41 start
ifdef	Int13_Extensions
		cmp	al,9
		je	short LODW
endif	;Int13_Extensions
;R41 end
		CMP	AL,7
		JAE	SHORT LODB
		CMP	AL,2
		JE	SHORT LODB
LODW:		LODSW				; MOV	AX,ES:[DI]
		JMP	SHORT DONE1
LODB:		LODSB				; MOV	AL,ES:[DI]
DONE1:		POP	SI
		POP	DS
		RET
GETHPARM	ENDP

ifdef IDE_LBA_MODE_SUPPORT

;R31;LBA = [(Cylinder * "# of Heads") + Head] * Sectors/Track + Sector - 1
;R31;Because (Cylinder * "# of Heads") maybe overflow 65535 so that can't
;R31;multiplication (Sectors/Track).
;R31;Solution : LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track + Sector - 1
;R31
;R31		align	4			;R05
;R31Set_LBA_Reg	PROC	NEAR
;R31		call	Detect_LBA_Mode
;R31		jne	short LBA_Is_Disable
;R31		pop	ax
;R31		shl	eax,16			;store return address
;R31		mov	al,2
;R31		mov	dl,DRIVE
;R31		call	GETHPARM		;get "# of Heads"
;R31		mov	cl,al			;store
;R31		mov	al,14
;R31		call	GETHPARM		;get Sectors/Track
;R31		push	ax
;R31		mul	cl			;"# of Heads" * Sectors/Track
;R31		mov	cx,ax			;store
;R31		mov	ax,+6[BP]		;cylinder and sector
;R31		xchg	al,ah
;R31		shr	ah,6
;R31		mul	cx			;"# of Heads" * Sectors/Track * Cylinder
;R31		pop	cx
;R31		push	dx
;R31		push	ax
;R31		mov	al,+9[BP]		;head
;R31		mul	cl
;R31		mov	bx,ax
;R31		pop	ax
;R31		pop	dx
;R31		add	ax,bx
;R31		adc	dx,0
;R31		mov	cl,+6[BP]		;get start sector
;R31		and	cl,3fh
;R31		dec	cl
;R31		xor	ch,ch
;R31		add	ax,cx
;R31		adc	dx,0
;R31		mov	ch,HD_CMD
;R31		mov	cl,DRIVE
;R31		shl	cl,4
;R31		or	cl,dh
;R31		or	cl,0e0h
;R31		push	cx
;R31		mov	dh,dl
;R31		mov	dl,ah
;R31		push	dx
;R31		mov	ah,al
;R31		mov	al,NUMSECS
;R31		push	ax
;R31		shr	eax,16			;restore return address
;R31		push	ax
;R31		clc
;R31		ret
;R31LBA_Is_Disable:
;R31		stc
;R31		ret
;R31Set_LBA_Reg	ENDP

		Public	Detect_LBA_Mode		;R16
		align	4			;R05
Detect_LBA_Mode	PROC	NEAR
		push	ax
		call	Detect_HDD_Mode
		cmp	al,1
		pop	ax
		ret
Detect_LBA_Mode	ENDP

		align	4			;R05
Detect_LARGE_Mode	PROC	NEAR
		push	ax
		call	Detect_HDD_Mode
		cmp	al,2
		pop	ax
		ret
Detect_LARGE_Mode	ENDP

		align	4			;R05
Detect_HDD_Mode	PROC	NEAR
		push	ds
		push	cx

		mov	cx,G_RAM
		mov	ds,cx
		ASSUME	ds:G_RAM
		mov	cl,DRIVE
		shl	cl,1
		mov	al,HDD_MODE_FLAG
		shr	al,cl
		and	al,3

		pop	cx
		pop	ds
		ret
Detect_HDD_Mode	ENDP
endif; IDE_LBA_MODE_SUPPORT

;R07 start
;=======================================================================
;PROC:  large_mode_head_adjust
;DESC:  Adjust head (DH) for large mode
;IN:    DH    head
;OUT:   DH    adjusted head for large mode
;========================================================================
large_mode_head_adjust  proc

    push  ax
    call	Detect_LARGE_Mode
		jne	short @F
;R43    mov al,2
;R43    mov dl,DRIVE
;R43    call GETHPARM
;R43    shr al,1            ; get physical head
;R43    cmp dh,al
;R43    jb short @F
;R43    sub dh,al           ; adjust head
;R43 start
		mov	al,11
		mov	dl,DRIVE
		call	GETHPARM
Large_Head2:
		cmp	dh,al
		jb	short @F
		sub	dh,al
		jmp	short Large_Head2
;R43 end
@@:
    pop ax
    ret

large_mode_head_adjust  endp
;R07 end

;R35;R13 - start
;R35;[]------------------------------------------[]
;R35;Function :	Set the IDE HDD Standby Timer
;R35;
;R35;Input    :	AL = number of minutes,
;R35;		e.g. AL=1 --> 1 Min
;R35;
;R35;Output   :	None
;R35;
;R35;Destroy  :	FLAGS
;R35;[]------------------------------------------[]
		Public	Set_HDD_Standby_Timer
Set_HDD_Standby_Timer	Proc	Near
;R35
;R35;R29 		mov	bl,FIXED_TYPE[bp]
;R35;R29		test	bl,0f0h			;is there a fixed disk present?
;R35;R29		jz	short No_HDD_Item
;R35
;R35		push	cx
;R35		push	dx
;R35		push	bx
;R35		push	ds
;R35		mov	bx,G_RAM
;R35		mov	ds,bx
;R35		assume	ds:G_RAM
;R35		xor	bl,bl
;R35
;R35		mov	cl,12			;1 unit is 5 second
;R35		mul	cl			;one minute is 12 units
;R35;R29		mov	dx,1F2h			;sector count register
;R35		mov	ch,al
;R35Set_4_IDE_Loop:
;R35;R29 start
;R35;R33		cmp	ds:[NUMHDSKS],bl
;R35		cmp	HDD_EXIST_Flag[bp],bl		;R33
;R35		jbe	short No_Else_HDD
;R35		mov	dx,1F2h			;sector count register
;R35		mov	cl,bl
;R35		shl	cl,1
;R35		mov	bh,byte ptr HDD_Drive_Port
;R35		shr	bh,cl
;R35;R29A		test	bh,1
;R35		test	bh,2			;R29A Is primary channel?
;R35		jz	short @F		;Yes,jump
;R35		sub	dl,80h
;R35@@:
;R35;R29 end
;R35		out	dx,al			;set the seconds
;R35		iodelay
;R35
;R35;R29		add	dx,4
;R35;R29		mov	ah,0a0h			;select drive 0
;R35		add	dl,4			;R29
;R35		mov	al,0a0h			;R29
;R35;R29A		test	bh,2			;R29
;R35		test	bh,1			;R29A Is master drive?
;R35		jz	short @F		;R29  Yes,jump
;R35		mov	al,0b0h			;R29  set salve drive
;R35@@:						;R29
;R35Set_timer_loop:
;R35;R29		cmp	ds:[NUMHDSKS],bl
;R35;R29		jbe	short No_Else_HDD
;R35;R29		mov	al,ah
;R35		out	dx,al
;R35		iodelay
;R35;R29		inc	dx
;R35		inc	dl	;R29
;R35
;R35		mov	al,0e3h
;R35		out	dx,al
;R35		iodelay
;R35
;R35		in	al,dx
;R35		iodelay
;R35		test	al,1
;R35		jz	short @F
;R35		push	ax
;R35		push	dx
;R35		mov	dl,bl
;R35		add	dl,80h
;R35		xor	ah,ah
;R35		int	13h
;R35		pop	dx
;R35		pop	ax
;R35@@:
;R35		inc	bl
;R35
;R35;R29		dec	dx
;R35;R29		add	ah,10h
;R35;R29		cmp	ah,0c0h
;R35;R29		jb	short Set_timer_loop
;R35;R29
;R35;R29Set_Second_IDE_Timer	=	0
;R35;R29ifdef	Support_4_IDE
;R35;R29Set_Second_IDE_Timer	=	1
;R35;R29endif	;Support_4_IDE
;R35;R29ifdef	Always_Set_Second_IDE_Timer
;R35;R29Set_Second_IDE_Timer	=	1
;R35;R29endif	;Always_Set_Second_IDE_Timer
;R35;R29
;R35;R29IF	Set_Second_IDE_Timer EQ 1
;R35;R29		cmp	dx,1f0h
;R35;R29		jb	short @F
;R35;R29		test	byte ptr ds:POST_FLAG,DRIVE1_ABSENT
;R35;R29		jz	short Drive1_not_exist
;R35;R29		dec	bl
;R35;R29Drive1_not_exist:
;R35;R29		sub	dx,84h					;dx=172h
;R35;R29		mov	al,ch
;R35		mov	al,ch				;R29B
;R35		jmp	short Set_4_IDE_Loop
;R35;R29@@:
;R35;R29ENDIF	;Set_Second_IDE_Timer
;R35
;R35No_Else_HDD:
;R35		pop	ds
;R35		pop	bx
;R35		pop	dx
;R35		pop	cx
;R35No_HDD_Item:
;R35;R24C		POST_FUNC_CALL	Reset_HDD_controller		;R24
;R35;R24B		xor	ah,ah					;R24A
;R35;R24B		mov	dl,80h					;R24A
;R35;R24B		int	13h					;R24A
		ret
Set_HDD_Standby_Timer	EndP
;R35;R13 - end

ifndef	Trend_AntiVirus					;R49
;R38 start
;************************************;
; input : bh screen page             ;
;         dl for cursor column       ;
; 	  dh for cursor row          ;
; output: set cursor to new position ;
;************************************;
Set_Cursor_Posi	MACRO
		mov	ah,2
		int	10h
    		ENDM
;
;
;********************************;
; input : dx for sound time      ;
;         bx for sound frequence ;
; output: speaker sound          ;
;********************************;
SPEAKER_PORT	EQU	61h
		align	4			;R05
Speaker		PROC	NEAR
		in	al,SPEAKER_PORT
		and	al,0feh
Speaker_Loop:
		or	al,2
		out	SPEAKER_PORT,al
		mov	cx,bx
		loop	short $
		and	al,0fdh
		out	SPEAKER_PORT,al
		mov	cx,bx
		loop	short $
		dec	dx
		jnz	short Speaker_Loop
		ret
Speaker 	ENDP
;
PART_CYL_SEC	EQU	1	;partition table cylinders(high 10 bits)=0 sector(low 6 bits)=1
PART_HEAD	EQU	0	;partition table head
WARN_ROW	EQU	10	;warning message start row
WARN_COLUMN	EQU	22	;warning message start column
CARRY_RETURN	EQU	1
STRING_END	EQU	0
WARN_ATTRIBUTE	EQU	70h	;warn message attribyte is reverse
SOUND_FREQ_1	EQU	988   	;warning first sound frequence
SOUND_FREQ_2	EQU	1319   	;warning second sound frequence
SOUND_TIME	EQU	20	;warning sound time length
warning_msg:	DB	'ÿÿÿÿ ÿÿÿÿÿ!!!ÿWARNINGÿ!!!ÿÿÿÿ ÿÿÿ  ÿ',CARRY_RETURN
		DB	' DiskÿBootÿsectorÿis toÿbeÿmodified ',CARRY_RETURN
		DB	'Typeÿ"Y"ÿtoÿaccept, any keyÿtoÿabort',CARRY_RETURN
		DB	'ÿÿÿÿÿÿÿ Award Software, Inc.ÿÿÿ ÿÿ ÿ',STRING_END

;
;instruction : 1. This Virus_Detect rotine is comapre drive,heads,cylinders
;	          and sectors are writing Partition_Table or Boot_Area.
;	       2. Partition_Table is local drive=C or D ,head=0 ,cylinder=0
;		  and sector=1.
;	       3. Boot_Area is define 64 bytes in offset=1beh of Partition_Table.
;
Check_Write_Protect:
;R53		push	es
;R53		push	bx
;R53
;R53		MOV	BX,G_RAM
;R53		MOV	ES,BX			; set es=0
;R53		ASSUME	ES:G_RAM
;R53		test	byte ptr es:POST_FLAG,VIRUS_DETECT
;R53		pop	bx
;R53		pop	es
;R53		jz	No_Virus_Protect	;No virus warning allow

		push	si
		push	ds
		push	ax

		MOV	ax,G_RAM
		MOV	ds,ax			; set es=0
		ASSUME	ds:G_RAM
;R53 start
		test	byte ptr [POST_FLAG],VIRUS_DETECT
		jz	Normal_Active
		mov	al,[CON_MODE]
		cmp	al,3			;text mode?
		jbe	short Is_Text_Mode	;Yes,go
		cmp	al,7			;text mode?
		jne	Normal_Active		;No,skip
Is_Text_Mode:
;R53 end
		mov	si,[boot_sector_addr]
		mov	ax,[boot_sector_addr+2]
		mov	ds,ax

		mov	ax,[si] 		;check [bp+8](driver&head) = boot area driver&head?
           	cmp	word ptr [bp+8],ax
		jz	short Boot_Cyl_Sec	;Yes,jump Boot_Cyl_Sec
		jmp	short Check_Boot  	;No,jump Check_Boot
Boot_Cyl_Sec:
		mov	ax,[si+2]		;check [bp+6](cylinder&sector) = boot area (cylinder&sector)
		cmp	[bp+6],ax
		jz	short Check_Ok		;Yes,jump Check_Ok
Check_Boot:
		cmp	word ptr [bp+6],PART_CYL_SEC  	;check write cylinder&sector=partition table cylinder&sector?
		jz	short Check_Head		;Yes,jump Check_Head
		jmp	Normal_Active		;No,jump Normal_Active
Check_Head:
                cmp	byte ptr [bp+9],PART_HEAD	;check write head = partition table head
		jz	short Check_Ok			;Yes,jump Check_Ok
		jmp	Normal_Active		;No,jump Normal_Active
Check_Ok:
		push	di
		push	bx
		push	cx
		push	dx
		mov	ah,0fh			;get now screen page
		int	10h
		mov	ah,3	   		;push now cursor position
		int	10h
		push	dx
		mov	dh,WARN_ROW		;set cursor position
		mov	dl,WARN_COLUMN
		Set_Cursor_Posi
		mov	si,offset warning_msg
		mov	bl,WARN_ATTRIBUTE
Warn_Loop:
		mov	cl,cs:[si]
		cmp	cl,CARRY_RETURN
		jnz	short Check_End
		inc	si
		inc	dh
		mov	dl,WARN_COLUMN
		Set_Cursor_Posi
		jmp	short Warn_Loop
Check_End:
		cmp	cl,STRING_END
		jnz	short Display_Char
		xor	si,si
		sub	dh,WARN_ROW		;caculate warning message high
		sub	dl,WARN_COLUMN		;caculate warning message wide
		mov	di,dx			;store to di
		mov	dx,1900h		;store cursor in row=19h column=0
		Set_Cursor_Posi
		jmp	short Warn_Loop0
Display_Char:
		mov	ah,8			;backup background charactory and attribute
		int	10h
		push	ax
		mov	al,cl
		mov	ah,9
		mov	cx,1
		int	10h
		inc	dl
		Set_Cursor_Posi
		inc	si
		jmp 	short Warn_Loop
Warn_Loop0:					;sound loop
		mov	bx,SOUND_FREQ_1
		mov	dx,SOUND_TIME
		call	Speaker
		mov	cx,2000h
Warn_Delay0:
		mov	ah,1
		int	16h
		jnz	short Warn_Exit
		loop	short Warn_Delay0
		mov	bx,SOUND_FREQ_2
		mov	dx,SOUND_TIME
		call	Speaker
		mov	cx,2000h
Warn_Delay1:
		mov	ah,1
		int	16h
		jnz	short Warn_Exit
		loop	short Warn_Delay1
		mov	bx,SOUND_FREQ_1
		mov	dx,SOUND_TIME
		call	Speaker
		mov	cx,2000h
Warn_Delay2:
		mov	ah,1
		int	16h
		jnz	short Warn_Exit
		loop	Warn_Delay2
		mov	bx,SOUND_FREQ_2
		mov	dx,SOUND_TIME
		call	Speaker
		mov	cx,6000h
Warn_Delay3:
		mov	ah,1
		int	16h
		jnz	short Warn_Exit
		loop	short Warn_Delay3
		jmp	short Warn_Loop0
Warn_Exit:					;warning message end
		mov	ah,0
		int	16h
		cmp	si,0		 	;check already compare?
		jnz	short Next_Key1		;yes,jump Next_Key
		cmp	al,'Y'			;compare keyin is 'Y'?
		jnz	short Compare_Next	;no,jump Compare_Next
		mov	si,2			;yes,set si=2 (already compare and keyin='Y')
		jmp	short Next_Key1
Compare_Next:
		cmp	al,'y'			;compare keyin is 'y'?
		jnz	short Next_Key0		;no,jump Next_Key0
		mov	si,2			;yes,set si=2 (already compare and keyin='Y')
		jmp	short Next_Key1
Next_Key0:
		mov	si,1			;set si=1 (already compare but not keyin 'Y')
Next_Key1:
		mov	ah,1
		int	16h
		jnz	short Warn_Exit
		mov	cx,di			;restore background charactory and attribute
		mov	ah,0fh			;get now screen page
		int	10h
		mov	dh,WARN_ROW
		add	dh,ch  			;restore high
		inc	ch
Restore0:
		mov	dl,WARN_COLUMN
		add	dl,cl
		dec	dl
		mov	di,cx			;restore wide
		and	di,0ffh
Restore1:
		Set_Cursor_Posi
		pop	ax
		mov	ds,cx
		mov	cx,1
		mov	bl,ah
 		mov	ah,9
		int	10h
		dec	dl
		mov	cx,ds
		dec	di
		jnz	short Restore1
		dec	dh
		dec	ch
		jnz	short Restore0
		pop	dx
		Set_Cursor_Posi
		pop	dx
		pop	cx
		pop	bx
		pop	di
		pop	ax
		pop	ds
		cmp	si,2			;compare press 'Y'
		jz	short Normal_Active0	;yes,jump Normal_Active0 to execute normal active
		pop	si			;no,jump Error_Ret
		jmp	Error_Ret
Normal_Active:
		pop	ax
		pop	ds
Normal_Active0:
		pop	si
No_Virus_Protect:
		ret
;R38 end
endif;	Trend_AntiVirus					;R49
;R50-start
ifdef	Int13_Extensions
Extend_Func:
		DW	OFFSET	FUN41		;FUN41
		DW	OFFSET	FUN42		;FUN42
		DW	OFFSET	FUN43		;FUN43
		DW	OFFSET	FUN44		;FUN44
		DW	OFFSET	FUN45		;FUN45
		DW	OFFSET	FUN46		;FUN46
		DW	OFFSET	FUN47		;FUN47
		DW	OFFSET	FUN48		;FUN48
		DW	OFFSET	FUN49		;FUN49
Extend_Func_MAX	EQU	($-offset Extend_Func)/2

;[]------------------------------------------------------------------------[]
;Function:   	Check for Extension support
;Entry:  	INT 13h
;Input:  	AH = 41h
;		BX = 55AAh
;               DL = Drive Number
;Output: 	CF = 0 - operation successfully completed
;		   AH - major version of extensions
;		   AL - minor version of extensions
;		   BX = 0AA55h
;		   CX = Bits 15 to 2 - reserved (set to 0)
;			Bits 1 = 0 - Removable-media control is not supported
;			       = 1 - Removable-media control is supported
;			Bits 0 = 0 - Extended disk access is not supported
;			       = 1 - Extended disk access is supported
;		CF = 1 - operation failed
;		   AH - Status of operation
;Description:
;
;[]------------------------------------------------------------------------[]
FUN41:
		cmp	word ptr +4[bp],55aah		;BX = 55aah?
		jne	FUN10_2				;no,then return error
;R51		mov	word ptr +2[bp],2100h		;return AX
ifdef Support_EDDS30					;R51A
		mov	word ptr +2[bp],3000h		;return AX ;R51
else; Support_EDDS30					;R51A
		mov	word ptr +2[bp],2100h		;return AX ;R51A
endif; Support_EDDS30					;R51A

		mov	word ptr +4[bp],0aa55h		;return BX
		mov	word ptr +6[bp],5		;return CX
		jmp	GOOD_RET

;[]------------------------------------------------------------------------[]
;Function:   	Extended Read
;Entry:  	INT 13h
;Input:  	AH = 42h
;               DL = Drive Number
;		DS:SI = Disk-address packet
;Output: 	CF = 0 - operation successfully completed
;		     1 - operation failed
;		   AH - Status of operation
;Description:
;
;[]------------------------------------------------------------------------[]
FUN42:
		mov	HD_CMD,20h
		jmp	cont_cmd

;[]------------------------------------------------------------------------[]
;Function:   	Extended Write
;Entry:  	INT 13h
;Input:  	AH = 43h
;		AL = Bits 7 to 1 - reserved (set to 0)
;		     Bit 0 = 0 - Write-verify off
;		     	   = 1 - Write-verify on
;               DL = Drive Number
;		DS:SI = Disk-address packet
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH - Status of operation
;Description:
;
;[]------------------------------------------------------------------------[]
FUN43:
		mov	HD_CMD,30h
		jmp	cont_cmd

;[]------------------------------------------------------------------------[]
;Function:   	Extended Verification
;Entry:  	INT 13h
;Input:  	AH = 44h
;               DL = Drive Number
;		DS:SI = Disk-address packet
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH - Status of operation
;Description:
;
;[]------------------------------------------------------------------------[]
FUN44:
		mov	HD_CMD,40h
		jmp	cont_cmd

;[]------------------------------------------------------------------------[]
;Function:   	Lock/Unlock drive
;Entry:  	INT 13h
;Input:  	AH = 45h
;               AL = 0 - Lock media in drive
;                  = 1 - Unlock media in drive
;                  = 2 - Return lock/unlock status
;                  = 3 to 0ffh - reserved
;               DL = Drive Number
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH - Status of operation
;		      =	1   - unsupported function or parameter
;		      =	20h - general controller failure
;		      =	80h - controller did not respond
;		      =	B0h - media not locked in drive
;		      =	B4h - lock count exceeded
;		   AH - Lock/Unlock status
;		      = 0 - drive is locked
;		      = 1 - drive is unlocked
;Description:
;
;[]------------------------------------------------------------------------[]
FUN45:

;[]------------------------------------------------------------------------[]
;Function:   	Eject media from drive
;Entry:  	INT 13h
;Input:  	AH = 46h
;               DL = Drive Number
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH - Status of operation
;		      =	1   - unsupported function or parameter
;		      =	20h - general controller failure
;		      =	80h - controller did not respond
;		      =	B1h - media locked in drive
;		      =	B2h - media not removable
;		      =	B2h - media in use
;		      =	B5h - valid eject request failed
;Description:
;
;[]------------------------------------------------------------------------[]
FUN46:
		jmp	FUN10_2

;[]------------------------------------------------------------------------[]
;Function:   	Extended Seek
;Entry:  	INT 13h
;Input:  	AH = 47h
;               DL = Drive Number
;		DS:SI = Disk-address packet
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH - Status of operation
;Description:
;
;[]------------------------------------------------------------------------[]
FUN47:
		mov	HD_CMD,70h
		jmp	cont_cmd

;[]------------------------------------------------------------------------[]
;Function:   	Extended Get Drive Parameters
;Entry:  	INT 13h
;Input:  	AH = 48h
;               DL = Drive Number
;		DS:SI = Disk-address packet
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH - Status of operation
;		DS:SI = Resulting buffer
;Description:
;
;[]------------------------------------------------------------------------[]
FUN48:
	mov	si,+14[bp]
	mov	ds,si
	mov	si,+16[bp]
	mov	ax,ds:[si]			;get buffer size
	cmp	ax,26				;check buffer size
	jae	short @F			;>= 26 then set parameter to buffer
	mov	word ptr +2[BP],100h		;set status = bad command
	jmp	AHDSK_ERROR_RET			;error return
@@:
;R51	mov	word ptr ds:[si],26		;set buffer size = 26
;R51	cmp	ax,30				;check buffer size
;R51	jb	short @F			;< 26 then set parameter to buffer
;R51	mov	word ptr ds:[si],30		;set buffer size = 30
;R51@@:

ifdef Support_EDDS30						;R51A

;R51 - start
	mov	word ptr ds:[si],65		;set buffer size = 65
	cmp	ax,65				;check buffer size
	jae	short Set_Buffer_size_end_0	;>= 65 then set parameter to buffer
endif; Support_EDDS30				;R51A 
	mov	word ptr ds:[si],30		;set buffer size = 30
	cmp	ax,30				;check buffer size
	jae	short Set_Buffer_size_end_0	;>= 30 then set parameter to buffer
	mov	word ptr ds:[si],26		;set buffer size = 26
Set_Buffer_size_end_0:
;R51 - end
	mov	word ptr ds:[si+2],00000010b	;information flags
;R46B start
ifndef ExtInt13_LBA
	mov	dx,90bh
	mov	cl,4
	call	Detect_LBA_Mode
	je	short @F
	call	Detect_LARGE_Mode
	je	short @F
endif ;ExtInt13_LBA
;R46B end
	mov	dx,2
	mov	cl,14
;R46Bifndef ExtInt13_LBA
;R46B	call	Detect_LBA_Mode
;R46B	jne	short @F
;R46B	mov	dx,90bh
;R46B	mov	cl,4
@@:
;R46Bendif ;ExtInt13_LBA
	xor	eax,eax
	mov	al,dl
	mov	dl,DRIVE
	CALL	GETHPARM			;get heads
	mov	ds:[si+8],eax			;store to buffer
	mov	ch,al

	mov	al,cl
	CALL	GETHPARM			;get sectors
	mov	ds:[si+0ch],eax			;store to buffer
	mov	cl,al

	mov	al,dh
	CALL	GETHPARM			;get cylinders
	mov	ds:[si+4],eax			;store to buffer
	xchg	ax,cx
	mul	ah
	mul	cx
	mov	word ptr ds:[si+16],ax
	mov	word ptr ds:[si+18],dx
;R51 - start
;?	cmp	dx,00ech		  	;if Number of Physical sector
;?	ja	short Above_EC4000H		; is greater than 15,482,880
;?	jb	short Below_EC4000H		; is smaller than 15,482,880
;?	cmp	ax,4000				; (EC4000h) offset 2, bit 1 cleared
;?	jb	short Below_EC4000H		; to 0
;?Above_EC4000H:
;?	and	word ptr ds:[si+2],not 02 
;?Below_EC4000H:
;R51 - end

	mov	word ptr ds:[si+20],0		;set high dword = 0
	mov	word ptr ds:[si+22],0
	mov	word ptr ds:[si+24],200h	;bytes in a sectors
	cmp	word ptr ds:[si],30		;check buffer size = 30?
;R51	jb	short @F			;if< 30 then skip
	jb	Dont_set_FDPTE_H		;R51
	movzx	dx,DRIVE
	shl	dl,4
	add	dx,offset cs:FDPTE_Drive0	;get FDPTE address	
	mov	word ptr ds:[si+26],dx		;save FDPTE offset
	mov	word ptr ds:[si+28],0f000h	;save segment
;R51 - start
ifdef Support_EDDS30						;R51A
	cmp	word ptr ds:[si],65		
	jb	Dont_set_FDPTE_H		;if< 65 then skip
	mov	word ptr ds:[si+30],0BEDDh	;indicates presence of device Path information
	mov	byte ptr ds:[si+32],36		;length
	mov	byte ptr ds:[si+33],0		;Reserved
	mov	word ptr ds:[si+34],0		;Reserved

	mov	dword ptr ds:[si+36],'ISA '	;Legacy 16 bit fixed bus
	mov	dx,1f0h
	sub	dl,PORT_MODULATE
	mov	word ptr ds:[si+48],dx		;16 bit address 1f0/170h
	mov	word ptr ds:[si+50],0		;Reserved
	mov	dword ptr ds:[si+52],0		;Reserved
	call	Host_Bus_type
	jc	short IDE_Use_ISA
	mov	dword ptr ds:[si+36],'PCI '
	mov	byte ptr ds:[si+48],0		;bus number
	mov	byte ptr ds:[si+49],ah		;slot = device number
	mov	byte ptr ds:[si+50],al		;Function number
IDE_Use_ISA:

	mov	dword ptr ds:[si+40],'    '	;8 bytes for ASCII
	mov	dword ptr ds:[si+44],'ATA '
	xor	al,al
	test	DRIVE,1h			;test master/slave
	jz	short	@F			;master? Yes, skip
	inc	al				;slave
@@:
	mov	byte ptr ds:[si+56],al		;master/slave
	mov	byte ptr ds:[si+57],0		;Reserved
	mov	word ptr ds:[si+58],0		;Reserved
	mov	dword ptr ds:[si+60],0		;Reserved
	mov	byte ptr ds:[si+64],0		;Reserved
	pusha
	movzx	cx,byte ptr ds:[si+32]		;length
	dec	cx
	xor	ax,ax		
@@:
	add	al,byte ptr ds:[si+30]
	inc	si
	loop	short @B
	neg	al
	mov	byte ptr ds:[si+30],al		;Checksum 2's ;offset 65
	popa
endif; Support_EDDS30					;R51A
Dont_set_FDPTE_H:
;R51 - end

@@:

	mov	byte ptr +3[BP],0		;no error return
	jmp	GOOD_RET

;[]------------------------------------------------------------------------[]
;Function:   	Extended Disk-Change status
;Entry:  	INT 13h
;Input:  	AH = 49h
;               DL = Drive Number
;Output: 	CF = 0 - operation successfully completed
;		CF = 1 - operation failed
;		   AH = 0 - 'Change' line is inactive
;		      =	1 - 'Change' line is active
;Description:
;
;[]------------------------------------------------------------------------[]
FUN49:
		jmp	FUN10_2

Get_DAP_Value:
		push	ds
		push	si
		mov	si,+14[bp]
		mov	ds,si
		mov	si,+16[bp]
		mov	eax,dword ptr ds:[si][bx]
		pop	si
		pop	ds
		clc
		ret
endif	;Int13_Extensions

		public	FDPTE_Drive0
		public	FDPTE_Drive1
		public	FDPTE_Drive2
		public	FDPTE_Drive3
		align 	16
FDPTE_Drive0	db	16 dup(0)
FDPTE_Drive1	db	16 dup(0)
FDPTE_Drive2	db	16 dup(0)
FDPTE_Drive3	db	16 dup(0)
;R50-end

;R56 start
ifdef	IDE_DMA_Transfer
;[]------------------------------------------------------------------------[]
;Name:   	IDE_DMA_Function
;Description:	
;[]------------------------------------------------------------------------[]
IDE_DMA_Function:
;----- Get Buffer of Address -----
		mov	ax,+12[BP]		;get destination segment(ES of input)
		shl	eax,16
		mov	ax,+4[BP]		;get destination offset(BX of input)
ifdef	Int13_Extensions
		cmp	byte ptr FUNC_CMD,41h	;function call(AH) below 41h
		jb	short Standard_Int13_Data;Yes,standard call
		mov	bx,offset Disk_Address_Pkt.DAP_Buffer_Address
		call	Get_DAP_Value
Standard_Int13_Data:
endif	;Int13_Extensions
		movzx	ecx,ax			;get buffer of offset
		shr	eax,12			;get buffer of segment
		and	al,0f0h			;mask bits 0-3
		add	eax,ecx			;EAX=physical address
		mov	cl,al			;get low nibble
		and	cl,1			;isolate useful bit
		mov	DMA_First_Offset,cl	;store to temp buffer
		call	Get_PRD_Offset		;Get offset of PRD_Descriptor_Table
		and	al,not 1		;mask bit 0
		mov	ss:[bx].PRD_Base_Addr,eax;store to temp buffer
		or	al,cl			;recovery bit 0
		xor	cx,cx			;64K boundary offset
		mov	bl,byte ptr NUMSECS	;get transfer sector number
		mov	Total_NUMSECS,bl	;Save it
		shl	bx,9
		add	bx,ax
		jnc	SecDMA_Transfer
		jz	SecDMA_Transfer
		sub	cx,ax
		shr	cx,9			;first transfer sectors
		jz	short FirstPIO_Transfer
;----- Execute first DMA transfer -----
		mov	NUMSECS,cl		;get transfer sector number
		call	IDE_DMA_Transfer_Routine
		or	ah,ah
		jnz	DMA_Transfer_End

;----- Execute PIO transfer -----
FirstPIO_Transfer:
		call	PIO_1Sector_Transfer
		or	ah,ah			;error?
		jnz	short DMA_Transfer_End	;Yes,skip

;----- Execute secondary DMA transfer -----
SecDMA_Transfer:
		mov	bl,Total_NUMSECS
		mov	NUMSECS,bl
		call	IDE_DMA_Transfer_Routine

DMA_Transfer_End:
		mov	+3[BP],ah
		add	sp,6			;balance stack
		jmp	INT13_RET
;----------------------------------------------------------------------------

BMI_Command_Reg		equ	0	;Bus Master IDE command register(IO)
BMI_Status_Reg		equ	2	;Bus Master IDE status register(IO)
BMI_Desc_Tbl_Point_Reg	equ	4	;Bus Master IDE Descriptor Table Pointer register(IO)
;[]------------------------------------------------------------------------[]
;Name:   	IDE_DMA_Transfer_Routine
;Description:	IDE DMA transfer just for Intel compatible chip(e.g. PIIX4).
;		If IDE drive support DMA then call this routine to use
;		DMA transfer.
;[]------------------------------------------------------------------------[]
IDE_DMA_Transfer_Routine:
		pop	bx			;Get return address
		mov	DMA_Trans_Ret_Offset,bx	;store to stack buffer

		cmp	Total_NUMSECS,0
		je	IDTR_End

;----- Prepare for Bus Master IDE Descriptor Table Pointer Register (IO) -----
		mov	dl,byte ptr NUMSECS	;get transfer sector number

		or	dl,dl			;no more sector to be transfer
		jz	IDTR_End

		mov	bx,sp			;------------------------
		mov	ss:[bx],dl	;set value for 1x2h port

		shl	dx,9			;modulate to bytes
		call	Get_PRD_Offset		;Get offset of PRD_Descriptor_Table
		mov	ss:[bx].PRD_Byte_Count,dx;store to temp buffer
		mov	ss:[bx].PRD_EOT,8000h	;store to temp buffer

		mov	eax,ss:[bx].PRD_Base_Addr;store to temp buffer
		mov	ebx,eax
		ror	ebx,16			;get segment
		shl	bx,12
		mov	ds,bx			;start segment
		shr	ebx,16			;get offset

		and	bl,not 1		;align to word
		mov	bl,ds:[bx]		;save first dword of buffer
		mov	DMA_First_Byte,bl	;store to temp buffer

		cmp	HD_CMD,0cah		;Is write command?
		jne	short @F		;No,skip
		xor	al,al			;backward remove
		call	Fix_data
@@:

;----- Output data to Bus Master IDE command register (IO) -----
		call	Get_IDE_DMA_BasePort	;DX = Base port
;----- Step 1 : Loading the PRD table pointer Register
		xor	eax,eax
		mov	ax,ss			;get segment of PRD_Base_Addr
		shl	eax,4
		call	Get_PRD_Offset
		add	eax,ebx			;BX = offset PRD_Descriptor_Table
		push	dx			;save base port
		add	dl,4			;descriptor table pointer register
		out	dx,eax			;out it
		newiodelay
		pop	dx

;----- Step 2 : Set Read/Write control bit in the command register
		xor	ah,ah			;set to write action
		cmp	HD_CMD,0cah		;Is write command?
		je	short @F		;Yes,skip
		mov	ah,8			;Assume read action
@@:
		in	al,dx			;get original value of command register
		newiodelay
		and	al,not 9		;mask stop and R/W bit
		or	al,ah			;set flag
		out	dx,al			;out it
		newiodelay
		
;----- Step 3 : Clear interrupt bit and error bit in the status register
		push	dx			;save base port
		add	dl,2			;status register port
		in	al,dx			;get original value
		newiodelay
		and	al,not 7		;bit 2 is interrupt status bit
						;bit 1 is error bit
						;bit 0 is Active bit
		or	al,4			;enable interrupt bit
		out	dx,al			;out it
		newiodelay
		pop	dx			;restore

;----- Step 4 : Issues DMA transfer command to disk device and wait for data
		call	SEND_CMD
		call	GetDRQ

		call	Get_IDE_DMA_BasePort	;DX = Base port
;----- Step 5 : Engage the bus master function by writing a 1 to start bit in
;-----		the command register
		in	al,dx
		newiodelay
		or	al,1			;Start bit = 1
		out	dx,al
		newiodelay

;----- Step 6 : Wait for BMIDEA bit be reset
		push	dx
		add	dl,2
		mov	ax,504h			;wait for BMIDEA bit to be 0
		mov	bh,cs:[WAIT_HDU_CTLR_BUSY_HI]
		mov	cx,cs:[WAIT_HDU_CTLR_BUSY_LO]
		call	WAIT_FOR_PORT

		CALL	WAIT_INT		;wait for interrupt
		pop	dx

;----- Step 7 : Reset the Start/Stop bit in command register
		in	al,dx
		newiodelay
		and	al,not 1		;Start bit = 0(stop)
		out	dx,al
		newiodelay

;----- Step 8 : Move data to real offset when buffer address is odd -----
		mov	al,1			;forward remove
		call	Fix_data

		call	Reset_PIO_Sector
		sub	Total_NUMSECS,al	;Save it
		shl	ax,9
		call	Get_PRD_Offset		;Get offset of PRD_Descriptor_Table
		add	dword ptr ss:[bx].PRD_Base_Addr,eax	;point to next address

		CALL	CK_STATUS		; ax = ck_status()
IDTR_End:
		jmp	DMA_Trans_Ret_Offset	;fill return offset to stack

;[]------------------------------------------------------------------------[]
;Name:   	PIO_1Sector_Transfer
;Description:	
;[]------------------------------------------------------------------------[]
PIO_1Sector_Transfer:
		pop	bx			;Get return address
		mov	PIO_Trans_Ret_Offset,bx	;store to stack buffer

		cmp	Total_NUMSECS,0
		je	P1ST_Ret

		mov	al,1
		mov	NUMSECS,al		;get transfer sector number
		mov	bl,2			;command register index
		call	Set_PIO_Data

		mov	al,20h			;assume read
		cmp	HD_CMD,0c8h
		je	short @F
		mov	al,30h			;write command
@@:
		mov	bl,7			;command register index
		call	Set_PIO_Data

		CALL	SEND_CMD
		or	ah,ah
		jne	short P1ST_Ret

		cmp	HD_CMD,0cah
		je	short PIO_Write
		CALL	WAIT_INT		;wait for interrupt
		or	ah,ah
		jne	short P1ST_Ret
PIO_Write:
		call	GETDRQ
		or	ah,ah
		jne	short P1ST_Ret

		call	Get_PRD_Offset		;Get offset of PRD_Descriptor_Table

		mov	dx,1f0h			;PIO data port
		sub	dl,PORT_MODULATE	;correspond to channel
		mov	eax,ss:[bx].PRD_Base_Addr;offset of buffer
		add	al,DMA_First_Offset	;store to temp buffer
		mov	di,ax			;get offset
		and	di,0fh			;only lowest nibble available
		shr	eax,4			;get segment
		mov	si,ax			;set to SI
		mov	cx,100h			;count = 256 words
		cld
		cli
		cmp	HD_CMD,0c8h
		je	short PIO_Read
		mov	ds,si			;get segment
		mov	si,di			;get offset
		align	4
		rep	outsw
		sti
		CALL	WAIT_INT		;wait for interrupt
		jmp	short PIO_Transfer_End
PIO_Read:
		push	es
		mov	es,si			;get segment
		align	4
		rep	insw
		sti
		pop	es
PIO_Transfer_End:
		CALL	CK_STATUS		; ax = ck_status()
		or	ah,ah
		jnz	short P1ST_Ret

		call	Reset_PIO_Sector
		sub	Total_NUMSECS,al	;Save it
		shl	ax,9
		call	Get_PRD_Offset		;Get offset of PRD_Descriptor_Table
		add	dword ptr ss:[bx].PRD_Base_Addr,eax	;point to next address

		mov	al,HD_CMD
		mov	bl,7			;command register index
		call	Set_PIO_Data
		xor	ah,ah			;indicate no error
P1ST_Ret:
		jmp	PIO_Trans_Ret_Offset	;fill return offset to stack

;[]------------------------------------------------------------------------[]
;Name:   Fix_data
;Input : AL = 0 means backward remove
;	      1 means forward remove
;[]------------------------------------------------------------------------[]
Fix_data:
		test	DMA_First_Offset,1	;buffer address is odd
		jz	short FD_Ret
		push	ax			;save flag
		call	Get_PRD_Offset		;Get offset of PRD_Descriptor_Table
		mov	eax,ss:[bx].PRD_Base_Addr;store to temp buffer
		movzx	ecx,byte ptr NUMSECS	;get transfer sector number
		shl	cx,9			;total bytes in CX
		pop	bx			;restore flag
		push	es
		pushf
		or	bl,bl			;backward remove?
		jz	short Backward_Move	;Yes,skip
		add	eax,ecx			;end offset of buffer
		mov	di,ax			;destination offset
		mov	si,di
		dec	si			;source offset

		ror	eax,16
		shl	ax,12
		mov	ds,ax			;source segment
		mov	es,ax			;destination segment
		std
		jmp	short Move_Done
Backward_Move:
		mov	di,ax			;destination offset
		and	di,0fh
		mov	si,di
		inc	si			;source offset

		shr	eax,4
		mov	ds,ax			;source segment
		mov	es,ax			;destination segment
		cld
Move_Done:

		cli
		align	4
		rep	movsb			;*** only use byte to move
		popf

		or	bl,bl			;forward remove?
		jz	short @F		;Yes,skip
		mov	al,DMA_First_Byte	;get first byte original value
		mov	es:[di],al		;restore it
@@:
		pop	es
FD_Ret:
		ret

;[]------------------------------------------------------------------------[]
;Name:   	Get_IDE_DMA_BasePort
;Output : DX = IDE DMA base port
;[]------------------------------------------------------------------------[]
Get_IDE_DMA_BasePort:
		mov	dx,cs:[IDE_DMA_BMIBA]	;get bus master interface base address
		and	dl,0f0h			;mask unuse bits 0-3
		cmp	drive,2			;Primary channel
		jb	short Get_Port_Done	;Yes,skip
		add	dl,8			;correspond to secondary channel
Get_Port_Done:
		ret

;[]------------------------------------------------------------------------[]
;Name:	Get_PRD_Offset
;Output : BX = offset of PRD_Descriptor_Table
;[]------------------------------------------------------------------------[]
Get_PRD_Offset:
		lea	bx,offset PRD_Descriptor_Table	;store to temp buffer
		add	bl,3
		and	bl,not 3		;align to dword
		ret

;[]------------------------------------------------------------------------[]
;Name:	Reset_PIO_Sector
;Output : Fill 1x1h-1x7h port of data
;	  AL = NUMSECS
;[]------------------------------------------------------------------------[]
Reset_PIO_Sector:
		call	Detect_LBA_Mode			;check LBA mode support?
		movzx	eax,NUMSECS			;get transfer sector number
		jne	short No_LBA			;No,jump to standard HDD
		push	bx
		mov	bx,sp
		add	dword ptr ss:[bx+5],eax		;add to sector count(bits 0-7)
		pop	bx
		ret
No_LBA:





		ret

;[]------------------------------------------------------------------------[]
;Name:	Set_PIO_Data
;Input  : AL = value
;	  BL = index (0=1x0h, 1=1x1h...)
;Output : Fill 1x1h-1x7h port of data
;[]------------------------------------------------------------------------[]
Set_PIO_Data:
		push	bx
		add	bx,2
		xor	bh,bh
		add	bx,sp
		mov	byte ptr ss:[bx],al		;add to sector count(bits 0-7)
		pop	bx
		ret
endif	;IDE_DMA_Transfer
;R56 end

;R58B;R58 start
;R58B;[]------------------------------------------------------------------------[]
;R58B;Name	     : Send_ATAPI_NOP_CMD
;R58B;Description : Send a NOP of ATA command to all ATAPI device
;R58B;Input	     : NONE
;R58B;Output	     : NONE
;R58B;[]------------------------------------------------------------------------[]
;R58BSend_ATAPI_NOP_CMD	proc	near
;R58B;R58A		push	es
;R58B		pusha
;R58B
;R58B;R58A;----- first, set flag for all HDD drive -----
;R58B;R58A		push	G_RAM
;R58B;R58A		pop	es				;ES=G_RAM segment
;R58B;R58A		mov	al,es:[HDD_Drive_Port]		;Get HDD Drive Port
;R58B;R58A		mov	bh,NUMDSKS			;Get Num of IDE HDD
;R58B;R58A		xor	bl,bl				;assume none HDD of IDE
;R58B;R58ASet_IDE_HDD_Flag:
;R58B;R58A		mov	cl,al				;get current location of device
;R58B;R58A		and	cl,3				;isolate used bits
;R58B;R58A		mov	ch,1				;set flag for base
;R58B;R58A		shl	ch,cl				;shift to correspond of bit
;R58B;R58A		or	bl,ch				;set flag for exactly
;R58B;R58A		shr	al,2				;shift to next drive of port
;R58B;R58A		dec	bh				;next drive
;R58B;R58A		jnz	short Set_IDE_HDD_Flag		;more drive,continue...
;R58B
;R58B;----- second, send NOP command for all ATAPI drive -----
;R58B		mov	bh,1				;start from drive 0
;R58B		mov	cx,cs:[IDE_drive_Type]		;R58A
;R58BSend_Nop_CMD_Loop:
;R58B;R58A		test	bh,bl				;Is HDD?
;R58B;R58A		jnz	short Send_Nop_CMD_Next		;Yes,skip
;R58B;R58A start
;R58B		mov	al,cl				;get current verify IDE HDD of type
;R58B		and	al,0fh				;-----
;R58B		cmp	al,1				;Is HDD or none any device?
;R58B		jbe	short Send_Nop_CMD_Next		;Yes,skip
;R58B;R58A end
;R58B
;R58B		mov	PORT_MODULATE,0			;assume primary channel
;R58B		test	bh,00000011b			;is primary channel?
;R58B		jnz	short @F			;Yes,jump
;R58B		mov	PORT_MODULATE,80h		;set port for secondary channel
;R58B@@:
;R58B		mov	al,0a0h				;set master value
;R58B		test	bh,00000101b			;Is master drive?
;R58B		jnz	short @F			;Yes,jump
;R58B		or	al,10h				;change to slave value
;R58B@@:
;R58B		push	bx				;store BX to stack
;R58B		push	cx				;R58A ;store BX to stack
;R58B		call	CKDRIVERDY
;R58B		call	CTLR_BUSY
;R58B		xor	al,al				;NOP command
;R58B		out	dx,al				;send it out
;R58B		pop	cx				;R58A ;restore BX
;R58B		pop	bx				;restore BX
;R58BSend_Nop_CMD_Next:
;R58B		shr	cx,4				;R58A ;shift to next drive of type
;R58B		shl	bh,1				;next drive
;R58B		test	bh,10h				;drive > 4?
;R58B		jz	Send_Nop_CMD_Loop		;below then continue
;R58B
;R58B		popa
;R58B;R58A		pop	es
;R58B		ret
;R58BSend_ATAPI_NOP_CMD	endp
;R58B;R58 end

FCODE		ENDS
		END
