3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Our DriverBinding member functions operate on the handles
19 created by the NT Bus driver.
21 Handle(1) - 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"
51 EFI_DRIVER_BINDING_PROTOCOL gUnixSerialIoDriverBinding
= {
52 UnixSerialIoDriverBindingSupported
,
53 UnixSerialIoDriverBindingStart
,
54 UnixSerialIoDriverBindingStop
,
130 DEBUG ((EFI_D_ERROR
, "Invalid Baud Rate Parameter!\r\n"));
136 ConvertByteSize2Unix (
150 DEBUG ((EFI_D_ERROR
, "Invalid Data Size Parameter!\r\n"));
157 struct termios
*Options
,
158 EFI_PARITY_TYPE Parity
163 Options
->c_cflag
&= ~PARENB
;
166 Options
->c_cflag
|= PARENB
;
169 Options
->c_cflag
|= PARENB
;
170 Options
->c_cflag
|= PARODD
;
173 Options
->c_cflag
= PARENB
| CMSPAR
| PARODD
;
176 Options
->c_cflag
|= PARENB
| CMSPAR
;
177 Options
->c_cflag
&= ~PARODD
;
180 DEBUG ((EFI_D_ERROR
, "Invalid Parity Parameter!\r\n"));
185 ConvertStopBit2Unix (
186 struct termios
*Options
,
187 EFI_STOP_BITS_TYPE StopBits
192 Options
->c_cflag
|= CSTOPB
;
195 case OneFiveStopBits
:
196 case DefaultStopBits
:
197 Options
->c_cflag
&= ~CSTOPB
;
203 UnixSerialIoDriverBindingSupported (
204 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
205 IN EFI_HANDLE Handle
,
206 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
211 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
222 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
223 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
224 UART_DEVICE_PATH
*UartNode
;
227 // Open the IO Abstraction(s) needed to perform the supported test
229 Status
= gBS
->OpenProtocol (
231 &gEfiDevicePathProtocolGuid
,
232 (VOID
**)&ParentDevicePath
,
233 This
->DriverBindingHandle
,
235 EFI_OPEN_PROTOCOL_BY_DRIVER
237 if (Status
== EFI_ALREADY_STARTED
) {
241 if (EFI_ERROR (Status
)) {
247 &gEfiDevicePathProtocolGuid
,
248 This
->DriverBindingHandle
,
252 Status
= gBS
->OpenProtocol (
254 &gEfiUnixIoProtocolGuid
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_BY_DRIVER
260 if (Status
== EFI_ALREADY_STARTED
) {
264 if (EFI_ERROR (Status
)) {
269 // Make sure that the Unix Thunk Protocol is valid
271 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
272 Status
= EFI_UNSUPPORTED
;
277 // Check the GUID to see if this is a handle type the driver supports
279 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
280 Status
= EFI_UNSUPPORTED
;
284 if (RemainingDevicePath
!= NULL
) {
285 Status
= EFI_UNSUPPORTED
;
286 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
287 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
288 UartNode
->Header
.SubType
!= MSG_UART_DP
||
289 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
292 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
295 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
298 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
301 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
304 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
307 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
310 Status
= EFI_SUCCESS
;
315 // Close the I/O Abstraction(s) used to perform the supported test
319 &gEfiUnixIoProtocolGuid
,
320 This
->DriverBindingHandle
,
329 UnixSerialIoDriverBindingStart (
330 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
331 IN EFI_HANDLE Handle
,
332 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
347 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
348 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
350 UART_DEVICE_PATH Node
;
351 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
352 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
355 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
356 CHAR8 AsciiDevName
[1024];
358 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
363 // Grab the protocols we need
365 Status
= gBS
->OpenProtocol (
367 &gEfiDevicePathProtocolGuid
,
368 (VOID
**)&ParentDevicePath
,
369 This
->DriverBindingHandle
,
371 EFI_OPEN_PROTOCOL_BY_DRIVER
373 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
378 // Grab the IO abstraction we need to get any work done
380 Status
= gBS
->OpenProtocol (
382 &gEfiUnixIoProtocolGuid
,
384 This
->DriverBindingHandle
,
386 EFI_OPEN_PROTOCOL_BY_DRIVER
388 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
391 &gEfiDevicePathProtocolGuid
,
392 This
->DriverBindingHandle
,
398 if (Status
== EFI_ALREADY_STARTED
) {
400 if (RemainingDevicePath
== NULL
) {
405 // Make sure a child handle does not already exist. This driver can only
406 // produce one child per serial port.
408 Status
= gBS
->OpenProtocolInformation (
410 &gEfiUnixIoProtocolGuid
,
414 if (EFI_ERROR (Status
)) {
418 Status
= EFI_ALREADY_STARTED
;
419 for (Index
= 0; Index
< EntryCount
; Index
++) {
420 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
421 Status
= gBS
->OpenProtocol (
422 OpenInfoBuffer
[Index
].ControllerHandle
,
423 &gEfiSerialIoProtocolGuid
,
425 This
->DriverBindingHandle
,
427 EFI_OPEN_PROTOCOL_GET_PROTOCOL
429 if (!EFI_ERROR (Status
)) {
430 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
431 Status
= SerialIo
->SetAttributes (
434 SerialIo
->Mode
->ReceiveFifoDepth
,
435 SerialIo
->Mode
->Timeout
,
445 FreePool (OpenInfoBuffer
);
450 // Check to see if we can access the hardware device. If it's Open in Unix we
451 // will not get access.
453 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
454 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
456 if (UnixHandle
== -1) {
457 DEBUG ((EFI_D_INFO
, "Faile to open serial device, %s!\r\n", UnixIo
->EnvString
));
458 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
459 Status
= EFI_DEVICE_ERROR
;
462 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
465 // Construct Private data
467 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
468 if (Private
== NULL
) {
473 // This signature must be valid before any member function is called
475 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
476 Private
->UnixHandle
= UnixHandle
;
477 Private
->ControllerHandle
= Handle
;
478 Private
->Handle
= NULL
;
479 Private
->UnixThunk
= UnixIo
->UnixThunk
;
480 Private
->ParentDevicePath
= ParentDevicePath
;
481 Private
->ControllerNameTable
= NULL
;
483 Private
->SoftwareLoopbackEnable
= FALSE
;
484 Private
->HardwareLoopbackEnable
= FALSE
;
485 Private
->HardwareFlowControl
= FALSE
;
486 Private
->Fifo
.First
= 0;
487 Private
->Fifo
.Last
= 0;
488 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
492 gUnixSerialIoComponentName
.SupportedLanguages
,
493 &Private
->ControllerNameTable
,
497 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
498 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
499 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
500 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
501 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
502 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
503 Private
->SerialIo
.Read
= UnixSerialIoRead
;
504 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
506 if (RemainingDevicePath
!= NULL
) {
508 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
509 // already checked to make sure the RemainingDevicePath contains settings
510 // that we can support.
512 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
515 // Build the device path by appending the UART node to the ParentDevicePath
516 // from the UnixIo handle. The Uart setings are zero here, since
517 // SetAttribute() will update them to match the default setings.
519 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
520 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
521 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
522 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
526 // Build the device path by appending the UART node to the ParentDevicePath
527 // from the UnixIo handle. The Uart setings are zero here, since
528 // SetAttribute() will update them to match the current setings.
530 Private
->DevicePath
= AppendDevicePathNode (
532 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
534 if (Private
->DevicePath
== NULL
) {
535 Status
= EFI_OUT_OF_RESOURCES
;
540 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
542 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
543 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
544 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
545 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
546 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
547 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
548 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
551 // Issue a reset to initialize the COM port
553 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
554 if (EFI_ERROR (Status
)) {
559 // Create new child handle
561 Status
= gBS
->InstallMultipleProtocolInterfaces (
563 &gEfiSerialIoProtocolGuid
,
565 &gEfiDevicePathProtocolGuid
,
569 if (EFI_ERROR (Status
)) {
574 // Open For Child Device
576 Status
= gBS
->OpenProtocol (
578 &gEfiUnixIoProtocolGuid
,
580 This
->DriverBindingHandle
,
582 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
584 if (EFI_ERROR (Status
)) {
592 // Use the Stop() function to free all resources allocated in Start()
594 if (Private
!= NULL
) {
595 if (Private
->Handle
!= NULL
) {
596 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
598 if (UnixHandle
!= -1) {
599 Private
->UnixThunk
->Close (UnixHandle
);
602 if (Private
->DevicePath
!= NULL
) {
603 FreePool (Private
->DevicePath
);
606 FreeUnicodeStringTable (Private
->ControllerNameTable
);
612 This
->Stop (This
, Handle
, 0, NULL
);
619 UnixSerialIoDriverBindingStop (
620 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
621 IN EFI_HANDLE Handle
,
622 IN UINTN NumberOfChildren
,
623 IN EFI_HANDLE
*ChildHandleBuffer
629 TODO: Add function description
633 This - TODO: add argument description
634 Handle - TODO: add argument description
635 NumberOfChildren - TODO: add argument description
636 ChildHandleBuffer - TODO: add argument description
640 EFI_DEVICE_ERROR - TODO: Add description for return value
641 EFI_SUCCESS - TODO: Add description for return value
647 BOOLEAN AllChildrenStopped
;
648 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
649 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
650 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
653 // Complete all outstanding transactions to Controller.
654 // Don't allow any new transaction to Controller to be started.
657 if (NumberOfChildren
== 0) {
659 // Close the bus driver
661 Status
= gBS
->CloseProtocol (
663 &gEfiUnixIoProtocolGuid
,
664 This
->DriverBindingHandle
,
667 Status
= gBS
->CloseProtocol (
669 &gEfiDevicePathProtocolGuid
,
670 This
->DriverBindingHandle
,
676 AllChildrenStopped
= TRUE
;
678 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
679 Status
= gBS
->OpenProtocol (
680 ChildHandleBuffer
[Index
],
681 &gEfiSerialIoProtocolGuid
,
683 This
->DriverBindingHandle
,
685 EFI_OPEN_PROTOCOL_GET_PROTOCOL
687 if (!EFI_ERROR (Status
)) {
688 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
690 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
692 Status
= gBS
->CloseProtocol (
694 &gEfiUnixIoProtocolGuid
,
695 This
->DriverBindingHandle
,
696 ChildHandleBuffer
[Index
]
699 Status
= gBS
->UninstallMultipleProtocolInterfaces (
700 ChildHandleBuffer
[Index
],
701 &gEfiSerialIoProtocolGuid
,
703 &gEfiDevicePathProtocolGuid
,
708 if (EFI_ERROR (Status
)) {
711 &gEfiUnixIoProtocolGuid
,
713 This
->DriverBindingHandle
,
714 ChildHandleBuffer
[Index
],
715 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
718 Private
->UnixThunk
->Close (Private
->UnixHandle
);
720 FreePool (Private
->DevicePath
);
722 FreeUnicodeStringTable (Private
->ControllerNameTable
);
728 if (EFI_ERROR (Status
)) {
729 AllChildrenStopped
= FALSE
;
733 if (!AllChildrenStopped
) {
734 return EFI_DEVICE_ERROR
;
741 // Serial IO Protocol member functions
747 IN EFI_SERIAL_IO_PROTOCOL
*This
753 TODO: Add function description
757 This - TODO: add argument description
761 TODO: add return values
765 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
769 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
771 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
773 UnixStatus
= Private
->UnixThunk
->Tcflush (
777 switch (UnixStatus
) {
779 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
780 return EFI_DEVICE_ERROR
;
782 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
783 return EFI_DEVICE_ERROR
;
785 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
786 return EFI_DEVICE_ERROR
;
788 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
791 gBS
->RestoreTPL (Tpl
);
793 return This
->SetAttributes (
795 This
->Mode
->BaudRate
,
796 This
->Mode
->ReceiveFifoDepth
,
799 (UINT8
) This
->Mode
->DataBits
,
806 UnixSerialIoSetAttributes (
807 IN EFI_SERIAL_IO_PROTOCOL
*This
,
809 IN UINT32 ReceiveFifoDepth
,
811 IN EFI_PARITY_TYPE Parity
,
813 IN EFI_STOP_BITS_TYPE StopBits
819 This function is used to set the attributes.
823 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
824 BaudRate - The Baud rate of the serial device.
825 ReceiveFifoDepth - The request depth of fifo on receive side.
826 Timeout - the request timeout for a single charact.
827 Parity - The type of parity used in serial device.
828 DataBits - Number of deata bits used in serial device.
829 StopBits - Number of stop bits used in serial device.
839 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
841 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
843 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
844 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
847 // Some of our arguments have defaults if a null value is passed in, and
848 // we must set the default values if a null argument is passed in.
851 BaudRate
= SERIAL_BAUD_DEFAULT
;
854 if (ReceiveFifoDepth
== 0) {
855 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
859 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
862 if (Parity
== DefaultParity
) {
867 DataBits
= SERIAL_DATABITS_DEFAULT
;
870 if (StopBits
== DefaultStopBits
) {
871 StopBits
= OneStopBit
;
875 // See if the new attributes already match the current attributes
877 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
878 Private
->UartDevicePath
.DataBits
== DataBits
&&
879 Private
->UartDevicePath
.Parity
== Parity
&&
880 Private
->UartDevicePath
.StopBits
== StopBits
&&
881 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
882 Private
->SerialIoMode
.Timeout
== Timeout
) {
883 gBS
->RestoreTPL(Tpl
);
888 // Try to get options from serial device.
890 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
891 Private
->UnixThunk
->Perror ("IoSetAttributes");
892 gBS
->RestoreTPL (Tpl
);
893 return EFI_DEVICE_ERROR
;
899 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
900 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
904 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
905 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
909 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
913 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
917 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
921 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
923 // Support hardware flow control
925 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
929 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
930 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
935 if (-1 == Private
->UnixThunk
->Tcsetattr (
938 &Private
->UnixTermios
940 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
941 return EFI_DEVICE_ERROR
;
947 Private
->SerialIoMode
.BaudRate
= BaudRate
;
948 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
949 Private
->SerialIoMode
.Timeout
= Timeout
;
950 Private
->SerialIoMode
.Parity
= Parity
;
951 Private
->SerialIoMode
.DataBits
= DataBits
;
952 Private
->SerialIoMode
.StopBits
= StopBits
;
954 // See if Device Path Node has actually changed
956 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
957 Private
->UartDevicePath
.DataBits
== DataBits
&&
958 Private
->UartDevicePath
.Parity
== Parity
&&
959 Private
->UartDevicePath
.StopBits
== StopBits
) {
960 gBS
->RestoreTPL(Tpl
);
965 // Update the device path
967 Private
->UartDevicePath
.BaudRate
= BaudRate
;
968 Private
->UartDevicePath
.DataBits
= DataBits
;
969 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
970 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
972 NewDevicePath
= AppendDevicePathNode (
973 Private
->ParentDevicePath
,
974 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
976 if (NewDevicePath
== NULL
) {
977 gBS
->RestoreTPL (Tpl
);
978 return EFI_DEVICE_ERROR
;
981 if (Private
->Handle
!= NULL
) {
982 Status
= gBS
->ReinstallProtocolInterface (
984 &gEfiDevicePathProtocolGuid
,
988 if (EFI_ERROR (Status
)) {
989 gBS
->RestoreTPL (Tpl
);
994 if (Private
->DevicePath
!= NULL
) {
995 FreePool (Private
->DevicePath
);
998 Private
->DevicePath
= NewDevicePath
;
1000 gBS
->RestoreTPL (Tpl
);
1007 UnixSerialIoSetControl (
1008 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1013 Routine Description:
1015 TODO: Add function description
1019 This - TODO: add argument description
1020 Control - TODO: add argument description
1024 EFI_DEVICE_ERROR - TODO: Add description for return value
1025 EFI_DEVICE_ERROR - TODO: Add description for return value
1026 EFI_SUCCESS - TODO: Add description for return value
1030 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1033 struct termios Options
;
1036 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1038 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1040 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1043 Private
->UnixThunk
->Perror ("SerialSetControl");
1044 gBS
->RestoreTPL (Tpl
);
1045 return EFI_DEVICE_ERROR
;
1048 Private
->HardwareFlowControl
= FALSE
;
1049 Private
->SoftwareLoopbackEnable
= FALSE
;
1050 Private
->HardwareLoopbackEnable
= FALSE
;
1052 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1053 Options
.c_cflag
|= TIOCM_RTS
;
1056 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1057 Options
.c_cflag
|= TIOCM_DTR
;
1060 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1061 Private
->HardwareFlowControl
= TRUE
;
1064 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1065 Private
->SoftwareLoopbackEnable
= TRUE
;
1068 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1069 Private
->HardwareLoopbackEnable
= TRUE
;
1072 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &Status
);
1075 Private
->UnixThunk
->Perror ("SerialSetControl");
1076 gBS
->RestoreTPL (Tpl
);
1077 return EFI_DEVICE_ERROR
;
1080 gBS
->RestoreTPL (Tpl
);
1087 UnixSerialIoGetControl (
1088 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1093 Routine Description:
1095 TODO: Add function description
1099 This - TODO: add argument description
1100 Control - TODO: add argument description
1104 EFI_DEVICE_ERROR - TODO: Add description for return value
1105 EFI_DEVICE_ERROR - TODO: Add description for return value
1106 EFI_DEVICE_ERROR - TODO: Add description for return value
1107 EFI_SUCCESS - TODO: Add description for return value
1111 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1118 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1120 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1121 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1123 Private
->UnixThunk
->Perror ("SerialGetControl");
1124 gBS
->RestoreTPL (Tpl
);
1125 return EFI_DEVICE_ERROR
;
1128 if ((Status
& TIOCM_CTS
) == TIOCM_CTS
) {
1129 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1132 if ((Status
& TIOCM_DSR
) == TIOCM_DSR
) {
1133 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1136 if ((Status
& TIOCM_DTR
) == TIOCM_DTR
) {
1137 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1140 if ((Status
& TIOCM_RTS
) == TIOCM_RTS
) {
1141 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1144 if ((Status
& TIOCM_RNG
) == TIOCM_RNG
) {
1145 Bits
|= EFI_SERIAL_RING_INDICATE
;
1148 if ((Status
& TIOCM_CAR
) == TIOCM_CAR
) {
1149 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1152 if (Private
->HardwareFlowControl
) {
1153 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1156 if (Private
->SoftwareLoopbackEnable
) {
1157 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1160 if (Private
->HardwareLoopbackEnable
) {
1161 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1164 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, FIONREAD
, &Bytes
);
1166 Private
->UnixThunk
->Perror ("SerialGetControl");
1167 gBS
->RestoreTPL (Tpl
);
1168 return EFI_DEVICE_ERROR
;
1172 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1177 gBS
->RestoreTPL (Tpl
);
1185 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1186 IN OUT UINTN
*BufferSize
,
1191 Routine Description:
1193 TODO: Add function description
1197 This - TODO: add argument description
1198 BufferSize - TODO: add argument description
1199 Buffer - TODO: add argument description
1203 EFI_DEVICE_ERROR - TODO: Add description for return value
1204 EFI_SUCCESS - TODO: Add description for return value
1208 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1210 UINT32 TotalBytesWritten
;
1212 UINT32 BytesWritten
;
1217 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1219 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1221 ByteBuffer
= (UINT8
*) Buffer
;
1222 TotalBytesWritten
= 0;
1224 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1225 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1226 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1227 TotalBytesWritten
++;
1233 BytesToGo
= (*BufferSize
);
1236 if (Private
->HardwareFlowControl
) {
1240 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1241 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1242 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1248 BytesWritten
= Private
->UnixThunk
->Write (
1249 Private
->UnixHandle
,
1250 &ByteBuffer
[TotalBytesWritten
],
1254 if (Private
->HardwareFlowControl
) {
1258 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1259 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1260 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1263 TotalBytesWritten
+= BytesWritten
;
1264 BytesToGo
-= BytesWritten
;
1265 } while (BytesToGo
> 0);
1268 *BufferSize
= TotalBytesWritten
;
1270 gBS
->RestoreTPL (Tpl
);
1278 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1279 IN OUT UINTN
*BufferSize
,
1284 Routine Description:
1286 TODO: Add function description
1290 This - TODO: add argument description
1291 BufferSize - TODO: add argument description
1292 Buffer - TODO: add argument description
1296 EFI_DEVICE_ERROR - TODO: Add description for return value
1300 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1308 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1310 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1315 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1316 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1317 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1318 ((UINT8
*) Buffer
)[Index
] = Data
;
1325 if (Private
->HardwareFlowControl
) {
1326 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1327 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1328 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1331 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1332 if (Private
->HardwareFlowControl
) {
1333 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1334 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1335 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1340 if (BytesRead
!= *BufferSize
) {
1341 Status
= EFI_TIMEOUT
;
1343 Status
= EFI_SUCCESS
;
1346 *BufferSize
= (UINTN
) BytesRead
;
1348 gBS
->RestoreTPL (Tpl
);
1355 IN SERIAL_DEV_FIFO
*Fifo
1359 Routine Description:
1360 Detect whether specific FIFO is full or not
1363 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1366 TRUE: the FIFO is full
1367 FALSE: the FIFO is not full
1371 if (Fifo
->Surplus
== 0) {
1379 IsaSerialFifoEmpty (
1380 IN SERIAL_DEV_FIFO
*Fifo
1384 Routine Description:
1385 Detect whether specific FIFO is empty or not
1388 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1391 TRUE: the FIFO is empty
1392 FALSE: the FIFO is not empty
1396 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1405 IN SERIAL_DEV_FIFO
*Fifo
,
1410 Routine Description:
1411 Add data to specific FIFO
1414 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1415 Data UINT8: the data added to FIFO
1418 EFI_SUCCESS: Add data to specific FIFO successfully
1419 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1422 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1425 // if FIFO full can not add data
1427 if (IsaSerialFifoFull (Fifo
)) {
1428 return EFI_OUT_OF_RESOURCES
;
1432 // FIFO is not full can add data
1434 Fifo
->Data
[Fifo
->Last
] = Data
;
1437 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1445 IsaSerialFifoRemove (
1446 IN SERIAL_DEV_FIFO
*Fifo
,
1451 Routine Description:
1452 Remove data from specific FIFO
1455 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1456 Data UINT8*: the data removed from FIFO
1459 EFI_SUCCESS: Remove data from specific FIFO successfully
1460 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1463 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1466 // if FIFO is empty, no data can remove
1468 if (IsaSerialFifoEmpty (Fifo
)) {
1469 return EFI_OUT_OF_RESOURCES
;
1473 // FIFO is not empty, can remove data
1475 *Data
= Fifo
->Data
[Fifo
->First
];
1478 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {