3 Copyright (c) 2006 - 2009, 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 // If protocols were opened normally, closed it
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
375 FreePool (OpenInfoBuffer
);
377 if (Index
< EntryCount
) {
379 // If gEfiWinNtIoProtocolGuid is opened by one child device, return
384 // If gEfiWinNtIoProtocolGuid is not opened by any child device,
385 // go further to create child device handle based on RemainingDevicePath
389 if (RemainingDevicePath
== NULL
) {
391 // Build the device path by appending the UART node to the ParentDevicePath
392 // from the WinNtIo handle. The Uart setings are zero here, since
393 // SetAttribute() will update them to match the default setings.
395 ZeroMem (&Node
, sizeof (UART_DEVICE_PATH
));
396 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
397 Node
.Header
.SubType
= MSG_UART_DP
;
398 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Node
, sizeof (UART_DEVICE_PATH
));
400 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
402 // If RemainingDevicePath isn't the End of Device Path Node,
403 // only scan the specified device by RemainingDevicePath
406 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
407 // already checked to make sure the RemainingDevicePath contains settings
408 // that we can support.
410 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
414 // If RemainingDevicePath is the End of Device Path Node,
415 // skip enumerate any device and return EFI_SUCESSS
421 // Check to see if we can access the hardware device. If it's Open in NT we
422 // will not get access.
424 NtHandle
= WinNtIo
->WinNtThunk
->CreateFile (
426 GENERIC_READ
| GENERIC_WRITE
,
433 if (NtHandle
== INVALID_HANDLE_VALUE
) {
434 Status
= EFI_DEVICE_ERROR
;
439 // Construct Private data
441 Private
= AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA
));
442 if (Private
== NULL
) {
447 // This signature must be valid before any member function is called
449 Private
->Signature
= WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
450 Private
->NtHandle
= NtHandle
;
451 Private
->ControllerHandle
= Handle
;
452 Private
->Handle
= NULL
;
453 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
454 Private
->ParentDevicePath
= ParentDevicePath
;
455 Private
->ControllerNameTable
= NULL
;
457 Private
->SoftwareLoopbackEnable
= FALSE
;
458 Private
->HardwareLoopbackEnable
= FALSE
;
459 Private
->HardwareFlowControl
= FALSE
;
460 Private
->Fifo
.First
= 0;
461 Private
->Fifo
.Last
= 0;
462 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
464 CopyMem (&Private
->UartDevicePath
, &Node
, sizeof (UART_DEVICE_PATH
));
468 gWinNtSerialIoComponentName
.SupportedLanguages
,
469 &Private
->ControllerNameTable
,
475 gWinNtSerialIoComponentName2
.SupportedLanguages
,
476 &Private
->ControllerNameTable
,
482 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
483 Private
->SerialIo
.Reset
= WinNtSerialIoReset
;
484 Private
->SerialIo
.SetAttributes
= WinNtSerialIoSetAttributes
;
485 Private
->SerialIo
.SetControl
= WinNtSerialIoSetControl
;
486 Private
->SerialIo
.GetControl
= WinNtSerialIoGetControl
;
487 Private
->SerialIo
.Write
= WinNtSerialIoWrite
;
488 Private
->SerialIo
.Read
= WinNtSerialIoRead
;
489 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
492 // Build the device path by appending the UART node to the ParentDevicePath
493 // from the WinNtIo handle. The Uart setings are zero here, since
494 // SetAttribute() will update them to match the current setings.
496 Private
->DevicePath
= AppendDevicePathNode (
498 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
500 if (Private
->DevicePath
== NULL
) {
501 Status
= EFI_OUT_OF_RESOURCES
;
506 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
508 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
509 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
510 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
511 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
512 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
513 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
514 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
517 // Issue a reset to initialize the COM port
519 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
520 if (EFI_ERROR (Status
)) {
525 // Create new child handle
527 Status
= gBS
->InstallMultipleProtocolInterfaces (
529 &gEfiSerialIoProtocolGuid
,
531 &gEfiDevicePathProtocolGuid
,
535 if (EFI_ERROR (Status
)) {
540 // Open For Child Device
542 Status
= gBS
->OpenProtocol (
544 &gEfiWinNtIoProtocolGuid
,
546 This
->DriverBindingHandle
,
548 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
550 if (EFI_ERROR (Status
)) {
558 // Use the Stop() function to free all resources allocated in Start()
560 if (Private
!= NULL
) {
561 if (Private
->Handle
!= NULL
) {
562 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
564 if (NtHandle
!= INVALID_HANDLE_VALUE
) {
565 Private
->WinNtThunk
->CloseHandle (NtHandle
);
568 if (Private
->DevicePath
!= NULL
) {
569 FreePool (Private
->DevicePath
);
572 FreeUnicodeStringTable (Private
->ControllerNameTable
);
578 This
->Stop (This
, Handle
, 0, NULL
);
585 WinNtSerialIoDriverBindingStop (
586 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
587 IN EFI_HANDLE Handle
,
588 IN UINTN NumberOfChildren
,
589 IN EFI_HANDLE
*ChildHandleBuffer
595 TODO: Add function description
599 This - TODO: add argument description
600 Handle - TODO: add argument description
601 NumberOfChildren - TODO: add argument description
602 ChildHandleBuffer - TODO: add argument description
606 EFI_DEVICE_ERROR - TODO: Add description for return value
607 EFI_SUCCESS - TODO: Add description for return value
613 BOOLEAN AllChildrenStopped
;
614 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
615 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
616 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
619 // Complete all outstanding transactions to Controller.
620 // Don't allow any new transaction to Controller to be started.
623 if (NumberOfChildren
== 0) {
625 // Close the bus driver
627 Status
= gBS
->CloseProtocol (
629 &gEfiWinNtIoProtocolGuid
,
630 This
->DriverBindingHandle
,
633 Status
= gBS
->CloseProtocol (
635 &gEfiDevicePathProtocolGuid
,
636 This
->DriverBindingHandle
,
642 AllChildrenStopped
= TRUE
;
644 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
645 Status
= gBS
->OpenProtocol (
646 ChildHandleBuffer
[Index
],
647 &gEfiSerialIoProtocolGuid
,
649 This
->DriverBindingHandle
,
651 EFI_OPEN_PROTOCOL_GET_PROTOCOL
653 if (!EFI_ERROR (Status
)) {
654 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
656 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
658 Status
= gBS
->CloseProtocol (
660 &gEfiWinNtIoProtocolGuid
,
661 This
->DriverBindingHandle
,
662 ChildHandleBuffer
[Index
]
665 Status
= gBS
->UninstallMultipleProtocolInterfaces (
666 ChildHandleBuffer
[Index
],
667 &gEfiSerialIoProtocolGuid
,
669 &gEfiDevicePathProtocolGuid
,
674 if (EFI_ERROR (Status
)) {
677 &gEfiWinNtIoProtocolGuid
,
679 This
->DriverBindingHandle
,
680 ChildHandleBuffer
[Index
],
681 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
684 Private
->WinNtThunk
->CloseHandle (Private
->NtHandle
);
686 FreePool (Private
->DevicePath
);
688 FreeUnicodeStringTable (Private
->ControllerNameTable
);
694 if (EFI_ERROR (Status
)) {
695 AllChildrenStopped
= FALSE
;
699 if (!AllChildrenStopped
) {
700 return EFI_DEVICE_ERROR
;
707 // Serial IO Protocol member functions
713 IN EFI_SERIAL_IO_PROTOCOL
*This
719 TODO: Add function description
723 This - TODO: add argument description
727 TODO: add return values
731 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
734 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
736 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
738 Private
->WinNtThunk
->PurgeComm (
740 PURGE_TXCLEAR
| PURGE_RXCLEAR
743 gBS
->RestoreTPL (Tpl
);
745 return This
->SetAttributes (
747 This
->Mode
->BaudRate
,
748 This
->Mode
->ReceiveFifoDepth
,
750 (EFI_PARITY_TYPE
)This
->Mode
->Parity
,
751 (UINT8
) This
->Mode
->DataBits
,
752 (EFI_STOP_BITS_TYPE
)This
->Mode
->StopBits
758 WinNtSerialIoSetAttributes (
759 IN EFI_SERIAL_IO_PROTOCOL
*This
,
761 IN UINT32 ReceiveFifoDepth
,
763 IN EFI_PARITY_TYPE Parity
,
765 IN EFI_STOP_BITS_TYPE StopBits
771 This function is used to set the attributes.
775 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
776 BaudRate - The Baud rate of the serial device.
777 ReceiveFifoDepth - The request depth of fifo on receive side.
778 Timeout - the request timeout for a single charact.
779 Parity - The type of parity used in serial device.
780 DataBits - Number of deata bits used in serial device.
781 StopBits - Number of stop bits used in serial device.
789 // TODO: EFI_SUCCESS - add return value to function comment
790 // TODO: EFI_DEVICE_ERROR - add return value to function comment
791 // TODO: EFI_DEVICE_ERROR - add return value to function comment
792 // TODO: EFI_DEVICE_ERROR - add return value to function comment
793 // TODO: EFI_SUCCESS - add return value to function comment
794 // TODO: EFI_DEVICE_ERROR - add return value to function comment
795 // TODO: EFI_SUCCESS - add return value to function comment
799 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
800 COMMTIMEOUTS PortTimeOuts
;
803 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
806 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
809 // Some of our arguments have defaults if a null value is passed in, and
810 // we must set the default values if a null argument is passed in.
813 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
816 if (ReceiveFifoDepth
== 0) {
817 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
821 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
824 if (Parity
== DefaultParity
) {
825 Parity
= (EFI_PARITY_TYPE
) (FixedPcdGet8 (PcdUartDefaultParity
));
829 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
832 if (StopBits
== DefaultStopBits
) {
833 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
837 // Make sure all parameters are valid
839 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
840 return EFI_INVALID_PARAMETER
;
844 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
847 for (Index
= 1; Index
< (sizeof (mBaudRateCurrentSupport
) / sizeof (mBaudRateCurrentSupport
[0])); Index
++) {
848 if (BaudRate
< mBaudRateCurrentSupport
[Index
]) {
849 BaudRate
= mBaudRateCurrentSupport
[Index
-1];
854 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
855 return EFI_INVALID_PARAMETER
;
858 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
859 return EFI_INVALID_PARAMETER
;
862 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
863 return EFI_INVALID_PARAMETER
;
866 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
867 return EFI_INVALID_PARAMETER
;
871 // Now we only support DataBits=7,8.
873 if ((DataBits
< 7) || (DataBits
> 8)) {
874 return EFI_INVALID_PARAMETER
;
878 // Now we only support DataBits=7,8.
879 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
881 if (StopBits
== OneFiveStopBits
) {
882 return EFI_INVALID_PARAMETER
;
886 // See if the new attributes already match the current attributes
888 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
889 Private
->UartDevicePath
.DataBits
== DataBits
&&
890 Private
->UartDevicePath
.Parity
== Parity
&&
891 Private
->UartDevicePath
.StopBits
== StopBits
&&
892 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
893 Private
->SerialIoMode
.Timeout
== Timeout
) {
897 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
900 // Get current values from NT
902 ZeroMem (&Private
->NtDCB
, sizeof (DCB
));
903 Private
->NtDCB
.DCBlength
= sizeof (DCB
);
905 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Private
->NtDCB
)) {
906 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
907 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: GetCommState %d\n", Private
->NtError
));
908 gBS
->RestoreTPL (Tpl
);
909 return EFI_DEVICE_ERROR
;
913 // Map EFI com setting to NT
915 Private
->NtDCB
.BaudRate
= ConvertBaud2Nt (BaudRate
);
916 Private
->NtDCB
.ByteSize
= ConvertData2Nt (DataBits
);
917 Private
->NtDCB
.Parity
= ConvertParity2Nt (Parity
);
918 Private
->NtDCB
.StopBits
= ConvertStop2Nt (StopBits
);
920 Private
->NtDCB
.fBinary
= TRUE
;
921 Private
->NtDCB
.fParity
= Private
->NtDCB
.Parity
== NOPARITY
? FALSE
: TRUE
;
922 Private
->NtDCB
.fOutxCtsFlow
= FALSE
;
923 Private
->NtDCB
.fOutxDsrFlow
= FALSE
;
924 Private
->NtDCB
.fDtrControl
= DTR_CONTROL_ENABLE
;
925 Private
->NtDCB
.fDsrSensitivity
= FALSE
;
926 Private
->NtDCB
.fOutX
= FALSE
;
927 Private
->NtDCB
.fInX
= FALSE
;
928 Private
->NtDCB
.fRtsControl
= RTS_CONTROL_ENABLE
;
929 Private
->NtDCB
.fNull
= FALSE
;
934 Result
= Private
->WinNtThunk
->SetCommState (Private
->NtHandle
, &Private
->NtDCB
);
936 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
937 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommState %d\n", Private
->NtError
));
938 gBS
->RestoreTPL (Tpl
);
939 return EFI_DEVICE_ERROR
;
943 // Set com port read/write timeout values
945 ConvertedTime
= ConvertTime2Nt (Timeout
);
946 PortTimeOuts
.ReadIntervalTimeout
= MAXDWORD
;
947 PortTimeOuts
.ReadTotalTimeoutMultiplier
= 0;
948 PortTimeOuts
.ReadTotalTimeoutConstant
= ConvertedTime
;
949 PortTimeOuts
.WriteTotalTimeoutMultiplier
= ConvertedTime
== 0 ? 1 : ConvertedTime
;
950 PortTimeOuts
.WriteTotalTimeoutConstant
= 0;
952 if (!Private
->WinNtThunk
->SetCommTimeouts (Private
->NtHandle
, &PortTimeOuts
)) {
953 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
954 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommTimeouts %d\n", Private
->NtError
));
955 gBS
->RestoreTPL (Tpl
);
956 return EFI_DEVICE_ERROR
;
962 Private
->SerialIoMode
.BaudRate
= BaudRate
;
963 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
964 Private
->SerialIoMode
.Timeout
= Timeout
;
965 Private
->SerialIoMode
.Parity
= Parity
;
966 Private
->SerialIoMode
.DataBits
= DataBits
;
967 Private
->SerialIoMode
.StopBits
= StopBits
;
970 // See if Device Path Node has actually changed
972 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
973 Private
->UartDevicePath
.DataBits
== DataBits
&&
974 Private
->UartDevicePath
.Parity
== Parity
&&
975 Private
->UartDevicePath
.StopBits
== StopBits
) {
976 gBS
->RestoreTPL(Tpl
);
981 // Update the device path
983 Private
->UartDevicePath
.BaudRate
= BaudRate
;
984 Private
->UartDevicePath
.DataBits
= DataBits
;
985 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
986 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
988 NewDevicePath
= AppendDevicePathNode (
989 Private
->ParentDevicePath
,
990 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
992 if (NewDevicePath
== NULL
) {
993 gBS
->RestoreTPL (Tpl
);
994 return EFI_DEVICE_ERROR
;
997 if (Private
->Handle
!= NULL
) {
998 Status
= gBS
->ReinstallProtocolInterface (
1000 &gEfiDevicePathProtocolGuid
,
1001 Private
->DevicePath
,
1004 if (EFI_ERROR (Status
)) {
1005 gBS
->RestoreTPL (Tpl
);
1010 if (Private
->DevicePath
!= NULL
) {
1011 FreePool (Private
->DevicePath
);
1014 Private
->DevicePath
= NewDevicePath
;
1016 gBS
->RestoreTPL (Tpl
);
1023 WinNtSerialIoSetControl (
1024 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1029 Routine Description:
1031 TODO: Add function description
1035 This - TODO: add argument description
1036 Control - TODO: add argument description
1040 EFI_DEVICE_ERROR - TODO: Add description for return value
1041 EFI_DEVICE_ERROR - TODO: Add description for return value
1042 EFI_SUCCESS - TODO: Add description for return value
1046 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1052 // first determine the parameter is invalid
1054 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1055 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1056 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1057 return EFI_UNSUPPORTED
;
1060 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1062 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1064 Result
= Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
);
1067 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1068 DEBUG ((EFI_D_ERROR
, "SerialSetControl: GetCommState %d\n", Private
->NtError
));
1069 gBS
->RestoreTPL (Tpl
);
1070 return EFI_DEVICE_ERROR
;
1073 Dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1074 Dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1075 Private
->HardwareFlowControl
= FALSE
;
1076 Private
->SoftwareLoopbackEnable
= FALSE
;
1077 Private
->HardwareLoopbackEnable
= FALSE
;
1079 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1080 Dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1083 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1084 Dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1087 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1088 Private
->HardwareFlowControl
= TRUE
;
1091 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1092 Private
->SoftwareLoopbackEnable
= TRUE
;
1095 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1096 Private
->HardwareLoopbackEnable
= TRUE
;
1099 Result
= Private
->WinNtThunk
->SetCommState (
1105 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1106 DEBUG ((EFI_D_ERROR
, "SerialSetControl: SetCommState %d\n", Private
->NtError
));
1107 gBS
->RestoreTPL (Tpl
);
1108 return EFI_DEVICE_ERROR
;
1111 gBS
->RestoreTPL (Tpl
);
1118 WinNtSerialIoGetControl (
1119 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1124 Routine Description:
1126 TODO: Add function description
1130 This - TODO: add argument description
1131 Control - TODO: add argument description
1135 EFI_DEVICE_ERROR - TODO: Add description for return value
1136 EFI_DEVICE_ERROR - TODO: Add description for return value
1137 EFI_DEVICE_ERROR - TODO: Add description for return value
1138 EFI_SUCCESS - TODO: Add description for return value
1142 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1149 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1151 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1156 if (!Private
->WinNtThunk
->GetCommModemStatus (Private
->NtHandle
, &ModemStatus
)) {
1157 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1158 gBS
->RestoreTPL (Tpl
);
1159 return EFI_DEVICE_ERROR
;
1163 if (ModemStatus
& MS_CTS_ON
) {
1164 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1167 if (ModemStatus
& MS_DSR_ON
) {
1168 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1171 if (ModemStatus
& MS_RING_ON
) {
1172 Bits
|= EFI_SERIAL_RING_INDICATE
;
1175 if (ModemStatus
& MS_RLSD_ON
) {
1176 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1182 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
)) {
1183 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1184 DEBUG ((EFI_D_ERROR
, "SerialGetControl: GetCommState %d\n", Private
->NtError
));
1185 gBS
->RestoreTPL (Tpl
);
1186 return EFI_DEVICE_ERROR
;
1189 if (Dcb
.fDtrControl
== DTR_CONTROL_ENABLE
) {
1190 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1193 if (Dcb
.fRtsControl
== RTS_CONTROL_ENABLE
) {
1194 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1197 if (Private
->HardwareFlowControl
) {
1198 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1201 if (Private
->SoftwareLoopbackEnable
) {
1202 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1205 if (Private
->HardwareLoopbackEnable
) {
1206 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1210 // Get input buffer status
1212 if (!Private
->WinNtThunk
->ClearCommError (Private
->NtHandle
, &Errors
, &Private
->NtComStatus
)) {
1213 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1214 DEBUG ((EFI_D_ERROR
, "SerialGetControl: ClearCommError %d\n", Private
->NtError
));
1215 gBS
->RestoreTPL (Tpl
);
1216 return EFI_DEVICE_ERROR
;
1219 if (Private
->NtComStatus
.cbInQue
== 0) {
1220 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1225 gBS
->RestoreTPL (Tpl
);
1232 WinNtSerialIoWrite (
1233 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1234 IN OUT UINTN
*BufferSize
,
1239 Routine Description:
1241 TODO: Add function description
1245 This - TODO: add argument description
1246 BufferSize - TODO: add argument description
1247 Buffer - TODO: add argument description
1251 EFI_DEVICE_ERROR - TODO: Add description for return value
1252 EFI_SUCCESS - TODO: Add description for return value
1256 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1258 UINTN TotalBytesWritten
;
1266 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1268 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1270 ByteBuffer
= (UINT8
*) Buffer
;
1271 TotalBytesWritten
= 0;
1273 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1274 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1275 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1276 TotalBytesWritten
++;
1282 BytesToGo
= (DWORD
) (*BufferSize
);
1285 if (Private
->HardwareFlowControl
) {
1289 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1290 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1291 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1297 Result
= Private
->WinNtThunk
->WriteFile (
1299 &ByteBuffer
[TotalBytesWritten
],
1305 if (Private
->HardwareFlowControl
) {
1309 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1310 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1311 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1314 TotalBytesWritten
+= BytesWritten
;
1315 BytesToGo
-= BytesWritten
;
1317 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1318 DEBUG ((EFI_D_ERROR
, "SerialWrite: FileWrite %d\n", Private
->NtError
));
1319 *BufferSize
= TotalBytesWritten
;
1320 gBS
->RestoreTPL (Tpl
);
1321 return EFI_DEVICE_ERROR
;
1323 } while (BytesToGo
> 0);
1326 *BufferSize
= TotalBytesWritten
;
1328 gBS
->RestoreTPL (Tpl
);
1336 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1337 IN OUT UINTN
*BufferSize
,
1342 Routine Description:
1344 TODO: Add function description
1348 This - TODO: add argument description
1349 BufferSize - TODO: add argument description
1350 Buffer - TODO: add argument description
1354 EFI_DEVICE_ERROR - TODO: Add description for return value
1358 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1367 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1369 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1374 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1375 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1376 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1377 ((UINT8
*) Buffer
)[Index
] = Data
;
1384 if (Private
->HardwareFlowControl
) {
1385 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1386 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1387 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1390 Result
= Private
->WinNtThunk
->ReadFile (
1393 (DWORD
) *BufferSize
,
1398 if (Private
->HardwareFlowControl
) {
1399 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1400 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1401 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1405 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1406 gBS
->RestoreTPL (Tpl
);
1407 return EFI_DEVICE_ERROR
;
1411 if (BytesRead
!= *BufferSize
) {
1412 Status
= EFI_TIMEOUT
;
1414 Status
= EFI_SUCCESS
;
1417 *BufferSize
= (UINTN
) BytesRead
;
1419 gBS
->RestoreTPL (Tpl
);
1426 IN SERIAL_DEV_FIFO
*Fifo
1430 Routine Description:
1431 Detect whether specific FIFO is full or not
1434 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1437 TRUE: the FIFO is full
1438 FALSE: the FIFO is not full
1442 if (Fifo
->Surplus
== 0) {
1450 IsaSerialFifoEmpty (
1451 IN SERIAL_DEV_FIFO
*Fifo
1455 Routine Description:
1456 Detect whether specific FIFO is empty or not
1459 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1462 TRUE: the FIFO is empty
1463 FALSE: the FIFO is not empty
1467 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1476 IN SERIAL_DEV_FIFO
*Fifo
,
1481 Routine Description:
1482 Add data to specific FIFO
1485 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1486 Data UINT8: the data added to FIFO
1489 EFI_SUCCESS: Add data to specific FIFO successfully
1490 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1493 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1496 // if FIFO full can not add data
1498 if (IsaSerialFifoFull (Fifo
)) {
1499 return EFI_OUT_OF_RESOURCES
;
1503 // FIFO is not full can add data
1505 Fifo
->Data
[Fifo
->Last
] = Data
;
1508 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1516 IsaSerialFifoRemove (
1517 IN SERIAL_DEV_FIFO
*Fifo
,
1522 Routine Description:
1523 Remove data from specific FIFO
1526 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1527 Data UINT8*: the data removed from FIFO
1530 EFI_SUCCESS: Remove data from specific FIFO successfully
1531 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1534 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1537 // if FIFO is empty, no data can remove
1539 if (IsaSerialFifoEmpty (Fifo
)) {
1540 return EFI_OUT_OF_RESOURCES
;
1544 // FIFO is not empty, can remove data
1546 *Data
= Fifo
->Data
[Fifo
->First
];
1549 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {