winntserialio.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 990 行 · 第 1/2 页

C
990
字号
  This->Stop (This, Handle, 0, NULL);

  return Status;
}

STATIC
EFI_STATUS
EFIAPI
WinNtSerialIoDriverBindingStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,
  IN  EFI_HANDLE                    Handle,
  IN  UINTN                         NumberOfChildren,
  IN  EFI_HANDLE                    *ChildHandleBuffer
  )
{
  EFI_STATUS                      Status;
  UINTN                           Index;
  BOOLEAN                         AllChildrenStopped;
  EFI_SERIAL_IO_PROTOCOL          *SerialIo;
  WIN_NT_SERIAL_IO_PRIVATE_DATA   *Private;
  EFI_WIN_NT_IO_PROTOCOL          *WinNtIo;

  //
  // Complete all outstanding transactions to Controller.
  // Don't allow any new transaction to Controller to be started.
  //

  if (NumberOfChildren == 0) {
    //
    // Close the bus driver
    //
    Status =  gBS->CloseProtocol (
                     Handle, 
                     &gEfiWinNtIoProtocolGuid, 
                     This->DriverBindingHandle, 
                     Handle
                     );
    Status =  gBS->CloseProtocol (
                     Handle, 
                     &gEfiDevicePathProtocolGuid, 
                     This->DriverBindingHandle, 
                     Handle
                     );
    return Status;
  }

  AllChildrenStopped = TRUE;

  for (Index = 0; Index < NumberOfChildren; Index++) {
    Status = gBS->OpenProtocol (
                    ChildHandleBuffer[Index],   
                    &gEfiSerialIoProtocolGuid,  
                    &SerialIo,
                    This->DriverBindingHandle,   
                    Handle,   
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (!EFI_ERROR (Status)) {
      Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo);

      ASSERT (Private->Handle == ChildHandleBuffer[Index]);

      Status = gBS->CloseProtocol (
                      Handle, 
                      &gEfiWinNtIoProtocolGuid, 
                      This->DriverBindingHandle, 
                      ChildHandleBuffer[Index]
                      );

      Status = gBS->UninstallMultipleProtocolInterfaces (
                      ChildHandleBuffer[Index],                
                      &gEfiSerialIoProtocolGuid,        &Private->SerialIo,
                      &gEfiDevicePathProtocolGuid,      Private->DevicePath,
                      NULL
                      );  

      if (EFI_ERROR (Status)) {
        gBS->OpenProtocol (
               Handle,   
               &gEfiWinNtIoProtocolGuid,  
               (VOID **)&WinNtIo,
               This->DriverBindingHandle,   
               ChildHandleBuffer[Index],
               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
               );
      } else {
        Private->WinNtThunk->CloseHandle (Private->NtHandle);

        gBS->FreePool (Private->DevicePath);

        EfiLibFreeUnicodeStringTable (Private->ControllerNameTable);
        
        gBS->FreePool (Private);
      }
    }

    if (EFI_ERROR(Status)) {
      AllChildrenStopped = FALSE;
    }
  }

  if (!AllChildrenStopped) {
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}

//
// Serial IO Protocol member functions
//

STATIC
EFI_STATUS 
EFIAPI
WinNtSerialIoReset (
  IN EFI_SERIAL_IO_PROTOCOL *This
  )
{
  WIN_NT_SERIAL_IO_PRIVATE_DATA  *Private;

  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);

  Private->WinNtThunk->PurgeComm (
                         Private->NtHandle, 
                         PURGE_TXCLEAR | PURGE_RXCLEAR
                         );

  return This->SetAttributes (
                 This,
                 This->Mode->BaudRate,
                 This->Mode->ReceiveFifoDepth,
                 This->Mode->Timeout,
                 This->Mode->Parity,
                 (UINT8)This->Mode->DataBits,
                 This->Mode->StopBits 
                 );
}

