Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /*-------------------------------------------------------------------------+
0002 | inch.c v1.1 - PC386 BSP - 1997/08/07
0003 +--------------------------------------------------------------------------+
0004 | (C) Copyright 1997 -
0005 | - NavIST Group - Real-Time Distributed Systems and Industrial Automation
0006 |
0007 | http://pandora.ist.utl.pt
0008 |
0009 | Instituto Superior Tecnico * Lisboa * PORTUGAL
0010 +--------------------------------------------------------------------------+
0011 | Disclaimer:
0012 |
0013 | This file is provided "AS IS" without warranty of any kind, either
0014 | expressed or implied.
0015 +--------------------------------------------------------------------------+
0016 | This code is based on:
0017 |   inch.c,v 1.3 1995/12/19 20:07:25 joel Exp - go32 BSP
0018 | With the following copyright notice:
0019 | With the following copyright notice:
0020 | **************************************************************************
0021 | *  COPYRIGHT (c) 1989-1998.
0022 | *  On-Line Applications Research Corporation (OAR).
0023 | *
0024 | *  The license and distribution terms for this file may be
0025 | *  found in the file LICENSE in this distribution or at
0026 | *  http://www.rtems.org/license/LICENSE.
0027 | **************************************************************************
0028 +--------------------------------------------------------------------------*/
0029 
0030 #include <bsp.h>
0031 #include <bsp/bootcard.h>
0032 #include <bsp/irq.h>
0033 
0034 /*-------------------------------------------------------------------------+
0035 | Constants
0036 +--------------------------------------------------------------------------*/
0037 #define KBD_CTL      0x61  /* -------------------------------- */
0038 #define KBD_DATA     0x60  /* Ports for PC keyboard controller */
0039 #define KBD_STATUS   0x64  /* -------------------------------- */
0040 
0041 #define KBD_BUF_SIZE 256
0042 
0043 /*-------------------------------------------------------------------------+
0044 | Global Variables
0045 +--------------------------------------------------------------------------*/
0046 static char key_map[] =
0047 {
0048   0,033,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',
0049   'q','w','e','r','t','y','u','i','o','p','[',']',015,0x80,
0050   'a','s','d','f','g','h','j','k','l',';',047,0140,0x80,
0051   0134,'z','x','c','v','b','n','m',',','.','/',0x80,
0052   '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0053   0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0054   0x80,0x80,0x80,'0',0177
0055 }; /* Keyboard scancode -> character map with no modifiers.       */
0056 
0057 static char shift_map[] =
0058 {
0059   0,033,'!','@','#','$','%','^','&','*','(',')','_','+','\b','\t',
0060   'Q','W','E','R','T','Y','U','I','O','P','{','}',015,0x80,
0061   'A','S','D','F','G','H','J','K','L',':',042,'~',0x80,
0062   '|','Z','X','C','V','B','N','M','<','>','?',0x80,
0063   '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0064   0x80,0x80,0x80,0x80,'7','8','9',0x80,'4','5','6',0x80,
0065   '1','2','3','0',177
0066 }; /* Keyboard scancode -> character map with SHIFT key modifier. */
0067 
0068 static unsigned short   kbd_buffer[KBD_BUF_SIZE];
0069 static uint16_t         kbd_first = 0;
0070 static uint16_t         kbd_last  = 0;
0071 static uint16_t         kbd_end   = KBD_BUF_SIZE - 1;
0072 
0073 /*-------------------------------------------------------------------------+
0074 |         Function: _IBMPC_scankey
0075 |      Description: This function can be called during a poll for input, or by
0076 |                   an ISR. Basically any time you want to process a keypress.
0077 | Global Variables: key_map, shift_map.
0078 |        Arguments: outChar - character read in case of a valid reading,
0079 |                   otherwise unchanged.
0080 |          Returns: TRUE in case a valid character has been read,
0081 |                   FALSE otherwise.
0082 +--------------------------------------------------------------------------*/
0083 static bool
0084 _IBMPC_scankey(char *outChar)
0085 {
0086   unsigned char inChar;
0087   static int alt_pressed   = 0;
0088   static int ctrl_pressed  = 0;
0089   static int shift_pressed = 0;
0090   static int caps_pressed  = 0;
0091   static int extended      = 0;
0092 
0093   *outChar = '\0'; /* default value if we return false */
0094 
0095   /* Read keyboard controller, toggle enable */
0096   inport_byte(KBD_CTL, inChar);
0097   outport_byte(KBD_CTL, inChar & ~0x80);
0098   outport_byte(KBD_CTL, inChar | 0x80);
0099   outport_byte(KBD_CTL, inChar & ~0x80);
0100 
0101   /* See if it has data */
0102   inport_byte(KBD_STATUS, inChar);
0103   if ((inChar & 0x01) == 0)
0104     return false;
0105 
0106   /* Read the data.  Handle nonsense with shift, control, etc. */
0107   inport_byte(KBD_DATA, inChar);
0108 
0109   if (extended)
0110     extended--;
0111 
0112   switch (inChar)
0113   {
0114     case 0xe0:
0115       extended = 2;
0116       return false;
0117       break;
0118 
0119     case 0x38:
0120       alt_pressed = 1;
0121       return false;
0122       break;
0123     case 0xb8:
0124       alt_pressed = 0;
0125       return false;
0126       break;
0127 
0128     case 0x1d:
0129       ctrl_pressed = 1;
0130       return false;
0131       break;
0132     case 0x9d:
0133       ctrl_pressed = 0;
0134       return false;
0135       break;
0136 
0137     case 0x2a:
0138       if (extended)
0139         return false;
0140     case 0x36:
0141       shift_pressed = 1;
0142       return false;
0143       break;
0144     case 0xaa:
0145       if (extended)
0146         return false;
0147     case 0xb6:
0148       shift_pressed = 0;
0149       return false;
0150       break;
0151 
0152     case 0x3a:
0153       caps_pressed = 1;
0154       return false;
0155       break;
0156     case 0xba:
0157       caps_pressed = 0;
0158       return false;
0159       break;
0160 
0161     case 0x53:
0162       if (ctrl_pressed && alt_pressed)
0163         bsp_reset( RTEMS_FATAL_SOURCE_BSP, 0 ); /* ctrl+alt+del -> reboot */
0164       break;
0165 
0166     /*
0167      * Ignore unrecognized keys--usually arrow and such
0168      */
0169     default:
0170       if ((inChar & 0x80) || (inChar > 0x39))
0171       /* High-bit on means key is being released, not pressed */
0172         return false;
0173       break;
0174   } /* switch */
0175 
0176   /* Strip high bit, look up in our map */
0177   inChar &= 0x7f;
0178   if (ctrl_pressed)
0179   {
0180     *outChar = key_map[inChar];
0181     *outChar &= 037;
0182   }
0183   else
0184   {
0185     *outChar = shift_pressed ? shift_map[inChar] : key_map[inChar];
0186     if (caps_pressed)
0187     {
0188       if (*outChar >= 'A' && *outChar <= 'Z')
0189         *outChar += 'a' - 'A';
0190       else if (*outChar >= 'a' && *outChar <= 'z')
0191         *outChar -= 'a' - 'A';
0192     }
0193   }
0194 
0195   return true;
0196 } /* _IBMPC_scankey */
0197 
0198 /*-------------------------------------------------------------------------+
0199 |         Function: _IBMPC_chrdy
0200 |      Description: Check keyboard ISR buffer and return character if not empty.
0201 | Global Variables: kbd_buffer, kbd_first, kbd_last.
0202 |        Arguments: c - character read if keyboard buffer not empty, otherwise
0203 |                   unchanged.
0204 |          Returns: TRUE if keyboard buffer not empty, FALSE otherwise.
0205 +--------------------------------------------------------------------------*/
0206 static bool
0207 _IBMPC_chrdy(char *c)
0208 {
0209 #if CCJ_REMOVED_NO_IDEA_ABOUT_THIS_CODE_OR_COMMENT
0210   /* FIX ME!!! It doesn't work without something like the following line.
0211      Find out why! */
0212   printk("");
0213 #endif
0214 
0215   /* Check buffer our ISR builds */
0216   if (kbd_first != kbd_last)
0217   {
0218     *c = kbd_buffer[kbd_first];
0219 
0220     kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
0221     return true;
0222   }
0223   else
0224     return false;
0225 } /* _IBMPC_chrdy */
0226 
0227 /*-------------------------------------------------------------------------+
0228 |         Function: _IBMPC_inch
0229 |      Description: Poll keyboard until a character is ready and return it.
0230 | Global Variables: None.
0231 |        Arguments: None.
0232 |          Returns: character read from keyboard.
0233 +--------------------------------------------------------------------------*/
0234 char
0235 _IBMPC_inch(void)
0236 {
0237     char c;
0238     while (!_IBMPC_chrdy(&c))
0239       continue;
0240 
0241     return c;
0242 } /* _IBMPC_inch */
0243 
0244 /*
0245  * Routine that can be used before interrupt management is initialized.
0246  */
0247 int BSP_wait_polled_input(void)
0248 {
0249   char c;
0250   while (!_IBMPC_scankey(&c))
0251     continue;
0252 
0253   return c;
0254 }
0255 
0256 /*
0257  * Check if a key has been pressed. This is a non-destructive
0258  * call, meaning, it keeps the key in the buffer.
0259  */
0260 int rtems_kbpoll( void )
0261 {
0262   int                    rc;
0263 
0264   /*
0265    * The locking or disable of interrupts does not help
0266    * there because if interrupts are enabled after leave of this
0267    * function the state can change without notice anyway.
0268    */
0269   RTEMS_COMPILER_MEMORY_BARRIER();
0270 
0271   rc = ( kbd_first != kbd_last ) ? TRUE : FALSE;
0272 
0273   RTEMS_COMPILER_MEMORY_BARRIER();
0274 
0275   return rc;
0276 }
0277 
0278 int getch( void )
0279 {
0280   int c;
0281 
0282   while( kbd_first == kbd_last )
0283   {
0284      rtems_task_wake_after( 10 );
0285   }
0286   c = kbd_buffer[ kbd_first ];
0287   kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
0288   return c;
0289 }
0290 
0291 void add_to_queue( unsigned short b )
0292 {
0293  unsigned int next;
0294  kbd_buffer[ kbd_last ] = b;
0295  next = (kbd_last == kbd_end) ? 0 : kbd_last + 1;
0296  if( next != kbd_first )
0297  {
0298     kbd_last = next;
0299  }
0300 }