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
49 // The package level header files this module uses
54 // The protocols, PPI and GUID defintions for this module
56 #include <Protocol/WinNtIo.h>
57 #include <Protocol/ComponentName.h>
58 #include <Protocol/SerialIo.h>
59 #include <Protocol/DriverBinding.h>
60 #include <Protocol/DevicePath.h>
62 // The Library classes this module consumes
64 #include <Library/DebugLib.h>
65 #include <Library/BaseLib.h>
66 #include <Library/UefiDriverEntryPoint.h>
67 #include <Library/UefiLib.h>
68 #include <Library/BaseMemoryLib.h>
69 #include <Library/UefiBootServicesTableLib.h>
70 #include <Library/DevicePathLib.h>
71 #include <Library/MemoryAllocationLib.h>
73 #include "WinNtSerialIo.h"
75 EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding
= {
76 WinNtSerialIoDriverBindingSupported
,
77 WinNtSerialIoDriverBindingStart
,
78 WinNtSerialIoDriverBindingStop
,
85 The user Entry Point for module WinNtSerialIo. The user code starts with this function.
87 @param[in] ImageHandle The firmware allocated handle for the EFI image.
88 @param[in] SystemTable A pointer to the EFI System Table.
90 @retval EFI_SUCCESS The entry point is executed successfully.
91 @retval other Some error occurs when executing this entry point.
96 InitializeWinNtSerialIo(
97 IN EFI_HANDLE ImageHandle
,
98 IN EFI_SYSTEM_TABLE
*SystemTable
104 // Install driver model protocol(s).
106 Status
= EfiLibInstallAllDriverProtocols (
109 &gWinNtSerialIoDriverBinding
,
111 &gWinNtSerialIoComponentName
,
115 ASSERT_EFI_ERROR (Status
);
124 WinNtSerialIoDriverBindingSupported (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE Handle
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
140 // TODO: This - add argument and description to function comment
141 // TODO: Handle - add argument and description to function comment
142 // TODO: RemainingDevicePath - add argument and description to function comment
143 // TODO: EFI_SUCCESS - add return value to function comment
144 // TODO: EFI_SUCCESS - add return value to function comment
147 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
148 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
149 UART_DEVICE_PATH
*UartNode
;
152 // Open the IO Abstraction(s) needed to perform the supported test
154 Status
= gBS
->OpenProtocol (
156 &gEfiDevicePathProtocolGuid
,
158 This
->DriverBindingHandle
,
160 EFI_OPEN_PROTOCOL_BY_DRIVER
162 if (Status
== EFI_ALREADY_STARTED
) {
166 if (EFI_ERROR (Status
)) {
172 &gEfiDevicePathProtocolGuid
,
173 This
->DriverBindingHandle
,
177 Status
= gBS
->OpenProtocol (
179 &gEfiWinNtIoProtocolGuid
,
181 This
->DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (Status
== EFI_ALREADY_STARTED
) {
189 if (EFI_ERROR (Status
)) {
194 // Make sure that the WinNt Thunk Protocol is valid
196 if (WinNtIo
->WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
197 Status
= EFI_UNSUPPORTED
;
202 // Check the GUID to see if this is a handle type the driver supports
204 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtSerialPortGuid
)) {
205 Status
= EFI_UNSUPPORTED
;
209 if (RemainingDevicePath
!= NULL
) {
210 Status
= EFI_UNSUPPORTED
;
211 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
212 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
213 UartNode
->Header
.SubType
!= MSG_UART_DP
||
214 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
217 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
220 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
223 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
226 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
229 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
232 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
235 Status
= EFI_SUCCESS
;
240 // Close the I/O Abstraction(s) used to perform the supported test
244 &gEfiWinNtIoProtocolGuid
,
245 This
->DriverBindingHandle
,
255 WinNtSerialIoDriverBindingStart (
256 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
257 IN EFI_HANDLE Handle
,
258 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
271 // TODO: This - add argument and description to function comment
272 // TODO: Handle - add argument and description to function comment
273 // TODO: RemainingDevicePath - add argument and description to function comment
274 // TODO: EFI_SUCCESS - add return value to function comment
275 // TODO: EFI_SUCCESS - add return value to function comment
278 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
279 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
281 UART_DEVICE_PATH Node
;
282 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
283 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
286 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
289 NtHandle
= INVALID_HANDLE_VALUE
;
292 // Grab the protocols we need
294 Status
= gBS
->OpenProtocol (
296 &gEfiDevicePathProtocolGuid
,
298 This
->DriverBindingHandle
,
300 EFI_OPEN_PROTOCOL_BY_DRIVER
302 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
307 // Grab the IO abstraction we need to get any work done
309 Status
= gBS
->OpenProtocol (
311 &gEfiWinNtIoProtocolGuid
,
313 This
->DriverBindingHandle
,
315 EFI_OPEN_PROTOCOL_BY_DRIVER
317 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
320 &gEfiDevicePathProtocolGuid
,
321 This
->DriverBindingHandle
,
327 if (Status
== EFI_ALREADY_STARTED
) {
329 if (RemainingDevicePath
== NULL
) {
334 // Make sure a child handle does not already exist. This driver can only
335 // produce one child per serial port.
337 Status
= gBS
->OpenProtocolInformation (
339 &gEfiWinNtIoProtocolGuid
,
343 if (EFI_ERROR (Status
)) {
347 Status
= EFI_ALREADY_STARTED
;
348 for (Index
= 0; Index
< EntryCount
; Index
++) {
349 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
350 Status
= gBS
->OpenProtocol (
351 OpenInfoBuffer
[Index
].ControllerHandle
,
352 &gEfiSerialIoProtocolGuid
,
354 This
->DriverBindingHandle
,
356 EFI_OPEN_PROTOCOL_GET_PROTOCOL
358 if (!EFI_ERROR (Status
)) {
359 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
360 Status
= SerialIo
->SetAttributes (
363 SerialIo
->Mode
->ReceiveFifoDepth
,
364 SerialIo
->Mode
->Timeout
,
374 FreePool (OpenInfoBuffer
);
379 // Check to see if we can access the hardware device. If it's Open in NT we
380 // will not get access.
382 NtHandle
= WinNtIo
->WinNtThunk
->CreateFile (
384 GENERIC_READ
| GENERIC_WRITE
,
391 if (NtHandle
== INVALID_HANDLE_VALUE
) {
392 Status
= EFI_DEVICE_ERROR
;
397 // Construct Private data
399 Private
= AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA
));
400 if (Private
== NULL
) {
405 // This signature must be valid before any member function is called
407 Private
->Signature
= WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
408 Private
->NtHandle
= NtHandle
;
409 Private
->ControllerHandle
= Handle
;
410 Private
->Handle
= NULL
;
411 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
412 Private
->ParentDevicePath
= ParentDevicePath
;
413 Private
->ControllerNameTable
= NULL
;
415 Private
->SoftwareLoopbackEnable
= FALSE
;
416 Private
->HardwareLoopbackEnable
= FALSE
;
417 Private
->HardwareFlowControl
= FALSE
;
418 Private
->Fifo
.First
= 0;
419 Private
->Fifo
.Last
= 0;
420 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
424 gWinNtSerialIoComponentName
.SupportedLanguages
,
425 &Private
->ControllerNameTable
,
429 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
430 Private
->SerialIo
.Reset
= WinNtSerialIoReset
;
431 Private
->SerialIo
.SetAttributes
= WinNtSerialIoSetAttributes
;
432 Private
->SerialIo
.SetControl
= WinNtSerialIoSetControl
;
433 Private
->SerialIo
.GetControl
= WinNtSerialIoGetControl
;
434 Private
->SerialIo
.Write
= WinNtSerialIoWrite
;
435 Private
->SerialIo
.Read
= WinNtSerialIoRead
;
436 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
438 if (RemainingDevicePath
!= NULL
) {
440 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
441 // already checked to make sure the RemainingDevicePath contains settings
442 // that we can support.
444 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
447 // Build the device path by appending the UART node to the ParentDevicePath
448 // from the WinNtIo handle. The Uart setings are zero here, since
449 // SetAttribute() will update them to match the default setings.
451 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
452 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
453 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
454 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
458 // Build the device path by appending the UART node to the ParentDevicePath
459 // from the WinNtIo handle. The Uart setings are zero here, since
460 // SetAttribute() will update them to match the current setings.
462 Private
->DevicePath
= AppendDevicePathNode (
464 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
466 if (Private
->DevicePath
== NULL
) {
467 Status
= EFI_OUT_OF_RESOURCES
;
472 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
474 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
475 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
476 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
477 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
478 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
479 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
480 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
483 // Issue a reset to initialize the COM port
485 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
486 if (EFI_ERROR (Status
)) {
491 // Create new child handle
493 Status
= gBS
->InstallMultipleProtocolInterfaces (
495 &gEfiSerialIoProtocolGuid
,
497 &gEfiDevicePathProtocolGuid
,
501 if (EFI_ERROR (Status
)) {
506 // Open For Child Device
508 Status
= gBS
->OpenProtocol (
510 &gEfiWinNtIoProtocolGuid
,
512 This
->DriverBindingHandle
,
514 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
516 if (EFI_ERROR (Status
)) {
524 // Use the Stop() function to free all resources allocated in Start()
526 if (Private
!= NULL
) {
527 if (Private
->Handle
!= NULL
) {
528 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
530 if (NtHandle
!= INVALID_HANDLE_VALUE
) {
531 Private
->WinNtThunk
->CloseHandle (NtHandle
);
534 if (Private
->DevicePath
!= NULL
) {
535 FreePool (Private
->DevicePath
);
538 FreeUnicodeStringTable (Private
->ControllerNameTable
);
544 This
->Stop (This
, Handle
, 0, NULL
);
552 WinNtSerialIoDriverBindingStop (
553 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
554 IN EFI_HANDLE Handle
,
555 IN UINTN NumberOfChildren
,
556 IN EFI_HANDLE
*ChildHandleBuffer
562 TODO: Add function description
566 This - TODO: add argument description
567 Handle - TODO: add argument description
568 NumberOfChildren - TODO: add argument description
569 ChildHandleBuffer - TODO: add argument description
573 EFI_DEVICE_ERROR - TODO: Add description for return value
574 EFI_SUCCESS - TODO: Add description for return value
580 BOOLEAN AllChildrenStopped
;
581 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
582 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
583 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
586 // Complete all outstanding transactions to Controller.
587 // Don't allow any new transaction to Controller to be started.
590 if (NumberOfChildren
== 0) {
592 // Close the bus driver
594 Status
= gBS
->CloseProtocol (
596 &gEfiWinNtIoProtocolGuid
,
597 This
->DriverBindingHandle
,
600 Status
= gBS
->CloseProtocol (
602 &gEfiDevicePathProtocolGuid
,
603 This
->DriverBindingHandle
,
609 AllChildrenStopped
= TRUE
;
611 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
612 Status
= gBS
->OpenProtocol (
613 ChildHandleBuffer
[Index
],
614 &gEfiSerialIoProtocolGuid
,
616 This
->DriverBindingHandle
,
618 EFI_OPEN_PROTOCOL_GET_PROTOCOL
620 if (!EFI_ERROR (Status
)) {
621 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
623 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
625 Status
= gBS
->CloseProtocol (
627 &gEfiWinNtIoProtocolGuid
,
628 This
->DriverBindingHandle
,
629 ChildHandleBuffer
[Index
]
632 Status
= gBS
->UninstallMultipleProtocolInterfaces (
633 ChildHandleBuffer
[Index
],
634 &gEfiSerialIoProtocolGuid
,
636 &gEfiDevicePathProtocolGuid
,
641 if (EFI_ERROR (Status
)) {
644 &gEfiWinNtIoProtocolGuid
,
646 This
->DriverBindingHandle
,
647 ChildHandleBuffer
[Index
],
648 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
651 Private
->WinNtThunk
->CloseHandle (Private
->NtHandle
);
653 FreePool (Private
->DevicePath
);
655 FreeUnicodeStringTable (Private
->ControllerNameTable
);
661 if (EFI_ERROR (Status
)) {
662 AllChildrenStopped
= FALSE
;
666 if (!AllChildrenStopped
) {
667 return EFI_DEVICE_ERROR
;
674 // Serial IO Protocol member functions
681 IN EFI_SERIAL_IO_PROTOCOL
*This
687 TODO: Add function description
691 This - TODO: add argument description
695 TODO: add return values
699 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
702 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
704 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
706 Private
->WinNtThunk
->PurgeComm (
708 PURGE_TXCLEAR
| PURGE_RXCLEAR
711 gBS
->RestoreTPL (Tpl
);
713 return This
->SetAttributes (
715 This
->Mode
->BaudRate
,
716 This
->Mode
->ReceiveFifoDepth
,
719 (UINT8
) This
->Mode
->DataBits
,
727 WinNtSerialIoSetAttributes (
728 IN EFI_SERIAL_IO_PROTOCOL
*This
,
730 IN UINT32 ReceiveFifoDepth
,
732 IN EFI_PARITY_TYPE Parity
,
734 IN EFI_STOP_BITS_TYPE StopBits
740 This function is used to set the attributes.
744 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
745 BaudRate - The Baud rate of the serial device.
746 ReceiveFifoDepth - The request depth of fifo on receive side.
747 Timeout - the request timeout for a single charact.
748 Parity - The type of parity used in serial device.
749 DataBits - Number of deata bits used in serial device.
750 StopBits - Number of stop bits used in serial device.
758 // TODO: EFI_SUCCESS - add return value to function comment
759 // TODO: EFI_DEVICE_ERROR - add return value to function comment
760 // TODO: EFI_DEVICE_ERROR - add return value to function comment
761 // TODO: EFI_DEVICE_ERROR - add return value to function comment
762 // TODO: EFI_SUCCESS - add return value to function comment
763 // TODO: EFI_DEVICE_ERROR - add return value to function comment
764 // TODO: EFI_SUCCESS - add return value to function comment
767 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
768 COMMTIMEOUTS PortTimeOuts
;
771 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
774 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
776 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
779 // Some of our arguments have defaults if a null value is passed in, and
780 // we must set the default values if a null argument is passed in.
783 BaudRate
= SERIAL_BAUD_DEFAULT
;
786 if (ReceiveFifoDepth
== 0) {
787 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
791 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
794 if (Parity
== DefaultParity
) {
799 DataBits
= SERIAL_DATABITS_DEFAULT
;
802 if (StopBits
== DefaultStopBits
) {
803 StopBits
= OneStopBit
;
806 // See if the new attributes already match the current attributes
808 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
809 Private
->UartDevicePath
.DataBits
== DataBits
&&
810 Private
->UartDevicePath
.Parity
== Parity
&&
811 Private
->UartDevicePath
.StopBits
== StopBits
&&
812 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
813 Private
->SerialIoMode
.Timeout
== Timeout
) {
814 gBS
->RestoreTPL(Tpl
);
819 // Get current values from NT
821 ZeroMem (&Private
->NtDCB
, sizeof (DCB
));
822 Private
->NtDCB
.DCBlength
= sizeof (DCB
);
824 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Private
->NtDCB
)) {
825 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
826 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: GetCommState %d\n", Private
->NtError
));
827 gBS
->RestoreTPL (Tpl
);
828 return EFI_DEVICE_ERROR
;
832 // Map EFI com setting to NT
834 Private
->NtDCB
.BaudRate
= ConvertBaud2Nt (BaudRate
);
835 Private
->NtDCB
.ByteSize
= ConvertData2Nt (DataBits
);
836 Private
->NtDCB
.Parity
= ConvertParity2Nt (Parity
);
837 Private
->NtDCB
.StopBits
= ConvertStop2Nt (StopBits
);
839 Private
->NtDCB
.fBinary
= TRUE
;
840 Private
->NtDCB
.fParity
= Private
->NtDCB
.Parity
== NOPARITY
? FALSE
: TRUE
;
841 Private
->NtDCB
.fOutxCtsFlow
= FALSE
;
842 Private
->NtDCB
.fOutxDsrFlow
= FALSE
;
843 Private
->NtDCB
.fDtrControl
= DTR_CONTROL_ENABLE
;
844 Private
->NtDCB
.fDsrSensitivity
= FALSE
;
845 Private
->NtDCB
.fOutX
= FALSE
;
846 Private
->NtDCB
.fInX
= FALSE
;
847 Private
->NtDCB
.fRtsControl
= RTS_CONTROL_ENABLE
;
848 Private
->NtDCB
.fNull
= FALSE
;
853 Result
= Private
->WinNtThunk
->SetCommState (Private
->NtHandle
, &Private
->NtDCB
);
855 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
856 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommState %d\n", Private
->NtError
));
857 gBS
->RestoreTPL (Tpl
);
858 return EFI_DEVICE_ERROR
;
862 // Set com port read/write timeout values
864 ConvertedTime
= ConvertTime2Nt (Timeout
);
865 PortTimeOuts
.ReadIntervalTimeout
= MAXDWORD
;
866 PortTimeOuts
.ReadTotalTimeoutMultiplier
= 0;
867 PortTimeOuts
.ReadTotalTimeoutConstant
= ConvertedTime
;
868 PortTimeOuts
.WriteTotalTimeoutMultiplier
= ConvertedTime
== 0 ? 1 : ConvertedTime
;
869 PortTimeOuts
.WriteTotalTimeoutConstant
= 0;
871 if (!Private
->WinNtThunk
->SetCommTimeouts (Private
->NtHandle
, &PortTimeOuts
)) {
872 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
873 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommTimeouts %d\n", Private
->NtError
));
874 gBS
->RestoreTPL (Tpl
);
875 return EFI_DEVICE_ERROR
;
881 Private
->SerialIoMode
.BaudRate
= BaudRate
;
882 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
883 Private
->SerialIoMode
.Timeout
= Timeout
;
884 Private
->SerialIoMode
.Parity
= Parity
;
885 Private
->SerialIoMode
.DataBits
= DataBits
;
886 Private
->SerialIoMode
.StopBits
= StopBits
;
889 // See if Device Path Node has actually changed
891 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
892 Private
->UartDevicePath
.DataBits
== DataBits
&&
893 Private
->UartDevicePath
.Parity
== Parity
&&
894 Private
->UartDevicePath
.StopBits
== StopBits
) {
895 gBS
->RestoreTPL(Tpl
);
900 // Update the device path
902 Private
->UartDevicePath
.BaudRate
= BaudRate
;
903 Private
->UartDevicePath
.DataBits
= DataBits
;
904 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
905 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
907 NewDevicePath
= AppendDevicePathNode (
908 Private
->ParentDevicePath
,
909 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
911 if (NewDevicePath
== NULL
) {
912 gBS
->RestoreTPL (Tpl
);
913 return EFI_DEVICE_ERROR
;
916 if (Private
->Handle
!= NULL
) {
917 Status
= gBS
->ReinstallProtocolInterface (
919 &gEfiDevicePathProtocolGuid
,
923 if (EFI_ERROR (Status
)) {
924 gBS
->RestoreTPL (Tpl
);
929 if (Private
->DevicePath
!= NULL
) {
930 FreePool (Private
->DevicePath
);
933 Private
->DevicePath
= NewDevicePath
;
935 gBS
->RestoreTPL (Tpl
);
943 WinNtSerialIoSetControl (
944 IN EFI_SERIAL_IO_PROTOCOL
*This
,
951 TODO: Add function description
955 This - TODO: add argument description
956 Control - TODO: add argument description
960 EFI_DEVICE_ERROR - TODO: Add description for return value
961 EFI_DEVICE_ERROR - TODO: Add description for return value
962 EFI_SUCCESS - TODO: Add description for return value
966 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
971 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
973 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
975 Result
= Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
);
978 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
979 DEBUG ((EFI_D_ERROR
, "SerialSetControl: GetCommState %d\n", Private
->NtError
));
980 gBS
->RestoreTPL (Tpl
);
981 return EFI_DEVICE_ERROR
;
984 Dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
985 Dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
986 Private
->HardwareFlowControl
= FALSE
;
987 Private
->SoftwareLoopbackEnable
= FALSE
;
988 Private
->HardwareLoopbackEnable
= FALSE
;
990 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
991 Dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
994 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
995 Dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
998 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
999 Private
->HardwareFlowControl
= TRUE
;
1002 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1003 Private
->SoftwareLoopbackEnable
= TRUE
;
1006 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1007 Private
->HardwareLoopbackEnable
= TRUE
;
1010 Result
= Private
->WinNtThunk
->SetCommState (
1016 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1017 DEBUG ((EFI_D_ERROR
, "SerialSetControl: SetCommState %d\n", Private
->NtError
));
1018 gBS
->RestoreTPL (Tpl
);
1019 return EFI_DEVICE_ERROR
;
1022 gBS
->RestoreTPL (Tpl
);
1030 WinNtSerialIoGetControl (
1031 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1036 Routine Description:
1038 TODO: Add function description
1042 This - TODO: add argument description
1043 Control - TODO: add argument description
1047 EFI_DEVICE_ERROR - TODO: Add description for return value
1048 EFI_DEVICE_ERROR - TODO: Add description for return value
1049 EFI_DEVICE_ERROR - TODO: Add description for return value
1050 EFI_SUCCESS - TODO: Add description for return value
1054 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1061 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1063 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1068 if (!Private
->WinNtThunk
->GetCommModemStatus (Private
->NtHandle
, &ModemStatus
)) {
1069 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1070 gBS
->RestoreTPL (Tpl
);
1071 return EFI_DEVICE_ERROR
;
1075 if (ModemStatus
& MS_CTS_ON
) {
1076 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1079 if (ModemStatus
& MS_DSR_ON
) {
1080 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1083 if (ModemStatus
& MS_RING_ON
) {
1084 Bits
|= EFI_SERIAL_RING_INDICATE
;
1087 if (ModemStatus
& MS_RLSD_ON
) {
1088 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1094 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
)) {
1095 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1096 DEBUG ((EFI_D_ERROR
, "SerialGetControl: GetCommState %d\n", Private
->NtError
));
1097 gBS
->RestoreTPL (Tpl
);
1098 return EFI_DEVICE_ERROR
;
1101 if (Dcb
.fDtrControl
== DTR_CONTROL_ENABLE
) {
1102 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1105 if (Dcb
.fRtsControl
== RTS_CONTROL_ENABLE
) {
1106 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1109 if (Private
->HardwareFlowControl
) {
1110 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1113 if (Private
->SoftwareLoopbackEnable
) {
1114 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1117 if (Private
->HardwareLoopbackEnable
) {
1118 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1122 // Get input buffer status
1124 if (!Private
->WinNtThunk
->ClearCommError (Private
->NtHandle
, &Errors
, &Private
->NtComStatus
)) {
1125 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1126 DEBUG ((EFI_D_ERROR
, "SerialGetControl: ClearCommError %d\n", Private
->NtError
));
1127 gBS
->RestoreTPL (Tpl
);
1128 return EFI_DEVICE_ERROR
;
1131 if (Private
->NtComStatus
.cbInQue
== 0) {
1132 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1137 gBS
->RestoreTPL (Tpl
);
1145 WinNtSerialIoWrite (
1146 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1147 IN OUT UINTN
*BufferSize
,
1152 Routine Description:
1154 TODO: Add function description
1158 This - TODO: add argument description
1159 BufferSize - TODO: add argument description
1160 Buffer - TODO: add argument description
1164 EFI_DEVICE_ERROR - TODO: Add description for return value
1165 EFI_SUCCESS - TODO: Add description for return value
1169 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1171 UINTN TotalBytesWritten
;
1179 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1181 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1183 ByteBuffer
= (UINT8
*) Buffer
;
1184 TotalBytesWritten
= 0;
1186 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1187 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1188 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1189 TotalBytesWritten
++;
1195 BytesToGo
= (DWORD
) (*BufferSize
);
1198 if (Private
->HardwareFlowControl
) {
1202 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1203 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1204 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1210 Result
= Private
->WinNtThunk
->WriteFile (
1212 &ByteBuffer
[TotalBytesWritten
],
1218 if (Private
->HardwareFlowControl
) {
1222 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1223 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1224 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1227 TotalBytesWritten
+= BytesWritten
;
1228 BytesToGo
-= BytesWritten
;
1230 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1231 DEBUG ((EFI_D_ERROR
, "SerialWrite: FileWrite %d\n", Private
->NtError
));
1232 *BufferSize
= TotalBytesWritten
;
1233 gBS
->RestoreTPL (Tpl
);
1234 return EFI_DEVICE_ERROR
;
1236 } while (BytesToGo
> 0);
1239 *BufferSize
= TotalBytesWritten
;
1241 gBS
->RestoreTPL (Tpl
);
1250 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1251 IN OUT UINTN
*BufferSize
,
1256 Routine Description:
1258 TODO: Add function description
1262 This - TODO: add argument description
1263 BufferSize - TODO: add argument description
1264 Buffer - TODO: add argument description
1268 EFI_DEVICE_ERROR - TODO: Add description for return value
1272 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1281 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1283 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1288 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1289 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1290 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1291 ((UINT8
*) Buffer
)[Index
] = Data
;
1298 if (Private
->HardwareFlowControl
) {
1299 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1300 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1301 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1304 Result
= Private
->WinNtThunk
->ReadFile (
1307 (DWORD
) *BufferSize
,
1312 if (Private
->HardwareFlowControl
) {
1313 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1314 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1315 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1319 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1320 gBS
->RestoreTPL (Tpl
);
1321 return EFI_DEVICE_ERROR
;
1325 if (BytesRead
!= *BufferSize
) {
1326 Status
= EFI_TIMEOUT
;
1328 Status
= EFI_SUCCESS
;
1331 *BufferSize
= (UINTN
) BytesRead
;
1333 gBS
->RestoreTPL (Tpl
);
1340 IN SERIAL_DEV_FIFO
*Fifo
1344 Routine Description:
1345 Detect whether specific FIFO is full or not
1348 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1351 TRUE: the FIFO is full
1352 FALSE: the FIFO is not full
1356 if (Fifo
->Surplus
== 0) {
1364 IsaSerialFifoEmpty (
1365 IN SERIAL_DEV_FIFO
*Fifo
1369 Routine Description:
1370 Detect whether specific FIFO is empty or not
1373 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1376 TRUE: the FIFO is empty
1377 FALSE: the FIFO is not empty
1381 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1390 IN SERIAL_DEV_FIFO
*Fifo
,
1395 Routine Description:
1396 Add data to specific FIFO
1399 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1400 Data UINT8: the data added to FIFO
1403 EFI_SUCCESS: Add data to specific FIFO successfully
1404 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1407 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1410 // if FIFO full can not add data
1412 if (IsaSerialFifoFull (Fifo
)) {
1413 return EFI_OUT_OF_RESOURCES
;
1417 // FIFO is not full can add data
1419 Fifo
->Data
[Fifo
->Last
] = Data
;
1422 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1430 IsaSerialFifoRemove (
1431 IN SERIAL_DEV_FIFO
*Fifo
,
1436 Routine Description:
1437 Remove data from specific FIFO
1440 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1441 Data UINT8*: the data removed from FIFO
1444 EFI_SUCCESS: Remove data from specific FIFO successfully
1445 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1448 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1451 // if FIFO is empty, no data can remove
1453 if (IsaSerialFifoEmpty (Fifo
)) {
1454 return EFI_OUT_OF_RESOURCES
;
1458 // FIFO is not empty, can remove data
1460 *Data
= Fifo
->Data
[Fifo
->First
];
1463 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {