ps2kbdctrller.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,781 行 · 第 1/3 页

C
1,781
字号
  if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
    //
    // Leave critical section and return
    //
    gBS->RestoreTPL (OldTpl);
    return ;
  }
  //
  // If there is something error, issue a 'resend' command to keyboard
  //
  if (KeyReadStatusRegister (Context) & 0xc0) {
    //
    // wait for input buffer empty
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
      if (!(KeyReadStatusRegister (Context) & 0x02)) {
        break;
      }

      gBS->Stall (30);
    }
    //
    // issue the 'resend' command
    //
    KeyWriteDataRegister (Context, 0xfe);
  }

  Data = 0;

  //
  // if there is no key present, just return
  //
  if ((KeyReadStatusRegister (Context) & 0x21) != 0x1) {
    //
    // Leave critical section and return
    //
    gBS->RestoreTPL (OldTpl);

    return ;
  }
  //
  // Read one byte of the scan code and store it into the memory buffer
  //
  if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {

    Data = KeyReadDataRegister (Context);
    //
    // put the scancode into the memory scancode buffer
    //
    ConsoleIn->ScancodeBufCount++;
    ConsoleIn->ScancodeBufEndPos++;
    if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
      ConsoleIn->ScancodeBufEndPos = 0;
    }

    ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;

    //
    // Handle Alt+Ctrl+Del Key combination
    //
    switch (Data) {
    case SCANCODE_CTRL_MAKE:
      ConsoleIn->Ctrled = TRUE;
      break;

    case SCANCODE_CTRL_BREAK:
      ConsoleIn->Ctrled = FALSE;
      break;

    case SCANCODE_ALT_MAKE:
      ConsoleIn->Alted = TRUE;
      break;

    case SCANCODE_ALT_BREAK:
      ConsoleIn->Alted = FALSE;
      break;
    }
    //
    // if Alt+Ctrl+Del, Reboot the System
    //
    if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {
      gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
    }
  }
  //
  // Leave critical section and return
  //
  gBS->RestoreTPL (OldTpl);

  return ;
}

STATIC
EFI_STATUS
GetScancodeBufHead (
  KEYBOARD_CONSOLE_IN_DEV    *ConsoleIn,
  IN UINT32                  Count,
  OUT UINT8                  *Buf
  )
/*++

Routine Description:

  Read several bytes from the scancode buffer without removing them.
  This function is called to see if there are enough bytes of scancode
  representing a single key.

Arguments:

  Count - Number of bytes to be read
  Buf - Store the results
  
Returns:

  EFI_STATUS
  
--*/
// GC_TODO:    ConsoleIn - add argument and description to function comment
// GC_TODO:    EFI_NOT_READY - add return value to function comment
// GC_TODO:    EFI_SUCCESS - add return value to function comment
{
  UINT32  Index;
  UINT32  Pos;

  Index = 0;
  Pos   = 0;

  //
  // check the valid range of parameter 'Count'
  //
  if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {
    return EFI_NOT_READY;
  }
  //
  // retrieve the values
  //
  for (Index = 0; Index < Count; Index++) {

    if (Index == 0) {

      Pos = ConsoleIn->ScancodeBufStartPos;
    } else {

      Pos = Pos + 1;
      if (Pos >= KEYBOARD_BUFFER_MAX_COUNT) {
        Pos = 0;
      }
    }

    Buf[Index] = ConsoleIn->ScancodeBuf[Pos];
  }

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS
PopScancodeBufHead (
  KEYBOARD_CONSOLE_IN_DEV   *ConsoleIn,
  IN UINT32                 Count,
  OUT UINT8                 *Buf
  )
/*++

Routine Description:

  Read & remove several bytes from the scancode buffer.
  This function is usually called after GetScancodeBufHead()

Arguments:

  Count - Number of bytes to be read
  Buf - Store the results
  
Returns:

  EFI_STATUS
  
--*/
// GC_TODO:    ConsoleIn - add argument and description to function comment
// GC_TODO:    EFI_NOT_READY - add return value to function comment
// GC_TODO:    EFI_SUCCESS - add return value to function comment
{
  UINT32  Index;

  Index = 0;

  //
  // Check the valid range of parameter 'Count'
  //
  if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {
    return EFI_NOT_READY;
  }
  //
  // Retrieve and remove the values
  //
  for (Index = 0; Index < Count; Index++) {

    if (Index != 0) {

      ConsoleIn->ScancodeBufStartPos++;
      if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {
        ConsoleIn->ScancodeBufStartPos = 0;
      }
    }

    Buf[Index] = ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufStartPos];
    ConsoleIn->ScancodeBufCount--;
  }

  ConsoleIn->ScancodeBufStartPos++;
  if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {
    ConsoleIn->ScancodeBufStartPos = 0;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
KeyboardRead (
  IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
  OUT UINT8                   *Data
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  ConsoleIn - GC_TODO: add argument description
  Data      - GC_TODO: add argument description

Returns:

  EFI_TIMEOUT - GC_TODO: Add description for return value
  EFI_SUCCESS - GC_TODO: Add description for return value

--*/
{
  UINT32  TimeOut;
  UINT32  RegFilled;

  TimeOut   = 0;
  RegFilled = 0;

  //
  // wait till output buffer full then perform the read
  //
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
      RegFilled = 1;
      *Data     = KeyReadDataRegister (ConsoleIn);
      break;
    }

    gBS->Stall (30);
  }

  if (!RegFilled) {
    return EFI_TIMEOUT;
  }

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS
KeyboardWrite (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
  IN UINT8                   Data
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  ConsoleIn - GC_TODO: add argument description
  Data      - GC_TODO: add argument description

Returns:

  EFI_TIMEOUT - GC_TODO: Add description for return value
  EFI_SUCCESS - GC_TODO: Add description for return value

--*/
{
  UINT32  TimeOut;
  UINT32  RegEmptied;

  TimeOut     = 0;
  RegEmptied  = 0;

  //
  // wait for input buffer empty
  //
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
      RegEmptied = 1;
      break;
    }

    gBS->Stall (30);
  }

  if (!RegEmptied) {
    return EFI_TIMEOUT;
  }
  //
  // Write it
  //
  KeyWriteDataRegister (ConsoleIn, Data);

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS
KeyboardCommand (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
  IN UINT8                   Data
  )
/*++

Routine Description:

  GC_TODO: Add function description

Arguments:

  ConsoleIn - GC_TODO: add argument description
  Data      - GC_TODO: add argument description

Returns:

  EFI_TIMEOUT - GC_TODO: Add description for return value
  EFI_TIMEOUT - GC_TODO: Add description for return value
  EFI_SUCCESS - GC_TODO: Add description for return value

--*/
{
  UINT32  TimeOut;
  UINT32  RegEmptied;

  TimeOut     = 0;
  RegEmptied  = 0;

  //
  // Wait For Input Buffer Empty
  //
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
      RegEmptied = 1;
      break;
    }

    gBS->Stall (30);
  }

  if (!RegEmptied) {
    return EFI_TIMEOUT;
  }
  //
  // issue the command
  //
  KeyWriteCommandRegister (ConsoleIn, Data);

  //
  // Wait For Input Buffer Empty again
  //
  RegEmptied = 0;
  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
      RegEmptied = 1;
      break;
    }

    gBS->Stall (30);
  }

  if (!RegEmptied) {
    return EFI_TIMEOUT;
  }

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS
KeyboardWaitForValue (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
  IN UINT8                   Value
  )
