]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2Mouse.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Isa / Ps2MouseDxe / Ps2Mouse.c
CommitLineData
77833d0b
RN
1/** @file\r
2 PS/2 Mouse driver. Routines that interacts with callers,\r
3 conforming to EFI driver model.\r
4\r
5Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
77833d0b
RN
7\r
8**/\r
9\r
10#include "Ps2Mouse.h"\r
11#include "CommPs2.h"\r
12\r
13///\r
14/// DriverBinding Protocol Instance\r
15///\r
1436aea4 16EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver = {\r
77833d0b
RN
17 PS2MouseDriverSupported,\r
18 PS2MouseDriverStart,\r
19 PS2MouseDriverStop,\r
20 0xa,\r
21 NULL,\r
22 NULL\r
23};\r
24\r
25/**\r
26 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
27 than contains a IsaIo protocol can be supported.\r
28\r
29 @param This Protocol instance pointer.\r
30 @param ControllerHandle Handle of device to test\r
31 @param RemainingDevicePath Optional parameter use to pick a specific child\r
32 device to start.\r
33\r
34 @retval EFI_SUCCESS This driver supports this device\r
35 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
36 @retval other This driver does not support this device\r
37\r
38**/\r
39EFI_STATUS\r
40EFIAPI\r
41PS2MouseDriverSupported (\r
1436aea4
MK
42 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
43 IN EFI_HANDLE Controller,\r
44 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
77833d0b
RN
45 )\r
46{\r
1436aea4
MK
47 EFI_STATUS Status;\r
48 EFI_SIO_PROTOCOL *Sio;\r
49 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
50 ACPI_HID_DEVICE_PATH *Acpi;\r
77833d0b
RN
51\r
52 //\r
53 // Check whether the controller is keyboard.\r
54 //\r
55 Status = gBS->OpenProtocol (\r
56 Controller,\r
57 &gEfiDevicePathProtocolGuid,\r
1436aea4 58 (VOID **)&DevicePath,\r
77833d0b
RN
59 This->DriverBindingHandle,\r
60 Controller,\r
61 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
62 );\r
63 if (EFI_ERROR (Status)) {\r
64 return Status;\r
65 }\r
66\r
67 do {\r
1436aea4 68 Acpi = (ACPI_HID_DEVICE_PATH *)DevicePath;\r
77833d0b
RN
69 DevicePath = NextDevicePathNode (DevicePath);\r
70 } while (!IsDevicePathEnd (DevicePath));\r
71\r
1436aea4
MK
72 if ((DevicePathType (Acpi) != ACPI_DEVICE_PATH) ||\r
73 ((DevicePathSubType (Acpi) != ACPI_DP) && (DevicePathSubType (Acpi) != ACPI_EXTENDED_DP)))\r
74 {\r
77833d0b
RN
75 return EFI_UNSUPPORTED;\r
76 }\r
77\r
78 switch (Acpi->HID) {\r
1436aea4 79 case EISA_PNP_ID (0xF03):\r
77833d0b
RN
80 //\r
81 // Microsoft PS/2 style mouse\r
82 //\r
1436aea4
MK
83 case EISA_PNP_ID (0xF13):\r
84 //\r
85 // PS/2 Port for PS/2-style Mice\r
86 //\r
77833d0b 87 break;\r
77833d0b 88\r
1436aea4
MK
89 case EISA_PNP_ID (0x303):\r
90 //\r
91 // IBM Enhanced (101/102-key, PS/2 mouse support)\r
92 //\r
93 if (Acpi->UID == 1) {\r
94 break;\r
95 }\r
96\r
97 default:\r
98 return EFI_UNSUPPORTED;\r
99 break;\r
77833d0b
RN
100 }\r
101\r
102 //\r
103 // Open the IO Abstraction(s) needed to perform the supported test\r
104 //\r
105 Status = gBS->OpenProtocol (\r
106 Controller,\r
107 &gEfiSioProtocolGuid,\r
1436aea4 108 (VOID **)&Sio,\r
77833d0b
RN
109 This->DriverBindingHandle,\r
110 Controller,\r
111 EFI_OPEN_PROTOCOL_BY_DRIVER\r
112 );\r
113 if (EFI_ERROR (Status)) {\r
114 return Status;\r
115 }\r
116\r
117 //\r
118 // Close the I/O Abstraction(s) used to perform the supported test\r
119 //\r
120 gBS->CloseProtocol (\r
121 Controller,\r
122 &gEfiSioProtocolGuid,\r
123 This->DriverBindingHandle,\r
124 Controller\r
125 );\r
126\r
127 return Status;\r
128}\r
129\r
130/**\r
131 Start this driver on ControllerHandle by opening a Sio protocol, creating\r
132 PS2_MOUSE_DEV device and install gEfiSimplePointerProtocolGuid finally.\r
133\r
134 @param This Protocol instance pointer.\r
135 @param ControllerHandle Handle of device to bind driver to\r
136 @param RemainingDevicePath Optional parameter use to pick a specific child\r
137 device to start.\r
138\r
139 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
140 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
141 @retval other This driver does not support this device\r
142\r
143**/\r
144EFI_STATUS\r
145EFIAPI\r
146PS2MouseDriverStart (\r
1436aea4
MK
147 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
148 IN EFI_HANDLE Controller,\r
149 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
77833d0b
RN
150 )\r
151{\r
1436aea4
MK
152 EFI_STATUS Status;\r
153 EFI_STATUS EmptyStatus;\r
154 EFI_SIO_PROTOCOL *Sio;\r
155 PS2_MOUSE_DEV *MouseDev;\r
156 UINT8 Data;\r
157 EFI_TPL OldTpl;\r
158 EFI_STATUS_CODE_VALUE StatusCode;\r
159 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
77833d0b 160\r
1436aea4 161 StatusCode = 0;\r
77833d0b
RN
162\r
163 //\r
164 // Open the device path protocol\r
165 //\r
166 Status = gBS->OpenProtocol (\r
167 Controller,\r
168 &gEfiDevicePathProtocolGuid,\r
1436aea4 169 (VOID **)&DevicePath,\r
77833d0b
RN
170 This->DriverBindingHandle,\r
171 Controller,\r
172 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
173 );\r
174 if (EFI_ERROR (Status)) {\r
175 return Status;\r
176 }\r
1436aea4 177\r
77833d0b
RN
178 //\r
179 // Report that the keyboard is being enabled\r
180 //\r
181 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
182 EFI_PROGRESS_CODE,\r
183 EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE,\r
184 DevicePath\r
185 );\r
186\r
187 //\r
188 // Get the ISA I/O Protocol on Controller's handle\r
189 //\r
190 Status = gBS->OpenProtocol (\r
191 Controller,\r
192 &gEfiSioProtocolGuid,\r
1436aea4 193 (VOID **)&Sio,\r
77833d0b
RN
194 This->DriverBindingHandle,\r
195 Controller,\r
196 EFI_OPEN_PROTOCOL_BY_DRIVER\r
197 );\r
198 if (EFI_ERROR (Status)) {\r
199 return Status;\r
200 }\r
1436aea4 201\r
77833d0b
RN
202 //\r
203 // Raise TPL to avoid keyboard operation impact\r
204 //\r
205 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
206\r
207 //\r
208 // Allocate private data\r
209 //\r
210 MouseDev = AllocateZeroPool (sizeof (PS2_MOUSE_DEV));\r
211 if (MouseDev == NULL) {\r
212 Status = EFI_OUT_OF_RESOURCES;\r
213 goto ErrorExit;\r
214 }\r
1436aea4 215\r
77833d0b
RN
216 //\r
217 // Setup the device instance\r
218 //\r
219 MouseDev->Signature = PS2_MOUSE_DEV_SIGNATURE;\r
220 MouseDev->Handle = Controller;\r
221 MouseDev->SampleRate = SampleRate20;\r
222 MouseDev->Resolution = MouseResolution4;\r
223 MouseDev->Scaling = Scaling1;\r
224 MouseDev->DataPackageSize = 3;\r
225 MouseDev->DevicePath = DevicePath;\r
226\r
227 //\r
228 // Resolution = 4 counts/mm\r
229 //\r
1436aea4
MK
230 MouseDev->Mode.ResolutionX = 4;\r
231 MouseDev->Mode.ResolutionY = 4;\r
232 MouseDev->Mode.LeftButton = TRUE;\r
233 MouseDev->Mode.RightButton = TRUE;\r
77833d0b 234\r
1436aea4
MK
235 MouseDev->SimplePointerProtocol.Reset = MouseReset;\r
236 MouseDev->SimplePointerProtocol.GetState = MouseGetState;\r
237 MouseDev->SimplePointerProtocol.Mode = &(MouseDev->Mode);\r
77833d0b
RN
238\r
239 //\r
240 // Initialize keyboard controller if necessary\r
241 //\r
242 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
243 EFI_PROGRESS_CODE,\r
244 EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST,\r
245 DevicePath\r
246 );\r
247\r
248 Data = IoRead8 (KBC_CMD_STS_PORT);\r
249 //\r
250 // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.\r
251 //\r
252 if ((Data & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {\r
253 //\r
254 // If nobody decodes KBC I/O port, it will read back as 0xFF.\r
255 // Check the Time-Out and Parity bit to see if it has an active KBC in system\r
256 //\r
257 Status = EFI_DEVICE_ERROR;\r
258 StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED;\r
259 goto ErrorExit;\r
260 }\r
261\r
262 if ((Data & KBC_SYSF) != KBC_SYSF) {\r
263 Status = KbcSelfTest ();\r
264 if (EFI_ERROR (Status)) {\r
265 StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR;\r
266 goto ErrorExit;\r
267 }\r
268 }\r
269\r
270 KbcEnableAux ();\r
271\r
272 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
273 EFI_PROGRESS_CODE,\r
274 EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT,\r
275 DevicePath\r
276 );\r
277\r
278 //\r
279 // Reset the mouse\r
280 //\r
281 Status = MouseDev->SimplePointerProtocol.Reset (\r
1436aea4
MK
282 &MouseDev->SimplePointerProtocol,\r
283 FeaturePcdGet (PcdPs2MouseExtendedVerification)\r
284 );\r
77833d0b
RN
285 if (EFI_ERROR (Status)) {\r
286 //\r
287 // mouse not connected\r
288 //\r
1436aea4
MK
289 Status = EFI_SUCCESS;\r
290 StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED;\r
77833d0b
RN
291 goto ErrorExit;\r
292 }\r
293\r
294 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
295 EFI_PROGRESS_CODE,\r
296 EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED,\r
297 DevicePath\r
298 );\r
299\r
300 //\r
301 // Setup the WaitForKey event\r
302 //\r
303 Status = gBS->CreateEvent (\r
304 EVT_NOTIFY_WAIT,\r
305 TPL_NOTIFY,\r
306 MouseWaitForInput,\r
307 MouseDev,\r
308 &((MouseDev->SimplePointerProtocol).WaitForInput)\r
309 );\r
310 if (EFI_ERROR (Status)) {\r
311 Status = EFI_OUT_OF_RESOURCES;\r
312 goto ErrorExit;\r
313 }\r
1436aea4 314\r
77833d0b
RN
315 //\r
316 // Setup a periodic timer, used to poll mouse state\r
317 //\r
318 Status = gBS->CreateEvent (\r
319 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
320 TPL_NOTIFY,\r
321 PollMouse,\r
322 MouseDev,\r
323 &MouseDev->TimerEvent\r
324 );\r
325 if (EFI_ERROR (Status)) {\r
326 Status = EFI_OUT_OF_RESOURCES;\r
327 goto ErrorExit;\r
328 }\r
1436aea4 329\r
77833d0b
RN
330 //\r
331 // Start timer to poll mouse (100 samples per second)\r
332 //\r
333 Status = gBS->SetTimer (MouseDev->TimerEvent, TimerPeriodic, 100000);\r
334 if (EFI_ERROR (Status)) {\r
335 Status = EFI_OUT_OF_RESOURCES;\r
336 goto ErrorExit;\r
337 }\r
338\r
339 MouseDev->ControllerNameTable = NULL;\r
340 AddUnicodeString2 (\r
341 "eng",\r
342 gPs2MouseComponentName.SupportedLanguages,\r
343 &MouseDev->ControllerNameTable,\r
344 L"PS/2 Mouse Device",\r
345 TRUE\r
346 );\r
347 AddUnicodeString2 (\r
348 "en",\r
349 gPs2MouseComponentName2.SupportedLanguages,\r
350 &MouseDev->ControllerNameTable,\r
351 L"PS/2 Mouse Device",\r
352 FALSE\r
353 );\r
354\r
77833d0b
RN
355 //\r
356 // Install protocol interfaces for the mouse device.\r
357 //\r
358 Status = gBS->InstallMultipleProtocolInterfaces (\r
359 &Controller,\r
360 &gEfiSimplePointerProtocolGuid,\r
361 &MouseDev->SimplePointerProtocol,\r
362 NULL\r
363 );\r
364 if (EFI_ERROR (Status)) {\r
365 goto ErrorExit;\r
366 }\r
367\r
368 gBS->RestoreTPL (OldTpl);\r
369\r
370 return Status;\r
371\r
372ErrorExit:\r
373\r
374 if (Status != EFI_DEVICE_ERROR) {\r
375 KbcDisableAux ();\r
376 }\r
377\r
378 if (StatusCode != 0) {\r
379 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
380 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
381 StatusCode,\r
382 DevicePath\r
383 );\r
384 }\r
385\r
386 if ((MouseDev != NULL) && (MouseDev->SimplePointerProtocol.WaitForInput != NULL)) {\r
387 gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput);\r
388 }\r
389\r
390 if ((MouseDev != NULL) && (MouseDev->TimerEvent != NULL)) {\r
391 gBS->CloseEvent (MouseDev->TimerEvent);\r
392 }\r
393\r
394 if ((MouseDev != NULL) && (MouseDev->ControllerNameTable != NULL)) {\r
395 FreeUnicodeStringTable (MouseDev->ControllerNameTable);\r
396 }\r
397\r
398 if (Status != EFI_DEVICE_ERROR) {\r
399 //\r
400 // Since there will be no timer handler for mouse input any more,\r
401 // exhaust input data just in case there is still mouse data left\r
402 //\r
403 EmptyStatus = EFI_SUCCESS;\r
404 while (!EFI_ERROR (EmptyStatus)) {\r
405 EmptyStatus = In8042Data (&Data);\r
406 }\r
407 }\r
408\r
409 if (MouseDev != NULL) {\r
410 FreePool (MouseDev);\r
411 }\r
412\r
413 gBS->CloseProtocol (\r
414 Controller,\r
415 &gEfiDevicePathProtocolGuid,\r
416 This->DriverBindingHandle,\r
417 Controller\r
418 );\r
419\r
420 gBS->CloseProtocol (\r
421 Controller,\r
422 &gEfiSioProtocolGuid,\r
423 This->DriverBindingHandle,\r
424 Controller\r
425 );\r
426\r
427 gBS->RestoreTPL (OldTpl);\r
428\r
429 return Status;\r
430}\r
431\r
432/**\r
ed356b9e 433 Stop this driver on ControllerHandle. Support stopping any child handles\r
77833d0b
RN
434 created by this driver.\r
435\r
436 @param This Protocol instance pointer.\r
437 @param ControllerHandle Handle of device to stop driver on\r
438 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
439 children is zero stop the entire bus driver.\r
440 @param ChildHandleBuffer List of Child Handles to Stop.\r
441\r
442 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
443 @retval other This driver was not removed from this device\r
444\r
445**/\r
446EFI_STATUS\r
447EFIAPI\r
448PS2MouseDriverStop (\r
1436aea4
MK
449 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
450 IN EFI_HANDLE Controller,\r
451 IN UINTN NumberOfChildren,\r
452 IN EFI_HANDLE *ChildHandleBuffer\r
77833d0b
RN
453 )\r
454{\r
1436aea4
MK
455 EFI_STATUS Status;\r
456 EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;\r
457 PS2_MOUSE_DEV *MouseDev;\r
458 UINT8 Data;\r
77833d0b
RN
459\r
460 Status = gBS->OpenProtocol (\r
461 Controller,\r
462 &gEfiSimplePointerProtocolGuid,\r
1436aea4 463 (VOID **)&SimplePointerProtocol,\r
77833d0b
RN
464 This->DriverBindingHandle,\r
465 Controller,\r
466 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
467 );\r
468 if (EFI_ERROR (Status)) {\r
469 return EFI_SUCCESS;\r
470 }\r
471\r
472 MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol);\r
473\r
474 //\r
475 // Report that the keyboard is being disabled\r
476 //\r
477 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
478 EFI_PROGRESS_CODE,\r
479 EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE,\r
480 MouseDev->DevicePath\r
481 );\r
482\r
483 Status = gBS->UninstallProtocolInterface (\r
484 Controller,\r
485 &gEfiSimplePointerProtocolGuid,\r
486 &MouseDev->SimplePointerProtocol\r
487 );\r
488 if (EFI_ERROR (Status)) {\r
489 return Status;\r
490 }\r
491\r
492 //\r
493 // Cancel mouse data polling timer, close timer event\r
494 //\r
495 gBS->SetTimer (MouseDev->TimerEvent, TimerCancel, 0);\r
496 gBS->CloseEvent (MouseDev->TimerEvent);\r
497\r
498 //\r
499 // Since there will be no timer handler for mouse input any more,\r
500 // exhaust input data just in case there is still mouse data left\r
501 //\r
502 Status = EFI_SUCCESS;\r
503 while (!EFI_ERROR (Status)) {\r
504 Status = In8042Data (&Data);\r
505 }\r
506\r
507 gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput);\r
508 FreeUnicodeStringTable (MouseDev->ControllerNameTable);\r
509 FreePool (MouseDev);\r
510\r
511 gBS->CloseProtocol (\r
512 Controller,\r
513 &gEfiDevicePathProtocolGuid,\r
514 This->DriverBindingHandle,\r
515 Controller\r
516 );\r
517\r
518 gBS->CloseProtocol (\r
519 Controller,\r
520 &gEfiSioProtocolGuid,\r
521 This->DriverBindingHandle,\r
522 Controller\r
523 );\r
524\r
525 return EFI_SUCCESS;\r
526}\r
527\r
528/**\r
529 Reset the Mouse and do BAT test for it, if ExtendedVerification is TRUE and\r
ed356b9e 530 there is a mouse device connected to system.\r
77833d0b
RN
531\r
532 @param This - Pointer of simple pointer Protocol.\r
533 @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip.\r
534\r
535\r
536 @retval EFI_SUCCESS - The command byte is written successfully.\r
ed356b9e 537 @retval EFI_DEVICE_ERROR - Errors occurred during resetting keyboard.\r
77833d0b
RN
538\r
539**/\r
540EFI_STATUS\r
541EFIAPI\r
542MouseReset (\r
1436aea4
MK
543 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
544 IN BOOLEAN ExtendedVerification\r
77833d0b
RN
545 )\r
546{\r
1436aea4
MK
547 EFI_STATUS Status;\r
548 PS2_MOUSE_DEV *MouseDev;\r
549 EFI_TPL OldTpl;\r
550 BOOLEAN KeyboardEnable;\r
551 UINT8 Data;\r
77833d0b
RN
552\r
553 MouseDev = PS2_MOUSE_DEV_FROM_THIS (This);\r
554\r
555 //\r
556 // Report reset progress code\r
557 //\r
558 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
559 EFI_PROGRESS_CODE,\r
560 EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET,\r
561 MouseDev->DevicePath\r
562 );\r
563\r
564 KeyboardEnable = FALSE;\r
565\r
566 //\r
567 // Raise TPL to avoid keyboard operation impact\r
568 //\r
569 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
570\r
571 ZeroMem (&MouseDev->State, sizeof (EFI_SIMPLE_POINTER_STATE));\r
572 MouseDev->StateChanged = FALSE;\r
573\r
574 //\r
575 // Exhaust input data\r
576 //\r
577 Status = EFI_SUCCESS;\r
578 while (!EFI_ERROR (Status)) {\r
579 Status = In8042Data (&Data);\r
580 }\r
581\r
582 CheckKbStatus (&KeyboardEnable);\r
583\r
584 KbcDisableKb ();\r
585\r
586 //\r
587 // if there's data block on KBC data port, read it out\r
588 //\r
589 if ((IoRead8 (KBC_CMD_STS_PORT) & KBC_OUTB) == KBC_OUTB) {\r
590 IoRead8 (KBC_DATA_PORT);\r
591 }\r
592\r
593 Status = EFI_SUCCESS;\r
594 //\r
1d031e75
AC
595 // The PS2 mouse driver reset behavior is always successfully return no matter whether or not there is mouse connected to system.\r
596 // This behavior is needed by performance speed. The following mouse command only successfully finish when mouse device is\r
77833d0b
RN
597 // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling\r
598 //\r
599 if (ExtendedVerification && CheckMouseConnect (MouseDev)) {\r
600 //\r
601 // Send mouse reset command and set mouse default configure\r
602 //\r
603 Status = PS2MouseReset ();\r
604 if (EFI_ERROR (Status)) {\r
605 Status = EFI_DEVICE_ERROR;\r
606 goto Exit;\r
607 }\r
608\r
609 Status = PS2MouseSetSampleRate (MouseDev->SampleRate);\r
610 if (EFI_ERROR (Status)) {\r
611 Status = EFI_DEVICE_ERROR;\r
612 goto Exit;\r
613 }\r
614\r
615 Status = PS2MouseSetResolution (MouseDev->Resolution);\r
616 if (EFI_ERROR (Status)) {\r
617 Status = EFI_DEVICE_ERROR;\r
618 goto Exit;\r
619 }\r
620\r
621 Status = PS2MouseSetScaling (MouseDev->Scaling);\r
622 if (EFI_ERROR (Status)) {\r
623 Status = EFI_DEVICE_ERROR;\r
624 goto Exit;\r
625 }\r
626\r
627 Status = PS2MouseEnable ();\r
628 if (EFI_ERROR (Status)) {\r
629 Status = EFI_DEVICE_ERROR;\r
630 goto Exit;\r
631 }\r
632 }\r
1436aea4 633\r
77833d0b
RN
634Exit:\r
635 gBS->RestoreTPL (OldTpl);\r
636\r
637 if (KeyboardEnable) {\r
638 KbcEnableKb ();\r
639 }\r
640\r
641 return Status;\r
642}\r
643\r
644/**\r
645 Check whether there is Ps/2 mouse device in system\r
646\r
647 @param MouseDev - Mouse Private Data Structure\r
648\r
649 @retval TRUE - Keyboard in System.\r
650 @retval FALSE - Keyboard not in System.\r
651\r
652**/\r
653BOOLEAN\r
654CheckMouseConnect (\r
1436aea4 655 IN PS2_MOUSE_DEV *MouseDev\r
77833d0b
RN
656 )\r
657\r
658{\r
1436aea4 659 EFI_STATUS Status;\r
77833d0b
RN
660\r
661 Status = PS2MouseEnable ();\r
662 if (!EFI_ERROR (Status)) {\r
663 return TRUE;\r
664 }\r
665\r
666 return FALSE;\r
667}\r
668\r
669/**\r
670 Get and Clear mouse status.\r
671\r
672 @param This - Pointer of simple pointer Protocol.\r
673 @param State - Output buffer holding status.\r
674\r
675 @retval EFI_INVALID_PARAMETER Output buffer is invalid.\r
676 @retval EFI_NOT_READY Mouse is not changed status yet.\r
677 @retval EFI_SUCCESS Mouse status is changed and get successful.\r
678**/\r
679EFI_STATUS\r
680EFIAPI\r
681MouseGetState (\r
1436aea4
MK
682 IN EFI_SIMPLE_POINTER_PROTOCOL *This,\r
683 IN OUT EFI_SIMPLE_POINTER_STATE *State\r
77833d0b
RN
684 )\r
685{\r
1436aea4
MK
686 PS2_MOUSE_DEV *MouseDev;\r
687 EFI_TPL OldTpl;\r
77833d0b
RN
688\r
689 MouseDev = PS2_MOUSE_DEV_FROM_THIS (This);\r
690\r
691 if (State == NULL) {\r
692 return EFI_INVALID_PARAMETER;\r
693 }\r
694\r
695 if (!MouseDev->StateChanged) {\r
696 return EFI_NOT_READY;\r
697 }\r
698\r
699 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
700 CopyMem (State, &(MouseDev->State), sizeof (EFI_SIMPLE_POINTER_STATE));\r
701\r
702 //\r
703 // clear mouse state\r
704 //\r
705 MouseDev->State.RelativeMovementX = 0;\r
706 MouseDev->State.RelativeMovementY = 0;\r
707 MouseDev->State.RelativeMovementZ = 0;\r
708 MouseDev->StateChanged = FALSE;\r
709 gBS->RestoreTPL (OldTpl);\r
710\r
711 return EFI_SUCCESS;\r
712}\r
713\r
714/**\r
715\r
716 Event notification function for SIMPLE_POINTER.WaitForInput event.\r
717 Signal the event if there is input from mouse.\r
718\r
719 @param Event event object\r
720 @param Context event context\r
721\r
722**/\r
723VOID\r
724EFIAPI\r
725MouseWaitForInput (\r
1436aea4
MK
726 IN EFI_EVENT Event,\r
727 IN VOID *Context\r
77833d0b
RN
728 )\r
729{\r
1436aea4 730 PS2_MOUSE_DEV *MouseDev;\r
77833d0b 731\r
1436aea4 732 MouseDev = (PS2_MOUSE_DEV *)Context;\r
77833d0b
RN
733\r
734 //\r
735 // Someone is waiting on the mouse event, if there's\r
736 // input from mouse, signal the event\r
737 //\r
738 if (MouseDev->StateChanged) {\r
739 gBS->SignalEvent (Event);\r
740 }\r
77833d0b
RN
741}\r
742\r
743/**\r
744 Event notification function for TimerEvent event.\r
745 If mouse device is connected to system, try to get the mouse packet data.\r
746\r
747 @param Event - TimerEvent in PS2_MOUSE_DEV\r
748 @param Context - Pointer to PS2_MOUSE_DEV structure\r
749\r
750**/\r
751VOID\r
752EFIAPI\r
753PollMouse (\r
754 IN EFI_EVENT Event,\r
755 IN VOID *Context\r
756 )\r
757\r
758{\r
1436aea4 759 PS2_MOUSE_DEV *MouseDev;\r
77833d0b 760\r
1436aea4 761 MouseDev = (PS2_MOUSE_DEV *)Context;\r
77833d0b
RN
762\r
763 //\r
764 // Polling mouse packet data\r
765 //\r
766 PS2MouseGetPacket (MouseDev);\r
767}\r
768\r
769/**\r
770 The user Entry Point for module Ps2Mouse. The user code starts with this function.\r
771\r
772 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
773 @param[in] SystemTable A pointer to the EFI System Table.\r
774\r
775 @retval EFI_SUCCESS The entry point is executed successfully.\r
776 @retval other Some error occurs when executing this entry point.\r
777\r
778**/\r
779EFI_STATUS\r
780EFIAPI\r
1436aea4
MK
781InitializePs2Mouse (\r
782 IN EFI_HANDLE ImageHandle,\r
783 IN EFI_SYSTEM_TABLE *SystemTable\r
77833d0b
RN
784 )\r
785{\r
1436aea4 786 EFI_STATUS Status;\r
77833d0b
RN
787\r
788 //\r
789 // Install driver model protocol(s).\r
790 //\r
791 Status = EfiLibInstallDriverBindingComponentName2 (\r
792 ImageHandle,\r
793 SystemTable,\r
794 &gPS2MouseDriver,\r
795 ImageHandle,\r
796 &gPs2MouseComponentName,\r
797 &gPs2MouseComponentName2\r
798 );\r
799 ASSERT_EFI_ERROR (Status);\r
800\r
77833d0b
RN
801 return Status;\r
802}\r