blob: 6da297f101da456a94068b5d305217c7a6121bf5 [file] [log] [blame]
Kevin O'Connor3b897192008-07-20 10:08:59 -04001// Support for handling the PS/2 mouse/keyboard ports.
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05004// Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik
Kevin O'Connor3b897192008-07-20 10:08:59 -04005//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor3b897192008-07-20 10:08:59 -04007
8#include "ioport.h" // inb
9#include "util.h" // dprintf
Kevin O'Connor3693af02012-05-13 12:28:55 -040010#include "biosvar.h" // GET_LOW
Kevin O'Connordd5a8a62010-05-01 19:59:34 -040011#include "ps2port.h" // ps2_kbd_command
Kevin O'Connoraa7c2342013-07-14 15:07:21 -040012#include "pic.h" // pic_eoi1
Kevin O'Connor41639f82013-09-14 19:37:36 -040013#include "romfile.h" // romfile_loadint
Kevin O'Connor3df600b2013-09-14 19:28:55 -040014#include "stacks.h" // yield
Kevin O'Connor3b897192008-07-20 10:08:59 -040015
16
17/****************************************************************
18 * Low level i8042 commands.
19 ****************************************************************/
20
21// Timeout value.
22#define I8042_CTL_TIMEOUT 10000
23
24#define I8042_BUFFER_SIZE 16
25
Kevin O'Connor3b897192008-07-20 10:08:59 -040026static int
27i8042_wait_read(void)
28{
Kevin O'Connordd3588f2008-11-29 12:41:48 -050029 dprintf(7, "i8042_wait_read\n");
Kevin O'Connor3b897192008-07-20 10:08:59 -040030 int i;
31 for (i=0; i<I8042_CTL_TIMEOUT; i++) {
32 u8 status = inb(PORT_PS2_STATUS);
33 if (status & I8042_STR_OBF)
34 return 0;
35 udelay(50);
36 }
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -050037 warn_timeout();
Kevin O'Connor3b897192008-07-20 10:08:59 -040038 return -1;
39}
40
41static int
42i8042_wait_write(void)
43{
Kevin O'Connordd3588f2008-11-29 12:41:48 -050044 dprintf(7, "i8042_wait_write\n");
Kevin O'Connor3b897192008-07-20 10:08:59 -040045 int i;
46 for (i=0; i<I8042_CTL_TIMEOUT; i++) {
47 u8 status = inb(PORT_PS2_STATUS);
48 if (! (status & I8042_STR_IBF))
49 return 0;
50 udelay(50);
51 }
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -050052 warn_timeout();
Kevin O'Connor3b897192008-07-20 10:08:59 -040053 return -1;
54}
55
Kevin O'Connoradaf3732010-09-13 20:22:07 -040056static int
Kevin O'Connor3b897192008-07-20 10:08:59 -040057i8042_flush(void)
58{
Kevin O'Connordd3588f2008-11-29 12:41:48 -050059 dprintf(7, "i8042_flush\n");
Kevin O'Connor3b897192008-07-20 10:08:59 -040060 int i;
61 for (i=0; i<I8042_BUFFER_SIZE; i++) {
62 u8 status = inb(PORT_PS2_STATUS);
Kevin O'Connor10ad7992009-10-24 11:06:08 -040063 if (! (status & I8042_STR_OBF))
Kevin O'Connor3b897192008-07-20 10:08:59 -040064 return 0;
Kevin O'Connor3b897192008-07-20 10:08:59 -040065 udelay(50);
Kevin O'Connor0234cd92009-01-04 12:20:02 -050066 u8 data = inb(PORT_PS2_DATA);
Kevin O'Connor9e91c7b2009-01-17 02:30:21 -050067 dprintf(7, "i8042 flushed %x (status=%x)\n", data, status);
Kevin O'Connor3b897192008-07-20 10:08:59 -040068 }
69
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -050070 warn_timeout();
Kevin O'Connor3b897192008-07-20 10:08:59 -040071 return -1;
72}
73
74static int
75__i8042_command(int command, u8 *param)
76{
77 int receive = (command >> 8) & 0xf;
78 int send = (command >> 12) & 0xf;
79
80 // Send the command.
81 int ret = i8042_wait_write();
82 if (ret)
83 return ret;
84 outb(command, PORT_PS2_STATUS);
85
86 // Send parameters (if any).
87 int i;
88 for (i = 0; i < send; i++) {
89 ret = i8042_wait_write();
90 if (ret)
91 return ret;
92 outb(param[i], PORT_PS2_DATA);
93 }
94
95 // Receive parameters (if any).
96 for (i = 0; i < receive; i++) {
97 ret = i8042_wait_read();
98 if (ret)
99 return ret;
100 param[i] = inb(PORT_PS2_DATA);
Kevin O'Connor0234cd92009-01-04 12:20:02 -0500101 dprintf(7, "i8042 param=%x\n", param[i]);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400102 }
103
104 return 0;
105}
106
Kevin O'Connoradaf3732010-09-13 20:22:07 -0400107static int
Kevin O'Connor3b897192008-07-20 10:08:59 -0400108i8042_command(int command, u8 *param)
109{
Kevin O'Connordd3588f2008-11-29 12:41:48 -0500110 dprintf(7, "i8042_command cmd=%x\n", command);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400111 int ret = __i8042_command(command, param);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400112 if (ret)
113 dprintf(2, "i8042 command %x failed\n", command);
114 return ret;
115}
116
117static int
118i8042_kbd_write(u8 c)
119{
Kevin O'Connordd3588f2008-11-29 12:41:48 -0500120 dprintf(7, "i8042_kbd_write c=%d\n", c);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400121 int ret = i8042_wait_write();
122 if (! ret)
123 outb(c, PORT_PS2_DATA);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400124 return ret;
125}
126
127static int
128i8042_aux_write(u8 c)
129{
130 return i8042_command(I8042_CMD_AUX_SEND, &c);
131}
132
Kevin O'Connoradaf3732010-09-13 20:22:07 -0400133void
134i8042_reboot(void)
135{
Kevin O'Connore216ce82012-01-29 12:25:46 -0500136 if (! CONFIG_PS2PORT)
137 return;
Kevin O'Connoradaf3732010-09-13 20:22:07 -0400138 int i;
139 for (i=0; i<10; i++) {
140 i8042_wait_write();
141 udelay(50);
142 outb(0xfe, PORT_PS2_STATUS); /* pulse reset low */
143 udelay(50);
144 }
145}
146
Kevin O'Connor3b897192008-07-20 10:08:59 -0400147
148/****************************************************************
149 * Device commands.
150 ****************************************************************/
151
152#define PS2_RET_ACK 0xfa
153#define PS2_RET_NAK 0xfe
154
155static int
Kevin O'Connor0234cd92009-01-04 12:20:02 -0500156ps2_recvbyte(int aux, int needack, int timeout)
157{
Kevin O'Connor018bdd72013-07-20 18:22:57 -0400158 u32 end = timer_calc(timeout);
Kevin O'Connor0234cd92009-01-04 12:20:02 -0500159 for (;;) {
Kevin O'Connor10ad7992009-10-24 11:06:08 -0400160 u8 status = inb(PORT_PS2_STATUS);
161 if (status & I8042_STR_OBF) {
162 u8 data = inb(PORT_PS2_DATA);
163 dprintf(7, "ps2 read %x\n", data);
164
165 if (!!(status & I8042_STR_AUXDATA) == aux) {
166 if (!needack)
167 return data;
168 if (data == PS2_RET_ACK)
169 return data;
170 if (data == PS2_RET_NAK) {
Kevin O'Connor6080fe02009-12-02 21:19:30 -0500171 dprintf(1, "Got ps2 nak (status=%x)\n", status);
Kevin O'Connor10ad7992009-10-24 11:06:08 -0400172 return data;
173 }
174 }
175
Kevin O'Connorf6282442010-03-13 21:05:12 -0500176 // This data not part of command - just discard it.
177 dprintf(1, "Discarding ps2 data %02x (status=%02x)\n", data, status);
Kevin O'Connor10ad7992009-10-24 11:06:08 -0400178 }
179
Kevin O'Connor018bdd72013-07-20 18:22:57 -0400180 if (timer_check(end)) {
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -0500181 // Don't warn on second byte of a reset
182 if (timeout > 100)
183 warn_timeout();
Kevin O'Connor0234cd92009-01-04 12:20:02 -0500184 return -1;
185 }
Kevin O'Connor10ad7992009-10-24 11:06:08 -0400186 yield();
Kevin O'Connor0234cd92009-01-04 12:20:02 -0500187 }
188}
189
190static int
Kevin O'Connor235df202009-01-18 12:54:51 -0500191ps2_sendbyte(int aux, u8 command, int timeout)
Kevin O'Connor3b897192008-07-20 10:08:59 -0400192{
Kevin O'Connordd3588f2008-11-29 12:41:48 -0500193 dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400194 int ret;
195 if (aux)
196 ret = i8042_aux_write(command);
197 else
198 ret = i8042_kbd_write(command);
199 if (ret)
200 return ret;
201
202 // Read ack.
Kevin O'Connorb44a8522009-01-17 23:30:01 -0500203 ret = ps2_recvbyte(aux, 1, timeout);
Kevin O'Connor0234cd92009-01-04 12:20:02 -0500204 if (ret < 0)
Kevin O'Connor3b897192008-07-20 10:08:59 -0400205 return ret;
Kevin O'Connor6080fe02009-12-02 21:19:30 -0500206 if (ret != PS2_RET_ACK)
207 return -1;
Kevin O'Connor3b897192008-07-20 10:08:59 -0400208
209 return 0;
210}
211
Kevin O'Connor3693af02012-05-13 12:28:55 -0400212u8 Ps2ctr VARLOW;
213
Kevin O'Connor3b897192008-07-20 10:08:59 -0400214static int
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400215__ps2_command(int aux, int command, u8 *param)
Kevin O'Connor3b897192008-07-20 10:08:59 -0400216{
Kevin O'Connor6704cf92010-03-13 18:51:46 -0500217 int ret2;
Kevin O'Connor3b897192008-07-20 10:08:59 -0400218 int receive = (command >> 8) & 0xf;
219 int send = (command >> 12) & 0xf;
220
Kevin O'Connor6704cf92010-03-13 18:51:46 -0500221 // Disable interrupts and keyboard/mouse.
Kevin O'Connor3693af02012-05-13 12:28:55 -0400222 u8 ps2ctr = GET_LOW(Ps2ctr);
Kevin O'Connorf6282442010-03-13 21:05:12 -0500223 u8 newctr = ((ps2ctr | I8042_CTR_AUXDIS | I8042_CTR_KBDDIS)
224 & ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT));
Kevin O'Connor6704cf92010-03-13 18:51:46 -0500225 dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr);
226 int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
227 if (ret)
228 return ret;
Kevin O'Connor3b897192008-07-20 10:08:59 -0400229
Kevin O'Connor67a9eec2010-03-13 19:00:02 -0500230 // Flush any interrupts already pending.
231 yield();
232
Kevin O'Connorf6282442010-03-13 21:05:12 -0500233 // Enable port command is being sent to.
234 if (aux)
235 newctr &= ~I8042_CTR_AUXDIS;
236 else
237 newctr &= ~I8042_CTR_KBDDIS;
238 ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
239 if (ret)
240 goto fail;
241
Kevin O'Connor235df202009-01-18 12:54:51 -0500242 if (command == ATKBD_CMD_RESET_BAT) {
Kevin O'Connorb9ed5e22010-03-13 19:59:24 -0500243 // Reset is special wrt timeouts and bytes received.
Kevin O'Connor3b897192008-07-20 10:08:59 -0400244
Kevin O'Connor235df202009-01-18 12:54:51 -0500245 // Send command.
246 ret = ps2_sendbyte(aux, command, 1000);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400247 if (ret)
248 goto fail;
Kevin O'Connor235df202009-01-18 12:54:51 -0500249
250 // Receive parameters.
251 ret = ps2_recvbyte(aux, 0, 4000);
252 if (ret < 0)
253 goto fail;
254 param[0] = ret;
255 ret = ps2_recvbyte(aux, 0, 100);
256 if (ret < 0)
257 // Some devices only respond with one byte on reset.
258 ret = 0;
259 param[1] = ret;
Kevin O'Connorb9ed5e22010-03-13 19:59:24 -0500260 } else if (command == ATKBD_CMD_GETID) {
261 // Getid is special wrt bytes received.
262
263 // Send command.
264 ret = ps2_sendbyte(aux, command, 200);
265 if (ret)
266 goto fail;
267
268 // Receive parameters.
269 ret = ps2_recvbyte(aux, 0, 500);
270 if (ret < 0)
271 goto fail;
272 param[0] = ret;
273 if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d
274 || ret == 0x60 || ret == 0x47) {
275 // These ids (keyboards) return two bytes.
276 ret = ps2_recvbyte(aux, 0, 500);
277 if (ret < 0)
278 goto fail;
279 param[1] = ret;
280 } else {
281 param[1] = 0;
282 }
Kevin O'Connor235df202009-01-18 12:54:51 -0500283 } else {
284 // Send command.
285 ret = ps2_sendbyte(aux, command, 200);
286 if (ret)
287 goto fail;
288
289 // Send parameters (if any).
290 int i;
291 for (i = 0; i < send; i++) {
292 ret = ps2_sendbyte(aux, param[i], 200);
293 if (ret)
294 goto fail;
295 }
296
297 // Receive parameters (if any).
298 for (i = 0; i < receive; i++) {
299 ret = ps2_recvbyte(aux, 0, 500);
300 if (ret < 0)
301 goto fail;
302 param[i] = ret;
303 }
Kevin O'Connor3b897192008-07-20 10:08:59 -0400304 }
305
Kevin O'Connor235df202009-01-18 12:54:51 -0500306 ret = 0;
Kevin O'Connor3b897192008-07-20 10:08:59 -0400307
308fail:
Kevin O'Connor6704cf92010-03-13 18:51:46 -0500309 // Restore interrupts and keyboard/mouse.
310 ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr);
311 if (ret2)
312 return ret2;
Kevin O'Connor3b897192008-07-20 10:08:59 -0400313
314 return ret;
315}
316
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400317static int
318ps2_command(int aux, int command, u8 *param)
Kevin O'Connor3b897192008-07-20 10:08:59 -0400319{
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400320 dprintf(7, "ps2_command aux=%d cmd=%x\n", aux, command);
321 int ret = __ps2_command(aux, command, param);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400322 if (ret)
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400323 dprintf(2, "ps2 command %x failed (aux=%d)\n", command, aux);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400324 return ret;
325}
326
327int
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400328ps2_kbd_command(int command, u8 *param)
Kevin O'Connor3b897192008-07-20 10:08:59 -0400329{
Kevin O'Connore216ce82012-01-29 12:25:46 -0500330 if (! CONFIG_PS2PORT)
331 return -1;
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400332 return ps2_command(0, command, param);
333}
334
335int
336ps2_mouse_command(int command, u8 *param)
337{
Kevin O'Connore216ce82012-01-29 12:25:46 -0500338 if (! CONFIG_PS2PORT)
339 return -1;
340
Kevin O'Connor9ead6fc2011-05-07 14:19:29 -0400341 // Update ps2ctr for mouse enable/disable.
342 if (command == PSMOUSE_CMD_ENABLE || command == PSMOUSE_CMD_DISABLE) {
Kevin O'Connor3693af02012-05-13 12:28:55 -0400343 u8 ps2ctr = GET_LOW(Ps2ctr);
Kevin O'Connor9ead6fc2011-05-07 14:19:29 -0400344 if (command == PSMOUSE_CMD_ENABLE)
345 ps2ctr = (ps2ctr | I8042_CTR_AUXINT) & ~I8042_CTR_AUXDIS;
346 else
347 ps2ctr = (ps2ctr | I8042_CTR_AUXDIS) & ~I8042_CTR_AUXINT;
Kevin O'Connor3693af02012-05-13 12:28:55 -0400348 SET_LOW(Ps2ctr, ps2ctr);
Kevin O'Connor9ead6fc2011-05-07 14:19:29 -0400349 }
350
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400351 return ps2_command(1, command, param);
Kevin O'Connor3b897192008-07-20 10:08:59 -0400352}
Kevin O'Connor57877482009-12-09 21:00:41 -0500353
354
355/****************************************************************
356 * IRQ handlers
357 ****************************************************************/
358
359// INT74h : PS/2 mouse hardware interrupt
360void VISIBLE16
Kevin O'Connor1297e5d2012-06-02 20:30:58 -0400361handle_74(void)
Kevin O'Connor57877482009-12-09 21:00:41 -0500362{
363 if (! CONFIG_PS2PORT)
364 return;
365
Kevin O'Connor1297e5d2012-06-02 20:30:58 -0400366 debug_isr(DEBUG_ISR_74);
Kevin O'Connora5d84582010-03-13 20:06:34 -0500367
368 u8 v = inb(PORT_PS2_STATUS);
369 if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
370 != (I8042_STR_OBF|I8042_STR_AUXDATA)) {
Kevin O'Connorf6282442010-03-13 21:05:12 -0500371 dprintf(1, "ps2 mouse irq but no mouse data.\n");
Kevin O'Connora5d84582010-03-13 20:06:34 -0500372 goto done;
373 }
374 v = inb(PORT_PS2_DATA);
375
Kevin O'Connor3693af02012-05-13 12:28:55 -0400376 if (!(GET_LOW(Ps2ctr) & I8042_CTR_AUXINT))
Kevin O'Connorf6282442010-03-13 21:05:12 -0500377 // Interrupts not enabled.
378 goto done;
379
Kevin O'Connora5d84582010-03-13 20:06:34 -0500380 process_mouse(v);
381
382done:
Kevin O'Connoraa7c2342013-07-14 15:07:21 -0400383 pic_eoi2();
Kevin O'Connor57877482009-12-09 21:00:41 -0500384}
385
386// INT09h : Keyboard Hardware Service Entry Point
387void VISIBLE16
Kevin O'Connor1297e5d2012-06-02 20:30:58 -0400388handle_09(void)
Kevin O'Connor57877482009-12-09 21:00:41 -0500389{
390 if (! CONFIG_PS2PORT)
391 return;
392
Kevin O'Connor1297e5d2012-06-02 20:30:58 -0400393 debug_isr(DEBUG_ISR_09);
Kevin O'Connora5d84582010-03-13 20:06:34 -0500394
395 // read key from keyboard controller
396 u8 v = inb(PORT_PS2_STATUS);
Kevin O'Connorf6282442010-03-13 21:05:12 -0500397 if (v & I8042_STR_AUXDATA) {
398 dprintf(1, "ps2 keyboard irq but found mouse data?!\n");
Kevin O'Connora5d84582010-03-13 20:06:34 -0500399 goto done;
400 }
401 v = inb(PORT_PS2_DATA);
402
Kevin O'Connor3693af02012-05-13 12:28:55 -0400403 if (!(GET_LOW(Ps2ctr) & I8042_CTR_KBDINT))
Kevin O'Connorf6282442010-03-13 21:05:12 -0500404 // Interrupts not enabled.
405 goto done;
406
Kevin O'Connora5d84582010-03-13 20:06:34 -0500407 process_key(v);
408
Kevin O'Connor90ce89f2012-03-11 20:45:56 -0400409 // Some old programs expect ISR to turn keyboard back on.
410 i8042_command(I8042_CMD_KBD_ENABLE, NULL);
411
Kevin O'Connora5d84582010-03-13 20:06:34 -0500412done:
Kevin O'Connoraa7c2342013-07-14 15:07:21 -0400413 pic_eoi1();
Kevin O'Connor57877482009-12-09 21:00:41 -0500414}
415
416
417/****************************************************************
418 * Setup
419 ****************************************************************/
420
421static void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500422ps2_keyboard_setup(void *data)
Kevin O'Connor57877482009-12-09 21:00:41 -0500423{
424 /* flush incoming keys */
425 int ret = i8042_flush();
426 if (ret)
427 return;
428
429 // Controller self-test.
430 u8 param[2];
431 ret = i8042_command(I8042_CMD_CTL_TEST, param);
432 if (ret)
433 return;
434 if (param[0] != 0x55) {
435 dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]);
436 return;
437 }
438
439 // Controller keyboard test.
440 ret = i8042_command(I8042_CMD_KBD_TEST, param);
441 if (ret)
442 return;
443 if (param[0] != 0x00) {
444 dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]);
445 return;
446 }
447
Kevin O'Connorf6282442010-03-13 21:05:12 -0500448 // Disable keyboard and mouse events.
Kevin O'Connor3693af02012-05-13 12:28:55 -0400449 SET_LOW(Ps2ctr, I8042_CTR_KBDDIS | I8042_CTR_AUXDIS);
Kevin O'Connor57877482009-12-09 21:00:41 -0500450
451
452 /* ------------------- keyboard side ------------------------*/
453 /* reset keyboard and self test (keyboard side) */
Kevin O'Connoraafe4422011-07-05 20:44:00 -0400454 int spinupdelay = romfile_loadint("etc/ps2-keyboard-spinup", 0);
Kevin O'Connor018bdd72013-07-20 18:22:57 -0400455 u32 end = timer_calc(spinupdelay);
Kevin O'Connor299dc132011-05-28 11:00:28 -0400456 for (;;) {
457 ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param);
458 if (!ret)
459 break;
Kevin O'Connor018bdd72013-07-20 18:22:57 -0400460 if (timer_check(end)) {
Kevin O'Connoraafe4422011-07-05 20:44:00 -0400461 if (spinupdelay)
Kevin O'Connor299dc132011-05-28 11:00:28 -0400462 warn_timeout();
463 return;
464 }
465 yield();
466 }
Kevin O'Connor57877482009-12-09 21:00:41 -0500467 if (param[0] != 0xaa) {
468 dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]);
469 return;
470 }
471
472 /* Disable keyboard */
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400473 ret = ps2_kbd_command(ATKBD_CMD_RESET_DIS, NULL);
Kevin O'Connor57877482009-12-09 21:00:41 -0500474 if (ret)
475 return;
476
477 // Set scancode command (mode 2)
478 param[0] = 0x02;
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400479 ret = ps2_kbd_command(ATKBD_CMD_SSCANSET, param);
Kevin O'Connor57877482009-12-09 21:00:41 -0500480 if (ret)
481 return;
482
Kevin O'Connorf6282442010-03-13 21:05:12 -0500483 // Keyboard Mode: disable mouse, scan code convert, enable kbd IRQ
Kevin O'Connor3693af02012-05-13 12:28:55 -0400484 SET_LOW(Ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT);
Kevin O'Connor57877482009-12-09 21:00:41 -0500485
486 /* Enable keyboard */
Kevin O'Connordd5a8a62010-05-01 19:59:34 -0400487 ret = ps2_kbd_command(ATKBD_CMD_ENABLE, NULL);
Kevin O'Connor57877482009-12-09 21:00:41 -0500488 if (ret)
489 return;
490
Kevin O'Connor357bdfa2010-02-26 08:57:13 -0500491 dprintf(1, "PS2 keyboard initialized\n");
Kevin O'Connor57877482009-12-09 21:00:41 -0500492}
493
494void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500495ps2port_setup(void)
Kevin O'Connor57877482009-12-09 21:00:41 -0500496{
Kevin O'Connor59c75742010-02-13 18:49:24 -0500497 ASSERT32FLAT();
Kevin O'Connor57877482009-12-09 21:00:41 -0500498 if (! CONFIG_PS2PORT)
499 return;
500 dprintf(3, "init ps2port\n");
501
Kevin O'Connorcc9e1bf2010-07-28 21:31:38 -0400502 enable_hwirq(1, FUNC16(entry_09));
503 enable_hwirq(12, FUNC16(entry_74));
Kevin O'Connor57877482009-12-09 21:00:41 -0500504
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500505 run_thread(ps2_keyboard_setup, NULL);
Kevin O'Connor57877482009-12-09 21:00:41 -0500506}