diff options
Diffstat (limited to 'bsps/i386/pc386/console/inch.c')
-rw-r--r-- | bsps/i386/pc386/console/inch.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/bsps/i386/pc386/console/inch.c b/bsps/i386/pc386/console/inch.c new file mode 100644 index 0000000000..f5d5079236 --- /dev/null +++ b/bsps/i386/pc386/console/inch.c @@ -0,0 +1,300 @@ +/*-------------------------------------------------------------------------+ +| inch.c v1.1 - PC386 BSP - 1997/08/07 ++--------------------------------------------------------------------------+ +| (C) Copyright 1997 - +| - NavIST Group - Real-Time Distributed Systems and Industrial Automation +| +| http://pandora.ist.utl.pt +| +| Instituto Superior Tecnico * Lisboa * PORTUGAL ++--------------------------------------------------------------------------+ +| Disclaimer: +| +| This file is provided "AS IS" without warranty of any kind, either +| expressed or implied. ++--------------------------------------------------------------------------+ +| This code is based on: +| inch.c,v 1.3 1995/12/19 20:07:25 joel Exp - go32 BSP +| With the following copyright notice: +| With the following copyright notice: +| ************************************************************************** +| * COPYRIGHT (c) 1989-1998. +| * On-Line Applications Research Corporation (OAR). +| * +| * The license and distribution terms for this file may be +| * found in the file LICENSE in this distribution or at +| * http://www.rtems.org/license/LICENSE. +| ************************************************************************** ++--------------------------------------------------------------------------*/ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> + +/*-------------------------------------------------------------------------+ +| Constants ++--------------------------------------------------------------------------*/ +#define KBD_CTL 0x61 /* -------------------------------- */ +#define KBD_DATA 0x60 /* Ports for PC keyboard controller */ +#define KBD_STATUS 0x64 /* -------------------------------- */ + +#define KBD_BUF_SIZE 256 + +/*-------------------------------------------------------------------------+ +| Global Variables ++--------------------------------------------------------------------------*/ +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 +}; /* Keyboard scancode -> character map with no modifiers. */ + +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 +}; /* Keyboard scancode -> character map with SHIFT key modifier. */ + +static unsigned short kbd_buffer[KBD_BUF_SIZE]; +static uint16_t kbd_first = 0; +static uint16_t kbd_last = 0; +static uint16_t kbd_end = KBD_BUF_SIZE - 1; + +/*-------------------------------------------------------------------------+ +| Function: _IBMPC_scankey +| Description: This function can be called during a poll for input, or by +| an ISR. Basically any time you want to process a keypress. +| Global Variables: key_map, shift_map. +| Arguments: outChar - character read in case of a valid reading, +| otherwise unchanged. +| Returns: TRUE in case a valid character has been read, +| FALSE otherwise. ++--------------------------------------------------------------------------*/ +static bool +_IBMPC_scankey(char *outChar) +{ + unsigned char inChar; + static int alt_pressed = 0; + static int ctrl_pressed = 0; + static int shift_pressed = 0; + static int caps_pressed = 0; + static int extended = 0; + + *outChar = '\0'; /* default value if we return false */ + + /* Read keyboard controller, toggle enable */ + inport_byte(KBD_CTL, inChar); + outport_byte(KBD_CTL, inChar & ~0x80); + outport_byte(KBD_CTL, inChar | 0x80); + outport_byte(KBD_CTL, inChar & ~0x80); + + /* See if it has data */ + inport_byte(KBD_STATUS, inChar); + if ((inChar & 0x01) == 0) + return false; + + /* Read the data. Handle nonsense with shift, control, etc. */ + inport_byte(KBD_DATA, inChar); + + if (extended) + extended--; + + switch (inChar) + { + case 0xe0: + extended = 2; + return false; + break; + + case 0x38: + alt_pressed = 1; + return false; + break; + case 0xb8: + alt_pressed = 0; + return false; + break; + + case 0x1d: + ctrl_pressed = 1; + return false; + break; + case 0x9d: + ctrl_pressed = 0; + return false; + break; + + case 0x2a: + if (extended) + return false; + case 0x36: + shift_pressed = 1; + return false; + break; + case 0xaa: + if (extended) + return false; + case 0xb6: + shift_pressed = 0; + return false; + break; + + case 0x3a: + caps_pressed = 1; + return false; + break; + case 0xba: + caps_pressed = 0; + return false; + break; + + case 0x53: + if (ctrl_pressed && alt_pressed) + bsp_reset(); /* ctrl+alt+del -> reboot */ + break; + + /* + * Ignore unrecognized keys--usually arrow and such + */ + default: + if ((inChar & 0x80) || (inChar > 0x39)) + /* High-bit on means key is being released, not pressed */ + return false; + break; + } /* switch */ + + /* Strip high bit, look up in our map */ + inChar &= 0x7f; + if (ctrl_pressed) + { + *outChar = key_map[inChar]; + *outChar &= 037; + } + else + { + *outChar = shift_pressed ? shift_map[inChar] : key_map[inChar]; + if (caps_pressed) + { + if (*outChar >= 'A' && *outChar <= 'Z') + *outChar += 'a' - 'A'; + else if (*outChar >= 'a' && *outChar <= 'z') + *outChar -= 'a' - 'A'; + } + } + + return true; +} /* _IBMPC_scankey */ + +/*-------------------------------------------------------------------------+ +| Function: _IBMPC_chrdy +| Description: Check keyboard ISR buffer and return character if not empty. +| Global Variables: kbd_buffer, kbd_first, kbd_last. +| Arguments: c - character read if keyboard buffer not empty, otherwise +| unchanged. +| Returns: TRUE if keyboard buffer not empty, FALSE otherwise. ++--------------------------------------------------------------------------*/ +static bool +_IBMPC_chrdy(char *c) +{ +#if CCJ_REMOVED_NO_IDEA_ABOUT_THIS_CODE_OR_COMMENT + /* FIX ME!!! It doesn't work without something like the following line. + Find out why! */ + printk(""); +#endif + + /* Check buffer our ISR builds */ + if (kbd_first != kbd_last) + { + *c = kbd_buffer[kbd_first]; + + kbd_first = (kbd_first + 1) % KBD_BUF_SIZE; + return true; + } + else + return false; +} /* _IBMPC_chrdy */ + +/*-------------------------------------------------------------------------+ +| Function: _IBMPC_inch +| Description: Poll keyboard until a character is ready and return it. +| Global Variables: None. +| Arguments: None. +| Returns: character read from keyboard. ++--------------------------------------------------------------------------*/ +char +_IBMPC_inch(void) +{ + char c; + while (!_IBMPC_chrdy(&c)) + continue; + + return c; +} /* _IBMPC_inch */ + +/* + * Routine that can be used before interrupt management is initialized. + */ +int BSP_wait_polled_input(void) +{ + char c; + while (!_IBMPC_scankey(&c)) + continue; + + return c; +} + +/* + * Check if a key has been pressed. This is a non-destructive + * call, meaning, it keeps the key in the buffer. + */ +int rtems_kbpoll( void ) +{ + int rc; + + /* + * The locking or disable of interrupts does not help + * there because if interrupts are enabled after leave of this + * function the state can change without notice anyway. + */ + RTEMS_COMPILER_MEMORY_BARRIER(); + + rc = ( kbd_first != kbd_last ) ? TRUE : FALSE; + + RTEMS_COMPILER_MEMORY_BARRIER(); + + return rc; +} + +int getch( void ) +{ + int c; + + while( kbd_first == kbd_last ) + { + rtems_task_wake_after( 10 ); + } + c = kbd_buffer[ kbd_first ]; + kbd_first = (kbd_first + 1) % KBD_BUF_SIZE; + return c; +} + +void add_to_queue( unsigned short b ) +{ + unsigned int next; + kbd_buffer[ kbd_last ] = b; + next = (kbd_last == kbd_end) ? 0 : kbd_last + 1; + if( next != kbd_first ) + { + kbd_last = next; + } +} |