164 lines
7.7 KiB
Markdown
164 lines
7.7 KiB
Markdown
### At the Core {#Heading5}
|
|
|
|
A little background is necessary before we're ready to examine Listing
|
|
23.1. The VGA is built around four functional blocks, named the CRT
|
|
Controller (CRTC), the Sequence Controller (SC), the Attribute
|
|
Controller (AC), and the Graphics Controller (GC). The single-chip VGA
|
|
could have been designed to treat the registers for all the blocks as
|
|
one large set, addressed at one pair of I/O ports, but in the EGA, each
|
|
of these blocks was a separate chip, and the legacy of EGA compatibility
|
|
is why each of these blocks has a separate set of registers and is
|
|
addressed at different I/O ports in the VGA.
|
|
|
|
Each of these blocks has a sizable complement of registers. It is not
|
|
particularly important that you understand why a given block has a given
|
|
register; all the registers together make up the programming interface,
|
|
and it is the entire interface that is of interest to the VGA
|
|
programmer. However, the means by which most VGA registers are addressed
|
|
makes it necessary for you to remember which registers are in which
|
|
blocks.
|
|
|
|
Most VGA registers are addressed as *internally indexed* registers. The
|
|
internal address of the register is written to a given block's Index
|
|
register, and then the data for that register is written to the block's
|
|
Data register. For example, GC register 8, the Bit Mask register, is set
|
|
to 0FFH by writing 8 to port 3CEH, the GC Index register, and then
|
|
writing 0FFH to port 3CFH, the GC Data register. Internal indexing makes
|
|
it possible to address the 9 GC registers through only two ports, and
|
|
allows the entire VGA programming interface to be squeezed into fewer
|
|
than a dozen ports. The downside is that two I/O operations are required
|
|
to access most VGA registers.
|
|
|
|
The ports used to control the VGA are shown in Table 23.1. The CRTC, SC,
|
|
and GC Data registers are located at the addresses of their respective
|
|
Index registers plus one. However, the AC Index and Data registers are
|
|
located at the same address, 3C0H. The function of this port toggles on
|
|
every **OUT** to 3C0H, and resets to Index mode (in which the Index
|
|
register is programmed by the next **OUT** to 3C0H) on every read from
|
|
the Input Status 1 register (3DAH when the VGA is in a color mode,
|
|
|
|
* * * * *
|
|
|
|
Register
|
|
|
|
Address
|
|
|
|
* * * * *
|
|
|
|
AC Index/Data register
|
|
|
|
3C0H (write with toggle)
|
|
|
|
AC Index register
|
|
|
|
3C0H (read)
|
|
|
|
AC Data register
|
|
|
|
3C1H (read)
|
|
|
|
Miscellaneous Output register
|
|
|
|
3C2H (write)
|
|
|
|
3CCH (read)
|
|
|
|
Input Status 0 register
|
|
|
|
3C2H (read)
|
|
|
|
SC Index register
|
|
|
|
3C4H (read/write)
|
|
|
|
SC Data register
|
|
|
|
3C5H (read/write)
|
|
|
|
GC Index register
|
|
|
|
3CEH (read/write)
|
|
|
|
GC Data register
|
|
|
|
3CFH (read/write)
|
|
|
|
CRTC Index register
|
|
|
|
3B4H/3D4H (read/write)
|
|
|
|
CRTC Data register
|
|
|
|
3B5H/3D5H (read/write)
|
|
|
|
Input Status 1 register/
|
|
|
|
AC Index/Data reset
|
|
|
|
3 BAH/3DAH (read)
|
|
|
|
Feature Control
|
|
|
|
3BAH/3DAH (write)
|
|
|
|
3CAH (read)
|
|
|
|
Table 1.1 The Ports through which the VGA is controlled.
|
|
|
|
* * * * *
|
|
|
|
3BAH in monochrome modes). Note that all CRTC registers are addressed at
|
|
either 3DXH or 3BXH, the former in color modes and the latter in
|
|
monochrome modes. This provides compatibility with the register
|
|
addressing of the now-vanished Color/Graphics Adapter and Monochrome
|
|
Display Adapter.
|
|
|
|
The method used in the VGA BIOS to set registers is to point DX to the
|
|
desired Index register, load AL with the index, perform a byte **OUT**,
|
|
increment DX to point to the Data register (except in the case of the
|
|
AC, where DX remains the same), load AL with the desired data, and
|
|
perform a byte **OUT**. A handy shortcut is to point DX to the desired
|
|
Index register, load AL with the index, load AH with the data, and
|
|
perform a word **OUT**. Since the high byte of the **OUT** value goes to
|
|
port DX+1, this is equivalent to the first method but is faster.
|
|
However, this technique does not work for programming the AC Index and
|
|
Data registers; both AC registers are addressed at 3C0H, so two separate
|
|
byte **OUT**s must be used to program the AC. (Actually, word **OUT**s
|
|
to the AC do work in the EGA, but not in the VGA, so they shouldn't be
|
|
used.) As mentioned above, you must be sure which mode—Index or Data—the
|
|
AC is in before you do an **OUT** to 3C0H; you can read the Input Status
|
|
1 register at any time to force the AC to Index mode.
|
|
|
|
How safe is the word-**OUT** method of addressing VGA registers? I have,
|
|
in the past, run into adapter/computer combinations that had trouble
|
|
with word **OUT**s; however, all such problems I am aware of have been
|
|
fixed. Moreover, a great deal of graphics software now uses word
|
|
**OUT**s, so any computer or VGA that doesn't properly support word
|
|
**OUT**s could scarcely be considered a clone at all.
|
|
|
|
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
 *A speed tip: The setting of each chip's Index register remains the same until it is reprogrammed. This means that in cases where you are setting the same internal register repeatedly, you can set the Index register to point to that internal register once, then write to the Data register multiple times. For example, the Bit Mask register (GC register 8) is often set repeatedly inside a loop when drawing lines. The standard code for this is:*
|
|
------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
MOV DX,03CEH ;point to GC Index register
|
|
MOV AL,8 ;internal index of Bit Mask register
|
|
OUT DX,AX ;AH contains Bit Mask register setting
|
|
|
|
-- ------------------------------------------------------------------------------------------------------
|
|
*Alternatively, the GC Index register could initially be set to point to the Bit Mask register with*
|
|
-- ------------------------------------------------------------------------------------------------------
|
|
|
|
MOV DX,03CEH ;point to GC Index register
|
|
MOV AL,8 ;internal index of Bit Mask register
|
|
OUT DX,AL ;set GC Index register
|
|
INC DX ;point to GC Data register
|
|
|
|
-- -------------------------------------------------------------------------------------------------
|
|
*and then the Bit Mask register could be set repeatedly with the byte-size **OUT** instruction*
|
|
-- -------------------------------------------------------------------------------------------------
|
|
|
|
OUT DX,AL ;AL contains Bit Mask register setting
|
|
|
|
-- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
*which is generally faster (and never slower) than a word-sized **OUT**, and which does not require AH to be set, freeing up a register. Of course, this method only works if the GC Index register remains unchanged throughout the loop.*
|
|
-- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|