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
,
63 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
66 struct termios Options
;
68 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Options
) == 0) {
69 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Input mode: 0x%x\r\n", Private
->UnixHandle
, Options
.c_iflag
));
70 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Output mode: 0x%x\r\n", Private
->UnixHandle
, Options
.c_oflag
));
71 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Control flag: 0x%x\r\n", Private
->UnixHandle
, Options
.c_cflag
));
72 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Local mode flag: 0x%x\r\n", Private
->UnixHandle
, Options
.c_lflag
));
73 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Line discipline: 0x%x\r\n", Private
->UnixHandle
, Options
.c_line
));
74 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Input Speed: 0x%x\r\n", Private
->UnixHandle
, Options
.c_ispeed
));
75 DEBUG ((EFI_D_INFO
, "Serial[0x%x]:Output Speed: 0x%x\r\n", Private
->UnixHandle
, Options
.c_ospeed
));
150 DEBUG ((EFI_D_ERROR
, "Invalid Baud Rate Parameter!\r\n"));
157 ConvertByteSize2Unix (
171 DEBUG ((EFI_D_ERROR
, "Invalid Data Size Parameter!\r\n"));
179 struct termios
*Options
,
180 EFI_PARITY_TYPE Parity
185 Options
->c_cflag
&= ~PARENB
;
188 Options
->c_cflag
|= PARENB
;
191 Options
->c_cflag
|= PARENB
;
192 Options
->c_cflag
|= PARODD
;
195 Options
->c_cflag
= PARENB
| CMSPAR
| PARODD
;
198 Options
->c_cflag
|= PARENB
| CMSPAR
;
199 Options
->c_cflag
&= ~PARODD
;
202 DEBUG ((EFI_D_ERROR
, "Invalid Parity Parameter!\r\n"));
208 ConvertStopBit2Unix (
209 struct termios
*Options
,
210 EFI_STOP_BITS_TYPE StopBits
215 Options
->c_cflag
|= CSTOPB
;
218 case OneFiveStopBits
:
219 case DefaultStopBits
:
220 Options
->c_cflag
&= ~CSTOPB
;
226 UnixSerialIoDriverBindingSupported (
227 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
228 IN EFI_HANDLE Handle
,
229 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
234 The implementation of EFI_DRIVER_BINDING_PROTOCOL.EFI_DRIVER_BINDING_SUPPORTED.
245 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
246 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
247 UART_DEVICE_PATH
*UartNode
;
250 // Open the IO Abstraction(s) needed to perform the supported test
252 Status
= gBS
->OpenProtocol (
254 &gEfiDevicePathProtocolGuid
,
255 (VOID
**)&ParentDevicePath
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_BY_DRIVER
260 if (Status
== EFI_ALREADY_STARTED
) {
264 if (EFI_ERROR (Status
)) {
270 &gEfiDevicePathProtocolGuid
,
271 This
->DriverBindingHandle
,
275 Status
= gBS
->OpenProtocol (
277 &gEfiUnixIoProtocolGuid
,
279 This
->DriverBindingHandle
,
281 EFI_OPEN_PROTOCOL_BY_DRIVER
283 if (Status
== EFI_ALREADY_STARTED
) {
287 if (EFI_ERROR (Status
)) {
292 // Make sure that the Unix Thunk Protocol is valid
294 if (UnixIo
->UnixThunk
->Signature
!= EFI_UNIX_THUNK_PROTOCOL_SIGNATURE
) {
295 Status
= EFI_UNSUPPORTED
;
300 // Check the GUID to see if this is a handle type the driver supports
302 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixSerialPortGuid
)) {
303 Status
= EFI_UNSUPPORTED
;
307 if (RemainingDevicePath
!= NULL
) {
308 Status
= EFI_UNSUPPORTED
;
309 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
310 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
311 UartNode
->Header
.SubType
!= MSG_UART_DP
||
312 DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL
*)UartNode
) != sizeof(UART_DEVICE_PATH
)) {
315 if (UartNode
->BaudRate
< 0 || UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
318 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
321 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
324 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
327 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
330 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
333 Status
= EFI_SUCCESS
;
338 // Close the I/O Abstraction(s) used to perform the supported test
342 &gEfiUnixIoProtocolGuid
,
343 This
->DriverBindingHandle
,
352 UnixSerialIoDriverBindingStart (
353 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
354 IN EFI_HANDLE Handle
,
355 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
370 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
371 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
373 UART_DEVICE_PATH Node
;
374 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
375 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
378 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
379 CHAR8 AsciiDevName
[1024];
381 DEBUG ((EFI_D_INFO
, "SerialIo drive binding start!\r\n"));
386 // Grab the protocols we need
388 Status
= gBS
->OpenProtocol (
390 &gEfiDevicePathProtocolGuid
,
391 (VOID
**)&ParentDevicePath
,
392 This
->DriverBindingHandle
,
394 EFI_OPEN_PROTOCOL_BY_DRIVER
396 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
401 // Grab the IO abstraction we need to get any work done
403 Status
= gBS
->OpenProtocol (
405 &gEfiUnixIoProtocolGuid
,
407 This
->DriverBindingHandle
,
409 EFI_OPEN_PROTOCOL_BY_DRIVER
411 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
414 &gEfiDevicePathProtocolGuid
,
415 This
->DriverBindingHandle
,
421 if (Status
== EFI_ALREADY_STARTED
) {
423 if (RemainingDevicePath
== NULL
) {
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 CopyMem (&Node
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
454 Status
= SerialIo
->SetAttributes (
457 SerialIo
->Mode
->ReceiveFifoDepth
,
458 SerialIo
->Mode
->Timeout
,
468 FreePool (OpenInfoBuffer
);
473 // Check to see if we can access the hardware device. If it's Open in Unix we
474 // will not get access.
476 UnicodeStrToAsciiStr(UnixIo
->EnvString
, AsciiDevName
);
477 UnixHandle
= UnixIo
->UnixThunk
->Open (AsciiDevName
, O_RDWR
| O_NOCTTY
, 0);
479 if (UnixHandle
== -1) {
480 DEBUG ((EFI_D_INFO
, "Faile to open serial device, %s!\r\n", UnixIo
->EnvString
));
481 UnixIo
->UnixThunk
->Perror (AsciiDevName
);
482 Status
= EFI_DEVICE_ERROR
;
485 DEBUG ((EFI_D_INFO
, "Success to open serial device %s, Hanle = 0x%x \r\n", UnixIo
->EnvString
, UnixHandle
));
488 // Construct Private data
490 Private
= AllocatePool (sizeof (UNIX_SERIAL_IO_PRIVATE_DATA
));
491 if (Private
== NULL
) {
496 // This signature must be valid before any member function is called
498 Private
->Signature
= UNIX_SERIAL_IO_PRIVATE_DATA_SIGNATURE
;
499 Private
->UnixHandle
= UnixHandle
;
500 Private
->ControllerHandle
= Handle
;
501 Private
->Handle
= NULL
;
502 Private
->UnixThunk
= UnixIo
->UnixThunk
;
503 Private
->ParentDevicePath
= ParentDevicePath
;
504 Private
->ControllerNameTable
= NULL
;
506 Private
->SoftwareLoopbackEnable
= FALSE
;
507 Private
->HardwareLoopbackEnable
= FALSE
;
508 Private
->HardwareFlowControl
= FALSE
;
509 Private
->Fifo
.First
= 0;
510 Private
->Fifo
.Last
= 0;
511 Private
->Fifo
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
515 gUnixSerialIoComponentName
.SupportedLanguages
,
516 &Private
->ControllerNameTable
,
520 Private
->SerialIo
.Revision
= SERIAL_IO_INTERFACE_REVISION
;
521 Private
->SerialIo
.Reset
= UnixSerialIoReset
;
522 Private
->SerialIo
.SetAttributes
= UnixSerialIoSetAttributes
;
523 Private
->SerialIo
.SetControl
= UnixSerialIoSetControl
;
524 Private
->SerialIo
.GetControl
= UnixSerialIoGetControl
;
525 Private
->SerialIo
.Write
= UnixSerialIoWrite
;
526 Private
->SerialIo
.Read
= UnixSerialIoRead
;
527 Private
->SerialIo
.Mode
= &Private
->SerialIoMode
;
529 if (RemainingDevicePath
!= NULL
) {
531 // Match the configuration of the RemainingDevicePath. IsHandleSupported()
532 // already checked to make sure the RemainingDevicePath contains settings
533 // that we can support.
535 CopyMem (&Private
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
538 // Build the device path by appending the UART node to the ParentDevicePath
539 // from the UnixIo handle. The Uart setings are zero here, since
540 // SetAttribute() will update them to match the default setings.
542 ZeroMem (&Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
543 Private
->UartDevicePath
.Header
.Type
= MESSAGING_DEVICE_PATH
;
544 Private
->UartDevicePath
.Header
.SubType
= MSG_UART_DP
;
545 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
549 // Build the device path by appending the UART node to the ParentDevicePath
550 // from the UnixIo handle. The Uart setings are zero here, since
551 // SetAttribute() will update them to match the current setings.
553 Private
->DevicePath
= AppendDevicePathNode (
555 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
557 if (Private
->DevicePath
== NULL
) {
558 Status
= EFI_OUT_OF_RESOURCES
;
563 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
565 Private
->SerialIoMode
.ControlMask
= SERIAL_CONTROL_MASK
;
566 Private
->SerialIoMode
.Timeout
= SERIAL_TIMEOUT_DEFAULT
;
567 Private
->SerialIoMode
.BaudRate
= Private
->UartDevicePath
.BaudRate
;
568 Private
->SerialIoMode
.ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
569 Private
->SerialIoMode
.DataBits
= Private
->UartDevicePath
.DataBits
;
570 Private
->SerialIoMode
.Parity
= Private
->UartDevicePath
.Parity
;
571 Private
->SerialIoMode
.StopBits
= Private
->UartDevicePath
.StopBits
;
574 // Issue a reset to initialize the COM port
576 Status
= Private
->SerialIo
.Reset (&Private
->SerialIo
);
577 if (EFI_ERROR (Status
)) {
582 // Create new child handle
584 Status
= gBS
->InstallMultipleProtocolInterfaces (
586 &gEfiSerialIoProtocolGuid
,
588 &gEfiDevicePathProtocolGuid
,
592 if (EFI_ERROR (Status
)) {
597 // Open For Child Device
599 Status
= gBS
->OpenProtocol (
601 &gEfiUnixIoProtocolGuid
,
603 This
->DriverBindingHandle
,
605 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
607 if (EFI_ERROR (Status
)) {
615 // Use the Stop() function to free all resources allocated in Start()
617 if (Private
!= NULL
) {
618 if (Private
->Handle
!= NULL
) {
619 This
->Stop (This
, Handle
, 1, &Private
->Handle
);
621 if (UnixHandle
!= -1) {
622 Private
->UnixThunk
->Close (UnixHandle
);
625 if (Private
->DevicePath
!= NULL
) {
626 FreePool (Private
->DevicePath
);
629 FreeUnicodeStringTable (Private
->ControllerNameTable
);
635 This
->Stop (This
, Handle
, 0, NULL
);
642 UnixSerialIoDriverBindingStop (
643 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
644 IN EFI_HANDLE Handle
,
645 IN UINTN NumberOfChildren
,
646 IN EFI_HANDLE
*ChildHandleBuffer
652 TODO: Add function description
656 This - TODO: add argument description
657 Handle - TODO: add argument description
658 NumberOfChildren - TODO: add argument description
659 ChildHandleBuffer - TODO: add argument description
663 EFI_DEVICE_ERROR - TODO: Add description for return value
664 EFI_SUCCESS - TODO: Add description for return value
670 BOOLEAN AllChildrenStopped
;
671 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
672 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
673 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
676 // Complete all outstanding transactions to Controller.
677 // Don't allow any new transaction to Controller to be started.
680 if (NumberOfChildren
== 0) {
682 // Close the bus driver
684 Status
= gBS
->CloseProtocol (
686 &gEfiUnixIoProtocolGuid
,
687 This
->DriverBindingHandle
,
690 Status
= gBS
->CloseProtocol (
692 &gEfiDevicePathProtocolGuid
,
693 This
->DriverBindingHandle
,
699 AllChildrenStopped
= TRUE
;
701 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
702 Status
= gBS
->OpenProtocol (
703 ChildHandleBuffer
[Index
],
704 &gEfiSerialIoProtocolGuid
,
706 This
->DriverBindingHandle
,
708 EFI_OPEN_PROTOCOL_GET_PROTOCOL
710 if (!EFI_ERROR (Status
)) {
711 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo
);
713 ASSERT (Private
->Handle
== ChildHandleBuffer
[Index
]);
715 Status
= gBS
->CloseProtocol (
717 &gEfiUnixIoProtocolGuid
,
718 This
->DriverBindingHandle
,
719 ChildHandleBuffer
[Index
]
722 Status
= gBS
->UninstallMultipleProtocolInterfaces (
723 ChildHandleBuffer
[Index
],
724 &gEfiSerialIoProtocolGuid
,
726 &gEfiDevicePathProtocolGuid
,
731 if (EFI_ERROR (Status
)) {
734 &gEfiUnixIoProtocolGuid
,
736 This
->DriverBindingHandle
,
737 ChildHandleBuffer
[Index
],
738 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
741 Private
->UnixThunk
->Close (Private
->UnixHandle
);
743 FreePool (Private
->DevicePath
);
745 FreeUnicodeStringTable (Private
->ControllerNameTable
);
751 if (EFI_ERROR (Status
)) {
752 AllChildrenStopped
= FALSE
;
756 if (!AllChildrenStopped
) {
757 return EFI_DEVICE_ERROR
;
764 // Serial IO Protocol member functions
770 IN EFI_SERIAL_IO_PROTOCOL
*This
776 TODO: Add function description
780 This - TODO: add argument description
784 TODO: add return values
788 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
792 Tpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
794 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
796 UnixStatus
= Private
->UnixThunk
->Tcflush (
800 switch (UnixStatus
) {
802 DEBUG ((EFI_D_ERROR
, "Invalid handle of serial device!\r\n"));
803 return EFI_DEVICE_ERROR
;
805 DEBUG ((EFI_D_ERROR
, "Invalid queue selector!\r\n"));
806 return EFI_DEVICE_ERROR
;
808 DEBUG ((EFI_D_ERROR
, "The file associated with serial's handle is not a terminal!\r\n"));
809 return EFI_DEVICE_ERROR
;
811 DEBUG ((EFI_D_ERROR
, "The serial IO device is reset successfully!\r\n"));
814 gBS
->RestoreTPL (Tpl
);
816 return This
->SetAttributes (
818 This
->Mode
->BaudRate
,
819 This
->Mode
->ReceiveFifoDepth
,
822 (UINT8
) This
->Mode
->DataBits
,
829 UnixSerialIoSetAttributes (
830 IN EFI_SERIAL_IO_PROTOCOL
*This
,
832 IN UINT32 ReceiveFifoDepth
,
834 IN EFI_PARITY_TYPE Parity
,
836 IN EFI_STOP_BITS_TYPE StopBits
842 This function is used to set the attributes.
846 This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue.
847 BaudRate - The Baud rate of the serial device.
848 ReceiveFifoDepth - The request depth of fifo on receive side.
849 Timeout - the request timeout for a single charact.
850 Parity - The type of parity used in serial device.
851 DataBits - Number of deata bits used in serial device.
852 StopBits - Number of stop bits used in serial device.
862 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
864 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
866 Tpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
867 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
870 // Some of our arguments have defaults if a null value is passed in, and
871 // we must set the default values if a null argument is passed in.
874 BaudRate
= SERIAL_BAUD_DEFAULT
;
877 if (ReceiveFifoDepth
== 0) {
878 ReceiveFifoDepth
= SERIAL_FIFO_DEFAULT
;
882 Timeout
= SERIAL_TIMEOUT_DEFAULT
;
885 if (Parity
== DefaultParity
) {
890 DataBits
= SERIAL_DATABITS_DEFAULT
;
893 if (StopBits
== DefaultStopBits
) {
894 StopBits
= OneStopBit
;
898 // See if the new attributes already match the current attributes
900 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
901 Private
->UartDevicePath
.DataBits
== DataBits
&&
902 Private
->UartDevicePath
.Parity
== Parity
&&
903 Private
->UartDevicePath
.StopBits
== StopBits
&&
904 Private
->SerialIoMode
.ReceiveFifoDepth
== ReceiveFifoDepth
&&
905 Private
->SerialIoMode
.Timeout
== Timeout
) {
906 gBS
->RestoreTPL(Tpl
);
911 // Try to get options from serial device.
913 if (Private
->UnixThunk
->Tcgetattr (Private
->UnixHandle
, &Private
->UnixTermios
) == -1) {
914 Private
->UnixThunk
->Perror ("IoSetAttributes");
915 gBS
->RestoreTPL (Tpl
);
916 return EFI_DEVICE_ERROR
;
922 Private
->UnixThunk
->Cfsetispeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
923 Private
->UnixThunk
->Cfsetospeed (&Private
->UnixTermios
, ConvertBaud2Unix(BaudRate
));
927 Private
->UnixTermios
.c_cflag
&= ~CSIZE
;
928 Private
->UnixTermios
.c_cflag
|= ConvertByteSize2Unix (DataBits
);
932 ConvertParity2Unix (&Private
->UnixTermios
, Parity
);
936 ConvertStopBit2Unix (&Private
->UnixTermios
, StopBits
);
940 Private
->UnixTermios
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
944 Private
->UnixTermios
.c_oflag
&= ~OPOST
;
946 // Support hardware flow control
948 Private
->UnixTermios
.c_cflag
&= ~CRTSCTS
;;
952 Private
->UnixTermios
.c_cc
[VMIN
] = 0;
953 Private
->UnixTermios
.c_cc
[VTIME
] = (Timeout
/1000000) * 10;
958 if (-1 == Private
->UnixThunk
->Tcsetattr (
961 &Private
->UnixTermios
963 DEBUG ((EFI_D_INFO
, "Fail to set options for serial device!\r\n"));
964 return EFI_DEVICE_ERROR
;
970 Private
->SerialIoMode
.BaudRate
= BaudRate
;
971 Private
->SerialIoMode
.ReceiveFifoDepth
= ReceiveFifoDepth
;
972 Private
->SerialIoMode
.Timeout
= Timeout
;
973 Private
->SerialIoMode
.Parity
= Parity
;
974 Private
->SerialIoMode
.DataBits
= DataBits
;
975 Private
->SerialIoMode
.StopBits
= StopBits
;
977 // See if Device Path Node has actually changed
979 if (Private
->UartDevicePath
.BaudRate
== BaudRate
&&
980 Private
->UartDevicePath
.DataBits
== DataBits
&&
981 Private
->UartDevicePath
.Parity
== Parity
&&
982 Private
->UartDevicePath
.StopBits
== StopBits
) {
983 gBS
->RestoreTPL(Tpl
);
988 // Update the device path
990 Private
->UartDevicePath
.BaudRate
= BaudRate
;
991 Private
->UartDevicePath
.DataBits
= DataBits
;
992 Private
->UartDevicePath
.Parity
= (UINT8
) Parity
;
993 Private
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
995 NewDevicePath
= AppendDevicePathNode (
996 Private
->ParentDevicePath
,
997 (EFI_DEVICE_PATH_PROTOCOL
*) &Private
->UartDevicePath
999 if (NewDevicePath
== NULL
) {
1000 gBS
->RestoreTPL (Tpl
);
1001 return EFI_DEVICE_ERROR
;
1004 if (Private
->Handle
!= NULL
) {
1005 Status
= gBS
->ReinstallProtocolInterface (
1007 &gEfiDevicePathProtocolGuid
,
1008 Private
->DevicePath
,
1011 if (EFI_ERROR (Status
)) {
1012 gBS
->RestoreTPL (Tpl
);
1017 if (Private
->DevicePath
!= NULL
) {
1018 FreePool (Private
->DevicePath
);
1021 Private
->DevicePath
= NewDevicePath
;
1023 gBS
->RestoreTPL (Tpl
);
1030 UnixSerialIoSetControl (
1031 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1036 Routine Description:
1038 TODO: Add function description
1042 This - TODO: add argument description
1043 Control - TODO: add argument description
1047 EFI_DEVICE_ERROR - TODO: Add description for return value
1048 EFI_DEVICE_ERROR - TODO: Add description for return value
1049 EFI_SUCCESS - TODO: Add description for return value
1053 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1056 struct termios Options
;
1059 Tpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1061 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1063 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1066 Private
->UnixThunk
->Perror ("SerialSetControl");
1067 gBS
->RestoreTPL (Tpl
);
1068 return EFI_DEVICE_ERROR
;
1071 Private
->HardwareFlowControl
= FALSE
;
1072 Private
->SoftwareLoopbackEnable
= FALSE
;
1073 Private
->HardwareLoopbackEnable
= FALSE
;
1075 if (Control
& EFI_SERIAL_REQUEST_TO_SEND
) {
1076 Options
.c_cflag
|= TIOCM_RTS
;
1079 if (Control
& EFI_SERIAL_DATA_TERMINAL_READY
) {
1080 Options
.c_cflag
|= TIOCM_DTR
;
1083 if (Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1084 Private
->HardwareFlowControl
= TRUE
;
1087 if (Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1088 Private
->SoftwareLoopbackEnable
= TRUE
;
1091 if (Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1092 Private
->HardwareLoopbackEnable
= TRUE
;
1095 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMSET
, &Status
);
1098 Private
->UnixThunk
->Perror ("SerialSetControl");
1099 gBS
->RestoreTPL (Tpl
);
1100 return EFI_DEVICE_ERROR
;
1103 gBS
->RestoreTPL (Tpl
);
1110 UnixSerialIoGetControl (
1111 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1116 Routine Description:
1118 TODO: Add function description
1122 This - TODO: add argument description
1123 Control - TODO: add argument description
1127 EFI_DEVICE_ERROR - TODO: Add description for return value
1128 EFI_DEVICE_ERROR - TODO: Add description for return value
1129 EFI_DEVICE_ERROR - TODO: Add description for return value
1130 EFI_SUCCESS - TODO: Add description for return value
1134 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1137 struct termios Options
;
1142 Tpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1144 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1145 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, TIOCMGET
, &Status
);
1147 Private
->UnixThunk
->Perror ("SerialGetControl");
1148 gBS
->RestoreTPL (Tpl
);
1149 return EFI_DEVICE_ERROR
;
1152 if ((Status
& TIOCM_CTS
) == TIOCM_CTS
) {
1153 Bits
|= EFI_SERIAL_CLEAR_TO_SEND
;
1156 if ((Status
& TIOCM_DSR
) == TIOCM_DSR
) {
1157 Bits
|= EFI_SERIAL_DATA_SET_READY
;
1160 if ((Status
& TIOCM_DTR
) == TIOCM_DTR
) {
1161 Bits
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1164 if ((Status
& TIOCM_RTS
) == TIOCM_RTS
) {
1165 Bits
|= EFI_SERIAL_REQUEST_TO_SEND
;
1168 if ((Status
& TIOCM_RNG
) == TIOCM_RNG
) {
1169 Bits
|= EFI_SERIAL_RING_INDICATE
;
1172 if ((Status
& TIOCM_CAR
) == TIOCM_CAR
) {
1173 Bits
|= EFI_SERIAL_CARRIER_DETECT
;
1176 if (Private
->HardwareFlowControl
) {
1177 Bits
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1180 if (Private
->SoftwareLoopbackEnable
) {
1181 Bits
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1184 if (Private
->HardwareLoopbackEnable
) {
1185 Bits
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1188 Result
= Private
->UnixThunk
->IoCtl (Private
->UnixHandle
, FIONREAD
, &Bytes
);
1190 Private
->UnixThunk
->Perror ("SerialGetControl");
1191 gBS
->RestoreTPL (Tpl
);
1192 return EFI_DEVICE_ERROR
;
1196 Bits
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1201 gBS
->RestoreTPL (Tpl
);
1209 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1210 IN OUT UINTN
*BufferSize
,
1215 Routine Description:
1217 TODO: Add function description
1221 This - TODO: add argument description
1222 BufferSize - TODO: add argument description
1223 Buffer - TODO: add argument description
1227 EFI_DEVICE_ERROR - TODO: Add description for return value
1228 EFI_SUCCESS - TODO: Add description for return value
1232 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1234 UINT32 TotalBytesWritten
;
1236 UINT32 BytesWritten
;
1241 Tpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1243 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1245 ByteBuffer
= (UINT8
*) Buffer
;
1246 TotalBytesWritten
= 0;
1248 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1249 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1250 if (IsaSerialFifoAdd (&Private
->Fifo
, ByteBuffer
[Index
]) == EFI_SUCCESS
) {
1251 TotalBytesWritten
++;
1257 BytesToGo
= (*BufferSize
);
1260 if (Private
->HardwareFlowControl
) {
1264 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1265 Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1266 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1272 BytesWritten
= Private
->UnixThunk
->Write (
1273 Private
->UnixHandle
,
1274 &ByteBuffer
[TotalBytesWritten
],
1278 if (Private
->HardwareFlowControl
) {
1282 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1283 Control
&= ~ (UINT32
) EFI_SERIAL_REQUEST_TO_SEND
;
1284 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1287 TotalBytesWritten
+= BytesWritten
;
1288 BytesToGo
-= BytesWritten
;
1289 } while (BytesToGo
> 0);
1292 *BufferSize
= TotalBytesWritten
;
1294 gBS
->RestoreTPL (Tpl
);
1302 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1303 IN OUT UINTN
*BufferSize
,
1308 Routine Description:
1310 TODO: Add function description
1314 This - TODO: add argument description
1315 BufferSize - TODO: add argument description
1316 Buffer - TODO: add argument description
1320 EFI_DEVICE_ERROR - TODO: Add description for return value
1324 UNIX_SERIAL_IO_PRIVATE_DATA
*Private
;
1332 Tpl
= gBS
->RaiseTPL (EFI_TPL_NOTIFY
);
1334 Private
= UNIX_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This
);
1339 if (Private
->SoftwareLoopbackEnable
|| Private
->HardwareLoopbackEnable
) {
1340 for (Index
= 0, BytesRead
= 0; Index
< *BufferSize
; Index
++) {
1341 if (IsaSerialFifoRemove (&Private
->Fifo
, &Data
) == EFI_SUCCESS
) {
1342 ((UINT8
*) Buffer
)[Index
] = Data
;
1349 if (Private
->HardwareFlowControl
) {
1350 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1351 Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1352 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1355 BytesRead
= Private
->UnixThunk
->Read (Private
->UnixHandle
, Buffer
, *BufferSize
);
1356 if (Private
->HardwareFlowControl
) {
1357 UnixSerialIoGetControl (&Private
->SerialIo
, &Control
);
1358 Control
&= ~ (UINT32
) EFI_SERIAL_DATA_TERMINAL_READY
;
1359 UnixSerialIoSetControl (&Private
->SerialIo
, Control
);
1364 if (BytesRead
!= *BufferSize
) {
1365 Status
= EFI_TIMEOUT
;
1367 Status
= EFI_SUCCESS
;
1370 *BufferSize
= (UINTN
) BytesRead
;
1372 gBS
->RestoreTPL (Tpl
);
1379 IN SERIAL_DEV_FIFO
*Fifo
1383 Routine Description:
1384 Detect whether specific FIFO is full or not
1387 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1390 TRUE: the FIFO is full
1391 FALSE: the FIFO is not full
1395 if (Fifo
->Surplus
== 0) {
1403 IsaSerialFifoEmpty (
1404 IN SERIAL_DEV_FIFO
*Fifo
1408 Routine Description:
1409 Detect whether specific FIFO is empty or not
1412 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1415 TRUE: the FIFO is empty
1416 FALSE: the FIFO is not empty
1420 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
1429 IN SERIAL_DEV_FIFO
*Fifo
,
1434 Routine Description:
1435 Add data to specific FIFO
1438 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1439 Data UINT8: the data added to FIFO
1442 EFI_SUCCESS: Add data to specific FIFO successfully
1443 EFI_OUT_RESOURCE: Failed to add data because FIFO is already full
1446 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1449 // if FIFO full can not add data
1451 if (IsaSerialFifoFull (Fifo
)) {
1452 return EFI_OUT_OF_RESOURCES
;
1456 // FIFO is not full can add data
1458 Fifo
->Data
[Fifo
->Last
] = Data
;
1461 if (Fifo
->Last
>= SERIAL_MAX_BUFFER_SIZE
) {
1469 IsaSerialFifoRemove (
1470 IN SERIAL_DEV_FIFO
*Fifo
,
1475 Routine Description:
1476 Remove data from specific FIFO
1479 Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO
1480 Data UINT8*: the data removed from FIFO
1483 EFI_SUCCESS: Remove data from specific FIFO successfully
1484 EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty
1487 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1490 // if FIFO is empty, no data can remove
1492 if (IsaSerialFifoEmpty (Fifo
)) {
1493 return EFI_OUT_OF_RESOURCES
;
1497 // FIFO is not empty, can remove data
1499 *Data
= Fifo
->Data
[Fifo
->First
];
1502 if (Fifo
->First
>= SERIAL_MAX_BUFFER_SIZE
) {