2 Serial driver for standard UARTS on an ISA bus.
4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // ISA Serial Driver Global Variables
20 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver
= {
21 SerialControllerDriverSupported
,
22 SerialControllerDriverStart
,
23 SerialControllerDriverStop
,
30 SERIAL_DEV gSerialDevTempate
= {
34 SERIAL_IO_INTERFACE_REVISION
,
36 IsaSerialSetAttributes
,
44 SERIAL_PORT_SUPPORT_CONTROL_MASK
,
45 SERIAL_PORT_DEFAULT_TIMEOUT
,
46 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
47 SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
,
48 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
49 FixedPcdGet8 (PcdUartDefaultParity
), // Parity
50 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
56 MESSAGING_DEVICE_PATH
,
59 (UINT8
) (sizeof (UART_DEVICE_PATH
)),
60 (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8)
64 FixedPcdGet64 (PcdUartDefaultBaudRate
),
65 FixedPcdGet8 (PcdUartDefaultDataBits
),
66 FixedPcdGet8 (PcdUartDefaultParity
),
67 FixedPcdGet8 (PcdUartDefaultStopBits
)
74 SERIAL_MAX_BUFFER_SIZE
,
80 SERIAL_MAX_BUFFER_SIZE
,
90 Check the device path node whether it's the Flow Control node or not.
92 @param[in] FlowControl The device path node to be checked.
94 @retval TRUE It's the Flow Control node.
95 @retval FALSE It's not.
99 IsUartFlowControlNode (
100 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
104 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
105 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
106 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
111 Check the device path node whether it contains Flow Control node or not.
113 @param[in] DevicePath The device path to be checked.
115 @retval TRUE It contains the Flow Control node.
116 @retval FALSE It doesn't.
120 ContainsFlowControl (
121 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
124 while (!IsDevicePathEnd (DevicePath
)) {
125 if (IsUartFlowControlNode ((UART_FLOW_CONTROL_DEVICE_PATH
*) DevicePath
)) {
128 DevicePath
= NextDevicePathNode (DevicePath
);
135 The user Entry Point for module IsaSerial. The user code starts with this function.
137 @param[in] ImageHandle The firmware allocated handle for the EFI image.
138 @param[in] SystemTable A pointer to the EFI System Table.
140 @retval EFI_SUCCESS The entry point is executed successfully.
141 @retval other Some error occurs when executing this entry point.
146 InitializeIsaSerial (
147 IN EFI_HANDLE ImageHandle
,
148 IN EFI_SYSTEM_TABLE
*SystemTable
154 // Install driver model protocol(s).
156 Status
= EfiLibInstallDriverBindingComponentName2 (
159 &gSerialControllerDriver
,
161 &gIsaSerialComponentName
,
162 &gIsaSerialComponentName2
164 ASSERT_EFI_ERROR (Status
);
171 Check to see if this driver supports the given controller
173 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
174 @param Controller The handle of the controller to test.
175 @param RemainingDevicePath A pointer to the remaining portion of a device path.
177 @return EFI_SUCCESS This driver can support the given controller
182 SerialControllerDriverSupported (
183 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
184 IN EFI_HANDLE Controller
,
185 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
190 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
191 EFI_ISA_IO_PROTOCOL
*IsaIo
;
192 UART_DEVICE_PATH
*UartNode
;
193 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
194 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
195 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
198 BOOLEAN HasFlowControl
;
201 // Check RemainingDevicePath validation
203 if (RemainingDevicePath
!= NULL
) {
205 // Check if RemainingDevicePath is the End of Device Path Node,
206 // if yes, go on checking other conditions
208 if (!IsDevicePathEnd (RemainingDevicePath
)) {
210 // If RemainingDevicePath isn't the End of Device Path Node,
211 // check its validation
213 Status
= EFI_UNSUPPORTED
;
215 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
216 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
217 UartNode
->Header
.SubType
!= MSG_UART_DP
||
218 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) UartNode
)
223 if (UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
227 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
231 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
235 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
239 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
243 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
247 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (UartNode
);
248 if (IsUartFlowControlNode (FlowControlNode
)) {
250 // If the second node is Flow Control Node,
251 // return error when it request other than hardware flow control.
253 if ((ReadUnaligned32 (&FlowControlNode
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
261 // Open the IO Abstraction(s) needed to perform the supported test
263 Status
= gBS
->OpenProtocol (
265 &gEfiIsaIoProtocolGuid
,
267 This
->DriverBindingHandle
,
269 EFI_OPEN_PROTOCOL_BY_DRIVER
271 if (Status
== EFI_ALREADY_STARTED
) {
272 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
274 // If RemainingDevicePath is NULL or is the End of Device Path Node
279 // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
280 // return unsupported, and vice versa.
282 Status
= gBS
->OpenProtocolInformation (
284 &gEfiIsaIoProtocolGuid
,
288 if (EFI_ERROR (Status
)) {
292 for (Index
= 0; Index
< EntryCount
; Index
++) {
293 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
294 Status
= gBS
->OpenProtocol (
295 OpenInfoBuffer
[Index
].ControllerHandle
,
296 &gEfiDevicePathProtocolGuid
,
297 (VOID
**) &DevicePath
,
298 This
->DriverBindingHandle
,
300 EFI_OPEN_PROTOCOL_GET_PROTOCOL
302 if (!EFI_ERROR (Status
)) {
303 HasFlowControl
= ContainsFlowControl (RemainingDevicePath
);
304 if (HasFlowControl
^ ContainsFlowControl (DevicePath
)) {
305 Status
= EFI_UNSUPPORTED
;
311 FreePool (OpenInfoBuffer
);
315 if (EFI_ERROR (Status
)) {
320 // Close the I/O Abstraction(s) used to perform the supported test
324 &gEfiIsaIoProtocolGuid
,
325 This
->DriverBindingHandle
,
330 // Open the EFI Device Path protocol needed to perform the supported test
332 Status
= gBS
->OpenProtocol (
334 &gEfiDevicePathProtocolGuid
,
335 (VOID
**) &ParentDevicePath
,
336 This
->DriverBindingHandle
,
338 EFI_OPEN_PROTOCOL_BY_DRIVER
340 if (Status
== EFI_ALREADY_STARTED
) {
344 if (EFI_ERROR (Status
)) {
348 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
349 // can be managed by this driver.
351 Status
= EFI_SUCCESS
;
352 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x501)) {
353 Status
= EFI_UNSUPPORTED
;
359 // Close protocol, don't use device path protocol in the Support() function
363 &gEfiDevicePathProtocolGuid
,
364 This
->DriverBindingHandle
,
372 Start to management the controller passed in
374 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
375 @param Controller The handle of the controller to test.
376 @param RemainingDevicePath A pointer to the remaining portion of a device path.
378 @return EFI_SUCCESS Driver is started successfully
383 SerialControllerDriverStart (
384 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
385 IN EFI_HANDLE Controller
,
386 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
391 EFI_ISA_IO_PROTOCOL
*IsaIo
;
392 SERIAL_DEV
*SerialDevice
;
394 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
395 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
397 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
398 UART_DEVICE_PATH
*Uart
;
399 UINT32 FlowControlMap
;
400 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
401 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
406 // Get the Parent Device Path
408 Status
= gBS
->OpenProtocol (
410 &gEfiDevicePathProtocolGuid
,
411 (VOID
**) &ParentDevicePath
,
412 This
->DriverBindingHandle
,
414 EFI_OPEN_PROTOCOL_BY_DRIVER
416 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
420 // Report status code enable the serial
422 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
424 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
429 // Grab the IO abstraction we need to get any work done
431 Status
= gBS
->OpenProtocol (
433 &gEfiIsaIoProtocolGuid
,
435 This
->DriverBindingHandle
,
437 EFI_OPEN_PROTOCOL_BY_DRIVER
439 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
443 if (Status
== EFI_ALREADY_STARTED
) {
445 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
447 // If RemainingDevicePath is NULL or is the End of Device Path Node
453 // Make sure a child handle does not already exist. This driver can only
454 // produce one child per serial port.
456 Status
= gBS
->OpenProtocolInformation (
458 &gEfiIsaIoProtocolGuid
,
462 if (EFI_ERROR (Status
)) {
466 Status
= EFI_ALREADY_STARTED
;
467 for (Index
= 0; Index
< EntryCount
; Index
++) {
468 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
469 Status
= gBS
->OpenProtocol (
470 OpenInfoBuffer
[Index
].ControllerHandle
,
471 &gEfiSerialIoProtocolGuid
,
473 This
->DriverBindingHandle
,
475 EFI_OPEN_PROTOCOL_GET_PROTOCOL
477 if (!EFI_ERROR (Status
)) {
478 Uart
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
479 Status
= SerialIo
->SetAttributes (
482 SerialIo
->Mode
->ReceiveFifoDepth
,
483 SerialIo
->Mode
->Timeout
,
484 (EFI_PARITY_TYPE
) Uart
->Parity
,
486 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
489 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
490 if (!EFI_ERROR (Status
) && IsUartFlowControlNode (FlowControl
)) {
491 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
492 if (!EFI_ERROR (Status
)) {
493 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
494 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
496 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
499 // Clear the bits that are not allowed to pass to SetControl
501 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
502 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
503 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
504 Status
= SerialIo
->SetControl (SerialIo
, Control
);
512 FreePool (OpenInfoBuffer
);
516 if (RemainingDevicePath
!= NULL
) {
517 if (IsDevicePathEnd (RemainingDevicePath
)) {
519 // If RemainingDevicePath is the End of Device Path Node,
520 // skip enumerate any device and return EFI_SUCESSS
527 // Initialize the serial device instance
529 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTempate
);
530 if (SerialDevice
== NULL
) {
531 Status
= EFI_OUT_OF_RESOURCES
;
535 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
536 SerialDevice
->IsaIo
= IsaIo
;
537 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
542 // Check if RemainingDevicePath is NULL,
543 // if yes, use the values from the gSerialDevTempate as no remaining device path was
546 if (RemainingDevicePath
!= NULL
) {
548 // If RemainingDevicePath isn't NULL,
549 // match the configuration of the RemainingDevicePath. IsHandleSupported()
550 // already checked to make sure the RemainingDevicePath contains settings
551 // that we can support.
553 CopyMem (&SerialDevice
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
554 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
555 if (IsUartFlowControlNode (FlowControl
)) {
556 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
562 AddName (SerialDevice
, IsaIo
);
564 for (Index
= 0; SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
565 if (SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
566 SerialDevice
->BaseAddress
= (UINT16
) SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
570 SerialDevice
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
573 // Report status code the serial present
575 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
577 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
581 if (!IsaSerialPortPresent (SerialDevice
)) {
582 Status
= EFI_DEVICE_ERROR
;
583 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
585 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
592 // Build the device path by appending the UART node to the ParentDevicePath.
593 // The Uart setings are zero here, since SetAttribute() will update them to match
594 // the default setings.
596 SerialDevice
->DevicePath
= AppendDevicePathNode (
598 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
601 // Only produce the Flow Control node when remaining device path has it
603 if (FlowControl
!= NULL
) {
604 TempDevicePath
= SerialDevice
->DevicePath
;
605 if (TempDevicePath
!= NULL
) {
606 SerialDevice
->DevicePath
= AppendDevicePathNode (
608 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
610 FreePool (TempDevicePath
);
613 if (SerialDevice
->DevicePath
== NULL
) {
614 Status
= EFI_OUT_OF_RESOURCES
;
619 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
621 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
622 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
623 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
624 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
627 // Issue a reset to initialize the COM port
629 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
630 if (EFI_ERROR (Status
)) {
631 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
633 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
639 // Install protocol interfaces for the serial device.
641 Status
= gBS
->InstallMultipleProtocolInterfaces (
642 &SerialDevice
->Handle
,
643 &gEfiDevicePathProtocolGuid
,
644 SerialDevice
->DevicePath
,
645 &gEfiSerialIoProtocolGuid
,
646 &SerialDevice
->SerialIo
,
649 if (EFI_ERROR (Status
)) {
653 // Open For Child Device
655 Status
= gBS
->OpenProtocol (
657 &gEfiIsaIoProtocolGuid
,
659 This
->DriverBindingHandle
,
660 SerialDevice
->Handle
,
661 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
665 if (EFI_ERROR (Status
)) {
668 &gEfiDevicePathProtocolGuid
,
669 This
->DriverBindingHandle
,
674 &gEfiIsaIoProtocolGuid
,
675 This
->DriverBindingHandle
,
678 if (SerialDevice
!= NULL
) {
679 if (SerialDevice
->DevicePath
!= NULL
) {
680 gBS
->FreePool (SerialDevice
->DevicePath
);
683 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
684 gBS
->FreePool (SerialDevice
);
692 Disconnect this driver with the controller, uninstall related protocol instance
694 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
695 @param Controller The handle of the controller to test.
696 @param NumberOfChildren Number of child device.
697 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
699 @retval EFI_SUCCESS Operation successfully
700 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
705 SerialControllerDriverStop (
706 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
707 IN EFI_HANDLE Controller
,
708 IN UINTN NumberOfChildren
,
709 IN EFI_HANDLE
*ChildHandleBuffer
715 BOOLEAN AllChildrenStopped
;
716 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
717 SERIAL_DEV
*SerialDevice
;
718 EFI_ISA_IO_PROTOCOL
*IsaIo
;
719 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
721 Status
= gBS
->HandleProtocol (
723 &gEfiDevicePathProtocolGuid
,
724 (VOID
**) &DevicePath
728 // Report the status code disable the serial
730 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
732 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
737 // Complete all outstanding transactions to Controller.
738 // Don't allow any new transaction to Controller to be started.
740 if (NumberOfChildren
== 0) {
742 // Close the bus driver
744 Status
= gBS
->CloseProtocol (
746 &gEfiIsaIoProtocolGuid
,
747 This
->DriverBindingHandle
,
751 Status
= gBS
->CloseProtocol (
753 &gEfiDevicePathProtocolGuid
,
754 This
->DriverBindingHandle
,
760 AllChildrenStopped
= TRUE
;
762 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
764 Status
= gBS
->OpenProtocol (
765 ChildHandleBuffer
[Index
],
766 &gEfiSerialIoProtocolGuid
,
768 This
->DriverBindingHandle
,
770 EFI_OPEN_PROTOCOL_GET_PROTOCOL
772 if (!EFI_ERROR (Status
)) {
774 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
776 Status
= gBS
->CloseProtocol (
778 &gEfiIsaIoProtocolGuid
,
779 This
->DriverBindingHandle
,
780 ChildHandleBuffer
[Index
]
783 Status
= gBS
->UninstallMultipleProtocolInterfaces (
784 ChildHandleBuffer
[Index
],
785 &gEfiDevicePathProtocolGuid
,
786 SerialDevice
->DevicePath
,
787 &gEfiSerialIoProtocolGuid
,
788 &SerialDevice
->SerialIo
,
791 if (EFI_ERROR (Status
)) {
794 &gEfiIsaIoProtocolGuid
,
796 This
->DriverBindingHandle
,
797 ChildHandleBuffer
[Index
],
798 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
801 if (SerialDevice
->DevicePath
!= NULL
) {
802 gBS
->FreePool (SerialDevice
->DevicePath
);
805 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
806 gBS
->FreePool (SerialDevice
);
810 if (EFI_ERROR (Status
)) {
811 AllChildrenStopped
= FALSE
;
815 if (!AllChildrenStopped
) {
816 return EFI_DEVICE_ERROR
;
823 Detect whether specific FIFO is full or not.
825 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
827 @return whether specific FIFO is full or not
832 IN SERIAL_DEV_FIFO
*Fifo
836 if (Fifo
->Surplus
== 0) {
844 Detect whether specific FIFO is empty or not.
846 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
848 @return whether specific FIFO is empty or not
853 IN SERIAL_DEV_FIFO
*Fifo
857 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
865 Add data to specific FIFO.
867 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
868 @param Data the data added to FIFO
870 @retval EFI_SUCCESS Add data to specific FIFO successfully
871 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
876 IN SERIAL_DEV_FIFO
*Fifo
,
882 // if FIFO full can not add data
884 if (IsaSerialFifoFull (Fifo
)) {
885 return EFI_OUT_OF_RESOURCES
;
888 // FIFO is not full can add data
890 Fifo
->Data
[Fifo
->Last
] = Data
;
893 if (Fifo
->Last
== SERIAL_MAX_BUFFER_SIZE
) {
901 Remove data from specific FIFO.
903 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
904 @param Data the data removed from FIFO
906 @retval EFI_SUCCESS Remove data from specific FIFO successfully
907 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
911 IsaSerialFifoRemove (
912 IN SERIAL_DEV_FIFO
*Fifo
,
918 // if FIFO is empty, no data can remove
920 if (IsaSerialFifoEmpty (Fifo
)) {
921 return EFI_OUT_OF_RESOURCES
;
924 // FIFO is not empty, can remove data
926 *Data
= Fifo
->Data
[Fifo
->First
];
929 if (Fifo
->First
== SERIAL_MAX_BUFFER_SIZE
) {
937 Reads and writes all avaliable data.
939 @param SerialDevice The device to flush
941 @retval EFI_SUCCESS Data was read/written successfully.
942 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
943 this happens, pending writes are not done.
947 IsaSerialReceiveTransmit (
948 IN SERIAL_DEV
*SerialDevice
954 BOOLEAN ReceiveFifoFull
;
962 // Begin the read or write
964 if (SerialDevice
->SoftwareLoopbackEnable
) {
966 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
967 if (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
968 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
969 if (ReceiveFifoFull
) {
970 return EFI_OUT_OF_RESOURCES
;
973 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
975 } while (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
977 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
979 // For full handshake flow control, tell the peer to send data
980 // if receive buffer is available.
982 if (SerialDevice
->HardwareFlowControl
&&
983 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)&&
986 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
988 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
991 Lsr
.Data
= READ_LSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
994 // Flush incomming data to prevent a an overrun during a long write
996 if ((Lsr
.Bits
.Dr
== 1) && !ReceiveFifoFull
) {
997 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
998 if (!ReceiveFifoFull
) {
999 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Oe
== 1 || Lsr
.Bits
.Pe
== 1 || Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
1000 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1002 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1003 SerialDevice
->DevicePath
1005 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Pe
== 1|| Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
1006 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1011 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1013 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
1016 // For full handshake flow control, if receive buffer full
1017 // tell the peer to stop sending data.
1019 if (SerialDevice
->HardwareFlowControl
&&
1020 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
) &&
1021 IsaSerialFifoFull (&SerialDevice
->Receive
)
1023 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1025 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1031 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1033 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER
| EFI_PERIPHERAL_SERIAL_PORT
,
1034 SerialDevice
->DevicePath
1041 if (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1043 // Make sure the transmit data will not be missed
1045 if (SerialDevice
->HardwareFlowControl
) {
1047 // For half handshake flow control assert RTS before sending.
1049 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
1050 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1052 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1058 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1059 while ((Msr
.Bits
.Dcd
== 1) && ((Msr
.Bits
.Cts
== 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
1060 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1066 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1069 if ((Msr
.Bits
.Dcd
== 0) || ((Msr
.Bits
.Cts
== 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
1070 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
1071 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
1075 // For half handshake flow control, tell DCE we are done.
1077 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
1078 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1080 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1083 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
1084 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
1087 } while (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
1094 // Interface Functions
1097 Reset serial device.
1099 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1101 @retval EFI_SUCCESS Reset successfully
1102 @retval EFI_DEVICE_ERROR Failed to reset
1108 IN EFI_SERIAL_IO_PROTOCOL
*This
1112 SERIAL_DEV
*SerialDevice
;
1113 SERIAL_PORT_LCR Lcr
;
1114 SERIAL_PORT_IER Ier
;
1115 SERIAL_PORT_MCR Mcr
;
1116 SERIAL_PORT_FCR Fcr
;
1120 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1123 // Report the status code reset the serial
1125 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1127 EFI_P_PC_RESET
| EFI_PERIPHERAL_SERIAL_PORT
,
1128 SerialDevice
->DevicePath
1131 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1134 // Make sure DLAB is 0.
1136 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1138 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1141 // Turn off all interrupts
1143 Ier
.Data
= READ_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1148 WRITE_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Ier
.Data
);
1151 // Disable the FIFO.
1153 Fcr
.Bits
.TrFIFOE
= 0;
1154 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1157 // Turn off loopback and disable device interrupt.
1159 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1163 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1166 // Clear the scratch pad register
1168 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0);
1171 // Go set the current attributes
1173 Status
= This
->SetAttributes (
1175 This
->Mode
->BaudRate
,
1176 This
->Mode
->ReceiveFifoDepth
,
1177 This
->Mode
->Timeout
,
1178 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
1179 (UINT8
) This
->Mode
->DataBits
,
1180 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
1183 if (EFI_ERROR (Status
)) {
1184 gBS
->RestoreTPL (Tpl
);
1185 return EFI_DEVICE_ERROR
;
1188 // Go set the current control bits
1191 if (SerialDevice
->HardwareFlowControl
) {
1192 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1194 if (SerialDevice
->SoftwareLoopbackEnable
) {
1195 Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1197 Status
= This
->SetControl (
1202 if (EFI_ERROR (Status
)) {
1203 gBS
->RestoreTPL (Tpl
);
1204 return EFI_DEVICE_ERROR
;
1207 // for 16550A enable FIFO, 16550 disable FIFO
1209 Fcr
.Bits
.TrFIFOE
= 1;
1210 Fcr
.Bits
.ResetRF
= 1;
1211 Fcr
.Bits
.ResetTF
= 1;
1212 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1215 // Reset the software FIFO
1217 SerialDevice
->Receive
.First
= 0;
1218 SerialDevice
->Receive
.Last
= 0;
1219 SerialDevice
->Receive
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1220 SerialDevice
->Transmit
.First
= 0;
1221 SerialDevice
->Transmit
.Last
= 0;
1222 SerialDevice
->Transmit
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1224 gBS
->RestoreTPL (Tpl
);
1227 // Device reset is complete
1233 Set new attributes to a serial device.
1235 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1236 @param BaudRate The baudrate of the serial device
1237 @param ReceiveFifoDepth The depth of receive FIFO buffer
1238 @param Timeout The request timeout for a single char
1239 @param Parity The type of parity used in serial device
1240 @param DataBits Number of databits used in serial device
1241 @param StopBits Number of stopbits used in serial device
1243 @retval EFI_SUCCESS The new attributes were set
1244 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
1245 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
1246 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
1251 IsaSerialSetAttributes (
1252 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1254 IN UINT32 ReceiveFifoDepth
,
1256 IN EFI_PARITY_TYPE Parity
,
1258 IN EFI_STOP_BITS_TYPE StopBits
1262 SERIAL_DEV
*SerialDevice
;
1265 SERIAL_PORT_LCR Lcr
;
1266 UART_DEVICE_PATH
*Uart
;
1269 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1272 // Check for default settings and fill in actual values.
1274 if (BaudRate
== 0) {
1275 BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
1278 if (ReceiveFifoDepth
== 0) {
1279 ReceiveFifoDepth
= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
;
1283 Timeout
= SERIAL_PORT_DEFAULT_TIMEOUT
;
1286 if (Parity
== DefaultParity
) {
1287 Parity
= (EFI_PARITY_TYPE
)PcdGet8 (PcdUartDefaultParity
);
1290 if (DataBits
== 0) {
1291 DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
1294 if (StopBits
== DefaultStopBits
) {
1295 StopBits
= (EFI_STOP_BITS_TYPE
) PcdGet8 (PcdUartDefaultStopBits
);
1298 // 5 and 6 data bits can not be verified on a 16550A UART
1299 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1301 if ((DataBits
== 5) || (DataBits
== 6)) {
1302 return EFI_INVALID_PARAMETER
;
1305 // Make sure all parameters are valid
1307 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
1308 return EFI_INVALID_PARAMETER
;
1311 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1312 // 38400,57600,115200
1314 if (BaudRate
< 75) {
1316 } else if (BaudRate
< 110) {
1318 } else if (BaudRate
< 134) {
1320 } else if (BaudRate
< 150) {
1322 } else if (BaudRate
< 300) {
1324 } else if (BaudRate
< 600) {
1326 } else if (BaudRate
< 1200) {
1328 } else if (BaudRate
< 1800) {
1330 } else if (BaudRate
< 2000) {
1332 } else if (BaudRate
< 2400) {
1334 } else if (BaudRate
< 3600) {
1336 } else if (BaudRate
< 4800) {
1338 } else if (BaudRate
< 7200) {
1340 } else if (BaudRate
< 9600) {
1342 } else if (BaudRate
< 19200) {
1344 } else if (BaudRate
< 38400) {
1346 } else if (BaudRate
< 57600) {
1348 } else if (BaudRate
< 115200) {
1350 } else if (BaudRate
<= SERIAL_PORT_MAX_BAUD_RATE
) {
1354 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
1355 return EFI_INVALID_PARAMETER
;
1358 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
1359 return EFI_INVALID_PARAMETER
;
1362 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
1363 return EFI_INVALID_PARAMETER
;
1366 if ((DataBits
< 5) || (DataBits
> 8)) {
1367 return EFI_INVALID_PARAMETER
;
1370 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
1371 return EFI_INVALID_PARAMETER
;
1375 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1377 if ((DataBits
>= 6) && (DataBits
<= 8) && (StopBits
== OneFiveStopBits
)) {
1378 return EFI_INVALID_PARAMETER
;
1382 // Compute divisor use to program the baud rate using a round determination
1384 Divisor
= (UINT32
) DivU64x32Remainder (
1385 SERIAL_PORT_INPUT_CLOCK
,
1386 ((UINT32
) BaudRate
* 16),
1389 if (Remained
!= 0) {
1393 if ((Divisor
== 0) || ((Divisor
& 0xffff0000) != 0)) {
1394 return EFI_INVALID_PARAMETER
;
1397 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1400 // Compute the actual baud rate that the serial port will be programmed for.
1402 BaudRate
= SERIAL_PORT_INPUT_CLOCK
/ Divisor
/ 16;
1405 // Put serial port on Divisor Latch Mode
1407 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1409 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1412 // Write the divisor to the serial port
1414 WRITE_DLL (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) (Divisor
& 0xff));
1415 WRITE_DLM (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) ((Divisor
>> 8) & 0xff));
1418 // Put serial port back in normal mode and set remaining attributes.
1425 Lcr
.Bits
.EvenPar
= 0;
1426 Lcr
.Bits
.SticPar
= 0;
1431 Lcr
.Bits
.EvenPar
= 1;
1432 Lcr
.Bits
.SticPar
= 0;
1437 Lcr
.Bits
.EvenPar
= 0;
1438 Lcr
.Bits
.SticPar
= 0;
1443 Lcr
.Bits
.EvenPar
= 1;
1444 Lcr
.Bits
.SticPar
= 1;
1449 Lcr
.Bits
.EvenPar
= 0;
1450 Lcr
.Bits
.SticPar
= 1;
1462 case OneFiveStopBits
:
1473 Lcr
.Bits
.SerialDB
= (UINT8
) ((DataBits
- 5) & 0x03);
1474 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1477 // Set the Serial I/O mode
1479 This
->Mode
->BaudRate
= BaudRate
;
1480 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
1481 This
->Mode
->Timeout
= Timeout
;
1482 This
->Mode
->Parity
= Parity
;
1483 This
->Mode
->DataBits
= DataBits
;
1484 This
->Mode
->StopBits
= StopBits
;
1487 // See if Device Path Node has actually changed
1489 if (SerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
1490 SerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
1491 SerialDevice
->UartDevicePath
.Parity
== Parity
&&
1492 SerialDevice
->UartDevicePath
.StopBits
== StopBits
1494 gBS
->RestoreTPL (Tpl
);
1498 // Update the device path
1500 SerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
1501 SerialDevice
->UartDevicePath
.DataBits
= DataBits
;
1502 SerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1503 SerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1505 Status
= EFI_SUCCESS
;
1506 if (SerialDevice
->Handle
!= NULL
) {
1507 Uart
= (UART_DEVICE_PATH
*) (
1508 (UINTN
) SerialDevice
->DevicePath
1509 + GetDevicePathSize (SerialDevice
->ParentDevicePath
)
1510 - END_DEVICE_PATH_LENGTH
1512 CopyMem (Uart
, &SerialDevice
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
1513 Status
= gBS
->ReinstallProtocolInterface (
1514 SerialDevice
->Handle
,
1515 &gEfiDevicePathProtocolGuid
,
1516 SerialDevice
->DevicePath
,
1517 SerialDevice
->DevicePath
1521 gBS
->RestoreTPL (Tpl
);
1529 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1530 @param Control Control bits that can be settable
1532 @retval EFI_SUCCESS New Control bits were set successfully
1533 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
1538 IsaSerialSetControl (
1539 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1543 SERIAL_DEV
*SerialDevice
;
1544 SERIAL_PORT_MCR Mcr
;
1546 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1550 // The control bits that can be set are :
1551 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1552 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1553 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1554 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1555 // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW
1557 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1560 // first determine the parameter is invalid
1562 if ((Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1563 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1564 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) != 0) {
1565 return EFI_UNSUPPORTED
;
1568 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1570 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1574 SerialDevice
->SoftwareLoopbackEnable
= FALSE
;
1575 SerialDevice
->HardwareFlowControl
= FALSE
;
1577 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
1581 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
1585 if ((Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1589 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1590 SerialDevice
->HardwareFlowControl
= TRUE
;
1593 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1595 if ((Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1596 SerialDevice
->SoftwareLoopbackEnable
= TRUE
;
1599 Status
= EFI_SUCCESS
;
1600 if (SerialDevice
->Handle
!= NULL
) {
1601 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) (
1602 (UINTN
) SerialDevice
->DevicePath
1603 + GetDevicePathSize (SerialDevice
->ParentDevicePath
)
1604 - END_DEVICE_PATH_LENGTH
1605 + sizeof (UART_DEVICE_PATH
)
1607 if (IsUartFlowControlNode (FlowControl
) &&
1608 ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) ^ SerialDevice
->HardwareFlowControl
)) {
1610 // Flow Control setting is changed, need to reinstall device path protocol
1612 WriteUnaligned32 (&FlowControl
->FlowControlMap
, SerialDevice
->HardwareFlowControl
? UART_FLOW_CONTROL_HARDWARE
: 0);
1613 Status
= gBS
->ReinstallProtocolInterface (
1614 SerialDevice
->Handle
,
1615 &gEfiDevicePathProtocolGuid
,
1616 SerialDevice
->DevicePath
,
1617 SerialDevice
->DevicePath
1622 gBS
->RestoreTPL (Tpl
);
1630 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1631 @param Control Control signals of the serial device
1633 @retval EFI_SUCCESS Get Control signals successfully
1638 IsaSerialGetControl (
1639 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1643 SERIAL_DEV
*SerialDevice
;
1644 SERIAL_PORT_MSR Msr
;
1645 SERIAL_PORT_MCR Mcr
;
1648 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1650 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1655 // Read the Modem Status Register
1657 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1659 if (Msr
.Bits
.Cts
== 1) {
1660 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1663 if (Msr
.Bits
.Dsr
== 1) {
1664 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1667 if (Msr
.Bits
.Ri
== 1) {
1668 *Control
|= EFI_SERIAL_RING_INDICATE
;
1671 if (Msr
.Bits
.Dcd
== 1) {
1672 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1675 // Read the Modem Control Register
1677 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1679 if (Mcr
.Bits
.DtrC
== 1) {
1680 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1683 if (Mcr
.Bits
.Rts
== 1) {
1684 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1687 if (Mcr
.Bits
.Lme
== 1) {
1688 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1691 if (SerialDevice
->HardwareFlowControl
) {
1692 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1695 // See if the Transmit FIFO is empty
1697 IsaSerialReceiveTransmit (SerialDevice
);
1699 if (IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1700 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1703 // See if the Receive FIFO is empty.
1705 IsaSerialReceiveTransmit (SerialDevice
);
1707 if (IsaSerialFifoEmpty (&SerialDevice
->Receive
)) {
1708 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1711 if (SerialDevice
->SoftwareLoopbackEnable
) {
1712 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1715 gBS
->RestoreTPL (Tpl
);
1721 Write the specified number of bytes to serial device.
1723 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1724 @param BufferSize On input the size of Buffer, on output the amount of
1725 data actually written
1726 @param Buffer The buffer of data to write
1728 @retval EFI_SUCCESS The data were written successfully
1729 @retval EFI_DEVICE_ERROR The device reported an error
1730 @retval EFI_TIMEOUT The write operation was stopped due to timeout
1736 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1737 IN OUT UINTN
*BufferSize
,
1741 SERIAL_DEV
*SerialDevice
;
1748 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1752 if (*BufferSize
== 0) {
1756 if (Buffer
== NULL
) {
1757 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1759 EFI_P_EC_OUTPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1760 SerialDevice
->DevicePath
1763 return EFI_DEVICE_ERROR
;
1766 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1768 CharBuffer
= (UINT8
*) Buffer
;
1770 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1771 IsaSerialFifoAdd (&SerialDevice
->Transmit
, CharBuffer
[Index
]);
1773 while (IsaSerialReceiveTransmit (SerialDevice
) != EFI_SUCCESS
|| !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1775 // Unsuccessful write so check if timeout has expired, if not,
1776 // stall for a bit, increment time elapsed, and try again
1778 if (Elapsed
>= This
->Mode
->Timeout
) {
1779 *BufferSize
= ActualWrite
;
1780 gBS
->RestoreTPL (Tpl
);
1784 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1786 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1791 // Successful write so reset timeout
1796 gBS
->RestoreTPL (Tpl
);
1802 Read the specified number of bytes from serial device.
1804 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1805 @param BufferSize On input the size of Buffer, on output the amount of
1806 data returned in buffer
1807 @param Buffer The buffer to return the data into
1809 @retval EFI_SUCCESS The data were read successfully
1810 @retval EFI_DEVICE_ERROR The device reported an error
1811 @retval EFI_TIMEOUT The read operation was stopped due to timeout
1817 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1818 IN OUT UINTN
*BufferSize
,
1822 SERIAL_DEV
*SerialDevice
;
1829 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1832 if (*BufferSize
== 0) {
1836 if (Buffer
== NULL
) {
1837 return EFI_DEVICE_ERROR
;
1840 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1842 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1844 if (EFI_ERROR (Status
)) {
1847 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1849 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1850 SerialDevice
->DevicePath
1853 gBS
->RestoreTPL (Tpl
);
1855 return EFI_DEVICE_ERROR
;
1858 CharBuffer
= (UINT8
*) Buffer
;
1859 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1860 while (IsaSerialFifoRemove (&SerialDevice
->Receive
, &(CharBuffer
[Index
])) != EFI_SUCCESS
) {
1862 // Unsuccessful read so check if timeout has expired, if not,
1863 // stall for a bit, increment time elapsed, and try again
1864 // Need this time out to get conspliter to work.
1866 if (Elapsed
>= This
->Mode
->Timeout
) {
1867 *BufferSize
= Index
;
1868 gBS
->RestoreTPL (Tpl
);
1872 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1873 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1875 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1876 if (Status
== EFI_DEVICE_ERROR
) {
1877 *BufferSize
= Index
;
1878 gBS
->RestoreTPL (Tpl
);
1879 return EFI_DEVICE_ERROR
;
1883 // Successful read so reset timeout
1888 IsaSerialReceiveTransmit (SerialDevice
);
1890 gBS
->RestoreTPL (Tpl
);
1896 Use scratchpad register to test if this serial port is present.
1898 @param SerialDevice Pointer to serial device structure
1900 @return if this serial port is present
1903 IsaSerialPortPresent (
1904 IN SERIAL_DEV
*SerialDevice
1916 Temp
= READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1917 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0xAA);
1919 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0xAA) {
1923 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0x55);
1925 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0x55) {
1931 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Temp
);
1936 Use IsaIo protocol to read serial port.
1938 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1939 @param BaseAddress Serial port register group base address
1940 @param Offset Offset in register group
1942 @return Data read from serial port
1947 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1948 IN UINT16 BaseAddress
,
1955 // Use IsaIo to access IO
1960 BaseAddress
+ Offset
,
1968 Use IsaIo protocol to write serial port.
1970 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1971 @param BaseAddress Serial port register group base address
1972 @param Offset Offset in register group
1973 @param Data data which is to be written to some serial port register
1977 IsaSerialWritePort (
1978 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1979 IN UINT16 BaseAddress
,
1985 // Use IsaIo to access IO
1990 BaseAddress
+ Offset
,