Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / drivers / char / mouse / ps2.c
blob6ae8a20a6c35c53aa72267fcf1d31b940efa8b1e
1 /*
2 * ZeX/OS
3 * Copyright (C) 2009 Martin 'povik' Poviser (martin.povik@gmail.com)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <build.h>
22 #ifdef ARCH_i386
24 #include <system.h>
25 #include <arch/io.h>
26 #include <mouse.h>
27 #include <task.h>
29 #define PS2MOUSE_TIMEOUT 500000
30 #define PS2MOUSE_ACK 0xFA
31 #define PS2MOUSE_PORT 0x60
32 #define PS2MOUSE_CTRL 0x64
33 #define PS2MOUSE_COMMAND 0xD4
34 #define PS2MOUSE_COMMAND_RESET 0xFF
35 #define PS2MOUSE_COMMAND_GET_MOUSE_ID 0xF2
36 #define PS2MOUSE_COMMAND_GET_PACKET 0xEB
37 #define PS2MOUSE_COMMAND_ENABLE_PACKETS 0xF4
38 #define PS2MOUSE_COMMAND_SET_SAMPLERATE 0xF3
39 #define PS2MOUSE_COMMAND_SET_RESOLUTION 0xE8
40 #define PS2MOUSE_COMMAND_SET_REMOTE 0xF0
41 #define PS2MOUSE_RESET_ACK 0xAA
42 #define PS2MOUSE_IRQ 12
44 #define PS2MOUSE_SAMPLERATE_80 0x50
45 #define PS2MOUSE_SAMPLERATE_100 0x64
46 #define PS2MOUSE_SAMPLERATE_200 0xC8
48 #define PS2MOUSE_SAMPLERATE PS2MOUSE_SAMPLERATE_100
51 static unsigned ps2mouse_extwheel = 0;
52 static unsigned ps2mouse_extbuttons = 0;
54 static dev_mouse_t ps2mouse_state;
55 static dev_mouse_t ps2mouse_cache;
57 static unsigned ps2mouse_reset ();
58 static unsigned ps2mouse_write (unsigned char command);
59 static unsigned char ps2mouse_read ();
61 /* ps2mouse_reset - reset mouse */
63 unsigned ps2mouse_reset ()
65 int timeout;
67 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
68 if((inb (PS2MOUSE_CTRL) && 0x02) != 0x02)
69 break;
72 outb (PS2MOUSE_CTRL, PS2MOUSE_COMMAND);
73 outb (PS2MOUSE_PORT, PS2MOUSE_COMMAND_RESET);
75 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
76 unsigned char state = ps2mouse_read ();
78 if (state == PS2MOUSE_RESET_ACK)
79 return 1;
81 if (state == -1)
82 return 0;
85 return 0;
88 /* ps2mouse_write - send a command to mouse */
90 unsigned ps2mouse_write (unsigned char command)
92 int timeout;
94 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
95 if((inb (PS2MOUSE_CTRL) && 0x02) != 0x02)
96 break;
99 outb (PS2MOUSE_CTRL, PS2MOUSE_COMMAND);
100 outb (PS2MOUSE_PORT, command);
102 short read = ps2mouse_read ();
104 if (read == PS2MOUSE_ACK)
105 return 1;
107 if (read == -1)
108 return 0;
110 return 0;
113 /* ps2mouse_read - read a value from mouse */
115 unsigned char ps2mouse_read ()
117 int timeout;
119 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
120 if ((inb (PS2MOUSE_CTRL) && 0x01) == 0x01)
121 return inb (PS2MOUSE_PORT);
124 return -1;
127 /* ps2mouse_get_state - get a mouse state */
129 unsigned ps2mouse_get_state ()
131 unsigned char b1, b2, b3, b4 = 0;
133 if (ps2mouse_write (PS2MOUSE_COMMAND_GET_PACKET) == -1)
134 return 0;
136 b1 = ps2mouse_read ();
137 b2 = ps2mouse_read ();
138 b3 = ps2mouse_read ();
140 if (ps2mouse_extwheel || ps2mouse_extbuttons)
141 b4 = ps2mouse_read ();
143 ps2mouse_state.flags = 0;
144 ps2mouse_state.flags |= ((b1 & 1) ? MOUSE_FLAG_BUTTON1 : 0);
145 ps2mouse_state.flags |= ((b1 & 2) ? MOUSE_FLAG_BUTTON2 : 0);
146 ps2mouse_state.flags |= ((b1 & 3) ? MOUSE_FLAG_BUTTON3 : 0);
147 ps2mouse_state.flags |= ((b1 & 4) ? MOUSE_FLAG_BUTTON4 : 0);
148 ps2mouse_state.flags |= ((b1 & 5) ? MOUSE_FLAG_BUTTON5 : 0);
150 short dx, dy, dz;
152 dx = (b1 & 0x10) ? b2 - 256 : b2;
153 dy = (b1 & 0x20) ? -(b3 - 256) : -b3;
154 dz = (b4 & 0x08) ? (b4 & 7) - 8 : b4 & 7;
156 if (dx > 5 || dx < -5)
157 dx *= 4;
158 if (dy > 5 || dy < -5)
159 dy *= 4;
161 ps2mouse_state.pos_x = dx;
162 ps2mouse_state.pos_y = dy;
164 if (dz > 0)
165 ps2mouse_state.flags = ps2mouse_state.flags | MOUSE_FLAG_SCROLLUP;
166 if (dz < 0)
167 ps2mouse_state.flags = ps2mouse_state.flags | MOUSE_FLAG_SCROLLDOWN;
169 return 1;
172 unsigned char ps2mouse_get_mouseid ()
174 short mouse_id;
176 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
177 ps2mouse_write (PS2MOUSE_SAMPLERATE_200);
179 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
180 ps2mouse_write (PS2MOUSE_SAMPLERATE_100);
182 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
183 ps2mouse_write (PS2MOUSE_SAMPLERATE_80);
185 ps2mouse_write (PS2MOUSE_COMMAND_GET_MOUSE_ID);
186 mouse_id = ps2mouse_read ();
188 if (mouse_id < 3)
189 goto ret;
190 else
191 ps2mouse_extwheel = true;
193 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
194 ps2mouse_write (PS2MOUSE_SAMPLERATE_200);
196 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
197 ps2mouse_write (PS2MOUSE_SAMPLERATE_200);
199 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
200 ps2mouse_write (PS2MOUSE_SAMPLERATE_80);
202 ps2mouse_write (PS2MOUSE_COMMAND_GET_MOUSE_ID);
203 mouse_id = ps2mouse_read ();
205 if (mouse_id > 3)
206 ps2mouse_extbuttons = true;
207 ret:
208 return mouse_id;
211 unsigned ps2mouse_init ()
213 int timeout;
215 ps2mouse_extbuttons = false;
216 ps2mouse_extwheel = false;
218 if (!ps2mouse_reset ())
219 return 0;
221 if (ps2mouse_read () != 0) /* mouse type: 0 = PS2, 3 = IMPS/2, 4 = IMEX */
222 return 0;
224 if (ps2mouse_get_mouseid () == -1)
225 return 0;
227 ps2mouse_write (PS2MOUSE_COMMAND_SET_REMOTE);
228 ps2mouse_write (PS2MOUSE_COMMAND_ENABLE_PACKETS);
230 return 1;
233 void ps2mouse_update ()
235 for (;; schedule ()) {
236 if (!ps2mouse_state.pos_x && !ps2mouse_state.pos_y)
237 ps2mouse_get_state ();
241 bool ps2mouse_acthandler (unsigned act, char *block, unsigned block_len)
243 switch (act) {
244 case DEV_ACT_INIT:
246 dev_flags_t *flags = (dev_flags_t *) block;
248 if (!flags)
249 return 0;
251 if (block_len != sizeof (dev_flags_t))
252 return 0;
254 unsigned r = ps2mouse_init ();
256 if (!r)
257 return 0;
259 flags->iomem = (void *) &ps2mouse_state;
260 flags->iolen = sizeof (dev_mouse_t);
262 //task_t *task = task_create ("mouseps2", (unsigned) &ps2mouse_update, 255);
264 return r;
266 break;
267 case DEV_ACT_READ:
269 memcpy (block, &ps2mouse_state, sizeof (dev_mouse_t));
271 return 1;
273 break;
274 case DEV_ACT_WRITE:
276 memcpy (&ps2mouse_state, block, sizeof (dev_mouse_t));
278 return 1;
280 break;
281 case DEV_ACT_UPDATE:
283 ps2mouse_get_state ();
285 return 1;
287 break;
290 return 0;
293 #endif