SayoriOS 0.3.3

ps2.c
1 //
2 // Created by ndraey on 2/15/24.
3 //
4
5 // PS2 controller
6
7 #include "drv/ps2.h"
8 #include "io/ports.h"
9
10 bool ps2_channel1_okay = false;
11 bool ps2_channel2_okay = false;
12
13 uint8_t ps2_read_configuration_byte() {
14 ps2_in_wait_until_empty();
15 outb(PS2_STATE_REG, 0x20);
16
17 return ps2_read();
18 }
19
20 void ps2_write_configuration_byte(uint8_t byte) {
21 ps2_in_wait_until_empty();
22 outb(PS2_STATE_REG, 0x60);
23
24 ps2_write(byte);
25 }
26
27 void ps2_in_wait_until_empty() {
28 while(inb(PS2_STATE_REG) & (1 << 1));
29 }
30
31 void ps2_out_wait_until_full() {
32 while(!(inb(PS2_STATE_REG) & 1));
33 }
34
35 uint8_t ps2_read() {
36 ps2_out_wait_until_full();
37 return inb(PS2_DATA_PORT);
38 }
39
40 void ps2_write(uint8_t byte) {
41 ps2_in_wait_until_empty();
42 outb(PS2_DATA_PORT, byte);
43 }
44
45 void ps2_disable_first_device() {
46 ps2_in_wait_until_empty();
47 outb(PS2_STATE_REG, 0xAD); // 1
48 }
49
50 void ps2_disable_second_device() {
51 ps2_in_wait_until_empty();
52 outb(PS2_STATE_REG, 0xA7); // 2
53 }
54
55 void ps2_enable_first_device() {
56 ps2_in_wait_until_empty();
57 outb(PS2_STATE_REG, 0xAE); // 1
58 }
59
60 void ps2_enable_second_device() {
61 ps2_in_wait_until_empty();
62 outb(PS2_STATE_REG, 0xA8); // 2
63 }
64
65 void ps2_flush() {
66 while(inb(PS2_STATE_REG) & 1) {
67 inb(PS2_DATA_PORT);
68 }
69 }
70
71 // false - error; true - ok
72 bool ps2_test() {
73 ps2_in_wait_until_empty();
74
75 outb(PS2_STATE_REG, 0xAA); // Test
76
77 ps2_out_wait_until_full();
78
79 uint8_t reply = inb(PS2_DATA_PORT);
80
81 return reply == 0x55;
82 }
83
84
85 void ps2_init() {
86 ps2_disable_first_device();
87 ps2_disable_second_device();
88
89 ps2_flush();
90
91 ps2_in_wait_until_empty();
92
93 uint8_t conf = ps2_read_configuration_byte();
94 ps2_write_configuration_byte(conf & ~(0b1000011));
95
96 // TEST CONTROLLER
97
98 bool test_ok = ps2_test();
99
100 if(test_ok) {
101 qemu_ok("PS/2 test ok!");
102 } else {
103 qemu_ok("PS/2 TEST ERROR!");
104 return;
105 }
106
107 // Test first port
108
109 ps2_in_wait_until_empty();
110 outb(PS2_STATE_REG, 0xAB);
111
112 ps2_out_wait_until_full();
113 uint8_t result = inb(PS2_DATA_PORT);
114
115 if(result == 0x00) {
116 qemu_ok("Passed test for channel 1!");
117 ps2_channel1_okay = true;
118 } else {
119 qemu_err("Channel 1: Test failed! Result: %x", result);
120 }
121
122 // Test second port
123
124 ps2_in_wait_until_empty();
125 outb(PS2_STATE_REG, 0xA9);
126
127 ps2_out_wait_until_full();
128 result = inb(PS2_DATA_PORT);
129
130 if(result == 0x00) {
131 qemu_ok("Passed test for channel 2!");
132 ps2_channel2_okay = true;
133 } else {
134 qemu_err("Channel 2: Test failed! Result: %x", result);
135 }
136
137 ps2_enable_first_device();
138 ps2_enable_second_device();
139 }