⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wdrminit.asm

📁 Dos6.0
💻 ASM
📖 第 1 页 / 共 4 页
字号:
    ;
    ;	  /d:svf
    ;	  /d:s /d:v /d:f
    ;
    ; These two are the same, both s and v debug options are specified.
    ; we allow both forms so that users don't get confused and can do multiple
    ; debug options either way.
    ;
    ; This loop exits immeidatly if /d:f is found.  Wdctrl will be disabled.
    ;

	movzx	cx, BYTE PTR ds:[80h]
	jcxz	WD_RMI_TSD_No_Debug_Opt

	mov	si, 81h
	cld
WD_RMI_TSD_Cont_Search:
	lodsb
WD_RMI_TSD_Cont_Search2:
	cmp	al,'/'
	jne	short WD_RMI_TSD_ChkBnd
WD_RMI_TSD_NextSw:
	dec	cx
	jz	SHORT WD_RMI_TSD_No_Debug_Opt
	lodsb
	or	al,20h			; force to lower case
	cmp	al,'d'			; /d ?
	jne	SHORT WD_RMI_TSD_UnkSwitch	; No, unknown switch
	dec	cx
	jz	SHORT WD_RMI_TSD_No_Debug_Opt
	lodsb
	cmp	al,':'			; /d: ?
	jne	SHORT WD_RMI_TSD_UnkSwitch	; No, unknown switch
	dec	cx
	jz	SHORT WD_RMI_TSD_No_Debug_Opt
	lodsb
WD_RMI_TSD_ContDebOpt:
	cmp	al,'A'			; /d: something that is a letter?
	jb	short WD_RMI_TSD_UnkSwitch	; No, unknown switch
	cmp	al,'Z'
	jbe	short WD_RMI_TSD_IsUpDebOpt	; Yes
	cmp	al,'a'
	jb	short WD_RMI_TSD_UnkSwitch	; No, unknown switch
	cmp	al,'z'
	ja	short WD_RMI_TSD_UnkSwitch	; No, unknown switch
WD_RMI_TSD_IsUpDebOpt:
	or	al,20h			; force to lower case
	cmp	al, "f"
	je	SHORT WD_RMI_TSD_Dont_Load
	dec	cx
	jz	SHORT WD_RMI_TSD_No_Debug_Opt
	lodsb
	cmp	al,20h			; End of this debug opt?
	je	short WD_RMI_TSD_LoopIt 	; Yes
	cmp	al,09h			; End of this debug opt?
	je	short WD_RMI_TSD_LoopIt 	; Yes
	cmp	al,'/'			; End of this debug opt?
	je	short WD_RMI_TSD_NextSw 	; Yes
	jmp	short WD_RMI_TSD_ContDebOpt

WD_RMI_TSD_UnkSwitch:
	dec	cx
	jz	SHORT WD_RMI_TSD_No_Debug_Opt
WD_RMI_TSD_UnkSwitchCnt:
	lodsb
	cmp	al,20h
	je	short WD_RMI_TSD_LoopIt
	cmp	al,09h
	je	short WD_RMI_TSD_LoopIt
	cmp	al,'/'
	je	short WD_RMI_TSD_NextSw
	loop	WD_RMI_TSD_UnkSwitchCnt
	jmp	SHORT WD_RMI_TSD_No_Debug_Opt

WD_RMI_TSD_ChkBnd:
	cmp	al,' '
	je	short WD_RMI_TSD_LoopIt
	cmp	al,09h
	jne	short WD_RMI_TSD_No_Debug_Opt
WD_RMI_TSD_LoopIt:
	loop	WD_RMI_TSD_Cont_Search

WD_RMI_TSD_No_Debug_Opt:
	clc
WD_RMI_TSD_Pop_Exit:
	popa
	pop	ds
	ret

WD_RMI_TSD_Dont_Load:
	stc
	jmp	WD_RMI_TSD_Pop_Exit

EndProc Test_Disable_Switch


