Skip to content

Commit 288ee4f

Browse files
82marbagwipawel
authored andcommitted
keyboard: interrupt routed through APIC
The keyboard interrupt is routed to the local cpu using APIC Signed-off-by: Daniele Ahmed <ahmeddan amazon c;om >
1 parent 30a0584 commit 288ee4f

File tree

5 files changed

+137
-127
lines changed

5 files changed

+137
-127
lines changed

arch/x86/traps.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void init_traps(unsigned int cpu) {
162162
_ul(asm_interrupt_handler_uart), GATE_DPL0, GATE_PRESENT, 0);
163163
set_intr_gate(&percpu->idt[PIT_IRQ0_OFFSET], __KERN_CS,
164164
_ul(asm_interrupt_handler_pit), GATE_DPL0, GATE_PRESENT, 0);
165-
set_intr_gate(&percpu->idt[KEYBOARD_IRQ0_OFFSET], __KERN_CS,
165+
set_intr_gate(&percpu->idt[KEYBOARD_PORT1_IRQ0_OFFSET], __KERN_CS,
166166
_ul(asm_interrupt_handler_keyboard), GATE_DPL0, GATE_PRESENT, 0);
167167

168168
barrier();

common/kernel.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,5 @@ void kernel_main(void) {
6767

6868
printk("All tasks done.\n");
6969

70-
while (1)
71-
echo_loop();
70+
echo_loop();
7271
}

common/setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic,
237237
init_pit(get_bsp_cpu_id());
238238

239239
/* Initialize keyboard */
240-
init_keyboard();
240+
init_keyboard(get_bsp_cpu_id());
241241

242242
/* Jump from .text.init section to .text */
243243
asm volatile("push %0; ret" ::"r"(&kernel_main));

drivers/keyboard.c

Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,78 +22,103 @@
2222
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2323
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424
*/
25+
#include <apic.h>
2526
#include <drivers/keyboard.h>
2627
#include <drivers/pic.h>
28+
#include <ioapic.h>
2729
#include <lib.h>
2830
#include <string.h>
2931

30-
static struct {
31-
int shift, caps, ctrl, alt;
32+
/* clang-format off */
33+
static const unsigned char key_map[] = { /* map scan code to key */
34+
0xff, SCAN_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
35+
'\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
36+
SCAN_ENTER, SCAN_CTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
37+
SCAN_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
38+
SCAN_RSHIFT, 0x37, SCAN_ALT, ' ', SCAN_CAPS,
39+
SCAN_F1, SCAN_F2, SCAN_F3, SCAN_F4, SCAN_F5, SCAN_F6, SCAN_F7, SCAN_F8, SCAN_F9, SCAN_F10,
40+
SCAN_NUMLOCK, SCAN_SCROLLLOCK, SCAN_HOME, SCAN_UP, SCAN_PAGEUP, 0x4a, SCAN_LEFT,
41+
SCAN_KEYPAD5, SCAN_RIGHT, 0x4e, SCAN_END, SCAN_DOWN, SCAN_PAGEDOWN, SCAN_INS, SCAN_DEL,
42+
0x54, SCAN_F11, 0x56, 0x57, SCAN_F12
43+
};
44+
45+
static const unsigned char key_map_up[] = { /* map scan code to upper key */
46+
0xff, SCAN_ESC, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
47+
'\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}',
48+
SCAN_ENTER, SCAN_CTRL, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
49+
SCAN_LSHIFT, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?'};
50+
/* clang-format on */
51+
52+
struct keyboard_state {
53+
bool shift, caps, ctrl, alt;
3254

3355
char buf[KEY_BUF];
3456
unsigned curr;
3557
unsigned init;
36-
} keyboard_state;
58+
};
59+
typedef struct keyboard_state keyboard_state_t;
3760

38-
void init_keyboard() {
61+
static keyboard_state_t keyboard_state;
62+
63+
void init_keyboard(uint8_t dst_cpus) {
3964
printk("Initializing keyboard driver\n");
4065

4166
/* Disable devices */
42-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_0);
4367
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_1);
68+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_2);
4469

4570
/* Flush output buffer */
4671
while (inb(KEYBOARD_PORT_DATA) & KEYBOARD_STATUS_OUT_FULL)
4772
; /* discard leftover bytes */
4873

4974
/* Controller configuration */
50-
char current_status;
51-
int dual_channel;
75+
keyboard_controller_config_t current_status;
76+
bool dual_channel;
5277

5378
/* Read controller config */
5479
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_READ_CONFIGURATION);
55-
current_status = inb(KEYBOARD_PORT_DATA);
80+
current_status.config = inb(KEYBOARD_PORT_DATA);
81+
82+
dual_channel = current_status.clock2 == 0 ? 1 : 0; /* second channel enabled if 0 */
83+
84+
printk("Current PS/2 status before: %x\n", current_status.config);
5685

