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
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.
18 Our DriverBinding member functions operate on the handles
19 created by the NT Bus driver.
21 Handle(1) - WinNtIo - DevicePath(1)
23 If a serial port is added to the system this driver creates a new handle.
24 The new handle is required, since the serial device must add an UART device
27 Handle(2) - SerialIo - DevicePath(1)\UART
29 The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1).
30 The instance data for this protocol is the private data used to create
33 Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort
35 If the driver is unloaded Handle(2) is removed from the system and
36 gEfiWinNtSerialPortGuid is removed from Handle(1).
38 Note: Handle(1) is any handle created by the Win NT Bus driver that is passed
39 into the DriverBinding member functions of this driver. This driver requires
40 a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and
41 the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid.
43 If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is
48 #include "WinNtSerialIo.h"
50 EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding
= {
51 WinNtSerialIoDriverBindingSupported
,
52 WinNtSerialIoDriverBindingStart
,
53 WinNtSerialIoDriverBindingStop
,
60 // List of supported baud rate
62 UINT64 mBaudRateCurrentSupport
[] = {50, 75, 110, 134, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800, 7200, 9600, 19200, 38400, 57600, 115200, SERIAL_PORT_MAX_BAUD_RATE
+ 1};
65 The user Entry Point for module WinNtSerialIo. The user code starts with this function.
67 @param[in] ImageHandle The firmware allocated handle for the EFI image.
68 @param[in] SystemTable A pointer to the EFI System Table.
70 @retval EFI_SUCCESS The entry point is executed successfully.
71 @retval other Some error occurs when executing this entry point.
76 InitializeWinNtSerialIo(
77 IN EFI_HANDLE ImageHandle
,
78 IN EFI_SYSTEM_TABLE
*SystemTable
84 // Install driver model protocol(s).
86 Status
= EfiLibInstallAllDriverProtocols (
89 &gWinNtSerialIoDriverBinding
,
91 &gWinNtSerialIoComponentName
,
95 ASSERT_EFI_ERROR (Status
);
104 WinNtSerialIoDriverBindingSupported (
105 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
106 IN EFI_HANDLE Handle
,
107 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
120 // TODO: This - add argument and description to function comment
121 // TODO: Handle - add argument and description to function comment
122 // TODO: RemainingDevicePath - add argument and description to function comment
123 // TODO: EFI_SUCCESS - add return value to function comment
124 // TODO: EFI_SUCCESS - add return value to function comment
127 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
128 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
129 UART_DEVICE_PATH
*UartNode
;
132 // Open the IO Abstraction(s) needed to perform the supported test
134 Status
= gBS
->OpenProtocol (
136 &gEfiDevicePathProtocolGuid
,
138 This
->DriverBindingHandle
,
140 EFI_OPEN_PROTOCOL_BY_DRIVER
142 if (Status
== EFI_ALREADY_STARTED
) {
146 if (EFI_ERROR (Status
)) {
152 &gEfiDevicePathProtocolGuid
,
153 This
->DriverBindingHandle
,
157 Status
= gBS
->OpenProtocol (
159 &gEfiWinNtIoProtocolGuid
,
161 This
->DriverBindingHandle
,
163 EFI_OPEN_PROTOCOL_BY_DRIVER
165 if (Status
== EFI_ALREADY_STARTED
) {
169 if (EFI_ERROR (Status
)) {
174 // Make sure that the WinNt Thunk Protocol is valid
176 if (WinNtIo
->WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
177 Status
= EFI_UNSUPPORTED
;
182 // Check the GUID to see if this is a handle type the driver supports
184 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtSerialPortGuid
)) {
185 Status
= EFI_UNSUPPORTED
;
189 if (RemainingDevicePath
!= NULL
) {
190 Status
= EFI_UNSUPPORTED
;
191 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
192 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
193 UartNode
->Header
.SubType
!= MSG_UART_DP
||
194 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
197 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
200 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
203 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
206 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
209 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
212 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
215 Status
= EFI_SUCCESS
;
220 // Close the I/O Abstraction(s) used to perform the supported test
224 &gEfiWinNtIoProtocolGuid
,
225 This
->DriverBindingHandle
,
235 WinNtSerialIoDriverBindingStart (
236 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
237 IN EFI_HANDLE Handle
,
238 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
251 // TODO: This - add argument and description to function comment
252 // TODO: Handle - add argument and description to function comment
253 // TODO: RemainingDevicePath - add argument and description to function comment
254 // TODO: EFI_SUCCESS - add return value to function comment
255 // TODO: EFI_SUCCESS - add return value to function comment
258 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
259 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
261 UART_DEVICE_PATH Node
;
262 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
263 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
266 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
269 NtHandle
= INVALID_HANDLE_VALUE
;
272 // Grab the protocols we need
274 Status
= gBS
->OpenProtocol (
276 &gEfiDevicePathProtocolGuid
,
278 This
->DriverBindingHandle
,
280 EFI_OPEN_PROTOCOL_BY_DRIVER
282 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
287 // Grab the IO abstraction we need to get any work done
289 Status
= gBS
->OpenProtocol (
291 &gEfiWinNtIoProtocolGuid
,
293 This
->DriverBindingHandle
,
295 EFI_OPEN_PROTOCOL_BY_DRIVER
297 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
300 &gEfiDevicePathProtocolGuid
,
301 This
->DriverBindingHandle
,
307 if (Status
== EFI_ALREADY_STARTED
) {
309 if (RemainingDevicePath
== NULL
) {
314 // Make sure a child handle does not already exist. This driver can only
315 // produce one child per serial port.
317 Status
= gBS
->OpenProtocolInformation (
319 &gEfiWinNtIoProtocolGuid
,
323 if (EFI_ERROR (Status
)) {
327 Status
= EFI_ALREADY_STARTED
;
328 for (Index
= 0; Index
< EntryCount
; Index
++) {
329 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
330 Status
= gBS
->OpenProtocol (
331 OpenInfoBuffer
[Index
].ControllerHandle
,
332 &gEfiSerialIoProtocolGuid
,
334 This
->DriverBindingHandle
,
336 EFI_OPEN_PROTOCOL_GET_PROTOCOL
338 if (!EFI_ERROR (Status
)) {
339 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
340 Status
= SerialIo
->SetAttributes (
343 SerialIo
->Mode
->ReceiveFifoDepth
,
344 SerialIo
->Mode
->Timeout
,
354 FreePool (OpenInfoBuffer
);
359 // Check to see if we can access the hardware device. If it's Open in NT we
360 // will not get access.
362 NtHandle
= WinNtIo
->WinNtThunk
->CreateFile (
364 GENERIC_READ
| GENERIC_WRITE
,
371 if (NtHandle
== INVALID_HANDLE_VALUE
) {
372 Status
= EFI_DEVICE_ERROR
;
377 // Construct Private data
379 Private
= AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA
));
380 if (Private
== NULL
) {
385 // This signature must be valid before any member function is called
387 Private
->Signature
= WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
388 Private
->NtHandle
= NtHandle
;
389 Private
->ControllerHandle
= Handle
;
390 Private
->Handle
= NULL
;
391 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
392 Private
->ParentDevicePath
= ParentDevicePath
;
393 Private
->ControllerNameTable
= NULL
;
395 Private
->SoftwareLoopbackEnable
= FALSE
;
396 Private
->HardwareLoopbackEnable
= FALSE
;
397 Private
->HardwareFlowControl
= FALSE
;
398 Private
->Fifo
.First
= 0;
399 Private
->Fifo
.Last
= 0;
400 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
404 gWinNtSerialIoComponentName
.SupportedLanguages
,
405 &Private
->ControllerNameTable
,
409 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
410 Private
->SerialIo
.Reset
= WinNtSerialIoReset
;
411 Private
->SerialIo
.SetAttributes
= WinNtSerialIoSetAttributes
;
412 Private
->SerialIo
.SetControl
= WinNtSerialIoSetControl
;
413 Private
->SerialIo
.GetControl
= WinNtSerialIoGetControl
;
414 Private
->SerialIo
.Write
= WinNtSerialIoWrite
;
415 Private
->SerialIo
.Read
= WinNtSerialIoRead
;
416 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
418 if (RemainingDevicePath
!= NULL
) {
420 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
421 // already checked to make sure the RemainingDevicePath contains settings
422 // that we can support.
424 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
427 // Build the device path by appending the UART node to the ParentDevicePath
428 // from the WinNtIo handle. The Uart setings are zero here, since
429 // SetAttribute() will update them to match the default setings.
431 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
432 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
433 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
434 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
438 // Build the device path by appending the UART node to the ParentDevicePath
439 // from the WinNtIo handle. The Uart setings are zero here, since
440 // SetAttribute() will update them to match the current setings.
442 Private
->DevicePath
= AppendDevicePathNode (
444 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
446 if (Private
->DevicePath
== NULL
) {
447 Status
= EFI_OUT_OF_RESOURCES
;
452 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
454 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
455 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
456 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
457 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
458 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
459 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
460 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
463 // Issue a reset to initialize the COM port
465 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
466 if (EFI_ERROR (Status
)) {
471 // Create new child handle
473 Status
= gBS
->InstallMultipleProtocolInterfaces (
475 &gEfiSerialIoProtocolGuid
,
477 &gEfiDevicePathProtocolGuid
,
481 if (EFI_ERROR (Status
)) {
486 // Open For Child Device
488 Status
= gBS
->OpenProtocol (
490 &gEfiWinNtIoProtocolGuid
,
492 This
->DriverBindingHandle
,
494 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
496 if (EFI_ERROR (Status
)) {
504 // Use the Stop() function to free all resources allocated in Start()
506 if (Private
!= NULL
) {
507 if (Private
->Handle
!= NULL
) {
508 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
510 if (NtHandle
!= INVALID_HANDLE_VALUE
) {
511 Private
->WinNtThunk
->CloseHandle (NtHandle
);
514 if (Private
->DevicePath
!= NULL
) {
515 FreePool (Private
->DevicePath
);
518 FreeUnicodeStringTable (Private
->ControllerNameTable
);
524 This
->Stop (This
, Handle
, 0, NULL
);
532 WinNtSerialIoDriverBindingStop (
533 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
534 IN EFI_HANDLE Handle
,
535 IN UINTN NumberOfChildren
,
536 IN EFI_HANDLE
*ChildHandleBuffer
542 TODO: Add function description
546 This - TODO: add argument description
547 Handle - TODO: add argument description
548 NumberOfChildren - TODO: add argument description
549 ChildHandleBuffer - TODO: add argument description
553 EFI_DEVICE_ERROR - TODO: Add description for return value
554 EFI_SUCCESS - TODO: Add description for return value
560 BOOLEAN AllChildrenStopped
;
561 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
562 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
563 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
566 // Complete all outstanding transactions to Controller.
567 // Don't allow any new transaction to Controller to be started.
570 if (NumberOfChildren
== 0) {
572 // Close the bus driver
574 Status
= gBS
->CloseProtocol (
576 &gEfiWinNtIoProtocolGuid
,
577 This
->DriverBindingHandle
,
580 Status
= gBS
->CloseProtocol (
582 &gEfiDevicePathProtocolGuid
,
583 This
->DriverBindingHandle
,
589 AllChildrenStopped
= TRUE
;
591 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
592 Status
= gBS
->OpenProtocol (
593 ChildHandleBuffer
[Index
],
594 &gEfiSerialIoProtocolGuid
,
596 This
->DriverBindingHandle
,
598 EFI_OPEN_PROTOCOL_GET_PROTOCOL
600 if (!EFI_ERROR (Status
)) {
601 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
603 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
605 Status
= gBS
->CloseProtocol (
607 &gEfiWinNtIoProtocolGuid
,
608 This
->DriverBindingHandle
,
609 ChildHandleBuffer
[Index
]
612 Status
= gBS
->UninstallMultipleProtocolInterfaces (
613 ChildHandleBuffer
[Index
],
614 &gEfiSerialIoProtocolGuid
,
616 &gEfiDevicePathProtocolGuid
,
621 if (EFI_ERROR (Status
)) {
624 &gEfiWinNtIoProtocolGuid
,
626 This
->DriverBindingHandle
,
627 ChildHandleBuffer
[Index
],
628 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
631 Private
->WinNtThunk
->CloseHandle (Private
->NtHandle
);
633 FreePool (Private
->DevicePath
);
635 FreeUnicodeStringTable (Private
->ControllerNameTable
);
641 if (EFI_ERROR (Status
)) {
642 AllChildrenStopped
= FALSE
;
646 if (!AllChildrenStopped
) {
647 return EFI_DEVICE_ERROR
;
654 // Serial IO Protocol member functions
661 IN EFI_SERIAL_IO_PROTOCOL
*This
667 TODO: Add function description
671 This - TODO: add argument description
675 TODO: add return values
679 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
682 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
684 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
686 Private
->WinNtThunk
->PurgeComm (
688 PURGE_TXCLEAR
| PURGE_RXCLEAR
691 gBS
->RestoreTPL (Tpl
);
693 return This
->SetAttributes (
695 This
->Mode
->BaudRate
,
696 This
->Mode
->ReceiveFifoDepth
,
699 (UINT8
) This
->Mode
->DataBits
,
707 WinNtSerialIoSetAttributes (
708 IN EFI_SERIAL_IO_PROTOCOL
*This
,
710 IN UINT32 ReceiveFifoDepth
,
712 IN EFI_PARITY_TYPE Parity
,
714 IN EFI_STOP_BITS_TYPE StopBits
720 This function is used to set the attributes.
724 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
725 BaudRate - The Baud rate of the serial device.
726 ReceiveFifoDepth - The request depth of fifo on receive side.
727 Timeout - the request timeout for a single charact.
728 Parity - The type of parity used in serial device.
729 DataBits - Number of deata bits used in serial device.
730 StopBits - Number of stop bits used in serial device.
738 // TODO: EFI_SUCCESS - add return value to function comment
739 // TODO: EFI_DEVICE_ERROR - add return value to function comment
740 // TODO: EFI_DEVICE_ERROR - add return value to function comment
741 // TODO: EFI_DEVICE_ERROR - add return value to function comment
742 // TODO: EFI_SUCCESS - add return value to function comment
743 // TODO: EFI_DEVICE_ERROR - add return value to function comment
744 // TODO: EFI_SUCCESS - add return value to function comment
748 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
749 COMMTIMEOUTS PortTimeOuts
;
752 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
755 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
758 // Some of our arguments have defaults if a null value is passed in, and
759 // we must set the default values if a null argument is passed in.
762 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
765 if (ReceiveFifoDepth
== 0) {
766 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
770 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
773 if (Parity
== DefaultParity
) {
774 Parity
= FixedPcdGet8 (PcdUartDefaultParity
);
778 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
781 if (StopBits
== DefaultStopBits
) {
782 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
786 // Make sure all parameters are valid
788 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
789 return EFI_INVALID_PARAMETER
;
793 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
796 for (Index
= 1; Index
< (sizeof (mBaudRateCurrentSupport
) / sizeof (mBaudRateCurrentSupport
[0])); Index
++) {
797 if (BaudRate
< mBaudRateCurrentSupport
[Index
]) {
798 BaudRate
= mBaudRateCurrentSupport
[Index
-1];
803 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
804 return EFI_INVALID_PARAMETER
;
807 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
808 return EFI_INVALID_PARAMETER
;
811 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
812 return EFI_INVALID_PARAMETER
;
815 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
816 return EFI_INVALID_PARAMETER
;
820 // Now we only support DataBits=7,8.
822 if ((DataBits
< 7) || (DataBits
> 8)) {
823 return EFI_INVALID_PARAMETER
;
827 // Now we only support DataBits=7,8.
828 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
830 if (StopBits
== OneFiveStopBits
) {
831 return EFI_INVALID_PARAMETER
;
835 // See if the new attributes already match the current attributes
837 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
838 Private
->UartDevicePath
.DataBits
== DataBits
&&
839 Private
->UartDevicePath
.Parity
== Parity
&&
840 Private
->UartDevicePath
.StopBits
== StopBits
&&
841 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
842 Private
->SerialIoMode
.Timeout
== Timeout
) {
846 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
849 // Get current values from NT
851 ZeroMem (&Private
->NtDCB
, sizeof (DCB
));
852 Private
->NtDCB
.DCBlength
= sizeof (DCB
);
854 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Private
->NtDCB
)) {
855 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
856 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: GetCommState %d\n", Private
->NtError
));
857 gBS
->RestoreTPL (Tpl
);
858 return EFI_DEVICE_ERROR
;
862 // Map EFI com setting to NT
864 Private
->NtDCB
.BaudRate
= ConvertBaud2Nt (BaudRate
);
865 Private
->NtDCB
.ByteSize
= ConvertData2Nt (DataBits
);
866 Private
->NtDCB
.Parity
= ConvertParity2Nt (Parity
);
867 Private
->NtDCB
.StopBits
= ConvertStop2Nt (StopBits
);
869 Private
->NtDCB
.fBinary
= TRUE
;
870 Private
->NtDCB
.fParity
= Private
->NtDCB
.Parity
== NOPARITY
? FALSE
: TRUE
;
871 Private
->NtDCB
.fOutxCtsFlow
= FALSE
;
872 Private
->NtDCB
.fOutxDsrFlow
= FALSE
;
873 Private
->NtDCB
.fDtrControl
= DTR_CONTROL_ENABLE
;
874 Private
->NtDCB
.fDsrSensitivity
= FALSE
;
875 Private
->NtDCB
.fOutX
= FALSE
;
876 Private
->NtDCB
.fInX
= FALSE
;
877 Private
->NtDCB
.fRtsControl
= RTS_CONTROL_ENABLE
;
878 Private
->NtDCB
.fNull
= FALSE
;
883 Result
= Private
->WinNtThunk
->SetCommState (Private
->NtHandle
, &Private
->NtDCB
);
885 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
886 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommState %d\n", Private
->NtError
));
887 gBS
->RestoreTPL (Tpl
);
888 return EFI_DEVICE_ERROR
;
892 // Set com port read/write timeout values
894 ConvertedTime
= ConvertTime2Nt (Timeout
);
895 PortTimeOuts
.ReadIntervalTimeout
= MAXDWORD
;
896 PortTimeOuts
.ReadTotalTimeoutMultiplier
= 0;
897 PortTimeOuts
.ReadTotalTimeoutConstant
= ConvertedTime
;
898 PortTimeOuts
.WriteTotalTimeoutMultiplier
= ConvertedTime
== 0 ? 1 : ConvertedTime
;
899 PortTimeOuts
.WriteTotalTimeoutConstant
= 0;
901 if (!Private
->WinNtThunk
->SetCommTimeouts (Private
->NtHandle
, &PortTimeOuts
)) {
902 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
903 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommTimeouts %d\n", Private
->NtError
));
904 gBS
->RestoreTPL (Tpl
);
905 return EFI_DEVICE_ERROR
;
911 Private
->SerialIoMode
.BaudRate
= BaudRate
;
912 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
913 Private
->SerialIoMode
.Timeout
= Timeout
;
914 Private
->SerialIoMode
.Parity
= Parity
;
915 Private
->SerialIoMode
.DataBits
= DataBits
;
916 Private
->SerialIoMode
.StopBits
= StopBits
;
919 // See if Device Path Node has actually changed
921 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
922 Private
->UartDevicePath
.DataBits
== DataBits
&&
923 Private
->UartDevicePath
.Parity
== Parity
&&
924 Private
->UartDevicePath
.StopBits
== StopBits
) {
925 gBS
->RestoreTPL(Tpl
);
930 // Update the device path
932 Private
->UartDevicePath
.BaudRate
= BaudRate
;
933 Private
->UartDevicePath
.DataBits
= DataBits
;
934 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
935 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
937 NewDevicePath
= AppendDevicePathNode (
938 Private
->ParentDevicePath
,
939 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
941 if (NewDevicePath
== NULL
) {
942 gBS
->RestoreTPL (Tpl
);
943 return EFI_DEVICE_ERROR
;
946 if (Private
->Handle
!= NULL
) {
947 Status
= gBS
->ReinstallProtocolInterface (
949 &gEfiDevicePathProtocolGuid
,
953 if (EFI_ERROR (Status
)) {
954 gBS
->RestoreTPL (Tpl
);
959 if (Private
->DevicePath
!= NULL
) {
960 FreePool (Private
->DevicePath
);
963 Private
->DevicePath
= NewDevicePath
;
965 gBS
->RestoreTPL (Tpl
);
973 WinNtSerialIoSetControl (
974 IN EFI_SERIAL_IO_PROTOCOL
*This
,
981 TODO: Add function description
985 This - TODO: add argument description
986 Control - TODO: add argument description
990 EFI_DEVICE_ERROR - TODO: Add description for return value
991 EFI_DEVICE_ERROR - TODO: Add description for return value
992 EFI_SUCCESS - TODO: Add description for return value
996 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1002 // first determine the parameter is invalid
1004 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1005 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1006 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1007 return EFI_UNSUPPORTED
;
1010 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1012 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1014 Result
= Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
);
1017 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1018 DEBUG ((EFI_D_ERROR
, "SerialSetControl: GetCommState %d\n", Private
->NtError
));
1019 gBS
->RestoreTPL (Tpl
);
1020 return EFI_DEVICE_ERROR
;
1023 Dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1024 Dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1025 Private
->HardwareFlowControl
= FALSE
;
1026 Private
->SoftwareLoopbackEnable
= FALSE
;
1027 Private
->HardwareLoopbackEnable
= FALSE
;
1029 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1030 Dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1033 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1034 Dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1037 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1038 Private
->HardwareFlowControl
= TRUE
;
1041 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1042 Private
->SoftwareLoopbackEnable
= TRUE
;
1045 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1046 Private
->HardwareLoopbackEnable
= TRUE
;
1049 Result
= Private
->WinNtThunk
->SetCommState (
1055 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1056 DEBUG ((EFI_D_ERROR
, "SerialSetControl: SetCommState %d\n", Private
->NtError
));
1057 gBS
->RestoreTPL (Tpl
);
1058 return EFI_DEVICE_ERROR
;
1061 gBS
->RestoreTPL (Tpl
);
1069 WinNtSerialIoGetControl (
1070 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1075 Routine Description:
1077 TODO: Add function description
1081 This - TODO: add argument description
1082 Control - TODO: add argument description
1086 EFI_DEVICE_ERROR - TODO: Add description for return value
1087 EFI_DEVICE_ERROR - TODO: Add description for return value
1088 EFI_DEVICE_ERROR - TODO: Add description for return value
1089 EFI_SUCCESS - TODO: Add description for return value
1093 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1100 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1102 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1107 if (!Private
->WinNtThunk
->GetCommModemStatus (Private
->NtHandle
, &ModemStatus
)) {
1108 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1109 gBS
->RestoreTPL (Tpl
);
1110 return EFI_DEVICE_ERROR
;
1114 if (ModemStatus
& MS_CTS_ON
) {
1115 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1118 if (ModemStatus
& MS_DSR_ON
) {
1119 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1122 if (ModemStatus
& MS_RING_ON
) {
1123 Bits
|= EFI_SERIAL_RING_INDICATE
;
1126 if (ModemStatus
& MS_RLSD_ON
) {
1127 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1133 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
)) {
1134 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1135 DEBUG ((EFI_D_ERROR
, "SerialGetControl: GetCommState %d\n", Private
->NtError
));
1136 gBS
->RestoreTPL (Tpl
);
1137 return EFI_DEVICE_ERROR
;
1140 if (Dcb
.fDtrControl
== DTR_CONTROL_ENABLE
) {
1141 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1144 if (Dcb
.fRtsControl
== RTS_CONTROL_ENABLE
) {
1145 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1148 if (Private
->HardwareFlowControl
) {
1149 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1152 if (Private
->SoftwareLoopbackEnable
) {
1153 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1156 if (Private
->HardwareLoopbackEnable
) {
1157 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1161 // Get input buffer status
1163 if (!Private
->WinNtThunk
->ClearCommError (Private
->NtHandle
, &Errors
, &Private
->NtComStatus
)) {
1164 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1165 DEBUG ((EFI_D_ERROR
, "SerialGetControl: ClearCommError %d\n", Private
->NtError
));
1166 gBS
->RestoreTPL (Tpl
);
1167 return EFI_DEVICE_ERROR
;
1170 if (Private
->NtComStatus
.cbInQue
== 0) {
1171 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1176 gBS
->RestoreTPL (Tpl
);
1184 WinNtSerialIoWrite (
1185 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1186 IN OUT UINTN
*BufferSize
,
1191 Routine Description:
1193 TODO: Add function description
1197 This - TODO: add argument description
1198 BufferSize - TODO: add argument description
1199 Buffer - TODO: add argument description
1203 EFI_DEVICE_ERROR - TODO: Add description for return value
1204 EFI_SUCCESS - TODO: Add description for return value
1208 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1210 UINTN TotalBytesWritten
;
1218 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1220 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1222 ByteBuffer
= (UINT8
*) Buffer
;
1223 TotalBytesWritten
= 0;
1225 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1226 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1227 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1228 TotalBytesWritten
++;
1234 BytesToGo
= (DWORD
) (*BufferSize
);
1237 if (Private
->HardwareFlowControl
) {
1241 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1242 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1243 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1249 Result
= Private
->WinNtThunk
->WriteFile (
1251 &ByteBuffer
[TotalBytesWritten
],
1257 if (Private
->HardwareFlowControl
) {
1261 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1262 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1263 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1266 TotalBytesWritten
+= BytesWritten
;
1267 BytesToGo
-= BytesWritten
;
1269 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1270 DEBUG ((EFI_D_ERROR
, "SerialWrite: FileWrite %d\n", Private
->NtError
));
1271 *BufferSize
= TotalBytesWritten
;
1272 gBS
->RestoreTPL (Tpl
);
1273 return EFI_DEVICE_ERROR
;
1275 } while (BytesToGo
> 0);
1278 *BufferSize
= TotalBytesWritten
;
1280 gBS
->RestoreTPL (Tpl
);
1289 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1290 IN OUT UINTN
*BufferSize
,
1295 Routine Description:
1297 TODO: Add function description
1301 This - TODO: add argument description
1302 BufferSize - TODO: add argument description
1303 Buffer - TODO: add argument description
1307 EFI_DEVICE_ERROR - TODO: Add description for return value
1311 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1320 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1322 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1327 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1328 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1329 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1330 ((UINT8
*) Buffer
)[Index
] = Data
;
1337 if (Private
->HardwareFlowControl
) {
1338 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1339 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1340 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1343 Result
= Private
->WinNtThunk
->ReadFile (
1346 (DWORD
) *BufferSize
,
1351 if (Private
->HardwareFlowControl
) {
1352 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1353 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1354 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1358 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1359 gBS
->RestoreTPL (Tpl
);
1360 return EFI_DEVICE_ERROR
;
1364 if (BytesRead
!= *BufferSize
) {
1365 Status
= EFI_TIMEOUT
;
1367 Status
= EFI_SUCCESS
;
1370 *BufferSize
= (UINTN
) BytesRead
;
1372 gBS
->RestoreTPL (Tpl
);
1379 IN SERIAL_DEV_FIFO
*Fifo
1383 Routine Description:
1384 Detect whether specific FIFO is full or not
1387 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1390 TRUE: the FIFO is full
1391 FALSE: the FIFO is not full
1395 if (Fifo
->Surplus
== 0) {
1403 IsaSerialFifoEmpty (
1404 IN SERIAL_DEV_FIFO
*Fifo
1408 Routine Description:
1409 Detect whether specific FIFO is empty or not
1412 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1415 TRUE: the FIFO is empty
1416 FALSE: the FIFO is not empty
1420 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1429 IN SERIAL_DEV_FIFO
*Fifo
,
1434 Routine Description:
1435 Add data to specific FIFO
1438 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1439 Data UINT8: the data added to FIFO
1442 EFI_SUCCESS: Add data to specific FIFO successfully
1443 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1446 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1449 // if FIFO full can not add data
1451 if (IsaSerialFifoFull (Fifo
)) {
1452 return EFI_OUT_OF_RESOURCES
;
1456 // FIFO is not full can add data
1458 Fifo
->Data
[Fifo
->Last
] = Data
;
1461 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1469 IsaSerialFifoRemove (
1470 IN SERIAL_DEV_FIFO
*Fifo
,
1475 Routine Description:
1476 Remove data from specific FIFO
1479 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1480 Data UINT8*: the data removed from FIFO
1483 EFI_SUCCESS: Remove data from specific FIFO successfully
1484 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1487 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1490 // if FIFO is empty, no data can remove
1492 if (IsaSerialFifoEmpty (Fifo
)) {
1493 return EFI_OUT_OF_RESOURCES
;
1497 // FIFO is not empty, can remove data
1499 *Data
= Fifo
->Data
[Fifo
->First
];
1502 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {