]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
Update to support EFI_SIMPLE_INPUT_EX protocol
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2Keyboard.c
1 /**@file
2
3 PS/2 Keyboard driver. Routines that interacts with callers,
4 conforming to EFI driver model
5
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
11
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.
14
15 **/
16
17 #include "Ps2Keyboard.h"
18
19 //
20 // Function prototypes
21 //
22 EFI_STATUS
23 EFIAPI
24 KbdControllerDriverSupported (
25 IN EFI_DRIVER_BINDING_PROTOCOL *This,
26 IN EFI_HANDLE Controller,
27 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
28 );
29
30 EFI_STATUS
31 EFIAPI
32 KbdControllerDriverStart (
33 IN EFI_DRIVER_BINDING_PROTOCOL *This,
34 IN EFI_HANDLE Controller,
35 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
36 );
37
38 EFI_STATUS
39 EFIAPI
40 KbdControllerDriverStop (
41 IN EFI_DRIVER_BINDING_PROTOCOL *This,
42 IN EFI_HANDLE Controller,
43 IN UINTN NumberOfChildren,
44 IN EFI_HANDLE *ChildHandleBuffer
45 );
46
47 //
48 // Global variables
49 //
50 //
51 // DriverBinding Protocol Instance
52 //
53 EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
54 KbdControllerDriverSupported,
55 KbdControllerDriverStart,
56 KbdControllerDriverStop,
57 0xa,
58 NULL,
59 NULL
60 };
61
62 EFI_STATUS
63 EFIAPI
64 KbdControllerDriverSupported (
65 IN EFI_DRIVER_BINDING_PROTOCOL *This,
66 IN EFI_HANDLE Controller,
67 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
68 )
69 /*++
70
71 Routine Description:
72
73 ControllerDriver Protocol Method
74
75 Arguments:
76
77 Returns:
78
79 --*/
80 // GC_TODO: This - add argument and description to function comment
81 // GC_TODO: Controller - add argument and description to function comment
82 // GC_TODO: RemainingDevicePath - add argument and description to function comment
83 {
84 EFI_STATUS Status;
85 EFI_ISA_IO_PROTOCOL *IsaIo;
86
87 //
88 // Open the IO Abstraction(s) needed to perform the supported test
89 //
90 Status = gBS->OpenProtocol (
91 Controller,
92 &gEfiIsaIoProtocolGuid,
93 (VOID **) &IsaIo,
94 This->DriverBindingHandle,
95 Controller,
96 EFI_OPEN_PROTOCOL_BY_DRIVER
97 );
98 if (EFI_ERROR (Status)) {
99 return Status;
100 }
101 //
102 // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
103 //
104 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
105 Status = EFI_UNSUPPORTED;
106 }
107 //
108 // Close the I/O Abstraction(s) used to perform the supported test
109 //
110 gBS->CloseProtocol (
111 Controller,
112 &gEfiIsaIoProtocolGuid,
113 This->DriverBindingHandle,
114 Controller
115 );
116
117 return Status;
118 }
119
120 EFI_STATUS
121 EFIAPI
122 KbdControllerDriverStart (
123 IN EFI_DRIVER_BINDING_PROTOCOL *This,
124 IN EFI_HANDLE Controller,
125 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
126 )
127 /*++
128
129 Routine Description:
130
131 Arguments:
132
133 Returns:
134
135 --*/
136 // GC_TODO: This - add argument and description to function comment
137 // GC_TODO: Controller - add argument and description to function comment
138 // GC_TODO: RemainingDevicePath - add argument and description to function comment
139 // GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
140 {
141 EFI_STATUS Status;
142 EFI_STATUS Status1;
143 EFI_ISA_IO_PROTOCOL *IsaIo;
144 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
145 UINT8 Data;
146 EFI_STATUS_CODE_VALUE StatusCode;
147 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
148
149 StatusCode = 0;
150
151 Status = gBS->OpenProtocol (
152 Controller,
153 &gEfiDevicePathProtocolGuid,
154 (VOID **) &ParentDevicePath,
155 This->DriverBindingHandle,
156 Controller,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
158 );
159 if (EFI_ERROR (Status)) {
160 return Status;
161 }
162 //
163 // Report that the keyboard is being enabled
164 //
165 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
166 EFI_PROGRESS_CODE,
167 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
168 ParentDevicePath
169 );
170
171 //
172 // Get the ISA I/O Protocol on Controller's handle
173 //
174 Status = gBS->OpenProtocol (
175 Controller,
176 &gEfiIsaIoProtocolGuid,
177 (VOID **) &IsaIo,
178 This->DriverBindingHandle,
179 Controller,
180 EFI_OPEN_PROTOCOL_BY_DRIVER
181 );
182 if (EFI_ERROR (Status)) {
183 gBS->CloseProtocol (
184 Controller,
185 &gEfiDevicePathProtocolGuid,
186 This->DriverBindingHandle,
187 Controller
188 );
189 return EFI_INVALID_PARAMETER;
190 }
191 //
192 // Allocate private data
193 //
194 ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
195 if (ConsoleIn == NULL) {
196 Status = EFI_OUT_OF_RESOURCES;
197 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
198 goto ErrorExit;
199 }
200 //
201 // Setup the device instance
202 //
203 ConsoleIn->Signature = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
204 ConsoleIn->Handle = Controller;
205 (ConsoleIn->ConIn).Reset = KeyboardEfiReset;
206 (ConsoleIn->ConIn).ReadKeyStroke = KeyboardReadKeyStroke;
207 ConsoleIn->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER;
208 ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER;
209 ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
210 ConsoleIn->IsaIo = IsaIo;
211 ConsoleIn->ScancodeBufStartPos = 0;
212 ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1;
213 ConsoleIn->ScancodeBufCount = 0;
214 ConsoleIn->Ctrled = FALSE;
215 ConsoleIn->Alted = FALSE;
216 ConsoleIn->DevicePath = ParentDevicePath;
217
218 //
219 // Setup the WaitForKey event
220 //
221 Status = gBS->CreateEvent (
222 EVT_NOTIFY_WAIT,
223 TPL_NOTIFY,
224 KeyboardWaitForKey,
225 &(ConsoleIn->ConIn),
226 &((ConsoleIn->ConIn).WaitForKey)
227 );
228 if (EFI_ERROR (Status)) {
229 Status = EFI_OUT_OF_RESOURCES;
230 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
231 goto ErrorExit;
232 }
233 //
234 // Setup a periodic timer, used for reading keystrokes at a fixed interval
235 //
236 Status = gBS->CreateEvent (
237 EVT_TIMER | EVT_NOTIFY_SIGNAL,
238 TPL_NOTIFY,
239 KeyboardTimerHandler,
240 ConsoleIn,
241 &ConsoleIn->TimerEvent
242 );
243 if (EFI_ERROR (Status)) {
244 Status = EFI_OUT_OF_RESOURCES;
245 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
246 goto ErrorExit;
247 }
248
249 Status = gBS->SetTimer (
250 ConsoleIn->TimerEvent,
251 TimerPeriodic,
252 KEYBOARD_TIMER_INTERVAL
253 );
254 if (EFI_ERROR (Status)) {
255 Status = EFI_OUT_OF_RESOURCES;
256 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
257 goto ErrorExit;
258 }
259
260 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
261 EFI_PROGRESS_CODE,
262 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
263 ParentDevicePath
264 );
265
266 //
267 // Reset the keyboard device
268 //
269 Status = ConsoleIn->ConIn.Reset (&ConsoleIn->ConIn, TRUE);
270 if (EFI_ERROR (Status)) {
271 Status = EFI_DEVICE_ERROR;
272 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
273 goto ErrorExit;
274 }
275
276 ConsoleIn->ControllerNameTable = NULL;
277 AddUnicodeString2 (
278 "eng",
279 gPs2KeyboardComponentName.SupportedLanguages,
280 &ConsoleIn->ControllerNameTable,
281 L"PS/2 Keyboard Device",
282 TRUE
283 );
284 AddUnicodeString2 (
285 "en",
286 gPs2KeyboardComponentName2.SupportedLanguages,
287 &ConsoleIn->ControllerNameTable,
288 L"PS/2 Keyboard Device",
289 FALSE
290 );
291
292
293 //
294 // Install protocol interfaces for the keyboard device.
295 //
296 Status = gBS->InstallMultipleProtocolInterfaces (
297 &Controller,
298 &gEfiSimpleTextInProtocolGuid,
299 &ConsoleIn->ConIn,
300 NULL
301 );
302 if (EFI_ERROR (Status)) {
303 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
304 goto ErrorExit;
305 }
306
307 return Status;
308
309 ErrorExit:
310 //
311 // Report error code
312 //
313 if (StatusCode != 0) {
314 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
315 EFI_ERROR_CODE | EFI_ERROR_MINOR,
316 StatusCode,
317 ParentDevicePath
318 );
319 }
320
321 if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
322 gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
323 }
324
325 if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
326 gBS->CloseEvent (ConsoleIn->TimerEvent);
327 }
328
329 if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
330 FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
331 }
332 //
333 // Since there will be no timer handler for keyboard input any more,
334 // exhaust input data just in case there is still keyboard data left
335 //
336 Status1 = EFI_SUCCESS;
337 while (!EFI_ERROR (Status1)) {
338 Status1 = KeyboardRead (ConsoleIn, &Data);;
339 }
340
341 if (ConsoleIn != NULL) {
342 gBS->FreePool (ConsoleIn);
343 }
344
345 gBS->CloseProtocol (
346 Controller,
347 &gEfiDevicePathProtocolGuid,
348 This->DriverBindingHandle,
349 Controller
350 );
351
352 gBS->CloseProtocol (
353 Controller,
354 &gEfiIsaIoProtocolGuid,
355 This->DriverBindingHandle,
356 Controller
357 );
358
359 return Status;
360 }
361
362 EFI_STATUS
363 EFIAPI
364 KbdControllerDriverStop (
365 IN EFI_DRIVER_BINDING_PROTOCOL *This,
366 IN EFI_HANDLE Controller,
367 IN UINTN NumberOfChildren,
368 IN EFI_HANDLE *ChildHandleBuffer
369 )
370 /*++
371
372 Routine Description:
373
374 Arguments:
375
376 Returns:
377
378 --*/
379 // GC_TODO: This - add argument and description to function comment
380 // GC_TODO: Controller - add argument and description to function comment
381 // GC_TODO: NumberOfChildren - add argument and description to function comment
382 // GC_TODO: ChildHandleBuffer - add argument and description to function comment
383 // GC_TODO: EFI_SUCCESS - add return value to function comment
384 {
385 EFI_STATUS Status;
386 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
387 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
388 UINT8 Data;
389
390 //
391 // Disable Keyboard
392 //
393 Status = gBS->OpenProtocol (
394 Controller,
395 &gEfiSimpleTextInProtocolGuid,
396 (VOID **) &ConIn,
397 This->DriverBindingHandle,
398 Controller,
399 EFI_OPEN_PROTOCOL_GET_PROTOCOL
400 );
401 if (EFI_ERROR (Status)) {
402 return Status;
403 }
404
405 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
406
407 //
408 // Report that the keyboard is being disabled
409 //
410 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
411 EFI_PROGRESS_CODE,
412 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
413 ConsoleIn->DevicePath
414 );
415
416 if (ConsoleIn->TimerEvent) {
417 gBS->CloseEvent (ConsoleIn->TimerEvent);
418 ConsoleIn->TimerEvent = NULL;
419 }
420 //
421 // Disable the keyboard interface
422 //
423 Status = DisableKeyboard (ConsoleIn);
424
425 //
426 // Since there will be no timer handler for keyboard input any more,
427 // exhaust input data just in case there is still keyboard data left
428 //
429 Status = EFI_SUCCESS;
430 while (!EFI_ERROR (Status)) {
431 Status = KeyboardRead (ConsoleIn, &Data);;
432 }
433 //
434 // Uninstall the Simple TextIn Protocol
435 //
436 Status = gBS->UninstallProtocolInterface (
437 Controller,
438 &gEfiSimpleTextInProtocolGuid,
439 &ConsoleIn->ConIn
440 );
441 if (EFI_ERROR (Status)) {
442 return Status;
443 }
444
445 gBS->CloseProtocol (
446 Controller,
447 &gEfiDevicePathProtocolGuid,
448 This->DriverBindingHandle,
449 Controller
450 );
451
452 gBS->CloseProtocol (
453 Controller,
454 &gEfiIsaIoProtocolGuid,
455 This->DriverBindingHandle,
456 Controller
457 );
458
459 //
460 // Free other resources
461 //
462 if ((ConsoleIn->ConIn).WaitForKey) {
463 gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
464 (ConsoleIn->ConIn).WaitForKey = NULL;
465 }
466
467 FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
468 gBS->FreePool (ConsoleIn);
469
470 return EFI_SUCCESS;
471 }
472
473
474 /**
475 The user Entry Point for module Ps2Keyboard. The user code starts with this function.
476
477 @param[in] ImageHandle The firmware allocated handle for the EFI image.
478 @param[in] SystemTable A pointer to the EFI System Table.
479
480 @retval EFI_SUCCESS The entry point is executed successfully.
481 @retval other Some error occurs when executing this entry point.
482
483 **/
484 EFI_STATUS
485 EFIAPI
486 InitializePs2Keyboard(
487 IN EFI_HANDLE ImageHandle,
488 IN EFI_SYSTEM_TABLE *SystemTable
489 )
490 {
491 EFI_STATUS Status;
492
493 //
494 // Install driver model protocol(s).
495 //
496 Status = EfiLibInstallDriverBindingComponentName2 (
497 ImageHandle,
498 SystemTable,
499 &gKeyboardControllerDriver,
500 ImageHandle,
501 &gPs2KeyboardComponentName,
502 &gPs2KeyboardComponentName2
503 );
504 ASSERT_EFI_ERROR (Status);
505
506
507 return Status;
508 }