X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=blobdiff_plain;f=specs%2Ffreevga%2Fvga%2Fvgareg.htm;fp=specs%2Ffreevga%2Fvga%2Fvgareg.htm;h=45d31626c77d410432816ce0c9a0bf2fcb66f0ec;hp=0000000000000000000000000000000000000000;hb=8af06d1fd50343e17229618ef4d2693193b2b3d9;hpb=d0d14ca50fbac167253e1e1d8d806bfd749a5e8a
diff --git a/specs/freevga/vga/vgareg.htm b/specs/freevga/vga/vgareg.htm
new file mode 100644
index 0000000..45d3162
--- /dev/null
+++ b/specs/freevga/vga/vgareg.htm
@@ -0,0 +1,508 @@
+
+
+
+
+
+
+ VGA/SVGA Video Programming--Accessing the VGA Registers
+
+
+
+Home Intro Advice
+Fudge Paranoia External
+Indexed Attribute Color
+Binary Example Masking
+Back
+
Hardware Level VGA and SVGA Video Programming Information
+Page
+
+Accessing the VGA Registers
+
+
+
+Introduction
+
This section discusses methods
+of manipulating the particular registers present in VGA hardware. Depending
+upon which register one is accessing, the method of accessing them is different
+and sometimes difficult to understand. The VGA has many more registers
+than it has I/O ports, thus it must provide a way to re-use or multiplex
+many registers onto a relatively small number of ports. All of the VGA
+ports are accessed by inputting and outputting bytes to I/O ports; however,
+in many cases it is necessary to perform additional steps to ready the
+VGA adapter for reading and writing data. Port addresses are given at their
+hexadecimal address, such as 3C2h.
+
+General Advice
+
If a program takes
+control of the video card and changes its state, it is considered good
+programming practice to keep track of the original values of any register
+it changes such that upon termination (normal or abnormal) it can write
+them back to the hardware to restore the state. Anyone who has seen a graphics
+application abort in the middle of a graphics screen knows how annoying
+this can be. Almost all of the VGA registers can be saved and restored
+in this fashion. In addition when changing only a particular field of a
+register, the value of the register should be read and the byte should
+be masked so that only the field one is trying to change is actually changed.
+
+
I/O Fudge Factor
+
Often a hardware device
+is not capable handling I/O accesses as fast as the processor can issue
+them. In this case, a program must provide adequate delay between I/O accesses
+to the same device. While many modern chipsets provide this delay in hardware,
+there are still many implementations in existence that do not provide this
+delay. If you are attempting to write programs for the largest possible
+variety of hardware configurations, then it is necessary to know the amount
+of delay necessary. Unfortunately, this delay is not often specified, and
+varies from one VGA implementation to another. In the interest of performance
+it is ideal to keep this delay to the minimum necessary. In the interest
+of compatibility it is necessary to implement a delay independent of clock
+speed. (Faster processors are continuously being developed, and also a
+user may change clock speed dynamically via the Turbo button on their case.)
+
+
Paranoia
+
If one wishes to be extra
+cautious when writing to registers, after writing to a register one can
+read the value back and compare it with the original value. If they differ
+it may mean that the VGA hardware has a stuck bit in one its registers,
+that you are attempting to modify a locked or unsupported register, or
+that you are not providing enough delay between I/O accesses. As long as
+reading the register twice doesn't have any unintended side effects, when
+reading a registers value, one can read the register twice and compare
+the values read, after masking out any fields that may change without CPU
+intervention. If the values read back are different it may mean that you
+are not providing enough delay between I/O accesses, that the hardware
+is malfunctioning, or are reading the wrong register or field. Other problems
+that these techniques can address are noise on the I/O bus due to faulty
+hardware, dirty contacts, or even sunspots! When perform I/O operations
+and these checks fail, try repeating the operation, possibly with increased
+I/O delay time. By providing extra robustness, I have found that my own
+programs will work properly on hardware that causes less robust programs
+to fail.
+
+
Accessing the External Registers
+
The external registers are
+the easiest to program, because they each have their own separate I/O address.
+Reading and writing to them is as simple as inputting and outputting bytes
+to their respective port address. Note, however some, such as the Miscellaneous
+Output Register is written at port 3C2h, but is read at port 3CCh. The
+reason for this is for backwards compatibility with the EGA and previous
+adapters. Many registers in the EGA were write only, and thus the designers
+placed read-only registers at the same location as write-only ones. However,
+the biggest complaint programmers had with the EGA was the inability to
+read the EGA's video state and thus in the design of the VGA most of these
+write-only registers were changed to read/write registers. However, for
+backwards compatibility, the read-only register had to remain at 3C2h,
+so they used a different port.
+
+
Accessing the Sequencer, Graphics, and CRT
+Controller Registers
+
These registers are accessed
+in an indexed fashion. Each of the three have two unique read/write ports
+assigned to them. The first port is the Address Register for the group.
+The other is the Data Register for the group. By writing a byte to the
+Address Register equal to the index of the particular sub-register you
+wish to access, one can address the data pointed to by that index by reading
+and writing the Data Register. The current value of the index can be read
+by reading the Address Register. It is best to save this value and restore
+it after writing data, particularly so in an interrupt routine because
+the interrupted process may be in the middle of writing to the same register
+when the interrupt occurred. To read and write a data register in one of
+these register groups perform the following procedure:
+
+-
+Input the value of the Address Register and save it for step 6
+
+-
+Output the index of the desired Data Register to the Address Register.
+
+-
+Read the value of the Data Register and save it for later restoration upon
+termination, if needed.
+
+-
+If writing, modify the value read in step 3, making sure to mask off bits
+not being modified.
+
+-
+If writing, write the new value from step 4 to the Data register.
+
+-
+Write the value of Address register saved in step 1 to the Address Register.
+
+ If you are paranoid, then you
+might want to read back and compare the bytes written in step 2, 5, and
+6 as in the Paranoia section above. Note that certain
+CRTC registers can be protected from read or write access for compatibility
+with programs written prior to the VGA's existence. This protection is
+controlled via the Enable Vertical Retrace Access
+and CRTC Registers Protect Enable fields.
+Ensuring that access is not prevented even if your card does not normally
+protect these registers makes your
+
+Accessing the Attribute Registers
+
The attribute registers
+are also accessed in an indexed fashion, albeit in a more confusing way.
+The address register is read and written via port 3C0h. The data register
+is written to port 3C0h and read from port 3C1h. The index and the data
+are written to the same port, one after another. A flip-flop inside the
+card keeps track of whether the next write will be handled is an index
+or data. Because there is no standard method of determining the state of
+this flip-flop, the ability to reset the flip-flop such that the next write
+will be handled as an index is provided. This is accomplished by reading
+the Input Status #1 Register (normally port 3DAh) (the data received is
+not important.) This can cause problems with interrupts because there is
+no standard way to find out what the state of the flip-flop is; therefore
+interrupt routines require special card when reading this register. (Especially
+since the Input Status #1 Register's purpose is to determine whether a
+horizontal or vertical retrace is in progress, something likely to be read
+by an interrupt routine that deals with the display.) If an interrupt were
+to read 3DAh in the middle of writing to an address/data pair, then the
+flip-flop would be reset and the data would be written to the address register
+instead. Any further writes would also be handled incorrectly and thus
+major corruption of the registers could occur. To read and write an data
+register in the attribute register group, perform the following procedure:
+
+-
+Input a value from the Input Status #1 Register (normally port 3DAh) and
+discard it.
+
+-
+Read the value of the Address/Data Register and save it for step 7.
+
+-
+Output the index of the desired Data Register to the Address/Data Register
+
+-
+Read the value of the Data Register and save it for later restoration upon
+termination, if needed.
+
+-
+If writing, modify the value read in step 4, making sure to mask off bits
+not being modified.
+
+-
+If writing, write the new value from step 5 to the Address/Data register.
+
+-
+Write the value of Address register saved in step 1 to the Address/Data
+Register.
+
+-
+If you wish to leave the register waiting for an index, input a value from
+the Input Status #1 Register (normally port 3DAh) and discard it.
+
+ If you have control over interrupts,
+then you can disable interrupts while in the middle of writing to the register.
+If not, then you may be able to implement a critical section where you
+use a byte in memory as a flag whether it is safe to modify the attribute
+registers and have your interrupt routine honor this. And again, it pays
+to be paranoid. Resetting the flip-flop even though it should be
+in the reset state already helps prevent catastrophic problems. Also, you
+might want to read back and compare the bytes written in step 3, 6, and
+7 as in the Paranoia section above.
+
On the IBM VGA implementation,
+an undocumented register (CRTC Index=24h, bit 7) can be read to determine
+the status of the flip-flop (0=address,1=data) and many VGA compatible
+chipsets duplicate this behavior, but it is not guaranteed. However, it
+is a simple matter to determine if this is the case. Also, some SVGA chipsets
+provide the ability to access the attribute registers in the same fashion
+as the CRT, Sequencer, and Graphics controllers. Because this functionality
+is vendor specific it is really only useful when programming for that particular
+chipset. To determine if this undocumented bit is supported, perform the
+following procedure:
+
+-
+Input a value from the Input Status #1 Register (normally port 3DAh) and
+discard it.
+
+-
+Verify that the flip-flop status bit (CRTC Index 24, bit 7) is 0. If bit=1
+then feature is not supported, else continue to step 3.
+
+-
+Output an address value to the Attribute Address/Data register.
+
+-
+Verify that the flip-flop status bit (CRTC Index 24, bit 7) is 1. If bit=0
+then feature is not supported, else continue to step 5.
+
+-
+Input a value from the Input Status #1 Register (normally port 3DAh) and
+discard it.
+
+-
+Verify that the flip-flop status bit (CRTC Index 24, bit 7) is 0. If bit=1
+then feature is not supported, else feature is supported.
+
+Accessing the Color Registers
+
The color registers require an altogether
+different technique; this is because the 256-color palette requires 3 bytes
+to store 18-bit color values. In addition the hardware supports the capability
+to load all or portions of the palette rapidly. To write to the palette,
+first you must output the value of the palette entry to the PEL Address
+Write Mode Register (port 3C8h.) Then you should output the component values
+to the PEL Data Register (port 3C9h), in the order red, green, then blue.
+The PEL Address Write Mode Register will then automatically increment,
+allowing the component values of the palette entry to be written to the
+PEL Data Register. Reading is performed similarly, except that the PEL
+Address Read Mode Register (port 3C7h) is used to specify the palette entry
+to be read, and the values are read from the PEL Data Register. Again,
+the PEL Address Read Mode Register auto-increments after each triplet is
+written. The current index for the current operation can be read from the
+PEL Address Write Mode Register. Reading port 3C7h gives the DAC State
+Register, which specifies whether a read operation or a write operation
+is in effect. As in the attribute registers, there is guaranteed way for
+an interrupt routine to access the color registers and return the color
+registers to the state they were in prior to access without some communication
+between the ISR and the main program. For some workarounds see the Accessing
+the Attribute Registers section above. To read the color registers:
+
+-
+Read the DAC State Register and save the value for use in step 8.
+
+-
+Read the PEL Address Write Mode Register for use in step 8.
+
+-
+Output the value of the first color entry to be read to the PEL Address
+Read Mode Register.
+
+-
+Read the PEL Data Register to obtain the red component value.
+
+-
+Read the PEL Data Register to obtain the green component value.
+
+-
+Read the PEL Data Register to obtain the blue component value.
+
+-
+If more colors are to be read, repeat steps 4-6.
+
+-
+Based upon the DAC State from step 1, write the value saved in step 2 to
+either the PEL Address Write Mode Register or the PEL Address Read Mode
+Register.
+
+Note: Steps 1, 2, and 8 are hopelessly optimistic. This in no way guarantees
+that the state is preserved, and with some DAC implementations this may
+actually guarantee that the state is never preserved. See the DAC
+Operation page for more details.
+
+Binary Operations
+
In order to better
+understand dealing with bit fields it is necessary to know a little bit
+about logical operations such as logical-and (AND), logical-or (OR), and
+exclusive-or(XOR.) These operations are performed on a bit by bit basis
+using the truth tables below. All of these operations are commutative,
+i.e. A OR B = B OR A, so you look up one bit in the left column and the
+other in the top row and consult the intersecting row and column for the
+answer.
+
+
+
+AND |
+
+ |
+
+OR |
+
+ |
+
+XOR |
+
+
+
+ |
+
+0 |
+
+1 |
+
+ |
+
+ |
+
+0 |
+
+1 |
+
+ |
+
+ |
+
+0 |
+
+1 |
+
+
+
+0 |
+
+0 |
+
+0 |
+
+ |
+
+0 |
+
+0 |
+
+1 |
+
+ |
+
+0 |
+
+0 |
+
+1 |
+
+
+
+1 |
+
+0 |
+
+1 |
+
+ |
+
+1 |
+
+1 |
+
+1 |
+
+ |
+
+1 |
+
+1 |
+
+0 |
+
+
+
+Example Register
+
The following table is an
+example of one particular register, the Mode Register of the Graphics Register.
+Each number from 7-0 represents the bit position in the byte. Many registers
+contain more than one field, each of which performs a different function.
+This particular chart contains four fields, two of which are two bits in
+length. It also contains two bits which are not implemented (to the best
+of my knowledge) by the standard VGA hardware.
+
+
+Mode Register (Index 05h)
+
+
+7 |
+
+6 |
+
+5 |
+
+4 |
+
+3 |
+
+2 |
+
+1 |
+
+0 |
+
+
+
+ |
+
+Shift Register |
+
+Odd/Even |
+
+RM |
+
+ |
+
+Write Mode |
+
+
+
+Masking Bit-Fields
+
Your development environment
+may provide some assistance in dealing with bit fields. Consult your documentation
+for this. In addition it can be performed using the logical operators AND,
+OR, and XOR (for details on these operators see the Binary
+Operations section above.) To change the value of the Shift Register
+field of the example register above, we would first mask out the bits we
+do not wish to change. This is accomplished by performing a logical AND
+of the value read from the register and a binary value in which all of
+the bits we wish to leave alone are set to 1, which would be 10011111b
+for our example. This leaves all of the bits except the Shift Register
+field alone and set the Shift Register field to zero. If this was our goal,
+then we would stop here and write the value back to the register. We then
+OR the value with a binary number in which the bits are shifted into position.
+To set this field to 10b we would OR the result of the AND with 01000000b.
+The resulting byte would then be written to the register. To set a bitfield
+to all ones the AND step is not necessary, similar to setting the bitfield
+to all zeros using AND. To toggle a bitfield you can XOR a value with a
+byte with a ones in the positions to toggle. For example XORing the value
+read with 01100000b would toggle the value of the Shift Register bitfield.
+By using these techniques you can assure that you do not cause any unwanted
+"side-effects" when modifying registers.
+
+Notice: All trademarks used or referred to on this page are the property
+of their respective owners.
+
All pages are Copyright © 1997, 1998, J. D. Neal, except where
+noted. Permission for utilization and distribution is subject to the terms
+of the FreeVGA Project Copyright License.
+
+
+
+