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 // Open the IO Abstraction(s) needed to perform the supported test
228 Status
= gBS
->OpenProtocol (
230 &gEfiDevicePathProtocolGuid
,
231 (VOID
**)&ParentDevicePath
,
232 This
->DriverBindingHandle
,
234 EFI_OPEN_PROTOCOL_BY_DRIVER
236 if (Status
== EFI_ALREADY_STARTED
) {
240 if (EFI_ERROR (Status
)) {
246 &gEfiDevicePathProtocolGuid
,
247 This
->DriverBindingHandle
,
251 Status
= gBS
->OpenProtocol (
253 &gEfiUnixIoProtocolGuid
,
255 This
->DriverBindingHandle
,
257 EFI_OPEN_PROTOCOL_BY_DRIVER
259 if (Status
== EFI_ALREADY_STARTED
) {
263 if (EFI_ERROR (Status
)) {
268 // Make sure that the Unix Thunk Protocol is valid
270 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
271 Status
= EFI_UNSUPPORTED
;
276 // Check the GUID to see if this is a handle type the driver supports
278 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
279 Status
= EFI_UNSUPPORTED
;
283 if (RemainingDevicePath
!= NULL
) {
284 Status
= EFI_UNSUPPORTED
;
285 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
286 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
287 UartNode
->Header
.SubType
!= MSG_UART_DP
||
288 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
291 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
294 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
297 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
300 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
303 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
306 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
309 Status
= EFI_SUCCESS
;
314 // Close the I/O Abstraction(s) used to perform the supported test
318 &gEfiUnixIoProtocolGuid
,
319 This
->DriverBindingHandle
,
328 UnixSerialIoDriverBindingStart (
329 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
330 IN EFI_HANDLE Handle
,
331 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
346 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
347 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
349 UART_DEVICE_PATH Node
;
350 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
351 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
354 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
355 CHAR8 AsciiDevName
[1024];
357 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
362 // Grab the protocols we need
364 Status
= gBS
->OpenProtocol (
366 &gEfiDevicePathProtocolGuid
,
367 (VOID
**)&ParentDevicePath
,
368 This
->DriverBindingHandle
,
370 EFI_OPEN_PROTOCOL_BY_DRIVER
372 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
377 // Grab the IO abstraction we need to get any work done
379 Status
= gBS
->OpenProtocol (
381 &gEfiUnixIoProtocolGuid
,
383 This
->DriverBindingHandle
,
385 EFI_OPEN_PROTOCOL_BY_DRIVER
387 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
390 &gEfiDevicePathProtocolGuid
,
391 This
->DriverBindingHandle
,
397 if (Status
== EFI_ALREADY_STARTED
) {
399 if (RemainingDevicePath
== NULL
) {
404 // Make sure a child handle does not already exist. This driver can only
405 // produce one child per serial port.
407 Status
= gBS
->OpenProtocolInformation (
409 &gEfiUnixIoProtocolGuid
,
413 if (EFI_ERROR (Status
)) {
417 Status
= EFI_ALREADY_STARTED
;
418 for (Index
= 0; Index
< EntryCount
; Index
++) {
419 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
420 Status
= gBS
->OpenProtocol (
421 OpenInfoBuffer
[Index
].ControllerHandle
,
422 &gEfiSerialIoProtocolGuid
,
424 This
->DriverBindingHandle
,
426 EFI_OPEN_PROTOCOL_GET_PROTOCOL
428 if (!EFI_ERROR (Status
)) {
429 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
430 Status
= SerialIo
->SetAttributes (
433 SerialIo
->Mode
->ReceiveFifoDepth
,
434 SerialIo
->Mode
->Timeout
,
444 FreePool (OpenInfoBuffer
);
449 // Check to see if we can access the hardware device. If it's Open in Unix we
450 // will not get access.
452 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
453 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
455 if (UnixHandle
== -1) {
456 DEBUG ((EFI_D_INFO
, "Failed to open serial device, %s!\r\n", UnixIo
->EnvString
));
457 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
458 Status
= EFI_DEVICE_ERROR
;
461 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
464 // Construct Private data
466 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
467 if (Private
== NULL
) {
472 // This signature must be valid before any member function is called
474 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
475 Private
->UnixHandle
= UnixHandle
;
476 Private
->ControllerHandle
= Handle
;
477 Private
->Handle
= NULL
;
478 Private
->UnixThunk
= UnixIo
->UnixThunk
;
479 Private
->ParentDevicePath
= ParentDevicePath
;
480 Private
->ControllerNameTable
= NULL
;
482 Private
->SoftwareLoopbackEnable
= FALSE
;
483 Private
->HardwareLoopbackEnable
= FALSE
;
484 Private
->HardwareFlowControl
= FALSE
;
485 Private
->Fifo
.First
= 0;
486 Private
->Fifo
.Last
= 0;
487 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
491 gUnixSerialIoComponentName
.SupportedLanguages
,
492 &Private
->ControllerNameTable
,
496 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
497 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
498 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
499 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
500 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
501 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
502 Private
->SerialIo
.Read
= UnixSerialIoRead
;
503 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
505 if (RemainingDevicePath
!= NULL
) {
507 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
508 // already checked to make sure the RemainingDevicePath contains settings
509 // that we can support.
511 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
514 // Build the device path by appending the UART node to the ParentDevicePath
515 // from the UnixIo handle. The Uart setings are zero here, since
516 // SetAttribute() will update them to match the default setings.
518 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
519 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
520 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
521 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
525 // Build the device path by appending the UART node to the ParentDevicePath
526 // from the UnixIo handle. The Uart setings are zero here, since
527 // SetAttribute() will update them to match the current setings.
529 Private
->DevicePath
= AppendDevicePathNode (
531 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
533 if (Private
->DevicePath
== NULL
) {
534 Status
= EFI_OUT_OF_RESOURCES
;
539 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
541 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
542 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
543 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
544 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
545 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
546 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
547 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
550 // Issue a reset to initialize the COM port
552 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
553 if (EFI_ERROR (Status
)) {
558 // Create new child handle
560 Status
= gBS
->InstallMultipleProtocolInterfaces (
562 &gEfiSerialIoProtocolGuid
,
564 &gEfiDevicePathProtocolGuid
,
568 if (EFI_ERROR (Status
)) {
573 // Open For Child Device
575 Status
= gBS
->OpenProtocol (
577 &gEfiUnixIoProtocolGuid
,
579 This
->DriverBindingHandle
,
581 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
583 if (EFI_ERROR (Status
)) {
591 // Use the Stop() function to free all resources allocated in Start()
593 if (Private
!= NULL
) {
594 if (Private
->Handle
!= NULL
) {
595 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
597 if (UnixHandle
!= -1) {
598 Private
->UnixThunk
->Close (UnixHandle
);
601 if (Private
->DevicePath
!= NULL
) {
602 FreePool (Private
->DevicePath
);
605 FreeUnicodeStringTable (Private
->ControllerNameTable
);
611 This
->Stop (This
, Handle
, 0, NULL
);
618 UnixSerialIoDriverBindingStop (
619 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
620 IN EFI_HANDLE Handle
,
621 IN UINTN NumberOfChildren
,
622 IN EFI_HANDLE
*ChildHandleBuffer
628 TODO: Add function description
632 This - TODO: add argument description
633 Handle - TODO: add argument description
634 NumberOfChildren - TODO: add argument description
635 ChildHandleBuffer - TODO: add argument description
639 EFI_DEVICE_ERROR - TODO: Add description for return value
640 EFI_SUCCESS - TODO: Add description for return value
646 BOOLEAN AllChildrenStopped
;
647 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
648 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
649 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
652 // Complete all outstanding transactions to Controller.
653 // Don't allow any new transaction to Controller to be started.
656 if (NumberOfChildren
== 0) {
658 // Close the bus driver
660 Status
= gBS
->CloseProtocol (
662 &gEfiUnixIoProtocolGuid
,
663 This
->DriverBindingHandle
,
666 Status
= gBS
->CloseProtocol (
668 &gEfiDevicePathProtocolGuid
,
669 This
->DriverBindingHandle
,
675 AllChildrenStopped
= TRUE
;
677 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
678 Status
= gBS
->OpenProtocol (
679 ChildHandleBuffer
[Index
],
680 &gEfiSerialIoProtocolGuid
,
682 This
->DriverBindingHandle
,
684 EFI_OPEN_PROTOCOL_GET_PROTOCOL
686 if (!EFI_ERROR (Status
)) {
687 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
689 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
691 Status
= gBS
->CloseProtocol (
693 &gEfiUnixIoProtocolGuid
,
694 This
->DriverBindingHandle
,
695 ChildHandleBuffer
[Index
]
698 Status
= gBS
->UninstallMultipleProtocolInterfaces (
699 ChildHandleBuffer
[Index
],
700 &gEfiSerialIoProtocolGuid
,
702 &gEfiDevicePathProtocolGuid
,
707 if (EFI_ERROR (Status
)) {
710 &gEfiUnixIoProtocolGuid
,
712 This
->DriverBindingHandle
,
713 ChildHandleBuffer
[Index
],
714 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
717 Private
->UnixThunk
->Close (Private
->UnixHandle
);
719 FreePool (Private
->DevicePath
);
721 FreeUnicodeStringTable (Private
->ControllerNameTable
);
727 if (EFI_ERROR (Status
)) {
728 AllChildrenStopped
= FALSE
;
732 if (!AllChildrenStopped
) {
733 return EFI_DEVICE_ERROR
;
740 // Serial IO Protocol member functions
746 IN EFI_SERIAL_IO_PROTOCOL
*This
752 TODO: Add function description
756 This - TODO: add argument description
760 TODO: add return values
764 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
768 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
770 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
772 UnixStatus
= Private
->UnixThunk
->Tcflush (
776 switch (UnixStatus
) {
778 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
779 return EFI_DEVICE_ERROR
;
781 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
782 return EFI_DEVICE_ERROR
;
784 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
785 return EFI_DEVICE_ERROR
;
787 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
790 gBS
->RestoreTPL (Tpl
);
792 return This
->SetAttributes (
794 This
->Mode
->BaudRate
,
795 This
->Mode
->ReceiveFifoDepth
,
798 (UINT8
) This
->Mode
->DataBits
,
805 UnixSerialIoSetAttributes (
806 IN EFI_SERIAL_IO_PROTOCOL
*This
,
808 IN UINT32 ReceiveFifoDepth
,
810 IN EFI_PARITY_TYPE Parity
,
812 IN EFI_STOP_BITS_TYPE StopBits
818 This function is used to set the attributes.
822 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
823 BaudRate - The Baud rate of the serial device.
824 ReceiveFifoDepth - The request depth of fifo on receive side.
825 Timeout - the request timeout for a single charact.
826 Parity - The type of parity used in serial device.
827 DataBits - Number of deata bits used in serial device.
828 StopBits - Number of stop bits used in serial device.
838 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
840 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
842 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
843 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
846 // Some of our arguments have defaults if a null value is passed in, and
847 // we must set the default values if a null argument is passed in.
850 BaudRate
= SERIAL_BAUD_DEFAULT
;
853 if (ReceiveFifoDepth
== 0) {
854 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
858 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
861 if (Parity
== DefaultParity
) {
866 DataBits
= SERIAL_DATABITS_DEFAULT
;
869 if (StopBits
== DefaultStopBits
) {
870 StopBits
= OneStopBit
;
874 // See if the new attributes already match the current attributes
876 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
877 Private
->UartDevicePath
.DataBits
== DataBits
&&
878 Private
->UartDevicePath
.Parity
== Parity
&&
879 Private
->UartDevicePath
.StopBits
== StopBits
&&
880 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
881 Private
->SerialIoMode
.Timeout
== Timeout
) {
882 gBS
->RestoreTPL(Tpl
);
887 // Try to get options from serial device.
889 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
890 Private
->UnixThunk
->Perror ("IoSetAttributes");
891 gBS
->RestoreTPL (Tpl
);
892 return EFI_DEVICE_ERROR
;
898 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
899 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
903 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
904 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
908 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
912 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
916 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
920 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
922 // Support hardware flow control
924 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
928 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
929 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
934 if (-1 == Private
->UnixThunk
->Tcsetattr (
937 &Private
->UnixTermios
939 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
940 return EFI_DEVICE_ERROR
;
946 Private
->SerialIoMode
.BaudRate
= BaudRate
;
947 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
948 Private
->SerialIoMode
.Timeout
= Timeout
;
949 Private
->SerialIoMode
.Parity
= Parity
;
950 Private
->SerialIoMode
.DataBits
= DataBits
;
951 Private
->SerialIoMode
.StopBits
= StopBits
;
953 // See if Device Path Node has actually changed
955 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
956 Private
->UartDevicePath
.DataBits
== DataBits
&&
957 Private
->UartDevicePath
.Parity
== Parity
&&
958 Private
->UartDevicePath
.StopBits
== StopBits
) {
959 gBS
->RestoreTPL(Tpl
);
964 // Update the device path
966 Private
->UartDevicePath
.BaudRate
= BaudRate
;
967 Private
->UartDevicePath
.DataBits
= DataBits
;
968 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
969 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
971 NewDevicePath
= AppendDevicePathNode (
972 Private
->ParentDevicePath
,
973 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
975 if (NewDevicePath
== NULL
) {
976 gBS
->RestoreTPL (Tpl
);
977 return EFI_DEVICE_ERROR
;
980 if (Private
->Handle
!= NULL
) {
981 Status
= gBS
->ReinstallProtocolInterface (
983 &gEfiDevicePathProtocolGuid
,
987 if (EFI_ERROR (Status
)) {
988 gBS
->RestoreTPL (Tpl
);
993 if (Private
->DevicePath
!= NULL
) {
994 FreePool (Private
->DevicePath
);
997 Private
->DevicePath
= NewDevicePath
;
999 gBS
->RestoreTPL (Tpl
);
1006 UnixSerialIoSetControl (
1007 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1012 Routine Description:
1014 TODO: Add function description
1018 This - TODO: add argument description
1019 Control - TODO: add argument description
1023 EFI_DEVICE_ERROR - TODO: Add description for return value
1024 EFI_DEVICE_ERROR - TODO: Add description for return value
1025 EFI_SUCCESS - TODO: Add description for return value
1029 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1032 struct termios Options
;
1035 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1037 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1039 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1042 Private
->UnixThunk
->Perror ("SerialSetControl");
1043 gBS
->RestoreTPL (Tpl
);
1044 return EFI_DEVICE_ERROR
;
1047 Private
->HardwareFlowControl
= FALSE
;
1048 Private
->SoftwareLoopbackEnable
= FALSE
;
1049 Private
->HardwareLoopbackEnable
= FALSE
;
1051 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1052 Options
.c_cflag
|= TIOCM_RTS
;
1055 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1056 Options
.c_cflag
|= TIOCM_DTR
;
1059 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1060 Private
->HardwareFlowControl
= TRUE
;
1063 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1064 Private
->SoftwareLoopbackEnable
= TRUE
;
1067 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1068 Private
->HardwareLoopbackEnable
= TRUE
;
1071 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &Status
);
1074 Private
->UnixThunk
->Perror ("SerialSetControl");
1075 gBS
->RestoreTPL (Tpl
);
1076 return EFI_DEVICE_ERROR
;
1079 gBS
->RestoreTPL (Tpl
);
1086 UnixSerialIoGetControl (
1087 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1092 Routine Description:
1094 TODO: Add function description
1098 This - TODO: add argument description
1099 Control - TODO: add argument description
1103 EFI_DEVICE_ERROR - TODO: Add description for return value
1104 EFI_DEVICE_ERROR - TODO: Add description for return value
1105 EFI_DEVICE_ERROR - TODO: Add description for return value
1106 EFI_SUCCESS - TODO: Add description for return value
1110 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1117 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1119 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1120 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1122 Private
->UnixThunk
->Perror ("SerialGetControl");
1123 gBS
->RestoreTPL (Tpl
);
1124 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
;
1211 UINT32 TotalBytesWritten
;
1213 UINT32 BytesWritten
;
1218 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1220 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1222 ByteBuffer
= (UINT8
*) Buffer
;
1223 Status
= EFI_SUCCESS
;
1224 TotalBytesWritten
= 0;
1226 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1227 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1228 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1229 TotalBytesWritten
++;
1235 BytesToGo
= (*BufferSize
);
1238 if (Private
->HardwareFlowControl
) {
1242 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1243 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1244 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1250 BytesWritten
= Private
->UnixThunk
->Write (
1251 Private
->UnixHandle
,
1252 &ByteBuffer
[TotalBytesWritten
],
1255 if (BytesWritten
== -1) {
1256 Status
= EFI_DEVICE_ERROR
;
1260 if (Private
->HardwareFlowControl
) {
1264 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1265 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1266 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1269 TotalBytesWritten
+= BytesWritten
;
1270 BytesToGo
-= BytesWritten
;
1271 } while (BytesToGo
> 0);
1274 *BufferSize
= TotalBytesWritten
;
1276 gBS
->RestoreTPL (Tpl
);
1284 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1285 IN OUT UINTN
*BufferSize
,
1290 Routine Description:
1292 TODO: Add function description
1296 This - TODO: add argument description
1297 BufferSize - TODO: add argument description
1298 Buffer - TODO: add argument description
1302 EFI_DEVICE_ERROR - TODO: Add description for return value
1306 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1314 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1316 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1321 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1322 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1323 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1324 ((UINT8
*) Buffer
)[Index
] = Data
;
1331 if (Private
->HardwareFlowControl
) {
1332 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1333 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1334 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1337 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1338 if (Private
->HardwareFlowControl
) {
1339 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1340 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1341 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1346 if (BytesRead
!= *BufferSize
) {
1347 Status
= EFI_TIMEOUT
;
1349 Status
= EFI_SUCCESS
;
1352 *BufferSize
= (UINTN
) BytesRead
;
1354 gBS
->RestoreTPL (Tpl
);
1361 IN SERIAL_DEV_FIFO
*Fifo
1365 Routine Description:
1366 Detect whether specific FIFO is full or not
1369 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1372 TRUE: the FIFO is full
1373 FALSE: the FIFO is not full
1377 if (Fifo
->Surplus
== 0) {
1385 IsaSerialFifoEmpty (
1386 IN SERIAL_DEV_FIFO
*Fifo
1390 Routine Description:
1391 Detect whether specific FIFO is empty or not
1394 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1397 TRUE: the FIFO is empty
1398 FALSE: the FIFO is not empty
1402 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1411 IN SERIAL_DEV_FIFO
*Fifo
,
1416 Routine Description:
1417 Add data to specific FIFO
1420 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1421 Data UINT8: the data added to FIFO
1424 EFI_SUCCESS: Add data to specific FIFO successfully
1425 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1428 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1431 // if FIFO full can not add data
1433 if (IsaSerialFifoFull (Fifo
)) {
1434 return EFI_OUT_OF_RESOURCES
;
1438 // FIFO is not full can add data
1440 Fifo
->Data
[Fifo
->Last
] = Data
;
1443 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1451 IsaSerialFifoRemove (
1452 IN SERIAL_DEV_FIFO
*Fifo
,
1457 Routine Description:
1458 Remove data from specific FIFO
1461 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1462 Data UINT8*: the data removed from FIFO
1465 EFI_SUCCESS: Remove data from specific FIFO successfully
1466 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1469 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1472 // if FIFO is empty, no data can remove
1474 if (IsaSerialFifoEmpty (Fifo
)) {
1475 return EFI_OUT_OF_RESOURCES
;
1479 // FIFO is not empty, can remove data
1481 *Data
= Fifo
->Data
[Fifo
->First
];
1484 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {