whitespace
[AROS.git] / rom / hidds / i8042 / kbd_common.c
blobb69305a50543612908255ab979a4a9ad9be6f914
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Low-level routines for i8042 controller.
6 Lang: English.
7 */
9 #include "kbd.h"
10 #include "kbd_common.h"
12 #define TIMER_RPROK 3599597124UL
14 static int wait_for_input(ULONG timeout);
16 static ULONG usec2tick(ULONG usec)
18 ULONG ret;
19 ULONG prok = TIMER_RPROK;
20 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(prok));
21 return ret;
25 * !!! FIXME PLEASE !!!
26 * These delays cannot be just converted to timer.device, because they are
27 * used also by kbd_updateleds() function, which is called from within interrupt.
28 * Delays inside interrupts are evil, and this needs one more serious refactoring
29 * iteration. I think LED control can be delegated to separate task, which is
30 * signalled by interrupt code when update is needed.
31 * After this delays can be converted to timer.device. Mouse driver does not use
32 * them inside interrupt.
34 void kbd_usleep(LONG usec)
36 int oldtick, tick;
37 usec = usec2tick(usec);
39 outb(0x80, 0x43);
40 oldtick = inb(0x42);
41 oldtick += inb(0x42) << 8;
43 while (usec > 0)
45 outb(0x80, 0x43);
46 tick = inb(0x42);
47 tick += inb(0x42) << 8;
49 usec -= (oldtick - tick);
50 if (tick > oldtick) usec -= 0x10000;
51 oldtick = tick;
55 unsigned char handle_kbd_event(void)
57 unsigned char status = kbd_read_status();
58 unsigned int work = 10000;
60 while (status & KBD_STATUS_OBF)
62 kbd_read_input();
64 status = kbd_read_status();
65 if(!work--)
67 //printf(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n",status);
68 break;
71 return status;
75 * Wait until we can write to a peripheral again. Any input that comes in
76 * while we're waiting is discarded.
78 void kb_wait(ULONG timeout)
82 unsigned char status = handle_kbd_event();
83 if (! (status & KBD_STATUS_IBF))
84 return;
86 kbd_usleep(1000);
87 timeout--;
88 } while (timeout);
91 void kbd_write_cmd(int cmd)
93 kb_wait(100);
94 kbd_write_command(KBD_CTRLCMD_WRITE_MODE);
95 kb_wait(100);
96 kbd_write_output(cmd);
100 * Aux (mouse) port uses longer delays, this is necessary
101 * in order to detect IntelliMouse properly
103 void aux_write_ack(int val)
105 kb_wait(1000);
106 kbd_write_command(KBD_CTRLCMD_WRITE_MOUSE);
107 kb_wait(1000);
108 kbd_write_output(val);
109 aux_wait_for_input();
112 void aux_write_noack(int val)
114 kb_wait(1000);
115 kbd_write_command(KBD_CTRLCMD_WRITE_MOUSE);
116 kb_wait(1000);
117 kbd_write_output(val);
120 void kbd_write_output_w(int data)
122 kb_wait(100);
123 kbd_write_output(data);
126 void kbd_write_command_w(int data)
128 kb_wait(100);
129 kbd_write_command(data);
132 int kbd_read_data(void)
134 LONG retval = KBD_NO_DATA;
135 UBYTE status;
137 status = kbd_read_status();
138 if (status & KBD_STATUS_OBF)
140 UBYTE data = kbd_read_input();
142 retval = data;
143 if (status & (KBD_STATUS_GTO | KBD_STATUS_PERR))
144 retval = KBD_BAD_DATA;
147 return retval;
150 int kbd_clear_input(void)
152 int maxread = 100, code, lastcode = KBD_NO_DATA;
153 UBYTE status;
157 status = kbd_read_status();
158 if ((code = kbd_read_data()) == KBD_NO_DATA)
159 break;
160 if (!(status & KBD_STATUS_MOUSE_OBF))
161 lastcode = code;
162 } while (--maxread);
164 return lastcode;
167 int kbd_wait_for_input(void)
169 return wait_for_input(100);
172 int aux_wait_for_input(void)
174 return wait_for_input(1000);
177 static int wait_for_input(ULONG timeout)
181 int retval = kbd_read_data();
182 if (retval >= 0)
183 return retval;
184 kbd_usleep(1000);
185 } while(--timeout);
186 return -1;