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 }