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
,
131 DEBUG ((EFI_D_ERROR
, "Invalid Baud Rate Parameter!\r\n"));
138 ConvertByteSize2Unix (
152 DEBUG ((EFI_D_ERROR
, "Invalid Data Size Parameter!\r\n"));
160 struct termios
*Options
,
161 EFI_PARITY_TYPE Parity
166 Options
->c_cflag
&= ~PARENB
;
169 Options
->c_cflag
|= PARENB
;
172 Options
->c_cflag
|= PARENB
;
173 Options
->c_cflag
|= PARODD
;
176 Options
->c_cflag
= PARENB
| CMSPAR
| PARODD
;
179 Options
->c_cflag
|= PARENB
| CMSPAR
;
180 Options
->c_cflag
&= ~PARODD
;
183 DEBUG ((EFI_D_ERROR
, "Invalid Parity Parameter!\r\n"));
189 ConvertStopBit2Unix (
190 struct termios
*Options
,
191 EFI_STOP_BITS_TYPE StopBits
196 Options
->c_cflag
|= CSTOPB
;
199 case OneFiveStopBits
:
200 case DefaultStopBits
:
201 Options
->c_cflag
&= ~CSTOPB
;
207 UnixSerialIoDriverBindingSupported (
208 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
209 IN EFI_HANDLE Handle
,
210 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
215 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
226 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
227 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
228 UART_DEVICE_PATH
*UartNode
;
231 // Open the IO Abstraction(s) needed to perform the supported test
233 Status
= gBS
->OpenProtocol (
235 &gEfiDevicePathProtocolGuid
,
236 (VOID
**)&ParentDevicePath
,
237 This
->DriverBindingHandle
,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
241 if (Status
== EFI_ALREADY_STARTED
) {
245 if (EFI_ERROR (Status
)) {
251 &gEfiDevicePathProtocolGuid
,
252 This
->DriverBindingHandle
,
256 Status
= gBS
->OpenProtocol (
258 &gEfiUnixIoProtocolGuid
,
260 This
->DriverBindingHandle
,
262 EFI_OPEN_PROTOCOL_BY_DRIVER
264 if (Status
== EFI_ALREADY_STARTED
) {
268 if (EFI_ERROR (Status
)) {
273 // Make sure that the Unix Thunk Protocol is valid
275 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
276 Status
= EFI_UNSUPPORTED
;
281 // Check the GUID to see if this is a handle type the driver supports
283 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
284 Status
= EFI_UNSUPPORTED
;
288 if (RemainingDevicePath
!= NULL
) {
289 Status
= EFI_UNSUPPORTED
;
290 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
291 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
292 UartNode
->Header
.SubType
!= MSG_UART_DP
||
293 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
296 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
299 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
302 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
305 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
308 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
311 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
314 Status
= EFI_SUCCESS
;
319 // Close the I/O Abstraction(s) used to perform the supported test
323 &gEfiUnixIoProtocolGuid
,
324 This
->DriverBindingHandle
,
333 UnixSerialIoDriverBindingStart (
334 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
335 IN EFI_HANDLE Handle
,
336 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
351 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
352 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
354 UART_DEVICE_PATH Node
;
355 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
356 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
359 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
360 CHAR8 AsciiDevName
[1024];
362 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
367 // Grab the protocols we need
369 Status
= gBS
->OpenProtocol (
371 &gEfiDevicePathProtocolGuid
,
372 (VOID
**)&ParentDevicePath
,
373 This
->DriverBindingHandle
,
375 EFI_OPEN_PROTOCOL_BY_DRIVER
377 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
382 // Grab the IO abstraction we need to get any work done
384 Status
= gBS
->OpenProtocol (
386 &gEfiUnixIoProtocolGuid
,
388 This
->DriverBindingHandle
,
390 EFI_OPEN_PROTOCOL_BY_DRIVER
392 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
395 &gEfiDevicePathProtocolGuid
,
396 This
->DriverBindingHandle
,
402 if (Status
== EFI_ALREADY_STARTED
) {
404 if (RemainingDevicePath
== NULL
) {
409 // Make sure a child handle does not already exist. This driver can only
410 // produce one child per serial port.
412 Status
= gBS
->OpenProtocolInformation (
414 &gEfiUnixIoProtocolGuid
,
418 if (EFI_ERROR (Status
)) {
422 Status
= EFI_ALREADY_STARTED
;
423 for (Index
= 0; Index
< EntryCount
; Index
++) {
424 if (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) {
425 Status
= gBS
->OpenProtocol (
426 OpenInfoBuffer
[Index
].ControllerHandle
,
427 &gEfiSerialIoProtocolGuid
,
429 This
->DriverBindingHandle
,
431 EFI_OPEN_PROTOCOL_GET_PROTOCOL
433 if (!EFI_ERROR (Status
)) {
434 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
435 Status
= SerialIo
->SetAttributes (
438 SerialIo
->Mode
->ReceiveFifoDepth
,
439 SerialIo
->Mode
->Timeout
,
449 FreePool (OpenInfoBuffer
);
454 // Check to see if we can access the hardware device. If it's Open in Unix we
455 // will not get access.
457 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
458 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
460 if (UnixHandle
== -1) {
461 DEBUG ((EFI_D_INFO
, "Faile to open serial device, %s!\r\n", UnixIo
->EnvString
));
462 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
463 Status
= EFI_DEVICE_ERROR
;
466 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
469 // Construct Private data
471 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
472 if (Private
== NULL
) {
477 // This signature must be valid before any member function is called
479 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
480 Private
->UnixHandle
= UnixHandle
;
481 Private
->ControllerHandle
= Handle
;
482 Private
->Handle
= NULL
;
483 Private
->UnixThunk
= UnixIo
->UnixThunk
;
484 Private
->ParentDevicePath
= ParentDevicePath
;
485 Private
->ControllerNameTable
= NULL
;
487 Private
->SoftwareLoopbackEnable
= FALSE
;
488 Private
->HardwareLoopbackEnable
= FALSE
;
489 Private
->HardwareFlowControl
= FALSE
;
490 Private
->Fifo
.First
= 0;
491 Private
->Fifo
.Last
= 0;
492 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
496 gUnixSerialIoComponentName
.SupportedLanguages
,
497 &Private
->ControllerNameTable
,
501 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
502 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
503 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
504 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
505 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
506 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
507 Private
->SerialIo
.Read
= UnixSerialIoRead
;
508 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
510 if (RemainingDevicePath
!= NULL
) {
512 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
513 // already checked to make sure the RemainingDevicePath contains settings
514 // that we can support.
516 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
519 // Build the device path by appending the UART node to the ParentDevicePath
520 // from the UnixIo handle. The Uart setings are zero here, since
521 // SetAttribute() will update them to match the default setings.
523 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
524 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
525 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
526 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
530 // Build the device path by appending the UART node to the ParentDevicePath
531 // from the UnixIo handle. The Uart setings are zero here, since
532 // SetAttribute() will update them to match the current setings.
534 Private
->DevicePath
= AppendDevicePathNode (
536 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
538 if (Private
->DevicePath
== NULL
) {
539 Status
= EFI_OUT_OF_RESOURCES
;
544 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
546 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
547 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
548 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
549 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
550 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
551 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
552 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
555 // Issue a reset to initialize the COM port
557 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
558 if (EFI_ERROR (Status
)) {
563 // Create new child handle
565 Status
= gBS
->InstallMultipleProtocolInterfaces (
567 &gEfiSerialIoProtocolGuid
,
569 &gEfiDevicePathProtocolGuid
,
573 if (EFI_ERROR (Status
)) {
578 // Open For Child Device
580 Status
= gBS
->OpenProtocol (
582 &gEfiUnixIoProtocolGuid
,
584 This
->DriverBindingHandle
,
586 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
588 if (EFI_ERROR (Status
)) {
596 // Use the Stop() function to free all resources allocated in Start()
598 if (Private
!= NULL
) {
599 if (Private
->Handle
!= NULL
) {
600 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
602 if (UnixHandle
!= -1) {
603 Private
->UnixThunk
->Close (UnixHandle
);
606 if (Private
->DevicePath
!= NULL
) {
607 FreePool (Private
->DevicePath
);
610 FreeUnicodeStringTable (Private
->ControllerNameTable
);
616 This
->Stop (This
, Handle
, 0, NULL
);
623 UnixSerialIoDriverBindingStop (
624 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
625 IN EFI_HANDLE Handle
,
626 IN UINTN NumberOfChildren
,
627 IN EFI_HANDLE
*ChildHandleBuffer
633 TODO: Add function description
637 This - TODO: add argument description
638 Handle - TODO: add argument description
639 NumberOfChildren - TODO: add argument description
640 ChildHandleBuffer - TODO: add argument description
644 EFI_DEVICE_ERROR - TODO: Add description for return value
645 EFI_SUCCESS - TODO: Add description for return value
651 BOOLEAN AllChildrenStopped
;
652 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
653 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
654 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
657 // Complete all outstanding transactions to Controller.
658 // Don't allow any new transaction to Controller to be started.
661 if (NumberOfChildren
== 0) {
663 // Close the bus driver
665 Status
= gBS
->CloseProtocol (
667 &gEfiUnixIoProtocolGuid
,
668 This
->DriverBindingHandle
,
671 Status
= gBS
->CloseProtocol (
673 &gEfiDevicePathProtocolGuid
,
674 This
->DriverBindingHandle
,
680 AllChildrenStopped
= TRUE
;
682 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
683 Status
= gBS
->OpenProtocol (
684 ChildHandleBuffer
[Index
],
685 &gEfiSerialIoProtocolGuid
,
687 This
->DriverBindingHandle
,
689 EFI_OPEN_PROTOCOL_GET_PROTOCOL
691 if (!EFI_ERROR (Status
)) {
692 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
694 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
696 Status
= gBS
->CloseProtocol (
698 &gEfiUnixIoProtocolGuid
,
699 This
->DriverBindingHandle
,
700 ChildHandleBuffer
[Index
]
703 Status
= gBS
->UninstallMultipleProtocolInterfaces (
704 ChildHandleBuffer
[Index
],
705 &gEfiSerialIoProtocolGuid
,
707 &gEfiDevicePathProtocolGuid
,
712 if (EFI_ERROR (Status
)) {
715 &gEfiUnixIoProtocolGuid
,
717 This
->DriverBindingHandle
,
718 ChildHandleBuffer
[Index
],
719 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
722 Private
->UnixThunk
->Close (Private
->UnixHandle
);
724 FreePool (Private
->DevicePath
);
726 FreeUnicodeStringTable (Private
->ControllerNameTable
);
732 if (EFI_ERROR (Status
)) {
733 AllChildrenStopped
= FALSE
;
737 if (!AllChildrenStopped
) {
738 return EFI_DEVICE_ERROR
;
745 // Serial IO Protocol member functions
751 IN EFI_SERIAL_IO_PROTOCOL
*This
757 TODO: Add function description
761 This - TODO: add argument description
765 TODO: add return values
769 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
773 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
775 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
777 UnixStatus
= Private
->UnixThunk
->Tcflush (
781 switch (UnixStatus
) {
783 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
784 return EFI_DEVICE_ERROR
;
786 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
787 return EFI_DEVICE_ERROR
;
789 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
790 return EFI_DEVICE_ERROR
;
792 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
795 gBS
->RestoreTPL (Tpl
);
797 return This
->SetAttributes (
799 This
->Mode
->BaudRate
,
800 This
->Mode
->ReceiveFifoDepth
,
803 (UINT8
) This
->Mode
->DataBits
,
810 UnixSerialIoSetAttributes (
811 IN EFI_SERIAL_IO_PROTOCOL
*This
,
813 IN UINT32 ReceiveFifoDepth
,
815 IN EFI_PARITY_TYPE Parity
,
817 IN EFI_STOP_BITS_TYPE StopBits
823 This function is used to set the attributes.
827 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
828 BaudRate - The Baud rate of the serial device.
829 ReceiveFifoDepth - The request depth of fifo on receive side.
830 Timeout - the request timeout for a single charact.
831 Parity - The type of parity used in serial device.
832 DataBits - Number of deata bits used in serial device.
833 StopBits - Number of stop bits used in serial device.
843 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
845 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
847 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
848 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
851 // Some of our arguments have defaults if a null value is passed in, and
852 // we must set the default values if a null argument is passed in.
855 BaudRate
= SERIAL_BAUD_DEFAULT
;
858 if (ReceiveFifoDepth
== 0) {
859 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
863 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
866 if (Parity
== DefaultParity
) {
871 DataBits
= SERIAL_DATABITS_DEFAULT
;
874 if (StopBits
== DefaultStopBits
) {
875 StopBits
= OneStopBit
;
879 // See if the new attributes already match the current attributes
881 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
882 Private
->UartDevicePath
.DataBits
== DataBits
&&
883 Private
->UartDevicePath
.Parity
== Parity
&&
884 Private
->UartDevicePath
.StopBits
== StopBits
&&
885 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
886 Private
->SerialIoMode
.Timeout
== Timeout
) {
887 gBS
->RestoreTPL(Tpl
);
892 // Try to get options from serial device.
894 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
895 Private
->UnixThunk
->Perror ("IoSetAttributes");
896 gBS
->RestoreTPL (Tpl
);
897 return EFI_DEVICE_ERROR
;
903 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
904 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
908 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
909 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
913 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
917 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
921 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
925 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
927 // Support hardware flow control
929 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
933 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
934 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
939 if (-1 == Private
->UnixThunk
->Tcsetattr (
942 &Private
->UnixTermios
944 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
945 return EFI_DEVICE_ERROR
;
951 Private
->SerialIoMode
.BaudRate
= BaudRate
;
952 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
953 Private
->SerialIoMode
.Timeout
= Timeout
;
954 Private
->SerialIoMode
.Parity
= Parity
;
955 Private
->SerialIoMode
.DataBits
= DataBits
;
956 Private
->SerialIoMode
.StopBits
= StopBits
;
958 // See if Device Path Node has actually changed
960 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
961 Private
->UartDevicePath
.DataBits
== DataBits
&&
962 Private
->UartDevicePath
.Parity
== Parity
&&
963 Private
->UartDevicePath
.StopBits
== StopBits
) {
964 gBS
->RestoreTPL(Tpl
);
969 // Update the device path
971 Private
->UartDevicePath
.BaudRate
= BaudRate
;
972 Private
->UartDevicePath
.DataBits
= DataBits
;
973 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
974 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
976 NewDevicePath
= AppendDevicePathNode (
977 Private
->ParentDevicePath
,
978 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
980 if (NewDevicePath
== NULL
) {
981 gBS
->RestoreTPL (Tpl
);
982 return EFI_DEVICE_ERROR
;
985 if (Private
->Handle
!= NULL
) {
986 Status
= gBS
->ReinstallProtocolInterface (
988 &gEfiDevicePathProtocolGuid
,
992 if (EFI_ERROR (Status
)) {
993 gBS
->RestoreTPL (Tpl
);
998 if (Private
->DevicePath
!= NULL
) {
999 FreePool (Private
->DevicePath
);
1002 Private
->DevicePath
= NewDevicePath
;
1004 gBS
->RestoreTPL (Tpl
);
1011 UnixSerialIoSetControl (
1012 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1017 Routine Description:
1019 TODO: Add function description
1023 This - TODO: add argument description
1024 Control - TODO: add argument description
1028 EFI_DEVICE_ERROR - TODO: Add description for return value
1029 EFI_DEVICE_ERROR - TODO: Add description for return value
1030 EFI_SUCCESS - TODO: Add description for return value
1034 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1037 struct termios Options
;
1040 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1042 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1044 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1047 Private
->UnixThunk
->Perror ("SerialSetControl");
1048 gBS
->RestoreTPL (Tpl
);
1049 return EFI_DEVICE_ERROR
;
1052 Private
->HardwareFlowControl
= FALSE
;
1053 Private
->SoftwareLoopbackEnable
= FALSE
;
1054 Private
->HardwareLoopbackEnable
= FALSE
;
1056 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1057 Options
.c_cflag
|= TIOCM_RTS
;
1060 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1061 Options
.c_cflag
|= TIOCM_DTR
;
1064 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1065 Private
->HardwareFlowControl
= TRUE
;
1068 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1069 Private
->SoftwareLoopbackEnable
= TRUE
;
1072 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1073 Private
->HardwareLoopbackEnable
= TRUE
;
1076 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &Status
);
1079 Private
->UnixThunk
->Perror ("SerialSetControl");
1080 gBS
->RestoreTPL (Tpl
);
1081 return EFI_DEVICE_ERROR
;
1084 gBS
->RestoreTPL (Tpl
);
1091 UnixSerialIoGetControl (
1092 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1097 Routine Description:
1099 TODO: Add function description
1103 This - TODO: add argument description
1104 Control - TODO: add argument description
1108 EFI_DEVICE_ERROR - TODO: Add description for return value
1109 EFI_DEVICE_ERROR - TODO: Add description for return value
1110 EFI_DEVICE_ERROR - TODO: Add description for return value
1111 EFI_SUCCESS - TODO: Add description for return value
1115 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1122 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1124 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1125 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1127 Private
->UnixThunk
->Perror ("SerialGetControl");
1128 gBS
->RestoreTPL (Tpl
);
1129 return EFI_DEVICE_ERROR
;
1132 if ((Status
& TIOCM_CTS
) == TIOCM_CTS
) {
1133 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1136 if ((Status
& TIOCM_DSR
) == TIOCM_DSR
) {
1137 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1140 if ((Status
& TIOCM_DTR
) == TIOCM_DTR
) {
1141 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1144 if ((Status
& TIOCM_RTS
) == TIOCM_RTS
) {
1145 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1148 if ((Status
& TIOCM_RNG
) == TIOCM_RNG
) {
1149 Bits
|= EFI_SERIAL_RING_INDICATE
;
1152 if ((Status
& TIOCM_CAR
) == TIOCM_CAR
) {
1153 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1156 if (Private
->HardwareFlowControl
) {
1157 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1160 if (Private
->SoftwareLoopbackEnable
) {
1161 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1164 if (Private
->HardwareLoopbackEnable
) {
1165 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1168 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, FIONREAD
, &Bytes
);
1170 Private
->UnixThunk
->Perror ("SerialGetControl");
1171 gBS
->RestoreTPL (Tpl
);
1172 return EFI_DEVICE_ERROR
;
1176 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1181 gBS
->RestoreTPL (Tpl
);
1189 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1190 IN OUT UINTN
*BufferSize
,
1195 Routine Description:
1197 TODO: Add function description
1201 This - TODO: add argument description
1202 BufferSize - TODO: add argument description
1203 Buffer - TODO: add argument description
1207 EFI_DEVICE_ERROR - TODO: Add description for return value
1208 EFI_SUCCESS - TODO: Add description for return value
1212 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1214 UINT32 TotalBytesWritten
;
1216 UINT32 BytesWritten
;
1221 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1223 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1225 ByteBuffer
= (UINT8
*) Buffer
;
1226 TotalBytesWritten
= 0;
1228 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1229 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1230 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1231 TotalBytesWritten
++;
1237 BytesToGo
= (*BufferSize
);
1240 if (Private
->HardwareFlowControl
) {
1244 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1245 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1246 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1252 BytesWritten
= Private
->UnixThunk
->Write (
1253 Private
->UnixHandle
,
1254 &ByteBuffer
[TotalBytesWritten
],
1258 if (Private
->HardwareFlowControl
) {
1262 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1263 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1264 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1267 TotalBytesWritten
+= BytesWritten
;
1268 BytesToGo
-= BytesWritten
;
1269 } while (BytesToGo
> 0);
1272 *BufferSize
= TotalBytesWritten
;
1274 gBS
->RestoreTPL (Tpl
);
1282 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1283 IN OUT UINTN
*BufferSize
,
1288 Routine Description:
1290 TODO: Add function description
1294 This - TODO: add argument description
1295 BufferSize - TODO: add argument description
1296 Buffer - TODO: add argument description
1300 EFI_DEVICE_ERROR - TODO: Add description for return value
1304 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1312 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1314 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1319 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1320 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1321 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1322 ((UINT8
*) Buffer
)[Index
] = Data
;
1329 if (Private
->HardwareFlowControl
) {
1330 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1331 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1332 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1335 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1336 if (Private
->HardwareFlowControl
) {
1337 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1338 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1339 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1344 if (BytesRead
!= *BufferSize
) {
1345 Status
= EFI_TIMEOUT
;
1347 Status
= EFI_SUCCESS
;
1350 *BufferSize
= (UINTN
) BytesRead
;
1352 gBS
->RestoreTPL (Tpl
);
1359 IN SERIAL_DEV_FIFO
*Fifo
1363 Routine Description:
1364 Detect whether specific FIFO is full or not
1367 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1370 TRUE: the FIFO is full
1371 FALSE: the FIFO is not full
1375 if (Fifo
->Surplus
== 0) {
1383 IsaSerialFifoEmpty (
1384 IN SERIAL_DEV_FIFO
*Fifo
1388 Routine Description:
1389 Detect whether specific FIFO is empty or not
1392 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1395 TRUE: the FIFO is empty
1396 FALSE: the FIFO is not empty
1400 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1409 IN SERIAL_DEV_FIFO
*Fifo
,
1414 Routine Description:
1415 Add data to specific FIFO
1418 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1419 Data UINT8: the data added to FIFO
1422 EFI_SUCCESS: Add data to specific FIFO successfully
1423 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1426 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1429 // if FIFO full can not add data
1431 if (IsaSerialFifoFull (Fifo
)) {
1432 return EFI_OUT_OF_RESOURCES
;
1436 // FIFO is not full can add data
1438 Fifo
->Data
[Fifo
->Last
] = Data
;
1441 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1449 IsaSerialFifoRemove (
1450 IN SERIAL_DEV_FIFO
*Fifo
,
1455 Routine Description:
1456 Remove data from specific FIFO
1459 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1460 Data UINT8*: the data removed from FIFO
1463 EFI_SUCCESS: Remove data from specific FIFO successfully
1464 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1467 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1470 // if FIFO is empty, no data can remove
1472 if (IsaSerialFifoEmpty (Fifo
)) {
1473 return EFI_OUT_OF_RESOURCES
;
1477 // FIFO is not empty, can remove data
1479 *Data
= Fifo
->Data
[Fifo
->First
];
1482 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {