📄 ps2_kbd.c
字号:
//==========================================================================
//
// ps2_kbd.c
//
// PS/2 Keyboard Controller Code
//
// Author(s): Michael Kelly, Cogent Computer Systems, Inc.
// Contributors:
// Date: 02/05/2002
// Description: This file contains Code to intialize the Holtek HT6542
// Keyboard Controller for keyboard operation as well
// as a basic scan code to ascii converter suitable as an
// input device
//
//--------------------------------------------------------------------------
#include "config.h"
#if INCLUDE_PS2KBD
#include "cpuio.h"
#include "stddefs.h"
#include "genlib.h"
#include "ps2_kbd.h"
//--------------------------------------------------------------------------
// Function Prototypes
//
int ps2_kbd_init(void);
void ps2_kbd_test(void);
void ps2_kbd_obf_flush(void);
vulong wait_ps2_kbd_ibf_clr(void);
vulong wait_ps2_kbd_ibf_set(void);
vulong wait_ps2_kbd_obf_clr(void);
vulong wait_ps2_kbd_obf_set(void);
vulong ps2_gotachar(void);
vuchar ps2_getchar(void);
vuchar ps2_scan(void);
int ps2_tst(void);
//--------------------------------------------------------------------------
// Global to hold the state of the interface
//
static vulong ps2_kbd_ok;
static vuchar ps2_ctl_flag, ps2_alt_flag, ps2_shift_flag;
static vuchar ps2_led_flag, ps2_break_c;
//--------------------------------------------------------------------------
// Globals to hold the ps2 character and status
//
static vuchar ps2_char, ps2_char_ok;
//--------------------------------------------------------------------------
// ps2_kbd_init()
//
// The following function initializes the PS/2 Controller and performs a
// a simple self test. The global, ps2_kbd_ok, will be set based
// on the results. This allows the ascii routine to determine
// if a keyboard (or even the keyboard controller) is present.
//
// Notes:
//
// 1. There are two peripherals we are communicating with. The first
// is the PS/2 controller itself located on the motherboard. The
// second is the PS/2 keyboard connected via the Data/Clock pin.
//
// 2. The term "output buffer" refers to the buffer that the PS/2
// controller uses to send data to the CPU. From our sw point
// of view it is the input to us. But to prevent even more
// confusion, we maintain that designation. Likewise, the
// "input buffer" refers to the location where the host places
// commands to the PS/2 controller.
//
// 3. The keyboard is communicated with via the Data port when we
// have established communication with a keyboard
//
int ps2_kbd_init()
{
vuchar temp8;
int retry;
ps2_kbd_ok = 0;
retry = 10;
while(retry)
{
// flush the output buffer first
ps2_kbd_obf_flush();
// turn the keyboard port off then on
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_CMD) = PS2_CMD_KBD_OFF;
monDelay (100);
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_CMD) = PS2_CMD_KBD_ON;
ps2_kbd_obf_flush();
#ifdef PS2_DEBUG
printf("PS2 Controller Self Test - Sent: %02x\n", PS2_CMD_DIAG);
#endif
// Send the Diagnostic Command
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_CMD) = PS2_CMD_DIAG;
// check the results
if (wait_ps2_kbd_obf_set()) return -1;
temp8 = PS2_REG(PS2_DATA);
if (temp8 != PS2_KBD_STAT_DIAG_OK) {
printf("PS2 Controller Self Test - Fail: %x\n", temp8);
return -1;
}
#ifdef PS2_DEBUG
printf("PS2 Controller Self Test - Pass: %02x\n", temp8);
printf("PS2 Controller Enable Keyboard: %02x\n", PS2_CMD_KBD_ON);
#endif
// Enable the Keyboard Port on the PS controller itself
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_CMD) = PS2_CMD_KBD_ON;
ps2_kbd_obf_flush();
// Send a Reset command to the keyboard
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_RST;
// wait until we get a response, then check for timeout
if (wait_ps2_kbd_obf_set()) return -1;
temp8 = PS2_REG(PS2_STAT);
if (temp8 & (PS2_STAT_TX | PS2_STAT_RX)){
// did we get a re-send?
temp8 = PS2_REG(PS2_DATA);
if (temp8 != PS2_KBD_STAT_RESEND) continue;
}
else
{
// now check for ack
temp8 = PS2_REG(PS2_DATA);
if (temp8 == PS2_KBD_STAT_ACK) break;
}
#ifdef PS2_DEBUG
printf("PS2 Keyboard - Re-sending Reset\n");
#endif
retry--;
} // while retry
if (retry == 0){
#ifdef PS2_DEBUG
printf("Keyboard Reset Failed. No Keyboard Connected?\n");
#endif
return -1;
}
// If we got an ACK, the next byte should be Reset OK
if (wait_ps2_kbd_obf_set()) return -1;
temp8 = PS2_REG(PS2_DATA);
if (temp8 != PS2_KBD_STAT_RST_OK)
{
#ifdef PS2_DEBUG
printf("Keyboard Reset Failed - Expected Reset OK: got: %02x\n", temp8);
#endif
return -1;
}
#ifdef PS2_DEBUG
printf("PS2 Keyboard Reset - Received OK\n");
#endif
// Set the keyboard to scan mode 1
// First Flush the Output Buffer - The keyboard may have
// sent us scan codes already
ps2_kbd_obf_flush();
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_MODE;
// Again, flush the Input Buffer
ps2_kbd_obf_flush();
if (wait_ps2_kbd_ibf_clr()) return -1;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_MODE_SCAN1;
printf("PS/2 Keyboard found and initialized.\n");
// initialize the globals
ps2_kbd_ok = 1;
ps2_char = 0;
ps2_char_ok = 0;
ps2_shift_flag = 0;
ps2_alt_flag = 0;
ps2_ctl_flag = 0;
ps2_led_flag = 0;
return 0;
}
//--------------------------------------------------------------------------
// wait_ps2_kbd_ibf_set()
//
// This routine waits until the Input Buffer Flag is Set,
// or time's out.
vulong wait_ps2_kbd_ibf_set()
{
int timeout;
// check the results
timeout = PS2_TIMEOUT;
while(timeout){
// delay before each check
monDelay(1);
if(PS2_REG(PS2_STAT) & PS2_STAT_IBF) break;
timeout--;
}
if (timeout == 0){
ps2_kbd_ok = 0;
printf("PS2 Wait for Input Buffer Flag Set Timed Out - Controller Failure?\n");
return 1;
}
return 0;
}
//--------------------------------------------------------------------------
// wait_ps2_kbd_ibf_clr()
//
// This routine waits until the Input Buffer Flag is Clear,
// or time's out.
vulong wait_ps2_kbd_ibf_clr()
{
int timeout;
// check the results
timeout = PS2_TIMEOUT;
while(timeout){
// delay before each check
monDelay(1);
if((PS2_REG(PS2_STAT) & PS2_STAT_IBF) == 0) break;
timeout--;
}
if (timeout == 0){
ps2_kbd_ok = 0;
printf("PS2 Wait for Input Buffer Flag Clear Timed Out - Controller Failure?\n");
return 1;
}
return 0;
}
//--------------------------------------------------------------------------
// ps2_kbd_obf_flush()
//
// This routine waits until the Output Buffer Flag is Clear,
// by reading the data port continuously
void ps2_kbd_obf_flush()
{
// Clear the Output Buffer
while ((PS2_REG(PS2_STAT) & PS2_STAT_OBF)) {
PS2_REG(PS2_DATA);
}
}
//--------------------------------------------------------------------------
// wait_ps2_kbd_obf_clr()
//
// This routine waits until the Output Buffer Flag is Cleared,
// or time's out
vulong wait_ps2_kbd_obf_clr()
{
int timeout;
// check the results
timeout = PS2_TIMEOUT;
while(timeout){
// delay before each check
monDelay(1);
if ((PS2_REG(PS2_STAT) & PS2_STAT_OBF) == 0) break;
timeout--;
}
if (timeout == 0){
ps2_kbd_ok = 0;
printf("PS2 Wait for Output Buffer Flag Clear Timed Out - Controller Failure?\n");
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -