source: rtems/c/src/lib/libbsp/powerpc/shared/console/inch.c @ 83e392b4

4.9
Last change on this file since 83e392b4 was 83e392b4, checked in by Eric Norum <WENorum@…>, on 10/23/08 at 13:45:55

Reset card on RTEMS shutdown.

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