]> git.dujemihanovic.xyz Git - nameless-os.git/blob - kernel/drivers/input/ps2.c
050702426f39e9114ad5468e7754ba1177e0c46e
[nameless-os.git] / kernel / drivers / input / ps2.c
1 #include <tty.h>
2 #include <io.h>
3 #include <input/ps2.h>
4 #include <bitflags.h>
5
6 int ps2_initialize()
7 {
8 uint8_t ccb, is_2channel, port_1_test, port_2_test;
9
10 kprint("ps2: Begin initializing PS/2 controller\n", 0);
11 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_DISABLE);
12 ps2_input_wait();
13 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_1_DISABLE);
14 ps2_input_wait();
15 inb(PS2_DATA_PORT);
16
17 outb(PS2_CMD_STS_PORT, PS2_CMD_READ_CCB);
18 ps2_output_wait();
19 ccb = inb(PS2_DATA_PORT);
20
21 CLEAR(ccb, 0);
22 CLEAR(ccb, 1);
23 CLEAR(ccb, 6);
24
25 ps2_input_wait();
26 outb(PS2_CMD_STS_PORT, PS2_CMD_WRITE_CCB);
27 ps2_input_wait();
28 outb(PS2_DATA_PORT, ccb);
29
30 ps2_input_wait();
31 outb(PS2_CMD_STS_PORT, PS2_CMD_CONTROLLER_TEST);
32 ps2_output_wait();
33 if (inb(PS2_DATA_PORT) != PS2_CONTROLLER_GOOD) {
34 kprint("ps2: Controller self test failed, exiting!\n", 0);
35 return -1;
36 };
37
38 ps2_input_wait();
39 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_ENABLE);
40 ps2_input_wait();
41 outb(PS2_CMD_STS_PORT, PS2_CMD_READ_CCB);
42 ps2_output_wait();
43 ccb = inb(PS2_DATA_PORT);
44
45 if (ccb & PORT_2_CLK != PORT_2_CLK) {
46 is_2channel = 0;
47 kprint("ps2: Controller is single-channel\n", 0);
48 } else {
49 is_2channel = 1;
50 kprint("ps2: Controller is dual-channel\n", 0);
51 ps2_input_wait();
52 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_DISABLE);
53 }
54
55 ps2_input_wait();
56 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_1_TEST);
57 ps2_output_wait();
58
59 if (inb(PS2_DATA_PORT) != 0) {
60 port_1_test = 0;
61 kprint("ps2: Port 1 test failed!\n", 0);
62 if (!is_2channel) {
63 kprint("ps2: No functional port, exiting!\n", 0);
64 return -1;
65 }
66 } else port_1_test = 1;
67
68 ps2_input_wait();
69 if (is_2channel) {
70 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_TEST);
71 ps2_output_wait();
72
73 if (inb(PS2_DATA_PORT) != 0) {
74 port_2_test = 0;
75 kprint("ps2: Port 2 test failed!", 0);
76 if (!port_1_test) {
77 kprint("ps2: No functional port, exiting!\n", 0);
78 return -1;
79 }
80 } else port_2_test = 1;
81 }
82
83 if (port_1_test) { ps2_input_wait(); outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_1_ENABLE); }
84 if (port_2_test) { ps2_input_wait(); outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_ENABLE); }
85
86 int dev_1_test, dev_2_test;
87
88 /*
89 if (port_1_test) {
90 uint8_t resp;
91
92 do {
93 ps2_input_wait();
94 outb(PS2_DATA_PORT, PS2_DEV_RESET);
95 ps2_output_wait();
96 resp = inb(PS2_DATA_PORT);
97 } while (resp == RESEND);
98
99 if (resp == SELF_TEST_BAD || resp == SELF_TEST_BAD_2) {
100 dev_1_test = 0;
101 kprint("ps2: Port 1 device self test failed!\n", 0);
102 if (!port_2_test) {
103 kprint("ps2: No functioning devices, exiting!\n", 0);
104 return -1;
105 }
106 } else { dev_1_test = 1; kprint("ps2: Port 1 device test successful\n", 0); }
107 }
108
109 if (port_2_test) {
110 int resp = RESEND;
111
112 while (resp == RESEND) {
113 ps2_input_wait();
114 outb(PS2_CMD_STS_PORT, PS2_CMD_PORT_2_WRITE);
115 ps2_input_wait();
116 outb(PS2_DATA_PORT, PS2_DEV_RESET);
117 ps2_output_wait();
118 resp = inb(PS2_DATA_PORT);
119 }
120
121 if (resp == SELF_TEST_BAD || resp == SELF_TEST_BAD_2) {
122 dev_2_test = 0;
123 kprint("ps2: Port 2 device self test failed!\n", 0);
124 if (!dev_1_test) {
125 kprint("ps2: No functioning devices, exiting!\n", 0);
126 return -1;
127 }
128 } else { dev_2_test = 1; kprint("ps2: Port 2 test successful\n", 0); }
129 }
130 */
131
132 ps2_input_wait();
133 outb(PS2_CMD_STS_PORT, PS2_CMD_READ_CCB);
134 ps2_output_wait();
135 ccb = inb(PS2_DATA_PORT);
136
137 SET(ccb, PORT_1_IRQ);
138
139 ps2_input_wait();
140 outb(PS2_CMD_STS_PORT, PS2_CMD_WRITE_CCB);
141 ps2_input_wait();
142 outb(PS2_DATA_PORT, ccb);
143
144 if (dev_2_test && dev_1_test) return 1;
145 else return 0;
146 }
147
148 void ps2_output_wait()
149 {
150 uint8_t status;
151 status = inb(PS2_CMD_STS_PORT);
152
153 while (!IS_SET(status, OUT_STATUS)) status = inb(PS2_CMD_STS_PORT);
154 return;
155 }
156
157 void ps2_input_wait()
158 {
159 uint8_t status;
160 status = inb(PS2_CMD_STS_PORT);
161
162 while (IS_SET(status, IN_STATUS)) status = inb(PS2_CMD_STS_PORT);
163 return;
164 }