gateA20.c File Reference

#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 Documentation

#define K_RDWR   0x60

Definition at line 9 of file gateA20.c.

Referenced by empty_8042(), and gateA20_set().

#define K_STATUS   0x64

Definition at line 10 of file gateA20.c.

#define K_CMD   0x64

Definition at line 11 of file gateA20.c.

Referenced by empty_8042(), and gateA20_set().

#define K_OBUF_FUL   0x01

Definition at line 13 of file gateA20.c.

Referenced by empty_8042().

#define K_IBUF_FUL   0x02

Definition at line 14 of file gateA20.c.

Referenced by empty_8042().

#define KC_CMD_WIN   0xd0

Definition at line 16 of file gateA20.c.

#define KC_CMD_WOUT   0xd1

Definition at line 17 of file gateA20.c.

Referenced by gateA20_set().

#define KC_CMD_NULL   0xff

Definition at line 18 of file gateA20.c.

Referenced by gateA20_set().

#define KB_SET_A20   0xdf

Definition at line 19 of file gateA20.c.

Referenced by gateA20_set().

#define KB_UNSET_A20   0xdd

Definition at line 23 of file gateA20.c.

#define SCP_A   0x92

Definition at line 28 of file gateA20.c.

Referenced by gateA20_set().

#define A20_MAX_RETRIES   32

Definition at line 40 of file gateA20.c.

Referenced by gateA20_set().

#define A20_INT15_RETRIES   32

Definition at line 41 of file gateA20.c.

Referenced by gateA20_set().

#define A20_KBC_RETRIES   (2^21)

Definition at line 42 of file gateA20.c.

Referenced by gateA20_set().

#define A20_SCPA_RETRIES   (2^21)

Definition at line 43 of file gateA20.c.

Referenced by gateA20_set().


Enumeration Type Documentation

anonymous enum

Enumerator:
Disable_A20 
Enable_A20 
Query_A20_Status 
Query_A20_Support 

Definition at line 30 of file gateA20.c.

00030      { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402,
00031         Query_A20_Support = 0x2403 };

Enumerator:
A20_UNKNOWN 
A20_INT15 
A20_KBC 
A20_SCPA 

Definition at line 33 of file gateA20.c.

00033                  {
00034         A20_UNKNOWN = 0,
00035         A20_INT15,
00036         A20_KBC,
00037         A20_SCPA,
00038 };


Function Documentation

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.

Parameters:
retries Number of times to retry before giving up
Return values:
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   ) 

Definition at line 174 of file gateA20.c.

Referenced by nbi_boot16().

00174                             {
00175         /* Not currently implemented */
00176 }


Generated on Tue Apr 6 20:01:12 2010 for gPXE by  doxygen 1.5.7.1