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 + -
显示快捷键?