WindowsXP/base/mvdm/dos/v86/cmd/mem/chkvdisk.asm
2025-04-27 07:49:33 -04:00

217 lines
5.7 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1988 - 1991
; * All Rights Reserved.
; */
; Check for existence of a VDisk header. Check the beginning of the segment
; addressed by the INT 19 vector, and, if XMS is available to give us
; A20 toggling, check at the 1Mb boundary. We don't do the latter check
; if we can't do the A20 switch.
;
; Return the size of the VDisk if found.
;
; Checking for a VDISK header at 1Mb is currently disabled. This is because
; the XMS calls used to access the HMA will cause INT 15 memory to
; be claimed if there are currently no Himem or XMS users, and the MEM
; command shouldn't disturb the memory environment in that way.
; We rely on VDisk allocators to use the INT 19 approach to signal
; their memory usage. According to Ray Duncan, this may not be
; entirely reliable, but this is probably better than adding the
; code necessary to do lots of INT 15 block moves to interrogate
; the extended memory arena.
CHECKXMS equ 0 ; set to non-zero to enable checking
; of the HMA for VDisk headers.
.MODEL SMALL
.CODE
extrn _XMM_Installed :Near
extrn _XMM_QueryA20 :Near
extrn _XMM_EnableA20 :Near
extrn _XMM_DisableA20 :Near
;----------------------------------------------------------------------------
;
; following piece of code will be moved into a para boundary. And the para
; address posted in seg of int 19h vector. Offset of int 19h will point to
; VDint19. This is to protect HMA from apps which use VDISK header method
; to determine free extended memory.
;
; For more details read "power programming" column by Ray Duncan in the
; May 30 1989 issue of PC Magazine (pp 377-388) [USING EXTENDED MEMORY,PART 1]
;
;----------------------------------------------------------------------------
;
StartVDHead label byte
;
;-------------- what follows is a dummy device driver header (not used by DOS)
;
dd 0 ; link to next device driver
dw 8000h ; device attribute
dw 0 ; strategy routine offset
dw 0 ; interrupt routine offset
db 1 ; number of units
db 7 dup(0) ; reserved area
VDiskSig1 db 'VDISK'
VLEN1 equ ($-offset VDiskSig1)
db ' V3.3' ; vdisk label
db 15 dup (0) ; pad
VDiskEnd1 dw 0 ; bits 0-15 of free HMA
db 11h ; bits 16-23 of free HMA (1M + 64K)
VDInt19:
db 0eah ; jmp to old vector
OldVDInt19 dd ? ; Saved int 19 vector
EndVDHead label byte
;
;
VDiskHMAHead db 0,0,0 ; non-bootable disk
VDiskSig2 db 'VDISK'
VLEN2 equ ($-offset VDiskSig2)
db '3.3' ; OEM - signature
dw 128 ; number of bytes/sector
db 1 ; sectors/cluster
dw 1 ; reserved sectors
db 1 ; number of FAT copies
dw 64 ; number of root dir entries
dw 512 ; number of sectors
db 0feh ; media descriptor
dw 6 ; number of sectors/FAT
dw 8 ; sectors per track
dw 1 ; number of heads
dw 0 ; number of hodden sectors
VDiskEnd2 dw 440h ; Start of free HMA in K (1M+64K)
EndVDiskHMAHead label byte
;
;
;----------------------------------------------------------------------------
;
; procedure : IsVDiskInstalled
;
; Checks for the presence of VDISK header at 1MB boundary
; & INT 19 vector. Returns number of Kb used as Vdisk
;
; Inputs : none
; Outputs : AX = size of VDisk in Kb, 0 if none found
; Uses : AX, CX
;
;----------------------------------------------------------------------------
;
public _CheckVDisk
_CheckVDisk proc near
push bp
push si ; Save regs
push di
push es
push ds
mov ax,3519h ; Get Int Vector 19h
int 21h
; set registers for CMPS
mov di, offset VDiskSig1 - offset StartVDHead
mov cx, VLEN1
push cs
pop ds
mov si, offset VDiskSig1
rep cmpsb
IF NOT CHECKXMS
jnz cvd_NoDisk
ELSE
jnz cvd_checkXMS ; jump if we didn't find it
ENDIF
;
; Get the first free address in Kb, and determine the number of Kb used
; above 1Mb. First free address in a 24-bit address, so divide by 1024
; to get number of Kb
;
mov di,offset VDiskEnd1 - offset StartVDHead
mov ax,es:[di]+1 ; load top 16 bits of end address
shr ax,1
shr ax,1 ; fast divide of 24 bits by 1024
test es:[di],03FFh ; check for rounding
jz @F
inc ax ; round up if needed
@@:
IF NOT CHECKXMS
jmp short cvd_End
ELSE
pop ds ; clear top of stack
jmp short cvd_End ; AX now has size in Kb
;
; Ensure that A20 is on before we check above 1Mb. If XMS is not
; installed, we punt, and assume no VDisk
;
cvd_checkXMS:
pop ds ; get DS again
call _XMM_Installed
or ax,ax
jz cvd_NoDisk ; No XMS, assume no VDisk
;
; Get and save current A20 state, get A20 on
;
call _XMM_QueryA20
push ax ; save current state
or ax,ax ; already on?
jnz cvd_A20On ; yes, don't turn it on
call _XMM_EnableA20 ; turn it on
cvd_A20On:
push ds ; save DS again
mov ax, 0ffffh
mov ds, ax
mov si, 10h+(offset VDiskSig2 - offset VDiskHMAHead)
mov ax,cs
mov es,ax
mov di, offset VDiskSig2
mov cx, VLEN2
rep cmpsb
jne @F ; if no header, turn off A20 now
; get first free address in Kb
mov si,offset VDiskEnd2 - offset VDiskHMAHead
mov ax,[si]
@@:
pop ds ; get original DS again
pop ax ; get original A20 state
pushf ; save result of header check
or ax,ax ; was A20 already on?
jnz @F ; jump if yes
call _XMM_DisableA20 ; else turn it off again
@@:
popf ; get result of header check
je cvd_End ; jump if present
ENDIF ; CHECKXMS
cvd_NoDisk:
mov ax,1024 ; set up to return 0
cvd_End:
sub ax,1024 ; discount first 1Mb from first
; free address to get size in Kb
IF NOT CHECKXMS
pop ds
ENDIF
pop es
pop di
pop si
pop bp
ret
_CheckVDisk endp
end