STATIC
EFI_STATUS 
EFIAPI
WinNtSerialIoSetAttributes (
  IN EFI_SERIAL_IO_PROTOCOL *This,
  IN UINT64                 BaudRate,
  IN UINT32                 ReceiveFifoDepth,
  IN UINT32                 Timeout,
  IN EFI_PARITY_TYPE        Parity,
  IN UINT8                  DataBits,
  IN EFI_STOP_BITS_TYPE     StopBits
  )
{
  EFI_STATUS                     Status;
  WIN_NT_SERIAL_IO_PRIVATE_DATA  *Private;
  COMMTIMEOUTS                   PortTimeOuts;
  DWORD                          ConvertedTime;
  BOOL                           Result;
  EFI_DEVICE_PATH_PROTOCOL       *NewDevicePath;

  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);

  //
  //  Some of our arguments have defaults if a null value is passed in, and
  //   we must set the default values if a null argument is passed in.
  //
  if (BaudRate == 0) {
    BaudRate = SERIAL_BAUD_DEFAULT;
  }
  if (ReceiveFifoDepth == 0) {
    ReceiveFifoDepth = SERIAL_FIFO_DEFAULT;
  }
  if (Timeout == 0) {
    Timeout = SERIAL_TIMEOUT_DEFAULT;
  }
  if (Parity == DefaultParity) {
    Parity = NoParity; 
  }
  if (DataBits == 0) {
    DataBits = SERIAL_DATABITS_DEFAULT;
  }
  if (StopBits == DefaultStopBits) {
    StopBits = OneStopBit;
  }

  //
  // See if the new attributes already match the current attributes
  //
  if (Private->UartDevicePath.BaudRate       == BaudRate         &&
      Private->UartDevicePath.DataBits       == DataBits         &&
      Private->UartDevicePath.Parity         == Parity           &&
      Private->UartDevicePath.StopBits       == StopBits         &&
      Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth &&
      Private->SerialIoMode.Timeout          == Timeout             ) {
    return EFI_SUCCESS;
  }

  //
  //  Get current values from NT
  //
  EfiZeroMem (&Private->NtDCB, sizeof(DCB));
  Private->NtDCB.DCBlength = sizeof(DCB);

  if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) {
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError));
    return EFI_DEVICE_ERROR;
  }

  //
  // Map EFI com setting to NT
  //
  Private->NtDCB.BaudRate        = ConvertBaud2Nt (BaudRate);
  Private->NtDCB.ByteSize        = ConvertData2Nt (DataBits);
  Private->NtDCB.Parity          = ConvertParity2Nt (Parity);
  Private->NtDCB.StopBits        = ConvertStop2Nt (StopBits);

  Private->NtDCB.fBinary         = TRUE;
  Private->NtDCB.fParity         = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE;
  Private->NtDCB.fOutxCtsFlow    = FALSE;
  Private->NtDCB.fOutxDsrFlow    = FALSE;
  Private->NtDCB.fDtrControl     = DTR_CONTROL_ENABLE;
  Private->NtDCB.fDsrSensitivity = FALSE;
  Private->NtDCB.fOutX           = FALSE;
  Private->NtDCB.fInX            = FALSE;
  Private->NtDCB.fRtsControl     = RTS_CONTROL_ENABLE;
  Private->NtDCB.fNull           = FALSE;

  //
  //  Set new values
  //
  Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB);
  if (!Result) {
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError ));
    return EFI_DEVICE_ERROR;
  }

  //
  //  Set com port read/write timeout values
  //
  ConvertedTime = ConvertTime2Nt (Timeout);
  PortTimeOuts.ReadIntervalTimeout         = MAXDWORD;
  PortTimeOuts.ReadTotalTimeoutMultiplier  = 0;
  PortTimeOuts.ReadTotalTimeoutConstant    = ConvertedTime;
  PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime;
  PortTimeOuts.WriteTotalTimeoutConstant   = 0;

  if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) {
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError ));
    return EFI_DEVICE_ERROR;
  }

  //
  //  Update mode
  //
  Private->SerialIoMode.BaudRate         = BaudRate;
  Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth;
  Private->SerialIoMode.Timeout          = Timeout;
  Private->SerialIoMode.Parity           = Parity;
  Private->SerialIoMode.DataBits         = DataBits;
  Private->SerialIoMode.StopBits         = StopBits;

  //
  // See if Device Path Node has actually changed
  //
  if (Private->UartDevicePath.BaudRate     == BaudRate &&
      Private->UartDevicePath.DataBits     == DataBits &&
      Private->UartDevicePath.Parity       == Parity   &&
      Private->UartDevicePath.StopBits     == StopBits    ) {
    return EFI_SUCCESS;
  }

  //
  // Update the device path
  //
  Private->UartDevicePath.BaudRate = BaudRate;
  Private->UartDevicePath.DataBits = DataBits;
  Private->UartDevicePath.Parity   = (UINT8)Parity;
  Private->UartDevicePath.StopBits = (UINT8)StopBits;

  NewDevicePath = EfiAppendDevicePathNode (
                    Private->ParentDevicePath,
                    (EFI_DEVICE_PATH_PROTOCOL *)&Private->UartDevicePath
                    );
  if (NewDevicePath == NULL) {
    return EFI_DEVICE_ERROR;
  }

  if (Private->Handle != NULL) {
    Status = gBS->ReinstallProtocolInterface (
                    Private->Handle,                 
                    &gEfiDevicePathProtocolGuid, 
                    Private->DevicePath, 
                    NewDevicePath
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  if (Private->DevicePath) {
    gBS->FreePool (Private->DevicePath);
  }
  Private->DevicePath = NewDevicePath;

  return EFI_SUCCESS;
}


STATIC
EFI_STATUS 
EFIAPI
WinNtSerialIoSetControl (
  IN EFI_SERIAL_IO_PROTOCOL *This,
  IN UINT32                 Control
  )
{
  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
  BOOL                          Result;

  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);

  Result = Private->WinNtThunk->EscapeCommFunction (
                                  Private->NtHandle,
                                  (Control & EFI_SERIAL_REQUEST_TO_SEND) ? SETRTS : CLRRTS
                                  );
  if (!Result) {    
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialSetControl: EscapeCommFunct - RTS %d\n", Private->NtError));
    return EFI_DEVICE_ERROR;
  }

  Result = Private->WinNtThunk->EscapeCommFunction (
                                  Private->NtHandle,
                                  (Control & EFI_SERIAL_DATA_TERMINAL_READY) ? SETDTR : CLRDTR
                                  );
  if (!Result) {
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialSetControl: EscpeCommFunct - DTR %d\n", Private->NtError ));
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
}


STATIC
EFI_STATUS 
EFIAPI
WinNtSerialIoGetControl (
  IN  EFI_SERIAL_IO_PROTOCOL  *This,
  OUT UINT32                  *Control
  )
{
  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
  DWORD                         ModemStatus;
  DWORD                         Errors;
  UINT32                        Bits;

  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);

  //
  //  Get modem status
  //
  if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) {
      Private->NtError = Private->WinNtThunk->GetLastError();
      DEBUG((EFI_D_ERROR, "SerialGetControl: GetCommModemStatus %d\n", Private->NtError ));
      return EFI_DEVICE_ERROR;
  }

  Bits = 0;
  if (ModemStatus & MS_CTS_ON) {
    Bits |= EFI_SERIAL_CLEAR_TO_SEND;
  }
  if (ModemStatus & MS_DSR_ON) {
    Bits |= EFI_SERIAL_DATA_SET_READY;
  }
  if (ModemStatus & MS_RING_ON) {
    Bits |= EFI_SERIAL_RING_INDICATE;
  }
  if (ModemStatus & MS_RLSD_ON) {
    Bits |= EFI_SERIAL_CARRIER_DETECT;
  }

  //
  //  Get input buffer status
  //
  if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) {
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError ));
    return EFI_DEVICE_ERROR;
  }

  if (Private->NtComStatus.cbInQue == 0) {
    Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
  }

  *Control = Bits;

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS 
EFIAPI
WinNtSerialIoWrite (
  IN EFI_SERIAL_IO_PROTOCOL   *This,
  IN OUT UINTN                *BufferSize,
  IN VOID                     *Buffer
  )
{
  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
  UINT8                         *ByteBuffer;
  UINTN                         TotalBytesWritten;
  DWORD                         BytesToGo;
  DWORD                         BytesWritten;
  BOOL                          Result;
        
  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);

  ByteBuffer = (UINT8 *)Buffer;
  BytesToGo = (DWORD)(*BufferSize);
  TotalBytesWritten = 0;
  do {
    //
    //  Do the write
    //
    Result = Private->WinNtThunk->WriteFile (
                                    Private->NtHandle, 
                                    &ByteBuffer[TotalBytesWritten], 
                                    BytesToGo, 
                                    &BytesWritten, 
                                    NULL
                                    );
    TotalBytesWritten += BytesWritten;
    BytesToGo -= BytesWritten;
    if (!Result) {
      Private->NtError = Private->WinNtThunk->GetLastError();
      DEBUG((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError ));
      *BufferSize = TotalBytesWritten;
      return EFI_DEVICE_ERROR;
    }
  } while (BytesToGo > 0);

  *BufferSize = TotalBytesWritten;
  return EFI_SUCCESS;
}


STATIC
EFI_STATUS 
EFIAPI
WinNtSerialIoRead (
  IN  EFI_SERIAL_IO_PROTOCOL  *This,
  IN  OUT UINTN               *BufferSize,
  OUT VOID                    *Buffer
  )
{
  WIN_NT_SERIAL_IO_PRIVATE_DATA *Private;
  BOOL                          Result;
  DWORD                         BytesRead;
  EFI_STATUS                    Status;

  Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This);

  //
  //  Do the read
  //
  Result = Private->WinNtThunk->ReadFile (
                                  Private->NtHandle, 
                                  Buffer, 
                                  (DWORD)*BufferSize, 
                                  &BytesRead, 
                                  NULL
                                  );
  if (!Result) {
    Private->NtError = Private->WinNtThunk->GetLastError();
    DEBUG((EFI_D_ERROR, "SerialRead: FileRead %d\n", Private->NtError ));
    return EFI_DEVICE_ERROR;
  }
    
  if (BytesRead != *BufferSize) {
    Status = EFI_TIMEOUT;
  } else {
    Status = EFI_SUCCESS;
  }

  *BufferSize = (UINTN)BytesRead;
  return Status;
}



⌨️ 快捷键说明

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