VGA Hardware

From OSDev.wiki
Revision as of 09:49, 28 December 2006 by Combuster (talk | contribs) (User:Combuster/VGAwip moved to VGA Hardware: Merge with main namespace)
Jump to navigation Jump to search
This page is a work in progress.
This page may thus be incomplete. Its content may be changed in the near future.

Things that still need to be done:

  • I need to reverse engineer documentation for the sequencer.
  • I need to test some additional GC bits for effects.
  • Read Modes 0 and 1, Write modes 1,2,3 (this is easy as this documentation is rather complete. I Have not tested all details of this stuff)
  • Register Accessing (pretty obvious for the insider, although i recently caught a guru messing this up O.o)
  • Color Logic (There's more to this than the eye meets. I can write this from info out of Abrash's book, but i should still test it anyway
  • CRTC: byte word doubleword mode, doublescanning, why 256-color modes have halved horizontal resolutions. Some of this depends on the sequencer operation...

- Combuster 16:55, 27 December 2006 (CST)


What you can do:

  • Proof-read it, check for sanity.
  • Comment on n00b-friendliness
  • check registers and timings
  • probably a lot more :)

- Combuster 16:55, 27 December 2006 (CST)



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

WARNING: Improperly changing CRTC settings can be harmful to the monitor attached to it

DISCLAIMER: The information provided might not be accurate, and using them is to be done entirely at your own risk


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:

Overview of VGA Hardware

This diagram is however an simplification for the ease of programming, and should not be considered correct.

VGA Registers

todo: how to read/write registers

Video Memory Layout

The video memory consists of four 'planes' (individual units) of memory, each with a size of 64KB, giving the VGA 256k of video memory. Connected to it is the Sequencer, which interprets this memory to generate colors which are fed to the subsequent stages. The way colors are organized in this memory mainly depends on the color depth.

Memory Layout in 16-color graphics modes

16 colors means there are 4 bits used per color. The VGA has four planes, and for each pixel, and each plane holds one bit of each pixel drawn. Since the information for each pixel is scattered over four memory locations, this is the most difficult memory model.

Bit 7 of each address contains information about the first pixel, Bit 6 has information about the next pixel, and so on.

Plane 0 contains the first bits of all pixels, Plane 1 the second bits and so on.

Example:

one byte
Bits 0 1 2 3 4 5 6 7
Plane 0 0 0 0 0 1 1 1 1
Plane 1 0 0 1 1 1 1 0 0
Plane 2 0 1 1 0 0 1 1 0
Plane 3 0 1 0 1 0 1 0 1
Colors displayed 0000 (0) 1100 (12) 0110 (6) 1010 (10) 0011 (3) 1111 (15) 0101 (5) 1001 (9)

Memory Layout in 256-color graphics modes

In this mode, each byte of video memory describes exactly one pixel. Pixels are generated by increasing address in linear mode, with all colors taken from plane 0. In planar mode (Also known as Mode X) each address describes 4 consecutive pixels, one from each plane. Plane 0 describing the first pixel, plane 1 the next, and so on.

Memory Layout in text modes

In text mode, the screen is divided into character cells rather than pixels. Only three of the four planes are actually in use. Plane 0 contains the character codes for each cell, Plane 1 contains the respective attributes.

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 14 are commonly in used.

Memory Layoud in 4-bit modes

Todo: i know close to nothing about 4-bit color modes, kindof before my age

The Graphics Controller

The Graphics Controller (Abbreviated to GC) is responsible for directing memory reads and writes to and from video memory.

The memory consists of four planes of 64k on a standard VGA. Each read and write operation selects one address within all of these planes, then operates on all four planes. This means that for each byte of data written, four bytes of video memory might potentially be changed.

Apart from a few standard modes, the implementation of various control bits vary between implementations. However, the exact details can be probed by performing writes in the mode to check, then reading it out in planar mode.

These modes seem to be consistent among all VGA compatibles and emulators i've tested:

  • Mode 3 (Text mode) (right now I can only set it by keeping a state dump of VGA registers of the old mode)
  • Mode X (Planar 256 color mode)

I have yet to write code that enters the following standard modes on all hardware

  • Mode 13h (Linear 256 color mode) - GC part seems ok, however, I cant get the sequencer to work properly (Video output is bogus)
  • Mode 11h (Planar 16 color mode) - Not tried
  • Mode 04h (4 color mode) - Not tried

