title "Display Adapter type detection" ;++ ; ; Copyright (c) 1989 Microsoft Corporation ; ; Module Name: ; ; video.asm ; ; Abstract: ; ; This module implements the assembley code necessary to determine ; various display chip sets. ; ; Author: ; ; Shie-Lin Tzong (shielint) 04-Dec-1991. ; Most of the code is taken from Win31 vdd and setup code(with modification.) ; ; Environment: ; ; x86 Real Mode. ; ; Revision History: ; ; ;-- if 0 ; Remove video detection .xlist include video.inc .list else FONT_POINTERS EQU 700h ; physical addr to store font pointers ; This is also the DOS loaded area endif ; Remove Video detection .386 if 0 ; Remove video detection IO_Delay macro jmp $+2 jmp $+2 endm TRUE EQU 1 FALSE EQU 0 extrn _HwIsMcaSystem: near; extrn Ps2SystemBoardVideoId: near; extrn _HwMcaPosData: DWORD; endif ; Remove video detection _DATA SEGMENT PARA USE16 PUBLIC 'DATA' if 0 ; Remove video detection ; ; PVGA ; str_Paradise DB "PARADISE" len_str_Paradise EQU $-str_Paradise str_WDIGITAL DB "WESTERN DIGITAL" len_str_WDIGITAL EQU $-str_WDIGITAL ; ; followings are for Paradise 1F chip check - C. Chiang ; bSave0F db 0 ; Unlock\Lock PR0-PR4 bSave29 db 0 ; Unlock\Lock PR11-PR17 bSave34 db 0 ; Unlock\Lock Flat Panel bSave35 db 0 ; Unlock\Lock Mapping Ram str_PVGA1F db "OPYRIGHT1990WDC" len_str_1F equ $-str_PVGA1F str_PVGA1FC db "OPYRIGHTWD90C22" len_str_1FC equ $-str_PVGA1FC str_1F_GEN db "WD90C2" len_str_GEN equ $-str_1F_GEN String db len_str_1F dup(?) ; ; ATIVGA ; ATI_Sig DB " 761295520" ; ATI signature at in ROM at offset 30 ATI_Sig_Len EQU $-ATI_Sig ; ; TTVGA ; TVGA_Sig DB "TRIDENT MICROSYSTEMS" TVGA_Sig_Len EQU $-TVGA_Sig ; ; Compaq ; CompaqSig db 'OMPAQ' endif ; Remove video detection _DATA ends _TEXT SEGMENT PARA USE16 PUBLIC 'CODE' ASSUME CS: _TEXT, DS:_DATA, SS:NOTHING if 0 ; Remove video detection ;++ ; ; ULONG ; GetVideoAdapterType ( ; VOID ; ) ; ; Routine Description: ; ; This function determines video adapter type in the system. If possible, ; it also determines the various chip sets used in the VGA card. ; ; N.B. Currently, we determine the chip set ONLY if it is VGA and the ; following chip sets are detectiable by this routine: ; ; ; ; ; Arguments: ; ; None. ; ; Return Value: ; ; (eax): Bit 16 - 31 Adapter type i.e. XGA, VGA, 8514 ; Bit 0 - 15 Adapter subtype, V7VGA, CompaqVGA, TsengLab, ... ; zero means unknown type or subtype. EGA and CGA are NOT ; supported. ; ;-- public _GetVideoAdapterType _GetVideoAdapterType proc near push ebx ; ; First check if it is a XGA card? ; call IsXga ; Is it XGA? or ax, ax jz gvaCompaqQVision ; if z, no, go check for Comapq QVision mov eax, VD_XGA ; else it is XGA jmp VideoDone ; ; Check if it is Compaq QVision? ; gvaCompaqQVision: call IsCompaqVideo ; Is it Compaq video ROM? or ax, ax jz short gvaCheckVGA ; Don't do any compaq video test call IsCompaqQVision ; Is it Compaq QVision? or ax, ax jz gvaCompaqAvga ; if z, no, go check for AVGA mov eax, VD_COMPAQ_QVIS jmp VideoDone ; ; Check if it is Compaq AVGA? ; gvaCompaqAvga: call IsCompaqAvga ; Is it Compaq AVGA? or ax, ax jz gvaCheckVga ; if z, no, go check for VGA mov eax, VD_COMPAQ_AVGA jmp VideoDone ; ; Then we check the vga/svga which can be detected by int 10 func 1A. ; gvaCheckVga: MOV AX, 1A00h ; read display combination code INT 10h CMP AL, 1Ah ; function supported ? JNZ gvaUnknown ; No, then set it to unknown ; ; BL contains active display code. I have however, seen that on some vga ; cards this call will return the active display in BH. For this reason I ; am checking BL for zero, if I find that BL is zero ; I will place BH into BL and assume that the only display attached to the ; system is the active display. ; or bl,bl ; Do we have an active display ? jnz Normal_combo_code ; Yes, then continue on normaly. mov bl,bh ; No, then move bh to bl. or bl,bl jz gvaUnknown ; if fail, we don't know the card Normal_combo_code: mov eax, VD_COLOR ; Assume it is VGA color CMP BL, 08h ; VGA color ? je gvaVgaCheck mov eax, VD_MONO ; Assume it is VGA mono CMP BL, 07h ; VGA mono? JNE gvaUnknown ; if nz, it's a code which we don't support gvaVgaCheck: mov ebx, eax ; [ebx] = video type call GetVgaChipSet or eax, ebx ; combine vga type and subtype jmp VideoDone gvaUnknown: mov eax, VD_UNKNOWN ; set return type to unknown VideoDone: mov edx, eax shr edx, 16 ; return (dx:ax) pop ebx ret _GetVideoAdapterType endp ;++ ; ; ULONG ; GetVgaChipSet ( ; VOID ; ) ; ; Routine Description: ; ; This function tries to determine the chip set used in the VGA card. ; Currently the followings are detectable: ; ; 8514 ; GENOA VGA ; VIDEO 7 VRAM/DRAM VGA ; Trident TVGA ; Paradise VGA ; ATI VGA ; Tseng Lab VGA ; Cirrus Logic VGA ; dell dgx ; ; N.B. This function can ONLY be called when we already know the video ; type is VGA. ; ; Arguments: ; ; None. ; ; Return Value: ; ; (eax) = Video SubType. ; ;-- public GetVgaChipSet GetVgaChipSet proc near push bp push bx push si push di push es ; ; First check if it is 8514. ; xor eax, eax ; clear eax call Is8514Adapter ; Is it 8514? or ax, ax jz gvc10 ; if z, no, go check for other chip sets add eax, VD_8514 jmp VRI_Exit gvc10: mov ax, 1130h mov bh, 2 int 10h ; es:bp -> ROM font, so use es as ROM segment ; ; VGA real mode adapter detection ; Note that individual adapter detection routines must either ; jump to VRI_Exit with EDX = VT_Flags value or preserve ; the ES and DX register. ES is the adapter ROM segment (usually C000h) ; and DX is the status register port address (for resetting the ; attribute controller index/value toggle). ; ; Load status port value in DX ; This is to prevent duplication in OEM specific detection ; mov dx,pMiscIn in al,dx test al,1 mov dl,(pStatColr AND 0FFh) jnz SHORT gvc20 mov dl,(pStatMono AND 0FFh) gvc20: ; ; ======================= VGA REAL mode adapter detection code =============== ; ============================================================================ ; ; The code here is usually supplied by video adapter OEMs. ; Note that individual adapter detection routines must either ; jump to VRI_Exit with EAX = VIDEO_SUBTYPE_XXXX or preserve ; the ES and DX register. ES is the adapter ROM segment (usually C000h) ; and DX is the status register port address (for resetting the ; attribute controller index/value toggle). ; ; Entry: ; At this point: ; [es] = Adapter ROM segment ; [dx] = status register port addr ; ; Exit: [eax] = Video subtype ; ; ============================================================================ ; ============================================================================ ; ; **************************** ; * * ; * Genoa SuperVGA detection * ; * * ; **************************** ; mov bx,WORD PTR ES:[0037h] ; ; If there is no ROM at this address, then we need to validate that BX is ; something reasonable, because some pmode guys do not emulate segment ; wrap correctly. ; cmp bx, 0FFFCh ja SHORT Not_GENVGA mov eax,ES:[bx] cmp eax,66991177h je SHORT Is_GENVGA cmp eax,66992277h jnz SHORT Not_GENVGA ; ; It is a GENOA VGA ; Is_GENVGA: mov eax,VD_GENOA_VGA ; GENOA SuperVGA jmp VRI_Exit Not_GENVGA: ; ; ************************************ ; * * ; * NCR 77C22 chip detection * ; * * ; ************************************ ; ; NCR77C22 detection ; push dx ; ; save the current sequencer index register. ; mov dx, pSeqIndx ; (dx)=pSeqIndx in al, dx push ax ; (TOS)=content of Seq index ; ; set the sequencer index register to 0x05 which is lock register. ; save the data that we find there. ; mov al, 05 out dx, al inc dx ; (dx)=pSeqData in al, dx push ax ; (TOS)=context of LOCK reg ; ; Lock our extended registers ; mov al, 0 out dx, al ; (dx)=pSeqData ; ; Check an extended register to see if it responds ; mov al, 25h dec dx ; (dx)=pSeqIndx out dx, al inc dx in al, dx ; (dx)=pSeqData push ax ; ; (TOS)= test register content ; (TOS+2) = Lock reg content ; (TOS+4) = Sequencer index reg content ; mov al, 0AAh ; detected bit pattern out dx, al xor ecx, ecx ; assume not NCR77C2x in al, dx cmp al, 0AAh je short NcrRestore ; ; The register didn't respond...maybe the lock is working ; Unlock the registers and see if the extended register responds now.. ; mov al, 5 dec dx ; (dx)=pSeqIndx out dx, al mov al, 1 ; unlock it inc dx ; (dx)=pSeqData out dx, al ; ; Try the lock again. This time we unlock it. ; mov al, 25h dec dx ; (dx)=pSeqIndx out dx, al mov al, 0AAh inc dx ; (dx)=pSeqData out dx, al ; ; Check if the unlock works ; xor ecx, ecx ; assume not NCR IO_Delay in al, dx cmp al, 0AAh jne short NcrRestore ; ; The register responded now that we unlocked it. ; Since our lock register worked, assume an NCR 77C22 style system ; mov al, 8 ; index of version id in SEQ dec dx ; (dx)=pSeqIndx out dx, al inc dx ; (dx)=pSeqData in al, dx mov ecx, VD_NCR_77C22 ; ; Determine what kind of 77C2x ; and al, 0f0h shr al, 4 cmp al, 0 je short NcrRestore cmp al, 1 je short @f cmp al, 2 jne short NcrRestore @@: add ecx, VF_NCR_77C22E NcrRestore: mov al, 25h mov dx, pSeqIndx out dx, al inc dx ; (dx)= pSeqData pop ax ; (al) = test reg content out dx, al ; restore test reg mov al, 5 dec dx ; (dx)=pSeqIndx out dx, al inc dx ; (dx)=pSeqData pop ax ; (al) = Lock reg content out dx, al ; restore lock reg dec dx pop ax ; (al)= Index reg content out dx, al or ecx, ecx jz short @f mov eax, ecx pop dx jmp VRI_Exit @@: pop dx ; ; ************************************ ; * * ; * DELL DGX video chip detection * ; * * ; ************************************ ; ; DELL_DGX detection ; push dx mov dx,6c80h in ax,dx cmp ax,0ac10h jne short NotDgx add dx,2 in ax,dx cmp ax,1140h je short IsDgx cmp ax,0160h jne NotDgx IsDgx: pop dx mov eax,VD_DELL_DGX jmp VRI_Exit NotDgx: pop dx ; ; ****************************** ; * * ; * Video 7 SuperVGA detection * ; * * ; ****************************** ; push dx xor bx,bx ; clear it out mov ax,6f00h int 10h cmp bx,'V7' ; any of the products? jnz SHORT VRI_NotV7 ; nope... ; ; check the chip version # ; mov cx,0ffffh mov ax,06f07h ; get the # from the bios int 10h xor dx,dx ; Assume no flags passed in or cx,cx ; zero? jne SHORT VRI_NotV7 and bl,0f0h cmp bl,70h ; V7VGA chip? je SHORT @f ; Yes, this is VRAM 1 push ds ; Get V7VGA id from c000:86 mov cx, VIDEO_SEG mov ds, cx mov bx, V7_ID_OFFSET mov cx, [bx] pop ds cmp cx, VRAM2_ROM_ID_1 je short @f cmp cx, VRAM2_ROM_ID_2 je short @f cmp cx, VRAM2ERGO_ROM_ID je short @f pop dx mov eax, VD_VIDEO7_VGA jmp VRI_Exit @@: add sp,2 ; Throw away DX on stack mov cl, ah mov eax,VD_VIDEO7_VGA + VF_V7_DRAM ; assume it's video 7 VRAM test cl, 80h ; is it VRAM? je VRI_Exit mov eax,VD_VIDEO7_VGA + VF_V7_VRAM ; eax = Video 7 DRAM jmp VRI_Exit VRI_NotV7: pop dx ; ; ****************************** ; * * ; * Trident TVGA detection * ; * * ; ****************************** ; ; ; Try to find "TRIDENT MICROSYSTEMS" from ROM BIOS. ; Search C000h. If not found, try E000h, some motherboard makers ; put our BIOS there. ; - Trident, Henry Zeng ; lea si, TVGA_Sig xor di, di mov cx, 128 SearchTrident: push si push di push cx mov cx, TVGA_Sig_Len repe cmpsb ; ? Trident pop cx pop di pop si jz short IsTVGA ; Gotcha! inc di loop SearchTrident jmp short NotTVGA public IsTVGA IsTVGA: mov edx, VD_TRIDENT_VGA ; Trident TVGA ; ; Check if TVGA9100 ; push dx ; ? version # (3C5.B) == 93h mov dx, 03C4h mov al, 0Bh out dx, al inc dx in al, dx pop dx cmp al, 93h jnz short Not9100 or edx, VF_TVGA_9100 ; Is TVGA9100 Not9100: mov eax, edx jmp VRI_Exit NotTVGA: ; The other guy ; ; ****************************** ; * * ; * Westerm Digital detection * ; * * ; ****************************** ; push dx push bx ; ; Write 3ce.0c ; mov al, 0Ch mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData in al, dx push ax ; (TOS)= SaveGrph0C and al, 0bfh out dx, al ; ; write 3ce.0f ; mov al, 0Fh mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData in al, dx push ax ; (TOS)= SaveGrph0F mov al, 0 out dx, al ; ; write 3ce.09 ; mov al, 09h mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData in al, dx mov ah, al ; (ah)= temp1 inc al out dx, al ; write (temp1+1) IO_Delay xor ecx, ecx ; Assume not WD in al, dx ; Read it back mov bl, al ; (bl)= temp2 mov al, ah ; restore the old value out dx, al inc al cmp al, bl ; Is (temp1+1)== temp2? je WdRestore ; if yes, not Wd mov ax, 050Fh mov dx, pGrpIndx out dx, ax mov ax, 09h mov dx, pGrpIndx out dx, ax inc dx ; (dx)= grpData in al, dx mov ah, al ; (ah)=temp1 inc al out dx, al ; write (temp1+1) IO_Delay in al, dx ; read it back mov bl, al ; (bl) = temp 2 mov al, ah ; restore old value out dx, al inc al ; Is (temp1+1) == temp2 cmp al, bl jne WdRestore ; if no, not WD ; ; it *is* a WDVGA! ; ; ; Look for extended regsiters that are only in WD90C31 and over ; mov ecx, VD_WD_90C + VF_WD_31 ; Assume we have 90C31 mov dx, WD_EXT_IO_PORT in al, dx mov bl, al ; save it mov al, 2 out dx, al IO_Delay in al, dx cmp al, 2 je @f ; ; WD90C30 or older. ; mov ecx, VD_WD_90C + VF_WD_30 @@: mov al, bl ; restore ext io port value out dx, al ; ; Get chip type to determine if we have a 90c30 or 90c00 ; cmp ecx, VD_WD_90C + VF_WD_30 ; Is 90C30? jne WdRestore ; No, do nothing mov al, 06 mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData in al, dx push ax ; save reg 06 content mov al, 48h out dx, al mov al, 08 mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData in al, dx push ax ; Save reg 08 content mov al, 5Ah out dx, al IO_Delay in al, dx cmp al, 5Ah je short @f ; ; old chip, can't support 1R1W banking ; mov ecx, VD_WD_90C + VF_WD_00 @@: mov al, 08 mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData pop ax out dx, al ; Restore REg 08 mov al, 06 mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData pop ax out dx, al ; Restore reg 06 ; ; Restore registers to what they were. ; WdRestore: mov al, 0Ch mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData pop bx ; (bl)= saved Grp0F pop ax ; (al)= saved Crp0C out dx, al mov al, 0Fh mov dx, pGrpIndx out dx, al inc dx ; (dx)= grpData mov al, bl ; (al)= saved Grp0C out dx, al or ecx, ecx jz short @f mov eax, ecx pop bx pop dx jmp VRI_Exit @@: pop bx pop dx if 0 ; ; ****************************** ; * * ; * Paradise VGA detection * ; * * ; ****************************** ; ; -------------------------------------------------------------------- ; ; [1] ; Paradise 1C has 5 DIP switches, not 4 any more. The 5th switch ; controls if interlace or non-interlace is used. Register 3CE.0F ; bit 0-2 used for lock/unlock PR0-PR4, bit 3-7 used to return ; DIP switch information. This affects flag fvid_pvga used for other ; modules if paradise is selected. - C. Chiang - ; ; -------------------------------------------------------------------- ; push dx mov dl,(pGrpIndx AND 0FFh) mov al,0Fh out dx,al inc dx in al,dx push ax and al,0F8h mov ah,al xor al,0F8h ; Reverse upper 5 bits or al,5 out dx,al IO_Delay in al,dx xor al,ah ; Q: Are lower bits 5 and cmp al,5 ; upper bits unchanged? pop ax out dx,al ; Restore original value jnz NotPVGA ; N: Must not be PVGA ; ; It's Paradise VGA, check for Paradise VGA ROM ; mov si,OFFSET str_Paradise xor di,di mov cx,128 mov edx,VD_PARADISE_VGA ; Assume not Paradise ROM PVGA_FindROMLoop: push di push si push cx mov cx,len_str_Paradise repe cmpsb ; Q: Paradise ROM? pop cx pop si pop di jz SHORT IsPVGARom ; Yes inc di loop PVGA_FindROMLoop ; No, look thru 128 bytes ; ; PARADISE not found, now look for WESTERN DIGITAL ; mov si,OFFSET str_WDIGITAL xor di,di mov cx,128 PVGA_FindROMLoop1: push di push si push cx mov cx,len_str_WDigital repe cmpsb ; Q: Paradise ROM? pop cx pop si pop di jz SHORT IsPVGARom ; Yes inc di loop PVGA_FindROMLoop1 ; No, look thru 128 bytes ; ;-------------------------------------------------------------------- ; ; [3] It is Paradise Chip, but not Paradise BIOS ROM. In this case, ; set the flag to fVid_PVGA in order for OEMs who use their own ; BIOS and our Chip to work properly. - Chiang - ; ;--------------------------------------------------------------- ; mov edx,VD_PARADISE_VGA ; no Paradise ROM jmp SHORT Chk_1F IsPVGARom: or edx, VF_PVGA_PROM ; with Paradise ROM ; ;--------------------------------------------------------------------- ; ; [2] following are for Paradise chip type checking - C. Chiang - ; ;--------------------------------------------------------------------- ; Chk_1F: push es ; ; SAVE 3CE.0F ; mov dx, 3CEh mov al, 0Fh out dx, al inc dx in al,dx ; Read 3CF.F mov bSave0F, al ; Save the lock register state ; ; get 3D4 or 3b4 ; xor ax, ax mov es, ax mov dx, es:463h ; Fetch the register address to use mov ax, ds ; DS = ES mov es, ax mov cx, len_str_1F lea di, String ; Get the String ptr mov bx, 31h ; ;--- For 1F we need to unlock\lock the regs: ;--- 3?4.29 - Unlock PR11-PR17 ; ; mov al, 29h ; Select PR10 ; out dx, al ; inc dx ; in al, dx ; Read the contents ; mov bSave29, al ; and save it ; mov al, 80h ; Unlock the date code register ; out dx, al ; dec dx ; ; ;--- 3?4.34 - Lock Flat Panel ; mov al, 34h ; Select PR1B out dx, al inc dx in al, dx ; Read the contents mov bSave34, al ; and save it mov al, 0 ; Lock the flat panel out dx, al dec dx ; ;--- 3?4.35 - Lock Mapping Ram ; mov al, 35h ; Select PR30 out dx, al inc dx in al, dx ; Read the contents mov bSave35, al ; and save it mov al, 0 ; Lock the mapping ram out dx, al dec dx loopit: mov al, bl ; Loop to read the chip ID out dx, al inc dx in al, dx stosb dec dx inc bx loop loopit ; ;--- For 1F we need to restore the regs ; ; ;--- 3?4.35 - Lock Mapping Ram ; mov al, 35h ; Select PR30 out dx, al mov al, bSave35 ; and restore it cmp al, 30h ; If wasn't unlocked jne SHORT skip1 ; then leave alone inc dx out dx, al dec dx skip1: ; ;--- 3?4.34 - Lock Flat Panel ; mov al, 34h ; Select PR1B out dx, al mov al, bSave34 ; and restore it cmp al, 0A6h ; If wasn't unlocked jne SHORT skip2 ; then leave alone inc dx out dx, al dec dx skip2: ; ;--- IT TURNS OUT THAT THE BIOS NEVER LOCKS THESE ;--- 3?4.29 - Unlock\lock PR11-PR17 ; mov al, 29h ; Select PR10 ; out dx, al ; inc dx ; mov al, bSave29 ; and restore it ; out dx, al ; dec dx ; ;--- Restore the state of the lock/unlock register: 3CF.F ; exit_pgm: mov dx, 3CEh mov al, 0Fh out dx, al inc dx mov al, bSave0F ; Restore lock/unlock status out dx, al ; ;--- Now, the chip signature is in String ; mov si, OFFSET str_PVGA1F ; check string "OPYRIGHT1990WDC" mov di, OFFSET String mov cx, len_str_1F repe cmpsb ; Q: jz SHORT isPVGA1F mov si, OFFSET str_PVGA1FC ; check string "OPYRIGHTWD90C22" mov di, OFFSET String mov cx, len_str_1FC repe cmpsb ; Q: jz SHORT isPVGA1F mov si, OFFSET str_1F_GEN ; check string "OPYRIGHTWD90C22" mov di, OFFSET String mov cx, len_str_GEN repe cmpsb ; Q: jnz SHORT Exit_1F_check isPVGA1F: or edx, VF_PVGA_CHIP_1F ; set flag for Paradise 1F chip Exit_1F_check: pop es ; ;---------------------------------------------- ; end of Paradise 1F chip checking ;---------------------------------------------- ; add sp,2 ; discard saved DX mov eax, edx jmp VRI_Exit NotPVGA: pop dx endif ; ; ****************************** ; * * ; * ATI VGA detection * ; * * ; ****************************** ; push dx push bp mov ax,1203h mov bx,5506h mov bp,0ffffh int 10h cmp bp,0ffffh pop bp je short Not_ATI_VGA mov si,OFFSET ATI_Sig mov di,30h mov cx, ATI_Sig_Len rep cmpsb jnz SHORT Not_ATI_VGA ; ; Further checks for version of ATI VGA ; add sp, 2 mov edx, VD_ATI_VGA cmp es:byte ptr [40h],'3' ;VGAWONDER product code ? jne SHORT Ati_Vga ; mov edx,VD_ATI_VGA ; cmp es:byte ptr [43h],'1' ;VGAWONDDER V3 ? ; jne short Ati_Vga or edx,VF_ATIVGA_WONDDER3 Ati_Vga: mov eax, edx jmp VRI_Exit Not_ATI_VGA: pop dx ; ; ************************************ ; * * ; * Tseng Lab VGA detection * ; * * ; ************************************ ; ; Tseng Labs VGA detection ; Attribute Controller Reg 16h is known to exist only on Tseng Labs VGA ; push dx mov bl,0 ;ET3000/ET4000 flag (0=ET3000) mov dx, 3BFh xor al, al out dx, al pop dx push dx sub dl, pStatColr-03D8h ; mode control register is 3B8 or 3D8 in al, dx test al, 01000000b ;Q: writing 0 to 3BF cleared bit 6 of ; mode control port? jnz SHORT tlvga_2 ; N: not ET4000 mov dx, 3BFh mov al, 10b out dx, al pop dx push dx sub dl, pStatColr-03D8h ; mode control register is 3B8 or 3D8 IO_Delay in al, dx test al, 01000000b ;Q: writing 10b to 3BF set bit 6 of ; mode control port? jz SHORT tlvga_2 ; N: not ET4000 ; Y: possibly an ET4000 mov bl,1 ;flag ET4000 not ET3000 ; ; attempt to write ET4000 "KEY" ; mov dx, 3BFh mov al, 3 out dx, al pop dx push dx sub dl, pStatColr-03D8h ; mode control register is 3B8 or 3D8 in al, dx mov ah, al IO_Delay mov al, 0A0h out dx, al tlvga_2: pop dx push dx push ax push bx call Check_Writing_ATC16 ;sets ECX=0 or VT_Flags for ET3000 pop bx pop ax sub dl, pStatColr-03D8h ; mode control register is 3B8 or 3D8 mov al, ah out dx, al ; restore mode control register mov dx,03BFh mov al,1 out dx,al ;restore 3BF to normal value or ecx,ecx jz SHORT Not_TLVGA ; jump if not ET3000/ET4000 pop dx mov edx,VD_TSENGLAB_VGA + VF_TLVGA_ET3000 ;if ET4000 with 256k or bl,bl ;test if ET4000 jz short tlvga_4 ; ;is an ET4000: ; mov edx,VD_TSENGLAB_VGA + VF_TLVGA_ET4000 ;if ET4000 with 256k tlvga_4: mov eax,edx jmp VRI_Exit Not_TLVGA: pop dx ; ; ************************************ ; * * ; * Cirrus VGA detection * ; * * ; ************************************ ; ; Cirrus Logic VGA detection ; ; ; First save SR6 and SRIndx ; push dx xor cx,cx ; assume not CLVGA mov dl,(pSeqIndx AND 0FFh) in al,dx IO_Delay mov bh,al ; BH = SR index mov al,6 out dx,al IO_Delay inc dx in al,dx IO_Delay mov bl,al ; BH=SRindx,BL=SR6 value ; ;enable extension register in the CLVGA ; mov ecx,VD_CIRRUS_VGA ; ECX = potential VT_Flags mov al,0ECh ; extension enable value out dx,al IO_Delay in al,dx IO_Delay cmp al,1 ; Q: Could enable Ext? jnz SHORT Check542x ; ; now check to see if we can disable the extensions ; mov al,0CEh ; extension disable value out dx,al IO_Delay in al,dx IO_Delay and al,al ; Q: extensions disabled successfully? jz short @f ; Y: it is 610/620 ; Y: its Cirrus logic Check542x: mov al, 12h ; Unlock ext regs with 12h out dx, al IO_Delay in al, dx IO_Delay cmp al, 12h ; Could enable ext? jnz Not_CLVGA ; No, not CL VGA mov al, 0 out dx, al IO_Delay in al, dx IO_Delay cmp al, 0fh jnz Not_CLVGA @@: ; ; we know its a Cirrus chipset, now find out if it is a 610/620 Rev. C. ; chipset. ; push ecx ; save flag value push dx mov ah,12h mov bl,80h int 10h ; Inquire VGA type cmp al,3 ; returns 3 for 610/620 LCD controller jnz short Is542x ; otherwise check for 542x ; ; its a 610/620, now find out if its RevC or not. ; cmp bl,80h jz short CheckChip cmp bl,2 jnz short Not610 IsRevC: mov eax,VF_CLVGA_REVC jmp short Done610 CheckChip: mov dx,3c4h mov al,8eh out dx,al inc dx in al,dx ; 8Eh is chip revision. cmp al,0ach jz IsRevC Not610: xor eax,eax Done610: pop dx pop ecx or ecx,eax jmp short Restor_CLVGA ; all done, now get outa here Is542x: cmp ax, 12h ; check 5420r0 jne short @f ; Check next chip version mov eax, VF_CLVGA_5420r0 ; We found a 5420r0 jmp short Done610 @@: cmp ax, 16h ; check 5420r1 jne short @f ; Check next chip version mov eax, VF_CLVGA_5420r1 ; We found a 5420r1 jmp short Done610 @@: cmp ax, 18h ; check 5428 jne short @f ; we did not find any of compaq rev. mov eax, VF_CLVGA_5428 ; We found a 5428 jmp short Done610 @@: cmp ax, 12h jb short Not610 mov eax, VF_CLVGA_542x ; if (ax) >= 12h, it's 542x jmp short Done610 Not_CLVGA: xor ecx,ecx ; Indicate not CL VGA Restor_CLVGA: dec dx mov al,6 out dx,al IO_Delay mov al,bl ; old value of SR6 or ecx,ecx ; Q: CL VGA? jz SHORT Restor_SR6 ; N: output value read mov bl,0ECh Restor_Ena: or al,al ; Q: extensions enabled? mov al,bl ; AL = 0ECh (enable) jnz SHORT Restor_SR6 ; Y: output enable value ror al,4 ; N: output disable (0CEh) Restor_SR6: inc dx out dx,al ; Restore value of SR6 IO_Delay mov al,bh dec dx out dx,al ; Restore index IO_Delay or ecx,ecx jz SHORT Is_Not_CLVGA add sp,2 mov eax,ecx jmp VRI_Exit Is_Not_CLVGA: pop dx ; ; ************************************ ; * * ; * S3 video chip detection * ; * * ; ************************************ ; ; S3 detection ; mov ax, dx push dx ; save dx push bx and ax, 0fff0h or ax, 4h ; (ax) = Crt index mov dx, ax inc dx in al, dx mov ah, al dec dx in al, dx ; (ah) = original data reg ; (al) = oroginal addr reg push ax ; Save it mov al, 38h out dx, al inc dx in al, dx IO_Delay mov ah, al ; (ah) = original data on index 38 mov al, 39h dec dx out dx, al IO_Delay inc dx in al, dx ; (al) = original data on index 39 push ax ; save them dec dx ; ; Before unlocking all the S3 registers, lets try read the id reg ; if 0 mov ax, 038h ; lock S3 registers out dx, ax IO_Delay dec dx mov ax, 039h out dx, ax IO_Delay dec dx mov al, 30h ; crt controller index for s3 ID reg out dx, al IO_Delay inc dx in al, dx ; get (potential) Id mov bl, al ; (bl) = ID reg content before unlocked dec dx endif ; ; Now Unlock all the S3 registers ; mov ax, 4838h out dx, ax IO_Delay dec dx mov ax, 0A039h out dx, ax IO_Delay dec dx ; ; Read ID after we unlocked S3 registers ; mov al, 30h ; crt controller index for s3 ID reg out dx, al IO_Delay inc dx in al, dx ; get (potential) Id dec dx if 0 cmp bl, al ; compare ids mov ebx, 0 ; Assume it is NOT S3 je short ExitS3Detection else mov ebx, 0 endif ; ; Check if id is 8?. 9? or A? If yes, it is S3. ; and al, 0f0h cmp al, 80h ; Is Id = 8?h? jz short IsS3 ; if e, it's s3 cmp al, 90h ; Is Id = 9?h? jz short IsS3 ; if e, it's s3 cmp al, 0A0h ; Is Id = A?h? jnz short ExitS3Detection ; if nz, not s3 IsS3: mov ebx, VD_S3 ExitS3Detection: pop ax mov cx, ax mov ah, al mov al, 39h out dx, ax ; Restore reg 39 data IO_Delay dec dx mov ax, cx mov al, 38h out dx, ax ; Restore reg 38 data IO_Delay dec dx pop ax ; (ax) = crt data and index out dx, ax IO_Delay mov eax, ebx ; (eax) = VGA id pop bx pop dx cmp eax, VD_S3 je VRI_Exit ; ; ==================== End of VGA H/W detection =================== ; ; ; If we come here, the detection fails. ; mov eax, VD_VGA ; Set it to standard VGA ; ; eax = Video subtype ; VRI_Exit: ; ; before exit do setmode to init video ; push eax mov ah, 0fh int 10h ; (al) = current display mode mov ah, 0 int 10h ; set to current mode pop eax pop es pop di pop si pop bx pop bp ret GetVgaChipSet endp ;++ ; ; ULONG ; Check_Writing_ACT16 ( ; VOID ; ) ; ; Routine Description: ; ; This routine is part of Tseng Lab VGA detection code. ; In this routine, we try to access Attribute Controller reg 16h. It is ; known to exist only on Tseng Lab's VGA. ; ; Arguments: ; ; None. ; ; Return Value: ; ; (ecx) = 0, if NOT Tseng Lab VGA ; ;-- Check_Writing_ATC16 proc near push dx in al,dx IO_Delay mov dl,(pAttr AND 0FFh) in al,dx mov bh,al ; BH = current Attr index IO_Delay mov al,16h+20h ; Select 16h (leave video on) out dx,al IO_Delay inc dx in al,dx IO_Delay dec dx mov bl,al ; Save current reg 16h in BL xor al,10h ; Complement bit 4 out dx,al ; Write it out IO_Delay pop dx push dx in al,dx mov dl,(pAttr AND 0FFh) mov al,16h+20h ; Select 16h (leave video on) out dx,al IO_Delay inc dx in al,dx IO_Delay xor ecx,ecx ; CX = flag (not TLVGA) dec dx xor al,10h cmp al,bl ; Q: Is value same as written? jnz SHORT Restore16 ; N: Is not TLVGA mov ecx,VD_TSENGLAB_VGA ; Y: Is TLVGA Restore16: mov al,bl out dx,al IO_Delay pop dx push dx in al,dx IO_Delay mov dl,(pAttr AND 0FFh) mov al,bh out dx,al pop dx ret Check_Writing_ATC16 endp if 0 ; *** Removed ;++ ; ; BOOLEAN ; IsCompaqAgb ( ; VOID ; ) ; ; Routine Description: ; ; Function determines if the video system is a Compaq Advanced Graphics ; Board operating if pass through configuration in conjunction with a ; VGA card. ; ; Arguments: ; ; None. ; ; Return Value: ; ; Function will return TRUE or FALSE as to whether or not the Compaq AGB ; is present and operating in pass-through mode. ; ;-- ; public IsCompaqAgb ;IsCompaqAgb proc near ; ; mov dx,298h ; Port address for host CPU status reg. ; in al,dx ; Read register. ; mov cl,al ; Save value from reg. ; and al,00000011b ; Strip all but bit 0 and 1. ; or al,al ; Bits 0 and 1 should be 0. ; jnz no_CompaqAGB ; mov dx,299h ; Ok, next look at host CPU status 2 reg. ; in al,dx ; and al,00000001b ; Strip all but bit 0. ; or al,al ; jnz no_CompaqAGB ; bit zero should be 0. ; mov dx,298h ; in al,dx ; cmp al,cl ; One final check. ; jne no_CompaqAGB ; mov ax, TRUE ; jmp short AGB_done ; ;no_CompaqAGB: ; mov ax, FALSE ; return FALSE ;AGB_done: ; ret ; ;IsCompaqAgb endp ; endif ; *** Removed ;++ ; ; BOOLEAN ; Is8514Adapter ( ; VOID ; ) ; ; Routine Description: ; ; 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. Next I read in the value of ; the subsystem status register and check bit 7 to determine if the 8 plane ; memory configuration is present. Only if both these conditions are ; satisfied will we acknowledge that 8524 display driver is present. ; ; Arguments: ; ; None. ; ; Return Value: ; ; Function will return TRUE or FALSE as to whether or not the 8514 ; display card is present and contains the proper memory configuration. ; ;-- public Is8514Adapter Is8514Adapter proc near mov dx, ERR_TERM ; load DX with port address (error term port). mov ax, 5555h ; load AX with value to write to port. out dx, ax ; Write the data. IO_Delay IO_Delay in ax, dx ; Now read the data back in. cmp ax, 5555h ; Q: is 8524 present ? jne Not_8514 ; 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 6,5,4 of the subsystem ; status register. Depending on the Monitor attached we return: ; ; There are 4 valid monitor types: ; ; bits 6-4 Type ; ; 001 Ascot (mono) ; 010 Henley (color) ; 011 Invalid (color) This is supposedly valid in spite ; of what the spec says. ; 101 Surrey (mono) ; 110 Conestoga/Crown (color) ; mov dx,SUBSYS_STAT ; Now, we have the adapter. Check monitor. in ax,dx ; Get word from SUBSYS_STAT and ax,0070h ; Mask out bits 6-4 cmp ax,0020h ; Is it Henley type? je Disp_8514 ; Yes, then it is an 8514 type cmp ax,0060h ; Is it Conestoga/Crowwn type? je Disp_8514 ; Yes, then it is an 8514 type cmp ax,0030h ; Is it Korys' machine je Disp_8514 ; Yes, then it is an 8514 type cmp ax,0010h ; Is it Ascot type? je Disp_8503 ; Yes, then it is a VGA Mono type cmp ax,0050h ; Is it Surrey type? je Disp_8503 ; Yes, then it is a VGA Mono type mov ax,VF_MONITOR_VGA ; If none of the above, then it jmp short fn8514Done ; is just a standard VGA Disp_8503: mov ax,VF_MONITOR_MONO_8503 jmp short fn8514Done Disp_8514: mov ax,VF_MONITOR_GAD_8514 jmp short fn8514Done Not_8514: mov ax,FALSE fn8514Done: ret Is8514Adapter endp ;++ ; ; BOOLEAN ; IsCompaqVideo ( ; VOID ; ) ; ; Routine Description: ; ; This function searches ROM BIOS C0000 and E0000 for 'COMPAQ' to ; determine the presence of COMPAQ video ROM. ; ; Arguments: ; ; None. ; ; Return Value: ; ; (ax) = TRUE if it is compaq video rom. Otherwise, a value of FALSE is ; returned. ; ;-- public IsCompaqVideo IsCompaqVideo proc near push di push es mov ax, 0C000h ; Video ROM is C000:0000 to 8000h icvBeginSearch: mov es, ax mov di, 0000h mov al, 'C' ; Look for 'C' mov cx, 7FFCh ; search through 32K cld icvLoopAgain: repne scasb ; search for 'C' jne icvNotFound ; if searched entire video ROM, exit mov edx, dword ptr es:[di] cmp edx, 'APMO' ; search for 'OMPA' jne short icvLoopAgain ; fail, continue search mov dl, byte ptr es:[di+4] cmp dl, 'Q' jne short icvLoopAgain ; ; If we get to here we have found COMPAQ in the video ROM. ; mov ax, 1 jmp short icvExit icvNotFound: push es pop ax cmp ax, 0E000h je short @f mov ax, 0E000h jmp short icvBeginSearch @@: xor ax, ax ; NO, return FALSE (AX = 0) icvExit: pop es ; restore registers pop di ret IsCompaqVideo endp ; BOOLEAN ; IsCompaqQVision ( ; VOID ; ) ; ; Routine Description: ; ; Function determinec if the video system is a Compaq QVision board. ; ; Arguments: ; ; None. ; ; Return Value: ; ; Function will return TRUE or FALSE as to whether or not the Compaq QVision ; is present. ; ;-- public IsCompaqQvision IsCompaqQVision proc near push si push di push es mov ax, 0BF11h ; Get Extended Environment int 10h cmp al, 0BFh ; is the call supported ? jne QVision_not_found ; no, this is not a QVision card mov eax, DWORD PTR ES:[SI] ; get pointer to extended env DWORD and al, 80h ; are QVision modes supported ? jz QVision_not_found ; no, this is not a QVision card mov eax, 01h ; yes jmp short QVision_exit QVision_not_found: xor ax, ax ; NO, return FALSE (AX = 0) QVision_exit: pop es ; restore registers pop di pop si ret IsCompaqQVision endp ;++ ; ; BOOLEAN ; IsCompaqAvga ( ; VOID ; ) ; ; Routine Description: ; ; This function returns whether a COMPAQ AVGA display adapter is found. ; ; This is determined by: 1. Looking for COMPAQ Video ROM ; 2. Doing COMPAQ int 10h call ; ; The presence of COMPAQ video ROM can be determined by searching through ; the Video ROM (C000:0000 to C000:FFFF) for the string 'COMPAQ'. ; ; Arguments: ; ; None. ; ; Return Value: ; ; (ax) = TRUE if it is compaq AVGA. Otherwise, a value of FALSE is ; returned. ; ;-- public IsCompaqAvga IsCompaqAvga proc near push si ; Save registers push di push es mov ax, 0BF03h xor cx, cx int 10h and cl, 050h ; Are bits 4 (BitBlt Engine cmp cl, 050h ; and 6 (256 colors) both set jne avga_not_found mov eax, 01h ; YES, return TRUE (non-zero AX) jmp short avga_exit avga_not_found: xor ax, ax ; NO, return FALSE (AX = 0) avga_exit: pop es ; restore registers pop di pop si ret IsCompaqAvga endp ;++ ; ; BOOLEAN ; IsXga ( ; VOID ; ) ; ; Routine Description: ; ; This function returns whether a XGA display adapter is found. ; ; This is determined by: 1. Make sure this is a MicroChannel machine ; 2. Make sure Mother board VideoSubsystem Id is XGA ; ; N.B. Current assumption is that XGA is MicroChannel specific. ; ; Arguments: ; ; None. ; ; Return Value: ; ; (ax) = TRUE if it is IBM XGA. Otherwise, a value of FALSE is ; returned. ; ;-- IsXga proc near push es push bx call _HwIsMcaSystem ; First check if this is MCA machine or ax, ax ; If ax == 0, it is not. jz short Ix99 ; exit call Ps2SystemBoardVideoId ; (ax) = PS2 mother board video id cmp ax, IBM_XGA_ID_LOW ; Is it XGA id? jb short Ix50 ; if z, no, try something else. cmp ax, IBM_XGA_ID_HIGH jle short Ix99 Ix50: les bx, _HwMcaPosData mov cx, 0 Ix60: mov ax, es:[bx] cmp ax, IBM_XGA_ID_LOW ; Is it XGA id? jb short Ix70 ; if z, no, try next slot cmp ax, IBM_XGA_ID_HIGH jle short Ix99 Ix70: add bx, MCA_POS_DATA_SIZE inc cx cmp cx, 8 ; end of slot? jnz short Ix60 Ix90: mov ax, 0 Ix99: pop bx pop es ret IsXga endp endif ; Remove Video detection ;++ ; ; VOID ; GetVideoFontInformation ( ; VOID ; ) ; ; Routine Description: ; ; This function does int 10h, function 1130 to get font information and ; saves the pointers in the physical 700h addr. ; ; Arguments: ; ; None. ; ; Return Value: ; ; None. ; ;-- ASSUME DS:NOTHING public _GetVideoFontInformation _GetVideoFontInformation proc near push ds push es push bp push bx push si mov ax, FONT_POINTERS shr ax, 4 mov ds, ax mov si, FONT_POINTERS and si, 0fh mov bh, 2 @@: mov ax, 1130h ; Get font information int 10h mov [si], bp add si, 2 mov [si], es add si, 2 ; (si)= 8 inc bh cmp bh, 8 jb short @b pop si pop bx pop bp pop es pop ds ret _GetVideoFontInformation endp _TEXT ENDS END