;******************************************************************************
;
;   Print_Hex_Byte
;
;   DESCRIPTION:
;
;   ENTRY:
;	AL = Byte to print
;
;   EXIT:
;
;   USES:
;	Flags
;
;==============================================================================

Hex_Convert_Table db "0123456789ABCDEF"

BeginProc Print_Hex_Byte

	pusha

	mov	bx, ax
	mov	si, ax

	shr	bx, 4
	and	bx, 1111b
	and	si, 1111b

	mov	dl, Hex_Convert_Table[bx]
	mov	ah, 2
	int	21h

	mov	dl, Hex_Convert_Table[si]
	int	21h

	popa
	ret

EndProc Print_Hex_Byte

ENDIF

;******************************************************************************
;
;   Clean_Up_Hooks
;
;   DESCRIPTION:
;
;   ENTRY:
;
;   EXIT:
;
;   USES:
;
;==============================================================================

BeginProc Clean_Up_Hooks

	pusha

	xor     ecx, ecx
	xchg	ecx, [DOS_BIOS_Int13_Vec]
	jecxz	WD_UIC_Int13_Unhooked

	mov	eax, [ROM_BIOS_Int13_Vec]

	mov     dx, cx
	shr     ecx, 16
	mov     ds, cx

	mov     bx, ax
	shr     eax, 16
	mov     es, ax

	mov     ah, 13h
	int     2Fh

	mov     ax, cs
	mov     ds, ax
	mov     es, ax

;
;   Check to see if we have incremented the InDOS flag and broadcasted the
;   hardware detection Int 2Fh API.  If so, dec the InDOS flag and signal
;   then end of hardware detection.
;
WD_UIC_Int13_Unhooked:
	xor	cx, cx
	xchg	cl, [Signaled_Detection]
	jcxz	SHORT WD_UIC_Exit

;
;   WARNING:  Strange hanging bug with MS-NET server kernel loaded if you
;	      try to get the InDOS ptr while InDOS is non-zero.  Therefore,
;	      we don't want to call DOS here to get the InDOS flag.  That's
;	      why we saved it away earlier.
;
	push	es
	les	bx, [InDOS_Ptr] 		; ES:[BX] -> InDOS flag
	dec	BYTE PTR es:[bx]		; Dec the InDOS flag
	pop	es

	mov	ax, (W386_Int_Multiplex SHL 8) + W386_Device_Broadcast
	mov	bx, BlockDev_Device_ID
	mov	cx, BlockDev_API_Hw_Detect_End
	int	2Fh

WD_UIC_Exit:
	popa
	ret

EndProc Clean_Up_Hooks


;******************************************************************************
;
;   Fatal_Disk_Error
;
;   DESCRIPTION:
;       This procedure is jumped to by WDCtrl_Validate_Drive if a fatal
;       error is detected.  It displays a nasty warning message and hangs
;       the machine.
;
;   ENTRY:
;       DS = Our data segment
;       BL = Error code
;
;   EXIT:
;       Never!
;
;   USES:
;       Who cares!
;
;==============================================================================

BeginProc Fatal_Disk_Error

	call	Clean_Up_Hooks

IFNDEF SETUP
        add     bl,'0'                  ;Convert error code to ASCII 0-9
        mov     si, OFFSET WD_Fatal_Error_Code
        mov     ds:[si], bl             ;Poke the error number in

	mov     ah, 9
	mov     dx, OFFSET WD_Fatal_Error_Msg
	int     21h
ELSE
	mov   ax, DGROUP              ;Set up DS, ES to our data segment
	mov   ds, ax                  ;before calling error display routine.
	mov   es, ax

	mov   ax, ERR_WDCTRL_FATAL
	push  ax
	call  _WDCtrlHangError
	pop   ax
ENDIF

	jmp     $

EndProc Fatal_Disk_Error


