2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018-2019 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
30 iodelay(); iodelay(); iodelay(); iodelay(); \
31 iodelay(); iodelay(); iodelay(); \
34 static void set_ccb(unsigned char ccb);
35 static unsigned char get_ccb(void);
40 #define ADVANCE(x) ((x) = ((x) + 1) & (BUFSZ - 1))
42 static int buffer[BUFSZ];
43 static int buf_ridx, buf_widx;
45 static unsigned int num_pressed;
46 static unsigned char keystate[256];
51 buf_ridx = buf_widx = 0;
53 memset(keystate, 0, sizeof keystate);
55 /* make sure set1 translation is enabled */
58 interrupt(IRQ_TO_INTR(KB_IRQ), kbintr);
63 void kb_intr_enable(void)
65 unsigned char ccb = get_ccb();
66 ccb |= KB_CCB_KB_INTREN;
70 void kb_intr_disable(void)
72 unsigned char ccb = get_ccb();
73 ccb &= ~KB_CCB_KB_INTREN;
77 int kb_setmode(int mode)
80 if(!kb_wait_read() || kb_read_data() != KB_ACK) {
84 if(!kb_wait_read() || kb_read_data() != KB_ACK) {
95 if(!kb_wait_read() || kb_read_data() != KB_ACK) {
99 if(!kb_wait_read() || kb_read_data() != KB_ACK) {
102 mode = kb_read_data();
114 void kb_set_translate(int xlat)
116 unsigned char ccb = get_ccb();
118 ccb |= KB_CCB_KB_XLAT;
120 ccb &= ~KB_CCB_KB_XLAT;
125 int kb_get_translate(void)
127 return get_ccb() & KB_CCB_KB_XLAT;
130 int kb_isdown(int key)
137 return keystate[KB_LALT] + keystate[KB_RALT];
140 return keystate[KB_LCTRL] + keystate[KB_RCTRL];
142 return keystate[key];
148 while((key = kb_getkey()) == -1) {
149 /* put the processor to sleep while waiting for keypresses, but first
150 * make sure interrupts are enabled, or we'll sleep forever
162 if(buf_ridx == buf_widx) {
165 res = buffer[buf_ridx];
170 void kb_putback(int key)
172 /* go back a place */
177 /* if the write end hasn't caught up with us, go back one place
178 * and put it there, otherwise just overwrite the oldest key which
179 * is right where we were.
181 if(buf_ridx == buf_widx) {
185 buffer[buf_ridx] = key;
188 int kb_wait_write(void)
191 for(i=0; i<32768; i++) {
192 if(!(inp(KB_STATUS_PORT) & KB_STAT_INBUF_FULL)) {
197 /*printf("kb_wait_write timeout\n");*/
201 int kb_wait_read(void)
204 for(i=0; i<32768; i++) {
205 if((inp(KB_STATUS_PORT) & KB_STAT_OUTBUF_FULL)) {
210 /*printf("kb_wait_read timeout\n");*/
214 void kb_send_cmd(unsigned char cmd)
217 outp(KB_CMD_PORT, cmd);
220 void kb_send_data(unsigned char data)
223 outp(KB_DATA_PORT, data);
226 unsigned char kb_read_data(void)
230 return inp(KB_DATA_PORT);
233 static void set_ccb(unsigned char ccb)
235 kb_send_cmd(KB_CMD_SET_CMDBYTE);
243 static unsigned char get_ccb(void)
245 kb_send_cmd(KB_CMD_GET_CMDBYTE);
246 return kb_read_data();
255 code = inp(KB_DATA_PORT);
266 if(num_pressed > 0) {
276 key = code < 0x59 ? scantbl_set1[code] : 0;
279 case 0x1c: key = '\r'; break;
280 case 0x1d: key = KB_RCTRL; break;
281 //case 0x35: key = KB_NUM_MINUS; break;
282 //case 0x37: key = KB_SYSRQ; break;
283 case 0x38: key = KB_RALT; break;
284 case 0x47: key = KB_HOME; break;
285 case 0x48: key = KB_UP; break;
286 case 0x49: key = KB_PGUP; break;
287 case 0x4b: key = KB_LEFT; break;
288 case 0x4d: key = KB_RIGHT; break;
289 case 0x4f: key = KB_END; break;
290 case 0x50: key = KB_DOWN; break;
291 case 0x51: key = KB_PGDN; break;
292 case 0x52: key = KB_INSERT; break;
293 case 0x53: key = KB_DEL; break;
301 if(key == KB_DEL && (keystate[KB_LALT] || keystate[KB_RALT]) && (keystate[KB_LCTRL] || keystate[KB_RCTRL])) {
304 /* append to buffer */
305 buffer[buf_widx] = key;
307 /* if the write end overtook the read end, advance the read end
308 * too, to discard the oldest keypress from the buffer
310 if(buf_widx == buf_ridx) {
315 /* and update keystate table */
316 keystate[key] = press;