The Graphics Controller consists of of some addressing logic, and some specific read/write logic.

The Addressing logic controls the address in video memory to be accessed, and to some extent, the individual pages within it.

The Read/Write logic controls which planes of the memory are actually read or written, and how these values relate to the value being sent by the CPU.

Datapaths in the Graphics Controller

Addressing Logic

Registers involved:

Register Name Port Index 7 6 5 4 3 2 1 0
Sequencer Memory Mode Register 0x3C4 0x04 Chain 4 Odd/Even Disable

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 wether plane enable has effect in chain 4 writes.

Bochs Qemu Virtual PC ATI Card (X300) NVidia (GeForce 6 6150)
Chain 4 has effect on writes Yes Yes Yes Yes Yes
Chain 4 has effect on output Yes No No No No
Plane Write Enable takes effect on writes No Yes No Yes Yes

In bochs + VPC, as well as the hardware tested, Chain4 writes occur to this address:

plane  = addr & 0x0003; // lower bits
offset = addr & 0xfffb; // rest of the bits. multiples of 4 wont get written

In qemu writes go here:

plane  = addr & 0x0003; // lower bits
offset = addr >> 2;     // only the first 16k of each page gets written.

Odd/Even Disable Bit

Seems to be a Don't Care bit in bochs+qemu

VPC generates some form of echo:

plane1 = addr & 0x0001; // lowest bit
plane2 = plane1 + 2;    // pick the other odd/even plane
offset = addr & 0xfffe; // generate the offset
write (plane1, offset); // write to the plane
write (plane2, offset); // write to the other plane

This matches the NVidia card this, However my ATI card (and somewhat older, my V2x00 board) behaves slightly different (its pretty close though):

offset = addr & 0xffff; // generate the offset

There are probably some more things involved here, todo

Read/Write logic

The Read/Write Logic performs several operations on the written/read data, and a set of internal registers called the latches. Reading from video memory loads these latches with the value emitted by video memory. Write operations use the latches as an additional data source, apart from the data written to the host. 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 or'ed together.


Registers involved:

Register Name Port Index 7 6 5 4 3 2 1 0
Graphics Mode Register 0x3CE 0x05 Read Mode Write Mode
Map Mask Register 0x3C4 0x02 Memory Plane Write Enable
Enable Set/Reset Register 0x3CE 0x01 Enable Set/Reset
Set/Reset Register 0x3CE 0x00 Set/Reset Value
Data Rotate Register 0x3CE 0x03 Logical Operation Rotate Count
Bit Mask Register 0x3CE 0x08 Bit Mask

todo: Study effects of multibyte reads/writes on logic and latch operation

Write Mode 0

Write mode 0 is the standard write mode.

Write Mode 0 Logic

When a byte is written, it follows the following steps

  • The input byte is rotated right by the amount specified in Rotate Count, with all bits shifted off being fed into bit 7
  • The resulting byte is distributed over 4 separate paths, one for each plane of memory
  • If a bit in the Enable Set/Reset register is clear, the corresponding byte is left unmodified. Otherwise the byte is replaced by all 0s if the corresponding bit in Set/Reset Value is clear, or all 1s if the bit is one.
  • The resulting value and the latch value are passed to the ALU
  • Depending of the value of Logical Operation, the following operation is performed:
Value of Logical Operation Result
0 (0x00) The byte from the set/reset operation is forwarded
1 (0x08) Both inputs are ANDed together
2 (0x10) Both inputs are ORed together
3 (0x18) Both inputs are XORed together
  • 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.


Todo: more write modes, read modes

The Sequencer

The Sequencer is responsible to convert video memory to color indexes.

TODO

Color Logic

This block revolves around the Attribute Controller, Palette RAM and DAC, which are together responsible for generating a color signal out of an index generated by the Sequencer.

TODO

The CRT Controller

The Cathode Ray Tube Controller, or CRTC, is the unit to create a video signal from the data produced by the DAC. By programming this unit you can control the resolution of your monitor, as well as some hardware overlay and panning effects.

The following diagram gives a quick overview of how the CRTC is generally configured (with register names)

Resolution and Timing

CRTC output diagram

Horizontal timigs are based on character clocks (multiples of 8 or 9 pixels), Vertical timings are per-scanline. Since these easily exceed the 255 limit of one byte, the Overflow Register is used to store the high-order bits.

