1/** 2 * \file 3 */ 4 5/* 6 * Copyright (c) 2009, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include <stdio.h> // for printf() 15#include "vmkitmon.h" 16#include "keyboard.h" 17#include <stdlib.h> 18#include <barrelfish/terminal.h> 19 20struct key_map_entry { 21 uint8_t ascii, scan_code; 22}; 23 24// this table maps from input through the BF kernel to a key in the guest 25// scan codes taken from http://heim.ifi.uio.no/~stanisls/helppc/scan_codes.html 26static struct key_map_entry key_map[128] = { 27 // capital letters 28 ['A'] = { 0x41, 0x1E }, 29 ['B'] = { 0x42, 0x30 }, 30 ['C'] = { 0x43, 0x2E }, 31 ['D'] = { 0x44, 0x20 }, 32 ['E'] = { 0x45, 0x12 }, 33 ['F'] = { 0x46, 0x21 }, 34 ['G'] = { 0x47, 0x22 }, 35 ['H'] = { 0x48, 0x23 }, 36 ['I'] = { 0x49, 0x17 }, 37 ['J'] = { 0x4A, 0x24 }, 38 ['K'] = { 0x4B, 0x25 }, 39 ['L'] = { 0x4C, 0x26 }, 40 ['M'] = { 0x4D, 0x32 }, 41 ['N'] = { 0x4E, 0x31 }, 42 ['O'] = { 0x4F, 0x18 }, 43 ['P'] = { 0x50, 0x19 }, 44 ['Q'] = { 0x51, 0x10 }, 45 ['R'] = { 0x52, 0x13 }, 46 ['S'] = { 0x53, 0x1F }, 47 ['T'] = { 0x54, 0x14 }, 48 ['U'] = { 0x55, 0x16 }, 49 ['V'] = { 0x56, 0x2F }, 50 ['W'] = { 0x57, 0x11 }, 51 ['X'] = { 0x58, 0x2D }, 52 ['Y'] = { 0x59, 0x15 }, 53 ['Z'] = { 0x5A, 0x2C }, 54 // small letters 55 ['a'] = { 0x61, 0x1E }, 56 ['b'] = { 0x62, 0x30 }, 57 ['c'] = { 0x63, 0x2E }, 58 ['d'] = { 0x64, 0x20 }, 59 ['e'] = { 0x65, 0x12 }, 60 ['f'] = { 0x66, 0x21 }, 61 ['g'] = { 0x67, 0x22 }, 62 ['h'] = { 0x68, 0x23 }, 63 ['i'] = { 0x69, 0x17 }, 64 ['j'] = { 0x6A, 0x24 }, 65 ['k'] = { 0x6B, 0x25 }, 66 ['l'] = { 0x6C, 0x26 }, 67 ['m'] = { 0x6D, 0x32 }, 68 ['n'] = { 0x6E, 0x31 }, 69 ['o'] = { 0x6F, 0x18 }, 70 ['p'] = { 0x70, 0x19 }, 71 ['q'] = { 0x71, 0x10 }, 72 ['r'] = { 0x72, 0x13 }, 73 ['s'] = { 0x73, 0x1F }, 74 ['t'] = { 0x74, 0x14 }, 75 ['u'] = { 0x75, 0x16 }, 76 ['v'] = { 0x76, 0x2F }, 77 ['w'] = { 0x77, 0x11 }, 78 ['x'] = { 0x78, 0x2D }, 79 ['y'] = { 0x79, 0x15 }, 80 ['z'] = { 0x7A, 0x2C }, 81 // control characters 82 [0x08] = { 0x08, 0x0e }, // back-space 83 [0x7f] = { 0x7f, 0x0e }, // delete 84 [0x0d] = { 0x0d, 0x1c }, // enter 85 [0x1b] = { 0x1b, 0x01 }, // escape 86 [0x20] = { 0x20, 0x39 }, // space 87 [0x09] = { 0x09, 0x0f } // tab1 88}; 89 90struct keyboard * 91keyboard_new (struct guest *g) 92{ 93 struct keyboard *ret = calloc(1, sizeof(struct keyboard)); 94 95 ret->guest = g; 96 ret->status = KEYBOARD_STATUS_ENABLED; 97 98 return ret; 99} 100 101static inline int 102handle_60h_out (struct keyboard *k, uint32_t val) 103{ 104 if (!(k->status & KEYBOARD_STATUS_IN_CMD)) { 105 printf("keyboard: non command input\n"); 106 return -1; 107 } 108 109 switch (k->write_cmd) { 110 // Write Output Port 111 case 0xd1: 112 /* ------------------------------------------------------------------ 113 * |KBD data|KBD clk|in buf empty|out buf empty|ud|ud|gate a20|reset| 114 * ------------------------------------------------------------------ 115 */ 116 // check for gate a20 117 if (val & 0x2) { 118 k->guest->a20_gate_enabled = true; 119 } else { 120 k->guest->a20_gate_enabled = false; 121 } 122 // check for reset 123 if (!(val & 0x1)) { 124 assert(!"System reset requested"); 125 } 126 break; 127 default: 128 printf("keyboard: Unhandeled keyboard command"); 129 return 1; 130 } 131 132 k->write_cmd = 0; 133 k->status &= ~KEYBOARD_STATUS_IN_CMD; 134 135 return 0; 136} 137 138int 139keyboard_handle_pio_read (struct keyboard *k, uint16_t port, 140 enum opsize size, uint32_t *val) 141{ 142 switch (port) { 143 case 0x64: 144 assert(size & OPSIZE_8); 145 *val = k->status; 146 return HANDLER_ERR_OK; 147 } 148 149 return -1; 150} 151 152int 153keyboard_handle_pio_write (struct keyboard *k, uint16_t port, 154 enum opsize size, uint32_t val) 155{ 156 switch (port) { 157 case 0x60: 158 assert(size & OPSIZE_8); 159 return handle_60h_out(k, val); 160 case 0x64: 161 assert(size & OPSIZE_8); 162 k->write_cmd = val; 163 k->status |= KEYBOARD_STATUS_IN_CMD; 164 return HANDLER_ERR_OK; 165 } 166 167 return -1; 168} 169 170/* waits until a character arrives in the monitor */ 171/* FIXME: perhaps it is not such a good idea to stall the whole monitor for 172 this */ 173static int 174handle_get_keystroke (struct keyboard *k, struct guest *g) 175{ 176 int r; 177 uint8_t chr; 178 179 // loop for now here since we have too many unhandeled keys atm 180 // FIXME: use a complete keymap to avoid this loop 181 while (1) { 182 // wait for input 183 r = terminal_read((char*)&chr, 1); 184 assert(r == 1); 185 186 // check whether our keymap contains the entered key 187 if (key_map[chr].scan_code != 0) { 188 guest_set_al(g, key_map[chr].ascii); 189 guest_set_ah(g, key_map[chr].scan_code); 190 break; 191 } else { 192 printf("keyboard: Unhandeled input char with code %x\n", chr); 193 } 194 } 195 196 return HANDLER_ERR_OK; 197} 198 199int 200keyboard_handle_int16 (struct keyboard *k, struct guest *g) { 201 switch (guest_get_ah(g)) { 202 // KEYBOARD - GET KEYSTROKE 203 case 0: 204 return handle_get_keystroke(k, g); 205 default: 206 break; 207 } 208 209 return HANDLER_ERR_UNHANDELED; 210} 211