📄 videoid.asm
字号:
;
; Name: VideoID
;
; Function: Detects the presence of various video subsystems and
; associated monitors.
;
; Caller: Microsoft C:
;
; void VideoID(VIDstruct);
;
; struct
; {
; char VideoSubsystem;
; char Display;
; }
; *VIDstruct[2];
;
; Subsystem ID values:
; 0 = (none)
; 1 = MDA
; 2 = CGA
; 3 = EGA
; 4 = MCGA
; 5 = VGA
; 6 = 8514/A
; 7 = XGA
; 80h = HGC
; 81h = HGC+
; 82h = Hercules InColor
;
; Display types: 0 = (none)
; 1 = MDA-compatible monochrome
; 2 = CGA-compatible color
; 3 = EGA-compatible color
; 4 = PS/2-compatible monochrome
; 5 = PS/2-compatible color
; 6 = 8514/A Monitor
;
;
; The values returned in VIDstruct[0].VideoSubsystem and
; VIDstruct[0].Display indicate the currently active subsystem.
;
;----------------------------------------------------------------------------
cssize equ 2 ;Used for small memory model
ARGpVID EQU [bp+4+cssize] ; Pointer to structure
VIDstruct STRUC ; corresponds to C data structure
Video0Type DB ? ; first subsystem type
Display0Type DB ? ; display attached to first
; subsystem
Mode0 DB ? ; Mode of first subsystem
NumCols0 DB ? ; Number of columns on first
iMemory0 DW ? ; Memory in first system
Video1Type DB ? ; second subsystem type
Display1Type DB ? ; display attached to second
; subsystem
Mode1 DB ? ; Mode of second subsystem
NumCols1 DB ? ; Number of columns on second
iMemory1 DW ? ; Memory in second system
VIDstruct ENDS
Device0 EQU word ptr Video0Type[di]
Device1 EQU word ptr Video1Type[di]
MDA EQU 1 ; subsystem types
CGA EQU 2
EGA EQU 3
MCGA EQU 4
VGA EQU 5
Eighty514 EQU 6
XGA EQU 7
HGC EQU 80h
HGCPlus EQU 81h
InColor EQU 82h
MDADisplay EQU 1 ; display types
CGADisplay EQU 2
EGAColorDisplay EQU 3
VGAMonoDisplay EQU 4
VGAColorDisplay EQU 5
Eighty514Display EQU 6
TRUE EQU 1
FALSE EQU 0
DGROUP GROUP _DATA
_TEXT SEGMENT byte public 'CODE'
ASSUME cs:_TEXT,ds:DGROUP
PUBLIC _VideoID
EXTRN C ArcnetCardPresent:FAR
_VideoID PROC far
push bp ; preserve caller registers
mov bp,sp
push es ; Save caller's ES
push si
push di
; initialize the data structure that will contain the results
les di,ARGpVID ; ES:DI -> start of data structure
mov es:Device0,0 ; zero these variables
mov es:Device1,0
; look for the various subsystems using the subroutines whose addresses are
; tabulated in TestSequence; each subroutine sets flags in TestSequence
; to indicate whether subsequent subroutines need to be called
mov byte ptr TestSequence,TRUE
mov byte ptr XGAflag,FALSE
mov byte ptr Eighty514flag,FALSE
mov byte ptr EGAflag,TRUE
mov byte ptr CGAflag,TRUE
mov byte ptr Monoflag,TRUE
mov cx,NumberOfTests
mov si,offset DGROUP:TestSequence
L01: lodsb ; AL := flag
test al,al
lodsw ; AX := subroutine address
jz L02 ; skip subroutine if flag is false
push si
push cx
call ax ; call subroutine to detect
; subsystem
pop cx
pop si
L02: loop L01
; determine which subsystem is active
call FindActive
pop di ; restore caller registers and
; return
pop si
pop es
mov sp,bp
pop bp
ret
_VideoID ENDP
; FindXGA
;
; Note: XGA adapters MAY be able to be detected by checking port
; 2110H. Read the port, toggle bit 0, write to the port, wait,
; read the port and see if the port's value is the changed. If it
; did, it is an XGA. Don't forget to toggle the bit back again,
; and it might not hurt to disable interrupts (CLI) during the check.
;
; Bit 0 toggles the XGA's coprocessor between Intel and Motorola
; modes (backwards storage for 16 and 32 bit values). Also, the XGA
; standard allows for up to six XGA adapters to exist in a system
; at one time, each port address is 16 (10H) higher than the other.
; Checking 2120H, 2130H, 2140H, 2150H, and 2160H may be well advised.
;
; In the short time we had to hand over our code, I was not able to
; determine how to detect the monitor type attached to the XGA.
; Sorry about that. Also, I was not able to test this XGA detection
; theory out (except to see that VGAs did NOT retain the toggling of
; bit zero).
;
FindXGA PROC near
mov bx, OFFSET DGROUP:rgXgaPorts ; Store the XGA port address array location
XgaTestLoop:
mov dx, [bx] ; Get the XGA's port address
and dx, dx ; Jump out if it's zero
jz fnXgaDone
in al, dx ; Read the port
mov ch, al ; Store the "original" port value
xor al, 1 ; change bit 0
cli ; Clear all interrupts. This is
; important because this routine
; changes the way the XGA functions.
out dx, al ; Output the new value to the XGA port.
jmp short XgaWait01 ; Pause briefly, to allow the change
XgaWait01: ; to take effect.
jmp short XgaWait02
XgaWait02:
jmp short XgaWait03
XgaWait03:
in al, dx ; Get the "changed" value from the port.
mov cl, al ; Store the "changed" value.
mov al, ch ; Send the "original" back to the port.
out dx, al
jmp short XgaWait04 ; Pause briefly, to allow the change
XgaWait04: ; to take effect.
jmp short XgaWait05
XgaWait05:
jmp short XgaWait06
XgaWait06:
sti ; Restore all interrupts.
; I consider it a sucessful test if only bit zero changed. More changes
; might indicate that I am communicating with a different device.
mov ch, cl ; Copy the "changed" port value to bh
mov ah, al ; Copy the "original" port value to ah
and ch, 0FEh ; Mask off bit 0 of "changed" value.
and ah, 0FEh ; Mask off bit 0 of "original" value.
cmp ch, ah ; Q: Do they match?
jne fnXgaNotFound ; N: This is not an XGA port.
cmp cl, al ; Q: Since bits 1-7 match, do all 8
; bits match?
jne fnFoundXga ; N: This is an XGA port.
; Keep looking
fnXgaNotFound:
inc bx ; Bump the port pointer.
inc bx
jmp short XgaTestLoop ; Test the next port.
; This is an XGA.
fnFoundXga:
mov al, XGA ; Say it is an XGA adapter.
; Currently, I do not have a test for the monitor. I will assume it
; is an 8514/A Monitor until I have an accurate test.
mov ah,Eighty514Display ; AH := Display type.
call FoundDevice ; Store the answer.
fnXgaDone:
ret
FindXGA ENDP
;
; Find8514
;
; This function detects the presence of an 8514 display card.
;
; The way we do this is to first write to the Error Term Register and then
; make sure we can read back the value we wrote. Then we check to see
; what kind of monitor is attached since the 8514 can function like a VGA.
;
Find8514 PROC near
ERR_TERM equ 92e8h ; 8514 error term register.
SUBSYS_STAT equ 42e8h ; 8514 Subsystem status register.
call ArcnetCardPresent
or ax,ax ; if Arcnet Present do not do the 8514/a
jnz fn8514NotFound ; test as the Arcnet Card will be reset.
mov dx, ERR_TERM ; load DX with port address (error term port
in ax, dx ; Store original port value ...
mov ax, bx ; ... in BX
mov ax, 5555h ; load AX with value to write to port.
out dx, ax ; Write the data.
mov cx, 10h ; Wait for the port to respond
wait001: loop wait001
in ax, dx ; Read the data back in.
push ax ; Store the value on the stack for a moment
mov ax, bx ; Restore the original value of the port
out dx, ax
pop ax ; Now restore the value we wish to check
cmp ax, 5555h ; Q: is 8524 present ?
jne fn8514NotFound ; N: indicate 8514 not present.
; Y: 8514 is present, now check monitor.
;
; Now we need to determine what type of monitor is attached to the
; 8514 card. To do this we check ID bits 0,1,2 in the subsystem
; status register. Depending on the Monitor attached we return:
;
; 8503 Display = VGAMonoDisplay
; 8512 Display = VGAColorDisplay
; 8513 Display = VGAColorDisplay
; 8514 Display = Eighty514Display
;
mov dx,SUBSYS_STAT ; Now, we have the adapter. Check monitor.
in ax,dx ; Get word from SUBSYS_STAT
test ax,0040h ; Check Bit 2.
jz Disp_8514 ; Bit 2 == 0 = 8514 Display = GAD_8514.
test ax,0020h ; Bit 1 == 0 = 8503 Display = VGA_MONO.
jz Disp_8503
mov ah,VGAColorDisplay ; AH := Display type
jmp short fn8514Found
Disp_8503:
mov ah,VGAMonoDisplay ; AH := Display type
jmp short fn8514Found
Disp_8514:
mov ah,Eighty514Display ; AH := Display type
jmp short fn8514Found
fn8514Found:
mov al,Eighty514 ; AL := subystem type
call FoundDevice
; reset flags for subsystems that have been ruled out
mov byte ptr CGAflag,FALSE
mov byte ptr EGAflag,FALSE
jmp short fn8514Done
fn8514NotFound:
; Set the flag for subsystem yet to be checked
mov byte ptr XGAflag,TRUE
fn8514Done:
ret
Find8514 ENDP
;
; FindVGA
;
; This subroutine uses INT 10H function 1Ah to determine the video
; BIOS Display Combination Code (DCC) for each video subsystem
; present.
;
FindVGA PROC near
mov ax,1A00h
int 10h ; call video BIOS for info
cmp al,1Ah
jne L13 ; exit if function not supported
; (i.e., no MCGA or VGA in system)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -