3 Copyright (c) 2006 - 2010, 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) - 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
);
174 DEBUG ((EFI_D_ERROR
, "Invalid Baud Rate Parameter!\r\n"));
180 ConvertByteSize2Unix (
194 DEBUG ((EFI_D_ERROR
, "Invalid Data Size Parameter!\r\n"));
201 struct termios
*Options
,
202 EFI_PARITY_TYPE Parity
207 Options
->c_cflag
&= ~PARENB
;
210 Options
->c_cflag
|= PARENB
;
213 Options
->c_cflag
|= PARENB
;
214 Options
->c_cflag
|= PARODD
;
217 Options
->c_cflag
= PARENB
| CMSPAR
| PARODD
;
220 Options
->c_cflag
|= PARENB
| CMSPAR
;
221 Options
->c_cflag
&= ~PARODD
;
224 DEBUG ((EFI_D_ERROR
, "Invalid Parity Parameter!\r\n"));
229 ConvertStopBit2Unix (
230 struct termios
*Options
,
231 EFI_STOP_BITS_TYPE StopBits
236 Options
->c_cflag
|= CSTOPB
;
239 case OneFiveStopBits
:
240 case DefaultStopBits
:
241 Options
->c_cflag
&= ~CSTOPB
;
247 UnixSerialIoDriverBindingSupported (
248 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
249 IN EFI_HANDLE Handle
,
250 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
255 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
266 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
267 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
268 UART_DEVICE_PATH
*UartNode
;
269 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
270 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
271 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
276 // Check RemainingDevicePath validation
278 if (RemainingDevicePath
!= NULL
) {
280 // Check if RemainingDevicePath is the End of Device Path Node,
281 // if yes, go on checking other conditions
283 if (!IsDevicePathEnd (RemainingDevicePath
)) {
285 // If RemainingDevicePath isn't the End of Device Path Node,
286 // check its validation
288 Status
= EFI_UNSUPPORTED
;
289 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
290 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
291 UartNode
->Header
.SubType
!= MSG_UART_DP
||
292 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
295 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
298 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
301 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
304 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
307 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
310 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
314 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (UartNode
);
315 if (IsUartFlowControlNode (FlowControlNode
)) {
317 // If the second node is Flow Control Node,
318 // return error when it request other than hardware flow control.
320 if ((FlowControlNode
->FlowControlMap
& ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
328 // Open the IO Abstraction(s) needed to perform the supported test
330 Status
= gBS
->OpenProtocol (
332 &gEfiUnixIoProtocolGuid
,
334 This
->DriverBindingHandle
,
336 EFI_OPEN_PROTOCOL_BY_DRIVER
338 if (Status
== EFI_ALREADY_STARTED
) {
339 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
341 // If RemainingDevicePath is NULL or is the End of Device Path Node
346 // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
347 // return unsupported, and vice versa.
349 Status
= gBS
->OpenProtocolInformation (
351 &gEfiUnixIoProtocolGuid
,
355 if (EFI_ERROR (Status
)) {
359 for (Index
= 0; Index
< EntryCount
; Index
++) {
360 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
361 Status
= gBS
->OpenProtocol (
362 OpenInfoBuffer
[Index
].ControllerHandle
,
363 &gEfiDevicePathProtocolGuid
,
364 (VOID
**) &DevicePath
,
365 This
->DriverBindingHandle
,
367 EFI_OPEN_PROTOCOL_GET_PROTOCOL
369 if (!EFI_ERROR (Status
) &&
370 (ContainsFlowControl (RemainingDevicePath
) ^ ContainsFlowControl (DevicePath
))) {
371 Status
= EFI_UNSUPPORTED
;
376 FreePool (OpenInfoBuffer
);
380 if (EFI_ERROR (Status
)) {
385 // Close the I/O Abstraction(s) used to perform the supported test
389 &gEfiUnixIoProtocolGuid
,
390 This
->DriverBindingHandle
,
395 // Open the EFI Device Path protocol needed to perform the supported test
397 Status
= gBS
->OpenProtocol (
399 &gEfiDevicePathProtocolGuid
,
400 (VOID
**)&ParentDevicePath
,
401 This
->DriverBindingHandle
,
403 EFI_OPEN_PROTOCOL_BY_DRIVER
405 if (Status
== EFI_ALREADY_STARTED
) {
409 if (EFI_ERROR (Status
)) {
414 // Close protocol, don't use device path protocol in the Support() function
418 &gEfiDevicePathProtocolGuid
,
419 This
->DriverBindingHandle
,
424 // Make sure that the Unix Thunk Protocol is valid
426 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
427 Status
= EFI_UNSUPPORTED
;
432 // Check the GUID to see if this is a handle type the driver supports
434 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
435 Status
= EFI_UNSUPPORTED
;
447 UnixSerialIoDriverBindingStart (
448 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
449 IN EFI_HANDLE Handle
,
450 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
465 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
466 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
468 UART_DEVICE_PATH UartNode
;
469 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
470 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
473 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
474 CHAR8 AsciiDevName
[1024];
475 UART_DEVICE_PATH
*Uart
;
476 UINT32 FlowControlMap
;
477 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
478 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
481 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
486 // Get the Parent Device Path
488 Status
= gBS
->OpenProtocol (
490 &gEfiDevicePathProtocolGuid
,
491 (VOID
**)&ParentDevicePath
,
492 This
->DriverBindingHandle
,
494 EFI_OPEN_PROTOCOL_BY_DRIVER
496 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
501 // Grab the IO abstraction we need to get any work done
503 Status
= gBS
->OpenProtocol (
505 &gEfiUnixIoProtocolGuid
,
507 This
->DriverBindingHandle
,
509 EFI_OPEN_PROTOCOL_BY_DRIVER
511 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
514 &gEfiDevicePathProtocolGuid
,
515 This
->DriverBindingHandle
,
521 if (Status
== EFI_ALREADY_STARTED
) {
523 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
525 // If RemainingDevicePath is NULL or is the End of Device Path Node
531 // Make sure a child handle does not already exist. This driver can only
532 // produce one child per serial port.
534 Status
= gBS
->OpenProtocolInformation (
536 &gEfiUnixIoProtocolGuid
,
540 if (EFI_ERROR (Status
)) {
544 Status
= EFI_ALREADY_STARTED
;
545 for (Index
= 0; Index
< EntryCount
; Index
++) {
546 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
547 Status
= gBS
->OpenProtocol (
548 OpenInfoBuffer
[Index
].ControllerHandle
,
549 &gEfiSerialIoProtocolGuid
,
551 This
->DriverBindingHandle
,
553 EFI_OPEN_PROTOCOL_GET_PROTOCOL
555 if (!EFI_ERROR (Status
)) {
556 Uart
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
557 Status
= SerialIo
->SetAttributes (
560 SerialIo
->Mode
->ReceiveFifoDepth
,
561 SerialIo
->Mode
->Timeout
,
562 (EFI_PARITY_TYPE
) Uart
->Parity
,
564 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
567 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
568 if (!EFI_ERROR (Status
) && IsUartFlowControlNode (FlowControl
)) {
569 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
570 if (!EFI_ERROR (Status
)) {
571 if (FlowControl
->FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
) {
572 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
574 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
577 // Clear the bits that are not allowed to pass to SetControl
579 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
580 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
581 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
582 Status
= SerialIo
->SetControl (SerialIo
, Control
);
590 FreePool (OpenInfoBuffer
);
596 if (RemainingDevicePath
== NULL
) {
598 // Build the device path by appending the UART node to the ParentDevicePath
599 // from the UnixIo handle. The Uart setings are zero here, since
600 // SetAttribute() will update them to match the default setings.
602 ZeroMem (&UartNode
, sizeof (UART_DEVICE_PATH
));
603 UartNode
.Header
.Type
= MESSAGING_DEVICE_PATH
;
604 UartNode
.Header
.SubType
= MSG_UART_DP
;
605 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &UartNode
, sizeof (UART_DEVICE_PATH
));
607 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
609 // If RemainingDevicePath isn't the End of Device Path Node,
610 // only scan the specified device by RemainingDevicePath
613 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
614 // already checked to make sure the RemainingDevicePath contains settings
615 // that we can support.
617 CopyMem (&UartNode
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
618 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
619 if (IsUartFlowControlNode (FlowControl
)) {
620 FlowControlMap
= FlowControl
->FlowControlMap
;
627 // If RemainingDevicePath is the End of Device Path Node,
628 // skip enumerate any device and return EFI_SUCESSS
634 // Check to see if we can access the hardware device. If it's Open in Unix we
635 // will not get access.
637 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
638 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
640 if (UnixHandle
== -1) {
641 DEBUG ((EFI_D_INFO
, "Failed to open serial device, %s!\r\n", UnixIo
->EnvString
));
642 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
643 Status
= EFI_DEVICE_ERROR
;
646 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
649 // Construct Private data
651 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
652 if (Private
== NULL
) {
657 // This signature must be valid before any member function is called
659 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
660 Private
->UnixHandle
= UnixHandle
;
661 Private
->ControllerHandle
= Handle
;
662 Private
->Handle
= NULL
;
663 Private
->UnixThunk
= UnixIo
->UnixThunk
;
664 Private
->ParentDevicePath
= ParentDevicePath
;
665 Private
->ControllerNameTable
= NULL
;
667 Private
->SoftwareLoopbackEnable
= FALSE
;
668 Private
->HardwareLoopbackEnable
= FALSE
;
669 Private
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
670 Private
->Fifo
.First
= 0;
671 Private
->Fifo
.Last
= 0;
672 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
674 CopyMem (&Private
->UartDevicePath
, &UartNode
, sizeof (UART_DEVICE_PATH
));
678 gUnixSerialIoComponentName
.SupportedLanguages
,
679 &Private
->ControllerNameTable
,
683 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
684 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
685 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
686 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
687 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
688 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
689 Private
->SerialIo
.Read
= UnixSerialIoRead
;
690 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
695 // Build the device path by appending the UART node to the ParentDevicePath
696 // from the UnixIo handle. The Uart setings are zero here, since
697 // SetAttribute() will update them to match the current setings.
699 Private
->DevicePath
= AppendDevicePathNode (
701 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
704 // Only produce the FlowControl node when remaining device path has it
706 if (FlowControl
!= NULL
) {
707 TempDevicePath
= Private
->DevicePath
;
708 if (TempDevicePath
!= NULL
) {
709 Private
->DevicePath
= AppendDevicePathNode (
711 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
713 FreePool (TempDevicePath
);
716 if (Private
->DevicePath
== NULL
) {
717 Status
= EFI_OUT_OF_RESOURCES
;
722 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
724 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
725 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
726 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
727 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
728 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
729 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
730 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
733 // Issue a reset to initialize the COM port
735 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
736 if (EFI_ERROR (Status
)) {
741 // Create new child handle
743 Status
= gBS
->InstallMultipleProtocolInterfaces (
745 &gEfiSerialIoProtocolGuid
,
747 &gEfiDevicePathProtocolGuid
,
751 if (EFI_ERROR (Status
)) {
756 // Open For Child Device
758 Status
= gBS
->OpenProtocol (
760 &gEfiUnixIoProtocolGuid
,
762 This
->DriverBindingHandle
,
764 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
766 if (EFI_ERROR (Status
)) {
774 // Use the Stop() function to free all resources allocated in Start()
776 if (Private
!= NULL
) {
777 if (Private
->Handle
!= NULL
) {
778 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
780 if (UnixHandle
!= -1) {
781 Private
->UnixThunk
->Close (UnixHandle
);
784 if (Private
->DevicePath
!= NULL
) {
785 FreePool (Private
->DevicePath
);
788 FreeUnicodeStringTable (Private
->ControllerNameTable
);
794 This
->Stop (This
, Handle
, 0, NULL
);
801 UnixSerialIoDriverBindingStop (
802 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
803 IN EFI_HANDLE Handle
,
804 IN UINTN NumberOfChildren
,
805 IN EFI_HANDLE
*ChildHandleBuffer
811 TODO: Add function description
815 This - TODO: add argument description
816 Handle - TODO: add argument description
817 NumberOfChildren - TODO: add argument description
818 ChildHandleBuffer - TODO: add argument description
822 EFI_DEVICE_ERROR - TODO: Add description for return value
823 EFI_SUCCESS - TODO: Add description for return value
829 BOOLEAN AllChildrenStopped
;
830 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
831 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
832 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
835 // Complete all outstanding transactions to Controller.
836 // Don't allow any new transaction to Controller to be started.
839 if (NumberOfChildren
== 0) {
841 // Close the bus driver
843 Status
= gBS
->CloseProtocol (
845 &gEfiUnixIoProtocolGuid
,
846 This
->DriverBindingHandle
,
849 Status
= gBS
->CloseProtocol (
851 &gEfiDevicePathProtocolGuid
,
852 This
->DriverBindingHandle
,
858 AllChildrenStopped
= TRUE
;
860 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
861 Status
= gBS
->OpenProtocol (
862 ChildHandleBuffer
[Index
],
863 &gEfiSerialIoProtocolGuid
,
865 This
->DriverBindingHandle
,
867 EFI_OPEN_PROTOCOL_GET_PROTOCOL
869 if (!EFI_ERROR (Status
)) {
870 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
872 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
874 Status
= gBS
->CloseProtocol (
876 &gEfiUnixIoProtocolGuid
,
877 This
->DriverBindingHandle
,
878 ChildHandleBuffer
[Index
]
881 Status
= gBS
->UninstallMultipleProtocolInterfaces (
882 ChildHandleBuffer
[Index
],
883 &gEfiSerialIoProtocolGuid
,
885 &gEfiDevicePathProtocolGuid
,
890 if (EFI_ERROR (Status
)) {
893 &gEfiUnixIoProtocolGuid
,
895 This
->DriverBindingHandle
,
896 ChildHandleBuffer
[Index
],
897 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
900 Private
->UnixThunk
->Close (Private
->UnixHandle
);
902 FreePool (Private
->DevicePath
);
904 FreeUnicodeStringTable (Private
->ControllerNameTable
);
910 if (EFI_ERROR (Status
)) {
911 AllChildrenStopped
= FALSE
;
915 if (!AllChildrenStopped
) {
916 return EFI_DEVICE_ERROR
;
923 // Serial IO Protocol member functions
929 IN EFI_SERIAL_IO_PROTOCOL
*This
935 TODO: Add function description
939 This - TODO: add argument description
943 TODO: add return values
947 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
951 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
953 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
955 UnixStatus
= Private
->UnixThunk
->Tcflush (
959 switch (UnixStatus
) {
961 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
962 return EFI_DEVICE_ERROR
;
964 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
965 return EFI_DEVICE_ERROR
;
967 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
968 return EFI_DEVICE_ERROR
;
970 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
973 gBS
->RestoreTPL (Tpl
);
975 return This
->SetAttributes (
977 This
->Mode
->BaudRate
,
978 This
->Mode
->ReceiveFifoDepth
,
981 (UINT8
) This
->Mode
->DataBits
,
988 UnixSerialIoSetAttributes (
989 IN EFI_SERIAL_IO_PROTOCOL
*This
,
991 IN UINT32 ReceiveFifoDepth
,
993 IN EFI_PARITY_TYPE Parity
,
995 IN EFI_STOP_BITS_TYPE StopBits
1001 This function is used to set the attributes.
1005 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
1006 BaudRate - The Baud rate of the serial device.
1007 ReceiveFifoDepth - The request depth of fifo on receive side.
1008 Timeout - the request timeout for a single charact.
1009 Parity - The type of parity used in serial device.
1010 DataBits - Number of deata bits used in serial device.
1011 StopBits - Number of stop bits used in serial device.
1021 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1022 UART_DEVICE_PATH
*Uart
;
1025 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1026 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1029 // Some of our arguments have defaults if a null value is passed in, and
1030 // we must set the default values if a null argument is passed in.
1032 if (BaudRate
== 0) {
1033 BaudRate
= SERIAL_BAUD_DEFAULT
;
1036 if (ReceiveFifoDepth
== 0) {
1037 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
1041 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
1044 if (Parity
== DefaultParity
) {
1048 if (DataBits
== 0) {
1049 DataBits
= SERIAL_DATABITS_DEFAULT
;
1052 if (StopBits
== DefaultStopBits
) {
1053 StopBits
= OneStopBit
;
1057 // See if the new attributes already match the current attributes
1059 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
1060 Private
->UartDevicePath
.DataBits
== DataBits
&&
1061 Private
->UartDevicePath
.Parity
== Parity
&&
1062 Private
->UartDevicePath
.StopBits
== StopBits
&&
1063 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
1064 Private
->SerialIoMode
.Timeout
== Timeout
) {
1065 gBS
->RestoreTPL(Tpl
);
1070 // Try to get options from serial device.
1072 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
1073 Private
->UnixThunk
->Perror ("IoSetAttributes");
1074 gBS
->RestoreTPL (Tpl
);
1075 return EFI_DEVICE_ERROR
;
1079 // Setting Baud Rate
1081 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
1082 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
1086 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
1087 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
1091 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
1095 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
1099 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
1103 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
1105 // Support hardware flow control
1107 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
1111 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
1112 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
1117 if (-1 == Private
->UnixThunk
->Tcsetattr (
1118 Private
->UnixHandle
,
1120 &Private
->UnixTermios
1122 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
1123 gBS
->RestoreTPL (Tpl
);
1124 return EFI_DEVICE_ERROR
;
1130 Private
->SerialIoMode
.BaudRate
= BaudRate
;
1131 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
1132 Private
->SerialIoMode
.Timeout
= Timeout
;
1133 Private
->SerialIoMode
.Parity
= Parity
;
1134 Private
->SerialIoMode
.DataBits
= DataBits
;
1135 Private
->SerialIoMode
.StopBits
= StopBits
;
1138 // See if Device Path Node has actually changed
1140 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
1141 Private
->UartDevicePath
.DataBits
== DataBits
&&
1142 Private
->UartDevicePath
.Parity
== Parity
&&
1143 Private
->UartDevicePath
.StopBits
== StopBits
) {
1144 gBS
->RestoreTPL(Tpl
);
1149 // Update the device path
1151 Private
->UartDevicePath
.BaudRate
= BaudRate
;
1152 Private
->UartDevicePath
.DataBits
= DataBits
;
1153 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1154 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1156 Status
= EFI_SUCCESS
;
1157 if (Private
->Handle
!= NULL
) {
1158 Uart
= (UART_DEVICE_PATH
*) (
1159 (UINTN
) Private
->DevicePath
1160 + GetDevicePathSize (Private
->ParentDevicePath
)
1161 - END_DEVICE_PATH_LENGTH
1163 CopyMem (Uart
, &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
1164 Status
= gBS
->ReinstallProtocolInterface (
1166 &gEfiDevicePathProtocolGuid
,
1167 Private
->DevicePath
,
1172 gBS
->RestoreTPL (Tpl
);
1179 UnixSerialIoSetControl (
1180 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1185 Routine Description:
1187 TODO: Add function description
1191 This - TODO: add argument description
1192 Control - TODO: add argument description
1196 EFI_DEVICE_ERROR - TODO: Add description for return value
1197 EFI_DEVICE_ERROR - TODO: Add description for return value
1198 EFI_SUCCESS - TODO: Add description for return value
1202 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1205 struct termios Options
;
1207 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1211 // first determine the parameter is invalid
1213 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1214 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1215 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1216 return EFI_UNSUPPORTED
;
1219 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1221 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1223 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &IoStatus
);
1226 Private
->UnixThunk
->Perror ("SerialSetControl");
1227 gBS
->RestoreTPL (Tpl
);
1228 return EFI_DEVICE_ERROR
;
1231 Private
->HardwareFlowControl
= FALSE
;
1232 Private
->SoftwareLoopbackEnable
= FALSE
;
1233 Private
->HardwareLoopbackEnable
= FALSE
;
1235 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1236 Options
.c_cflag
|= TIOCM_RTS
;
1239 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1240 Options
.c_cflag
|= TIOCM_DTR
;
1243 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1244 Private
->HardwareFlowControl
= TRUE
;
1247 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1248 Private
->SoftwareLoopbackEnable
= TRUE
;
1251 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1252 Private
->HardwareLoopbackEnable
= TRUE
;
1255 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &IoStatus
);
1258 Private
->UnixThunk
->Perror ("SerialSetControl");
1259 gBS
->RestoreTPL (Tpl
);
1260 return EFI_DEVICE_ERROR
;
1263 Status
= EFI_SUCCESS
;
1264 if (Private
->Handle
!= NULL
) {
1265 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) (
1266 (UINTN
) Private
->DevicePath
1267 + GetDevicePathSize (Private
->ParentDevicePath
)
1268 - END_DEVICE_PATH_LENGTH
1269 + sizeof (UART_DEVICE_PATH
)
1271 if (IsUartFlowControlNode (FlowControl
) &&
1272 ((FlowControl
->FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
) ^ Private
->HardwareFlowControl
)) {
1274 // Flow Control setting is changed, need to reinstall device path protocol
1276 FlowControl
->FlowControlMap
= Private
->HardwareFlowControl
? UART_FLOW_CONTROL_HARDWARE
: 0;
1277 Status
= gBS
->ReinstallProtocolInterface (
1279 &gEfiDevicePathProtocolGuid
,
1280 Private
->DevicePath
,
1286 gBS
->RestoreTPL (Tpl
);
1293 UnixSerialIoGetControl (
1294 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1299 Routine Description:
1301 TODO: Add function description
1305 This - TODO: add argument description
1306 Control - TODO: add argument description
1310 EFI_DEVICE_ERROR - TODO: Add description for return value
1311 EFI_DEVICE_ERROR - TODO: Add description for return value
1312 EFI_DEVICE_ERROR - TODO: Add description for return value
1313 EFI_SUCCESS - TODO: Add description for return value
1317 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1324 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1326 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1327 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1329 Private
->UnixThunk
->Perror ("SerialGetControl");
1330 gBS
->RestoreTPL (Tpl
);
1331 return EFI_DEVICE_ERROR
;
1335 if ((Status
& TIOCM_CTS
) == TIOCM_CTS
) {
1336 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1339 if ((Status
& TIOCM_DSR
) == TIOCM_DSR
) {
1340 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1343 if ((Status
& TIOCM_DTR
) == TIOCM_DTR
) {
1344 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1347 if ((Status
& TIOCM_RTS
) == TIOCM_RTS
) {
1348 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1351 if ((Status
& TIOCM_RNG
) == TIOCM_RNG
) {
1352 Bits
|= EFI_SERIAL_RING_INDICATE
;
1355 if ((Status
& TIOCM_CAR
) == TIOCM_CAR
) {
1356 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1359 if (Private
->HardwareFlowControl
) {
1360 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1363 if (Private
->SoftwareLoopbackEnable
) {
1364 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1367 if (Private
->HardwareLoopbackEnable
) {
1368 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1371 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, FIONREAD
, &Bytes
);
1373 Private
->UnixThunk
->Perror ("SerialGetControl");
1374 gBS
->RestoreTPL (Tpl
);
1375 return EFI_DEVICE_ERROR
;
1379 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1384 gBS
->RestoreTPL (Tpl
);
1392 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1393 IN OUT UINTN
*BufferSize
,
1398 Routine Description:
1400 TODO: Add function description
1404 This - TODO: add argument description
1405 BufferSize - TODO: add argument description
1406 Buffer - TODO: add argument description
1410 EFI_DEVICE_ERROR - TODO: Add description for return value
1411 EFI_SUCCESS - TODO: Add description for return value
1415 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1418 UINT32 TotalBytesWritten
;
1420 UINT32 BytesWritten
;
1425 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1427 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1429 ByteBuffer
= (UINT8
*) Buffer
;
1430 Status
= EFI_SUCCESS
;
1431 TotalBytesWritten
= 0;
1433 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1434 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1435 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1436 TotalBytesWritten
++;
1442 BytesToGo
= (*BufferSize
);
1445 if (Private
->HardwareFlowControl
) {
1449 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1450 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1451 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1457 BytesWritten
= Private
->UnixThunk
->Write (
1458 Private
->UnixHandle
,
1459 &ByteBuffer
[TotalBytesWritten
],
1462 if (BytesWritten
== -1) {
1463 Status
= EFI_DEVICE_ERROR
;
1467 if (Private
->HardwareFlowControl
) {
1471 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1472 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1473 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1476 TotalBytesWritten
+= BytesWritten
;
1477 BytesToGo
-= BytesWritten
;
1478 } while (BytesToGo
> 0);
1481 *BufferSize
= TotalBytesWritten
;
1483 gBS
->RestoreTPL (Tpl
);
1491 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1492 IN OUT UINTN
*BufferSize
,
1497 Routine Description:
1499 TODO: Add function description
1503 This - TODO: add argument description
1504 BufferSize - TODO: add argument description
1505 Buffer - TODO: add argument description
1509 EFI_DEVICE_ERROR - TODO: Add description for return value
1513 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1521 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1523 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1528 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1529 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1530 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1531 ((UINT8
*) Buffer
)[Index
] = Data
;
1538 if (Private
->HardwareFlowControl
) {
1539 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1540 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1541 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1544 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1545 if (Private
->HardwareFlowControl
) {
1546 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1547 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1548 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1553 if (BytesRead
!= *BufferSize
) {
1554 Status
= EFI_TIMEOUT
;
1556 Status
= EFI_SUCCESS
;
1559 *BufferSize
= (UINTN
) BytesRead
;
1561 gBS
->RestoreTPL (Tpl
);
1568 IN SERIAL_DEV_FIFO
*Fifo
1572 Routine Description:
1573 Detect whether specific FIFO is full or not
1576 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1579 TRUE: the FIFO is full
1580 FALSE: the FIFO is not full
1584 if (Fifo
->Surplus
== 0) {
1592 IsaSerialFifoEmpty (
1593 IN SERIAL_DEV_FIFO
*Fifo
1597 Routine Description:
1598 Detect whether specific FIFO is empty or not
1601 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1604 TRUE: the FIFO is empty
1605 FALSE: the FIFO is not empty
1609 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1618 IN SERIAL_DEV_FIFO
*Fifo
,
1623 Routine Description:
1624 Add data to specific FIFO
1627 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1628 Data UINT8: the data added to FIFO
1631 EFI_SUCCESS: Add data to specific FIFO successfully
1632 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1635 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1638 // if FIFO full can not add data
1640 if (IsaSerialFifoFull (Fifo
)) {
1641 return EFI_OUT_OF_RESOURCES
;
1645 // FIFO is not full can add data
1647 Fifo
->Data
[Fifo
->Last
] = Data
;
1650 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1658 IsaSerialFifoRemove (
1659 IN SERIAL_DEV_FIFO
*Fifo
,
1664 Routine Description:
1665 Remove data from specific FIFO
1668 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1669 Data UINT8*: the data removed from FIFO
1672 EFI_SUCCESS: Remove data from specific FIFO successfully
1673 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1676 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1679 // if FIFO is empty, no data can remove
1681 if (IsaSerialFifoEmpty (Fifo
)) {
1682 return EFI_OUT_OF_RESOURCES
;
1686 // FIFO is not empty, can remove data
1688 *Data
= Fifo
->Data
[Fifo
->First
];
1691 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {