diff options
Diffstat (limited to 'c/src/lib/libbsp/i386/go32/console/inch.c')
-rw-r--r-- | c/src/lib/libbsp/i386/go32/console/inch.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/go32/console/inch.c b/c/src/lib/libbsp/i386/go32/console/inch.c new file mode 100644 index 0000000000..992723a4a0 --- /dev/null +++ b/c/src/lib/libbsp/i386/go32/console/inch.c @@ -0,0 +1,163 @@ +/* + * $Id$ + */ + +#include <pc.h> +#include <go32.h> +#include <bsp.h> +#include <cpu.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; +} |