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