57-
dual_channel = !!(current_status & (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1));
58-
printk("Current PS/2 status before: %x\n", current_status);
5986
/* Disable IRQs and translation */
60-
current_status = current_status &
61-
~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT) &
62-
~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT) &
63-
~(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION);
87+
current_status.port1_int = 0;
88+
current_status.port2_int = 0;
89+
current_status.translation = 0;
90+
6491
/* Write controller config */
6592
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION);
66-
outb(KEYBOARD_PORT_DATA, current_status);
93+
outb(KEYBOARD_PORT_DATA, current_status.config);
6794

68-
printk("Current PS/2 status after mods: %x\n", current_status);
95+
printk("Current PS/2 status after mods: %x\n", current_status.config);
6996
printk("PS/2 dual channel? %d\n", dual_channel);
7097

7198
/* Controller self test */
7299
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_SELF_TEST);
73100
if (inb(KEYBOARD_PORT_DATA) != KEYBOARD_RES_SELF_TEST) {
74-
printk("Self test did not succed\n");
101+
printk("Self test did not succeed\n");
75102
return;
76103
}
77104

78105
/* Determine whether second channel exists */
79106
if (dual_channel) {
80-
printk("Enabling second PS/2 port\n");
81-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1);
107+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_2);
82108
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_READ_CONFIGURATION);
83-
current_status = inb(KEYBOARD_PORT_DATA);
84-
dual_channel =
85-
(current_status & (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1)) == 0;
109+
current_status.config = inb(KEYBOARD_PORT_DATA);
110+
dual_channel = current_status.clock2 == 0 ? 1 : 0;
86111
}
87112
if (dual_channel)
88-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_1);
113+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_DISABLE_PORT_2);
89114

90115
/* Interface tests */
91116
int port1, port2 = 0;
92-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_0);
93-
port1 = inb(KEYBOARD_PORT_DATA) == 0;
117+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_1);
118+
port1 = inb(KEYBOARD_PORT_DATA) == 0 ? 1 : 0;
94119
if (dual_channel) {
95-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_1);
96-
port2 = inb(KEYBOARD_PORT_DATA) == 0;
120+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_TEST_PORT_2);
121+
port2 = inb(KEYBOARD_PORT_DATA) == 0 ? 1 : 0;
97122
}
98123

99124
printk("Port1 available? %d - port2 available? %d\n", port1, port2);
@@ -105,25 +130,25 @@ void init_keyboard() {
105130
/* Enable devices */
106131
if (port1) {
107132
printk("Keyboard: enabling first channel\n");
108-
current_status = current_status |
109-
(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT) |
110-
(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1) |
111-
(1 << KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION);
133+
current_status.port1_int = 1;
134+
current_status.clock2 = 1; /* disable second port clock */
135+
current_status.translation = 1;
112136
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION);
113-
outb(KEYBOARD_PORT_DATA, current_status);
137+
outb(KEYBOARD_PORT_DATA, current_status.config);
114138

115-
pic_enable_irq(PIC1_DEVICE_SEL, KEYBOARD_IRQ);
116-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_0);
139+
configure_isa_irq(KEYBOARD_PORT1_IRQ, KEYBOARD_PORT1_IRQ0_OFFSET,
140+
IOAPIC_DEST_MODE_PHYSICAL, dst_cpus);
141+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1);
117142
}
118143
else {
119144
printk("Keyboard: enabling second channel\n");
120-
current_status =
121-
current_status | (1 << KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT);
145+
current_status.port2_int = 1;
122146
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_WRITE_CONFIGURATION);
123-
outb(KEYBOARD_PORT_DATA, current_status);
147+
outb(KEYBOARD_PORT_DATA, current_status.config);
124148

