]>
Commit | Line | Data |
---|---|---|
172870ef | 1 | /** @file\r |
2 | PS2 Mouse Communication Interface.\r | |
0a6f4824 LG |
3 | \r |
4 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r | |
c0a00b14 | 5 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
05fbd06d | 6 | \r |
f8cd287b | 7 | **/\r |
05fbd06d | 8 | \r |
05fbd06d | 9 | #include "Ps2Mouse.h"\r |
10 | #include "CommPs2.h"\r | |
11 | \r | |
3ae99102 | 12 | UINT8 SampleRateTbl[MaxSampleRate] = { 0xa, 0x14, 0x28, 0x3c, 0x50, 0x64, 0xc8 };\r |
05fbd06d | 13 | \r |
3ae99102 | 14 | UINT8 ResolutionTbl[MaxResolution] = { 0, 1, 2, 3 };\r |
05fbd06d | 15 | \r |
ff1fcef8 | 16 | /**\r |
17 | Issue self test command via IsaIo interface.\r | |
0a6f4824 | 18 | \r |
ff1fcef8 | 19 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 20 | \r |
ff1fcef8 | 21 | @return EFI_SUCCESS Success to do keyboard self testing.\r |
22 | @return others Fail to do keyboard self testing.\r | |
23 | **/\r | |
05fbd06d | 24 | EFI_STATUS\r |
25 | KbcSelfTest (\r | |
26 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
27 | )\r | |
05fbd06d | 28 | {\r |
29 | EFI_STATUS Status;\r | |
30 | UINT8 Data;\r | |
31 | \r | |
32 | //\r | |
33 | // Keyboard controller self test\r | |
34 | //\r | |
35 | Status = Out8042Command (IsaIo, SELF_TEST);\r | |
36 | if (EFI_ERROR (Status)) {\r | |
37 | return Status;\r | |
38 | }\r | |
39 | //\r | |
40 | // Read return code\r | |
41 | //\r | |
42 | Status = In8042Data (IsaIo, &Data);\r | |
43 | if (EFI_ERROR (Status)) {\r | |
44 | return Status;\r | |
45 | }\r | |
46 | \r | |
47 | if (Data != 0x55) {\r | |
48 | return EFI_DEVICE_ERROR;\r | |
49 | }\r | |
50 | //\r | |
51 | // Set system flag\r | |
52 | //\r | |
53 | Status = Out8042Command (IsaIo, READ_CMD_BYTE);\r | |
54 | if (EFI_ERROR (Status)) {\r | |
55 | return Status;\r | |
56 | }\r | |
57 | \r | |
58 | Status = In8042Data (IsaIo, &Data);\r | |
59 | if (EFI_ERROR (Status)) {\r | |
60 | return Status;\r | |
61 | }\r | |
62 | \r | |
63 | Status = Out8042Command (IsaIo, WRITE_CMD_BYTE);\r | |
64 | if (EFI_ERROR (Status)) {\r | |
65 | return Status;\r | |
66 | }\r | |
67 | \r | |
68 | Data |= CMD_SYS_FLAG;\r | |
69 | Status = Out8042Data (IsaIo, Data);\r | |
70 | if (EFI_ERROR (Status)) {\r | |
71 | return Status;\r | |
72 | }\r | |
73 | \r | |
74 | return EFI_SUCCESS;\r | |
75 | }\r | |
76 | \r | |
ff1fcef8 | 77 | /**\r |
78 | Issue command to enable keyboard AUX functionality.\r | |
0a6f4824 | 79 | \r |
ff1fcef8 | 80 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 81 | \r |
ff1fcef8 | 82 | @return Status of command issuing.\r |
83 | **/\r | |
05fbd06d | 84 | EFI_STATUS\r |
85 | KbcEnableAux (\r | |
86 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
87 | )\r | |
05fbd06d | 88 | {\r |
89 | //\r | |
90 | // Send 8042 enable mouse command\r | |
91 | //\r | |
92 | return Out8042Command (IsaIo, ENABLE_AUX);\r | |
93 | }\r | |
94 | \r | |
ff1fcef8 | 95 | /**\r |
96 | Issue command to disable keyboard AUX functionality.\r | |
0a6f4824 | 97 | \r |
ff1fcef8 | 98 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 99 | \r |
ff1fcef8 | 100 | @return Status of command issuing.\r |
101 | **/\r | |
05fbd06d | 102 | EFI_STATUS\r |
103 | KbcDisableAux (\r | |
104 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
105 | )\r | |
05fbd06d | 106 | {\r |
107 | //\r | |
108 | // Send 8042 disable mouse command\r | |
109 | //\r | |
110 | return Out8042Command (IsaIo, DISABLE_AUX);\r | |
111 | }\r | |
112 | \r | |
ff1fcef8 | 113 | /**\r |
114 | Issue command to enable keyboard.\r | |
0a6f4824 | 115 | \r |
ff1fcef8 | 116 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 117 | \r |
ff1fcef8 | 118 | @return Status of command issuing.\r |
119 | **/\r | |
05fbd06d | 120 | EFI_STATUS\r |
121 | KbcEnableKb (\r | |
122 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
123 | )\r | |
05fbd06d | 124 | {\r |
125 | //\r | |
126 | // Send 8042 enable keyboard command\r | |
127 | //\r | |
128 | return Out8042Command (IsaIo, ENABLE_KB);\r | |
129 | }\r | |
130 | \r | |
ff1fcef8 | 131 | /**\r |
132 | Issue command to disable keyboard.\r | |
0a6f4824 | 133 | \r |
ff1fcef8 | 134 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 135 | \r |
ff1fcef8 | 136 | @return Status of command issuing.\r |
137 | **/\r | |
05fbd06d | 138 | EFI_STATUS\r |
139 | KbcDisableKb (\r | |
140 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
141 | )\r | |
05fbd06d | 142 | {\r |
143 | //\r | |
144 | // Send 8042 disable keyboard command\r | |
145 | //\r | |
146 | return Out8042Command (IsaIo, DISABLE_KB);\r | |
147 | }\r | |
148 | \r | |
ff1fcef8 | 149 | /**\r |
150 | Issue command to check keyboard status.\r | |
0a6f4824 | 151 | \r |
ff1fcef8 | 152 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
153 | @param KeyboardEnable return whether keyboard is enable.\r | |
0a6f4824 | 154 | \r |
ff1fcef8 | 155 | @return Status of command issuing.\r |
156 | **/\r | |
05fbd06d | 157 | EFI_STATUS\r |
158 | CheckKbStatus (\r | |
159 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
160 | OUT BOOLEAN *KeyboardEnable\r | |
161 | )\r | |
05fbd06d | 162 | {\r |
163 | EFI_STATUS Status;\r | |
164 | UINT8 Data;\r | |
165 | \r | |
166 | //\r | |
167 | // Send command to read KBC command byte\r | |
168 | //\r | |
169 | Status = Out8042Command (IsaIo, READ_CMD_BYTE);\r | |
170 | if (EFI_ERROR (Status)) {\r | |
171 | return Status;\r | |
172 | }\r | |
173 | \r | |
174 | Status = In8042Data (IsaIo, &Data);\r | |
175 | if (EFI_ERROR (Status)) {\r | |
176 | return Status;\r | |
177 | }\r | |
178 | //\r | |
179 | // Check keyboard enable or not\r | |
180 | //\r | |
181 | if ((Data & CMD_KB_STS) == CMD_KB_DIS) {\r | |
182 | *KeyboardEnable = FALSE;\r | |
183 | } else {\r | |
184 | *KeyboardEnable = TRUE;\r | |
185 | }\r | |
186 | \r | |
187 | return EFI_SUCCESS;\r | |
188 | }\r | |
189 | \r | |
ff1fcef8 | 190 | /**\r |
191 | Issue command to reset keyboard.\r | |
0a6f4824 | 192 | \r |
ff1fcef8 | 193 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 194 | \r |
ff1fcef8 | 195 | @return Status of command issuing.\r |
196 | **/\r | |
05fbd06d | 197 | EFI_STATUS\r |
198 | PS2MouseReset (\r | |
199 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
200 | )\r | |
05fbd06d | 201 | {\r |
202 | EFI_STATUS Status;\r | |
203 | UINT8 Data;\r | |
204 | \r | |
205 | Status = Out8042AuxCommand (IsaIo, RESET_CMD, FALSE);\r | |
206 | if (EFI_ERROR (Status)) {\r | |
207 | return Status;\r | |
208 | }\r | |
209 | \r | |
210 | Status = In8042AuxData (IsaIo, &Data);\r | |
211 | if (EFI_ERROR (Status)) {\r | |
212 | return Status;\r | |
213 | }\r | |
214 | //\r | |
215 | // Check BAT Complete Code\r | |
216 | //\r | |
217 | if (Data != PS2MOUSE_BAT1) {\r | |
218 | return EFI_DEVICE_ERROR;\r | |
219 | }\r | |
220 | \r | |
221 | Status = In8042AuxData (IsaIo, &Data);\r | |
222 | if (EFI_ERROR (Status)) {\r | |
223 | return Status;\r | |
224 | }\r | |
225 | //\r | |
226 | // Check BAT Complete Code\r | |
227 | //\r | |
228 | if (Data != PS2MOUSE_BAT2) {\r | |
229 | return EFI_DEVICE_ERROR;\r | |
230 | }\r | |
231 | \r | |
232 | return EFI_SUCCESS;\r | |
233 | }\r | |
234 | \r | |
ff1fcef8 | 235 | /**\r |
236 | Issue command to set mouse's sample rate\r | |
0a6f4824 | 237 | \r |
ff1fcef8 | 238 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 LG |
239 | @param SampleRate value of sample rate\r |
240 | \r | |
ff1fcef8 | 241 | @return Status of command issuing.\r |
242 | **/\r | |
05fbd06d | 243 | EFI_STATUS\r |
244 | PS2MouseSetSampleRate (\r | |
245 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
246 | IN MOUSE_SR SampleRate\r | |
247 | )\r | |
05fbd06d | 248 | {\r |
249 | EFI_STATUS Status;\r | |
250 | \r | |
251 | //\r | |
252 | // Send auxiliary command to set mouse sample rate\r | |
253 | //\r | |
254 | Status = Out8042AuxCommand (IsaIo, SETSR_CMD, FALSE);\r | |
255 | if (EFI_ERROR (Status)) {\r | |
256 | return Status;\r | |
257 | }\r | |
258 | \r | |
259 | Status = Out8042AuxData (IsaIo, SampleRateTbl[SampleRate]);\r | |
260 | \r | |
261 | return Status;\r | |
262 | }\r | |
263 | \r | |
ff1fcef8 | 264 | /**\r |
265 | Issue command to set mouse's resolution.\r | |
0a6f4824 | 266 | \r |
ff1fcef8 | 267 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
268 | @param Resolution value of resolution\r | |
0a6f4824 | 269 | \r |
ff1fcef8 | 270 | @return Status of command issuing.\r |
271 | **/\r | |
05fbd06d | 272 | EFI_STATUS\r |
273 | PS2MouseSetResolution (\r | |
274 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
275 | IN MOUSE_RE Resolution\r | |
276 | )\r | |
05fbd06d | 277 | {\r |
278 | EFI_STATUS Status;\r | |
279 | \r | |
280 | //\r | |
281 | // Send auxiliary command to set mouse resolution\r | |
282 | //\r | |
283 | Status = Out8042AuxCommand (IsaIo, SETRE_CMD, FALSE);\r | |
284 | if (EFI_ERROR (Status)) {\r | |
285 | return Status;\r | |
286 | }\r | |
287 | \r | |
288 | Status = Out8042AuxData (IsaIo, ResolutionTbl[Resolution]);\r | |
289 | \r | |
290 | return Status;\r | |
291 | }\r | |
292 | \r | |
ff1fcef8 | 293 | /**\r |
294 | Issue command to set mouse's scaling.\r | |
0a6f4824 | 295 | \r |
ff1fcef8 | 296 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
297 | @param Scaling value of scaling\r | |
0a6f4824 | 298 | \r |
ff1fcef8 | 299 | @return Status of command issuing.\r |
300 | **/\r | |
05fbd06d | 301 | EFI_STATUS\r |
302 | PS2MouseSetScaling (\r | |
303 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
304 | IN MOUSE_SF Scaling\r | |
305 | )\r | |
05fbd06d | 306 | {\r |
307 | UINT8 Command;\r | |
308 | \r | |
f66d00ca | 309 | Command = (UINT8) (Scaling == Scaling1 ? SETSF1_CMD : SETSF2_CMD);\r |
05fbd06d | 310 | \r |
311 | //\r | |
312 | // Send auxiliary command to set mouse scaling data\r | |
313 | //\r | |
314 | return Out8042AuxCommand (IsaIo, Command, FALSE);\r | |
315 | }\r | |
316 | \r | |
ff1fcef8 | 317 | /**\r |
318 | Issue command to enable Ps2 mouse.\r | |
0a6f4824 | 319 | \r |
ff1fcef8 | 320 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 321 | \r |
ff1fcef8 | 322 | @return Status of command issuing.\r |
323 | **/\r | |
05fbd06d | 324 | EFI_STATUS\r |
325 | PS2MouseEnable (\r | |
326 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
327 | )\r | |
05fbd06d | 328 | {\r |
329 | //\r | |
330 | // Send auxiliary command to enable mouse\r | |
331 | //\r | |
332 | return Out8042AuxCommand (IsaIo, ENABLE_CMD, FALSE);\r | |
333 | }\r | |
334 | \r | |
bcd70414 | 335 | /**\r |
05fbd06d | 336 | Get mouse packet . Only care first 3 bytes\r |
337 | \r | |
0a6f4824 | 338 | @param MouseDev Pointer of PS2 Mouse Private Data Structure\r |
05fbd06d | 339 | \r |
ff1fcef8 | 340 | @retval EFI_NOT_READY Mouse Device not ready to input data packet, or some error happened during getting the packet\r |
341 | @retval EFI_SUCCESS The data packet is gotten successfully.\r | |
05fbd06d | 342 | \r |
bcd70414 | 343 | **/\r |
ff1fcef8 | 344 | EFI_STATUS\r |
345 | PS2MouseGetPacket (\r | |
346 | PS2_MOUSE_DEV *MouseDev\r | |
347 | )\r | |
348 | \r | |
05fbd06d | 349 | {\r |
350 | EFI_STATUS Status;\r | |
351 | BOOLEAN KeyboardEnable;\r | |
352 | UINT8 Packet[PS2_PACKET_LENGTH];\r | |
353 | UINT8 Data;\r | |
354 | UINTN Count;\r | |
355 | UINTN State;\r | |
356 | INT16 RelativeMovementX;\r | |
357 | INT16 RelativeMovementY;\r | |
358 | BOOLEAN LButton;\r | |
359 | BOOLEAN RButton;\r | |
360 | \r | |
361 | KeyboardEnable = FALSE;\r | |
362 | Count = 1;\r | |
363 | State = PS2_READ_BYTE_ONE;\r | |
364 | \r | |
365 | //\r | |
366 | // State machine to get mouse packet\r | |
367 | //\r | |
368 | while (1) {\r | |
369 | \r | |
370 | switch (State) {\r | |
371 | case PS2_READ_BYTE_ONE:\r | |
372 | //\r | |
373 | // Read mouse first byte data, if failed, immediately return\r | |
374 | //\r | |
375 | KbcDisableAux (MouseDev->IsaIo);\r | |
376 | Status = PS2MouseRead (MouseDev->IsaIo, &Data, &Count, State);\r | |
377 | if (EFI_ERROR (Status)) {\r | |
378 | KbcEnableAux (MouseDev->IsaIo);\r | |
379 | return EFI_NOT_READY;\r | |
380 | }\r | |
381 | \r | |
382 | if (Count != 1) {\r | |
383 | KbcEnableAux (MouseDev->IsaIo);\r | |
384 | return EFI_NOT_READY;\r | |
385 | }\r | |
386 | \r | |
387 | if (IS_PS2_SYNC_BYTE (Data)) {\r | |
388 | Packet[0] = Data;\r | |
389 | State = PS2_READ_DATA_BYTE;\r | |
390 | \r | |
391 | CheckKbStatus (MouseDev->IsaIo, &KeyboardEnable);\r | |
392 | KbcDisableKb (MouseDev->IsaIo);\r | |
393 | KbcEnableAux (MouseDev->IsaIo);\r | |
394 | }\r | |
395 | break;\r | |
396 | \r | |
397 | case PS2_READ_DATA_BYTE:\r | |
398 | Count = 2;\r | |
399 | Status = PS2MouseRead (MouseDev->IsaIo, (Packet + 1), &Count, State);\r | |
400 | if (EFI_ERROR (Status)) {\r | |
401 | if (KeyboardEnable) {\r | |
402 | KbcEnableKb (MouseDev->IsaIo);\r | |
403 | }\r | |
404 | \r | |
405 | return EFI_NOT_READY;\r | |
406 | }\r | |
407 | \r | |
408 | if (Count != 2) {\r | |
409 | if (KeyboardEnable) {\r | |
410 | KbcEnableKb (MouseDev->IsaIo);\r | |
411 | }\r | |
412 | \r | |
413 | return EFI_NOT_READY;\r | |
414 | }\r | |
415 | \r | |
416 | State = PS2_PROCESS_PACKET;\r | |
417 | break;\r | |
418 | \r | |
419 | case PS2_PROCESS_PACKET:\r | |
420 | if (KeyboardEnable) {\r | |
421 | KbcEnableKb (MouseDev->IsaIo);\r | |
422 | }\r | |
423 | //\r | |
424 | // Decode the packet\r | |
425 | //\r | |
426 | RelativeMovementX = Packet[1];\r | |
427 | RelativeMovementY = Packet[2];\r | |
428 | //\r | |
0a6f4824 LG |
429 | // Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0\r |
430 | // Byte 0 | Y overflow | X overflow | Y sign bit | X sign bit | Always 1 | Middle Btn | Right Btn | Left Btn\r | |
431 | // Byte 1 | 8 bit X Movement\r | |
432 | // Byte 2 | 8 bit Y Movement\r | |
433 | //\r | |
05fbd06d | 434 | // X sign bit + 8 bit X Movement : 9-bit signed twos complement integer that presents the relative displacement of the device in the X direction since the last data transmission.\r |
435 | // Y sign bit + 8 bit Y Movement : Same as X sign bit + 8 bit X Movement.\r | |
436 | //\r | |
437 | //\r | |
438 | // First, Clear X and Y high 8 bits\r | |
439 | //\r | |
0a6f4824 LG |
440 | RelativeMovementX = (INT16) (RelativeMovementX & 0xFF);\r |
441 | RelativeMovementY = (INT16) (RelativeMovementY & 0xFF);\r | |
05fbd06d | 442 | //\r |
443 | // Second, if the 9-bit signed twos complement integer is negative, set the high 8 bit 0xff\r | |
444 | //\r | |
445 | if ((Packet[0] & 0x10) != 0) {\r | |
446 | RelativeMovementX = (INT16) (RelativeMovementX | 0xFF00);\r | |
447 | }\r | |
448 | if ((Packet[0] & 0x20) != 0) {\r | |
449 | RelativeMovementY = (INT16) (RelativeMovementY | 0xFF00);\r | |
450 | }\r | |
451 | \r | |
0a6f4824 | 452 | \r |
05fbd06d | 453 | RButton = (UINT8) (Packet[0] & 0x2);\r |
454 | LButton = (UINT8) (Packet[0] & 0x1);\r | |
455 | \r | |
456 | //\r | |
457 | // Update mouse state\r | |
458 | //\r | |
459 | MouseDev->State.RelativeMovementX += RelativeMovementX;\r | |
460 | MouseDev->State.RelativeMovementY -= RelativeMovementY;\r | |
461 | MouseDev->State.RightButton = (UINT8) (RButton ? TRUE : FALSE);\r | |
462 | MouseDev->State.LeftButton = (UINT8) (LButton ? TRUE : FALSE);\r | |
463 | MouseDev->StateChanged = TRUE;\r | |
464 | \r | |
465 | return EFI_SUCCESS;\r | |
466 | }\r | |
467 | }\r | |
468 | }\r | |
469 | \r | |
ff1fcef8 | 470 | /**\r |
471 | Read data via IsaIo protocol with given number.\r | |
0a6f4824 | 472 | \r |
ff1fcef8 | 473 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
474 | @param Buffer Buffer receive data of mouse\r | |
475 | @param BufSize The size of buffer\r | |
476 | @param State Check input or read data\r | |
0a6f4824 | 477 | \r |
ff1fcef8 | 478 | @return status of reading mouse data.\r |
479 | **/\r | |
05fbd06d | 480 | EFI_STATUS\r |
481 | PS2MouseRead (\r | |
482 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
483 | OUT VOID *Buffer,\r | |
484 | IN OUT UINTN *BufSize,\r | |
485 | IN UINTN State\r | |
486 | )\r | |
05fbd06d | 487 | {\r |
488 | EFI_STATUS Status;\r | |
489 | UINTN BytesRead;\r | |
490 | \r | |
491 | Status = EFI_SUCCESS;\r | |
492 | BytesRead = 0;\r | |
493 | \r | |
494 | if (State == PS2_READ_BYTE_ONE) {\r | |
495 | //\r | |
496 | // Check input for mouse\r | |
497 | //\r | |
498 | Status = CheckForInput (IsaIo);\r | |
499 | \r | |
500 | if (EFI_ERROR (Status)) {\r | |
501 | return Status;\r | |
502 | }\r | |
503 | }\r | |
504 | \r | |
505 | while (BytesRead < *BufSize) {\r | |
506 | \r | |
507 | Status = WaitOutputFull (IsaIo, TIMEOUT);\r | |
508 | if (EFI_ERROR (Status)) {\r | |
509 | break;\r | |
510 | }\r | |
511 | \r | |
512 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Buffer);\r | |
513 | \r | |
514 | BytesRead++;\r | |
515 | Buffer = (UINT8 *) Buffer + 1;\r | |
516 | }\r | |
517 | //\r | |
518 | // Verify the correct number of bytes read\r | |
519 | //\r | |
520 | if (BytesRead == 0 || BytesRead != *BufSize) {\r | |
521 | Status = EFI_NOT_FOUND;\r | |
522 | }\r | |
523 | \r | |
524 | *BufSize = BytesRead;\r | |
525 | return Status;\r | |
526 | }\r | |
527 | //\r | |
528 | // 8042 I/O function\r | |
529 | //\r | |
ff1fcef8 | 530 | /**\r |
531 | I/O work flow of outing 8042 command.\r | |
0a6f4824 | 532 | \r |
ff1fcef8 | 533 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
534 | @param Command I/O command.\r | |
0a6f4824 | 535 | \r |
70d3fe9d | 536 | @retval EFI_SUCCESS Success to execute I/O work flow\r |
ff1fcef8 | 537 | @retval EFI_TIMEOUT Keyboard controller time out.\r |
538 | **/\r | |
05fbd06d | 539 | EFI_STATUS\r |
540 | Out8042Command (\r | |
541 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
542 | IN UINT8 Command\r | |
543 | )\r | |
05fbd06d | 544 | {\r |
545 | EFI_STATUS Status;\r | |
546 | UINT8 Data;\r | |
547 | \r | |
548 | //\r | |
549 | // Wait keyboard controller input buffer empty\r | |
550 | //\r | |
551 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
552 | if (EFI_ERROR (Status)) {\r | |
553 | return Status;\r | |
554 | }\r | |
555 | //\r | |
556 | // Send command\r | |
557 | //\r | |
558 | Data = Command;\r | |
559 | IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r | |
560 | \r | |
561 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
562 | if (EFI_ERROR (Status)) {\r | |
563 | return Status;\r | |
564 | }\r | |
565 | \r | |
566 | return EFI_SUCCESS;\r | |
567 | }\r | |
568 | \r | |
ff1fcef8 | 569 | /**\r |
570 | I/O work flow of outing 8042 data.\r | |
0a6f4824 | 571 | \r |
ff1fcef8 | 572 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
573 | @param Data Data value\r | |
0a6f4824 | 574 | \r |
70d3fe9d | 575 | @retval EFI_SUCCESS Success to execute I/O work flow\r |
ff1fcef8 | 576 | @retval EFI_TIMEOUT Keyboard controller time out.\r |
577 | **/\r | |
05fbd06d | 578 | EFI_STATUS\r |
579 | Out8042Data (\r | |
580 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
581 | IN UINT8 Data\r | |
582 | )\r | |
05fbd06d | 583 | {\r |
584 | EFI_STATUS Status;\r | |
172870ef | 585 | UINT8 Temp;\r |
05fbd06d | 586 | //\r |
587 | // Wait keyboard controller input buffer empty\r | |
588 | //\r | |
589 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
590 | if (EFI_ERROR (Status)) {\r | |
591 | return Status;\r | |
592 | }\r | |
593 | \r | |
172870ef | 594 | Temp = Data;\r |
595 | IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);\r | |
05fbd06d | 596 | \r |
597 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
598 | if (EFI_ERROR (Status)) {\r | |
599 | return Status;\r | |
600 | }\r | |
601 | \r | |
602 | return EFI_SUCCESS;\r | |
603 | }\r | |
604 | \r | |
ff1fcef8 | 605 | /**\r |
606 | I/O work flow of in 8042 data.\r | |
0a6f4824 | 607 | \r |
ff1fcef8 | 608 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
609 | @param Data Data value\r | |
0a6f4824 | 610 | \r |
70d3fe9d | 611 | @retval EFI_SUCCESS Success to execute I/O work flow\r |
ff1fcef8 | 612 | @retval EFI_TIMEOUT Keyboard controller time out.\r |
613 | **/\r | |
05fbd06d | 614 | EFI_STATUS\r |
615 | In8042Data (\r | |
616 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
617 | IN OUT UINT8 *Data\r | |
618 | )\r | |
05fbd06d | 619 | {\r |
620 | UINTN Delay;\r | |
172870ef | 621 | UINT8 Temp;\r |
05fbd06d | 622 | \r |
623 | Delay = TIMEOUT / 50;\r | |
624 | \r | |
625 | do {\r | |
172870ef | 626 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);\r |
05fbd06d | 627 | \r |
628 | //\r | |
629 | // Check keyboard controller status bit 0(output buffer status)\r | |
630 | //\r | |
172870ef | 631 | if ((Temp & KBC_OUTB) == KBC_OUTB) {\r |
05fbd06d | 632 | break;\r |
633 | }\r | |
634 | \r | |
635 | gBS->Stall (50);\r | |
636 | Delay--;\r | |
172870ef | 637 | } while (Delay != 0);\r |
05fbd06d | 638 | \r |
639 | if (Delay == 0) {\r | |
640 | return EFI_TIMEOUT;\r | |
641 | }\r | |
642 | \r | |
643 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);\r | |
644 | \r | |
645 | return EFI_SUCCESS;\r | |
646 | }\r | |
647 | \r | |
ff1fcef8 | 648 | /**\r |
649 | I/O work flow of outing 8042 Aux command.\r | |
0a6f4824 | 650 | \r |
ff1fcef8 | 651 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
652 | @param Command Aux I/O command\r | |
653 | @param Resend Whether need resend the Aux command.\r | |
0a6f4824 | 654 | \r |
70d3fe9d | 655 | @retval EFI_SUCCESS Success to execute I/O work flow\r |
ff1fcef8 | 656 | @retval EFI_TIMEOUT Keyboard controller time out.\r |
657 | **/\r | |
05fbd06d | 658 | EFI_STATUS\r |
659 | Out8042AuxCommand (\r | |
660 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
661 | IN UINT8 Command,\r | |
662 | IN BOOLEAN Resend\r | |
663 | )\r | |
05fbd06d | 664 | {\r |
665 | EFI_STATUS Status;\r | |
666 | UINT8 Data;\r | |
667 | \r | |
668 | //\r | |
669 | // Wait keyboard controller input buffer empty\r | |
670 | //\r | |
671 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
672 | if (EFI_ERROR (Status)) {\r | |
673 | return Status;\r | |
674 | }\r | |
675 | //\r | |
676 | // Send write to auxiliary device command\r | |
677 | //\r | |
678 | Data = WRITE_AUX_DEV;\r | |
679 | IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r | |
680 | \r | |
681 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
682 | if (EFI_ERROR (Status)) {\r | |
683 | return Status;\r | |
684 | }\r | |
685 | //\r | |
686 | // Send auxiliary device command\r | |
687 | //\r | |
688 | IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Command);\r | |
689 | \r | |
690 | //\r | |
691 | // Read return code\r | |
692 | //\r | |
693 | Status = In8042AuxData (IsaIo, &Data);\r | |
694 | if (EFI_ERROR (Status)) {\r | |
695 | return Status;\r | |
696 | }\r | |
697 | \r | |
698 | if (Data == PS2_ACK) {\r | |
699 | //\r | |
700 | // Receive mouse acknowledge, command send success\r | |
701 | //\r | |
702 | return EFI_SUCCESS;\r | |
703 | \r | |
704 | } else if (Resend) {\r | |
705 | //\r | |
706 | // Resend fail\r | |
707 | //\r | |
708 | return EFI_DEVICE_ERROR;\r | |
709 | \r | |
710 | } else if (Data == PS2_RESEND) {\r | |
711 | //\r | |
712 | // Resend command\r | |
713 | //\r | |
714 | Status = Out8042AuxCommand (IsaIo, Command, TRUE);\r | |
715 | if (EFI_ERROR (Status)) {\r | |
716 | return Status;\r | |
717 | }\r | |
718 | \r | |
719 | } else {\r | |
720 | //\r | |
721 | // Invalid return code\r | |
722 | //\r | |
723 | return EFI_DEVICE_ERROR;\r | |
724 | \r | |
725 | }\r | |
726 | \r | |
727 | return EFI_SUCCESS;\r | |
728 | }\r | |
729 | \r | |
ff1fcef8 | 730 | /**\r |
731 | I/O work flow of outing 8042 Aux data.\r | |
0a6f4824 | 732 | \r |
ff1fcef8 | 733 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
172870ef | 734 | @param Data Buffer holding return value\r |
0a6f4824 | 735 | \r |
70d3fe9d | 736 | @retval EFI_SUCCESS Success to execute I/O work flow\r |
ff1fcef8 | 737 | @retval EFI_TIMEOUT Keyboard controller time out.\r |
738 | **/\r | |
05fbd06d | 739 | EFI_STATUS\r |
740 | Out8042AuxData (\r | |
741 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
742 | IN UINT8 Data\r | |
743 | )\r | |
05fbd06d | 744 | {\r |
745 | EFI_STATUS Status;\r | |
746 | UINT8 Temp;\r | |
747 | //\r | |
748 | // Wait keyboard controller input buffer empty\r | |
749 | //\r | |
750 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
751 | if (EFI_ERROR (Status)) {\r | |
752 | return Status;\r | |
753 | }\r | |
754 | //\r | |
755 | // Send write to auxiliary device command\r | |
756 | //\r | |
757 | Temp = WRITE_AUX_DEV;\r | |
758 | IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Temp);\r | |
759 | \r | |
760 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
761 | if (EFI_ERROR (Status)) {\r | |
762 | return Status;\r | |
763 | }\r | |
764 | \r | |
765 | Temp = Data;\r | |
766 | IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Temp);\r | |
767 | \r | |
768 | Status = WaitInputEmpty (IsaIo, TIMEOUT);\r | |
769 | if (EFI_ERROR (Status)) {\r | |
770 | return Status;\r | |
771 | }\r | |
772 | \r | |
773 | return EFI_SUCCESS;\r | |
774 | }\r | |
775 | \r | |
ff1fcef8 | 776 | /**\r |
777 | I/O work flow of in 8042 Aux data.\r | |
0a6f4824 | 778 | \r |
ff1fcef8 | 779 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
780 | @param Data Buffer holding return value.\r | |
0a6f4824 | 781 | \r |
70d3fe9d | 782 | @retval EFI_SUCCESS Success to execute I/O work flow\r |
ff1fcef8 | 783 | @retval EFI_TIMEOUT Keyboard controller time out.\r |
784 | **/\r | |
05fbd06d | 785 | EFI_STATUS\r |
786 | In8042AuxData (\r | |
787 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
788 | IN OUT UINT8 *Data\r | |
789 | )\r | |
05fbd06d | 790 | {\r |
791 | EFI_STATUS Status;\r | |
792 | \r | |
793 | //\r | |
794 | // wait for output data\r | |
795 | //\r | |
796 | Status = WaitOutputFull (IsaIo, BAT_TIMEOUT);\r | |
797 | if (EFI_ERROR (Status)) {\r | |
798 | return Status;\r | |
799 | }\r | |
800 | \r | |
801 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, Data);\r | |
802 | \r | |
803 | return EFI_SUCCESS;\r | |
804 | }\r | |
805 | \r | |
ff1fcef8 | 806 | \r |
807 | /**\r | |
172870ef | 808 | Check keyboard controller status, if it is output buffer full and for auxiliary device.\r |
0a6f4824 | 809 | \r |
ff1fcef8 | 810 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
0a6f4824 | 811 | \r |
ff1fcef8 | 812 | @retval EFI_SUCCESS Keyboard controller is ready\r |
813 | @retval EFI_NOT_READY Keyboard controller is not ready\r | |
814 | **/\r | |
05fbd06d | 815 | EFI_STATUS\r |
816 | CheckForInput (\r | |
817 | IN EFI_ISA_IO_PROTOCOL *IsaIo\r | |
818 | )\r | |
05fbd06d | 819 | {\r |
820 | UINT8 Data;\r | |
821 | \r | |
822 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r | |
823 | \r | |
824 | //\r | |
825 | // Check keyboard controller status, if it is output buffer full and for auxiliary device\r | |
826 | //\r | |
827 | if ((Data & (KBC_OUTB | KBC_AUXB)) != (KBC_OUTB | KBC_AUXB)) {\r | |
828 | return EFI_NOT_READY;\r | |
829 | }\r | |
830 | \r | |
831 | return EFI_SUCCESS;\r | |
832 | }\r | |
833 | \r | |
ff1fcef8 | 834 | /**\r |
835 | I/O work flow to wait input buffer empty in given time.\r | |
0a6f4824 | 836 | \r |
ff1fcef8 | 837 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
838 | @param Timeout Wating time.\r | |
0a6f4824 | 839 | \r |
ff1fcef8 | 840 | @retval EFI_TIMEOUT if input is still not empty in given time.\r |
841 | @retval EFI_SUCCESS input is empty.\r | |
842 | **/\r | |
05fbd06d | 843 | EFI_STATUS\r |
844 | WaitInputEmpty (\r | |
845 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
846 | IN UINTN Timeout\r | |
847 | )\r | |
05fbd06d | 848 | {\r |
849 | UINTN Delay;\r | |
850 | UINT8 Data;\r | |
851 | \r | |
852 | Delay = Timeout / 50;\r | |
853 | \r | |
854 | do {\r | |
855 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r | |
856 | \r | |
857 | //\r | |
858 | // Check keyboard controller status bit 1(input buffer status)\r | |
859 | //\r | |
860 | if ((Data & KBC_INPB) == 0) {\r | |
861 | break;\r | |
862 | }\r | |
863 | \r | |
864 | gBS->Stall (50);\r | |
865 | Delay--;\r | |
172870ef | 866 | } while (Delay != 0);\r |
05fbd06d | 867 | \r |
868 | if (Delay == 0) {\r | |
869 | return EFI_TIMEOUT;\r | |
870 | }\r | |
871 | \r | |
872 | return EFI_SUCCESS;\r | |
873 | }\r | |
874 | \r | |
ff1fcef8 | 875 | /**\r |
876 | I/O work flow to wait output buffer full in given time.\r | |
0a6f4824 | 877 | \r |
ff1fcef8 | 878 | @param IsaIo Pointer to instance of EFI_ISA_IO_PROTOCOL\r |
879 | @param Timeout given time\r | |
0a6f4824 | 880 | \r |
ff1fcef8 | 881 | @retval EFI_TIMEOUT output is not full in given time\r |
882 | @retval EFI_SUCCESS output is full in given time.\r | |
883 | **/\r | |
05fbd06d | 884 | EFI_STATUS\r |
885 | WaitOutputFull (\r | |
886 | IN EFI_ISA_IO_PROTOCOL *IsaIo,\r | |
887 | IN UINTN Timeout\r | |
888 | )\r | |
05fbd06d | 889 | {\r |
890 | UINTN Delay;\r | |
891 | UINT8 Data;\r | |
892 | \r | |
893 | Delay = Timeout / 50;\r | |
894 | \r | |
895 | do {\r | |
896 | IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);\r | |
897 | \r | |
898 | //\r | |
899 | // Check keyboard controller status bit 0(output buffer status)\r | |
900 | // & bit5(output buffer for auxiliary device)\r | |
901 | //\r | |
902 | if ((Data & (KBC_OUTB | KBC_AUXB)) == (KBC_OUTB | KBC_AUXB)) {\r | |
903 | break;\r | |
904 | }\r | |
905 | \r | |
906 | gBS->Stall (50);\r | |
907 | Delay--;\r | |
172870ef | 908 | } while (Delay != 0);\r |
05fbd06d | 909 | \r |
910 | if (Delay == 0) {\r | |
911 | return EFI_TIMEOUT;\r | |
912 | }\r | |
913 | \r | |
914 | return EFI_SUCCESS;\r | |
915 | }\r |