217 lines
5.7 KiB
NASM
217 lines
5.7 KiB
NASM
;/*
|
||
; * 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
|
||
|