VGA Hardware: Difference between revisions

m
no edit summary
[unchecked revision][unchecked revision]
mNo edit summary
 
(26 intermediate revisions by 16 users not shown)
Line 1:
{{InVideo Progresswarning}}
<div style="text-align: center; background-color: green; padding: 5px; margin-left: 30%; margin-right: 30%;">See discussion page before editing.</div>
 
TheEven though VGA is a complex piece of hardware. Even though its old, many modern graphics cards are compatible with it, including NVidia and ATI cards. This can make writing ana VGA driver rather attractive. The amount of compatibility varies however, andso do not evernever assume a compatible card is compatible without proper hardware detection.
Apart from real machines, several emulators and virtual machines provide VGA emulation,: including [[Bochs]], [[QEMU]] and [[Microsoft Virtual PC]] to name a few. After 2011 video card manufacturers begun to drop VGA compatibility in favour of [[GOP]] under [[UEFI]] (VirtualBox UEFI and TianoCore both supports that).
 
== Overview ==
The VGA is a complex piece of hardware. Even though its old, many modern graphics cards are compatible with it, including NVidia and ATI cards. This can make writing an VGA driver rather attractive. The amount of compatibility varies however, and do not ever assume a compatible card without proper hardware detection.
Apart from real machines, several emulators and virtual machines provide VGA emulation, including [[Bochs]], [[QEMU]] and [[Microsoft Virtual PC]]
 
While the VGA chip is quite a simple piece of hardware compared to modern video equipment, it is possibly one of the more complicated devices to program for, and especially in the old days knowing your way around this particular device was sufficient for establishing quite a reputation. While currently a legacy device, it is a good place to begin practicing your video driver skills. While a full-blown VGA driver might make an USB controller look trivial, there are fortunately many shortcuts available for taking.
'''WARNING: Improperly changing CRTC settings can be harmful to the monitor attached to it'''
 
