📄 wdrminit.asm
字号:
PAGE 58,132
;******************************************************************************
TITLE WDRMINIT.ASM -- Real Mode Initialization for WDCTRL.386
;******************************************************************************
;
; (C) Copyright MICROSOFT Corp., 1990
;
; Title: WDRMINIT.ASM -- Real Mode Initialization for WDCTRL.386
;
; Version: 1.00
;
; Date: 17-Oct-1990
;
; Author: RAL
;
;------------------------------------------------------------------------------
;
; Change log:
;
; DATE REV DESCRIPTION
; ----------- --- -----------------------------------------------------------
; 17-Oct-1990 RAL
; 22-Oct-1991 JGT Switched to alternate status register
; Allowed Zenith machines to run by allowing track count
; to be THREE off (instead of the 'normal' TWO)
; 24-Oct-1991 JGT Allowed one drive to be non-FastDisk compatible and
; load.
; 27-Oct-1991 RAL For for hang if MS-NET kernel server running -- Don't
; call DOS to get InDOS ptr once incrmented.
;
; N.b., this file is (nearly) duplicated in apps\setup\dos\wdrminit.asm.
; Changes made to this file should also be made to that file.
;
;==============================================================================
.386p
;******************************************************************************
; I N C L U D E S
;******************************************************************************
.XLIST
INCLUDE VMM.Inc
INCLUDE OptTest.Inc
INCLUDE BlockDev.Inc
INCLUDE Int13.Inc
INCLUDE WDLocal.Inc
INCLUDE Int2FAPI.Inc
.LIST
;******************************************************************************
SETUP EQU 1
IFDEF SETUP
EXTRN _WDCtrlHangError:FAR
BeginProc MACRO ProcName
PUBLIC ProcName
ProcName PROC NEAR
ENDM
EndProc MACRO ProcName
ProcName ENDP
ENDM
DGROUP GROUP _DATA
ERR_WDCTRL_FATAL equ 41
ERR_WDCTRL_BAD_SOFTWARE equ 42
FLAT SEGMENT AT 0
FLAT ENDS
;------------------------------------------------------------------------------
FASTDISK SEGMENT WORD PUBLIC USE16 'CODE'
ASSUME CS:FASTDISK
ASSUME DS:FASTDISK
ASSUME ES:FASTDISK
ASSUME SS:FASTDISK
ELSE
VxD_REAL_INIT_SEG
EXTRN Invalid_Win386_Ver_String:BYTE
EXTRN Invalid_Int13_Chain:BYTE
EXTRN Invalid_IRQ_String:BYTE
EXTRN Invalid_Controller_String:BYTE
EXTRN Validation_Failed_String:BYTE
EXTRN Invalid_DOS_Ver_String:BYTE
EXTRN WD_Fatal_Error_Code:BYTE
EXTRN WD_Fatal_Error_Msg:BYTE
EXTRN WD_Incompatible_Sw_Msg:BYTE
EXTRN No_Fixed_Disk_String:BYTE
EXTRN Pause_String:BYTE
EXTRN WD_Env_String_Bail:BYTE
EXTRN ES_Debug:BYTE
EXTRN ES_Debug_Len:BYTE
EXTRN ES_Disable:BYTE
EXTRN ES_Disable_Len:BYTE
EXTRN PS_Enable_Wdctrl:BYTE
EXTRN PS_Force_Enable_80:BYTE
EXTRN PS_Force_Enable_81:BYTE
EXTRN PS_Force_Alt_Status0:BYTE
EXTRN PS_Force_Alt_Status1:BYTE
ENDIF
;******************************************************************************
ALIGN 4
InDOS_Ptr LABEL DWORD
InDOS_Off dw ?
InDOS_Seg dw ?
DOS_BIOS_Int13_Vec dd 0 ; 0 means not hooked
ROM_BIOS_Int13_Vec dd 0
Service_Addr dd 0
Int13_Buffer db 512 dup (?)
My_Read_Buffer db 512 dup (?)
Num_Int13_Drives db 0
Signaled_Detection db False
QEMMDeviceName db 'QEMM386$',0
QPIEntryPoint dd ?
QEMM_Stealth_Enabled db False
;******************************************************************************
;
; WD_Real_Mode_Init
;
; DESCRIPTION:
; This procedure attempts to detect a standard AT type hard disk
; controller being used for Int 13h. It will check for two hard
; disk drives by monitoring changes to the cylinder register after
; various reads. Note that this code will use the DOS Int 2Fh, AH=13h
; to bypass any caching software that may be installed.
;
; To detect the presence of a Western Digital controller this code
; will do the following:
; Get original Int 13h vector from DOS
; For disks 80h and 81h (if either exists) do
; Read port 1F7h (Status) and make sure it looks OK
; Read sector 1, track 0, head 0
; Temp=Value of port(1F4h)
; Read sector 1, track 2, head 0
; If Temp=Value of port(1F4h) then NOT OK
; If Temp-Value of port(1F4h) > 4 then NOT OK
;
; ENTRY:
; CS=DS=ES
; AX = Win386 version number (requires 3.10)
; SI = Environment segment
;
; EXIT:
; EDX = Flags
; Bit 0 = 1 if drive 80h is on standard AT controller
; Bit 1 = 1 if drive 81h is on standard AT controller
; Bit 2 = 1 if alternate status register should be used
;
; USES:
;
;==============================================================================
BeginProc WDCtrl_Real_Mode_Init
IFNDEF SETUP
cmp ax, 30Ah
jb WD_RMI_Invalid_Win386
;** Save the loader service address
mov [Service_Addr], ecx
call Test_Disable_Switch ; Q: User set /D:F option?
jc WD_RMI_Dont_Load_Silent ; Y: Don't load
;** Here we check for two environment strings:
;** WDCTRLDISABLE=Y ;Disables WDCTRL (displays message)
;** WDCTRLDEBUG=Y ;Stops debugger at INT 3 in RM Init
mov es, si ; Set ES to our environment
mov si, OFFSET ES_Disable ;'WDCTRLDISABLE='
xor ch,ch
mov cl, ES_Disable_Len
call WD_RMI_Get_Env_String ;Get the value for the string
or ax, ax ;Bail out?
jz SHORT WD_RMI_NoEnvBailOut ;No
mov dx, OFFSET WD_Env_String_Bail ;Get message
jmp WD_RMI_Print_Error ;Exit with error
WD_RMI_NoEnvBailOut:
mov si, OFFSET ES_Debug ;'WDCTRLDEBUG='
xor ch,ch
mov cl, ES_Debug_Len
call WD_RMI_Get_Env_String
or ax, ax
jz SHORT WD_RMI_NoInt3
int 3 ;Break to debugger
WD_RMI_NoInt3:
;** Check for SYSTEM.INI string that must be set to true for
;** WDCTRL to load.
mov ax, 3 ;Service: Get_Profile_Boolean
xor ecx, ecx ;Default is FALSE
xor si, si ;[386Enh] is default section
mov di, OFFSET PS_Enable_Wdctrl ;'32BITDISKACCESS'
call cs:[Service_Addr] ;Call loader service
or cx, cx
jz WD_RMI_Dont_Load_Silent
;** We have a SYSTEM.INI switch here to force WDCTRL enabled
;** without validation. This is useful for drives that fail
;** validation, but work fine with FastDisk.
mov ax, 3 ;Service: Get_Profile_Boolean
xor ecx, ecx ;Default is FALSE
xor si, si ;[386Enh] is default section
mov di, OFFSET PS_Force_Enable_80 ;'WDCTRLDRIVE0', 0
call cs:[Service_Addr] ;Call loader service
or cx, cx
mov bl,0 ;Clear the flag bits
jz SHORT WD_RMI_No_Drive_80 ;Drive not forced enabled
or bl, RF_Drive_80h_Ours ;Flag that drive 80h was forced on
WD_RMI_No_Drive_80:
mov ax, 3 ;Service: Get_Profile_Boolean
xor ecx, ecx ;Default is FALSE
xor si, si ;[386Enh] is default section
mov di, OFFSET PS_Force_Enable_81 ;'WDCTRLDRIVE1', 0
push bx ;Save flag bits
call cs:[Service_Addr] ;Call loader service
pop bx
or cx, cx
jz SHORT WD_RMI_No_Drive_81 ;Drive not forced enabled
or bl, RF_Drive_81h_Ours ;Flag that drive 80h was forced on
WD_RMI_No_Drive_81:
test bl,bl ;Any bits set?
jz SHORT WD_RMI_No_Force_Enable ;No. Do normal validation
;** Now that we have verified that the user wanted one or two
;** drives forced on, they can also specify if the drive
;** should use the alternate status register. Default is NO.
mov ax, 3 ;Service: Get_Profile_Boolean
xor ecx, ecx ;Default is FALSE
xor si, si ;[386Enh] is default section
mov di, OFFSET PS_Force_Alt_Status0 ;'WDCTRLALTSTATUS0', 0
push bx ;Save flag bits
call cs:[Service_Addr] ;Call loader service
pop bx
or cx, cx
jz SHORT WD_RMI_No_Alt_Status0 ;Drive not forced enabled
or bl, RF_Use_Alt_Stat_80 ;Flag that user wanted alt status reg
WD_RMI_No_Alt_Status0:
mov ax, 3 ;Service: Get_Profile_Boolean
xor ecx, ecx ;Default is FALSE
xor si, si ;[386Enh] is default section
mov di, OFFSET PS_Force_Alt_Status1 ;'WDCTRLALTSTATUS1', 0
push bx ;Save flag bits
call cs:[Service_Addr] ;Call loader service
pop bx
or cx, cx
jz SHORT WD_RMI_No_Alt_Status1 ;Drive not forced enabled
or bl, RF_Use_Alt_Stat_81 ;Flag that user wanted alt status reg
WD_RMI_No_Alt_Status1:
jmp WD_RMI_Have_Ref_Data ;Force it on as if validation
; passed successfully
WD_RMI_No_Force_Enable:
push ds ;Restore ES
pop es
ENDIF
;------------------------------------------------------------------------------
;
; Now make sure that we have some Int 13h drives by calling Get Drive
; Parameters for drive 80h.
;
;------------------------------------------------------------------------------
mov ah, 08h ; Get drive parameters
mov dl, 80h ; For first drive
int 13h ; Q: Is there one or more?
sti ; STI TO WORK AROUND AD-DOS!
IFNDEF SETUP
jc WD_RMI_No_Disk_Drives ; N: Pretty pointless
ELSE
jc WD_RMI_Error_Exit ; N: Pretty pointless
ENDIF
; Y: Do some funky tests
mov [Num_Int13_Drives], dl ; Save this for later
;------------------------------------------------------------------------------
;
; Now do a check for the COMPAQ dual WDCTRL configuration. COMPAQ machines
; have the ability to support two WDCTRLs at different I/O ports but which
; share the same IRQ (12). This would work, WDCTRL would handle one, and
; COMPAQ driver (EXTDISK.SYS) the other, except for the fact that the IRQ
; is shared. We don't have code to handle the IRQ sharing so we'll just
; punt this config and not install.
;
;------------------------------------------------------------------------------
;
; First see if this is a COMPAQ machine. This is the same detection
; code that is in VFD
;
push es
mov ax, 0F000h
mov es, ax
cmp DWORD PTR es:[0FFE8h], 'OC30'
clc
jnz SHORT CompDoneP ; Not COMPAQ
cmp DWORD PTR es:[0FFECh], 'QAPM'
clc
jnz SHORT CompDoneP ; Not COMPAQ
;
; Is a COMPAQ machine, check for DUAL controler config by reading CMOS
;
mov ax, 1bh ; Secondary controller drive 1
mov dx, 70h ; CMOS Index I/O port
out dx, al
inc dx ; CMOS data I/O port
IO_Delay
IO_Delay
in al, dx ; Get drive type
or al, al ; Q: Do we have a drive (clears carry)?
jz short CompDoneP ; N: jump with carry clear
dec dx
mov al, 0eh ; Check if CMOS is OK
IO_Delay
IO_Delay
out dx, al
inc dx
IO_Delay
IO_Delay
in al, dx
test al, 60h ; Q: Is CMOS Valid (clears carry)?
; Checking CMOS Bad Checksum and
; CMOS Config Invalid
jnz short CompDoneP ; N: Error, jump with carry clear
xor ecx,ecx
dec ecx ; Report validation phase 0FF,0FF
stc ; SET CARRY, dual controler config
CompDoneP:
pop es
IFNDEF SETUP
jc WD_RMI_Validation_Failed ; Don't instl COMPAQ dual CTRL
ELSE
jc WD_RMI_Error_Exit ; Don't instl COMPAQ dual CTRL
ENDIF
;------------------------------------------------------------------------------
;
; Check for QEMM stealth. WDCTRL will load if stealth is enabled even though
; the Int 13h hook points to a "bad" location (QEMM hooks it).
;
;------------------------------------------------------------------------------
call Detect_QEMM_Stealth
;------------------------------------------------------------------------------
;
; Now do lots of party stuff to make sure cache programs flush or at least
; don't try to lazy-write any data while we do this test. To make sure
; of this we will do the following:
; Broadcast the BlockDev hardware detection API Int 2Fh
; Do an Int 13h read of sector 0 on both drives
; Do a DOS disk reset on drives C-Z (may flush)
; Set the InDOS flag
;
;------------------------------------------------------------------------------
;
; Broadcast an Int 2Fh that tells cache programs that disk hardware detection
; is about to begin. This broadcast can be intercepted by new cache
; programs to prevent unnecessary flushes and to prevent conflicts.
;
;------------------------------------------------------------------------------
mov ax, (W386_Int_Multiplex SHL 8) + W386_Device_Broadcast
mov bx, BlockDev_Device_ID
mov cx, BlockDev_API_Hw_Detect_Start
int 2Fh
;------------------------------------------------------------------------------
;
; Some cache programs punt the entire cache when someone that is not DOS
; does an Int 13h. Hopefully this will happen when we do this read.
;
;------------------------------------------------------------------------------
mov ax, 0201h ; Read 1 sector
mov bx, OFFSET Int13_Buffer ; Into this buffer (ES:BX)
mov cx, 0001h ; Track 0, sector 1
mov dx, 0080h ; Head 0, drive 80h
int 13h ; Do it!
sti ; STI TO WORK AROUND AD-DOS!
cmp [Num_Int13_Drives], 1 ; Q: More than one drive?
je SHORT WD_RMI_Reset_Drives ; N: Done
mov ax, 0201h ; Read 1 sector
mov bx, OFFSET Int13_Buffer ; Into this buffer (ES:BX)
mov cx, 0001h ; Track 0, sector 1
mov dx, 0081h ; Head 0, drive 81h
int 13h ; Do it!
sti ; STI TO WORK AROUND AD-DOS!
;------------------------------------------------------------------------------
;
; Do a disk reset on every drive C-Z so that cache programs will flush.
; PC Super Kwik will pay attention to this DOS call and flush lazy writes.
;
;------------------------------------------------------------------------------
WD_RMI_Reset_Drives:
mov ah, 19h
int 21h
push ax
mov dl, 2 ; Start with drive C:
WD_RMI_Flush_Loop:
mov ah, 0Eh ; Select the drive
int 21h ; (AL contains max drive)
mov ah, 0Dh ; Flush the drive
int 21h
inc dl ; DL = Next drive to flush
cmp dl, al ; Q: Any more drives to flush?
jb SHORT WD_RMI_Flush_Loop ; Y: Keep looking
pop dx ; DL = Original default drive
mov ah, 0Eh ; Select drive
int 21h
;------------------------------------------------------------------------------
;
; TSRs should not pop up and do DOS calls when the InDOS flag is set.
; We will leave the flag non-zero throughout the entire test.
;
;------------------------------------------------------------------------------
WD_RMI_Set_InDOS:
push es
mov ah, 34h
int 21h ; ES:[BX] -> InDOS flag
inc BYTE PTR es:[bx]
mov [InDOS_Seg], es
mov [InDOS_Off], bx
pop es
mov [Signaled_Detection], True ; Set flag to indicate that
; we need to dec InDOS and
; do end detection Int 2Fh call
;------------------------------------------------------------------------------
;
; Now wait for 2 clock ticks to make sure all disk activity that may
; have slipped in before we bumped InDOS will complete.
;
;------------------------------------------------------------------------------
sti ; Paranoia in case some random
; software int turned off ints
push es
mov ax, 40h
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -