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
50 IN OUT LIST_ENTRY
*ListHead
54 // DriverBinding Protocol Instance
56 EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver
= {
57 KbdControllerDriverSupported
,
58 KbdControllerDriverStart
,
59 KbdControllerDriverStop
,
66 Test controller is a keyboard Controller
68 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
69 @param Controller driver's controller
70 @param RemainingDevicePath children device path
72 @retval EFI_UNSUPPORTED controller is not floppy disk
73 @retval EFI_SUCCESS controller is floppy disk
77 KbdControllerDriverSupported (
78 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
79 IN EFI_HANDLE Controller
,
80 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
84 EFI_ISA_IO_PROTOCOL
*IsaIo
;
87 // Open the IO Abstraction(s) needed to perform the supported test
89 Status
= gBS
->OpenProtocol (
91 &gEfiIsaIoProtocolGuid
,
93 This
->DriverBindingHandle
,
95 EFI_OPEN_PROTOCOL_BY_DRIVER
97 if (EFI_ERROR (Status
)) {
101 // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
103 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x303) || IsaIo
->ResourceList
->Device
.UID
!= 0) {
104 Status
= EFI_UNSUPPORTED
;
107 // Close the I/O Abstraction(s) used to perform the supported test
111 &gEfiIsaIoProtocolGuid
,
112 This
->DriverBindingHandle
,
120 Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
122 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
123 @param Controller driver controller handle
124 @param RemainingDevicePath Children's device path
126 @retval whether success to create floppy control instance.
130 KbdControllerDriverStart (
131 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
132 IN EFI_HANDLE Controller
,
133 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
138 EFI_ISA_IO_PROTOCOL
*IsaIo
;
139 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
141 EFI_STATUS_CODE_VALUE StatusCode
;
142 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
146 Status
= gBS
->OpenProtocol (
148 &gEfiDevicePathProtocolGuid
,
149 (VOID
**) &ParentDevicePath
,
150 This
->DriverBindingHandle
,
152 EFI_OPEN_PROTOCOL_BY_DRIVER
154 if (EFI_ERROR (Status
)) {
158 // Report that the keyboard is being enabled
160 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
162 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
,
167 // Get the ISA I/O Protocol on Controller's handle
169 Status
= gBS
->OpenProtocol (
171 &gEfiIsaIoProtocolGuid
,
173 This
->DriverBindingHandle
,
175 EFI_OPEN_PROTOCOL_BY_DRIVER
177 if (EFI_ERROR (Status
)) {
180 &gEfiDevicePathProtocolGuid
,
181 This
->DriverBindingHandle
,
184 return EFI_INVALID_PARAMETER
;
187 // Allocate private data
189 ConsoleIn
= AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV
));
190 if (ConsoleIn
== NULL
) {
191 Status
= EFI_OUT_OF_RESOURCES
;
192 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
196 // Setup the device instance
198 ConsoleIn
->Signature
= KEYBOARD_CONSOLE_IN_DEV_SIGNATURE
;
199 ConsoleIn
->Handle
= Controller
;
200 (ConsoleIn
->ConIn
).Reset
= KeyboardEfiReset
;
201 (ConsoleIn
->ConIn
).ReadKeyStroke
= KeyboardReadKeyStroke
;
202 ConsoleIn
->DataRegisterAddress
= KEYBOARD_8042_DATA_REGISTER
;
203 ConsoleIn
->StatusRegisterAddress
= KEYBOARD_8042_STATUS_REGISTER
;
204 ConsoleIn
->CommandRegisterAddress
= KEYBOARD_8042_COMMAND_REGISTER
;
205 ConsoleIn
->IsaIo
= IsaIo
;
206 ConsoleIn
->ScancodeBufStartPos
= 0;
207 ConsoleIn
->ScancodeBufEndPos
= KEYBOARD_BUFFER_MAX_COUNT
- 1;
208 ConsoleIn
->ScancodeBufCount
= 0;
209 ConsoleIn
->Ctrled
= FALSE
;
210 ConsoleIn
->Alted
= FALSE
;
211 ConsoleIn
->DevicePath
= ParentDevicePath
;
213 ConsoleIn
->ConInEx
.Reset
= KeyboardEfiResetEx
;
214 ConsoleIn
->ConInEx
.ReadKeyStrokeEx
= KeyboardReadKeyStrokeEx
;
215 ConsoleIn
->ConInEx
.SetState
= KeyboardSetState
;
216 ConsoleIn
->ConInEx
.RegisterKeyNotify
= KeyboardRegisterKeyNotify
;
217 ConsoleIn
->ConInEx
.UnregisterKeyNotify
= KeyboardUnregisterKeyNotify
;
219 InitializeListHead (&ConsoleIn
->NotifyList
);
221 // Setup the WaitForKey event
223 Status
= gBS
->CreateEvent (
228 &((ConsoleIn
->ConIn
).WaitForKey
)
230 if (EFI_ERROR (Status
)) {
231 Status
= EFI_OUT_OF_RESOURCES
;
232 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
236 // Setup the WaitForKeyEx event
238 Status
= gBS
->CreateEvent (
241 KeyboardWaitForKeyEx
,
242 &(ConsoleIn
->ConInEx
),
243 &(ConsoleIn
->ConInEx
.WaitForKeyEx
)
245 if (EFI_ERROR (Status
)) {
246 Status
= EFI_OUT_OF_RESOURCES
;
247 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
250 // Setup a periodic timer, used for reading keystrokes at a fixed interval
252 Status
= gBS
->CreateEvent (
253 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
255 KeyboardTimerHandler
,
257 &ConsoleIn
->TimerEvent
259 if (EFI_ERROR (Status
)) {
260 Status
= EFI_OUT_OF_RESOURCES
;
261 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
265 Status
= gBS
->SetTimer (
266 ConsoleIn
->TimerEvent
,
268 KEYBOARD_TIMER_INTERVAL
270 if (EFI_ERROR (Status
)) {
271 Status
= EFI_OUT_OF_RESOURCES
;
272 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
276 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
278 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
,
283 // Reset the keyboard device
285 Status
= ConsoleIn
->ConIn
.Reset (&ConsoleIn
->ConIn
, TRUE
);
286 if (EFI_ERROR (Status
)) {
287 Status
= EFI_DEVICE_ERROR
;
288 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
;
292 ConsoleIn
->ControllerNameTable
= NULL
;
295 gPs2KeyboardComponentName
.SupportedLanguages
,
296 &ConsoleIn
->ControllerNameTable
,
297 L
"PS/2 Keyboard Device",
302 gPs2KeyboardComponentName2
.SupportedLanguages
,
303 &ConsoleIn
->ControllerNameTable
,
304 L
"PS/2 Keyboard Device",
310 // Install protocol interfaces for the keyboard device.
312 Status
= gBS
->InstallMultipleProtocolInterfaces (
314 &gEfiSimpleTextInProtocolGuid
,
316 &gEfiSimpleTextInputExProtocolGuid
,
320 if (EFI_ERROR (Status
)) {
321 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
331 if (StatusCode
!= 0) {
332 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
333 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
339 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->ConIn
.WaitForKey
!= NULL
)) {
340 gBS
->CloseEvent (ConsoleIn
->ConIn
.WaitForKey
);
343 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->TimerEvent
!= NULL
)) {
344 gBS
->CloseEvent (ConsoleIn
->TimerEvent
);
346 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->ConInEx
.WaitForKeyEx
!= NULL
)) {
347 gBS
->CloseEvent (ConsoleIn
->ConInEx
.WaitForKeyEx
);
349 KbdFreeNotifyList (&ConsoleIn
->NotifyList
);
350 if ((ConsoleIn
!= NULL
) && (ConsoleIn
->ControllerNameTable
!= NULL
)) {
351 FreeUnicodeStringTable (ConsoleIn
->ControllerNameTable
);
354 // Since there will be no timer handler for keyboard input any more,
355 // exhaust input data just in case there is still keyboard data left
357 Status1
= EFI_SUCCESS
;
358 while (!EFI_ERROR (Status1
)) {
359 Status1
= KeyboardRead (ConsoleIn
, &Data
);;
362 if (ConsoleIn
!= NULL
) {
363 gBS
->FreePool (ConsoleIn
);
368 &gEfiDevicePathProtocolGuid
,
369 This
->DriverBindingHandle
,
375 &gEfiIsaIoProtocolGuid
,
376 This
->DriverBindingHandle
,
384 Stop this driver on ControllerHandle. Support stoping any child handles
385 created by this driver.
387 @param This Protocol instance pointer.
388 @param ControllerHandle Handle of device to stop driver on
389 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
390 children is zero stop the entire bus driver.
391 @param ChildHandleBuffer List of Child Handles to Stop.
393 @retval EFI_SUCCESS This driver is removed ControllerHandle
394 @retval other This driver was not removed from this device
399 KbdControllerDriverStop (
400 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
401 IN EFI_HANDLE Controller
,
402 IN UINTN NumberOfChildren
,
403 IN EFI_HANDLE
*ChildHandleBuffer
407 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*ConIn
;
408 KEYBOARD_CONSOLE_IN_DEV
*ConsoleIn
;
414 Status
= gBS
->OpenProtocol (
416 &gEfiSimpleTextInProtocolGuid
,
418 This
->DriverBindingHandle
,
420 EFI_OPEN_PROTOCOL_GET_PROTOCOL
422 if (EFI_ERROR (Status
)) {
425 Status
= gBS
->OpenProtocol (
427 &gEfiSimpleTextInputExProtocolGuid
,
429 This
->DriverBindingHandle
,
431 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
433 if (EFI_ERROR (Status
)) {
437 ConsoleIn
= KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn
);
440 // Report that the keyboard is being disabled
442 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
444 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
,
445 ConsoleIn
->DevicePath
448 if (ConsoleIn
->TimerEvent
) {
449 gBS
->CloseEvent (ConsoleIn
->TimerEvent
);
450 ConsoleIn
->TimerEvent
= NULL
;
453 // Disable the keyboard interface
455 Status
= DisableKeyboard (ConsoleIn
);
458 // Since there will be no timer handler for keyboard input any more,
459 // exhaust input data just in case there is still keyboard data left
461 Status
= EFI_SUCCESS
;
462 while (!EFI_ERROR (Status
)) {
463 Status
= KeyboardRead (ConsoleIn
, &Data
);;
466 // Uninstall the SimpleTextIn and SimpleTextInEx protocols
468 Status
= gBS
->UninstallMultipleProtocolInterfaces (
470 &gEfiSimpleTextInProtocolGuid
,
472 &gEfiSimpleTextInputExProtocolGuid
,
476 if (EFI_ERROR (Status
)) {
482 &gEfiDevicePathProtocolGuid
,
483 This
->DriverBindingHandle
,
489 &gEfiIsaIoProtocolGuid
,
490 This
->DriverBindingHandle
,
495 // Free other resources
497 if ((ConsoleIn
->ConIn
).WaitForKey
) {
498 gBS
->CloseEvent ((ConsoleIn
->ConIn
).WaitForKey
);
499 (ConsoleIn
->ConIn
).WaitForKey
= NULL
;
501 if (ConsoleIn
->ConInEx
.WaitForKeyEx
!= NULL
) {
502 gBS
->CloseEvent (ConsoleIn
->ConInEx
.WaitForKeyEx
);
503 ConsoleIn
->ConInEx
.WaitForKeyEx
= NULL
;
505 KbdFreeNotifyList (&ConsoleIn
->NotifyList
);
506 FreeUnicodeStringTable (ConsoleIn
->ControllerNameTable
);
507 gBS
->FreePool (ConsoleIn
);
513 Free the waiting key notify list.
515 @param ListHead Pointer to list head
520 IN OUT LIST_ENTRY
*ListHead
523 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
525 if (ListHead
== NULL
) {
526 return EFI_INVALID_PARAMETER
;
528 while (!IsListEmpty (ListHead
)) {
530 ListHead
->ForwardLink
,
531 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
533 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
535 RemoveEntryList (ListHead
->ForwardLink
);
536 gBS
->FreePool (NotifyNode
);
543 The user Entry Point for module Ps2Keyboard. The user code starts with this function.
545 @param[in] ImageHandle The firmware allocated handle for the EFI image.
546 @param[in] SystemTable A pointer to the EFI System Table.
548 @retval EFI_SUCCESS The entry point is executed successfully.
549 @retval other Some error occurs when executing this entry point.
554 InitializePs2Keyboard(
555 IN EFI_HANDLE ImageHandle
,
556 IN EFI_SYSTEM_TABLE
*SystemTable
562 // Install driver model protocol(s).
564 Status
= EfiLibInstallDriverBindingComponentName2 (
567 &gKeyboardControllerDriver
,
569 &gPs2KeyboardComponentName
,
570 &gPs2KeyboardComponentName2
572 ASSERT_EFI_ERROR (Status
);