3 PS/2 Keyboard driver. Routines that interacts with callers,
4 conforming to EFI driver model
6 Copyright (c) 2006 - 2007, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "Ps2Keyboard.h"
20 // Function prototypes
24 KbdControllerDriverSupported (
25 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
26 IN EFI_HANDLE Controller
,
27 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
32 KbdControllerDriverStart (
33 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
34 IN EFI_HANDLE Controller
,
35 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
40 KbdControllerDriverStop (
41 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
42 IN EFI_HANDLE Controller
,
43 IN UINTN NumberOfChildren
,
44 IN EFI_HANDLE
*ChildHandleBuffer
49 IN OUT LIST_ENTRY
*ListHead
53 // DriverBinding Protocol Instance
55 EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver
= {
56 KbdControllerDriverSupported
,
57 KbdControllerDriverStart
,
58 KbdControllerDriverStop
,
65 Test controller is a keyboard Controller
67 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
68 @param Controller driver's controller
69 @param RemainingDevicePath children device path
71 @retval EFI_UNSUPPORTED controller is not floppy disk
72 @retval EFI_SUCCESS controller is floppy disk
76 KbdControllerDriverSupported (
77 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
78 IN EFI_HANDLE Controller
,
79 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
83 EFI_ISA_IO_PROTOCOL
*IsaIo
;
86 // Open the IO Abstraction(s) needed to perform the supported test
88 Status
= gBS
->OpenProtocol (
90 &gEfiIsaIoProtocolGuid
,
92 This
->DriverBindingHandle
,
94 EFI_OPEN_PROTOCOL_BY_DRIVER
96 if (EFI_ERROR (Status
)) {
100 // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
102 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x303) || IsaIo
->ResourceList
->Device
.UID
!= 0) {
103 Status
= EFI_UNSUPPORTED
;
106 // Close the I/O Abstraction(s) used to perform the supported test
110 &gEfiIsaIoProtocolGuid
,
111 This
->DriverBindingHandle
,
119 Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
121 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
122 @param Controller driver controller handle
123 @param RemainingDevicePath Children's device path
125 @retval whether success to create floppy control instance.
129 KbdControllerDriverStart (
130 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
131 IN EFI_HANDLE Controller
,
132 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
137 EFI_ISA_IO_PROTOCOL
*IsaIo
;
138 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
140 EFI_STATUS_CODE_VALUE StatusCode
;
141 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
145 Status
= gBS
->OpenProtocol (
147 &gEfiDevicePathProtocolGuid
,
148 (VOID
**) &ParentDevicePath
,
149 This
->DriverBindingHandle
,
151 EFI_OPEN_PROTOCOL_BY_DRIVER
153 if (EFI_ERROR (Status
)) {
157 // Report that the keyboard is being enabled
159 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
161 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
,
166 // Get the ISA I/O Protocol on Controller's handle
168 Status
= gBS
->OpenProtocol (
170 &gEfiIsaIoProtocolGuid
,
172 This
->DriverBindingHandle
,
174 EFI_OPEN_PROTOCOL_BY_DRIVER
176 if (EFI_ERROR (Status
)) {
179 &gEfiDevicePathProtocolGuid
,
180 This
->DriverBindingHandle
,
183 return EFI_INVALID_PARAMETER
;
186 // Allocate private data
188 ConsoleIn
= AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV
));
189 if (ConsoleIn
== NULL
) {
190 Status
= EFI_OUT_OF_RESOURCES
;
191 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
195 // Setup the device instance
197 ConsoleIn
->Signature
= KEYBOARD_CONSOLE_IN_DEV_SIGNATURE
;
198 ConsoleIn
->Handle
= Controller
;
199 (ConsoleIn
->ConIn
).Reset
= KeyboardEfiReset
;
200 (ConsoleIn
->ConIn
).ReadKeyStroke
= KeyboardReadKeyStroke
;
201 ConsoleIn
->DataRegisterAddress
= KEYBOARD_8042_DATA_REGISTER
;
202 ConsoleIn
->StatusRegisterAddress
= KEYBOARD_8042_STATUS_REGISTER
;
203 ConsoleIn
->CommandRegisterAddress
= KEYBOARD_8042_COMMAND_REGISTER
;
204 ConsoleIn
->IsaIo
= IsaIo
;
205 ConsoleIn
->ScancodeBufStartPos
= 0;
206 ConsoleIn
->ScancodeBufEndPos
= KEYBOARD_BUFFER_MAX_COUNT
- 1;
207 ConsoleIn
->ScancodeBufCount
= 0;
208 ConsoleIn
->Ctrled
= FALSE
;
209 ConsoleIn
->Alted
= FALSE
;
210 ConsoleIn
->DevicePath
= ParentDevicePath
;
212 ConsoleIn
->ConInEx
.Reset
= KeyboardEfiResetEx
;
213 ConsoleIn
->ConInEx
.ReadKeyStrokeEx
= KeyboardReadKeyStrokeEx
;
214 ConsoleIn
->ConInEx
.SetState
= KeyboardSetState
;
215 ConsoleIn
->ConInEx
.RegisterKeyNotify
= KeyboardRegisterKeyNotify
;
216 ConsoleIn
->ConInEx
.UnregisterKeyNotify
= KeyboardUnregisterKeyNotify
;
218 InitializeListHead (&ConsoleIn
->NotifyList
);
220 // Setup the WaitForKey event
222 Status
= gBS
->CreateEvent (
227 &((ConsoleIn
->ConIn
).WaitForKey
)
229 if (EFI_ERROR (Status
)) {
230 Status
= EFI_OUT_OF_RESOURCES
;
231 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
235 // Setup the WaitForKeyEx event
237 Status
= gBS
->CreateEvent (
240 KeyboardWaitForKeyEx
,
241 &(ConsoleIn
->ConInEx
),
242 &(ConsoleIn
->ConInEx
.WaitForKeyEx
)
244 if (EFI_ERROR (Status
)) {
245 Status
= EFI_OUT_OF_RESOURCES
;
246 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
249 // Setup a periodic timer, used for reading keystrokes at a fixed interval
251 Status
= gBS
->CreateEvent (
252 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
254 KeyboardTimerHandler
,
256 &ConsoleIn
->TimerEvent
258 if (EFI_ERROR (Status
)) {
259 Status
= EFI_OUT_OF_RESOURCES
;
260 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
264 Status
= gBS
->SetTimer (
265 ConsoleIn
->TimerEvent
,
267 KEYBOARD_TIMER_INTERVAL
269 if (EFI_ERROR (Status
)) {
270 Status
= EFI_OUT_OF_RESOURCES
;
271 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
275 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
277 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
,
282 // Reset the keyboard device
284 Status
= ConsoleIn
->ConIn
.Reset (&ConsoleIn
->ConIn
, TRUE
);
285 if (EFI_ERROR (Status
)) {
286 Status
= EFI_DEVICE_ERROR
;
287 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
;
291 ConsoleIn
->ControllerNameTable
= NULL
;
294 gPs2KeyboardComponentName
.SupportedLanguages
,
295 &ConsoleIn
->ControllerNameTable
,
296 L
"PS/2 Keyboard Device",
301 gPs2KeyboardComponentName2
.SupportedLanguages
,
302 &ConsoleIn
->ControllerNameTable
,
303 L
"PS/2 Keyboard Device",
309 // Install protocol interfaces for the keyboard device.
311 Status
= gBS
->InstallMultipleProtocolInterfaces (
313 &gEfiSimpleTextInProtocolGuid
,
315 &gEfiSimpleTextInputExProtocolGuid
,
319 if (EFI_ERROR (Status
)) {
320 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
330 if (StatusCode
!= 0) {
331 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
332 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
338 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->ConIn
.WaitForKey
!= NULL
)) {
339 gBS
->CloseEvent (ConsoleIn
->ConIn
.WaitForKey
);
342 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->TimerEvent
!= NULL
)) {
343 gBS
->CloseEvent (ConsoleIn
->TimerEvent
);
345 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->ConInEx
.WaitForKeyEx
!= NULL
)) {
346 gBS
->CloseEvent (ConsoleIn
->ConInEx
.WaitForKeyEx
);
348 KbdFreeNotifyList (&ConsoleIn
->NotifyList
);
349 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->ControllerNameTable
!= NULL
)) {
350 FreeUnicodeStringTable (ConsoleIn
->ControllerNameTable
);
353 // Since there will be no timer handler for keyboard input any more,
354 // exhaust input data just in case there is still keyboard data left
356 Status1
= EFI_SUCCESS
;
357 while (!EFI_ERROR (Status1
)) {
358 Status1
= KeyboardRead (ConsoleIn
, &Data
);;
361 if (ConsoleIn
!= NULL
) {
362 gBS
->FreePool (ConsoleIn
);
367 &gEfiDevicePathProtocolGuid
,
368 This
->DriverBindingHandle
,
374 &gEfiIsaIoProtocolGuid
,
375 This
->DriverBindingHandle
,
383 Stop this driver on ControllerHandle. Support stoping any child handles
384 created by this driver.
386 @param This Protocol instance pointer.
387 @param ControllerHandle Handle of device to stop driver on
388 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
389 children is zero stop the entire bus driver.
390 @param ChildHandleBuffer List of Child Handles to Stop.
392 @retval EFI_SUCCESS This driver is removed ControllerHandle
393 @retval other This driver was not removed from this device
398 KbdControllerDriverStop (
399 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
400 IN EFI_HANDLE Controller
,
401 IN UINTN NumberOfChildren
,
402 IN EFI_HANDLE
*ChildHandleBuffer
406 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*ConIn
;
407 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
413 Status
= gBS
->OpenProtocol (
415 &gEfiSimpleTextInProtocolGuid
,
417 This
->DriverBindingHandle
,
419 EFI_OPEN_PROTOCOL_GET_PROTOCOL
421 if (EFI_ERROR (Status
)) {
424 Status
= gBS
->OpenProtocol (
426 &gEfiSimpleTextInputExProtocolGuid
,
428 This
->DriverBindingHandle
,
430 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
432 if (EFI_ERROR (Status
)) {
436 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn
);
439 // Report that the keyboard is being disabled
441 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
443 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
,
444 ConsoleIn
->DevicePath
447 if (ConsoleIn
->TimerEvent
) {
448 gBS
->CloseEvent (ConsoleIn
->TimerEvent
);
449 ConsoleIn
->TimerEvent
= NULL
;
452 // Disable the keyboard interface
454 Status
= DisableKeyboard (ConsoleIn
);
457 // Since there will be no timer handler for keyboard input any more,
458 // exhaust input data just in case there is still keyboard data left
460 Status
= EFI_SUCCESS
;
461 while (!EFI_ERROR (Status
)) {
462 Status
= KeyboardRead (ConsoleIn
, &Data
);;
465 // Uninstall the SimpleTextIn and SimpleTextInEx protocols
467 Status
= gBS
->UninstallMultipleProtocolInterfaces (
469 &gEfiSimpleTextInProtocolGuid
,
471 &gEfiSimpleTextInputExProtocolGuid
,
475 if (EFI_ERROR (Status
)) {
481 &gEfiDevicePathProtocolGuid
,
482 This
->DriverBindingHandle
,
488 &gEfiIsaIoProtocolGuid
,
489 This
->DriverBindingHandle
,
494 // Free other resources
496 if ((ConsoleIn
->ConIn
).WaitForKey
) {
497 gBS
->CloseEvent ((ConsoleIn
->ConIn
).WaitForKey
);
498 (ConsoleIn
->ConIn
).WaitForKey
= NULL
;
500 if (ConsoleIn
->ConInEx
.WaitForKeyEx
!= NULL
) {
501 gBS
->CloseEvent (ConsoleIn
->ConInEx
.WaitForKeyEx
);
502 ConsoleIn
->ConInEx
.WaitForKeyEx
= NULL
;
504 KbdFreeNotifyList (&ConsoleIn
->NotifyList
);
505 FreeUnicodeStringTable (ConsoleIn
->ControllerNameTable
);
506 gBS
->FreePool (ConsoleIn
);
512 Free the waiting key notify list.
514 @param ListHead Pointer to list head
518 IN OUT LIST_ENTRY
*ListHead
521 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
523 if (ListHead
== NULL
) {
524 return EFI_INVALID_PARAMETER
;
526 while (!IsListEmpty (ListHead
)) {
528 ListHead
->ForwardLink
,
529 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
531 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
533 RemoveEntryList (ListHead
->ForwardLink
);
534 gBS
->FreePool (NotifyNode
);
541 The user Entry Point for module Ps2Keyboard. The user code starts with this function.
543 @param[in] ImageHandle The firmware allocated handle for the EFI image.
544 @param[in] SystemTable A pointer to the EFI System Table.
546 @retval EFI_SUCCESS The entry point is executed successfully.
547 @retval other Some error occurs when executing this entry point.
552 InitializePs2Keyboard(
553 IN EFI_HANDLE ImageHandle
,
554 IN EFI_SYSTEM_TABLE
*SystemTable
560 // Install driver model protocol(s).
562 Status
= EfiLibInstallDriverBindingComponentName2 (
565 &gKeyboardControllerDriver
,
567 &gPs2KeyboardComponentName
,
568 &gPs2KeyboardComponentName2
570 ASSERT_EFI_ERROR (Status
);