2 * Copyright (C) 2003, 2004 Stefan Reinauer
4 * See the file "COPYING" for further information about
5 * the copyright and warranty status of this work.
9 #include "libopenbios/bindings.h"
10 #include "kernel/kernel.h"
11 #include "drivers/drivers.h"
12 #include "libc/vsprintf.h"
14 /* ******************************************************************
15 * simple polling video/keyboard console functions
16 * ****************************************************************** */
24 static const char normal[] = {
25 0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
26 '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
27 'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
28 'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
29 'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
30 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
31 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
34 static const char shifted[] = {
35 0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
36 '+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
37 'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
38 'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
39 'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
40 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
41 '9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
45 static int key_lshift = 0, key_rshift = 0, key_caps = 0;
49 static void pc_kbd_cmd(unsigned char cmd, unsigned char val)
52 /* wait until keyboard controller accepts cmds: */
53 while (inb(0x64) & 2);
55 while (inb(0x64) & 2);
58 static void pc_kbd_controller_cmd(unsigned char cmd, unsigned char val)
61 /* wait until keyboard controller accepts cmds: */
62 while (inb(0x64) & 2);
64 while (inb(0x64) & 2);
67 static char pc_kbd_poll(void)
94 pc_kbd_cmd(0xed, 4); /* set caps led */
100 // void printk(const char *format, ...);
101 printk("extended keycode: %x\n", c);
107 if (c & 0x80) /* unhandled key release */
110 if (key_lshift || key_rshift)
111 return key_caps ? normal[c] : shifted[c];
113 return key_caps ? shifted[c] : normal[c];
118 int pc_kbd_dataready(void)
123 last_key = pc_kbd_poll();
125 return (last_key != 0);
128 unsigned char pc_kbd_readdata(void)
131 while (!pc_kbd_dataready());
137 /* ( addr len -- actual ) */
145 addr = (unsigned char *)POP();
148 printk("pc_kbd_read: bad len, addr %lx len %x\n", (unsigned long)addr, len);
150 if (pc_kbd_dataready()) {
151 *addr = pc_kbd_readdata();
164 pc_kbd_open(unsigned long *address)
171 fword("ihandle>phandle");
172 ph = (phandle_t)POP();
173 prop = (unsigned long *)get_property(ph, "address", &len);
179 DECLARE_UNNAMED_NODE(pc_kbd, INSTALL_OPEN, sizeof(unsigned long));
181 NODE_METHODS(pc_kbd) = {
182 { "open", pc_kbd_open },
183 { "close", pc_kbd_close },
184 { "read", pc_kbd_read },
188 ob_pc_kbd_init(const char *path, const char *dev_name, uint64_t base,
189 uint64_t offset, int intr)
191 phandle_t chosen, aliases;
194 snprintf(nodebuff, sizeof(nodebuff), "%s/%s", path, dev_name);
195 REGISTER_NAMED_NODE(pc_kbd, nodebuff);
198 fword("find-device");
201 fword("device-name");
204 fword("device-type");
208 push_str("keyboard");
211 PUSH((base + offset) >> 32);
213 PUSH((base + offset) & 0xffffffff);
227 chosen = find_dev("/chosen");
230 set_int_property(chosen, "keyboard", POP());
232 aliases = find_dev("/aliases");
233 set_property(aliases, "keyboard", nodebuff, strlen(nodebuff) + 1);
235 pc_kbd_controller_cmd(0x60, 0x40); // Write mode command, translated mode