Artikel
Ingo Eickmann
Ob Hercules, ob VGA...
Automatische Erkennung von Videoadaptern
Angesichts der vielen unterschiedlichen Grafikkarten für den PC müssen Programme die Videoausgabe des gerade benutzten Computers eindeutig erkennen, um die Fähigkeiten der jeweiligen Bildschirmdarstellung zu nutzen. Wir zeigen, wie ein Programm den Typ der Grafikkarte erkennt.
Anpassungsfähigkeit ist gefragt. Programme, die sich nicht an die Videoausstattung eines PCs anpassen, sind undenkbar geworden. Um alle Leistungsmerkmale der so unterschiedlich aufgebauten Grafikadapter zu nutzen, fließt nicht nur die maximale Auflösung und die Anzahl der darstellbaren Farben ein: Bei Grafikprogrammen sind schnelle Bildschirmtreiber, die je nach verwendeter Videokarte eingesetzt werden, ein Muß. Erkennt ein Programm ein System mit zwei Bildschirmausgaben, kann die Grafik- und die Textausgabe sogar auf getrennten Anzeigen unabhängig voneinander erfolgen.
Vielfalt an Grafikkarten
Wer als Käufer vor
einer schier unüberschaubaren Vielfalt unterschiedlichster
Grafikadapter-Monitor-Kombinationen steht, kann sich vorstellen, wie
schwer es die Software bei der Unterscheidung hat. Ein Programm sieht
schließlich weder die Farbenvielfalt, noch die Auflösung,
und trotzdem wird von ihm erwartet, daß es die richtigen
Steuerregister korrekt anspricht und die vorhandenen
Statusinformationen interpretieren kann.
Im PS/2-Zeitalter wird es für die Software leichter. Das
Video-BIOS ist unterhaltsamer geworden und gibt bereitwillig
Auskunft über das Videosystem. Doch auch die nach wie vor
weit verbreiteten EGA,
CGA,
MDA
und Hercules-Karten müssen unterschieden werden.
Die Fragen, die eine Identifizierungsroutine für Videoadapter
beantworten muß, lauten daher:
- Welche Videoadapter befinden sich im System?
- Welche Darstellungsmöglichkeiten können genutzt werden?
- Auf welchem Videoadapter erfolgt zur Zeit die Ausgabe?
Angesichts
der unterschiedlichen Grafikadapter kann sich eine allgemeingültige
Identifizierung nur auf die Merkmale der Adapterstandards stützen.
Die Vielzahl unterschiedlicher Super-EGAs und Super-VGAs und ihre
meist nicht detailliert publizierten Erweiterungen zwingen dazu, sie
lediglich in ihrer Funktion als
Standard-EGA
und Standard-VGA zu
behandeln. Bild 1
enthält das Flußdiagramm zu einer
Identifizierungsroutine. Prinzipiell wird von den bestausgestatteten
Adaptern ausgegangen. Erst dann gelangt man zu den Standards
CGA und
MDA,
mit denen die PC-Ära
begonnen hat. Zunächst wird die
Hardware auf VGA-typische Eigenschaften abgeklopft. Sind diese
Eigenschaften nicht vorhanden, handelt es sich nicht um eine VGA, und
der nächste Test erfolgt auf eine typische EGA-Eigenschaft.
Dabei ist zu beachten, daß EGA-Karten zum VGA-Standard
aufwärtskompatibel sind, die EGA-Register und
EGA-BIOS-Funktionen sind also als Untermenge im VGA-System enthalten.
Die VGA bezeichnet man aus diesem Grund auch als abwärtskompatibel
zur EGA.
So wie bei VGA und
EGA,
verhält es sich zwischen EGA
und CGA.
Die CGA ist zur EGA – und damit
auch zur VGA – aufwärtskompatibel.
- Bild 1. Flußdiagramm zu Listing 1: Suchstrategien im Überblick.
Strategie beim Suchen
Das
Erkennen des Videoadapters ist in PS/2-Geräten
und PCs mit
VGA-Karte kein Problem.
Das Video-BIOS enthält bei dieser
Hardwarevoraussetzung einen Funktionsaufruf, der die vorhandene
Ausrüstung als Display Combination Codes liefert. Wenn der
Softwareinterrupt 10h eines PS/2-kompatiblen Videosystems mit dem
Funktionscode AX=1A00h aufgerufen wird, enthalten nach der Rückkehr
das BH- und das BL-Register die Kombinations-Codes des primären
und – falls vorhanden –
sekundären Videoadapters. Diese Zuordnung erfolgt nach Bit 4 und
5 im Equipment Byte(0040:0010h) und bezieht sich daher auf den
Zustand beim Booten. Die Zusammenstellung in Tabelle 1 zeigt
alle vordefinierten Kombinations-Codes und die hiermit verbundenen
Video-BIOS-Funktionen. Ist diese PS/2-Funktion nicht im Video-BIOS
enthalten, besitzt der Computer weder einen VGA, noch einen
MCGA-Adapter.
Ist eine EGA-Karte vorhanden, enthält das Video-BIOS die
EGA-Funktion Video Subsystem Configuration (AH=12h).
Tabelle 2 faßt alle Register zusammen, die für den
Aufruf und die Auswertung wichtig sind. Anhand der im CL-Register
zurückgegebenen DIP-Switch-Stellungen auf der EGA-Karte
läßt sich sofort bestimmen, ob sie als EGA, CGA oder
monochromer Adapter konfiguriert wurde. Ist zum Beispiel die
Einstellung CGA-Mode gewählt, dann meldet unsere Routine
ein CGA-Display.
Wenn keine EGA-Karte gefunden wurde, dann sucht das Programm nach
einer CGA. CGA-Karten haben – im Unterschied zu
monochromen Adaptern – ihren
CRT-Controller 6845 an Port 3D4h/3D5h. Die Anwesenheit des
Controllers kann man feststellen, indem man versucht, eines seiner
Register über Port 3D4h anzuwählen und über 3D5h zu
beschreiben. Den neuen Inhalt liest man wieder aus und verifiziert,
ob an dieser Portadresse wirklich ein Register den geschriebenen Wert
gespeichert hatte. Nicht vergessen, daß der frühere
Registerinhalt gerettet und zum Schluß wiederhergestellt werden
muß.
Für diese Art der Überprüfung können jedoch nicht
alle Register verwendet werden. Bei den schon fast antiken CGA-Karten
sind lediglich die CRTC-Register
14 und 15 (Cursoradresse) sowohl lesbar,
als auch beschreibbar.
Wurde auch keine CGA im System erkannt, dann bleibt noch die Möglichkeit,
daß ein Monochromadapter vorhanden ist. Ihn kann man auf die
gleiche Weise entdecken wie einen Farbgrafikadapter, lediglich die
Portadresse des CRT-Controllers ist jetzt eine andere. Monochrome
Videoadapter besitzen ebenfalls einen 6845, seine Portadressen sind
3B4h und 3B5h.
Sind alle bisherigen Versuche fehlgeschlagen, einen Videoadapter zu erkennen,
dann besitzt der Computer entweder keinen, oder er unterscheidet sich ganz
wesentlich von den Standardtypen MDA bis VGA.
Zweit- und Monochromadapter
Mit
dem Erkennen einer Videokarte hat das Identifizierprogramm seine
Aufgaben aber noch lange nicht erfüllt. Als nächstes muß
untersucht werden, ob sich eine zweite Grafikkarte im System
befindet. Der PS/2-Funktionsaufruf
1Ah (Video Display Combination) liefert direkt alle installierten Videokarten.
Wurde bislang aber nur eine
EGA-,
CGA- oder
MDA-Karte
entdeckt, dann müssen wir selbst
nach einem eventuell vorhandenen zweiten Adapter suchen. Wenn die EGA
als Farbkarte konfiguriert wurde, muß ebenso wie bei einer
entdeckten CGA noch nach einer monochromen Karte gesucht werden. Wird
die EGA als Monochromadapter eingesetzt, dann kann sich noch eine CGA
im PC befinden.
Wann nach welchem Videoadapter gesucht
wird, ist anhand des Flußdiagramms ersichtlich. Ergab sich auf
diese Weise, daß zwei Videoadapter vorhanden sind (Label Active
im Flußdiagramm und
im Listing), dann bleibt noch die
Reihenfolge zu klären: Auf welchem Bildschirm erscheinen die
Standardausgaben des Betriebssystems und welcher Adapter dient
lediglich als Sekundärausgabe?
Hier hilft der Videostatus
durch den BIOS-Aufruf
INT 10h mit ah=0Fh weiter. Auf das
Monochromsystem wird nur dann ausgegeben, wenn entweder Videomode 7
(Text) oder 0Fh (Grafik) gewählt ist. In allen anderen Fällen
ist der Farbadapter die primäre Ausgabe.
Wenn ein Monochromadapter im System entdeckt wurde, dann muß sowohl
bei einem PS/2-Computer,
als auch bei einem PC geklärt werden,
ob es sich um einen normalen MD-Adapter handelt, oder um eine
Hercules-Grafikkarte.
Hierzu ist es sinnvoll, im
CRTC-Status-Register (3BAh) das Bit 7 abzufragen. Es enthält nur
bei einer Hercules-Karte das vertikale Synchronisationssignal. Bei
einer Bildfrequenz von 50 Hz ändert sich der Zustand dieses Bits
alle 20 ms für die Dauer des vertikalen Synchronisationspulses.
Bleibt diese Änderung aus, dann handelt es sich eindeutig nicht
um einen Hercules-Adapter, sondern um einen MDA.
Die Assemblerunterroutine identify
in Listing 1, die den
Code zum Flußdiagramm in Bild 1 enthält, liefert die
Display Combination Codes im AX-Register, AH enthält den Wert
für den primären Adapter und AL den Wert für einen
sekundären Adapter. Die Zusammenstellung der Kombinations-Codes
in Tabelle 1 wurde um den Wert 64 für die Hercules-Karte
ergänzt. Das Video-BIOS sah bisher keinen Code für das
Nicht-IBM-Produkt von Hercules vor.
Wie die Identifizierung weiterverarbeitet werden kann, zeigen die
Listings 2
und 3.
Wenn der Objectcode als Funktion eingebunden wird, kann Pascal
primäre und sekundäre Ausgabemöglichkeiten erkennen.
Hoch auf OS/2
Mit der Identifizierung des
Videosystems ist die Voraussetzung für die Entwicklung portabler
Grafiksoftware erfüllt. Jetzt kann eine genauere Untersuchung
des Adapters folgen. Bei EGA-kompatiblen Grafikkarten kann
beispielsweise die RAM-Ausstattung interessieren, ebenso wie der
Zustand der Feature Bits (Tabelle 2).
Die zusätzlich verfügbaren Informationen bei PS/2-Systemen
erschlagen einen geradezu. Erwähnt seien an dieser Stelle
lediglich die Video-BIOS-Funktionen
Video Display Combination
(AH=1Ah, Tabelle 1) und
Video BIOS Functionality/State Information
(AH=1Bh), die einen 64 Byte großen Dynamic Video State Table
und einen 16 Byte Static Functionality Table liefert. Genaueres
findet sich in weiterführender, spezieller Literatur.
Auf zwei Unzulänglichkeiten des PS/2-Interrupts beim Model 30 muß
der Vollständigkeit halber hingewiesen werden. Ist im Model 30
eine VGA installiert, dann wird der vorhandene MCGA-Adapter nicht
mehr erkannt. Abhilfe: Model 30 am BIOS-Identifikationsbyte
(FFFF:000Eh) erkennen und automatisch MCGA melden.
Ist dagegen zusätzlich eine EGA-Karte eingesteckt, dann wird nur der
MCGA-Adapter gemeldet. Wenn das Model 30 erkannt wurde, können
wir die EGA-Karte mit der EGA-BIOS-Funktion aus Tabelle 2 erkennen.
Wer selbst auf diese Fälle noch eingehen möchte, kann das
Flußdiagramm und den Code leicht ergänzen.
Erkennen von Monitoren
Ein
Glied in der Funktionskette Computer-Videoadapter-Monitor-Mensch
bleibt der Software aber unbekannt: Der Monitor. Er bestimmt
letztendlich, wie das Bild dem Menschen dargeboten wird.
Ginge es nach dem Willen von Big Blue, dann gäbe es seit der
Markteinführung der PS/2-Modelle nur noch Monitore (und
Monitorkabel), die dem VGA-System über die drei codierten
Monitor-Kennungsbits verraten, wie der jeweilige Monitor angesteuert
werden will und welche Betriebsarten er zuläßt. Noch ist
die Masse der Monitore und Monitorkabel hierzu jedoch nicht in der
Lage. Das hat viele Designer von VGA-Clones wohl dazu bewogen, auf
eine automatische Verarbeitung der Kennungsbits zu verzichten und die
altbekannten DIP-Schalter noch nicht in der untersten Schublade
verschwinden zu lassen.
Nach wie vor ist es bei vielen
Nachbau-VGA, ebenso wie bei allen Adaptervorgängern nicht
möglich, softwareseitig die Ausgabe eines farbigen Bildes auf
einem monochromen Monitor zu erkennen und selbständig auf ein
Videolayout für monochromes Anzeigen umzuschalten.
Die einheitliche Codierung von Monitoren läßt sich sicher nur
durch die Publizierung des Codierungssystems erreichen, was zusammen
mit der Einführung des neuen 15poligen Videosteckers bereits den
Durchbruch hin zu einer einheitlichen Monitorcodierung hätte
bringen können.
Der Monitor bleibt die einzige Schwachstelle bei der Erkennung
der Bildausgabe auf einem Videoschirm.
Tabelle 1. PS/2 Video Display
Return Video Display Combination:
- Aufruf:
-
- al =
- 0
- Rückgabe:
-
- al =
- 1Ah
- bh =
- primärer Adapter beim Booten
- bl =
- sekundärer Adapter beim Booten
Folgende Werte sind definiert:
- -1:
- nicht erkannt
- 0:
- nicht vorhande
- 1:
- Monochrome Display Adapter (MDA)
- 2:
- Color Graphics Adapter (CGA)
- 3,9:
- reservierter Code
- 4:
- Enhanced Graphics Adapter (EGA) im Color Mode
- 5:
- Enhanced Graphics Adapter (EGA) im Monochrome Mode
- 6:
- Professional Graphics Controller
- 7:
- Video Graphics Array (VGA) mit Monochrome Display
- 8:
- Video Graphics Array (VGA) mit Color Display
- 10:
- Multi-Color Graphics Array (MCGA) mit digitalem Color Display
- 11:
- Multi-Color Graphics Array (MCGA) mit analogem Monochrome Display
- 12:
- Multi-Color Graphics Array (MCGA) mit analogem Color Display
Set Video Display Combination:
- Aufruf:
-
- al =
- 1
- bl =
- primärer Adapter
- bh =
- sekundärer Adapter
- Rückgabe:
-
- al =
- 1Ah, wenn die gewählten Display Combination Codes bei
den installierten Adaptern möglich sind.
Alle bei der jeweiligen Hardware möglichen Wertepaare für bh und bl sind im
Display Combination Code Table verzeichnet. Auf seinen Anfang zeigt der
zweite Vektor des Secondary Save Pointer tables.
Der Display Combination Code Table Index (DCC, 0040:008Ah) zeigt auf die
gewählte Adapterkombination im Display Combination Code Table, der
folgendermaßen aufgebaut ist:
- 1.Byte:
- Anzahl der Einträge im Datenfeld
- 2.Byte:
- Display Combination Code Table Version
- 3.Byte:
- Maximale Adapterkennzahl
- 4.Byte:
- reserviert
- 5.Byte:
- Hier beginnt das Datenfeld mit allen möglichen Combination Codes.
Der DDC zeigt auf die gerade angewählte Kombination.
Tabelle 2. EGA Video Subsystem
Return Video Configuration Information:
- Aufruf:
-
- bl =
- 10h
- Rückgabe:
-
- bh =
- default BIOS-Videomode
(0: Color, 1: Monochrome) - bl =
- Größe des Video RAM
(0: 64 KByte, 1: 128 KByte,
2: 192 KByte, 3: 256 KByte) - ch =
- Feature Bits
- cl =
- Stellung der Konfigurationsschalter
Listing 1. Identifizierung von Grafikadaptern
;------------------------------------------------------------------------
; Identifizierung von Video Adaptern release 1.0
; Copyright (c) Ingo Eickmann, 1989 09/01/89
;------------------------------------------------------------------------
PAGE 65,80
TITLE Identify
code segment word public 'CODE'
assume cs:code
;------------------------------------------------------------------------
; Identifizierung von Videoadaptern
public Identify ; Rückgabe: AH: primärer Adapter
; AL: sekundärer Adapter
;------------------------------------------------------------------------
Identify proc far
mov ax,1A00h
int 10h ; PS/2 Video Display Combination
cmp al,1Ah ; PS/2 ?
je Active ; Ja ->
mov ah,12h
mov bl,10h
int 10h ; EGA Video Subsystem Configuration
cmp bl,10h ; EGA vorhanden ?
mov bx,0
je TestCGA ; Nein ->
mov al,cl
shr al,1 ; DIP-Schalterstellung umrechnen
cmp al,3
jl EGA1
sub al,3
EGA1: mov bh,2
jz TestMDA ; EGA als CGA ->
shl bh,1
cmp al,1
je TestMDA ; EGA als EGA ->
mov bh,5 ; EGA als monochromer Adapter
call CGA ; CGA vorhanden ?
jnc Active ; Nein ->
mov bl,2
jmp Active
TestCGA:
call CGA ; CGA vorhanden ?
jnc TestMDA ; Nein ->
mov bh,2
TestMDA:
call MDA ; MDA vorhanden ?
jnc Active ; Nein ->
mov bl,1
or bh,bh
jnz Active
xchg bh,bl
Active:
or bl,bl ; Adapter 2 gefunden ?
jz TestHerc ; Nein ->
push bx
mov ah,0Fh
int 10h ; Return current Video Status
pop bx
and al,7
cmp bh,1 ; Adapter 1 MDA oder EGAMono ?
je Mono
cmp bh,5
jne NotMono ; Nein ->
Mono: cmp al,7 ; Mono Mode ?
je TestHerc ; Ja -> Reihenfolge stimmt
jmp Tausch
NotMono: ; Adapter 1 ist Color
cmp al,7 ; Mono Mode ?
jne TestHerc ; Nein -> Reihenfolge stimmt
Tausch: xchg bh,bl ; Adapter 1 <-> Adapter 2
TestHerc:
cmp bh,1 ; Adapter 1 = MDA ?
jne Herc1 ; Nein ->
call Herc ; Ist monochromer Adapter Hercules ?
jnc Raus ; Nein ->
mov bh,64 ; Hercules Display Combination Code
Herc1: cmp bl,1 ; Adapter 2 = MDA ?
jne Raus ; Nein ->
call Herc ; Ist monochromer Adapter Hercules ?
jnc Raus ; Nein ->
mov bl,64 ; Hercules Display Combination Code
Raus: mov ax,bx
ret
Identify endp
;------------------------------------------------------------------------
; CGA: Carry gesetzt, wenn 6845 einer CGA gefunden
;------------------------------------------------------------------------
CGA proc near
mov dx,3D4h ; CRT Controller Adresse bei CGA
call Test6845 ; 6845 vorhanden ?
ret
CGA endp
;------------------------------------------------------------------------
; MDA: Carry gesetzt, wenn 6845 eines MDA gefunden
;------------------------------------------------------------------------
MDA proc near
mov dx,3B4h ; CRT Controller Adresse bei MDA
call Test6845 ; 6845 vorhanden ?
ret
MDA endp
;------------------------------------------------------------------------
; Herc: Carry gesetzt, wenn monochromer Adapter als Hercules erkannt
;------------------------------------------------------------------------
Herc proc near
mov dx,3BAh ; CRTC Status Register
in al,dx ; Bit 7: Vertical Synchronisation
and al,10000000b ; (etwa alle 20 msec)
mov ah,al
xor cx,cx
Lop: in al,dx ; Warteschleife bis zur nächsten
and al,10000000b ; Änderung
cmp ah,al
loope Lop
clc
je NoHerc ; keine Änderung des Bits ->
cmc ; Änderung war da: Hercules
NoHerc: ret
Herc endp
;------------------------------------------------------------------------
; Test6845: Carry gesetzt, wenn 6845 an Port [dx] erkannt
;------------------------------------------------------------------------
Test6845 proc near
mov ax,01F0Eh ; Cursor Start Position
out dx,al
inc dx
in al,dx ; alten Inhalt retten
xchg ah,al
out dx,al ; neuen Wert schreiben
mov cx,100
loop $
in al,dx ; neuen Wert wieder auslesen
xchg ah,al
out dx,al ; alten Inhalt zurückschreiben
cmp ah,01Fh
clc
jne No6845 ; war ein CRTC Register vorhanden ?
cmc ; -> Ja: Carry setzen
No6845: ret
Test6845 endp
code ends
end
Listing 2. Einbindung in Turbo Pascal
unit Iden;
(* Unit - Deklaration für Turbo Pascal 4.0/5.x, I.Eickmann 1989 *)
{$F+}
interface
function Identify : integer;
implementation
{$L IDENTIFY.obj}
function Identify; external;
end.
Listing 3. Offenlegung der Videoausstattung
program Videoadapter;
(* Identifizierung des primären/sekundären Videoadapters, I.Eickmann 1989 *)
uses Iden;
var Video1,Video2 : Integer;
procedure printAdapter(Video : Integer);
var str : string;
beginHEIGHT=22
case Video of
0: str := 'nicht vorhanden';
1: str := 'Monochrome Display Adapter (MDA)';
2: str := 'Color Graphics Adapter (CGA)';
3,9: str := '[reservierter Video Display Combination Code (DCC)]';
4: str := 'Enhanced Graphics Adapter (EGA) im Color Mode';
5: str := 'Enhanced Graphics Adapter (EGA) im Monochrome Mode';
6: str := 'Professional Graphics Controller';
7: str := 'Video Graphics Array (VGA) mit Monochrome Display';
8: str := 'Video Graphics Array (VGA) mit Color Display';
10: str := 'Multi-Color Graphics Array (MCGA) ' +
'mit digitalem Color Display';
11: str := 'Multi-Color Graphics Array (MCGA) ' +
'mit analogem Monochrome Display';
12: str := 'Multi-Color Graphics Array (MCGA) ' +
'mit analogem Color Display';
64: str := 'Hercules Graphics Card (HGC)';
else str := 'nicht erkannt';
end;
writeln(str);
end;
Begin
Video1 := Identify;
Video2 := Video1 and 255;
Video1 := Video1 shr 8;
write('Videoadapter 1: ');
printAdapter(Video1);
write('Videoadapter 2: ');
printAdapter(Video2);
End.
aus mc 05/90 – Seite 44-48