#include <stdio.h>#include <realmode.h>#include <bios.h>#include <gpxe/io.h>#include <gpxe/timer.h>Go to the source code of this file.
Defines | |
| #define | K_RDWR 0x60 |
| #define | K_STATUS 0x64 |
| #define | K_CMD 0x64 |
| #define | K_OBUF_FUL 0x01 |
| #define | K_IBUF_FUL 0x02 |
| #define | KC_CMD_WIN 0xd0 |
| #define | KC_CMD_WOUT 0xd1 |
| #define | KC_CMD_NULL 0xff |
| #define | KB_SET_A20 0xdf |
| #define | KB_UNSET_A20 0xdd |
| #define | SCP_A 0x92 |
| #define | A20_MAX_RETRIES 32 |
| #define | A20_INT15_RETRIES 32 |
| #define | A20_KBC_RETRIES (2^21) |
| #define | A20_SCPA_RETRIES (2^21) |
Enumerations | |
| enum | { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402, Query_A20_Support = 0x2403 } |
| enum | a20_methods { A20_UNKNOWN = 0, A20_INT15, A20_KBC, A20_SCPA } |
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static void | empty_8042 (void) |
| Drain keyboard controller. | |
| static int | gateA20_is_set (int retries) |
| Fast test to see if gate A20 is already set. | |
| void | gateA20_set (void) |
| void | gateA20_unset (void) |
| #define K_RDWR 0x60 |
| #define K_CMD 0x64 |
| #define K_OBUF_FUL 0x01 |
| #define K_IBUF_FUL 0x02 |
| #define KC_CMD_WOUT 0xd1 |
| #define KC_CMD_NULL 0xff |
| #define KB_SET_A20 0xdf |
| #define SCP_A 0x92 |
| #define A20_MAX_RETRIES 32 |
| #define A20_INT15_RETRIES 32 |
| #define A20_KBC_RETRIES (2^21) |
| #define A20_SCPA_RETRIES (2^21) |
| anonymous enum |
Definition at line 30 of file gateA20.c.
00030 { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402, 00031 Query_A20_Support = 0x2403 };
| enum a20_methods |
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static void empty_8042 | ( | void | ) | [static] |
Drain keyboard controller.
Definition at line 48 of file gateA20.c.
References currticks(), inb, inb_p, iodelay(), K_CMD, K_IBUF_FUL, K_OBUF_FUL, K_RDWR, TICKS_PER_SEC, and time().
Referenced by gateA20_set().
00048 { 00049 unsigned long time; 00050 00051 time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */ 00052 while ( ( inb ( K_CMD ) & ( K_IBUF_FUL | K_OBUF_FUL ) ) && 00053 currticks() < time ) { 00054 iodelay(); 00055 ( void ) inb_p ( K_RDWR ); 00056 iodelay(); 00057 } 00058 }
| static int gateA20_is_set | ( | int | retries | ) | [static] |
Fast test to see if gate A20 is already set.
| retries | Number of times to retry before giving up |
| set | Gate A20 is set |
Definition at line 66 of file gateA20.c.
References copy_from_user(), iodelay(), phys_to_user(), and virt_to_phys().
Referenced by gateA20_set().
00066 { 00067 static uint32_t test_pattern = 0xdeadbeef; 00068 physaddr_t test_pattern_phys = virt_to_phys ( &test_pattern ); 00069 physaddr_t verify_pattern_phys = ( test_pattern_phys ^ 0x100000 ); 00070 userptr_t verify_pattern_user = phys_to_user ( verify_pattern_phys ); 00071 uint32_t verify_pattern; 00072 00073 do { 00074 /* Check for difference */ 00075 copy_from_user ( &verify_pattern, verify_pattern_user, 0, 00076 sizeof ( verify_pattern ) ); 00077 if ( verify_pattern != test_pattern ) 00078 return 1; 00079 00080 /* Avoid false negatives */ 00081 test_pattern++; 00082 00083 iodelay(); 00084 00085 /* Always retry at least once, to avoid false negatives */ 00086 } while ( retries-- >= 0 ); 00087 00088 /* Pattern matched every time; gate A20 is not set */ 00089 return 0; 00090 }
| void gateA20_set | ( | void | ) |
Definition at line 100 of file gateA20.c.
References __asm__(), A20_INT15, A20_INT15_RETRIES, A20_KBC, A20_KBC_RETRIES, A20_MAX_RETRIES, A20_SCPA, A20_SCPA_RETRIES, A20_UNKNOWN, DBG, empty_8042(), Enable_A20, gateA20_is_set(), inb, iodelay(), K_CMD, K_RDWR, KB_SET_A20, KC_CMD_NULL, KC_CMD_WOUT, outb, printf(), REAL_CODE, and SCP_A.
Referenced by nbi_boot16(), pxeparent_call(), and undi_load().
00100 { 00101 static char reentry_guard = 0; 00102 static int a20_method = A20_UNKNOWN; 00103 unsigned int discard_a; 00104 unsigned int scp_a; 00105 int retries = 0; 00106 00107 /* Avoid potential infinite recursion */ 00108 if ( reentry_guard ) 00109 return; 00110 reentry_guard = 1; 00111 00112 /* Fast check to see if gate A20 is already enabled */ 00113 if ( gateA20_is_set ( 0 ) ) 00114 goto out; 00115 00116 for ( ; retries < A20_MAX_RETRIES ; retries++ ) { 00117 switch ( a20_method ) { 00118 case A20_UNKNOWN: 00119 case A20_INT15: 00120 /* Try INT 15 method */ 00121 __asm__ __volatile__ ( REAL_CODE ( "int $0x15" ) 00122 : "=a" ( discard_a ) 00123 : "a" ( Enable_A20 ) ); 00124 if ( gateA20_is_set ( A20_INT15_RETRIES ) ) { 00125 DBG ( "Enabled gate A20 using BIOS\n" ); 00126 a20_method = A20_INT15; 00127 goto out; 00128 } 00129 /* fall through */ 00130 case A20_KBC: 00131 /* Try keyboard controller method */ 00132 empty_8042(); 00133 outb ( KC_CMD_WOUT, K_CMD ); 00134 empty_8042(); 00135 outb ( KB_SET_A20, K_RDWR ); 00136 empty_8042(); 00137 outb ( KC_CMD_NULL, K_CMD ); 00138 empty_8042(); 00139 if ( gateA20_is_set ( A20_KBC_RETRIES ) ) { 00140 DBG ( "Enabled gate A20 using " 00141 "keyboard controller\n" ); 00142 a20_method = A20_KBC; 00143 goto out; 00144 } 00145 /* fall through */ 00146 case A20_SCPA: 00147 /* Try "Fast gate A20" method */ 00148 scp_a = inb ( SCP_A ); 00149 scp_a &= ~0x01; /* Avoid triggering a reset */ 00150 scp_a |= 0x02; /* Enable A20 */ 00151 iodelay(); 00152 outb ( scp_a, SCP_A ); 00153 iodelay(); 00154 if ( gateA20_is_set ( A20_SCPA_RETRIES ) ) { 00155 DBG ( "Enabled gate A20 using " 00156 "Fast Gate A20\n" ); 00157 a20_method = A20_SCPA; 00158 goto out; 00159 } 00160 } 00161 } 00162 00163 /* Better to die now than corrupt memory later */ 00164 printf ( "FATAL: Gate A20 stuck\n" ); 00165 while ( 1 ) {} 00166 00167 out: 00168 if ( retries ) 00169 DBG ( "%d attempts were required to enable A20\n", 00170 ( retries + 1 ) ); 00171 reentry_guard = 0; 00172 }
| void gateA20_unset | ( | void | ) |
1.5.7.1