3 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4 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) - UnixIo - 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 gEfiUnixSerialPortGuid as a protocol to Handle(1).
30 The instance data for this protocol is the private data used to create
33 Handle(1) - UnixIo - DevicePath(1) - UnixSerialPort
35 If the driver is unloaded Handle(2) is removed from the system and
36 gEfiUnixSerialPortGuid 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 UnixIo protocol, a DevicePath protocol, and
41 the TypeGuid in the UnixIo must be gEfiUnixSerialPortGuid.
43 If Handle(1) contains a gEfiUnixSerialPortGuid protocol then the driver is
48 #include "UnixSerialIo.h"
50 EFI_DRIVER_BINDING_PROTOCOL gUnixSerialIoDriverBinding
= {
51 UnixSerialIoDriverBindingSupported
,
52 UnixSerialIoDriverBindingStart
,
53 UnixSerialIoDriverBindingStop
,
60 Check the device path node whether it's the Flow Control node or not.
62 @param[in] FlowControl The device path node to be checked.
64 @retval TRUE It's the Flow Control node.
65 @retval FALSE It's not.
69 IsUartFlowControlNode (
70 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
74 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
75 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
76 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
81 Check the device path node whether it contains Flow Control node or not.
83 @param[in] DevicePath The device path to be checked.
85 @retval TRUE It contains the Flow Control node.
86 @retval FALSE It doesn't.
91 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
94 while (!IsDevicePathEnd (DevicePath
)) {
95 if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH
*) DevicePath
)) {
98 DevicePath
= NextDevicePathNode (DevicePath
);
111 return 0; // Don't use B0 as it is also used in EFI #includes as a name so termios.h #define
112 // can break the build.
175 DEBUG ((EFI_D_ERROR
, "Invalid Baud Rate Parameter!\r\n"));
181 ConvertByteSize2Unix (
195 DEBUG ((EFI_D_ERROR
, "Invalid Data Size Parameter!\r\n"));
202 struct termios
*Options
,
203 EFI_PARITY_TYPE Parity
208 Options
->c_cflag
&= ~PARENB
;
211 Options
->c_cflag
|= PARENB
;
214 Options
->c_cflag
|= PARENB
;
215 Options
->c_cflag
|= PARODD
;
218 Options
->c_cflag
= PARENB
| CMSPAR
| PARODD
;
221 Options
->c_cflag
|= PARENB
| CMSPAR
;
222 Options
->c_cflag
&= ~PARODD
;
225 DEBUG ((EFI_D_ERROR
, "Invalid Parity Parameter!\r\n"));
230 ConvertStopBit2Unix (
231 struct termios
*Options
,
232 EFI_STOP_BITS_TYPE StopBits
237 Options
->c_cflag
|= CSTOPB
;
240 case OneFiveStopBits
:
241 case DefaultStopBits
:
242 Options
->c_cflag
&= ~CSTOPB
;
248 UnixSerialIoDriverBindingSupported (
249 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
250 IN EFI_HANDLE Handle
,
251 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
256 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
267 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
268 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
269 UART_DEVICE_PATH
*UartNode
;
270 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
271 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
272 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
275 BOOLEAN RemainingDevicePathContainsFlowControl
;
278 // Check RemainingDevicePath validation
280 if (RemainingDevicePath
!= NULL
) {
282 // Check if RemainingDevicePath is the End of Device Path Node,
283 // if yes, go on checking other conditions
285 if (!IsDevicePathEnd (RemainingDevicePath
)) {
287 // If RemainingDevicePath isn't the End of Device Path Node,
288 // check its validation
290 Status
= EFI_UNSUPPORTED
;
291 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
292 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
293 UartNode
->Header
.SubType
!= MSG_UART_DP
||
294 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
297 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
300 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
303 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
306 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
309 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
312 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
316 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (UartNode
);
317 if (IsUartFlowControlNode (FlowControlNode
)) {
319 // If the second node is Flow Control Node,
320 // return error when it request other than hardware flow control.
322 if ((FlowControlNode
->FlowControlMap
& ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
330 // Open the IO Abstraction(s) needed to perform the supported test
332 Status
= gBS
->OpenProtocol (
334 &gEfiUnixIoProtocolGuid
,
336 This
->DriverBindingHandle
,
338 EFI_OPEN_PROTOCOL_BY_DRIVER
340 if (Status
== EFI_ALREADY_STARTED
) {
341 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
343 // If RemainingDevicePath is NULL or is the End of Device Path Node
348 // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
349 // return unsupported, and vice versa.
351 Status
= gBS
->OpenProtocolInformation (
353 &gEfiUnixIoProtocolGuid
,
357 if (EFI_ERROR (Status
)) {
362 // See if RemainingDevicePath has a Flow Control device path node
364 RemainingDevicePathContainsFlowControl
= ContainsFlowControl (RemainingDevicePath
);
366 for (Index
= 0; Index
< EntryCount
; Index
++) {
367 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
368 Status
= gBS
->OpenProtocol (
369 OpenInfoBuffer
[Index
].ControllerHandle
,
370 &gEfiDevicePathProtocolGuid
,
371 (VOID
**) &DevicePath
,
372 This
->DriverBindingHandle
,
374 EFI_OPEN_PROTOCOL_GET_PROTOCOL
376 if (!EFI_ERROR (Status
)) {
377 if (RemainingDevicePathContainsFlowControl
^ ContainsFlowControl (DevicePath
)) {
378 Status
= EFI_UNSUPPORTED
;
384 FreePool (OpenInfoBuffer
);
388 if (EFI_ERROR (Status
)) {
393 // Close the I/O Abstraction(s) used to perform the supported test
397 &gEfiUnixIoProtocolGuid
,
398 This
->DriverBindingHandle
,
403 // Open the EFI Device Path protocol needed to perform the supported test
405 Status
= gBS
->OpenProtocol (
407 &gEfiDevicePathProtocolGuid
,
408 (VOID
**)&ParentDevicePath
,
409 This
->DriverBindingHandle
,
411 EFI_OPEN_PROTOCOL_BY_DRIVER
413 if (Status
== EFI_ALREADY_STARTED
) {
417 if (EFI_ERROR (Status
)) {
422 // Close protocol, don't use device path protocol in the Support() function
426 &gEfiDevicePathProtocolGuid
,
427 This
->DriverBindingHandle
,
432 // Make sure that the Unix Thunk Protocol is valid
434 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
435 Status
= EFI_UNSUPPORTED
;
440 // Check the GUID to see if this is a handle type the driver supports
442 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
443 Status
= EFI_UNSUPPORTED
;
455 UnixSerialIoDriverBindingStart (
456 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
457 IN EFI_HANDLE Handle
,
458 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
473 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
474 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
476 UART_DEVICE_PATH UartNode
;
477 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
478 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
481 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
482 CHAR8 AsciiDevName
[1024];
483 UART_DEVICE_PATH
*Uart
;
484 UINT32 FlowControlMap
;
485 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
486 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
489 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
494 // Get the Parent Device Path
496 Status
= gBS
->OpenProtocol (
498 &gEfiDevicePathProtocolGuid
,
499 (VOID
**)&ParentDevicePath
,
500 This
->DriverBindingHandle
,
502 EFI_OPEN_PROTOCOL_BY_DRIVER
504 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
509 // Grab the IO abstraction we need to get any work done
511 Status
= gBS
->OpenProtocol (
513 &gEfiUnixIoProtocolGuid
,
515 This
->DriverBindingHandle
,
517 EFI_OPEN_PROTOCOL_BY_DRIVER
519 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
522 &gEfiDevicePathProtocolGuid
,
523 This
->DriverBindingHandle
,
529 if (Status
== EFI_ALREADY_STARTED
) {
531 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
533 // If RemainingDevicePath is NULL or is the End of Device Path Node
539 // Make sure a child handle does not already exist. This driver can only
540 // produce one child per serial port.
542 Status
= gBS
->OpenProtocolInformation (
544 &gEfiUnixIoProtocolGuid
,
548 if (EFI_ERROR (Status
)) {
552 Status
= EFI_ALREADY_STARTED
;
553 for (Index
= 0; Index
< EntryCount
; Index
++) {
554 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
555 Status
= gBS
->OpenProtocol (
556 OpenInfoBuffer
[Index
].ControllerHandle
,
557 &gEfiSerialIoProtocolGuid
,
559 This
->DriverBindingHandle
,
561 EFI_OPEN_PROTOCOL_GET_PROTOCOL
563 if (!EFI_ERROR (Status
)) {
564 Uart
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
565 Status
= SerialIo
->SetAttributes (
568 SerialIo
->Mode
->ReceiveFifoDepth
,
569 SerialIo
->Mode
->Timeout
,
570 (EFI_PARITY_TYPE
) Uart
->Parity
,
572 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
575 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
576 if (!EFI_ERROR (Status
) && IsUartFlowControlNode (FlowControl
)) {
577 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
578 if (!EFI_ERROR (Status
)) {
579 if (FlowControl
->FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
) {
580 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
582 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
585 // Clear the bits that are not allowed to pass to SetControl
587 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
588 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
589 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
590 Status
= SerialIo
->SetControl (SerialIo
, Control
);
598 FreePool (OpenInfoBuffer
);
604 if (RemainingDevicePath
== NULL
) {
606 // Build the device path by appending the UART node to the ParentDevicePath
607 // from the UnixIo handle. The Uart setings are zero here, since
608 // SetAttribute() will update them to match the default setings.
610 ZeroMem (&UartNode
, sizeof (UART_DEVICE_PATH
));
611 UartNode
.Header
.Type
= MESSAGING_DEVICE_PATH
;
612 UartNode
.Header
.SubType
= MSG_UART_DP
;
613 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &UartNode
, sizeof (UART_DEVICE_PATH
));
615 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
617 // If RemainingDevicePath isn't the End of Device Path Node,
618 // only scan the specified device by RemainingDevicePath
621 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
622 // already checked to make sure the RemainingDevicePath contains settings
623 // that we can support.
625 CopyMem (&UartNode
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
626 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
627 if (IsUartFlowControlNode (FlowControl
)) {
628 FlowControlMap
= FlowControl
->FlowControlMap
;
635 // If RemainingDevicePath is the End of Device Path Node,
636 // skip enumerate any device and return EFI_SUCESSS
642 // Check to see if we can access the hardware device. If it's Open in Unix we
643 // will not get access.
645 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
646 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
648 if (UnixHandle
== -1) {
649 DEBUG ((EFI_D_INFO
, "Failed to open serial device, %s!\r\n", UnixIo
->EnvString
));
650 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
651 Status
= EFI_DEVICE_ERROR
;
654 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
657 // Construct Private data
659 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
660 if (Private
== NULL
) {
665 // This signature must be valid before any member function is called
667 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
668 Private
->UnixHandle
= UnixHandle
;
669 Private
->ControllerHandle
= Handle
;
670 Private
->Handle
= NULL
;
671 Private
->UnixThunk
= UnixIo
->UnixThunk
;
672 Private
->ParentDevicePath
= ParentDevicePath
;
673 Private
->ControllerNameTable
= NULL
;
675 Private
->SoftwareLoopbackEnable
= FALSE
;
676 Private
->HardwareLoopbackEnable
= FALSE
;
677 Private
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
678 Private
->Fifo
.First
= 0;
679 Private
->Fifo
.Last
= 0;
680 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
682 CopyMem (&Private
->UartDevicePath
, &UartNode
, sizeof (UART_DEVICE_PATH
));
686 gUnixSerialIoComponentName
.SupportedLanguages
,
687 &Private
->ControllerNameTable
,
691 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
692 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
693 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
694 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
695 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
696 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
697 Private
->SerialIo
.Read
= UnixSerialIoRead
;
698 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
703 // Build the device path by appending the UART node to the ParentDevicePath
704 // from the UnixIo handle. The Uart setings are zero here, since
705 // SetAttribute() will update them to match the current setings.
707 Private
->DevicePath
= AppendDevicePathNode (
709 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
712 // Only produce the FlowControl node when remaining device path has it
714 if (FlowControl
!= NULL
) {
715 TempDevicePath
= Private
->DevicePath
;
716 if (TempDevicePath
!= NULL
) {
717 Private
->DevicePath
= AppendDevicePathNode (
719 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
721 FreePool (TempDevicePath
);
724 if (Private
->DevicePath
== NULL
) {
725 Status
= EFI_OUT_OF_RESOURCES
;
730 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
732 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
733 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
734 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
735 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
736 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
737 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
738 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
741 // Issue a reset to initialize the COM port
743 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
744 if (EFI_ERROR (Status
)) {
749 // Create new child handle
751 Status
= gBS
->InstallMultipleProtocolInterfaces (
753 &gEfiSerialIoProtocolGuid
,
755 &gEfiDevicePathProtocolGuid
,
759 if (EFI_ERROR (Status
)) {
764 // Open For Child Device
766 Status
= gBS
->OpenProtocol (
768 &gEfiUnixIoProtocolGuid
,
770 This
->DriverBindingHandle
,
772 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
774 if (EFI_ERROR (Status
)) {
782 // Use the Stop() function to free all resources allocated in Start()
784 if (Private
!= NULL
) {
785 if (Private
->Handle
!= NULL
) {
786 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
788 if (UnixHandle
!= -1) {
789 Private
->UnixThunk
->Close (UnixHandle
);
792 if (Private
->DevicePath
!= NULL
) {
793 FreePool (Private
->DevicePath
);
796 FreeUnicodeStringTable (Private
->ControllerNameTable
);
802 This
->Stop (This
, Handle
, 0, NULL
);
809 UnixSerialIoDriverBindingStop (
810 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
811 IN EFI_HANDLE Handle
,
812 IN UINTN NumberOfChildren
,
813 IN EFI_HANDLE
*ChildHandleBuffer
819 TODO: Add function description
823 This - TODO: add argument description
824 Handle - TODO: add argument description
825 NumberOfChildren - TODO: add argument description
826 ChildHandleBuffer - TODO: add argument description
830 EFI_DEVICE_ERROR - TODO: Add description for return value
831 EFI_SUCCESS - TODO: Add description for return value
837 BOOLEAN AllChildrenStopped
;
838 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
839 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
840 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
843 // Complete all outstanding transactions to Controller.
844 // Don't allow any new transaction to Controller to be started.
847 if (NumberOfChildren
== 0) {
849 // Close the bus driver
851 Status
= gBS
->CloseProtocol (
853 &gEfiUnixIoProtocolGuid
,
854 This
->DriverBindingHandle
,
857 Status
= gBS
->CloseProtocol (
859 &gEfiDevicePathProtocolGuid
,
860 This
->DriverBindingHandle
,
866 AllChildrenStopped
= TRUE
;
868 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
869 Status
= gBS
->OpenProtocol (
870 ChildHandleBuffer
[Index
],
871 &gEfiSerialIoProtocolGuid
,
873 This
->DriverBindingHandle
,
875 EFI_OPEN_PROTOCOL_GET_PROTOCOL
877 if (!EFI_ERROR (Status
)) {
878 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
880 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
882 Status
= gBS
->CloseProtocol (
884 &gEfiUnixIoProtocolGuid
,
885 This
->DriverBindingHandle
,
886 ChildHandleBuffer
[Index
]
889 Status
= gBS
->UninstallMultipleProtocolInterfaces (
890 ChildHandleBuffer
[Index
],
891 &gEfiSerialIoProtocolGuid
,
893 &gEfiDevicePathProtocolGuid
,
898 if (EFI_ERROR (Status
)) {
901 &gEfiUnixIoProtocolGuid
,
903 This
->DriverBindingHandle
,
904 ChildHandleBuffer
[Index
],
905 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
908 Private
->UnixThunk
->Close (Private
->UnixHandle
);
910 FreePool (Private
->DevicePath
);
912 FreeUnicodeStringTable (Private
->ControllerNameTable
);
918 if (EFI_ERROR (Status
)) {
919 AllChildrenStopped
= FALSE
;
923 if (!AllChildrenStopped
) {
924 return EFI_DEVICE_ERROR
;
931 // Serial IO Protocol member functions
937 IN EFI_SERIAL_IO_PROTOCOL
*This
943 TODO: Add function description
947 This - TODO: add argument description
951 TODO: add return values
955 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
959 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
961 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
963 UnixStatus
= Private
->UnixThunk
->Tcflush (
967 switch (UnixStatus
) {
969 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
970 return EFI_DEVICE_ERROR
;
972 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
973 return EFI_DEVICE_ERROR
;
975 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
976 return EFI_DEVICE_ERROR
;
978 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
981 gBS
->RestoreTPL (Tpl
);
983 return This
->SetAttributes (
985 This
->Mode
->BaudRate
,
986 This
->Mode
->ReceiveFifoDepth
,
989 (UINT8
) This
->Mode
->DataBits
,
996 UnixSerialIoSetAttributes (
997 IN EFI_SERIAL_IO_PROTOCOL
*This
,
999 IN UINT32 ReceiveFifoDepth
,
1001 IN EFI_PARITY_TYPE Parity
,
1003 IN EFI_STOP_BITS_TYPE StopBits
1007 Routine Description:
1009 This function is used to set the attributes.
1013 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
1014 BaudRate - The Baud rate of the serial device.
1015 ReceiveFifoDepth - The request depth of fifo on receive side.
1016 Timeout - the request timeout for a single charact.
1017 Parity - The type of parity used in serial device.
1018 DataBits - Number of deata bits used in serial device.
1019 StopBits - Number of stop bits used in serial device.
1029 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1030 UART_DEVICE_PATH
*Uart
;
1033 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1034 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1037 // Some of our arguments have defaults if a null value is passed in, and
1038 // we must set the default values if a null argument is passed in.
1040 if (BaudRate
== 0) {
1041 BaudRate
= SERIAL_BAUD_DEFAULT
;
1044 if (ReceiveFifoDepth
== 0) {
1045 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
1049 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
1052 if (Parity
== DefaultParity
) {
1056 if (DataBits
== 0) {
1057 DataBits
= SERIAL_DATABITS_DEFAULT
;
1060 if (StopBits
== DefaultStopBits
) {
1061 StopBits
= OneStopBit
;
1065 // See if the new attributes already match the current attributes
1067 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
1068 Private
->UartDevicePath
.DataBits
== DataBits
&&
1069 Private
->UartDevicePath
.Parity
== Parity
&&
1070 Private
->UartDevicePath
.StopBits
== StopBits
&&
1071 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
1072 Private
->SerialIoMode
.Timeout
== Timeout
) {
1073 gBS
->RestoreTPL(Tpl
);
1078 // Try to get options from serial device.
1080 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
1081 Private
->UnixThunk
->Perror ("IoSetAttributes");
1082 gBS
->RestoreTPL (Tpl
);
1083 return EFI_DEVICE_ERROR
;
1087 // Setting Baud Rate
1089 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
1090 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
1094 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
1095 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
1099 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
1103 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
1107 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
1111 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
1113 // Support hardware flow control
1115 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
1119 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
1120 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
1125 if (-1 == Private
->UnixThunk
->Tcsetattr (
1126 Private
->UnixHandle
,
1128 &Private
->UnixTermios
1130 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
1131 gBS
->RestoreTPL (Tpl
);
1132 return EFI_DEVICE_ERROR
;
1138 Private
->SerialIoMode
.BaudRate
= BaudRate
;
1139 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
1140 Private
->SerialIoMode
.Timeout
= Timeout
;
1141 Private
->SerialIoMode
.Parity
= Parity
;
1142 Private
->SerialIoMode
.DataBits
= DataBits
;
1143 Private
->SerialIoMode
.StopBits
= StopBits
;
1146 // See if Device Path Node has actually changed
1148 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
1149 Private
->UartDevicePath
.DataBits
== DataBits
&&
1150 Private
->UartDevicePath
.Parity
== Parity
&&
1151 Private
->UartDevicePath
.StopBits
== StopBits
) {
1152 gBS
->RestoreTPL(Tpl
);
1157 // Update the device path
1159 Private
->UartDevicePath
.BaudRate
= BaudRate
;
1160 Private
->UartDevicePath
.DataBits
= DataBits
;
1161 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1162 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1164 Status
= EFI_SUCCESS
;
1165 if (Private
->Handle
!= NULL
) {
1166 Uart
= (UART_DEVICE_PATH
*) (
1167 (UINTN
) Private
->DevicePath
1168 + GetDevicePathSize (Private
->ParentDevicePath
)
1169 - END_DEVICE_PATH_LENGTH
1171 CopyMem (Uart
, &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
1172 Status
= gBS
->ReinstallProtocolInterface (
1174 &gEfiDevicePathProtocolGuid
,
1175 Private
->DevicePath
,
1180 gBS
->RestoreTPL (Tpl
);
1187 UnixSerialIoSetControl (
1188 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1193 Routine Description:
1195 TODO: Add function description
1199 This - TODO: add argument description
1200 Control - TODO: add argument description
1204 EFI_DEVICE_ERROR - TODO: Add description for return value
1205 EFI_DEVICE_ERROR - TODO: Add description for return value
1206 EFI_SUCCESS - TODO: Add description for return value
1210 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1213 struct termios Options
;
1215 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1219 // first determine the parameter is invalid
1221 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1222 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1223 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1224 return EFI_UNSUPPORTED
;
1227 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1229 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1231 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &IoStatus
);
1234 Private
->UnixThunk
->Perror ("SerialSetControl");
1235 gBS
->RestoreTPL (Tpl
);
1236 return EFI_DEVICE_ERROR
;
1239 Private
->HardwareFlowControl
= FALSE
;
1240 Private
->SoftwareLoopbackEnable
= FALSE
;
1241 Private
->HardwareLoopbackEnable
= FALSE
;
1243 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1244 Options
.c_cflag
|= TIOCM_RTS
;
1247 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1248 Options
.c_cflag
|= TIOCM_DTR
;
1251 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1252 Private
->HardwareFlowControl
= TRUE
;
1255 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1256 Private
->SoftwareLoopbackEnable
= TRUE
;
1259 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1260 Private
->HardwareLoopbackEnable
= TRUE
;
1263 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &IoStatus
);
1266 Private
->UnixThunk
->Perror ("SerialSetControl");
1267 gBS
->RestoreTPL (Tpl
);
1268 return EFI_DEVICE_ERROR
;
1271 Status
= EFI_SUCCESS
;
1272 if (Private
->Handle
!= NULL
) {
1273 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) (
1274 (UINTN
) Private
->DevicePath
1275 + GetDevicePathSize (Private
->ParentDevicePath
)
1276 - END_DEVICE_PATH_LENGTH
1277 + sizeof (UART_DEVICE_PATH
)
1279 if (IsUartFlowControlNode (FlowControl
) &&
1280 ((FlowControl
->FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
) ^ Private
->HardwareFlowControl
)) {
1282 // Flow Control setting is changed, need to reinstall device path protocol
1284 FlowControl
->FlowControlMap
= Private
->HardwareFlowControl
? UART_FLOW_CONTROL_HARDWARE
: 0;
1285 Status
= gBS
->ReinstallProtocolInterface (
1287 &gEfiDevicePathProtocolGuid
,
1288 Private
->DevicePath
,
1294 gBS
->RestoreTPL (Tpl
);
1301 UnixSerialIoGetControl (
1302 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1307 Routine Description:
1309 TODO: Add function description
1313 This - TODO: add argument description
1314 Control - TODO: add argument description
1318 EFI_DEVICE_ERROR - TODO: Add description for return value
1319 EFI_DEVICE_ERROR - TODO: Add description for return value
1320 EFI_DEVICE_ERROR - TODO: Add description for return value
1321 EFI_SUCCESS - TODO: Add description for return value
1325 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1332 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1334 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1335 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1337 Private
->UnixThunk
->Perror ("SerialGetControl");
1338 gBS
->RestoreTPL (Tpl
);
1339 return EFI_DEVICE_ERROR
;
1343 if ((Status
& TIOCM_CTS
) == TIOCM_CTS
) {
1344 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1347 if ((Status
& TIOCM_DSR
) == TIOCM_DSR
) {
1348 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1351 if ((Status
& TIOCM_DTR
) == TIOCM_DTR
) {
1352 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1355 if ((Status
& TIOCM_RTS
) == TIOCM_RTS
) {
1356 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1359 if ((Status
& TIOCM_RNG
) == TIOCM_RNG
) {
1360 Bits
|= EFI_SERIAL_RING_INDICATE
;
1363 if ((Status
& TIOCM_CAR
) == TIOCM_CAR
) {
1364 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1367 if (Private
->HardwareFlowControl
) {
1368 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1371 if (Private
->SoftwareLoopbackEnable
) {
1372 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1375 if (Private
->HardwareLoopbackEnable
) {
1376 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1379 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, FIONREAD
, &Bytes
);
1381 Private
->UnixThunk
->Perror ("SerialGetControl");
1382 gBS
->RestoreTPL (Tpl
);
1383 return EFI_DEVICE_ERROR
;
1387 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1392 gBS
->RestoreTPL (Tpl
);
1400 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1401 IN OUT UINTN
*BufferSize
,
1406 Routine Description:
1408 TODO: Add function description
1412 This - TODO: add argument description
1413 BufferSize - TODO: add argument description
1414 Buffer - TODO: add argument description
1418 EFI_DEVICE_ERROR - TODO: Add description for return value
1419 EFI_SUCCESS - TODO: Add description for return value
1423 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1426 UINT32 TotalBytesWritten
;
1428 UINT32 BytesWritten
;
1433 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1435 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1437 ByteBuffer
= (UINT8
*) Buffer
;
1438 Status
= EFI_SUCCESS
;
1439 TotalBytesWritten
= 0;
1441 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1442 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1443 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1444 TotalBytesWritten
++;
1450 BytesToGo
= (*BufferSize
);
1453 if (Private
->HardwareFlowControl
) {
1457 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1458 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1459 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1465 BytesWritten
= Private
->UnixThunk
->Write (
1466 Private
->UnixHandle
,
1467 &ByteBuffer
[TotalBytesWritten
],
1470 if (BytesWritten
== -1) {
1471 Status
= EFI_DEVICE_ERROR
;
1475 if (Private
->HardwareFlowControl
) {
1479 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1480 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1481 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1484 TotalBytesWritten
+= BytesWritten
;
1485 BytesToGo
-= BytesWritten
;
1486 } while (BytesToGo
> 0);
1489 *BufferSize
= TotalBytesWritten
;
1491 gBS
->RestoreTPL (Tpl
);
1499 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1500 IN OUT UINTN
*BufferSize
,
1505 Routine Description:
1507 TODO: Add function description
1511 This - TODO: add argument description
1512 BufferSize - TODO: add argument description
1513 Buffer - TODO: add argument description
1517 EFI_DEVICE_ERROR - TODO: Add description for return value
1521 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1529 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1531 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1536 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1537 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1538 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1539 ((UINT8
*) Buffer
)[Index
] = Data
;
1546 if (Private
->HardwareFlowControl
) {
1547 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1548 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1549 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1552 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1553 if (Private
->HardwareFlowControl
) {
1554 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1555 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1556 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1561 if (BytesRead
!= *BufferSize
) {
1562 Status
= EFI_TIMEOUT
;
1564 Status
= EFI_SUCCESS
;
1567 *BufferSize
= (UINTN
) BytesRead
;
1569 gBS
->RestoreTPL (Tpl
);
1576 IN SERIAL_DEV_FIFO
*Fifo
1580 Routine Description:
1581 Detect whether specific FIFO is full or not
1584 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1587 TRUE: the FIFO is full
1588 FALSE: the FIFO is not full
1592 if (Fifo
->Surplus
== 0) {
1600 IsaSerialFifoEmpty (
1601 IN SERIAL_DEV_FIFO
*Fifo
1605 Routine Description:
1606 Detect whether specific FIFO is empty or not
1609 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1612 TRUE: the FIFO is empty
1613 FALSE: the FIFO is not empty
1617 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1626 IN SERIAL_DEV_FIFO
*Fifo
,
1631 Routine Description:
1632 Add data to specific FIFO
1635 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1636 Data UINT8: the data added to FIFO
1639 EFI_SUCCESS: Add data to specific FIFO successfully
1640 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1643 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1646 // if FIFO full can not add data
1648 if (IsaSerialFifoFull (Fifo
)) {
1649 return EFI_OUT_OF_RESOURCES
;
1653 // FIFO is not full can add data
1655 Fifo
->Data
[Fifo
->Last
] = Data
;
1658 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1666 IsaSerialFifoRemove (
1667 IN SERIAL_DEV_FIFO
*Fifo
,
1672 Routine Description:
1673 Remove data from specific FIFO
1676 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1677 Data UINT8*: the data removed from FIFO
1680 EFI_SUCCESS: Remove data from specific FIFO successfully
1681 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1684 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1687 // if FIFO is empty, no data can remove
1689 if (IsaSerialFifoEmpty (Fifo
)) {
1690 return EFI_OUT_OF_RESOURCES
;
1694 // FIFO is not empty, can remove data
1696 *Data
= Fifo
->Data
[Fifo
->First
];
1699 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {