X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=blobdiff_plain;f=src%2Fkeyb.c;h=faf08a9e85ae6f5504acaa42baf9fef6fd11a901;hp=9a34d8fbdc712e7d4d67235a2355bdbfde2531a4;hb=81c11bdd80190ec319a82b0402173cfb65fcbf72;hpb=97356e29f73e12f0856fde92a48e86c73bef387c diff --git a/src/keyb.c b/src/keyb.c index 9a34d8f..faf08a9 100644 --- a/src/keyb.c +++ b/src/keyb.c @@ -1,6 +1,6 @@ /* pcboot - bootable PC demo/game kernel -Copyright (C) 2018 John Tsiombikas +Copyright (C) 2018-2019 John Tsiombikas 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 @@ -15,26 +15,24 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include +#include #include "keyb.h" #include "intr.h" #include "asmops.h" +#include "kbregs.h" +#include "kbscan.h" +#include "power.h" +#include "panic.h" -#define KB_IRQ 1 -#define KB_PORT 0x60 - -/* 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 */ -}; +#define delay7us() \ + do { \ + iodelay(); iodelay(); iodelay(); iodelay(); \ + iodelay(); iodelay(); iodelay(); \ + } while(0) + +static void set_ccb(unsigned char ccb); +static unsigned char get_ccb(void); static void kbintr(); @@ -47,9 +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) @@ -110,16 +184,83 @@ void kb_putback(int key) buffer[buf_ridx] = key; } +int kb_wait_write(void) +{ + int i; + for(i=0; i<32768; i++) { + if(!(inb(KB_STATUS_PORT) & KB_STAT_INBUF_FULL)) { + return 1; + } + iodelay(); + } + /*printf("kb_wait_write timeout\n");*/ + return 0; +} + +int kb_wait_read(void) +{ + int i; + for(i=0; i<32768; i++) { + if((inb(KB_STATUS_PORT) & KB_STAT_OUTBUF_FULL)) { + return 1; + } + iodelay(); + } + /*printf("kb_wait_read timeout\n");*/ + return 0; +} + +void kb_send_cmd(unsigned char cmd) +{ + kb_wait_write(); + outb(cmd, KB_CMD_PORT); +} + +void kb_send_data(unsigned char data) +{ + kb_wait_write(); + outb(data, KB_DATA_PORT); +} + +unsigned char kb_read_data(void) +{ + kb_wait_read(); + delay7us(); + 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); - code = inb(KB_PORT); + if(code == 0xe0) { + ext = 1; + return; + } - if(code >= 128) { + if(code & 0x80) { press = 0; - code -= 128; + code &= 0x7f; if(num_pressed > 0) { num_pressed--; @@ -130,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);