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
= EfiLibInstallDriverBindingComponentName2 (
89 &gWinNtSerialIoDriverBinding
,
91 &gWinNtSerialIoComponentName
,
92 &gWinNtSerialIoComponentName2
94 ASSERT_EFI_ERROR (Status
);
103 WinNtSerialIoDriverBindingSupported (
104 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
105 IN EFI_HANDLE Handle
,
106 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
119 // TODO: This - add argument and description to function comment
120 // TODO: Handle - add argument and description to function comment
121 // TODO: RemainingDevicePath - add argument and description to function comment
122 // TODO: EFI_SUCCESS - add return value to function comment
123 // TODO: EFI_SUCCESS - add return value to function comment
126 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
127 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
128 UART_DEVICE_PATH
*UartNode
;
131 // Open the IO Abstraction(s) needed to perform the supported test
133 Status
= gBS
->OpenProtocol (
135 &gEfiDevicePathProtocolGuid
,
137 This
->DriverBindingHandle
,
139 EFI_OPEN_PROTOCOL_BY_DRIVER
141 if (Status
== EFI_ALREADY_STARTED
) {
145 if (EFI_ERROR (Status
)) {
151 &gEfiDevicePathProtocolGuid
,
152 This
->DriverBindingHandle
,
156 Status
= gBS
->OpenProtocol (
158 &gEfiWinNtIoProtocolGuid
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
164 if (Status
== EFI_ALREADY_STARTED
) {
168 if (EFI_ERROR (Status
)) {
173 // Make sure that the WinNt Thunk Protocol is valid
175 if (WinNtIo
->WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
176 Status
= EFI_UNSUPPORTED
;
181 // Check the GUID to see if this is a handle type the driver supports
183 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtSerialPortGuid
)) {
184 Status
= EFI_UNSUPPORTED
;
188 if (RemainingDevicePath
!= NULL
) {
189 Status
= EFI_UNSUPPORTED
;
190 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
191 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
192 UartNode
->Header
.SubType
!= MSG_UART_DP
||
193 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
196 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
199 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
202 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
205 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
208 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
211 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
214 Status
= EFI_SUCCESS
;
219 // Close the I/O Abstraction(s) used to perform the supported test
223 &gEfiWinNtIoProtocolGuid
,
224 This
->DriverBindingHandle
,
234 WinNtSerialIoDriverBindingStart (
235 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
236 IN EFI_HANDLE Handle
,
237 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
250 // TODO: This - add argument and description to function comment
251 // TODO: Handle - add argument and description to function comment
252 // TODO: RemainingDevicePath - add argument and description to function comment
253 // TODO: EFI_SUCCESS - add return value to function comment
254 // TODO: EFI_SUCCESS - add return value to function comment
257 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
258 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
260 UART_DEVICE_PATH Node
;
261 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
262 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
265 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
268 NtHandle
= INVALID_HANDLE_VALUE
;
271 // Grab the protocols we need
273 Status
= gBS
->OpenProtocol (
275 &gEfiDevicePathProtocolGuid
,
277 This
->DriverBindingHandle
,
279 EFI_OPEN_PROTOCOL_BY_DRIVER
281 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
286 // Grab the IO abstraction we need to get any work done
288 Status
= gBS
->OpenProtocol (
290 &gEfiWinNtIoProtocolGuid
,
292 This
->DriverBindingHandle
,
294 EFI_OPEN_PROTOCOL_BY_DRIVER
296 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
299 &gEfiDevicePathProtocolGuid
,
300 This
->DriverBindingHandle
,
306 if (Status
== EFI_ALREADY_STARTED
) {
308 if (RemainingDevicePath
== NULL
) {
313 // Make sure a child handle does not already exist. This driver can only
314 // produce one child per serial port.
316 Status
= gBS
->OpenProtocolInformation (
318 &gEfiWinNtIoProtocolGuid
,
322 if (EFI_ERROR (Status
)) {
326 Status
= EFI_ALREADY_STARTED
;
327 for (Index
= 0; Index
< EntryCount
; Index
++) {
328 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
329 Status
= gBS
->OpenProtocol (
330 OpenInfoBuffer
[Index
].ControllerHandle
,
331 &gEfiSerialIoProtocolGuid
,
333 This
->DriverBindingHandle
,
335 EFI_OPEN_PROTOCOL_GET_PROTOCOL
337 if (!EFI_ERROR (Status
)) {
338 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
339 Status
= SerialIo
->SetAttributes (
342 SerialIo
->Mode
->ReceiveFifoDepth
,
343 SerialIo
->Mode
->Timeout
,
353 FreePool (OpenInfoBuffer
);
358 // Check to see if we can access the hardware device. If it's Open in NT we
359 // will not get access.
361 NtHandle
= WinNtIo
->WinNtThunk
->CreateFile (
363 GENERIC_READ
| GENERIC_WRITE
,
370 if (NtHandle
== INVALID_HANDLE_VALUE
) {
371 Status
= EFI_DEVICE_ERROR
;
376 // Construct Private data
378 Private
= AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA
));
379 if (Private
== NULL
) {
384 // This signature must be valid before any member function is called
386 Private
->Signature
= WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
387 Private
->NtHandle
= NtHandle
;
388 Private
->ControllerHandle
= Handle
;
389 Private
->Handle
= NULL
;
390 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
391 Private
->ParentDevicePath
= ParentDevicePath
;
392 Private
->ControllerNameTable
= NULL
;
394 Private
->SoftwareLoopbackEnable
= FALSE
;
395 Private
->HardwareLoopbackEnable
= FALSE
;
396 Private
->HardwareFlowControl
= FALSE
;
397 Private
->Fifo
.First
= 0;
398 Private
->Fifo
.Last
= 0;
399 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
403 gWinNtSerialIoComponentName
.SupportedLanguages
,
404 &Private
->ControllerNameTable
,
410 gWinNtSerialIoComponentName2
.SupportedLanguages
,
411 &Private
->ControllerNameTable
,
417 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
418 Private
->SerialIo
.Reset
= WinNtSerialIoReset
;
419 Private
->SerialIo
.SetAttributes
= WinNtSerialIoSetAttributes
;
420 Private
->SerialIo
.SetControl
= WinNtSerialIoSetControl
;
421 Private
->SerialIo
.GetControl
= WinNtSerialIoGetControl
;
422 Private
->SerialIo
.Write
= WinNtSerialIoWrite
;
423 Private
->SerialIo
.Read
= WinNtSerialIoRead
;
424 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
426 if (RemainingDevicePath
!= NULL
) {
428 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
429 // already checked to make sure the RemainingDevicePath contains settings
430 // that we can support.
432 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
435 // Build the device path by appending the UART node to the ParentDevicePath
436 // from the WinNtIo handle. The Uart setings are zero here, since
437 // SetAttribute() will update them to match the default setings.
439 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
440 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
441 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
442 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
446 // Build the device path by appending the UART node to the ParentDevicePath
447 // from the WinNtIo handle. The Uart setings are zero here, since
448 // SetAttribute() will update them to match the current setings.
450 Private
->DevicePath
= AppendDevicePathNode (
452 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
454 if (Private
->DevicePath
== NULL
) {
455 Status
= EFI_OUT_OF_RESOURCES
;
460 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
462 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
463 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
464 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
465 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
466 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
467 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
468 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
471 // Issue a reset to initialize the COM port
473 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
474 if (EFI_ERROR (Status
)) {
479 // Create new child handle
481 Status
= gBS
->InstallMultipleProtocolInterfaces (
483 &gEfiSerialIoProtocolGuid
,
485 &gEfiDevicePathProtocolGuid
,
489 if (EFI_ERROR (Status
)) {
494 // Open For Child Device
496 Status
= gBS
->OpenProtocol (
498 &gEfiWinNtIoProtocolGuid
,
500 This
->DriverBindingHandle
,
502 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
504 if (EFI_ERROR (Status
)) {
512 // Use the Stop() function to free all resources allocated in Start()
514 if (Private
!= NULL
) {
515 if (Private
->Handle
!= NULL
) {
516 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
518 if (NtHandle
!= INVALID_HANDLE_VALUE
) {
519 Private
->WinNtThunk
->CloseHandle (NtHandle
);
522 if (Private
->DevicePath
!= NULL
) {
523 FreePool (Private
->DevicePath
);
526 FreeUnicodeStringTable (Private
->ControllerNameTable
);
532 This
->Stop (This
, Handle
, 0, NULL
);
540 WinNtSerialIoDriverBindingStop (
541 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
542 IN EFI_HANDLE Handle
,
543 IN UINTN NumberOfChildren
,
544 IN EFI_HANDLE
*ChildHandleBuffer
550 TODO: Add function description
554 This - TODO: add argument description
555 Handle - TODO: add argument description
556 NumberOfChildren - TODO: add argument description
557 ChildHandleBuffer - TODO: add argument description
561 EFI_DEVICE_ERROR - TODO: Add description for return value
562 EFI_SUCCESS - TODO: Add description for return value
568 BOOLEAN AllChildrenStopped
;
569 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
570 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
571 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
574 // Complete all outstanding transactions to Controller.
575 // Don't allow any new transaction to Controller to be started.
578 if (NumberOfChildren
== 0) {
580 // Close the bus driver
582 Status
= gBS
->CloseProtocol (
584 &gEfiWinNtIoProtocolGuid
,
585 This
->DriverBindingHandle
,
588 Status
= gBS
->CloseProtocol (
590 &gEfiDevicePathProtocolGuid
,
591 This
->DriverBindingHandle
,
597 AllChildrenStopped
= TRUE
;
599 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
600 Status
= gBS
->OpenProtocol (
601 ChildHandleBuffer
[Index
],
602 &gEfiSerialIoProtocolGuid
,
604 This
->DriverBindingHandle
,
606 EFI_OPEN_PROTOCOL_GET_PROTOCOL
608 if (!EFI_ERROR (Status
)) {
609 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
611 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
613 Status
= gBS
->CloseProtocol (
615 &gEfiWinNtIoProtocolGuid
,
616 This
->DriverBindingHandle
,
617 ChildHandleBuffer
[Index
]
620 Status
= gBS
->UninstallMultipleProtocolInterfaces (
621 ChildHandleBuffer
[Index
],
622 &gEfiSerialIoProtocolGuid
,
624 &gEfiDevicePathProtocolGuid
,
629 if (EFI_ERROR (Status
)) {
632 &gEfiWinNtIoProtocolGuid
,
634 This
->DriverBindingHandle
,
635 ChildHandleBuffer
[Index
],
636 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
639 Private
->WinNtThunk
->CloseHandle (Private
->NtHandle
);
641 FreePool (Private
->DevicePath
);
643 FreeUnicodeStringTable (Private
->ControllerNameTable
);
649 if (EFI_ERROR (Status
)) {
650 AllChildrenStopped
= FALSE
;
654 if (!AllChildrenStopped
) {
655 return EFI_DEVICE_ERROR
;
662 // Serial IO Protocol member functions
669 IN EFI_SERIAL_IO_PROTOCOL
*This
675 TODO: Add function description
679 This - TODO: add argument description
683 TODO: add return values
687 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
690 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
692 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
694 Private
->WinNtThunk
->PurgeComm (
696 PURGE_TXCLEAR
| PURGE_RXCLEAR
699 gBS
->RestoreTPL (Tpl
);
701 return This
->SetAttributes (
703 This
->Mode
->BaudRate
,
704 This
->Mode
->ReceiveFifoDepth
,
707 (UINT8
) This
->Mode
->DataBits
,
715 WinNtSerialIoSetAttributes (
716 IN EFI_SERIAL_IO_PROTOCOL
*This
,
718 IN UINT32 ReceiveFifoDepth
,
720 IN EFI_PARITY_TYPE Parity
,
722 IN EFI_STOP_BITS_TYPE StopBits
728 This function is used to set the attributes.
732 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
733 BaudRate - The Baud rate of the serial device.
734 ReceiveFifoDepth - The request depth of fifo on receive side.
735 Timeout - the request timeout for a single charact.
736 Parity - The type of parity used in serial device.
737 DataBits - Number of deata bits used in serial device.
738 StopBits - Number of stop bits used in serial device.
746 // TODO: EFI_SUCCESS - add return value to function comment
747 // TODO: EFI_DEVICE_ERROR - add return value to function comment
748 // TODO: EFI_DEVICE_ERROR - add return value to function comment
749 // TODO: EFI_DEVICE_ERROR - add return value to function comment
750 // TODO: EFI_SUCCESS - add return value to function comment
751 // TODO: EFI_DEVICE_ERROR - add return value to function comment
752 // TODO: EFI_SUCCESS - add return value to function comment
756 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
757 COMMTIMEOUTS PortTimeOuts
;
760 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
763 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
766 // Some of our arguments have defaults if a null value is passed in, and
767 // we must set the default values if a null argument is passed in.
770 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
773 if (ReceiveFifoDepth
== 0) {
774 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
778 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
781 if (Parity
== DefaultParity
) {
782 Parity
= FixedPcdGet8 (PcdUartDefaultParity
);
786 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
789 if (StopBits
== DefaultStopBits
) {
790 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
794 // Make sure all parameters are valid
796 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
797 return EFI_INVALID_PARAMETER
;
801 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
804 for (Index
= 1; Index
< (sizeof (mBaudRateCurrentSupport
) / sizeof (mBaudRateCurrentSupport
[0])); Index
++) {
805 if (BaudRate
< mBaudRateCurrentSupport
[Index
]) {
806 BaudRate
= mBaudRateCurrentSupport
[Index
-1];
811 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
812 return EFI_INVALID_PARAMETER
;
815 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
816 return EFI_INVALID_PARAMETER
;
819 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
820 return EFI_INVALID_PARAMETER
;
823 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
824 return EFI_INVALID_PARAMETER
;
828 // Now we only support DataBits=7,8.
830 if ((DataBits
< 7) || (DataBits
> 8)) {
831 return EFI_INVALID_PARAMETER
;
835 // Now we only support DataBits=7,8.
836 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
838 if (StopBits
== OneFiveStopBits
) {
839 return EFI_INVALID_PARAMETER
;
843 // See if the new attributes already match the current attributes
845 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
846 Private
->UartDevicePath
.DataBits
== DataBits
&&
847 Private
->UartDevicePath
.Parity
== Parity
&&
848 Private
->UartDevicePath
.StopBits
== StopBits
&&
849 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
850 Private
->SerialIoMode
.Timeout
== Timeout
) {
854 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
857 // Get current values from NT
859 ZeroMem (&Private
->NtDCB
, sizeof (DCB
));
860 Private
->NtDCB
.DCBlength
= sizeof (DCB
);
862 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Private
->NtDCB
)) {
863 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
864 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: GetCommState %d\n", Private
->NtError
));
865 gBS
->RestoreTPL (Tpl
);
866 return EFI_DEVICE_ERROR
;
870 // Map EFI com setting to NT
872 Private
->NtDCB
.BaudRate
= ConvertBaud2Nt (BaudRate
);
873 Private
->NtDCB
.ByteSize
= ConvertData2Nt (DataBits
);
874 Private
->NtDCB
.Parity
= ConvertParity2Nt (Parity
);
875 Private
->NtDCB
.StopBits
= ConvertStop2Nt (StopBits
);
877 Private
->NtDCB
.fBinary
= TRUE
;
878 Private
->NtDCB
.fParity
= Private
->NtDCB
.Parity
== NOPARITY
? FALSE
: TRUE
;
879 Private
->NtDCB
.fOutxCtsFlow
= FALSE
;
880 Private
->NtDCB
.fOutxDsrFlow
= FALSE
;
881 Private
->NtDCB
.fDtrControl
= DTR_CONTROL_ENABLE
;
882 Private
->NtDCB
.fDsrSensitivity
= FALSE
;
883 Private
->NtDCB
.fOutX
= FALSE
;
884 Private
->NtDCB
.fInX
= FALSE
;
885 Private
->NtDCB
.fRtsControl
= RTS_CONTROL_ENABLE
;
886 Private
->NtDCB
.fNull
= FALSE
;
891 Result
= Private
->WinNtThunk
->SetCommState (Private
->NtHandle
, &Private
->NtDCB
);
893 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
894 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommState %d\n", Private
->NtError
));
895 gBS
->RestoreTPL (Tpl
);
896 return EFI_DEVICE_ERROR
;
900 // Set com port read/write timeout values
902 ConvertedTime
= ConvertTime2Nt (Timeout
);
903 PortTimeOuts
.ReadIntervalTimeout
= MAXDWORD
;
904 PortTimeOuts
.ReadTotalTimeoutMultiplier
= 0;
905 PortTimeOuts
.ReadTotalTimeoutConstant
= ConvertedTime
;
906 PortTimeOuts
.WriteTotalTimeoutMultiplier
= ConvertedTime
== 0 ? 1 : ConvertedTime
;
907 PortTimeOuts
.WriteTotalTimeoutConstant
= 0;
909 if (!Private
->WinNtThunk
->SetCommTimeouts (Private
->NtHandle
, &PortTimeOuts
)) {
910 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
911 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommTimeouts %d\n", Private
->NtError
));
912 gBS
->RestoreTPL (Tpl
);
913 return EFI_DEVICE_ERROR
;
919 Private
->SerialIoMode
.BaudRate
= BaudRate
;
920 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
921 Private
->SerialIoMode
.Timeout
= Timeout
;
922 Private
->SerialIoMode
.Parity
= Parity
;
923 Private
->SerialIoMode
.DataBits
= DataBits
;
924 Private
->SerialIoMode
.StopBits
= StopBits
;
927 // See if Device Path Node has actually changed
929 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
930 Private
->UartDevicePath
.DataBits
== DataBits
&&
931 Private
->UartDevicePath
.Parity
== Parity
&&
932 Private
->UartDevicePath
.StopBits
== StopBits
) {
933 gBS
->RestoreTPL(Tpl
);
938 // Update the device path
940 Private
->UartDevicePath
.BaudRate
= BaudRate
;
941 Private
->UartDevicePath
.DataBits
= DataBits
;
942 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
943 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
945 NewDevicePath
= AppendDevicePathNode (
946 Private
->ParentDevicePath
,
947 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
949 if (NewDevicePath
== NULL
) {
950 gBS
->RestoreTPL (Tpl
);
951 return EFI_DEVICE_ERROR
;
954 if (Private
->Handle
!= NULL
) {
955 Status
= gBS
->ReinstallProtocolInterface (
957 &gEfiDevicePathProtocolGuid
,
961 if (EFI_ERROR (Status
)) {
962 gBS
->RestoreTPL (Tpl
);
967 if (Private
->DevicePath
!= NULL
) {
968 FreePool (Private
->DevicePath
);
971 Private
->DevicePath
= NewDevicePath
;
973 gBS
->RestoreTPL (Tpl
);
981 WinNtSerialIoSetControl (
982 IN EFI_SERIAL_IO_PROTOCOL
*This
,
989 TODO: Add function description
993 This - TODO: add argument description
994 Control - TODO: add argument description
998 EFI_DEVICE_ERROR - TODO: Add description for return value
999 EFI_DEVICE_ERROR - TODO: Add description for return value
1000 EFI_SUCCESS - TODO: Add description for return value
1004 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1010 // first determine the parameter is invalid
1012 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1013 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1014 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1015 return EFI_UNSUPPORTED
;
1018 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1020 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1022 Result
= Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
);
1025 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1026 DEBUG ((EFI_D_ERROR
, "SerialSetControl: GetCommState %d\n", Private
->NtError
));
1027 gBS
->RestoreTPL (Tpl
);
1028 return EFI_DEVICE_ERROR
;
1031 Dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1032 Dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1033 Private
->HardwareFlowControl
= FALSE
;
1034 Private
->SoftwareLoopbackEnable
= FALSE
;
1035 Private
->HardwareLoopbackEnable
= FALSE
;
1037 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1038 Dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1041 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1042 Dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1045 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1046 Private
->HardwareFlowControl
= TRUE
;
1049 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1050 Private
->SoftwareLoopbackEnable
= TRUE
;
1053 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1054 Private
->HardwareLoopbackEnable
= TRUE
;
1057 Result
= Private
->WinNtThunk
->SetCommState (
1063 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1064 DEBUG ((EFI_D_ERROR
, "SerialSetControl: SetCommState %d\n", Private
->NtError
));
1065 gBS
->RestoreTPL (Tpl
);
1066 return EFI_DEVICE_ERROR
;
1069 gBS
->RestoreTPL (Tpl
);
1077 WinNtSerialIoGetControl (
1078 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1083 Routine Description:
1085 TODO: Add function description
1089 This - TODO: add argument description
1090 Control - TODO: add argument description
1094 EFI_DEVICE_ERROR - TODO: Add description for return value
1095 EFI_DEVICE_ERROR - TODO: Add description for return value
1096 EFI_DEVICE_ERROR - TODO: Add description for return value
1097 EFI_SUCCESS - TODO: Add description for return value
1101 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1108 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1110 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1115 if (!Private
->WinNtThunk
->GetCommModemStatus (Private
->NtHandle
, &ModemStatus
)) {
1116 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1117 gBS
->RestoreTPL (Tpl
);
1118 return EFI_DEVICE_ERROR
;
1122 if (ModemStatus
& MS_CTS_ON
) {
1123 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1126 if (ModemStatus
& MS_DSR_ON
) {
1127 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1130 if (ModemStatus
& MS_RING_ON
) {
1131 Bits
|= EFI_SERIAL_RING_INDICATE
;
1134 if (ModemStatus
& MS_RLSD_ON
) {
1135 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1141 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
)) {
1142 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1143 DEBUG ((EFI_D_ERROR
, "SerialGetControl: GetCommState %d\n", Private
->NtError
));
1144 gBS
->RestoreTPL (Tpl
);
1145 return EFI_DEVICE_ERROR
;
1148 if (Dcb
.fDtrControl
== DTR_CONTROL_ENABLE
) {
1149 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1152 if (Dcb
.fRtsControl
== RTS_CONTROL_ENABLE
) {
1153 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1156 if (Private
->HardwareFlowControl
) {
1157 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1160 if (Private
->SoftwareLoopbackEnable
) {
1161 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1164 if (Private
->HardwareLoopbackEnable
) {
1165 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1169 // Get input buffer status
1171 if (!Private
->WinNtThunk
->ClearCommError (Private
->NtHandle
, &Errors
, &Private
->NtComStatus
)) {
1172 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1173 DEBUG ((EFI_D_ERROR
, "SerialGetControl: ClearCommError %d\n", Private
->NtError
));
1174 gBS
->RestoreTPL (Tpl
);
1175 return EFI_DEVICE_ERROR
;
1178 if (Private
->NtComStatus
.cbInQue
== 0) {
1179 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1184 gBS
->RestoreTPL (Tpl
);
1192 WinNtSerialIoWrite (
1193 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1194 IN OUT UINTN
*BufferSize
,
1199 Routine Description:
1201 TODO: Add function description
1205 This - TODO: add argument description
1206 BufferSize - TODO: add argument description
1207 Buffer - TODO: add argument description
1211 EFI_DEVICE_ERROR - TODO: Add description for return value
1212 EFI_SUCCESS - TODO: Add description for return value
1216 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1218 UINTN TotalBytesWritten
;
1226 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1228 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1230 ByteBuffer
= (UINT8
*) Buffer
;
1231 TotalBytesWritten
= 0;
1233 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1234 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1235 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1236 TotalBytesWritten
++;
1242 BytesToGo
= (DWORD
) (*BufferSize
);
1245 if (Private
->HardwareFlowControl
) {
1249 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1250 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1251 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1257 Result
= Private
->WinNtThunk
->WriteFile (
1259 &ByteBuffer
[TotalBytesWritten
],
1265 if (Private
->HardwareFlowControl
) {
1269 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1270 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1271 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1274 TotalBytesWritten
+= BytesWritten
;
1275 BytesToGo
-= BytesWritten
;
1277 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1278 DEBUG ((EFI_D_ERROR
, "SerialWrite: FileWrite %d\n", Private
->NtError
));
1279 *BufferSize
= TotalBytesWritten
;
1280 gBS
->RestoreTPL (Tpl
);
1281 return EFI_DEVICE_ERROR
;
1283 } while (BytesToGo
> 0);
1286 *BufferSize
= TotalBytesWritten
;
1288 gBS
->RestoreTPL (Tpl
);
1297 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1298 IN OUT UINTN
*BufferSize
,
1303 Routine Description:
1305 TODO: Add function description
1309 This - TODO: add argument description
1310 BufferSize - TODO: add argument description
1311 Buffer - TODO: add argument description
1315 EFI_DEVICE_ERROR - TODO: Add description for return value
1319 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1328 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1330 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1335 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1336 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1337 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1338 ((UINT8
*) Buffer
)[Index
] = Data
;
1345 if (Private
->HardwareFlowControl
) {
1346 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1347 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1348 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1351 Result
= Private
->WinNtThunk
->ReadFile (
1354 (DWORD
) *BufferSize
,
1359 if (Private
->HardwareFlowControl
) {
1360 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1361 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1362 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1366 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1367 gBS
->RestoreTPL (Tpl
);
1368 return EFI_DEVICE_ERROR
;
1372 if (BytesRead
!= *BufferSize
) {
1373 Status
= EFI_TIMEOUT
;
1375 Status
= EFI_SUCCESS
;
1378 *BufferSize
= (UINTN
) BytesRead
;
1380 gBS
->RestoreTPL (Tpl
);
1387 IN SERIAL_DEV_FIFO
*Fifo
1391 Routine Description:
1392 Detect whether specific FIFO is full or not
1395 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1398 TRUE: the FIFO is full
1399 FALSE: the FIFO is not full
1403 if (Fifo
->Surplus
== 0) {
1411 IsaSerialFifoEmpty (
1412 IN SERIAL_DEV_FIFO
*Fifo
1416 Routine Description:
1417 Detect whether specific FIFO is empty or not
1420 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1423 TRUE: the FIFO is empty
1424 FALSE: the FIFO is not empty
1428 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1437 IN SERIAL_DEV_FIFO
*Fifo
,
1442 Routine Description:
1443 Add data to specific FIFO
1446 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1447 Data UINT8: the data added to FIFO
1450 EFI_SUCCESS: Add data to specific FIFO successfully
1451 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1454 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1457 // if FIFO full can not add data
1459 if (IsaSerialFifoFull (Fifo
)) {
1460 return EFI_OUT_OF_RESOURCES
;
1464 // FIFO is not full can add data
1466 Fifo
->Data
[Fifo
->Last
] = Data
;
1469 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1477 IsaSerialFifoRemove (
1478 IN SERIAL_DEV_FIFO
*Fifo
,
1483 Routine Description:
1484 Remove data from specific FIFO
1487 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1488 Data UINT8*: the data removed from FIFO
1491 EFI_SUCCESS: Remove data from specific FIFO successfully
1492 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1495 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1498 // if FIFO is empty, no data can remove
1500 if (IsaSerialFifoEmpty (Fifo
)) {
1501 return EFI_OUT_OF_RESOURCES
;
1505 // FIFO is not empty, can remove data
1507 *Data
= Fifo
->Data
[Fifo
->First
];
1510 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {