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