-
Notifications
You must be signed in to change notification settings - Fork 0
/
keyb.c
126 lines (106 loc) · 3.61 KB
/
keyb.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "keyboard_map.h"
#define LINES 25
#define COLUMNS_IN_LINE 80
#define BYTES_FOR_EACH_ELEMENT 2
#define SCREENSIZE BYTES_FOR_EACH_ELEMENT * COLUMNS_IN_LINE * LINES
#define VIDEO_START 0xb8000
#define REG_SCREEN_CTRL 0x3D4
#define REG_SCREEN_DATA 0x3D5
static int buf_pointer = 0;
static char input_buffer[256];
/* Maintain a global location for the current video memory to write to */
static int current_loc = 0;
/* Video memory starts at 0xb8000. Make it a constant pointer to
characters as this can improve compiler optimization since it
is a hint that the value of the pointer won't change */
static char *const vidptr = (char *) 0xb8000;
void handle_command(char* buf_ptr);
void set_cursor(int offset) {
offset /= 2; // Covert from cell offset to char offset.
// This is similar to get_cursor, only now we write
// bytes to those internal device registers.
write_port(REG_SCREEN_CTRL, 14);
write_port(REG_SCREEN_DATA, (unsigned char)(offset >> 8));
write_port(REG_SCREEN_CTRL, 15);
write_port(REG_SCREEN_DATA, offset);
}
int get_cursor_pos() {
return current_loc;
}
void kb_init(void) {
/* This is a very basic keyboard initialization. The assumption is we have a
* PS/2 keyboard and it is already in a propr state. This may not be the case
* on real hardware. We simply enable the keyboard interupt */
/* Get current master PIC interrupt mask */
unsigned char curmask_master = read_port(0x21);
/* 0xFD is 11111101 - enables only IRQ1 (keyboard) on master pic
by clearing bit 1. bit is clear for enabled and bit is set for disabled */
write_port(0x21, curmask_master & 0xFD);
}
void clear_screen(void) {
unsigned int i = 0;
while (i < SCREENSIZE) {
vidptr[i++] = ' ';
vidptr[i++] = 0x07;
}
}
void print_newline(void) {
unsigned int line_size = BYTES_FOR_EACH_ELEMENT * COLUMNS_IN_LINE;
current_loc = current_loc + (line_size - current_loc % (line_size));
}
void print(const char *str) {
unsigned int i = 0;
while (str[i] != '\0') {
if (str[i] == '\n') {
print_newline();
i++;
} else {
vidptr[current_loc++] = str[i++];
vidptr[current_loc++] = 0x07;
}
}
}
void clear_buf() {
for (int i = 0; i < 256; i++) {
input_buffer[i] = '\0';
}
}
void keyboard_handler(void) {
const char *kcmd = "kcmd> ";
signed char keycode;
keycode = read_port(0x60);
/* Only print characters on keydown event that have
* a non-zero mapping */
if (keycode >= 0 && keyboard_map[keycode]) {
switch (keyboard_map[keycode]) {
case '\n':
input_buffer[buf_pointer] = '\0';
buf_pointer = 0;
print_newline();
handle_command(input_buffer);
print(kcmd);
clear_buf();
break;
case '\b':
if (current_loc % COLUMNS_IN_LINE > 6 * 2) {
vidptr[--current_loc] = 0x07;
vidptr[--current_loc] = 0x00;
buf_pointer--;
}
break;
default:
input_buffer[buf_pointer++] = keyboard_map[keycode];
vidptr[current_loc++] = keyboard_map[keycode];
/* Attribute 0x02 is green on black characters */
vidptr[current_loc++] = 0x02;
}
}
if (current_loc > SCREENSIZE) {
clear_screen();
current_loc = 0;
print(kcmd);
}
set_cursor(current_loc);
/* Send End of Interrupt (EOI) to master PIC */
write_port(0x20, 0x20);
}