;******************************************************************************
;
;   WDCtrl_Validate_Drive
;
;   DESCRIPTION:
;   The procedure must be called with the following parameters:
;	DL = Int 13h drive number to test (80h or 81h)
;	[0:DI] -> Fixed disk parameter table for this drive
;	DS=ES pointing to a data segment with the following data variables:
;
;	    Orig_Int13_Vector	dd	?
;	    Int13_Buffer	db	512 dup (?)
;	    My_Read_Buffer	db	512 dup (?)
;
;	The Orig_Int13_Vector must be filled in by the caller before invoking
;	this code.  This variable should contain the CS:IP value returned
;	by DOS from the Int 2Fh/AH=13h call to obtain the address of the
;	original Int 13h handler.  The other variables do not need to be
;	filled in.
;
;   The procedure will do one of three things:
;	Return with carry clear to indicate that the drive is WDCtrl compatible
;	Return with carry set to indicate that it can't use the drive
;	Jump to a label named "FATAL_DISK_ERROR".  The main program should
;	    display an error message and HANG THE MACHINE if this happens.
;
;	If the procedure returns with carry set then CX will contain a value
;	    that defines the phase of initialization that failed.
;
;       A flag is returned in BX indicating whether or not the ALTERNATE
;	Status register should be used.  BX is set to 0FFFFh iff the
;	alt status register should be used by WDCtrl for this drive.  BX
;	will be 0 if the normal status register should be used for this drive.
;
;   All segment registers will be preserved by the procedure.  All other
;   registers and flags will be modified.
;
;==============================================================================


Check_Invalid MACRO JmpIns
        LOCAL WD_CI_Invalid, WD_CI_Valid

IFNDEF DEBUG
	JmpIns	WD_VD_Invalid
	inc	[bp.Test_Phase]
ELSE
        JmpIns  SHORT WD_CI_Invalid
        inc     [bp.Test_Phase]
        jmp     SHORT WD_CI_Valid

WD_CI_Invalid:
        int     3
        jmp     WD_VD_Invalid

WD_CI_Valid:
ENDIF
	ENDM

Check_Fatal_Error MACRO JmpIns,ErrorCode        ;;Trashes bl
	mov	bl, ErrorCode
	JmpIns	Fatal_Disk_Error
	ENDM


BeginProc WDCtrl_Validate_Drive

Test_Stack_Frame STRUC
Test_Sector_Num      dw         ?
Test_Cyl_Num	     dw	        ?
Test_Head_Num	     dw	        ?
Test_Phase	     dw	        ?
Test_Loop_Phase      dw	        ?
Test_Drive_Number    db	        ?
		     db	        ?       ; Dword align
Test_Param_Off	     dw	        ?
Test_Param_Seg	     dw	        ?
Test_Alt_Status_Flag dw         ?
Test_Stack_Frame ENDS


	push	es
	push	bp
	sub	sp, SIZE Test_Stack_Frame
	mov	bp, sp

	mov	[bp.Test_Drive_Number], dl

	xor	ax, ax
	mov	[bp.Test_Phase], ax
	mov	[bp.Test_Loop_Phase], ax

	mov	es, ax
	les	di, es:[di]			; ES:DI -> Drive param table

	mov	[bp.Test_Param_Seg], es
	mov	[bp.Test_Param_Off], di

        ;** Default to the ALT status register.  We clear the bit
        ;**     anytime we fail with this register and use the normal one.
	mov	[bp.Test_Alt_Status_Flag], 0FFFFh

