+/* Keyboard data register port. */
+#define DATA_REG 0x60
+
+/* Shift state bits. */
+#define LSHIFT 0x01 /* Left Shift. */
+#define RSHIFT 0x02 /* Right Shift. */
+#define LALT 0x04 /* Left Alt. */
+#define RALT 0x08 /* Right Alt. */
+#define LCTRL 0x10 /* Left Ctrl. */
+#define RCTRL 0x20 /* Right Ctrl. */
+#define CAPS 0x40 /* Caps Lock. */
+
+/* Current shift state. */
+static unsigned shift_state;
+
+/* Keyboard buffer. */
+static struct intq buffer;
+
+static intr_handler_func keyboard_interrupt;
+
+/* Initializes the keyboard. */
+void
+kbd_init (void)
+{
+ intq_init (&buffer, "keyboard");
+ intr_register (0x21, 0, INTR_OFF, keyboard_interrupt, "8042 Keyboard");
+}
+
+/* Retrieves a key from the keyboard buffer.
+ If the buffer is empty, waits for a key to be pressed. */
+uint8_t
+kbd_getc (void)
+{
+ uint8_t key;
+
+ intq_lock (&buffer);
+ key = intq_getc (&buffer);
+ intq_unlock (&buffer);
+
+ return key;
+}
+\f
+/* Maps a set of contiguous scancodes into characters. */
+struct keymap
+ {
+ uint8_t first_scancode; /* First scancode. */
+ const char *chars; /* chars[0] has scancode first_scancode,
+ chars[1] has scancode first_scancode + 1,
+ and so on to the end of the string. */
+ };
+
+/* Keys that produce the same characters regardless of whether
+ the Shift keys are down. Case of letters is an exception
+ that we handle elsewhere. */
+static const struct keymap invariant_keymap[] =
+ {
+ {0x01, "\033"},
+ {0x0e, "\b"},
+ {0x0f, "\tQWERTYUIOP"},
+ {0x1c, "\n"},
+ {0x1e, "ASDFGHJKL"},
+ {0x2c, "ZXCVBNM"},
+ {0x37, "*"},
+ {0x39, " "},
+ {0, NULL},
+ };
+
+/* Characters for keys pressed without Shift, for those keys
+ where it matters. */
+static const struct keymap unshifted_keymap[] =
+ {
+ {0x02, "1234567890-="},
+ {0x1a, "[]"},
+ {0x27, ";'`"},
+ {0x2b, "\\"},
+ {0x33, ",./"},
+ {0, NULL},
+ };
+
+/* Characters for keys pressed with Shift, for those keys where
+ it matters. */
+static const struct keymap shifted_keymap[] =
+ {
+ {0x02, "!@#$%^&*()_+"},
+ {0x1a, "{}"},
+ {0x27, ":\"~"},
+ {0x2b, "|"},
+ {0x33, "<>?"},
+ {0, NULL},
+ };
+
+static bool map_key (const struct keymap[], unsigned scancode, uint8_t *);
+