3 Copyright (c) 2006 - 2010, 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
= EfiLibInstallDriverBindingComponentName2 (
89 &gWinNtSerialIoDriverBinding
,
91 &gWinNtSerialIoComponentName
,
92 &gWinNtSerialIoComponentName2
94 ASSERT_EFI_ERROR (Status
);
102 WinNtSerialIoDriverBindingSupported (
103 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
104 IN EFI_HANDLE Handle
,
105 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
118 // TODO: This - add argument and description to function comment
119 // TODO: Handle - add argument and description to function comment
120 // TODO: RemainingDevicePath - add argument and description to function comment
121 // TODO: EFI_SUCCESS - add return value to function comment
122 // TODO: EFI_SUCCESS - add return value to function comment
125 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
126 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
127 UART_DEVICE_PATH
*UartNode
;
130 // Check RemainingDevicePath validation
132 if (RemainingDevicePath
!= NULL
) {
134 // Check if RemainingDevicePath is the End of Device Path Node,
135 // if yes, go on checking other conditions
137 if (!IsDevicePathEnd (RemainingDevicePath
)) {
139 // If RemainingDevicePath isn't the End of Device Path Node,
140 // check its validation
142 Status
= EFI_UNSUPPORTED
;
144 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
145 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
146 UartNode
->Header
.SubType
!= MSG_UART_DP
||
147 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
150 if ( UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
153 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
156 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
159 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
162 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
165 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
172 // Open the IO Abstraction(s) needed to perform the supported test
174 Status
= gBS
->OpenProtocol (
176 &gEfiWinNtIoProtocolGuid
,
178 This
->DriverBindingHandle
,
180 EFI_OPEN_PROTOCOL_BY_DRIVER
182 if (Status
== EFI_ALREADY_STARTED
) {
186 if (EFI_ERROR (Status
)) {
191 // Close the I/O Abstraction(s) used to perform the supported test
195 &gEfiWinNtIoProtocolGuid
,
196 This
->DriverBindingHandle
,
201 // Open the EFI Device Path protocol needed to perform the supported test
203 Status
= gBS
->OpenProtocol (
205 &gEfiDevicePathProtocolGuid
,
206 (VOID
**) &ParentDevicePath
,
207 This
->DriverBindingHandle
,
209 EFI_OPEN_PROTOCOL_BY_DRIVER
211 if (Status
== EFI_ALREADY_STARTED
) {
215 if (EFI_ERROR (Status
)) {
220 // Close protocol, don't use device path protocol in the Support() function
224 &gEfiDevicePathProtocolGuid
,
225 This
->DriverBindingHandle
,
230 // Make sure that the WinNt Thunk Protocol is valid
232 if (WinNtIo
->WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
233 Status
= EFI_UNSUPPORTED
;
238 // Check the GUID to see if this is a handle type the driver supports
240 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtSerialPortGuid
)) {
241 Status
= EFI_UNSUPPORTED
;
253 WinNtSerialIoDriverBindingStart (
254 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
255 IN EFI_HANDLE Handle
,
256 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
269 // TODO: This - add argument and description to function comment
270 // TODO: Handle - add argument and description to function comment
271 // TODO: RemainingDevicePath - add argument and description to function comment
272 // TODO: EFI_SUCCESS - add return value to function comment
273 // TODO: EFI_SUCCESS - add return value to function comment
276 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
277 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
279 UART_DEVICE_PATH Node
;
280 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
281 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
284 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
285 UART_DEVICE_PATH
*UartNode
;
288 NtHandle
= INVALID_HANDLE_VALUE
;
291 // Grab the protocols we need
293 Status
= gBS
->OpenProtocol (
295 &gEfiDevicePathProtocolGuid
,
296 (VOID
**) &ParentDevicePath
,
297 This
->DriverBindingHandle
,
299 EFI_OPEN_PROTOCOL_BY_DRIVER
301 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
306 // Grab the IO abstraction we need to get any work done
308 Status
= gBS
->OpenProtocol (
310 &gEfiWinNtIoProtocolGuid
,
312 This
->DriverBindingHandle
,
314 EFI_OPEN_PROTOCOL_BY_DRIVER
316 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
319 &gEfiDevicePathProtocolGuid
,
320 This
->DriverBindingHandle
,
326 if (Status
== EFI_ALREADY_STARTED
) {
328 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
330 // If RemainingDevicePath is NULL or is the End of Device Path Node
336 // Make sure a child handle does not already exist. This driver can only
337 // produce one child per serial port.
339 Status
= gBS
->OpenProtocolInformation (
341 &gEfiWinNtIoProtocolGuid
,
345 if (EFI_ERROR (Status
)) {
349 Status
= EFI_ALREADY_STARTED
;
350 for (Index
= 0; Index
< EntryCount
; Index
++) {
351 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
352 Status
= gBS
->OpenProtocol (
353 OpenInfoBuffer
[Index
].ControllerHandle
,
354 &gEfiSerialIoProtocolGuid
,
356 This
->DriverBindingHandle
,
358 EFI_OPEN_PROTOCOL_GET_PROTOCOL
360 if (!EFI_ERROR (Status
)) {
361 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
362 Status
= SerialIo
->SetAttributes (
365 SerialIo
->Mode
->ReceiveFifoDepth
,
366 SerialIo
->Mode
->Timeout
,
367 (EFI_PARITY_TYPE
)UartNode
->Parity
,
369 (EFI_STOP_BITS_TYPE
)UartNode
->StopBits
376 FreePool (OpenInfoBuffer
);
380 if (RemainingDevicePath
== NULL
) {
382 // Build the device path by appending the UART node to the ParentDevicePath
383 // from the WinNtIo handle. The Uart setings are zero here, since
384 // SetAttribute() will update them to match the default setings.
386 ZeroMem (&Node
, sizeof (UART_DEVICE_PATH
));
387 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
388 Node
.Header
.SubType
= MSG_UART_DP
;
389 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Node
, sizeof (UART_DEVICE_PATH
));
391 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
393 // If RemainingDevicePath isn't the End of Device Path Node,
394 // only scan the specified device by RemainingDevicePath
397 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
398 // already checked to make sure the RemainingDevicePath contains settings
399 // that we can support.
401 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
405 // If RemainingDevicePath is the End of Device Path Node,
406 // skip enumerate any device and return EFI_SUCESSS
412 // Check to see if we can access the hardware device. If it's Open in NT we
413 // will not get access.
415 NtHandle
= WinNtIo
->WinNtThunk
->CreateFile (
417 GENERIC_READ
| GENERIC_WRITE
,
424 if (NtHandle
== INVALID_HANDLE_VALUE
) {
425 Status
= EFI_DEVICE_ERROR
;
430 // Construct Private data
432 Private
= AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA
));
433 if (Private
== NULL
) {
438 // This signature must be valid before any member function is called
440 Private
->Signature
= WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
441 Private
->NtHandle
= NtHandle
;
442 Private
->ControllerHandle
= Handle
;
443 Private
->Handle
= NULL
;
444 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
445 Private
->ParentDevicePath
= ParentDevicePath
;
446 Private
->ControllerNameTable
= NULL
;
448 Private
->SoftwareLoopbackEnable
= FALSE
;
449 Private
->HardwareLoopbackEnable
= FALSE
;
450 Private
->HardwareFlowControl
= FALSE
;
451 Private
->Fifo
.First
= 0;
452 Private
->Fifo
.Last
= 0;
453 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
455 CopyMem (&Private
->UartDevicePath
, &Node
, sizeof (UART_DEVICE_PATH
));
459 gWinNtSerialIoComponentName
.SupportedLanguages
,
460 &Private
->ControllerNameTable
,
466 gWinNtSerialIoComponentName2
.SupportedLanguages
,
467 &Private
->ControllerNameTable
,
473 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
474 Private
->SerialIo
.Reset
= WinNtSerialIoReset
;
475 Private
->SerialIo
.SetAttributes
= WinNtSerialIoSetAttributes
;
476 Private
->SerialIo
.SetControl
= WinNtSerialIoSetControl
;
477 Private
->SerialIo
.GetControl
= WinNtSerialIoGetControl
;
478 Private
->SerialIo
.Write
= WinNtSerialIoWrite
;
479 Private
->SerialIo
.Read
= WinNtSerialIoRead
;
480 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
483 // Build the device path by appending the UART node to the ParentDevicePath
484 // from the WinNtIo handle. The Uart setings are zero here, since
485 // SetAttribute() will update them to match the current setings.
487 Private
->DevicePath
= AppendDevicePathNode (
489 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
491 if (Private
->DevicePath
== NULL
) {
492 Status
= EFI_OUT_OF_RESOURCES
;
497 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
499 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
500 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
501 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
502 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
503 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
504 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
505 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
508 // Issue a reset to initialize the COM port
510 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
511 if (EFI_ERROR (Status
)) {
516 // Create new child handle
518 Status
= gBS
->InstallMultipleProtocolInterfaces (
520 &gEfiSerialIoProtocolGuid
,
522 &gEfiDevicePathProtocolGuid
,
526 if (EFI_ERROR (Status
)) {
531 // Open For Child Device
533 Status
= gBS
->OpenProtocol (
535 &gEfiWinNtIoProtocolGuid
,
537 This
->DriverBindingHandle
,
539 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
541 if (EFI_ERROR (Status
)) {
549 // Use the Stop() function to free all resources allocated in Start()
551 if (Private
!= NULL
) {
552 if (Private
->Handle
!= NULL
) {
553 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
555 if (NtHandle
!= INVALID_HANDLE_VALUE
) {
556 Private
->WinNtThunk
->CloseHandle (NtHandle
);
559 if (Private
->DevicePath
!= NULL
) {
560 FreePool (Private
->DevicePath
);
563 FreeUnicodeStringTable (Private
->ControllerNameTable
);
569 This
->Stop (This
, Handle
, 0, NULL
);
576 WinNtSerialIoDriverBindingStop (
577 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
578 IN EFI_HANDLE Handle
,
579 IN UINTN NumberOfChildren
,
580 IN EFI_HANDLE
*ChildHandleBuffer
586 TODO: Add function description
590 This - TODO: add argument description
591 Handle - TODO: add argument description
592 NumberOfChildren - TODO: add argument description
593 ChildHandleBuffer - TODO: add argument description
597 EFI_DEVICE_ERROR - TODO: Add description for return value
598 EFI_SUCCESS - TODO: Add description for return value
604 BOOLEAN AllChildrenStopped
;
605 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
606 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
607 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
610 // Complete all outstanding transactions to Controller.
611 // Don't allow any new transaction to Controller to be started.
614 if (NumberOfChildren
== 0) {
616 // Close the bus driver
618 Status
= gBS
->CloseProtocol (
620 &gEfiWinNtIoProtocolGuid
,
621 This
->DriverBindingHandle
,
624 Status
= gBS
->CloseProtocol (
626 &gEfiDevicePathProtocolGuid
,
627 This
->DriverBindingHandle
,
633 AllChildrenStopped
= TRUE
;
635 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
636 Status
= gBS
->OpenProtocol (
637 ChildHandleBuffer
[Index
],
638 &gEfiSerialIoProtocolGuid
,
640 This
->DriverBindingHandle
,
642 EFI_OPEN_PROTOCOL_GET_PROTOCOL
644 if (!EFI_ERROR (Status
)) {
645 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
647 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
649 Status
= gBS
->CloseProtocol (
651 &gEfiWinNtIoProtocolGuid
,
652 This
->DriverBindingHandle
,
653 ChildHandleBuffer
[Index
]
656 Status
= gBS
->UninstallMultipleProtocolInterfaces (
657 ChildHandleBuffer
[Index
],
658 &gEfiSerialIoProtocolGuid
,
660 &gEfiDevicePathProtocolGuid
,
665 if (EFI_ERROR (Status
)) {
668 &gEfiWinNtIoProtocolGuid
,
670 This
->DriverBindingHandle
,
671 ChildHandleBuffer
[Index
],
672 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
675 Private
->WinNtThunk
->CloseHandle (Private
->NtHandle
);
677 FreePool (Private
->DevicePath
);
679 FreeUnicodeStringTable (Private
->ControllerNameTable
);
685 if (EFI_ERROR (Status
)) {
686 AllChildrenStopped
= FALSE
;
690 if (!AllChildrenStopped
) {
691 return EFI_DEVICE_ERROR
;
698 // Serial IO Protocol member functions
704 IN EFI_SERIAL_IO_PROTOCOL
*This
710 TODO: Add function description
714 This - TODO: add argument description
718 TODO: add return values
722 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
725 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
727 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
729 Private
->WinNtThunk
->PurgeComm (
731 PURGE_TXCLEAR
| PURGE_RXCLEAR
734 gBS
->RestoreTPL (Tpl
);
736 return This
->SetAttributes (
738 This
->Mode
->BaudRate
,
739 This
->Mode
->ReceiveFifoDepth
,
741 (EFI_PARITY_TYPE
)This
->Mode
->Parity
,
742 (UINT8
) This
->Mode
->DataBits
,
743 (EFI_STOP_BITS_TYPE
)This
->Mode
->StopBits
749 WinNtSerialIoSetAttributes (
750 IN EFI_SERIAL_IO_PROTOCOL
*This
,
752 IN UINT32 ReceiveFifoDepth
,
754 IN EFI_PARITY_TYPE Parity
,
756 IN EFI_STOP_BITS_TYPE StopBits
762 This function is used to set the attributes.
766 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
767 BaudRate - The Baud rate of the serial device.
768 ReceiveFifoDepth - The request depth of fifo on receive side.
769 Timeout - the request timeout for a single charact.
770 Parity - The type of parity used in serial device.
771 DataBits - Number of deata bits used in serial device.
772 StopBits - Number of stop bits used in serial device.
780 // TODO: EFI_SUCCESS - add return value to function comment
781 // TODO: EFI_DEVICE_ERROR - add return value to function comment
782 // TODO: EFI_DEVICE_ERROR - add return value to function comment
783 // TODO: EFI_DEVICE_ERROR - add return value to function comment
784 // TODO: EFI_SUCCESS - add return value to function comment
785 // TODO: EFI_DEVICE_ERROR - add return value to function comment
786 // TODO: EFI_SUCCESS - add return value to function comment
790 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
791 COMMTIMEOUTS PortTimeOuts
;
794 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
797 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
800 // Some of our arguments have defaults if a null value is passed in, and
801 // we must set the default values if a null argument is passed in.
804 BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
807 if (ReceiveFifoDepth
== 0) {
808 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
812 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
815 if (Parity
== DefaultParity
) {
816 Parity
= (EFI_PARITY_TYPE
) (PcdGet8 (PcdUartDefaultParity
));
820 DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
823 if (StopBits
== DefaultStopBits
) {
824 StopBits
= (EFI_STOP_BITS_TYPE
) PcdGet8 (PcdUartDefaultStopBits
);
828 // Make sure all parameters are valid
830 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
831 return EFI_INVALID_PARAMETER
;
835 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
838 for (Index
= 1; Index
< (sizeof (mBaudRateCurrentSupport
) / sizeof (mBaudRateCurrentSupport
[0])); Index
++) {
839 if (BaudRate
< mBaudRateCurrentSupport
[Index
]) {
840 BaudRate
= mBaudRateCurrentSupport
[Index
-1];
845 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
846 return EFI_INVALID_PARAMETER
;
849 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
850 return EFI_INVALID_PARAMETER
;
853 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
854 return EFI_INVALID_PARAMETER
;
857 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
858 return EFI_INVALID_PARAMETER
;
862 // Now we only support DataBits=7,8.
864 if ((DataBits
< 7) || (DataBits
> 8)) {
865 return EFI_INVALID_PARAMETER
;
869 // Now we only support DataBits=7,8.
870 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
872 if (StopBits
== OneFiveStopBits
) {
873 return EFI_INVALID_PARAMETER
;
877 // See if the new attributes already match the current attributes
879 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
880 Private
->UartDevicePath
.DataBits
== DataBits
&&
881 Private
->UartDevicePath
.Parity
== Parity
&&
882 Private
->UartDevicePath
.StopBits
== StopBits
&&
883 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
884 Private
->SerialIoMode
.Timeout
== Timeout
) {
888 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
891 // Get current values from NT
893 ZeroMem (&Private
->NtDCB
, sizeof (DCB
));
894 Private
->NtDCB
.DCBlength
= sizeof (DCB
);
896 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Private
->NtDCB
)) {
897 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
898 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: GetCommState %d\n", Private
->NtError
));
899 gBS
->RestoreTPL (Tpl
);
900 return EFI_DEVICE_ERROR
;
904 // Map EFI com setting to NT
906 Private
->NtDCB
.BaudRate
= ConvertBaud2Nt (BaudRate
);
907 Private
->NtDCB
.ByteSize
= ConvertData2Nt (DataBits
);
908 Private
->NtDCB
.Parity
= ConvertParity2Nt (Parity
);
909 Private
->NtDCB
.StopBits
= ConvertStop2Nt (StopBits
);
911 Private
->NtDCB
.fBinary
= TRUE
;
912 Private
->NtDCB
.fParity
= Private
->NtDCB
.Parity
== NOPARITY
? FALSE
: TRUE
;
913 Private
->NtDCB
.fOutxCtsFlow
= FALSE
;
914 Private
->NtDCB
.fOutxDsrFlow
= FALSE
;
915 Private
->NtDCB
.fDtrControl
= DTR_CONTROL_ENABLE
;
916 Private
->NtDCB
.fDsrSensitivity
= FALSE
;
917 Private
->NtDCB
.fOutX
= FALSE
;
918 Private
->NtDCB
.fInX
= FALSE
;
919 Private
->NtDCB
.fRtsControl
= RTS_CONTROL_ENABLE
;
920 Private
->NtDCB
.fNull
= FALSE
;
925 Result
= Private
->WinNtThunk
->SetCommState (Private
->NtHandle
, &Private
->NtDCB
);
927 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
928 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommState %d\n", Private
->NtError
));
929 gBS
->RestoreTPL (Tpl
);
930 return EFI_DEVICE_ERROR
;
934 // Set com port read/write timeout values
936 ConvertedTime
= ConvertTime2Nt (Timeout
);
937 PortTimeOuts
.ReadIntervalTimeout
= MAXDWORD
;
938 PortTimeOuts
.ReadTotalTimeoutMultiplier
= 0;
939 PortTimeOuts
.ReadTotalTimeoutConstant
= ConvertedTime
;
940 PortTimeOuts
.WriteTotalTimeoutMultiplier
= ConvertedTime
== 0 ? 1 : ConvertedTime
;
941 PortTimeOuts
.WriteTotalTimeoutConstant
= 0;
943 if (!Private
->WinNtThunk
->SetCommTimeouts (Private
->NtHandle
, &PortTimeOuts
)) {
944 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
945 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommTimeouts %d\n", Private
->NtError
));
946 gBS
->RestoreTPL (Tpl
);
947 return EFI_DEVICE_ERROR
;
953 Private
->SerialIoMode
.BaudRate
= BaudRate
;
954 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
955 Private
->SerialIoMode
.Timeout
= Timeout
;
956 Private
->SerialIoMode
.Parity
= Parity
;
957 Private
->SerialIoMode
.DataBits
= DataBits
;
958 Private
->SerialIoMode
.StopBits
= StopBits
;
961 // See if Device Path Node has actually changed
963 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
964 Private
->UartDevicePath
.DataBits
== DataBits
&&
965 Private
->UartDevicePath
.Parity
== Parity
&&
966 Private
->UartDevicePath
.StopBits
== StopBits
) {
967 gBS
->RestoreTPL(Tpl
);
972 // Update the device path
974 Private
->UartDevicePath
.BaudRate
= BaudRate
;
975 Private
->UartDevicePath
.DataBits
= DataBits
;
976 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
977 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
979 NewDevicePath
= AppendDevicePathNode (
980 Private
->ParentDevicePath
,
981 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
983 if (NewDevicePath
== NULL
) {
984 gBS
->RestoreTPL (Tpl
);
985 return EFI_DEVICE_ERROR
;
988 if (Private
->Handle
!= NULL
) {
989 Status
= gBS
->ReinstallProtocolInterface (
991 &gEfiDevicePathProtocolGuid
,
995 if (EFI_ERROR (Status
)) {
996 gBS
->RestoreTPL (Tpl
);
1001 if (Private
->DevicePath
!= NULL
) {
1002 FreePool (Private
->DevicePath
);
1005 Private
->DevicePath
= NewDevicePath
;
1007 gBS
->RestoreTPL (Tpl
);
1014 WinNtSerialIoSetControl (
1015 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1020 Routine Description:
1022 TODO: Add function description
1026 This - TODO: add argument description
1027 Control - TODO: add argument description
1031 EFI_DEVICE_ERROR - TODO: Add description for return value
1032 EFI_DEVICE_ERROR - TODO: Add description for return value
1033 EFI_SUCCESS - TODO: Add description for return value
1037 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1043 // first determine the parameter is invalid
1045 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1046 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1047 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1048 return EFI_UNSUPPORTED
;
1051 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1053 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1055 Result
= Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
);
1058 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1059 DEBUG ((EFI_D_ERROR
, "SerialSetControl: GetCommState %d\n", Private
->NtError
));
1060 gBS
->RestoreTPL (Tpl
);
1061 return EFI_DEVICE_ERROR
;
1064 Dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1065 Dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1066 Private
->HardwareFlowControl
= FALSE
;
1067 Private
->SoftwareLoopbackEnable
= FALSE
;
1068 Private
->HardwareLoopbackEnable
= FALSE
;
1070 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1071 Dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1074 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1075 Dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1078 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1079 Private
->HardwareFlowControl
= TRUE
;
1082 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1083 Private
->SoftwareLoopbackEnable
= TRUE
;
1086 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1087 Private
->HardwareLoopbackEnable
= TRUE
;
1090 Result
= Private
->WinNtThunk
->SetCommState (
1096 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1097 DEBUG ((EFI_D_ERROR
, "SerialSetControl: SetCommState %d\n", Private
->NtError
));
1098 gBS
->RestoreTPL (Tpl
);
1099 return EFI_DEVICE_ERROR
;
1102 gBS
->RestoreTPL (Tpl
);
1109 WinNtSerialIoGetControl (
1110 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1115 Routine Description:
1117 TODO: Add function description
1121 This - TODO: add argument description
1122 Control - TODO: add argument description
1126 EFI_DEVICE_ERROR - TODO: Add description for return value
1127 EFI_DEVICE_ERROR - TODO: Add description for return value
1128 EFI_DEVICE_ERROR - TODO: Add description for return value
1129 EFI_SUCCESS - TODO: Add description for return value
1133 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1140 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1142 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1147 if (!Private
->WinNtThunk
->GetCommModemStatus (Private
->NtHandle
, &ModemStatus
)) {
1148 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1149 gBS
->RestoreTPL (Tpl
);
1150 return EFI_DEVICE_ERROR
;
1154 if (ModemStatus
& MS_CTS_ON
) {
1155 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1158 if (ModemStatus
& MS_DSR_ON
) {
1159 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1162 if (ModemStatus
& MS_RING_ON
) {
1163 Bits
|= EFI_SERIAL_RING_INDICATE
;
1166 if (ModemStatus
& MS_RLSD_ON
) {
1167 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1173 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
)) {
1174 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1175 DEBUG ((EFI_D_ERROR
, "SerialGetControl: GetCommState %d\n", Private
->NtError
));
1176 gBS
->RestoreTPL (Tpl
);
1177 return EFI_DEVICE_ERROR
;
1180 if (Dcb
.fDtrControl
== DTR_CONTROL_ENABLE
) {
1181 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1184 if (Dcb
.fRtsControl
== RTS_CONTROL_ENABLE
) {
1185 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1188 if (Private
->HardwareFlowControl
) {
1189 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1192 if (Private
->SoftwareLoopbackEnable
) {
1193 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1196 if (Private
->HardwareLoopbackEnable
) {
1197 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1201 // Get input buffer status
1203 if (!Private
->WinNtThunk
->ClearCommError (Private
->NtHandle
, &Errors
, &Private
->NtComStatus
)) {
1204 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1205 DEBUG ((EFI_D_ERROR
, "SerialGetControl: ClearCommError %d\n", Private
->NtError
));
1206 gBS
->RestoreTPL (Tpl
);
1207 return EFI_DEVICE_ERROR
;
1210 if (Private
->NtComStatus
.cbInQue
== 0) {
1211 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1216 gBS
->RestoreTPL (Tpl
);
1223 WinNtSerialIoWrite (
1224 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1225 IN OUT UINTN
*BufferSize
,
1230 Routine Description:
1232 TODO: Add function description
1236 This - TODO: add argument description
1237 BufferSize - TODO: add argument description
1238 Buffer - TODO: add argument description
1242 EFI_DEVICE_ERROR - TODO: Add description for return value
1243 EFI_SUCCESS - TODO: Add description for return value
1247 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1249 UINTN TotalBytesWritten
;
1257 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1259 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1261 ByteBuffer
= (UINT8
*) Buffer
;
1262 TotalBytesWritten
= 0;
1264 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1265 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1266 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1267 TotalBytesWritten
++;
1273 BytesToGo
= (DWORD
) (*BufferSize
);
1276 if (Private
->HardwareFlowControl
) {
1280 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1281 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1282 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1288 Result
= Private
->WinNtThunk
->WriteFile (
1290 &ByteBuffer
[TotalBytesWritten
],
1296 if (Private
->HardwareFlowControl
) {
1300 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1301 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1302 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1305 TotalBytesWritten
+= BytesWritten
;
1306 BytesToGo
-= BytesWritten
;
1308 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1309 DEBUG ((EFI_D_ERROR
, "SerialWrite: FileWrite %d\n", Private
->NtError
));
1310 *BufferSize
= TotalBytesWritten
;
1311 gBS
->RestoreTPL (Tpl
);
1312 return EFI_DEVICE_ERROR
;
1314 } while (BytesToGo
> 0);
1317 *BufferSize
= TotalBytesWritten
;
1319 gBS
->RestoreTPL (Tpl
);
1327 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1328 IN OUT UINTN
*BufferSize
,
1333 Routine Description:
1335 TODO: Add function description
1339 This - TODO: add argument description
1340 BufferSize - TODO: add argument description
1341 Buffer - TODO: add argument description
1345 EFI_DEVICE_ERROR - TODO: Add description for return value
1349 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1358 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1360 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1365 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1366 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1367 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1368 ((UINT8
*) Buffer
)[Index
] = Data
;
1375 if (Private
->HardwareFlowControl
) {
1376 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1377 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1378 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1381 Result
= Private
->WinNtThunk
->ReadFile (
1384 (DWORD
) *BufferSize
,
1389 if (Private
->HardwareFlowControl
) {
1390 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1391 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1392 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1396 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1397 gBS
->RestoreTPL (Tpl
);
1398 return EFI_DEVICE_ERROR
;
1402 if (BytesRead
!= *BufferSize
) {
1403 Status
= EFI_TIMEOUT
;
1405 Status
= EFI_SUCCESS
;
1408 *BufferSize
= (UINTN
) BytesRead
;
1410 gBS
->RestoreTPL (Tpl
);
1417 IN SERIAL_DEV_FIFO
*Fifo
1421 Routine Description:
1422 Detect whether specific FIFO is full or not
1425 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1428 TRUE: the FIFO is full
1429 FALSE: the FIFO is not full
1433 if (Fifo
->Surplus
== 0) {
1441 IsaSerialFifoEmpty (
1442 IN SERIAL_DEV_FIFO
*Fifo
1446 Routine Description:
1447 Detect whether specific FIFO is empty or not
1450 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1453 TRUE: the FIFO is empty
1454 FALSE: the FIFO is not empty
1458 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1467 IN SERIAL_DEV_FIFO
*Fifo
,
1472 Routine Description:
1473 Add data to specific FIFO
1476 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1477 Data UINT8: the data added to FIFO
1480 EFI_SUCCESS: Add data to specific FIFO successfully
1481 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1484 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1487 // if FIFO full can not add data
1489 if (IsaSerialFifoFull (Fifo
)) {
1490 return EFI_OUT_OF_RESOURCES
;
1494 // FIFO is not full can add data
1496 Fifo
->Data
[Fifo
->Last
] = Data
;
1499 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1507 IsaSerialFifoRemove (
1508 IN SERIAL_DEV_FIFO
*Fifo
,
1513 Routine Description:
1514 Remove data from specific FIFO
1517 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1518 Data UINT8*: the data removed from FIFO
1521 EFI_SUCCESS: Remove data from specific FIFO successfully
1522 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1525 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1528 // if FIFO is empty, no data can remove
1530 if (IsaSerialFifoEmpty (Fifo
)) {
1531 return EFI_OUT_OF_RESOURCES
;
1535 // FIFO is not empty, can remove data
1537 *Data
= Fifo
->Data
[Fifo
->First
];
1540 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {