source: rtems/c/src/lib/libbsp/i386/pc386/console/inch.c @ 6b54dcb

Last change on this file since 6b54dcb was 6b54dcb, checked in by Pavel Pisa <pisa@…>, on Oct 12, 2016 at 7:40:41 AM

bsps/i386: replace global interrupt disable by SMP build supporting locking.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/*-------------------------------------------------------------------------+
2| inch.c v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| (C) Copyright 1997 -
5| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
6|
7| http://pandora.ist.utl.pt
8|
9| Instituto Superior Tecnico * Lisboa * PORTUGAL
10+--------------------------------------------------------------------------+
11| Disclaimer:
12|
13| This file is provided "AS IS" without warranty of any kind, either
14| expressed or implied.
15+--------------------------------------------------------------------------+
16| This code is based on:
17|   inch.c,v 1.3 1995/12/19 20:07:25 joel Exp - go32 BSP
18| With the following copyright notice:
19| With the following copyright notice:
20| **************************************************************************
21| *  COPYRIGHT (c) 1989-1998.
22| *  On-Line Applications Research Corporation (OAR).
23| *
24| *  The license and distribution terms for this file may be
25| *  found in the file LICENSE in this distribution or at
26| *  http://www.rtems.org/license/LICENSE.
27| **************************************************************************
28+--------------------------------------------------------------------------*/
29
30#include <bsp.h>
31#include <bsp/bootcard.h>
32#include <bsp/irq.h>
33
34/*-------------------------------------------------------------------------+
35| Constants
36+--------------------------------------------------------------------------*/
37#define KBD_CTL      0x61  /* -------------------------------- */
38#define KBD_DATA     0x60  /* Ports for PC keyboard controller */
39#define KBD_STATUS   0x64  /* -------------------------------- */
40
41#define KBD_BUF_SIZE 256
42
43/*-------------------------------------------------------------------------+
44| Global Variables
45+--------------------------------------------------------------------------*/
46static char key_map[] =
47{
48  0,033,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',
49  'q','w','e','r','t','y','u','i','o','p','[',']',015,0x80,
50  'a','s','d','f','g','h','j','k','l',';',047,0140,0x80,
51  0134,'z','x','c','v','b','n','m',',','.','/',0x80,
52  '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
53  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
54  0x80,0x80,0x80,'0',0177
55}; /* Keyboard scancode -> character map with no modifiers.       */
56
57static char shift_map[] =
58{
59  0,033,'!','@','#','$','%','^','&','*','(',')','_','+','\b','\t',
60  'Q','W','E','R','T','Y','U','I','O','P','{','}',015,0x80,
61  'A','S','D','F','G','H','J','K','L',':',042,'~',0x80,
62  '|','Z','X','C','V','B','N','M','<','>','?',0x80,
63  '*',0x80,' ',0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
64  0x80,0x80,0x80,0x80,'7','8','9',0x80,'4','5','6',0x80,
65  '1','2','3','0',177
66}; /* Keyboard scancode -> character map with SHIFT key modifier. */
67
68static unsigned short   kbd_buffer[KBD_BUF_SIZE];
69static uint16_t         kbd_first = 0;
70static uint16_t         kbd_last  = 0;
71static uint16_t         kbd_end   = KBD_BUF_SIZE - 1;
72
73/*-------------------------------------------------------------------------+
74|         Function: _IBMPC_scankey
75|      Description: This function can be called during a poll for input, or by
76|                   an ISR. Basically any time you want to process a keypress.
77| Global Variables: key_map, shift_map.
78|        Arguments: outChar - character read in case of a valid reading,
79|                   otherwise unchanged.
80|          Returns: TRUE in case a valid character has been read,
81|                   FALSE otherwise.
82+--------------------------------------------------------------------------*/
83static bool
84_IBMPC_scankey(char *outChar)
85{
86  unsigned char inChar;
87  static int alt_pressed   = 0;
88  static int ctrl_pressed  = 0;
89  static int shift_pressed = 0;
90  static int caps_pressed  = 0;
91  static int extended      = 0;
92
93  *outChar = '\0'; /* default value if we return false */
94
95  /* Read keyboard controller, toggle enable */
96  inport_byte(KBD_CTL, inChar);
97  outport_byte(KBD_CTL, inChar & ~0x80);
98  outport_byte(KBD_CTL, inChar | 0x80);
99  outport_byte(KBD_CTL, inChar & ~0x80);
100
101  /* See if it has data */
102  inport_byte(KBD_STATUS, inChar);
103  if ((inChar & 0x01) == 0)
104    return false;
105
106  /* Read the data.  Handle nonsense with shift, control, etc. */
107  inport_byte(KBD_DATA, inChar);
108
109  if (extended)
110    extended--;
111
112  switch (inChar)
113  {
114    case 0xe0:
115      extended = 2;
116      return false;
117      break;
118
119    case 0x38:
120      alt_pressed = 1;
121      return false;
122      break;
123    case 0xb8:
124      alt_pressed = 0;
125      return false;
126      break;
127
128    case 0x1d:
129      ctrl_pressed = 1;
130      return false;
131      break;
132    case 0x9d:
133      ctrl_pressed = 0;
134      return false;
135      break;
136
137    case 0x2a:
138      if (extended)
139        return false;
140    case 0x36:
141      shift_pressed = 1;
142      return false;
143      break;
144    case 0xaa:
145      if (extended)
146        return false;
147    case 0xb6:
148      shift_pressed = 0;
149      return false;
150      break;
151
152    case 0x3a:
153      caps_pressed = 1;
154      return false;
155      break;
156    case 0xba:
157      caps_pressed = 0;
158      return false;
159      break;
160
161    case 0x53:
162      if (ctrl_pressed && alt_pressed)
163        bsp_reset(); /* ctrl+alt+del -> reboot */
164      break;
165
166    /*
167     * Ignore unrecognized keys--usually arrow and such
168     */
169    default:
170      if ((inChar & 0x80) || (inChar > 0x39))
171      /* High-bit on means key is being released, not pressed */
172        return false;
173      break;
174  } /* switch */
175
176  /* Strip high bit, look up in our map */
177  inChar &= 0x7f;
178  if (ctrl_pressed)
179  {
180    *outChar = key_map[inChar];
181    *outChar &= 037;
182  }
183  else
184  {
185    *outChar = shift_pressed ? shift_map[inChar] : key_map[inChar];
186    if (caps_pressed)
187    {
188      if (*outChar >= 'A' && *outChar <= 'Z')
189        *outChar += 'a' - 'A';
190      else if (*outChar >= 'a' && *outChar <= 'z')
191        *outChar -= 'a' - 'A';
192    }
193  }
194
195  return true;
196} /* _IBMPC_scankey */
197
198/*-------------------------------------------------------------------------+
199|         Function: _IBMPC_chrdy
200|      Description: Check keyboard ISR buffer and return character if not empty.
201| Global Variables: kbd_buffer, kbd_first, kbd_last.
202|        Arguments: c - character read if keyboard buffer not empty, otherwise
203|                   unchanged.
204|          Returns: TRUE if keyboard buffer not empty, FALSE otherwise.
205+--------------------------------------------------------------------------*/
206static bool
207_IBMPC_chrdy(char *c)
208{
209#if CCJ_REMOVED_NO_IDEA_ABOUT_THIS_CODE_OR_COMMENT
210  /* FIX ME!!! It doesn't work without something like the following line.
211     Find out why! */
212  printk("");
213#endif
214
215  /* Check buffer our ISR builds */
216  if (kbd_first != kbd_last)
217  {
218    *c = kbd_buffer[kbd_first];
219
220    kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
221    return true;
222  }
223  else
224    return false;
225} /* _IBMPC_chrdy */
226
227/*-------------------------------------------------------------------------+
228|         Function: _IBMPC_inch
229|      Description: Poll keyboard until a character is ready and return it.
230| Global Variables: None.
231|        Arguments: None.
232|          Returns: character read from keyboard.
233+--------------------------------------------------------------------------*/
234char
235_IBMPC_inch(void)
236{
237    char c;
238    while (!_IBMPC_chrdy(&c))
239      continue;
240
241    return c;
242} /* _IBMPC_inch */
243
244/*
245 * Routine that can be used before interrupt management is initialized.
246 */
247int BSP_wait_polled_input(void)
248{
249  char c;
250  while (!_IBMPC_scankey(&c))
251    continue;
252
253  return c;
254}
255
256/*
257 * Check if a key has been pressed. This is a non-destructive
258 * call, meaning, it keeps the key in the buffer.
259 */
260int rtems_kbpoll( void )
261{
262  int                    rc;
263
264  /*
265   * The locking or disable of interrupts does not help
266   * there because if interrupts are enabled after leave of this
267   * function the state can change without notice anyway.
268   */
269  RTEMS_COMPILER_MEMORY_BARRIER();
270
271  rc = ( kbd_first != kbd_last ) ? TRUE : FALSE;
272
273  RTEMS_COMPILER_MEMORY_BARRIER();
274
275  return rc;
276}
277
278int getch( void )
279{
280  int c;
281
282  while( kbd_first == kbd_last )
283  {
284     rtems_task_wake_after( 10 );
285  }
286  c = kbd_buffer[ kbd_first ];
287  kbd_first = (kbd_first + 1) % KBD_BUF_SIZE;
288  return c;
289}
290
291void add_to_queue( unsigned short b )
292{
293 unsigned int next;
294 kbd_buffer[ kbd_last ] = b;
295 next = (kbd_last == kbd_end) ? 0 : kbd_last + 1;
296 if( next != kbd_first )
297 {
298    kbd_last = next;
299 }
300}
Note: See TracBrowser for help on using the repository browser.