/*++

Routine Description:

  wait for a specific value to be presented on
  8042 Data register by keyboard and then read it,
  used in keyboard commands ack

Arguments:

  ConsoleIn - The KEYBOARD_CONSOLE_IN_DEV instance pointer
  Value - The value to be waited for
  
Returns:

  EFI_STATUS
  
--*/
// GC_TODO:    EFI_SUCCESS - add return value to function comment
// GC_TODO:    EFI_TIMEOUT - add return value to function comment
{
  UINT8   Data;
  UINT32  TimeOut;
  UINT32  SumTimeOut;
  UINT32  GotIt;

  GotIt       = 0;
  TimeOut     = 0;
  SumTimeOut  = 0;

  //
  // Make sure the initial value of 'Data' is different from 'Value'
  //
  Data = 0;
  if (Data == Value) {
    Data = 1;
  }
  //
  // Read from 8042 (multiple times if needed)
  // until the expected value appears
  // use SumTimeOut to control the iteration
  //
  while (1) {
    //
    // Perform a read
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
      if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
        Data = KeyReadDataRegister (ConsoleIn);
        break;
      }

      gBS->Stall (30);
    }

    SumTimeOut += TimeOut;

    if (Data == Value) {
      GotIt = 1;
      break;
    }

    if (SumTimeOut >= mWaitForValueTimeOut) {
      break;
    }
  }
  //
  // Check results
  //
  if (GotIt) {
    return EFI_SUCCESS;
  } else {
    return EFI_TIMEOUT;
  }

}

STATIC
EFI_STATUS
UpdateStatusLights (
  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
  )
/*++

Routine Description:

  Show keyboard status lights according to
  indicators in ConsoleIn.

Arguments:

Returns:

--*/
// GC_TODO:    ConsoleIn - add argument and description to function comment
{
  EFI_STATUS  Status;
  UINT8       Command;

  //
  // Send keyboard command
  //
  Status = KeyboardWrite (ConsoleIn, 0xed);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  KeyboardWaitForValue (ConsoleIn, 0xfa);

  //
  // Light configuration
  //
  Command = 0;
  if (ConsoleIn->CapsLock) {
    Command |= 4;
  }

  if (ConsoleIn->NumLock) {
    Command |= 2;
  }

  if (ConsoleIn->ScrollLock) {
    Command |= 1;
  }

  Status = KeyboardWrite (ConsoleIn, Command);

  if (EFI_ERROR (Status)) {
    return Status;
  }

  KeyboardWaitForValue (ConsoleIn, 0xfa);
  return Status;
}

EFI_STATUS
KeyGetchar (
  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
  )
/*++

Routine Description:

  Get scancode from scancode buffer
  and translate into EFI-scancode and unicode defined by EFI spec
  The function is always called in EFI_TPL_NOTIFY

Arguments:

  ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer

Returns:

  EFI_NOT_READY - Input from console not ready yet.
  EFI_SUCCESS   - Function executed successfully. 

--*/
{
  EFI_STATUS  Status;
  UINT8       ScanCode;
  UINT8       Readed;
  BOOLEAN     Extended;
  UINT8       ScancodeArr[4];
  //
  // 4 bytes most
  //
  UINT32      ScancodeArrPos;
  //
  // point to the current position in ScancodeArr
  //
  UINT32      TimeOut;

  Readed          = 0;
  Extended        = FALSE;
  ScancodeArrPos  = 0;

  //
  // Read one byte of the scan code and store it into the memory buffer
  // This block of code is added to insert an action that is equivalent to
  // the timer event handling function, so as to increase the frequency of
  // detecting the availability of keys. Timer event has a max frequency of
  // 18Hz which is insufficient
  //
  //
  // If there is something error, issue a 'resend' command to keyboard
  //
  if (KeyReadStatusRegister (ConsoleIn) & 0xc0) {
    //
    // wait for input buffer empty
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
      if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
        break;
      }

      gBS->Stall (30);
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?