Home | History | Annotate | Download | only in Ps2MouseAbsolutePointerDxe
      1 /** @file
      2   A faked PS/2 Absolute Pointer driver. Routines that interacts with callers,
      3   conforming to EFI driver model
      4 
      5 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Ps2MouseAbsolutePointer.h"
     17 #include "CommPs2.h"
     18 
     19 //
     20 // DriverBinding Protocol Instance
     21 //
     22 EFI_DRIVER_BINDING_PROTOCOL gPS2MouseAbsolutePointerDriver = {
     23   PS2MouseAbsolutePointerDriverSupported,
     24   PS2MouseAbsolutePointerDriverStart,
     25   PS2MouseAbsolutePointerDriverStop,
     26   0x1,
     27   NULL,
     28   NULL
     29 };
     30 
     31 /**
     32   Test to see if this driver supports ControllerHandle. Any ControllerHandle
     33   than contains a IsaIo protocol can be supported.
     34 
     35   @param  This                Protocol instance pointer.
     36   @param  ControllerHandle    Handle of device to test
     37   @param  RemainingDevicePath Optional parameter use to pick a specific child
     38                               device to start.
     39 
     40   @retval EFI_SUCCESS         This driver supports this device
     41   @retval EFI_ALREADY_STARTED This driver is already running on this device
     42   @retval other               This driver does not support this device
     43 
     44 **/
     45 EFI_STATUS
     46 EFIAPI
     47 PS2MouseAbsolutePointerDriverSupported (
     48   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
     49   IN EFI_HANDLE                     Controller,
     50   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
     51   )
     52 {
     53   EFI_STATUS                          Status;
     54   EFI_ISA_IO_PROTOCOL                 *IsaIo;
     55 
     56   Status = EFI_SUCCESS;
     57 
     58   //
     59   // Open the IO Abstraction(s) needed to perform the supported test
     60   //
     61   Status = gBS->OpenProtocol (
     62                   Controller,
     63                   &gEfiIsaIoProtocolGuid,
     64                   (VOID **) &IsaIo,
     65                   This->DriverBindingHandle,
     66                   Controller,
     67                   EFI_OPEN_PROTOCOL_BY_DRIVER
     68                   );
     69   if (EFI_ERROR (Status)) {
     70     return Status;
     71   }
     72   //
     73   // Use the ISA I/O Protocol to see if Controller is the Mouse controller
     74   //
     75   switch (IsaIo->ResourceList->Device.HID) {
     76   case EISA_PNP_ID (0xF03):
     77   //
     78   // Microsoft PS/2 style mouse
     79   //
     80   case EISA_PNP_ID (0xF13):
     81     //
     82     // PS/2 Port for PS/2-style Mice
     83     //
     84     break;
     85 
     86   case EISA_PNP_ID (0x303):
     87     //
     88     // IBM Enhanced (101/102-key, PS/2 mouse support)
     89     //
     90     if (IsaIo->ResourceList->Device.UID == 1) {
     91       break;
     92     }
     93 
     94   default:
     95     Status = EFI_UNSUPPORTED;
     96     break;
     97   }
     98   //
     99   // Close the I/O Abstraction(s) used to perform the supported test
    100   //
    101   gBS->CloseProtocol (
    102          Controller,
    103          &gEfiIsaIoProtocolGuid,
    104          This->DriverBindingHandle,
    105          Controller
    106          );
    107 
    108   return Status;
    109 }
    110 
    111 /**
    112   Start this driver on ControllerHandle by opening a IsaIo protocol, creating
    113   PS2_MOUSE_ABSOLUTE_POINTER_DEV device and install gEfiAbsolutePointerProtocolGuid
    114   finally.
    115 
    116   @param  This                 Protocol instance pointer.
    117   @param  ControllerHandle     Handle of device to bind driver to
    118   @param  RemainingDevicePath  Optional parameter use to pick a specific child
    119                                device to start.
    120 
    121   @retval EFI_SUCCESS          This driver is added to ControllerHandle
    122   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
    123   @retval other                This driver does not support this device
    124 
    125 **/
    126 EFI_STATUS
    127 EFIAPI
    128 PS2MouseAbsolutePointerDriverStart (
    129   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
    130   IN EFI_HANDLE                     Controller,
    131   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
    132   )
    133 {
    134   EFI_STATUS                          Status;
    135   EFI_STATUS                          EmptyStatus;
    136   EFI_ISA_IO_PROTOCOL                 *IsaIo;
    137   PS2_MOUSE_ABSOLUTE_POINTER_DEV     *MouseAbsolutePointerDev;
    138   UINT8                               Data;
    139   EFI_TPL                             OldTpl;
    140   EFI_STATUS_CODE_VALUE               StatusCode;
    141   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
    142 
    143   StatusCode  = 0;
    144   MouseAbsolutePointerDev    = NULL;
    145   IsaIo       = NULL;
    146 
    147   //
    148   // Open the device path protocol
    149   //
    150   Status = gBS->OpenProtocol (
    151                   Controller,
    152                   &gEfiDevicePathProtocolGuid,
    153                   (VOID **) &ParentDevicePath,
    154                   This->DriverBindingHandle,
    155                   Controller,
    156                   EFI_OPEN_PROTOCOL_BY_DRIVER
    157                   );
    158   if (EFI_ERROR (Status)) {
    159     return Status;
    160   }
    161   //
    162   // Report that the keyboard is being enabled
    163   //
    164   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    165     EFI_PROGRESS_CODE,
    166     EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE,
    167     ParentDevicePath
    168     );
    169 
    170   //
    171   // Get the ISA I/O Protocol on Controller's handle
    172   //
    173   Status = gBS->OpenProtocol (
    174                   Controller,
    175                   &gEfiIsaIoProtocolGuid,
    176                   (VOID **) &IsaIo,
    177                   This->DriverBindingHandle,
    178                   Controller,
    179                   EFI_OPEN_PROTOCOL_BY_DRIVER
    180                   );
    181   if (EFI_ERROR (Status)) {
    182     gBS->CloseProtocol (
    183            Controller,
    184            &gEfiDevicePathProtocolGuid,
    185            This->DriverBindingHandle,
    186            Controller
    187            );
    188     return EFI_INVALID_PARAMETER;
    189   }
    190   //
    191   // Raise TPL to avoid keyboard operation impact
    192   //
    193   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    194 
    195   //
    196   // Allocate private data
    197   //
    198   MouseAbsolutePointerDev = AllocateZeroPool (sizeof (PS2_MOUSE_ABSOLUTE_POINTER_DEV));
    199   if (MouseAbsolutePointerDev == NULL) {
    200     Status = EFI_OUT_OF_RESOURCES;
    201     goto ErrorExit;
    202   }
    203   //
    204   // Setup the device instance
    205   //
    206   MouseAbsolutePointerDev->Signature       = PS2_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE;
    207   MouseAbsolutePointerDev->Handle          = Controller;
    208   MouseAbsolutePointerDev->SampleRate      = SampleRate20;
    209   MouseAbsolutePointerDev->Resolution      = MouseResolution4;
    210   MouseAbsolutePointerDev->Scaling         = Scaling1;
    211   MouseAbsolutePointerDev->DataPackageSize = 3;
    212   MouseAbsolutePointerDev->IsaIo           = IsaIo;
    213   MouseAbsolutePointerDev->DevicePath      = ParentDevicePath;
    214 
    215   //
    216   // Resolution = 4 counts/mm
    217   //
    218   MouseAbsolutePointerDev->Mode.AbsoluteMaxX               = 1024;
    219   MouseAbsolutePointerDev->Mode.AbsoluteMinX               = 0;
    220   MouseAbsolutePointerDev->Mode.AbsoluteMaxY               = 798;
    221   MouseAbsolutePointerDev->Mode.AbsoluteMinY               = 0;
    222   MouseAbsolutePointerDev->Mode.AbsoluteMaxZ               = 0;
    223   MouseAbsolutePointerDev->Mode.AbsoluteMinZ               = 0;
    224   MouseAbsolutePointerDev->Mode.Attributes                 = 0x03;
    225 
    226   MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset     = MouseAbsolutePointerReset;
    227   MouseAbsolutePointerDev->AbsolutePointerProtocol.GetState  = MouseAbsolutePointerGetState;
    228   MouseAbsolutePointerDev->AbsolutePointerProtocol.Mode      = &(MouseAbsolutePointerDev->Mode);
    229 
    230   //
    231   // Initialize keyboard controller if necessary
    232   //
    233   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    234     EFI_PROGRESS_CODE,
    235     EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST,
    236     ParentDevicePath
    237     );
    238 
    239   IsaIo->Io.Read (IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
    240   if ((Data & KBC_SYSF) != KBC_SYSF) {
    241     Status = KbcSelfTest (IsaIo);
    242     if (EFI_ERROR (Status)) {
    243       StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR;
    244       goto ErrorExit;
    245     }
    246   }
    247 
    248   KbcEnableAux (IsaIo);
    249 
    250   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    251     EFI_PROGRESS_CODE,
    252     EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT,
    253     ParentDevicePath
    254     );
    255 
    256   //
    257   // Reset the mouse
    258   //
    259   Status = MouseAbsolutePointerDev->AbsolutePointerProtocol.Reset (
    260                      &MouseAbsolutePointerDev->AbsolutePointerProtocol,
    261                      FeaturePcdGet (PcdPs2MouseExtendedVerification)
    262                      );
    263   if (EFI_ERROR (Status)) {
    264     //
    265     // mouse not connected
    266     //
    267     Status      = EFI_SUCCESS;
    268     StatusCode  = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED;
    269     goto ErrorExit;
    270   }
    271 
    272   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    273     EFI_PROGRESS_CODE,
    274     EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED,
    275     ParentDevicePath
    276     );
    277 
    278   //
    279   // Setup the WaitForKey event
    280   //
    281   Status = gBS->CreateEvent (
    282                   EVT_NOTIFY_WAIT,
    283                   TPL_NOTIFY,
    284                   MouseAbsolutePointerWaitForInput,
    285                   MouseAbsolutePointerDev,
    286                   &((MouseAbsolutePointerDev->AbsolutePointerProtocol).WaitForInput)
    287                   );
    288   if (EFI_ERROR (Status)) {
    289     Status = EFI_OUT_OF_RESOURCES;
    290     goto ErrorExit;
    291   }
    292   //
    293   // Setup a periodic timer, used to poll mouse state
    294   //
    295   Status = gBS->CreateEvent (
    296                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
    297                   TPL_NOTIFY,
    298                   PollMouseAbsolutePointer,
    299                   MouseAbsolutePointerDev,
    300                   &MouseAbsolutePointerDev->TimerEvent
    301                   );
    302   if (EFI_ERROR (Status)) {
    303     Status = EFI_OUT_OF_RESOURCES;
    304     goto ErrorExit;
    305   }
    306   //
    307   // Start timer to poll mouse (100 samples per second)
    308   //
    309   Status = gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerPeriodic, 100000);
    310   if (EFI_ERROR (Status)) {
    311     Status = EFI_OUT_OF_RESOURCES;
    312     goto ErrorExit;
    313   }
    314 
    315   MouseAbsolutePointerDev->ControllerNameTable = NULL;
    316   AddUnicodeString2 (
    317     "eng",
    318     gPs2MouseAbsolutePointerComponentName.SupportedLanguages,
    319     &MouseAbsolutePointerDev->ControllerNameTable,
    320     L"Faked PS/2 Touchpad Device",
    321     TRUE
    322     );
    323   AddUnicodeString2 (
    324     "en",
    325     gPs2MouseAbsolutePointerComponentName2.SupportedLanguages,
    326     &MouseAbsolutePointerDev->ControllerNameTable,
    327     L"Faked PS/2 Touchpad Device",
    328     FALSE
    329     );
    330 
    331 
    332   //
    333   // Install protocol interfaces for the mouse device.
    334   //
    335   Status = gBS->InstallMultipleProtocolInterfaces (
    336                   &Controller,
    337                   &gEfiAbsolutePointerProtocolGuid,
    338                   &MouseAbsolutePointerDev->AbsolutePointerProtocol,
    339                   NULL
    340                   );
    341   if (EFI_ERROR (Status)) {
    342     goto ErrorExit;
    343   }
    344 
    345   gBS->RestoreTPL (OldTpl);
    346 
    347   return Status;
    348 
    349 ErrorExit:
    350 
    351   KbcDisableAux (IsaIo);
    352 
    353   if (StatusCode != 0) {
    354     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    355       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    356       StatusCode,
    357       ParentDevicePath
    358       );
    359   }
    360 
    361   if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput != NULL)) {
    362     gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput);
    363   }
    364 
    365   if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->TimerEvent != NULL)) {
    366     gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent);
    367   }
    368 
    369   if ((MouseAbsolutePointerDev != NULL) && (MouseAbsolutePointerDev->ControllerNameTable != NULL)) {
    370     FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable);
    371   }
    372   //
    373   // Since there will be no timer handler for mouse input any more,
    374   // exhaust input data just in case there is still mouse data left
    375   //
    376   EmptyStatus = EFI_SUCCESS;
    377   while (!EFI_ERROR (EmptyStatus)) {
    378     EmptyStatus = In8042Data (IsaIo, &Data);
    379   }
    380 
    381   if (MouseAbsolutePointerDev != NULL) {
    382     FreePool (MouseAbsolutePointerDev);
    383   }
    384 
    385   gBS->CloseProtocol (
    386          Controller,
    387          &gEfiDevicePathProtocolGuid,
    388          This->DriverBindingHandle,
    389          Controller
    390          );
    391 
    392   gBS->CloseProtocol (
    393          Controller,
    394          &gEfiIsaIoProtocolGuid,
    395          This->DriverBindingHandle,
    396          Controller
    397          );
    398 
    399   gBS->RestoreTPL (OldTpl);
    400 
    401   return Status;
    402 }
    403 
    404 /**
    405   Stop this driver on ControllerHandle. Support stoping any child handles
    406   created by this driver.
    407 
    408   @param  This              Protocol instance pointer.
    409   @param  ControllerHandle  Handle of device to stop driver on
    410   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    411                             children is zero stop the entire bus driver.
    412   @param  ChildHandleBuffer List of Child Handles to Stop.
    413 
    414   @retval EFI_SUCCESS       This driver is removed ControllerHandle
    415   @retval other             This driver was not removed from this device
    416 
    417 **/
    418 EFI_STATUS
    419 EFIAPI
    420 PS2MouseAbsolutePointerDriverStop (
    421   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
    422   IN EFI_HANDLE                     Controller,
    423   IN UINTN                          NumberOfChildren,
    424   IN EFI_HANDLE                     *ChildHandleBuffer
    425   )
    426 {
    427   EFI_STATUS                            Status;
    428   EFI_ABSOLUTE_POINTER_PROTOCOL         *AbsolutePointerProtocol;
    429   PS2_MOUSE_ABSOLUTE_POINTER_DEV       *MouseAbsolutePointerDev;
    430   UINT8                                 Data;
    431 
    432   Status = gBS->OpenProtocol (
    433                   Controller,
    434                   &gEfiAbsolutePointerProtocolGuid,
    435                   (VOID **) &AbsolutePointerProtocol,
    436                   This->DriverBindingHandle,
    437                   Controller,
    438                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    439                   );
    440   if (EFI_ERROR (Status)) {
    441     return EFI_SUCCESS;
    442   }
    443 
    444   MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (AbsolutePointerProtocol);
    445 
    446   //
    447   // Report that the keyboard is being disabled
    448   //
    449   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    450     EFI_PROGRESS_CODE,
    451     EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE,
    452     MouseAbsolutePointerDev->DevicePath
    453     );
    454 
    455   Status = gBS->UninstallProtocolInterface (
    456                   Controller,
    457                   &gEfiAbsolutePointerProtocolGuid,
    458                   &MouseAbsolutePointerDev->AbsolutePointerProtocol
    459                   );
    460   if (EFI_ERROR (Status)) {
    461     return Status;
    462   }
    463 
    464   //
    465   // Cancel mouse data polling timer, close timer event
    466   //
    467   gBS->SetTimer (MouseAbsolutePointerDev->TimerEvent, TimerCancel, 0);
    468   gBS->CloseEvent (MouseAbsolutePointerDev->TimerEvent);
    469 
    470   //
    471   // Since there will be no timer handler for mouse input any more,
    472   // exhaust input data just in case there is still mouse data left
    473   //
    474   Status = EFI_SUCCESS;
    475   while (!EFI_ERROR (Status)) {
    476     Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data);
    477   }
    478 
    479   gBS->CloseEvent (MouseAbsolutePointerDev->AbsolutePointerProtocol.WaitForInput);
    480   FreeUnicodeStringTable (MouseAbsolutePointerDev->ControllerNameTable);
    481   FreePool (MouseAbsolutePointerDev);
    482 
    483   gBS->CloseProtocol (
    484          Controller,
    485          &gEfiDevicePathProtocolGuid,
    486          This->DriverBindingHandle,
    487          Controller
    488          );
    489 
    490   gBS->CloseProtocol (
    491          Controller,
    492          &gEfiIsaIoProtocolGuid,
    493          This->DriverBindingHandle,
    494          Controller
    495          );
    496 
    497   return EFI_SUCCESS;
    498 }
    499 
    500 /**
    501   Reset the Mouse and do BAT test for it, if ExtendedVerification isTRUE and there is a mouse device connectted to system.
    502 
    503   @param This                 - Pointer of simple pointer Protocol.
    504   @param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip.
    505 
    506 
    507   @retval EFI_SUCCESS         - The command byte is written successfully.
    508   @retval EFI_DEVICE_ERROR    - Errors occurred during reseting keyboard.
    509 
    510 **/
    511 EFI_STATUS
    512 EFIAPI
    513 MouseAbsolutePointerReset (
    514   IN EFI_ABSOLUTE_POINTER_PROTOCOL    *This,
    515   IN BOOLEAN                          ExtendedVerification
    516   )
    517 {
    518   EFI_STATUS                       Status;
    519   PS2_MOUSE_ABSOLUTE_POINTER_DEV  *MouseAbsolutePointerDev;
    520   EFI_TPL                          OldTpl;
    521   BOOLEAN                          KeyboardEnable;
    522   UINT8                            Data;
    523 
    524   MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This);
    525 
    526   //
    527   // Report reset progress code
    528   //
    529   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    530     EFI_PROGRESS_CODE,
    531     EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET,
    532     MouseAbsolutePointerDev->DevicePath
    533     );
    534 
    535   KeyboardEnable = FALSE;
    536 
    537   //
    538   // Raise TPL to avoid keyboard operation impact
    539   //
    540   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    541 
    542   ZeroMem (&MouseAbsolutePointerDev->State, sizeof (EFI_ABSOLUTE_POINTER_STATE));
    543   MouseAbsolutePointerDev->StateChanged = FALSE;
    544 
    545   //
    546   // Exhaust input data
    547   //
    548   Status = EFI_SUCCESS;
    549   while (!EFI_ERROR (Status)) {
    550     Status = In8042Data (MouseAbsolutePointerDev->IsaIo, &Data);
    551   }
    552 
    553   CheckKbStatus (MouseAbsolutePointerDev->IsaIo, &KeyboardEnable);
    554 
    555   KbcDisableKb (MouseAbsolutePointerDev->IsaIo);
    556 
    557   MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_CMD_STS_PORT, 1, &Data);
    558 
    559   //
    560   // if there's data block on KBC data port, read it out
    561   //
    562   if ((Data & KBC_OUTB) == KBC_OUTB) {
    563     MouseAbsolutePointerDev->IsaIo->Io.Read (MouseAbsolutePointerDev->IsaIo, EfiIsaIoWidthUint8, KBC_DATA_PORT, 1, &Data);
    564   }
    565 
    566   Status = EFI_SUCCESS;
    567   //
    568   // The PS2 mouse driver reset behavior is always successfully return no matter wheater or not there is mouse connected to system.
    569   // This behavior is needed by performance speed. The following mouse command only succeessfully finish when mouse device is
    570   // connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling
    571   //
    572   if (ExtendedVerification && CheckMouseAbsolutePointerConnect (MouseAbsolutePointerDev)) {
    573     //
    574     // Send mouse reset command and set mouse default configure
    575     //
    576     Status = PS2MouseReset (MouseAbsolutePointerDev->IsaIo);
    577     if (EFI_ERROR (Status)) {
    578       Status = EFI_DEVICE_ERROR;
    579       goto Exit;
    580     }
    581 
    582     Status = PS2MouseSetSampleRate (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->SampleRate);
    583     if (EFI_ERROR (Status)) {
    584       Status = EFI_DEVICE_ERROR;
    585       goto Exit;
    586     }
    587 
    588     Status = PS2MouseSetResolution (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Resolution);
    589     if (EFI_ERROR (Status)) {
    590       Status = EFI_DEVICE_ERROR;
    591       goto Exit;
    592     }
    593 
    594     Status = PS2MouseSetScaling (MouseAbsolutePointerDev->IsaIo, MouseAbsolutePointerDev->Scaling);
    595     if (EFI_ERROR (Status)) {
    596       Status = EFI_DEVICE_ERROR;
    597       goto Exit;
    598     }
    599 
    600     Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo);
    601     if (EFI_ERROR (Status)) {
    602       Status = EFI_DEVICE_ERROR;
    603       goto Exit;
    604     }
    605   }
    606 Exit:
    607   gBS->RestoreTPL (OldTpl);
    608 
    609   if (KeyboardEnable) {
    610     KbcEnableKb (MouseAbsolutePointerDev->IsaIo);
    611   }
    612 
    613   return Status;
    614 }
    615 
    616 /**
    617   Check whether there is Ps/2 mouse device in system
    618 
    619   @param MouseAbsolutePointerDev - Absolute Pointer Device Private Data Structure
    620 
    621   @retval TRUE                - Keyboard in System.
    622   @retval FALSE               - Keyboard not in System.
    623 
    624 **/
    625 BOOLEAN
    626 CheckMouseAbsolutePointerConnect (
    627   IN  PS2_MOUSE_ABSOLUTE_POINTER_DEV     *MouseAbsolutePointerDev
    628   )
    629 
    630 {
    631   EFI_STATUS     Status;
    632 
    633   Status = PS2MouseEnable (MouseAbsolutePointerDev->IsaIo);
    634   if (!EFI_ERROR (Status)) {
    635     return TRUE;
    636   }
    637 
    638   return FALSE;
    639 }
    640 
    641 /**
    642   Get and Clear mouse status.
    643 
    644   @param This                 - Pointer of simple pointer Protocol.
    645   @param State                - Output buffer holding status.
    646 
    647   @retval EFI_INVALID_PARAMETER Output buffer is invalid.
    648   @retval EFI_NOT_READY         Mouse is not changed status yet.
    649   @retval EFI_SUCCESS           Mouse status is changed and get successful.
    650 **/
    651 EFI_STATUS
    652 EFIAPI
    653 MouseAbsolutePointerGetState (
    654   IN EFI_ABSOLUTE_POINTER_PROTOCOL     *This,
    655   IN OUT EFI_ABSOLUTE_POINTER_STATE    *State
    656   )
    657 {
    658   PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
    659   EFI_TPL       OldTpl;
    660 
    661   MouseAbsolutePointerDev = PS2_MOUSE_ABSOLUTE_POINTER_DEV_FROM_THIS (This);
    662 
    663   if (State == NULL) {
    664     return EFI_INVALID_PARAMETER;
    665   }
    666 
    667   if (!MouseAbsolutePointerDev->StateChanged) {
    668     return EFI_NOT_READY;
    669   }
    670 
    671   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    672   CopyMem (State, &(MouseAbsolutePointerDev->State), sizeof (EFI_ABSOLUTE_POINTER_STATE));
    673 
    674   //
    675   // clear mouse state
    676   //
    677   MouseAbsolutePointerDev->State.CurrentX = 0;
    678   MouseAbsolutePointerDev->State.CurrentY = 0;
    679   MouseAbsolutePointerDev->State.CurrentZ = 0;
    680   MouseAbsolutePointerDev->State.ActiveButtons = 0x0;
    681   MouseAbsolutePointerDev->StateChanged            = FALSE;
    682   gBS->RestoreTPL (OldTpl);
    683 
    684   return EFI_SUCCESS;
    685 }
    686 
    687 /**
    688 
    689   Event notification function for SIMPLE_POINTER.WaitForInput event.
    690   Signal the event if there is input from mouse.
    691 
    692   @param Event    event object
    693   @param Context  event context
    694 
    695 **/
    696 VOID
    697 EFIAPI
    698 MouseAbsolutePointerWaitForInput (
    699   IN  EFI_EVENT               Event,
    700   IN  VOID                    *Context
    701   )
    702 {
    703   PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
    704 
    705   MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
    706 
    707   //
    708   // Someone is waiting on the mouse event, if there's
    709   // input from mouse, signal the event
    710   //
    711   if (MouseAbsolutePointerDev->StateChanged) {
    712     gBS->SignalEvent (Event);
    713   }
    714 
    715 }
    716 
    717 /**
    718   Event notification function for TimerEvent event.
    719   If mouse device is connected to system, try to get the mouse packet data.
    720 
    721   @param Event      -  TimerEvent in PS2_MOUSE_DEV
    722   @param Context    -  Pointer to PS2_MOUSE_DEV structure
    723 
    724 **/
    725 VOID
    726 EFIAPI
    727 PollMouseAbsolutePointer(
    728   IN EFI_EVENT  Event,
    729   IN VOID       *Context
    730   )
    731 
    732 {
    733   PS2_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
    734 
    735   MouseAbsolutePointerDev = (PS2_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
    736 
    737   //
    738   // Polling mouse packet data
    739   //
    740   PS2MouseGetPacket (MouseAbsolutePointerDev);
    741 }
    742 
    743 /**
    744   The user Entry Point for module Ps2MouseAbsolutePointer. The user code starts with this function.
    745 
    746   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    747   @param[in] SystemTable    A pointer to the EFI System Table.
    748 
    749   @retval EFI_SUCCESS       The entry point is executed successfully.
    750   @retval other             Some error occurs when executing this entry point.
    751 
    752 **/
    753 EFI_STATUS
    754 EFIAPI
    755 InitializePs2MouseAbsolutePointer(
    756   IN EFI_HANDLE           ImageHandle,
    757   IN EFI_SYSTEM_TABLE     *SystemTable
    758   )
    759 {
    760   EFI_STATUS              Status;
    761 
    762   //
    763   // Install driver model protocol(s).
    764   //
    765   Status = EfiLibInstallDriverBindingComponentName2 (
    766              ImageHandle,
    767              SystemTable,
    768              &gPS2MouseAbsolutePointerDriver,
    769              ImageHandle,
    770              &gPs2MouseAbsolutePointerComponentName,
    771              &gPs2MouseAbsolutePointerComponentName2
    772              );
    773   ASSERT_EFI_ERROR (Status);
    774 
    775 
    776   return Status;
    777 }
    778 
    779