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