=== What's not covered ===
'''DISCLAIMER: The information provided might not be accurate, and using them is to be done entirely at your own risk'''
While this page tries to be a complete overview on what the VGA can do, it does not fully cover the whole set of graphics. After all, a video card only turns bytes in its memory into a signal on the connector on its backside. Determining what bytes to put in memory is only barely touched in the wiki in general — there are examples of plotting pixels and setting individual characters but your OS will determine what pixels are formed by an image and which characters are part of your title screen. On the remote end, monitors have their own way of dealing with signals. A lot of those settings dictated by monitors are needed by the video card, and each resolution comes with its own set of settings. You can find out your own set of settings by [[Video Signals And Timing|using a set of equations]], but you can skip that step and reuse one of the examples provided at the [[VGA_Hardware#Sample_Register_Settings|example settings]] instead. The [[VGA_Hardware#The_CRT_Controller|CRTC chapter]] explains them in detail.
 
=== Getting started ===
There's a fair share of [[VGA Resources|modesetting code available]] around the web. The basic steps involve calculating the needed register values, writing them to the VGA, then continue with drawing. You'll need:
* Port I/O: The VGA needs 8-bit read/writes, and 16-bit writes.
* MMIO: The VGA uses uncached byte accesses to 0xA0000-0xBFFFF. In several cases, larger writes are also allowed.
* Functions to [[VGA_Hardware#VGA_Registers|read and write registers]] for each VGA component - since there are many more registers than there are ports you will need a wrapper for this.
* A structure that contains the VGA display settings. For a nice list of things you want to set, you can use the example register settings part. Keep in mind that you might also want a structure for things that change during drawing, such as colours and offsets.
* A function that writes that structure to the device
* A function that fills out that structure. You can also use a hardcoded structure initially.
 
=== Hardware components ===
 
The VGA can be divided in several parts. Historically, the predecessor of the VGA - the EGA - had several chips to perform each part in the system. These chips could be configured to your liking using the I/O Bus. On the VGA, these have been merged into one chip (with the exception of the DAC).
== Overview ==
 
The VGA can be divided in several parts. Historically, the predecessor of the VGA - the EGA - had several chips to perform each part in the system. These chips could be configured to your liking using the I/O Bus. On the VGA these have been merged into one chip (with the exception of the DAC).
 
The following diagram shows which units are responsible for which parts:
 
[[Image:VGA overview.gif|Overview of VGA Hardware|325px]]
 
This diagram is, however, ana simplification for the ease of programming, and should not be considered correct.
 
== VGA Registers ==
Line 29 ⟶ 37:
In the documentation below, a port number and possibly an index is provided. The port is usually the base port for indexed registers, or the actual port for single registers.
 
Note that [[PCI]] boards do *not* report the VGA addresses in their configuration space, and that the addresses can not be remapped. It is therefore not possible to properly operate two cards in VGA mode at the same time.
 
=== Port 0x3C0 ===
Line 38 ⟶ 46:
 
=== Port 0x3C4, 0x3CE, 0x3D4 ===
These are the most used indexed registers. The index byte is written to the port given, then the data byte can be read/written from port+1. Some programs use a single word16-bit access instead of two byte accesses for writing, which does effectively the same. (take care of byte ordering when doing so)
 
Port 0x3D4 has some extra requirements - it requires bit 0 of the '''Miscellaneous Output Register''' to be set before it responds to this address (if cleared, these ports appears at 0x3B4). Also, registers 0-7 of 0x3D4 are write protected by the protect bit (bit 7 of index 0x11)
Line 128 ⟶ 136:
|}
 
The Plane Write Enable register is used to choose the plane to be written, then the memory can be written by written by accessing the corresponding address in memory.
 
=== Memory Layout in 256-color graphics modes ===
Line 141 ⟶ 149:
Plane 2 contains the font data. For each of the 256 available characters this plane has 32 bytes reserved. Each byte represents one horizontal cross section through each character. The first byte of each group defines the top line, each next byte describes the rows below it. For every set bit, the foreground color is used, For every cleared bit, the background color is used.
 
Although 32 bytes are reserved for each character, only 16, 14, or 8 of them are commonly in used, depending on the character height.
 
Planes 0 and 1 are written directlyaccessible from the host by writing to the video memory range. Plane 0 is accessed on even addresses, plane 1 is accessed on odd addresses, with each consecutive word16-bit value describing the next character. Accessing plane 2 to change fonts requires [[VGA Fonts|changes in addressing logic]].
 
=== Memory Layout in 4-bitcolor modes ===
The CGA was limited to 4 concurrent colors, with two bits each. The EGA adds two extra bits by adding a pair of extra planes, increasing from the old two to the current four planes per pixel. If you want a 4-color mode that means you just should not touch planes 2 + 3.
'''Todo: i know close to nothing about 4-bit color modes, kindof before my age'''
 
'''Todo: determine the b/w/d, shift mode and odd/even mode for CGA compatibility (guesstimated at word mode, interleaved shift, odd/even enabled, i.e. equivalent to text mode except for the alphanumeric bit)'''
 
== The Graphics Controller ==
Line 204 ⟶ 214:
 
==== Chain 4 Bit ====
'' Been testing the effect of Chain 4 on memory writes and output, and the results aren't consistent with one another. Chain 4 is located in the Sequencer which would mean setting/clearing it would have effect on video output. Furthermore I have been testing whether plane enable has effect in chain 4 writes. '' - Combuster
 
 
'' This section needs a rewrite. Chain4 mode is perfectly normal function of VGA that standard BIOS 0x13 mode relies on for it's "linear" addressing. Basicly, when chain4 is set, lowest 2 bits of memory access address select the plane, and the address is shifted 2 bits down. The memory organization (as far as display goes) is always planar (like Mode-X) but the special mapping that is chain4 mode makes it appear linear. As such, I find it highly unlikely that the data about chain4 support below is correct. [[User:Mystran|Mystran]] 09:25, 9 December 2007 (CST)
 
 
'' Here's the catch: all systems emulate mode 0x13 and mode-x up to the extent most programmers do expect. When in mode 0x13, video memory seems linear due to the chain 4 bit. On the other end, selecting the corresponding byte-mode, word-mode and dword-mode make the display come up as appropriate, i.e. dword mode for 0x13 and byte mode for mode-x. It means that when you use only one mode there's nothing wrong. However, bochs does not support the b/w/d-mode bits and instead uses the chain-4 bit to determine the selection. QEmu doesn't support these bits either, but always uses byte mode and redirects the writes in chain-4 enabled mode to the location needed to have byte word work as expected. All the tested emulators have their quirks in this area, assuming that the real cards are the most VGA compatible. (MSVPC being the closest to a real card).''
 
''The process to verify the behaviour:''
* Enter mode-x, clear screen (I added rulers but they won't interfere with the actual process.)
* Enable chain-4 bit (but leave the BWD bits in their mode-x state) - this should not change the screen (it does however on bochs)
* write a test pattern to the screen
* Visually check the output. On real hardware you'll notice 4 coloured pixels followed by 12 blank ones, 4 pixels, 12 blanks etc.
''(you could also clear chain-4 and read out the actual planes to detect qemu writing pixels without blanks)''
 
''I have just verified it again. The write address is not shifted as you state, it is ANDed. The 12-pixel gaps appear supporting the stated hypothesis. If you have '' '''evidence''' '' of the opposite I would gladly see it. The purpose is after all to provide information.''
 
''If you look at existing mode-X code you will see that it will change the two Byte/Word/Doubleword bits besides just the chain4 bit.''
 
''I have in the meantime learned that the chip ordering isn't as logically distinct as you expect. Chain-4 is located at the GC end of the sequencer and should not affect the output at the CRTC/AC end. I added a stub instead of the comment above to at least make some effort regarding the rewrite'' - [[User:Combuster|Combuster]] 17:12, 9 December 2007 (CST)
 
''p.s. would you mind using the talkpage next time''
 
 
 
The Chain-4 bit changes accesses to video mode from a planar mode when clear to a linear mode when set. While under common circumstances this bit is emulated properly, the way this bit actually works is however very different among implementations (especially emulators) and can have strange effects if you are unaware of it. '''TODO'''What works in all cases, is if chain-4 matches the other settings that are common for established modes (i.e. if you enable chain-4, also make sure the other registers match the expected values for mode 13). Here is a list of differences between various implementations of Chain-4. Real hardware has so far proven to be consistent with the officially documented behavior.
 
{| {{Wikitable}}
Line 271 ⟶ 257:
plane = addr & 0x0003; // lower bits
offset = addr >> 2; // only the first 16k of each page gets written.
 
Note the fact that in Bochs, Chain-4 alters the physical display of the screen (equivalent to what doubleword mode normally does). This makes Bochs possibly troublesome since you only need to toggle this bit to enter Mode-X, while real hardware also requires that you change doubleword mode into byte mode.
 
==== Odd/Even Disable Bit ====
Line 283 ⟶ 271:
write (plane2, offset); // write to the other plane
 
This matches the NVidia card this, Howeverhowever my ATI card (and somewhat older, my V2x00 board) behaves slightly different (its pretty close though):
 
offset = addr & 0xfff'''f'''; // generate the offset
Line 294 ⟶ 282:
 
The read/write logic has several different operation modes. These can be chosen by setting the Graphics Mode register. The VGA has four write modes and 2 read modes, which can be set independently. By default, the VGA operates in read mode 0 and write mode 0 in such a fashion that all written data goes straight to memory, and read data from each plane is ORed together.
 
 
Registers involved:
Line 401 ⟶ 388:
* The Bit Mask Register is checked, for each set bit the corresponding bit from the ALU is forwarded. If the bit is clear the bit is taken directly from the Latch.
* The Memory Plane Write Enable field is ANDed with the input from the address logic. For each set bit in the result, the corresponding plane is loaded with the result.
 
 
==== Write mode 3 ====
Line 417 ⟶ 403:
* The computed bit mask is checked, for each set bit the corresponding bit from the set/reset logic is forwarded. If the bit is clear the bit is taken directly from the Latch. The result is sent towards memory.
* Finally, The Memory Plane Write Enable field and the input line from the address logic are ANDed together. The bits that remain set are the planes that are actually written.
 
 
''' Todo: more write modes, read modes '''
Line 427 ⟶ 412:
 
=== Alphanumeric Mode ===
In alphanumeric mode the four planes are assigned distinct tasks. Plane 0 contains character data, while plane 1 contains Attribute data. In a standard text mode, these planes are interleaved into host memory. Plane 2 holds the font data. TheWhen addressingdisplaying logictext data, the sequencer loads the character/attribute pairspair infor order.the Itcurrent thenset looksof eight pixels, after which it uses the value for byte 0 to look up the corresponding fontcharacter in plane 2, and adds the character line to get the font data needed. It then pops out the bits infrom orderMSB to LSB, generating athe chosen foreground color when a 1 is encountered, and athe background color when a 0 is encountered.
 
In typical text modes, the stored font is not directly accessible and needs some [[VGA Fonts|changes in addressing logic]] to be read or written.
 
'''TODO: schematics'''
Line 440 ⟶ 427:
While going through memory, the sequencer reads in a 4 bytes at a time from each of the four planes, then outputs 8 pixel colors. The VGA has three distinct modes of grouping this data into pixel values. The setting depends on two bits in a VGA register: the 256-color shift and interleaved shift bits. when both are off, Single shift mode is selected, otherwise the corresponding mode is used (256 color shift mode takes precedence over interleaved shift mode)
 
{| {{Wikitable}}
'''TODO: table of registers involved'''
|-
! Register Name
! Port
! Index
! 7
! 6
! 5
! 4
! 3
! 2
! 1
! 0
|-
| Graphics Mode Register
| 0x3CE
| 0x05
|
| 256-Color Shift
| Interleaved Shift
|
|
|
|
|
|}
 
* Single shift mode
:This mode is used in 16 color modes. For each pixel, one bit is popped off each plane and put together to form the value of a pixel. An example is given in [[VGA Hardware#Memory Layout in 16-color graphics modes|Memory Layout in 16-color graphics modes]]
An example is given in [[VGA Hardware#Memory Layout in 16-color graphics modes|Memory Layout in 16-color graphics modes]]
 
* Interleaved Shift Mode
:This mode makes 4-color modes relatively easy: 2 bits are popped off the most significant side of plane 0. The same is done with plane 2, which become the most significant bits (in 4-color modes, these are zero) After 4 pixels being popped from planes 0 and 2, the same is done with plane 1 and 3, until all 8 pixels have been generated.
 
* 256-Color Shift Mode
:This mode causes 4 bits to be popped of each time. Plane 0 gives the first two pixels, Plane 1 the next two and so on. However, it is not defined in which order this happens. Because this mode is normally used solely in 256-color modes where the color logic will merge two 4-bits pixels together to form one 8-bit pixel, the communication inbetween is acertainnot certain. However, the bits can only be shifted out one of two possible sides, and supporting two possibilities can be overseen. Another problem to this method is, you can not detect which method is used without user intervention or keeping a list. Either way, this method either shifts left (from the msb) or right (from the lsb). If you know the ordering of your video card, you can create a linear 16-bit color mode.
 
=== Address Calculation ===
Line 636 ⟶ 647:
==== Timing Model ====
 
The horizontal timing registers are based on a unit called 'character' (As they match one character in text mode). Each character equals 8 ('''9/8 Dot Mode''' is set) or 9 ('''9/8 Dot Mode''' is clear) pixels. Each scanline contains '''Horizontal Total''' + 5 characters, zero based. '''Horizontal Display End''' tells us the last character that is calculated from memory (i.e. the horizontal resolution in characters minus one). '''Horizontal Blanking Start''' and '''Horizontal Retrace Start''' give us the the last character before either period is started. '''Horizontal Blanking End''' and '''Horizontal Retrace End''' need more explanation, as they only contain part of a number. When blanking or horizontal retrace is enabled the significant bits are checked against the character counter, and if these bits match the respective period will be ended. The quick solution is to calculate the appropriate values, compute the last character clock at which each period should be active, then AND it with 0x3F (Blank) or 0x1F (Retrace) to get the register's value. Note that the periods must be between 1 and 63(Blank)/31(Retrace) character clocks. To be safe, there must be at least one character of overscan on each side of the screen to avoid additional artefacts.
 
The vertical timing is similar, apart from the fact that these registers operate on scan lines (pixels) instead of characters. The '''Vertical Retrace End''' and '''Vertical Blank End''' registers work also similar, although they are different sizes. The Retrace End is 4 bits wide (AND with 0xF, period is 1-15 scanlines), The Blank End size is at least 7 bits (some say its 8, some say its 7), so the value is computed by ANDing with 0xFF, with the period ranging from 1-127 scanlines. As with horizontal timing, at least one scan line of overscan must be present to avoid possible artefacts.
Line 651 ⟶ 662:
==== Sample timing scheme ====
 
640x480 (16 bitscolours) uses the following sizes:
* Timing: 25MHz dot clock, 8 pixels per character
* Totals: 800 pixels horizontally, (100 characters), 524 scan lines
Line 690 ⟶ 701:
! index
! mode 3h (80x25 text mode)
! mode 12h (640x480 planar 16-bit color mode)
! mode 13h (320x200 linear 256-color mode)
! mode X (320x240 planar 256 color mode)
Line 956 ⟶ 967:
 
|}
 
== See Also ==
 
=== External Links ===
 
* http://tinyvga.com/vga-timing — VGA Signal Timing
* http://www.osdever.net/FreeVGA/vga/vga.htm — includes some things not explained here
 
[[Category:VGA]]
[[Category:Video]]
[[Category:Hardware]]