/*
* $Id$
*/
#include <pc.h>
#include <go32.h>
#include <bsp.h>
/*
* Ports for PC keyboard
*/
#define KBD_CTL 0x61
#define KBD_DATA 0x60
#define KBD_STATUS 0x64
static char key_map[] = {
0,033,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',
'q','w','e','r','t','y','u','i','o','p','[',']',015,0x80,
'a','s','d','f','g','h','j','k','l',';',047,0140,0x80,
0134,'z','x','c','v','b','n','m',',','.','/',0x80,
'*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,'0',0177
};
static char shift_map[] = {
0,033,'!','@','#','$','%','^','&','*','(',')','_','+','\b','\t',
'Q','W','E','R','T','Y','U','I','O','P','{','}',015,0x80,
'A','S','D','F','G','H','J','K','L',':',042,'~',0x80,
'|','Z','X','C','V','B','N','M','<','>','?',0x80,
'*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,'7','8','9',0x80,'4','5','6',0x80,
'1','2','3','0',177
};
extern int _IBMPC_Use_Go32_IO;
#define KBD_BUF_SIZE 256
static char kbd_buffer[ KBD_BUF_SIZE ];
static unsigned int kbd_first = 0;
static unsigned int kbd_last = 0;
/* This function can be called during a poll for input, or by an ISR. */
/* Basically any time you want to process a keypress. */
int _IBMPC_scankey( char * ch )
{
unsigned char c;
unsigned char outch;
static int shift_pressed = 0;
static int ctrl_pressed = 0;
static int caps_pressed = 0;
/* Read keyboard controller, toggle enable */
inport_byte( KBD_CTL, c );
outport_byte( KBD_CTL, c & ~0x80 );
outport_byte( KBD_CTL, c | 0x80 );
outport_byte( KBD_CTL, c & ~0x80 );
/* See if it has data */
inport_byte( KBD_STATUS, c );
if ( ( c & 0x01 ) == 0 )
return 0;
/* Read the data. Handle nonsense with shift, control, etc. */
inport_byte( KBD_DATA, c );
switch ( c ) {
case 0x36:
case 0x2a:
shift_pressed = 1;
return 0;
case 0x3a:
caps_pressed = 1;
return 0;
case 0x1d:
ctrl_pressed = 1;
return 0;
case 0xb6:
case 0xaa:
shift_pressed = 0;
return 0;
case 0xba:
caps_pressed = 0;
return 0;
case 0x9d:
ctrl_pressed = 0;
return 0;
/*
* Ignore unrecognized keys--usually arrow and such
*/
default:
if ( c & 0x80 )
/* High-bit on means key is being released, not pressed */
return 0;
if ( c == 88 )
/* F12 - abort */
exit( 1 );
if ( c > 0x39 ) {
return 0;
}
}
/* Strip high bit, look up in our map */
c &= 127;
if ( ctrl_pressed ) {
outch = key_map[c];
outch &= 037;
} else {
outch = shift_pressed ? shift_map[c] : key_map[c];
if ( caps_pressed ) {
if ( outch >= 'A' && outch <= 'Z' ) outch += 'a' - 'A';
else if ( outch >= 'a' && outch <= 'z' ) outch -= 'a' - 'A';
}
}
*ch = outch;
return 1;
}
void _IBMPC_keyboard_isr( rtems_unsigned32 interrupt )
{
if ( _IBMPC_scankey( & kbd_buffer[ kbd_last ] ) ) {
/* Got one; save it if there is enough room in buffer. */
unsigned int next = (kbd_last + 1) % KBD_BUF_SIZE;
if ( next != kbd_first )
kbd_last = next;
}
/* Mark interrupt as handled */
outport_byte( 0x20, 0x20 );
}
int _IBMPC_chrdy( char * ch )
{
if ( _IBMPC_Use_Go32_IO ) {
/* Read keyboard via BIOS: raw mode. */
if ( kbhit() ) {
*ch = getkey();
return 1;
} else {
return 0;
}
} else {
/* Check buffer our ISR builds */
if ( kbd_first != kbd_last ) {
*ch = kbd_buffer[ kbd_first ];
kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
return 1;
} else {
return 0;
}
}
}
int _IBMPC_inch( void )
{
char Ch;
while ( ! _IBMPC_chrdy( & Ch ) )
continue;
return Ch;
}