;------------------------------------------------------------------------------
;
;   First make sure that the fixed disk parameter table contains the same
;   information as Int 13h Get Drive Parameters returns.
;
;------------------------------------------------------------------------------

        ;** Phase 0
	mov	ah, 08h
	pushf
	cli
	call	[ROM_BIOS_Int13_Vec]		; Q: Did get drive params work?
	Check_Invalid jc			;    N: Error
						;    Y: Compare to FDPT

        ;** Phase 1
	inc	dh				; One greater returned
	cmp	dh, es:[di.FDPT_Max_Heads]	; Q: Heads equal?
	Check_Invalid jne			;    N: No good

        ;** Phase 2
	mov	ax, cx
	and	al, 00111111b
	cmp	al, es:[di.FDPT_Sec_Per_Track]	; Q: Sector count the same?
	Check_Invalid jne			;    N: That's strange!

        ;** Phase 3
	shr	cl, 6
	xchg	ch, cl
	add	cx, 2				; TWO GREATER RETURNED!
	cmp	cx, es:[di.FDPT_Max_Cyl]	; Q: Cylinder numbers match?
        jne     SHORT @F                        ;    N: Try Zenith check
        inc     [bp.Test_Phase]                 ;    Y: Yes.  Bump phase
        jmp     SHORT WD_VD_CylOK
@@:     inc     cx                              ; Check THREE for Zenith
	cmp	cx, es:[di.FDPT_Max_Cyl]
	Check_Invalid jne			;    N: Very, very weird
WD_VD_CylOK:


;------------------------------------------------------------------------------
;
;   The Test_Loop_Phase variable determines which test to perform.  We will
;   attempt to read 3 different sectors:
;	The 1st sector on the 1st head on the 1st Cyl
;	The 503rd sector
;	The next-to-last sector on the next-to-last head on the next-to-last cyl
;
;------------------------------------------------------------------------------

WD_VD_Do_Next_Test:
	mov	ax, [bp.Test_Loop_Phase]
	cmp	ax, 1
	je	SHORT WD_VD_Test_503
	ja	SHORT WD_VD_Test_Last

	inc	ax
	mov	[bp.Test_Sector_Num], ax
	mov	[bp.Test_Head_Num], ax
	mov	[bp.Test_Cyl_Num], ax
	jmp	SHORT WD_VD_Do_Read_Now

;------------------------------------------------------------------------------
;
;   Now read the next-to-the-last sector on the next-to-the-last head,
;   and on the cylinder 7/8 of the way to the end.  We don't test the
;   last sector because the BIOS might be lying to us about where the
;   last sector resides.
;
;------------------------------------------------------------------------------

WD_VD_Test_Last:
	movzx	ax, es:[di.FDPT_Sec_Per_Track]
	dec	ax
	mov	[bp.Test_Sector_Num], ax
	movzx	ax, es:[di.FDPT_Max_Heads]
	dec	ax
	mov	[bp.Test_Head_Num], ax
	mov	ax, es:[di.FDPT_Max_Cyl]
        mov     cx, ax                          ; Get cyl 7/8 of way to end
        shr     cx, 3
        sub     ax, cx
	mov	[bp.Test_Cyl_Num], ax
	jmp	SHORT WD_VD_Do_Read_Now

;------------------------------------------------------------------------------
;
;   Now figure out the head/cyl/sector number for sector 503 on the disk.
;   This number was chosen since 503 (decimal) is a prime number.  This will
;   verify that the BIOS is using standard translation of the BIOS parameter
;   table.
;
;------------------------------------------------------------------------------

WD_VD_Test_503:
	mov	eax, 503			; EAX = Sector to begin xfer at

	xor	edx, edx			; Zero high dword for idiv
	movzx	ecx, es:[di.FDPT_Sec_Per_Track]
	idiv	ecx				; Remainder+1 = Starting sector
	inc	dx				; Inc to make 1 based
	mov	[bp.Test_Sector_Num], dx	; Save it on the stack
	xor	edx, edx			; Zero high dword for idiv
	movzx	ecx, es:[di.FDPT_Max_Heads]
	idiv	ecx				; EAX = Cylinder number
						; EDX = Starting head
	mov	[bp.Test_Cyl_Num], ax		; Save 'em for later
	mov	[bp.Test_Head_Num], dx

;------------------------------------------------------------------------------
;
;   The drive parameters look OK.  Now verify read a sector from the drive to
;   attempt to force that drive to be selected.  To prevent problems with a
;   cache we will call the original BIOS handler directly.
;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -