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
);
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 // Open the IO Abstraction(s) needed to perform the supported test
132 Status
= gBS
->OpenProtocol (
134 &gEfiDevicePathProtocolGuid
,
135 (VOID
**) &ParentDevicePath
,
136 This
->DriverBindingHandle
,
138 EFI_OPEN_PROTOCOL_BY_DRIVER
140 if (Status
== EFI_ALREADY_STARTED
) {
144 if (EFI_ERROR (Status
)) {
150 &gEfiDevicePathProtocolGuid
,
151 This
->DriverBindingHandle
,
155 Status
= gBS
->OpenProtocol (
157 &gEfiWinNtIoProtocolGuid
,
159 This
->DriverBindingHandle
,
161 EFI_OPEN_PROTOCOL_BY_DRIVER
163 if (Status
== EFI_ALREADY_STARTED
) {
167 if (EFI_ERROR (Status
)) {
172 // Make sure that the WinNt Thunk Protocol is valid
174 if (WinNtIo
->WinNtThunk
->Signature
!= EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE
) {
175 Status
= EFI_UNSUPPORTED
;
180 // Check the GUID to see if this is a handle type the driver supports
182 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtSerialPortGuid
)) {
183 Status
= EFI_UNSUPPORTED
;
187 if (RemainingDevicePath
!= NULL
) {
188 Status
= EFI_UNSUPPORTED
;
189 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
190 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
191 UartNode
->Header
.SubType
!= MSG_UART_DP
||
192 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
195 if ( UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
198 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
201 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
204 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
207 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
210 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
213 Status
= EFI_SUCCESS
;
218 // Close the I/O Abstraction(s) used to perform the supported test
222 &gEfiWinNtIoProtocolGuid
,
223 This
->DriverBindingHandle
,
232 WinNtSerialIoDriverBindingStart (
233 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
234 IN EFI_HANDLE Handle
,
235 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
248 // TODO: This - add argument and description to function comment
249 // TODO: Handle - add argument and description to function comment
250 // TODO: RemainingDevicePath - add argument and description to function comment
251 // TODO: EFI_SUCCESS - add return value to function comment
252 // TODO: EFI_SUCCESS - add return value to function comment
255 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
256 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
258 UART_DEVICE_PATH Node
;
259 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
260 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
263 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
266 NtHandle
= INVALID_HANDLE_VALUE
;
269 // Grab the protocols we need
271 Status
= gBS
->OpenProtocol (
273 &gEfiDevicePathProtocolGuid
,
274 (VOID
**) &ParentDevicePath
,
275 This
->DriverBindingHandle
,
277 EFI_OPEN_PROTOCOL_BY_DRIVER
279 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
284 // Grab the IO abstraction we need to get any work done
286 Status
= gBS
->OpenProtocol (
288 &gEfiWinNtIoProtocolGuid
,
290 This
->DriverBindingHandle
,
292 EFI_OPEN_PROTOCOL_BY_DRIVER
294 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
297 &gEfiDevicePathProtocolGuid
,
298 This
->DriverBindingHandle
,
304 if (Status
== EFI_ALREADY_STARTED
) {
306 if (RemainingDevicePath
== NULL
) {
311 // Make sure a child handle does not already exist. This driver can only
312 // produce one child per serial port.
314 Status
= gBS
->OpenProtocolInformation (
316 &gEfiWinNtIoProtocolGuid
,
320 if (EFI_ERROR (Status
)) {
324 Status
= EFI_ALREADY_STARTED
;
325 for (Index
= 0; Index
< EntryCount
; Index
++) {
326 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
327 Status
= gBS
->OpenProtocol (
328 OpenInfoBuffer
[Index
].ControllerHandle
,
329 &gEfiSerialIoProtocolGuid
,
331 This
->DriverBindingHandle
,
333 EFI_OPEN_PROTOCOL_GET_PROTOCOL
335 if (!EFI_ERROR (Status
)) {
336 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
337 Status
= SerialIo
->SetAttributes (
340 SerialIo
->Mode
->ReceiveFifoDepth
,
341 SerialIo
->Mode
->Timeout
,
342 (EFI_PARITY_TYPE
)Node
.Parity
,
344 (EFI_STOP_BITS_TYPE
)Node
.StopBits
351 FreePool (OpenInfoBuffer
);
356 // Check to see if we can access the hardware device. If it's Open in NT we
357 // will not get access.
359 NtHandle
= WinNtIo
->WinNtThunk
->CreateFile (
361 GENERIC_READ
| GENERIC_WRITE
,
368 if (NtHandle
== INVALID_HANDLE_VALUE
) {
369 Status
= EFI_DEVICE_ERROR
;
374 // Construct Private data
376 Private
= AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA
));
377 if (Private
== NULL
) {
382 // This signature must be valid before any member function is called
384 Private
->Signature
= WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
385 Private
->NtHandle
= NtHandle
;
386 Private
->ControllerHandle
= Handle
;
387 Private
->Handle
= NULL
;
388 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
389 Private
->ParentDevicePath
= ParentDevicePath
;
390 Private
->ControllerNameTable
= NULL
;
392 Private
->SoftwareLoopbackEnable
= FALSE
;
393 Private
->HardwareLoopbackEnable
= FALSE
;
394 Private
->HardwareFlowControl
= FALSE
;
395 Private
->Fifo
.First
= 0;
396 Private
->Fifo
.Last
= 0;
397 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
401 gWinNtSerialIoComponentName
.SupportedLanguages
,
402 &Private
->ControllerNameTable
,
408 gWinNtSerialIoComponentName2
.SupportedLanguages
,
409 &Private
->ControllerNameTable
,
415 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
416 Private
->SerialIo
.Reset
= WinNtSerialIoReset
;
417 Private
->SerialIo
.SetAttributes
= WinNtSerialIoSetAttributes
;
418 Private
->SerialIo
.SetControl
= WinNtSerialIoSetControl
;
419 Private
->SerialIo
.GetControl
= WinNtSerialIoGetControl
;
420 Private
->SerialIo
.Write
= WinNtSerialIoWrite
;
421 Private
->SerialIo
.Read
= WinNtSerialIoRead
;
422 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
424 if (RemainingDevicePath
!= NULL
) {
426 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
427 // already checked to make sure the RemainingDevicePath contains settings
428 // that we can support.
430 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
433 // Build the device path by appending the UART node to the ParentDevicePath
434 // from the WinNtIo handle. The Uart setings are zero here, since
435 // SetAttribute() will update them to match the default setings.
437 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
438 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
439 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
440 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
444 // Build the device path by appending the UART node to the ParentDevicePath
445 // from the WinNtIo handle. The Uart setings are zero here, since
446 // SetAttribute() will update them to match the current setings.
448 Private
->DevicePath
= AppendDevicePathNode (
450 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
452 if (Private
->DevicePath
== NULL
) {
453 Status
= EFI_OUT_OF_RESOURCES
;
458 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
460 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
461 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
462 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
463 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
464 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
465 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
466 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
469 // Issue a reset to initialize the COM port
471 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
472 if (EFI_ERROR (Status
)) {
477 // Create new child handle
479 Status
= gBS
->InstallMultipleProtocolInterfaces (
481 &gEfiSerialIoProtocolGuid
,
483 &gEfiDevicePathProtocolGuid
,
487 if (EFI_ERROR (Status
)) {
492 // Open For Child Device
494 Status
= gBS
->OpenProtocol (
496 &gEfiWinNtIoProtocolGuid
,
498 This
->DriverBindingHandle
,
500 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
502 if (EFI_ERROR (Status
)) {
510 // Use the Stop() function to free all resources allocated in Start()
512 if (Private
!= NULL
) {
513 if (Private
->Handle
!= NULL
) {
514 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
516 if (NtHandle
!= INVALID_HANDLE_VALUE
) {
517 Private
->WinNtThunk
->CloseHandle (NtHandle
);
520 if (Private
->DevicePath
!= NULL
) {
521 FreePool (Private
->DevicePath
);
524 FreeUnicodeStringTable (Private
->ControllerNameTable
);
530 This
->Stop (This
, Handle
, 0, NULL
);
537 WinNtSerialIoDriverBindingStop (
538 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
539 IN EFI_HANDLE Handle
,
540 IN UINTN NumberOfChildren
,
541 IN EFI_HANDLE
*ChildHandleBuffer
547 TODO: Add function description
551 This - TODO: add argument description
552 Handle - TODO: add argument description
553 NumberOfChildren - TODO: add argument description
554 ChildHandleBuffer - TODO: add argument description
558 EFI_DEVICE_ERROR - TODO: Add description for return value
559 EFI_SUCCESS - TODO: Add description for return value
565 BOOLEAN AllChildrenStopped
;
566 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
567 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
568 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
571 // Complete all outstanding transactions to Controller.
572 // Don't allow any new transaction to Controller to be started.
575 if (NumberOfChildren
== 0) {
577 // Close the bus driver
579 Status
= gBS
->CloseProtocol (
581 &gEfiWinNtIoProtocolGuid
,
582 This
->DriverBindingHandle
,
585 Status
= gBS
->CloseProtocol (
587 &gEfiDevicePathProtocolGuid
,
588 This
->DriverBindingHandle
,
594 AllChildrenStopped
= TRUE
;
596 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
597 Status
= gBS
->OpenProtocol (
598 ChildHandleBuffer
[Index
],
599 &gEfiSerialIoProtocolGuid
,
601 This
->DriverBindingHandle
,
603 EFI_OPEN_PROTOCOL_GET_PROTOCOL
605 if (!EFI_ERROR (Status
)) {
606 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
608 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
610 Status
= gBS
->CloseProtocol (
612 &gEfiWinNtIoProtocolGuid
,
613 This
->DriverBindingHandle
,
614 ChildHandleBuffer
[Index
]
617 Status
= gBS
->UninstallMultipleProtocolInterfaces (
618 ChildHandleBuffer
[Index
],
619 &gEfiSerialIoProtocolGuid
,
621 &gEfiDevicePathProtocolGuid
,
626 if (EFI_ERROR (Status
)) {
629 &gEfiWinNtIoProtocolGuid
,
631 This
->DriverBindingHandle
,
632 ChildHandleBuffer
[Index
],
633 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
636 Private
->WinNtThunk
->CloseHandle (Private
->NtHandle
);
638 FreePool (Private
->DevicePath
);
640 FreeUnicodeStringTable (Private
->ControllerNameTable
);
646 if (EFI_ERROR (Status
)) {
647 AllChildrenStopped
= FALSE
;
651 if (!AllChildrenStopped
) {
652 return EFI_DEVICE_ERROR
;
659 // Serial IO Protocol member functions
665 IN EFI_SERIAL_IO_PROTOCOL
*This
671 TODO: Add function description
675 This - TODO: add argument description
679 TODO: add return values
683 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
686 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
688 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
690 Private
->WinNtThunk
->PurgeComm (
692 PURGE_TXCLEAR
| PURGE_RXCLEAR
695 gBS
->RestoreTPL (Tpl
);
697 return This
->SetAttributes (
699 This
->Mode
->BaudRate
,
700 This
->Mode
->ReceiveFifoDepth
,
702 (EFI_PARITY_TYPE
)This
->Mode
->Parity
,
703 (UINT8
) This
->Mode
->DataBits
,
704 (EFI_STOP_BITS_TYPE
)This
->Mode
->StopBits
710 WinNtSerialIoSetAttributes (
711 IN EFI_SERIAL_IO_PROTOCOL
*This
,
713 IN UINT32 ReceiveFifoDepth
,
715 IN EFI_PARITY_TYPE Parity
,
717 IN EFI_STOP_BITS_TYPE StopBits
723 This function is used to set the attributes.
727 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
728 BaudRate - The Baud rate of the serial device.
729 ReceiveFifoDepth - The request depth of fifo on receive side.
730 Timeout - the request timeout for a single charact.
731 Parity - The type of parity used in serial device.
732 DataBits - Number of deata bits used in serial device.
733 StopBits - Number of stop bits used in serial device.
741 // TODO: EFI_SUCCESS - add return value to function comment
742 // TODO: EFI_DEVICE_ERROR - add return value to function comment
743 // TODO: EFI_DEVICE_ERROR - add return value to function comment
744 // TODO: EFI_DEVICE_ERROR - add return value to function comment
745 // TODO: EFI_SUCCESS - add return value to function comment
746 // TODO: EFI_DEVICE_ERROR - add return value to function comment
747 // TODO: EFI_SUCCESS - add return value to function comment
751 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
752 COMMTIMEOUTS PortTimeOuts
;
755 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
758 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
761 // Some of our arguments have defaults if a null value is passed in, and
762 // we must set the default values if a null argument is passed in.
765 BaudRate
= FixedPcdGet64 (PcdUartDefaultBaudRate
);
768 if (ReceiveFifoDepth
== 0) {
769 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
773 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
776 if (Parity
== DefaultParity
) {
777 Parity
= (EFI_PARITY_TYPE
) (FixedPcdGet8 (PcdUartDefaultParity
));
781 DataBits
= FixedPcdGet8 (PcdUartDefaultDataBits
);
784 if (StopBits
== DefaultStopBits
) {
785 StopBits
= (EFI_STOP_BITS_TYPE
) FixedPcdGet8 (PcdUartDefaultStopBits
);
789 // Make sure all parameters are valid
791 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
792 return EFI_INVALID_PARAMETER
;
796 //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter
799 for (Index
= 1; Index
< (sizeof (mBaudRateCurrentSupport
) / sizeof (mBaudRateCurrentSupport
[0])); Index
++) {
800 if (BaudRate
< mBaudRateCurrentSupport
[Index
]) {
801 BaudRate
= mBaudRateCurrentSupport
[Index
-1];
806 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
807 return EFI_INVALID_PARAMETER
;
810 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
811 return EFI_INVALID_PARAMETER
;
814 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
815 return EFI_INVALID_PARAMETER
;
818 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
819 return EFI_INVALID_PARAMETER
;
823 // Now we only support DataBits=7,8.
825 if ((DataBits
< 7) || (DataBits
> 8)) {
826 return EFI_INVALID_PARAMETER
;
830 // Now we only support DataBits=7,8.
831 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits.
833 if (StopBits
== OneFiveStopBits
) {
834 return EFI_INVALID_PARAMETER
;
838 // See if the new attributes already match the current attributes
840 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
841 Private
->UartDevicePath
.DataBits
== DataBits
&&
842 Private
->UartDevicePath
.Parity
== Parity
&&
843 Private
->UartDevicePath
.StopBits
== StopBits
&&
844 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
845 Private
->SerialIoMode
.Timeout
== Timeout
) {
849 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
852 // Get current values from NT
854 ZeroMem (&Private
->NtDCB
, sizeof (DCB
));
855 Private
->NtDCB
.DCBlength
= sizeof (DCB
);
857 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Private
->NtDCB
)) {
858 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
859 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: GetCommState %d\n", Private
->NtError
));
860 gBS
->RestoreTPL (Tpl
);
861 return EFI_DEVICE_ERROR
;
865 // Map EFI com setting to NT
867 Private
->NtDCB
.BaudRate
= ConvertBaud2Nt (BaudRate
);
868 Private
->NtDCB
.ByteSize
= ConvertData2Nt (DataBits
);
869 Private
->NtDCB
.Parity
= ConvertParity2Nt (Parity
);
870 Private
->NtDCB
.StopBits
= ConvertStop2Nt (StopBits
);
872 Private
->NtDCB
.fBinary
= TRUE
;
873 Private
->NtDCB
.fParity
= Private
->NtDCB
.Parity
== NOPARITY
? FALSE
: TRUE
;
874 Private
->NtDCB
.fOutxCtsFlow
= FALSE
;
875 Private
->NtDCB
.fOutxDsrFlow
= FALSE
;
876 Private
->NtDCB
.fDtrControl
= DTR_CONTROL_ENABLE
;
877 Private
->NtDCB
.fDsrSensitivity
= FALSE
;
878 Private
->NtDCB
.fOutX
= FALSE
;
879 Private
->NtDCB
.fInX
= FALSE
;
880 Private
->NtDCB
.fRtsControl
= RTS_CONTROL_ENABLE
;
881 Private
->NtDCB
.fNull
= FALSE
;
886 Result
= Private
->WinNtThunk
->SetCommState (Private
->NtHandle
, &Private
->NtDCB
);
888 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
889 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommState %d\n", Private
->NtError
));
890 gBS
->RestoreTPL (Tpl
);
891 return EFI_DEVICE_ERROR
;
895 // Set com port read/write timeout values
897 ConvertedTime
= ConvertTime2Nt (Timeout
);
898 PortTimeOuts
.ReadIntervalTimeout
= MAXDWORD
;
899 PortTimeOuts
.ReadTotalTimeoutMultiplier
= 0;
900 PortTimeOuts
.ReadTotalTimeoutConstant
= ConvertedTime
;
901 PortTimeOuts
.WriteTotalTimeoutMultiplier
= ConvertedTime
== 0 ? 1 : ConvertedTime
;
902 PortTimeOuts
.WriteTotalTimeoutConstant
= 0;
904 if (!Private
->WinNtThunk
->SetCommTimeouts (Private
->NtHandle
, &PortTimeOuts
)) {
905 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
906 DEBUG ((EFI_D_ERROR
, "SerialSetAttributes: SetCommTimeouts %d\n", Private
->NtError
));
907 gBS
->RestoreTPL (Tpl
);
908 return EFI_DEVICE_ERROR
;
914 Private
->SerialIoMode
.BaudRate
= BaudRate
;
915 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
916 Private
->SerialIoMode
.Timeout
= Timeout
;
917 Private
->SerialIoMode
.Parity
= Parity
;
918 Private
->SerialIoMode
.DataBits
= DataBits
;
919 Private
->SerialIoMode
.StopBits
= StopBits
;
922 // See if Device Path Node has actually changed
924 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
925 Private
->UartDevicePath
.DataBits
== DataBits
&&
926 Private
->UartDevicePath
.Parity
== Parity
&&
927 Private
->UartDevicePath
.StopBits
== StopBits
) {
928 gBS
->RestoreTPL(Tpl
);
933 // Update the device path
935 Private
->UartDevicePath
.BaudRate
= BaudRate
;
936 Private
->UartDevicePath
.DataBits
= DataBits
;
937 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
938 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
940 NewDevicePath
= AppendDevicePathNode (
941 Private
->ParentDevicePath
,
942 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
944 if (NewDevicePath
== NULL
) {
945 gBS
->RestoreTPL (Tpl
);
946 return EFI_DEVICE_ERROR
;
949 if (Private
->Handle
!= NULL
) {
950 Status
= gBS
->ReinstallProtocolInterface (
952 &gEfiDevicePathProtocolGuid
,
956 if (EFI_ERROR (Status
)) {
957 gBS
->RestoreTPL (Tpl
);
962 if (Private
->DevicePath
!= NULL
) {
963 FreePool (Private
->DevicePath
);
966 Private
->DevicePath
= NewDevicePath
;
968 gBS
->RestoreTPL (Tpl
);
975 WinNtSerialIoSetControl (
976 IN EFI_SERIAL_IO_PROTOCOL
*This
,
983 TODO: Add function description
987 This - TODO: add argument description
988 Control - TODO: add argument description
992 EFI_DEVICE_ERROR - TODO: Add description for return value
993 EFI_DEVICE_ERROR - TODO: Add description for return value
994 EFI_SUCCESS - TODO: Add description for return value
998 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1004 // first determine the parameter is invalid
1006 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1007 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1008 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1009 return EFI_UNSUPPORTED
;
1012 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1014 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1016 Result
= Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
);
1019 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1020 DEBUG ((EFI_D_ERROR
, "SerialSetControl: GetCommState %d\n", Private
->NtError
));
1021 gBS
->RestoreTPL (Tpl
);
1022 return EFI_DEVICE_ERROR
;
1025 Dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
1026 Dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
1027 Private
->HardwareFlowControl
= FALSE
;
1028 Private
->SoftwareLoopbackEnable
= FALSE
;
1029 Private
->HardwareLoopbackEnable
= FALSE
;
1031 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1032 Dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
1035 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1036 Dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
1039 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1040 Private
->HardwareFlowControl
= TRUE
;
1043 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1044 Private
->SoftwareLoopbackEnable
= TRUE
;
1047 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1048 Private
->HardwareLoopbackEnable
= TRUE
;
1051 Result
= Private
->WinNtThunk
->SetCommState (
1057 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1058 DEBUG ((EFI_D_ERROR
, "SerialSetControl: SetCommState %d\n", Private
->NtError
));
1059 gBS
->RestoreTPL (Tpl
);
1060 return EFI_DEVICE_ERROR
;
1063 gBS
->RestoreTPL (Tpl
);
1070 WinNtSerialIoGetControl (
1071 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1076 Routine Description:
1078 TODO: Add function description
1082 This - TODO: add argument description
1083 Control - TODO: add argument description
1087 EFI_DEVICE_ERROR - TODO: Add description for return value
1088 EFI_DEVICE_ERROR - TODO: Add description for return value
1089 EFI_DEVICE_ERROR - TODO: Add description for return value
1090 EFI_SUCCESS - TODO: Add description for return value
1094 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1101 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1103 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1108 if (!Private
->WinNtThunk
->GetCommModemStatus (Private
->NtHandle
, &ModemStatus
)) {
1109 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1110 gBS
->RestoreTPL (Tpl
);
1111 return EFI_DEVICE_ERROR
;
1115 if (ModemStatus
& MS_CTS_ON
) {
1116 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1119 if (ModemStatus
& MS_DSR_ON
) {
1120 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1123 if (ModemStatus
& MS_RING_ON
) {
1124 Bits
|= EFI_SERIAL_RING_INDICATE
;
1127 if (ModemStatus
& MS_RLSD_ON
) {
1128 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1134 if (!Private
->WinNtThunk
->GetCommState (Private
->NtHandle
, &Dcb
)) {
1135 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1136 DEBUG ((EFI_D_ERROR
, "SerialGetControl: GetCommState %d\n", Private
->NtError
));
1137 gBS
->RestoreTPL (Tpl
);
1138 return EFI_DEVICE_ERROR
;
1141 if (Dcb
.fDtrControl
== DTR_CONTROL_ENABLE
) {
1142 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1145 if (Dcb
.fRtsControl
== RTS_CONTROL_ENABLE
) {
1146 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1149 if (Private
->HardwareFlowControl
) {
1150 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1153 if (Private
->SoftwareLoopbackEnable
) {
1154 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1157 if (Private
->HardwareLoopbackEnable
) {
1158 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1162 // Get input buffer status
1164 if (!Private
->WinNtThunk
->ClearCommError (Private
->NtHandle
, &Errors
, &Private
->NtComStatus
)) {
1165 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1166 DEBUG ((EFI_D_ERROR
, "SerialGetControl: ClearCommError %d\n", Private
->NtError
));
1167 gBS
->RestoreTPL (Tpl
);
1168 return EFI_DEVICE_ERROR
;
1171 if (Private
->NtComStatus
.cbInQue
== 0) {
1172 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1177 gBS
->RestoreTPL (Tpl
);
1184 WinNtSerialIoWrite (
1185 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1186 IN OUT UINTN
*BufferSize
,
1191 Routine Description:
1193 TODO: Add function description
1197 This - TODO: add argument description
1198 BufferSize - TODO: add argument description
1199 Buffer - TODO: add argument description
1203 EFI_DEVICE_ERROR - TODO: Add description for return value
1204 EFI_SUCCESS - TODO: Add description for return value
1208 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1210 UINTN TotalBytesWritten
;
1218 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1220 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1222 ByteBuffer
= (UINT8
*) Buffer
;
1223 TotalBytesWritten
= 0;
1225 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1226 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1227 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1228 TotalBytesWritten
++;
1234 BytesToGo
= (DWORD
) (*BufferSize
);
1237 if (Private
->HardwareFlowControl
) {
1241 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1242 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1243 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1249 Result
= Private
->WinNtThunk
->WriteFile (
1251 &ByteBuffer
[TotalBytesWritten
],
1257 if (Private
->HardwareFlowControl
) {
1261 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1262 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1263 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1266 TotalBytesWritten
+= BytesWritten
;
1267 BytesToGo
-= BytesWritten
;
1269 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1270 DEBUG ((EFI_D_ERROR
, "SerialWrite: FileWrite %d\n", Private
->NtError
));
1271 *BufferSize
= TotalBytesWritten
;
1272 gBS
->RestoreTPL (Tpl
);
1273 return EFI_DEVICE_ERROR
;
1275 } while (BytesToGo
> 0);
1278 *BufferSize
= TotalBytesWritten
;
1280 gBS
->RestoreTPL (Tpl
);
1288 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1289 IN OUT UINTN
*BufferSize
,
1294 Routine Description:
1296 TODO: Add function description
1300 This - TODO: add argument description
1301 BufferSize - TODO: add argument description
1302 Buffer - TODO: add argument description
1306 EFI_DEVICE_ERROR - TODO: Add description for return value
1310 WIN_NT_SERIAL_IO_PRIVATE_DATA
*Private
;
1319 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1321 Private
= WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1326 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1327 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1328 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1329 ((UINT8
*) Buffer
)[Index
] = Data
;
1336 if (Private
->HardwareFlowControl
) {
1337 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1338 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1339 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1342 Result
= Private
->WinNtThunk
->ReadFile (
1345 (DWORD
) *BufferSize
,
1350 if (Private
->HardwareFlowControl
) {
1351 WinNtSerialIoGetControl (&Private
->SerialIo
, &Control
);
1352 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1353 WinNtSerialIoSetControl (&Private
->SerialIo
, Control
);
1357 Private
->NtError
= Private
->WinNtThunk
->GetLastError ();
1358 gBS
->RestoreTPL (Tpl
);
1359 return EFI_DEVICE_ERROR
;
1363 if (BytesRead
!= *BufferSize
) {
1364 Status
= EFI_TIMEOUT
;
1366 Status
= EFI_SUCCESS
;
1369 *BufferSize
= (UINTN
) BytesRead
;
1371 gBS
->RestoreTPL (Tpl
);
1378 IN SERIAL_DEV_FIFO
*Fifo
1382 Routine Description:
1383 Detect whether specific FIFO is full or not
1386 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1389 TRUE: the FIFO is full
1390 FALSE: the FIFO is not full
1394 if (Fifo
->Surplus
== 0) {
1402 IsaSerialFifoEmpty (
1403 IN SERIAL_DEV_FIFO
*Fifo
1407 Routine Description:
1408 Detect whether specific FIFO is empty or not
1411 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1414 TRUE: the FIFO is empty
1415 FALSE: the FIFO is not empty
1419 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1428 IN SERIAL_DEV_FIFO
*Fifo
,
1433 Routine Description:
1434 Add data to specific FIFO
1437 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1438 Data UINT8: the data added to FIFO
1441 EFI_SUCCESS: Add data to specific FIFO successfully
1442 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1445 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1448 // if FIFO full can not add data
1450 if (IsaSerialFifoFull (Fifo
)) {
1451 return EFI_OUT_OF_RESOURCES
;
1455 // FIFO is not full can add data
1457 Fifo
->Data
[Fifo
->Last
] = Data
;
1460 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1468 IsaSerialFifoRemove (
1469 IN SERIAL_DEV_FIFO
*Fifo
,
1474 Routine Description:
1475 Remove data from specific FIFO
1478 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1479 Data UINT8*: the data removed from FIFO
1482 EFI_SUCCESS: Remove data from specific FIFO successfully
1483 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1486 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1489 // if FIFO is empty, no data can remove
1491 if (IsaSerialFifoEmpty (Fifo
)) {
1492 return EFI_OUT_OF_RESOURCES
;
1496 // FIFO is not empty, can remove data
1498 *Data
= Fifo
->Data
[Fifo
->First
];
1501 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {