3 Copyright (c) 2006 - 2009, 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
,
129 DEBUG ((EFI_D_ERROR
, "Invalid Baud Rate Parameter!\r\n"));
135 ConvertByteSize2Unix (
149 DEBUG ((EFI_D_ERROR
, "Invalid Data Size Parameter!\r\n"));
156 struct termios
*Options
,
157 EFI_PARITY_TYPE Parity
162 Options
->c_cflag
&= ~PARENB
;
165 Options
->c_cflag
|= PARENB
;
168 Options
->c_cflag
|= PARENB
;
169 Options
->c_cflag
|= PARODD
;
172 Options
->c_cflag
= PARENB
| CMSPAR
| PARODD
;
175 Options
->c_cflag
|= PARENB
| CMSPAR
;
176 Options
->c_cflag
&= ~PARODD
;
179 DEBUG ((EFI_D_ERROR
, "Invalid Parity Parameter!\r\n"));
184 ConvertStopBit2Unix (
185 struct termios
*Options
,
186 EFI_STOP_BITS_TYPE StopBits
191 Options
->c_cflag
|= CSTOPB
;
194 case OneFiveStopBits
:
195 case DefaultStopBits
:
196 Options
->c_cflag
&= ~CSTOPB
;
202 UnixSerialIoDriverBindingSupported (
203 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
204 IN EFI_HANDLE Handle
,
205 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
210 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
221 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
222 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
223 UART_DEVICE_PATH
*UartNode
;
226 // Check RemainingDevicePath validation
228 if (RemainingDevicePath
!= NULL
) {
230 // Check if RemainingDevicePath is the End of Device Path Node,
231 // if yes, go on checking other conditions
233 if (!IsDevicePathEnd (RemainingDevicePath
)) {
235 // If RemainingDevicePath isn't the End of Device Path Node,
236 // check its validation
238 Status
= EFI_UNSUPPORTED
;
239 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
240 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
241 UartNode
->Header
.SubType
!= MSG_UART_DP
||
242 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
245 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
248 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
251 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
254 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
257 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
260 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
267 // Open the IO Abstraction(s) needed to perform the supported test
269 Status
= gBS
->OpenProtocol (
271 &gEfiUnixIoProtocolGuid
,
273 This
->DriverBindingHandle
,
275 EFI_OPEN_PROTOCOL_BY_DRIVER
277 if (Status
== EFI_ALREADY_STARTED
) {
281 if (EFI_ERROR (Status
)) {
286 // Close the I/O Abstraction(s) used to perform the supported test
290 &gEfiUnixIoProtocolGuid
,
291 This
->DriverBindingHandle
,
296 // Open the EFI Device Path protocol needed to perform the supported test
298 Status
= gBS
->OpenProtocol (
300 &gEfiDevicePathProtocolGuid
,
301 (VOID
**)&ParentDevicePath
,
302 This
->DriverBindingHandle
,
304 EFI_OPEN_PROTOCOL_BY_DRIVER
306 if (Status
== EFI_ALREADY_STARTED
) {
310 if (EFI_ERROR (Status
)) {
315 // Close protocol, don't use device path protocol in the Support() function
319 &gEfiDevicePathProtocolGuid
,
320 This
->DriverBindingHandle
,
325 // Make sure that the Unix Thunk Protocol is valid
327 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
328 Status
= EFI_UNSUPPORTED
;
333 // Check the GUID to see if this is a handle type the driver supports
335 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
336 Status
= EFI_UNSUPPORTED
;
348 UnixSerialIoDriverBindingStart (
349 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
350 IN EFI_HANDLE Handle
,
351 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
366 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
367 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
369 UART_DEVICE_PATH Node
;
370 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
371 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
374 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
375 CHAR8 AsciiDevName
[1024];
376 UART_DEVICE_PATH
*UartNode
;
378 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
383 // Grab the protocols we need
385 Status
= gBS
->OpenProtocol (
387 &gEfiDevicePathProtocolGuid
,
388 (VOID
**)&ParentDevicePath
,
389 This
->DriverBindingHandle
,
391 EFI_OPEN_PROTOCOL_BY_DRIVER
393 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
398 // Grab the IO abstraction we need to get any work done
400 Status
= gBS
->OpenProtocol (
402 &gEfiUnixIoProtocolGuid
,
404 This
->DriverBindingHandle
,
406 EFI_OPEN_PROTOCOL_BY_DRIVER
408 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
411 &gEfiDevicePathProtocolGuid
,
412 This
->DriverBindingHandle
,
418 if (Status
== EFI_ALREADY_STARTED
) {
420 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
422 // If RemainingDevicePath is NULL or is the End of Device Path Node
428 // Make sure a child handle does not already exist. This driver can only
429 // produce one child per serial port.
431 Status
= gBS
->OpenProtocolInformation (
433 &gEfiUnixIoProtocolGuid
,
437 if (EFI_ERROR (Status
)) {
441 Status
= EFI_ALREADY_STARTED
;
442 for (Index
= 0; Index
< EntryCount
; Index
++) {
443 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
444 Status
= gBS
->OpenProtocol (
445 OpenInfoBuffer
[Index
].ControllerHandle
,
446 &gEfiSerialIoProtocolGuid
,
448 This
->DriverBindingHandle
,
450 EFI_OPEN_PROTOCOL_GET_PROTOCOL
452 if (!EFI_ERROR (Status
)) {
453 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
454 Status
= SerialIo
->SetAttributes (
457 SerialIo
->Mode
->ReceiveFifoDepth
,
458 SerialIo
->Mode
->Timeout
,
468 FreePool (OpenInfoBuffer
);
472 if (RemainingDevicePath
== NULL
) {
474 // Build the device path by appending the UART node to the ParentDevicePath
475 // from the UnixIo handle. The Uart setings are zero here, since
476 // SetAttribute() will update them to match the default setings.
478 ZeroMem (&Node
, sizeof (UART_DEVICE_PATH
));
479 Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
480 Node
.Header
.SubType
= MSG_UART_DP
;
481 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Node
, sizeof (UART_DEVICE_PATH
));
483 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
485 // If RemainingDevicePath isn't the End of Device Path Node,
486 // only scan the specified device by RemainingDevicePath
489 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
490 // already checked to make sure the RemainingDevicePath contains settings
491 // that we can support.
493 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
497 // If RemainingDevicePath is the End of Device Path Node,
498 // skip enumerate any device and return EFI_SUCESSS
504 // Check to see if we can access the hardware device. If it's Open in Unix we
505 // will not get access.
507 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
508 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
510 if (UnixHandle
== -1) {
511 DEBUG ((EFI_D_INFO
, "Failed to open serial device, %s!\r\n", UnixIo
->EnvString
));
512 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
513 Status
= EFI_DEVICE_ERROR
;
516 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
519 // Construct Private data
521 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
522 if (Private
== NULL
) {
527 // This signature must be valid before any member function is called
529 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
530 Private
->UnixHandle
= UnixHandle
;
531 Private
->ControllerHandle
= Handle
;
532 Private
->Handle
= NULL
;
533 Private
->UnixThunk
= UnixIo
->UnixThunk
;
534 Private
->ParentDevicePath
= ParentDevicePath
;
535 Private
->ControllerNameTable
= NULL
;
537 Private
->SoftwareLoopbackEnable
= FALSE
;
538 Private
->HardwareLoopbackEnable
= FALSE
;
539 Private
->HardwareFlowControl
= FALSE
;
540 Private
->Fifo
.First
= 0;
541 Private
->Fifo
.Last
= 0;
542 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
544 CopyMem (&Private
->UartDevicePath
, &Node
, sizeof (UART_DEVICE_PATH
));
548 gUnixSerialIoComponentName
.SupportedLanguages
,
549 &Private
->ControllerNameTable
,
553 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
554 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
555 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
556 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
557 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
558 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
559 Private
->SerialIo
.Read
= UnixSerialIoRead
;
560 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
565 // Build the device path by appending the UART node to the ParentDevicePath
566 // from the UnixIo handle. The Uart setings are zero here, since
567 // SetAttribute() will update them to match the current setings.
569 Private
->DevicePath
= AppendDevicePathNode (
571 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
573 if (Private
->DevicePath
== NULL
) {
574 Status
= EFI_OUT_OF_RESOURCES
;
579 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
581 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
582 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
583 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
584 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
585 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
586 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
587 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
590 // Issue a reset to initialize the COM port
592 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
593 if (EFI_ERROR (Status
)) {
598 // Create new child handle
600 Status
= gBS
->InstallMultipleProtocolInterfaces (
602 &gEfiSerialIoProtocolGuid
,
604 &gEfiDevicePathProtocolGuid
,
608 if (EFI_ERROR (Status
)) {
613 // Open For Child Device
615 Status
= gBS
->OpenProtocol (
617 &gEfiUnixIoProtocolGuid
,
619 This
->DriverBindingHandle
,
621 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
623 if (EFI_ERROR (Status
)) {
631 // Use the Stop() function to free all resources allocated in Start()
633 if (Private
!= NULL
) {
634 if (Private
->Handle
!= NULL
) {
635 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
637 if (UnixHandle
!= -1) {
638 Private
->UnixThunk
->Close (UnixHandle
);
641 if (Private
->DevicePath
!= NULL
) {
642 FreePool (Private
->DevicePath
);
645 FreeUnicodeStringTable (Private
->ControllerNameTable
);
651 This
->Stop (This
, Handle
, 0, NULL
);
658 UnixSerialIoDriverBindingStop (
659 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
660 IN EFI_HANDLE Handle
,
661 IN UINTN NumberOfChildren
,
662 IN EFI_HANDLE
*ChildHandleBuffer
668 TODO: Add function description
672 This - TODO: add argument description
673 Handle - TODO: add argument description
674 NumberOfChildren - TODO: add argument description
675 ChildHandleBuffer - TODO: add argument description
679 EFI_DEVICE_ERROR - TODO: Add description for return value
680 EFI_SUCCESS - TODO: Add description for return value
686 BOOLEAN AllChildrenStopped
;
687 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
688 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
689 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
692 // Complete all outstanding transactions to Controller.
693 // Don't allow any new transaction to Controller to be started.
696 if (NumberOfChildren
== 0) {
698 // Close the bus driver
700 Status
= gBS
->CloseProtocol (
702 &gEfiUnixIoProtocolGuid
,
703 This
->DriverBindingHandle
,
706 Status
= gBS
->CloseProtocol (
708 &gEfiDevicePathProtocolGuid
,
709 This
->DriverBindingHandle
,
715 AllChildrenStopped
= TRUE
;
717 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
718 Status
= gBS
->OpenProtocol (
719 ChildHandleBuffer
[Index
],
720 &gEfiSerialIoProtocolGuid
,
722 This
->DriverBindingHandle
,
724 EFI_OPEN_PROTOCOL_GET_PROTOCOL
726 if (!EFI_ERROR (Status
)) {
727 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
729 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
731 Status
= gBS
->CloseProtocol (
733 &gEfiUnixIoProtocolGuid
,
734 This
->DriverBindingHandle
,
735 ChildHandleBuffer
[Index
]
738 Status
= gBS
->UninstallMultipleProtocolInterfaces (
739 ChildHandleBuffer
[Index
],
740 &gEfiSerialIoProtocolGuid
,
742 &gEfiDevicePathProtocolGuid
,
747 if (EFI_ERROR (Status
)) {
750 &gEfiUnixIoProtocolGuid
,
752 This
->DriverBindingHandle
,
753 ChildHandleBuffer
[Index
],
754 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
757 Private
->UnixThunk
->Close (Private
->UnixHandle
);
759 FreePool (Private
->DevicePath
);
761 FreeUnicodeStringTable (Private
->ControllerNameTable
);
767 if (EFI_ERROR (Status
)) {
768 AllChildrenStopped
= FALSE
;
772 if (!AllChildrenStopped
) {
773 return EFI_DEVICE_ERROR
;
780 // Serial IO Protocol member functions
786 IN EFI_SERIAL_IO_PROTOCOL
*This
792 TODO: Add function description
796 This - TODO: add argument description
800 TODO: add return values
804 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
808 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
810 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
812 UnixStatus
= Private
->UnixThunk
->Tcflush (
816 switch (UnixStatus
) {
818 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
819 return EFI_DEVICE_ERROR
;
821 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
822 return EFI_DEVICE_ERROR
;
824 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
825 return EFI_DEVICE_ERROR
;
827 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
830 gBS
->RestoreTPL (Tpl
);
832 return This
->SetAttributes (
834 This
->Mode
->BaudRate
,
835 This
->Mode
->ReceiveFifoDepth
,
838 (UINT8
) This
->Mode
->DataBits
,
845 UnixSerialIoSetAttributes (
846 IN EFI_SERIAL_IO_PROTOCOL
*This
,
848 IN UINT32 ReceiveFifoDepth
,
850 IN EFI_PARITY_TYPE Parity
,
852 IN EFI_STOP_BITS_TYPE StopBits
858 This function is used to set the attributes.
862 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
863 BaudRate - The Baud rate of the serial device.
864 ReceiveFifoDepth - The request depth of fifo on receive side.
865 Timeout - the request timeout for a single charact.
866 Parity - The type of parity used in serial device.
867 DataBits - Number of deata bits used in serial device.
868 StopBits - Number of stop bits used in serial device.
878 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
880 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
882 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
883 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
886 // Some of our arguments have defaults if a null value is passed in, and
887 // we must set the default values if a null argument is passed in.
890 BaudRate
= SERIAL_BAUD_DEFAULT
;
893 if (ReceiveFifoDepth
== 0) {
894 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
898 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
901 if (Parity
== DefaultParity
) {
906 DataBits
= SERIAL_DATABITS_DEFAULT
;
909 if (StopBits
== DefaultStopBits
) {
910 StopBits
= OneStopBit
;
914 // See if the new attributes already match the current attributes
916 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
917 Private
->UartDevicePath
.DataBits
== DataBits
&&
918 Private
->UartDevicePath
.Parity
== Parity
&&
919 Private
->UartDevicePath
.StopBits
== StopBits
&&
920 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
921 Private
->SerialIoMode
.Timeout
== Timeout
) {
922 gBS
->RestoreTPL(Tpl
);
927 // Try to get options from serial device.
929 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
930 Private
->UnixThunk
->Perror ("IoSetAttributes");
931 gBS
->RestoreTPL (Tpl
);
932 return EFI_DEVICE_ERROR
;
938 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
939 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
943 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
944 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
948 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
952 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
956 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
960 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
962 // Support hardware flow control
964 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
968 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
969 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
974 if (-1 == Private
->UnixThunk
->Tcsetattr (
977 &Private
->UnixTermios
979 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
980 return EFI_DEVICE_ERROR
;
986 Private
->SerialIoMode
.BaudRate
= BaudRate
;
987 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
988 Private
->SerialIoMode
.Timeout
= Timeout
;
989 Private
->SerialIoMode
.Parity
= Parity
;
990 Private
->SerialIoMode
.DataBits
= DataBits
;
991 Private
->SerialIoMode
.StopBits
= StopBits
;
993 // See if Device Path Node has actually changed
995 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
996 Private
->UartDevicePath
.DataBits
== DataBits
&&
997 Private
->UartDevicePath
.Parity
== Parity
&&
998 Private
->UartDevicePath
.StopBits
== StopBits
) {
999 gBS
->RestoreTPL(Tpl
);
1004 // Update the device path
1006 Private
->UartDevicePath
.BaudRate
= BaudRate
;
1007 Private
->UartDevicePath
.DataBits
= DataBits
;
1008 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1009 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1011 NewDevicePath
= AppendDevicePathNode (
1012 Private
->ParentDevicePath
,
1013 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
1015 if (NewDevicePath
== NULL
) {
1016 gBS
->RestoreTPL (Tpl
);
1017 return EFI_DEVICE_ERROR
;
1020 if (Private
->Handle
!= NULL
) {
1021 Status
= gBS
->ReinstallProtocolInterface (
1023 &gEfiDevicePathProtocolGuid
,
1024 Private
->DevicePath
,
1027 if (EFI_ERROR (Status
)) {
1028 gBS
->RestoreTPL (Tpl
);
1033 if (Private
->DevicePath
!= NULL
) {
1034 FreePool (Private
->DevicePath
);
1037 Private
->DevicePath
= NewDevicePath
;
1039 gBS
->RestoreTPL (Tpl
);
1046 UnixSerialIoSetControl (
1047 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1052 Routine Description:
1054 TODO: Add function description
1058 This - TODO: add argument description
1059 Control - TODO: add argument description
1063 EFI_DEVICE_ERROR - TODO: Add description for return value
1064 EFI_DEVICE_ERROR - TODO: Add description for return value
1065 EFI_SUCCESS - TODO: Add description for return value
1069 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1072 struct termios Options
;
1075 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1077 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1079 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1082 Private
->UnixThunk
->Perror ("SerialSetControl");
1083 gBS
->RestoreTPL (Tpl
);
1084 return EFI_DEVICE_ERROR
;
1087 Private
->HardwareFlowControl
= FALSE
;
1088 Private
->SoftwareLoopbackEnable
= FALSE
;
1089 Private
->HardwareLoopbackEnable
= FALSE
;
1091 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1092 Options
.c_cflag
|= TIOCM_RTS
;
1095 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1096 Options
.c_cflag
|= TIOCM_DTR
;
1099 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1100 Private
->HardwareFlowControl
= TRUE
;
1103 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1104 Private
->SoftwareLoopbackEnable
= TRUE
;
1107 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1108 Private
->HardwareLoopbackEnable
= TRUE
;
1111 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &Status
);
1114 Private
->UnixThunk
->Perror ("SerialSetControl");
1115 gBS
->RestoreTPL (Tpl
);
1116 return EFI_DEVICE_ERROR
;
1119 gBS
->RestoreTPL (Tpl
);
1126 UnixSerialIoGetControl (
1127 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1132 Routine Description:
1134 TODO: Add function description
1138 This - TODO: add argument description
1139 Control - TODO: add argument description
1143 EFI_DEVICE_ERROR - TODO: Add description for return value
1144 EFI_DEVICE_ERROR - TODO: Add description for return value
1145 EFI_DEVICE_ERROR - TODO: Add description for return value
1146 EFI_SUCCESS - TODO: Add description for return value
1150 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1157 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1159 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1160 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1162 Private
->UnixThunk
->Perror ("SerialGetControl");
1163 gBS
->RestoreTPL (Tpl
);
1164 return EFI_DEVICE_ERROR
;
1168 if ((Status
& TIOCM_CTS
) == TIOCM_CTS
) {
1169 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1172 if ((Status
& TIOCM_DSR
) == TIOCM_DSR
) {
1173 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1176 if ((Status
& TIOCM_DTR
) == TIOCM_DTR
) {
1177 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1180 if ((Status
& TIOCM_RTS
) == TIOCM_RTS
) {
1181 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1184 if ((Status
& TIOCM_RNG
) == TIOCM_RNG
) {
1185 Bits
|= EFI_SERIAL_RING_INDICATE
;
1188 if ((Status
& TIOCM_CAR
) == TIOCM_CAR
) {
1189 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1192 if (Private
->HardwareFlowControl
) {
1193 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1196 if (Private
->SoftwareLoopbackEnable
) {
1197 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1200 if (Private
->HardwareLoopbackEnable
) {
1201 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1204 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, FIONREAD
, &Bytes
);
1206 Private
->UnixThunk
->Perror ("SerialGetControl");
1207 gBS
->RestoreTPL (Tpl
);
1208 return EFI_DEVICE_ERROR
;
1212 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1217 gBS
->RestoreTPL (Tpl
);
1225 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1226 IN OUT UINTN
*BufferSize
,
1231 Routine Description:
1233 TODO: Add function description
1237 This - TODO: add argument description
1238 BufferSize - TODO: add argument description
1239 Buffer - TODO: add argument description
1243 EFI_DEVICE_ERROR - TODO: Add description for return value
1244 EFI_SUCCESS - TODO: Add description for return value
1248 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1251 UINT32 TotalBytesWritten
;
1253 UINT32 BytesWritten
;
1258 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1260 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1262 ByteBuffer
= (UINT8
*) Buffer
;
1263 Status
= EFI_SUCCESS
;
1264 TotalBytesWritten
= 0;
1266 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1267 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1268 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1269 TotalBytesWritten
++;
1275 BytesToGo
= (*BufferSize
);
1278 if (Private
->HardwareFlowControl
) {
1282 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1283 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1284 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1290 BytesWritten
= Private
->UnixThunk
->Write (
1291 Private
->UnixHandle
,
1292 &ByteBuffer
[TotalBytesWritten
],
1295 if (BytesWritten
== -1) {
1296 Status
= EFI_DEVICE_ERROR
;
1300 if (Private
->HardwareFlowControl
) {
1304 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1305 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1306 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1309 TotalBytesWritten
+= BytesWritten
;
1310 BytesToGo
-= BytesWritten
;
1311 } while (BytesToGo
> 0);
1314 *BufferSize
= TotalBytesWritten
;
1316 gBS
->RestoreTPL (Tpl
);
1324 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1325 IN OUT UINTN
*BufferSize
,
1330 Routine Description:
1332 TODO: Add function description
1336 This - TODO: add argument description
1337 BufferSize - TODO: add argument description
1338 Buffer - TODO: add argument description
1342 EFI_DEVICE_ERROR - TODO: Add description for return value
1346 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1354 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1356 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1361 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1362 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1363 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1364 ((UINT8
*) Buffer
)[Index
] = Data
;
1371 if (Private
->HardwareFlowControl
) {
1372 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1373 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1374 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1377 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1378 if (Private
->HardwareFlowControl
) {
1379 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1380 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1381 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1386 if (BytesRead
!= *BufferSize
) {
1387 Status
= EFI_TIMEOUT
;
1389 Status
= EFI_SUCCESS
;
1392 *BufferSize
= (UINTN
) BytesRead
;
1394 gBS
->RestoreTPL (Tpl
);
1401 IN SERIAL_DEV_FIFO
*Fifo
1405 Routine Description:
1406 Detect whether specific FIFO is full or not
1409 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1412 TRUE: the FIFO is full
1413 FALSE: the FIFO is not full
1417 if (Fifo
->Surplus
== 0) {
1425 IsaSerialFifoEmpty (
1426 IN SERIAL_DEV_FIFO
*Fifo
1430 Routine Description:
1431 Detect whether specific FIFO is empty or not
1434 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1437 TRUE: the FIFO is empty
1438 FALSE: the FIFO is not empty
1442 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1451 IN SERIAL_DEV_FIFO
*Fifo
,
1456 Routine Description:
1457 Add data to specific FIFO
1460 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1461 Data UINT8: the data added to FIFO
1464 EFI_SUCCESS: Add data to specific FIFO successfully
1465 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1468 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1471 // if FIFO full can not add data
1473 if (IsaSerialFifoFull (Fifo
)) {
1474 return EFI_OUT_OF_RESOURCES
;
1478 // FIFO is not full can add data
1480 Fifo
->Data
[Fifo
->Last
] = Data
;
1483 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1491 IsaSerialFifoRemove (
1492 IN SERIAL_DEV_FIFO
*Fifo
,
1497 Routine Description:
1498 Remove data from specific FIFO
1501 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1502 Data UINT8*: the data removed from FIFO
1505 EFI_SUCCESS: Remove data from specific FIFO successfully
1506 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1509 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1512 // if FIFO is empty, no data can remove
1514 if (IsaSerialFifoEmpty (Fifo
)) {
1515 return EFI_OUT_OF_RESOURCES
;
1519 // FIFO is not empty, can remove data
1521 *Data
= Fifo
->Data
[Fifo
->First
];
1524 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {