backported fixes from 256boss
[bootcensus] / src / keyb.c
index 3e86f43..faf08a9 100644 (file)
@@ -1,6 +1,6 @@
 /*
 pcboot - bootable PC demo/game kernel
-Copyright (C) 2018  John Tsiombikas <nuclear@member.fsf.org>
+Copyright (C) 2018-2019  John Tsiombikas <nuclear@member.fsf.org>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -21,6 +21,9 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #include "intr.h"
 #include "asmops.h"
 #include "kbregs.h"
+#include "kbscan.h"
+#include "power.h"
+#include "panic.h"
 
 #define delay7us() \
        do { \
@@ -28,19 +31,8 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
                iodelay(); iodelay(); iodelay(); \
        } while(0)
 
-/* table with rough translations from set 1 scancodes to ASCII-ish */
-static int scantbl[] = {
-       0, KB_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',            /* 0 - e */
-       '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',                 /* f - 1c */
-       KB_LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',                          /* 1d - 29 */
-       KB_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', KB_RSHIFT,                   /* 2a - 36 */
-       KB_NUM_MUL, KB_LALT, ' ', KB_CAPSLK, KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8, KB_F9, KB_F10,                     /* 37 - 44 */
-       KB_NUMLK, KB_SCRLK, KB_NUM_7, KB_NUM_8, KB_NUM_9, KB_NUM_MINUS, KB_NUM_4, KB_NUM_5, KB_NUM_6, KB_NUM_PLUS,      /* 45 - 4e */
-       KB_NUM_1, KB_NUM_2, KB_NUM_3, KB_NUM_0, KB_NUM_DOT, KB_SYSRQ, 0, 0, KB_F11, KB_F12,                                             /* 4d - 58 */
-       0, 0, 0, 0, 0, 0, 0,                                                                                                                    /* 59 - 5f */
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                                                                 /* 60 - 6f */
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                                                                  /* 70 - 7f */
-};
+static void set_ccb(unsigned char ccb);
+static unsigned char get_ccb(void);
 
 static void kbintr();
 
@@ -53,13 +45,85 @@ static int buf_ridx, buf_widx;
 static unsigned int num_pressed;
 static unsigned char keystate[256];
 
+
 void kb_init(void)
 {
        buf_ridx = buf_widx = 0;
        num_pressed = 0;
        memset(keystate, 0, sizeof keystate);
 
+       /* make sure set1 translation is enabled */
+       kb_set_translate(1);
+
        interrupt(IRQ_TO_INTR(KB_IRQ), kbintr);
+       kb_intr_enable();
+}
+
+void kb_intr_enable(void)
+{
+       unsigned char ccb = get_ccb();
+       ccb |= KB_CCB_KB_INTREN;
+       set_ccb(ccb);
+}
+
+void kb_intr_disable(void)
+{
+       unsigned char ccb = get_ccb();
+       ccb &= ~KB_CCB_KB_INTREN;
+       set_ccb(ccb);
+}
+
+int kb_setmode(int mode)
+{
+       kb_send_data(0xf0);
+       if(!kb_wait_read() || kb_read_data() != KB_ACK) {
+               return -1;
+       }
+       kb_send_data(mode);
+       if(!kb_wait_read() || kb_read_data() != KB_ACK) {
+               return -1;
+       }
+       return 0;
+}
+
+int kb_getmode(void)
+{
+       int mode;
+
+       kb_send_data(0xf0);
+       if(!kb_wait_read() || kb_read_data() != KB_ACK) {
+               return -1;
+       }
+       kb_send_data(0);
+       if(!kb_wait_read() || kb_read_data() != KB_ACK) {
+               return -1;
+       }
+       mode = kb_read_data();
+
+       switch(mode) {
+       case 0x43: return 1;
+       case 0x41: return 2;
+       case 0x3f: return 3;
+       default:
+               break;
+       }
+       return mode;
+}
+
+void kb_set_translate(int xlat)
+{
+       unsigned char ccb = get_ccb();
+       if(xlat) {
+               ccb |= KB_CCB_KB_XLAT;
+       } else {
+               ccb &= ~KB_CCB_KB_XLAT;
+       }
+       set_ccb(ccb);
+}
+
+int kb_get_translate(void)
+{
+       return get_ccb() & KB_CCB_KB_XLAT;
 }
 
 int kb_isdown(int key)
@@ -165,16 +229,38 @@ unsigned char kb_read_data(void)
        return inb(KB_DATA_PORT);
 }
 
+static void set_ccb(unsigned char ccb)
+{
+       kb_send_cmd(KB_CMD_SET_CMDBYTE);
+       kb_send_data(ccb);
+
+       if(kb_wait_read()) {
+               kb_read_data();
+       }
+}
+
+static unsigned char get_ccb(void)
+{
+       kb_send_cmd(KB_CMD_GET_CMDBYTE);
+       return kb_read_data();
+}
+
 static void kbintr()
 {
        unsigned char code;
        int key, press;
+       static int ext = 0;
 
        code = inb(KB_DATA_PORT);
 
-       if(code >= 128) {
+       if(code == 0xe0) {
+               ext = 1;
+               return;
+       }
+
+       if(code & 0x80) {
                press = 0;
-               code -= 128;
+               code &= 0x7f;
 
                if(num_pressed > 0) {
                        num_pressed--;
@@ -185,9 +271,13 @@ static void kbintr()
                num_pressed++;
        }
 
-       key = scantbl[code];
+       key = ext ? scantbl_set1_ext[code] : scantbl_set1[code];
+       ext = 0;
 
        if(press) {
+               if(key == KB_DEL && (keystate[KB_LALT] || keystate[KB_RALT]) && (keystate[KB_LCTRL] || keystate[KB_RCTRL])) {
+                       reboot();
+               }
                /* append to buffer */
                buffer[buf_widx] = key;
                ADVANCE(buf_widx);