For compatibility reasons many IBM-compatible PCs start with address line 20 disabled. Unfortunately many different methods have been proposed to ensure it is enabled. The text below sets out some questions and answers on the issues arising from the way that A20 is controlled.
This it is not a written guide. It is a collection of notes on some of the obscure issues involved. Detailed knowledge of the problem is assumed.
There is a proposed A20 sequence.
Address line 20 is traditionally in a disabled state at the point where an OS boot loader gets control but on some machines it will be enabled. These seem to be more modern machines which do away with the old compatibility.
In either case the OS writer, i.e. you!, must ensure that A20 is enabled before switching to protected mode. The behaviour of a number of CPUs is undefined if A20 has not been enabled first.
For an overview of how the state of A20 is likely to vary on different hardware take a look at the A20 section of machine-characteristics.
Which levels of cache respond to the gated A20?
- CPUs from the 486 onward have an A20 enable input
- A masked A20 should therefore be forced to zero at all cache levels including those within the CPU
Which addresses does it apply to?
- The A20 mask applies to CPU-generated addresses
- DMA does not mask A20 or honour the mask bit - See Intel386 EX Embedded Microprocessor User's Manual
Various means of control are shown below. The most complex is also the most widely supported.
Detecting Enable State
Before looking at how to enable A20 this section considers how to verify whether it is enabled or not, or has been enabled successfully.
Checking the bit in the kbc output port is reputed to be not reliable on all machines and will certainly only work on machines which have or emulate a keyboard controller.
On 486 and later wbinvd can be used to clear internal cache levels
- External caches will respond similarly - as long as the external hardware is compliant
Cache hardware may misbehave - http://groups.google.co.uk/group/fa.linux.kernel/msg/181c41358edfa23d?hl=en&dmode=source
Ideally there would be one way to enable A20 which would work on all machines. For various reasons that is not the case and an OS which wants to work on many different machines would need to adapt. MS-DOS reputedly had to include code for fourteen different methods though some of these may be differences of timing.
A20 should be active if it has been successfully enabled in either
- the kbc or
- system control port A
Only one of these ports is needed, not both
- Note under A20M# that A20M will wrap (A20 will be forced to zero) only if both the KBC and the PS/2 port (port A) are low (zero).
Most machines either have a keyboard controller or emulate one. A few machines such as those for embedded use may neither have a keyboard controller nor emulate one.
Some machines have a system control port A.
Some machines can enable A20 via the BIOS.
After enabling A20 with an out instruction a serialising instruction is needed (Pentium 1 manual)
- A serialising instruction will already be part of the sequence to enable protected mode
- Such as move to control register
Using the Keyboard Controller (kbc) 0x60, 0x64
- This is the original method
- Specifically recognised and emulated by some USB controllers (see below)
- Apparently required on some machines in order to allow suspend/resume as they fail to save and restore the state of 0x92
- Slow on some Toshiba laptops
- Unclear whether
- status bits 0x64 can take longer than 64k iterations or
- gate is slow to respond once the new value has been accepted by the controller
- Unclear whether
- May not be present if the machine does not have a keyboard controller
- Options to detect the presence of the kbc in approximate order
- Check BIOS call 0x15-2403, if supported
- Check a read of 0x64 gives sensible results
- Issue self-check and wait for and confirm results
- Issue loopback and check response
- Does not require a keyboard, is a keyboard controller function
Accessing the keyboard controller
The status register has a bit, bit 0, which it sets when it has a byte waiting to be read - such as the response to a command or a byte from the keyboard or the mouse. If you choose to read anything from the controller (such as the preexisting A20 enable bit) wait first for this bit to be set to one and wait a further seven microseconds if you could be dealing with a type 1 controller. See ibm-kadc.
The process of enabling A20 via the keyboard controller requires writing byte values to its ports. The controller can only receive one byte at a time. When a byte is received the controller sets bit 1 in its status register to indicate is unable to receive another byte. Before writing each byte to the controller wait until this bit is zero.
The MCA and PS/2 manual says both bits should show zero: "Address hex 0060 and address hex 0064 should be written to only when the input-buffer-full bit and output-buffer-full bit in the Controller Status register are set to 0." See ibm-kadc. No explanation is given as to why the output buffer should be empty.
The Linux routine to enable A20 calls a routine called empty_8042 to wait for both bits to show empty before writing.
Using System Control Port A 0x92
- Detecting the presence of port A in order
- May be hard to detect before writing to it
- Check BIOS call 0x15-2403, if supported
- Check a read of port A gives sane results
- Added method known as fast A20
- May not be saved by some BIOSes over suspend/resume. If unsure use kbc
Using the BIOS
- Some BIOSes support int 0x15-24 which has these calls (data from RBIL)
* 0x15-2400 - Disable A20
* 0x15-2401 - Enable A20
* 0x15-2402 - Is A20 enabled or disabled?
* 0x15-2403 - Query A20 gate support
- The enable call can apparently fail because the kbc is in "secure" mode (RBIL)
- It is not clear why 0x92 is not tried in that case
- The Query call, if supported, can report in BX whether A20 can be controlled by:
- Bit 0 - keyboard controller
- Bit 1 - System Control Port A
- This may be useful as a hint
Dealing with USB UHCI
- Has a specified sequence for fast switching
- Unclear whether reading 0x64 will break the start of the sequence
- Unclear what will happen if the sequence is broken but the steps are correct
- Is this just slower or
- will it fail to enable A20
Dealing with USB OHCI
How is A20 enabled where there is a OHCI keyboard controller?
Machines which apparently require careful treatment
Toshiba Tecra 710CDT
- On first read of 1M both bytes are incorrect
- On subsequent read they are correct
Asus P55TP5XE boards (Triton I chipset)
- On first read of 1M the first byte is incorrect
- The HP Vectra apparently allows
- Write 0xdd to port 0x64 to disable A20
- Write 0xdf to port 0x64 to enable A20
- However these steps may hang other machines
- 0xdd and 0xdf are not standard commands
- see kbc-commands
- Apparently allows
- write of 0x90 to 0x3f20 to enable A20
- write of 0x00 to 0x3f20 to disable A20
- It is not clear whether the AT&T 6300+ will accept kbc or port A methods