Horizontally and vertically, the area can be separated into four parts:

  • Active Display: The data rendered from memory, from the human perspective this area equals the resolution.
  • Overscan: the area around the Active Display. Although commonly black, this can be made visible by changing its colour. By default this is 8 pixels in size on each end.
  • Blanking Area: When the CRTC disables the colour output. This is the black area around the screen. By changing this you can move, center, and scale the screen.
  • Retrace Period: This area is not generally visible. This is just a signal sent to the monitor to go to the next scanline or the next frame. However, monitors may steal some of this time for the blanking area following it or vice versa. Consequently, the blanking sizes on either side are not equal to accomodate.

Registers

Registers involved in horizontal timing:

Register Name Port Index 7 6 5 4 3 2 1 0
Horizontal Total Register 0x3D4 0x00 Horizontal Total
End Horizontal Display Register 0x3D4 0x01 Horizontal Display End
Start Horizontal Blanking Register 0x3D4 0x02 Horizontal Blanking Start
End Horizontal Blanking Register 0x3D4 0x03 Horizontal Display Skew Horizontal Blanking End (bits 0..4)
Start Horizontal Retrace Register 0x3D4 0x04 Horizontal Retrace Start
End Horizontal Retrace Register 0x3D4 0x05 H. Blanking End (bit 5) Horizontal Retrace End

Registers involved in vertical timing:

Register Name Port Index 7 6 5 4 3 2 1 0
Vertical Total Register 0x3D4 0x06 Vertical Total (bits 0..7)
Overflow Register 0x3D4 0x07 V.Retr.St. (9) V.Disp.End (9) V.Total (9) V.Blank.St. (8) V.Retr.St. (8) V.Disp.End (8) V.Total (8)
Maximum Scan Line Register 0x3D4 0x09 V.Blank.St. (9)
Vertical Retrace Start Register 0x3D4 0x10 Vertical Retrace Start (bits 0..7)
Vertical Retrace End Register 0x3D4 0x11 Vertical Retrace End
Vertical Display End Register 0x3D4 0x12 Vertical Display End (bits 0..7)
Vertical Blanking Start Register 0x3D4 0x15 Vertical Blanking Start (bits 0..7)
Vertical Blanking End Register 0x3D4 0x16 Vertical Blanking End (bits 0..6)

Other registers dealing with timing:

Register Name Port Index 7 6 5 4 3 2 1 0
Miscellaneous Output Register 0x3C2 - Clock Select
Clocking Mode Register 0x3C4 0x01 9/8 Dot Mode

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.

The clock can be selected using Clock Select. Only two of four possible clocks are present on all VGAs. A clock of 25MHz is selected when this field is zero, 28MHz is selected when this field equals 1. Some boards have other clocks under values 2 and 3, but you should not write these values unless you know the clock that is there. Note that selecting the 28MHz clock and 9 pixels per pixel results in the same timings as selecting the 25MHz clock and 8 pixels per character, only with different resolutions.

The refresh rates can be calculated as follows:

  • Horizontal Refresh Rate = Clock Frequency (in Hz) / total pixels horizontally
  • Vertical Refresh Rate = Horizontal Refresh Rate / total scan lines

On a VGA monitor, the horizontal refresh rate should equal 31.25 kHz. Vertically, only 400 and 480 pixel resolutions are used.

If your monitor supports it, you can set virtually any crazy resolution you want. (provided the horizontal resolution is a multiple of 8 or 9 - 8 seems to be common) Most modern monitors allow anything between 400x300 and 800x600 being set this way.

Sample timing scheme

640x480 (16 bits) uses the following sizes:

  • Timing: 25MHz dot clock, 8 pixels per character
  • Totals: 800 pixels horizontally, (100 characters), 524 scan lines
  • Active Display: 640x480 (80 characters, 480 scan lines)
  • Overscan: 8 pixels (8 scan lines vertically / 1 character clock horizontally) on each side
  • Horizontal Retrace: 12 characters (96 pixels)
  • Vertical Retrace: 2 scan lines
  • Blanking (Left): 2 characters (16 pixels)
  • Blanking (Right): 4 characters (32 pixels)
  • Blanking (Top): 24 scan lines
  • Blanking (Bottom): 2 scan lines

Which should be VGA compatible