125-
pic_enable_irq(PIC1_DEVICE_SEL, KEYBOARD_IRQ_2);
126-
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_1);
149+
configure_isa_irq(KEYBOARD_PORT2_IRQ, KEYBOARD_PORT2_IRQ0_OFFSET,
150+
IOAPIC_DEST_MODE_PHYSICAL, dst_cpus);
151+
outb(KEYBOARD_PORT_CMD, KEYBOARD_CMD_ENABLE_PORT_2);
127152
}
128153

129154
memset(&keyboard_state, 0, sizeof(keyboard_state));
@@ -164,13 +189,12 @@ unsigned int keyboard_process_keys(void) {
164189

165190
void keyboard_interrupt_handler(void) {
166191
unsigned char status;
167-
int released;
168192

169193
status = inb(KEYBOARD_PORT_CMD);
170194
if (status & KEYBOARD_STATUS_OUT_FULL) {
171195
char scan = inb(KEYBOARD_PORT_DATA);
196+
int released = !!(scan & SCAN_RELEASE_MASK);
172197

173-
released = !!(scan & SCAN_RELEASE_MASK);
174198
scan = scan & (SCAN_RELEASE_MASK - 1);
175199

176200
switch (scan) {
@@ -199,5 +223,5 @@ void keyboard_interrupt_handler(void) {
199223
}
200224
}
201225

202-
outb(PIC1_PORT_CMD, PIC_EOI);
226+
apic_EOI();
203227
}

include/drivers/keyboard.h

Lines changed: 68 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -30,106 +30,93 @@
3030
#define KEYBOARD_PORT_CMD 0x64 /* keyboard command port */
3131
#define KEYBOARD_PORT_DATA 0x60 /* keyboard data port */
3232

33-
#define KEYBOARD_IRQ 0x01
34-
#define KEYBOARD_IRQ_2 0x04 /* Second port */
35-
#define KEYBOARD_IRQ0_OFFSET \
36-
(PIC_IRQ0_OFFSET + KEYBOARD_IRQ) /* keyboard first channel irq offset */
37-
#define KEYBOARD_2_IRQ0_OFFSET (PIC_IRQ0_OFFSET + KEYBOARD_IRQ_2)
33+
#define KEYBOARD_PORT1_IRQ 0x01
34+
#define KEYBOARD_PORT2_IRQ 0x04 /* Second port */
35+
#define KEYBOARD_PORT1_IRQ0_OFFSET \
36+
(PIC_IRQ0_OFFSET + KEYBOARD_PORT1_IRQ) /* keyboard first channel irq offset */
37+
#define KEYBOARD_PORT2_IRQ0_OFFSET (PIC_IRQ0_OFFSET + KEYBOARD_PORT2_IRQ)
3838

3939
#define KEYBOARD_STATUS_OUT_FULL 0x01 /* bit set when the keyboard buffer is full */
4040

4141
enum {
4242
KEYBOARD_CMD_WRITE_CONFIGURATION = 0x60, /* Write configuration byte */
4343
KEYBOARD_CMD_READ_CONFIGURATION = 0x20, /* Read configuration byte */
4444
KEYBOARD_CMD_SELF_TEST = 0xAA,
45-
KEYBOARD_CMD_TEST_PORT_0 = 0xAB,
46-
KEYBOARD_CMD_TEST_PORT_1 = 0xA9,
47-
KEYBOARD_CMD_DISABLE_PORT_0 = 0xAD,
48-
KEYBOARD_CMD_DISABLE_PORT_1 = 0xA7,
49-
KEYBOARD_CMD_ENABLE_PORT_0 = 0xAE,
50-
KEYBOARD_CMD_ENABLE_PORT_1 = 0xA8,
45+
KEYBOARD_CMD_TEST_PORT_1 = 0xAB,
46+
KEYBOARD_CMD_TEST_PORT_2 = 0xA9,
47+
KEYBOARD_CMD_DISABLE_PORT_1 = 0xAD,
48+
KEYBOARD_CMD_DISABLE_PORT_2 = 0xA7,
49+
KEYBOARD_CMD_ENABLE_PORT_1 = 0xAE,
50+
KEYBOARD_CMD_ENABLE_PORT_2 = 0xA8,
5151
} keyboard_cmd;
5252
typedef enum keyboard_cmd keyboard_cmd_t;
5353

54-
enum {
55-
KEYBOARD_RES_SELF_TEST = 0x55,
56-
} keyboard_res;
54+
#define KEYBOARD_RES_SELF_TEST 0x55
5755

58-
enum {
59-
KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_0_INTERRUPT,
60-
KEYBOARD_CONTROLLER_CONFIG_BIT_PORT_1_INTERRUPT,
61-
KEYBOARD_CONTROLLER_CONFIG_BIT_SYS_FLAG,
62-
KEYBOARD_CONTROLLER_CONFIG_BIT_ZERO,
63-
KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_0,
64-
KEYBOARD_CONTROLLER_CONFIG_BIT_CLOCK_1,
65-
KEYBOARD_CONTROLLER_CONFIG_BIT_TRANSLATION,
66-
KEYBOARD_CONTROLLER_CONFIG_BIT_ZERO_,
67-
} keyboard_controller_config_byte;
68-
typedef enum keyboard_controller_config_byte keyboard_controller_config_byte_t;
56+
union keyboard_controller_config {
57+
struct {
58+
/* clang-format off */
59+
uint8_t port1_int : 1,
60+
port2_int : 1,
61+
sys_flag : 1,
62+
zero0 : 1,
63+
clock1 : 1,
64+
clock2 : 1,
65+
translation : 1,
66+
zero1 : 1;
67+
/* clang-format on */
68+
} __packed;
69+
uint8_t config;
70+
};
71+
typedef union keyboard_controller_config keyboard_controller_config_t;
6972

7073
#define KEY_BUF 80 /* size of internal input buffer */
7174

7275
#define SCAN_RELEASE_MASK 0x80 /* bit set on key release */
7376

7477
#define KEY_NULL 0x00 /* no key */
7578

76-
/* scan codes */
77-
#define SCAN_NULL 0x0
78-
#define SCAN_ESC 0x1
79-
#define SCAN_ENTER 0x1c
80-
#define SCAN_CTRL 0x1d
81-
#define SCAN_LSHIFT 0x2a
82-
#define SCAN_RSHIFT 0x36
83-
#define SCAN_ALT 0x38
84-
#define SCAN_CAPS 0x3a
85-
#define SCAN_F1 0x3b
86-
#define SCAN_F2 0x3c
87-
#define SCAN_F3 0x3d
88-
#define SCAN_F4 0x3e
89-
#define SCAN_F5 0x3f
90-
#define SCAN_F6 0x40
91-
#define SCAN_F7 0x41
92-
#define SCAN_F8 0x42
93-
#define SCAN_F9 0x43
94-
#define SCAN_F10 0x44
95-
#define SCAN_F11 0x55
96-
#define SCAN_F12 0x58
97-
#define SCAN_NUMLOCK 0x45
98-
#define SCAN_SCROLLLOCK 0x46
99-
#define SCAN_HOME 0x47
100-
#define SCAN_UP 0x48
101-
#define SCAN_PAGEUP 0x49
102-
#define SCAN_LEFT 0x4b
103-
#define SCAN_KEYPAD5 0x4c
104-
#define SCAN_RIGHT 0x4d
105-
#define SCAN_END 0x4f
106-
#define SCAN_DOWN 0x50
107-
#define SCAN_PAGEDOWN 0x51
108-
#define SCAN_INS 0x52
109-
#define SCAN_DEL 0x53
110-
111-
void init_keyboard();
112-
void keyboard_interrupt_handler(void);
113-
unsigned int keyboard_process_keys(void);
114-
115-
/* clang-format off */
116-
static const unsigned char key_map[] = { /* map scan code to key */
117-
0xff, SCAN_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
118-
'\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
119-
SCAN_ENTER, SCAN_CTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
120-
SCAN_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
121-
SCAN_RSHIFT, 0x37, SCAN_ALT, ' ', SCAN_CAPS,
122-
SCAN_F1, SCAN_F2, SCAN_F3, SCAN_F4, SCAN_F5, SCAN_F6, SCAN_F7, SCAN_F8, SCAN_F9, SCAN_F10,
123-
SCAN_NUMLOCK, SCAN_SCROLLLOCK, SCAN_HOME, SCAN_UP, SCAN_PAGEUP, 0x4a, SCAN_LEFT,
124-
SCAN_KEYPAD5, SCAN_RIGHT, 0x4e, SCAN_END, SCAN_DOWN, SCAN_PAGEDOWN, SCAN_INS, SCAN_DEL,
125-
0x54, SCAN_F11, 0x56, 0x57, SCAN_F12
79+
enum scan_code {
80+
SCAN_NULL = 0x00,
81+
SCAN_ESC = 0x01,
82+
SCAN_ENTER = 0x1c,
83+
SCAN_CTRL = 0x1d,
84+
SCAN_LSHIFT = 0x2a,
85+
SCAN_RSHIFT = 0x36,
86+
SCAN_ALT = 0x38,
87+
SCAN_CAPS = 0x3a,
88+
SCAN_F1 = 0x3b,
89+
SCAN_F2 = 0x3c,
90+
SCAN_F3 = 0x3d,
91+
SCAN_F4 = 0x3e,
92+
SCAN_F5 = 0x3f,
93+
SCAN_F6 = 0x40,
94+
SCAN_F7 = 0x41,
95+
SCAN_F8 = 0x42,
96+
SCAN_F9 = 0x43,
97+
SCAN_F10 = 0x44,
98+
SCAN_F11 = 0x55,
99+
SCAN_F12 = 0x58,
100+
SCAN_NUMLOCK = 0x45,
101+
SCAN_SCROLLLOCK = 0x46,
102+
SCAN_HOME = 0x47,
103+
SCAN_UP = 0x48,
104+
SCAN_PAGEUP = 0x49,
105+
SCAN_LEFT = 0x4b,
106+
SCAN_KEYPAD5 = 0x4c,
107+
SCAN_RIGHT = 0x4d,
108+
SCAN_END = 0x4f,
109+
SCAN_DOWN = 0x50,
110+
SCAN_PAGEDOWN = 0x51,
111+
SCAN_INS = 0x52,
112+
SCAN_DEL = 0x53
126113
};
114+
typedef enum scan_code scan_code_t;
115+
116+
/* External Declarations */
127117

128-
static const unsigned char key_map_up[] = { /* map scan code to upper key */
129-
0xff, SCAN_ESC, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
130-
'\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}',
131-
SCAN_ENTER, SCAN_CTRL, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
132-
SCAN_LSHIFT, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?'};
133-
/* clang-format on */
118+
extern void init_keyboard(uint8_t dst_cpus);
119+
extern void keyboard_interrupt_handler(void);
120+
extern unsigned int keyboard_process_keys(void);
134121

135122
#endif

0 commit comments

Comments
 (0)