]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
change TokenSpaceGuid to the package Token Space Guid
[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 AddUnicodeString (
278 "eng",
279 gPs2KeyboardComponentName.SupportedLanguages,
280 &ConsoleIn->ControllerNameTable,
281 L"PS/2 Keyboard Device"
282 );
283
284 //
285 // Install protocol interfaces for the keyboard device.
286 //
287 Status = gBS->InstallMultipleProtocolInterfaces (
288 &Controller,
289 &gEfiSimpleTextInProtocolGuid,
290 &ConsoleIn->ConIn,
291 NULL
292 );
293 if (EFI_ERROR (Status)) {
294 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
295 goto ErrorExit;
296 }
297
298 return Status;
299
300 ErrorExit:
301 //
302 // Report error code
303 //
304 if (StatusCode != 0) {
305 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
306 EFI_ERROR_CODE | EFI_ERROR_MINOR,
307 StatusCode,
308 ParentDevicePath
309 );
310 }
311
312 if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
313 gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
314 }
315
316 if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
317 gBS->CloseEvent (ConsoleIn->TimerEvent);
318 }
319
320 if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
321 FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
322 }
323 //
324 // Since there will be no timer handler for keyboard input any more,
325 // exhaust input data just in case there is still keyboard data left
326 //
327 Status1 = EFI_SUCCESS;
328 while (!EFI_ERROR (Status1)) {
329 Status1 = KeyboardRead (ConsoleIn, &Data);;
330 }
331
332 if (ConsoleIn != NULL) {
333 gBS->FreePool (ConsoleIn);
334 }
335
336 gBS->CloseProtocol (
337 Controller,
338 &gEfiDevicePathProtocolGuid,
339 This->DriverBindingHandle,
340 Controller
341 );
342
343 gBS->CloseProtocol (
344 Controller,
345 &gEfiIsaIoProtocolGuid,
346 This->DriverBindingHandle,
347 Controller
348 );
349
350 return Status;
351 }
352
353 EFI_STATUS
354 EFIAPI
355 KbdControllerDriverStop (
356 IN EFI_DRIVER_BINDING_PROTOCOL *This,
357 IN EFI_HANDLE Controller,
358 IN UINTN NumberOfChildren,
359 IN EFI_HANDLE *ChildHandleBuffer
360 )
361 /*++
362
363 Routine Description:
364
365 Arguments:
366
367 Returns:
368
369 --*/
370 // GC_TODO: This - add argument and description to function comment
371 // GC_TODO: Controller - add argument and description to function comment
372 // GC_TODO: NumberOfChildren - add argument and description to function comment
373 // GC_TODO: ChildHandleBuffer - add argument and description to function comment
374 // GC_TODO: EFI_SUCCESS - add return value to function comment
375 {
376 EFI_STATUS Status;
377 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
378 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
379 UINT8 Data;
380
381 //
382 // Disable Keyboard
383 //
384 Status = gBS->OpenProtocol (
385 Controller,
386 &gEfiSimpleTextInProtocolGuid,
387 (VOID **) &ConIn,
388 This->DriverBindingHandle,
389 Controller,
390 EFI_OPEN_PROTOCOL_GET_PROTOCOL
391 );
392 if (EFI_ERROR (Status)) {
393 return Status;
394 }
395
396 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
397
398 //
399 // Report that the keyboard is being disabled
400 //
401 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
402 EFI_PROGRESS_CODE,
403 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
404 ConsoleIn->DevicePath
405 );
406
407 if (ConsoleIn->TimerEvent) {
408 gBS->CloseEvent (ConsoleIn->TimerEvent);
409 ConsoleIn->TimerEvent = NULL;
410 }
411 //
412 // Disable the keyboard interface
413 //
414 Status = DisableKeyboard (ConsoleIn);
415
416 //
417 // Since there will be no timer handler for keyboard input any more,
418 // exhaust input data just in case there is still keyboard data left
419 //
420 Status = EFI_SUCCESS;
421 while (!EFI_ERROR (Status)) {
422 Status = KeyboardRead (ConsoleIn, &Data);;
423 }
424 //
425 // Uninstall the Simple TextIn Protocol
426 //
427 Status = gBS->UninstallProtocolInterface (
428 Controller,
429 &gEfiSimpleTextInProtocolGuid,
430 &ConsoleIn->ConIn
431 );
432 if (EFI_ERROR (Status)) {
433 return Status;
434 }
435
436 gBS->CloseProtocol (
437 Controller,
438 &gEfiDevicePathProtocolGuid,
439 This->DriverBindingHandle,
440 Controller
441 );
442
443 gBS->CloseProtocol (
444 Controller,
445 &gEfiIsaIoProtocolGuid,
446 This->DriverBindingHandle,
447 Controller
448 );
449
450 //
451 // Free other resources
452 //
453 if ((ConsoleIn->ConIn).WaitForKey) {
454 gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
455 (ConsoleIn->ConIn).WaitForKey = NULL;
456 }
457
458 FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
459 gBS->FreePool (ConsoleIn);
460
461 return EFI_SUCCESS;
462 }
463
464
465 /**
466 The user Entry Point for module Ps2Keyboard. The user code starts with this function.
467
468 @param[in] ImageHandle The firmware allocated handle for the EFI image.
469 @param[in] SystemTable A pointer to the EFI System Table.
470
471 @retval EFI_SUCCESS The entry point is executed successfully.
472 @retval other Some error occurs when executing this entry point.
473
474 **/
475 EFI_STATUS
476 EFIAPI
477 InitializePs2Keyboard(
478 IN EFI_HANDLE ImageHandle,
479 IN EFI_SYSTEM_TABLE *SystemTable
480 )
481 {
482 EFI_STATUS Status;
483
484 //
485 // Install driver model protocol(s).
486 //
487 Status = EfiLibInstallAllDriverProtocols (
488 ImageHandle,
489 SystemTable,
490 &gKeyboardControllerDriver,
491 ImageHandle,
492 &gPs2KeyboardComponentName,
493 NULL,
494 NULL
495 );
496 ASSERT_EFI_ERROR (Status);
497
498
499 return Status;
500 }