2 Serial driver for standard UARTS on an ISA bus.
4 Copyright (c) 2006 - 2014, 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
,
47 SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
,
56 MESSAGING_DEVICE_PATH
,
59 (UINT8
) (sizeof (UART_DEVICE_PATH
)),
60 (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8)
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
);
167 // Initialize UART default setting in gSerialDevTempate
169 gSerialDevTempate
.SerialMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
170 gSerialDevTempate
.SerialMode
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
171 gSerialDevTempate
.SerialMode
.Parity
= PcdGet8 (PcdUartDefaultParity
);
172 gSerialDevTempate
.SerialMode
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
173 gSerialDevTempate
.UartDevicePath
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
174 gSerialDevTempate
.UartDevicePath
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
175 gSerialDevTempate
.UartDevicePath
.Parity
= PcdGet8 (PcdUartDefaultParity
);
176 gSerialDevTempate
.UartDevicePath
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
182 Check to see if this driver supports the given controller
184 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
185 @param Controller The handle of the controller to test.
186 @param RemainingDevicePath A pointer to the remaining portion of a device path.
188 @return EFI_SUCCESS This driver can support the given controller
193 SerialControllerDriverSupported (
194 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
195 IN EFI_HANDLE Controller
,
196 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
201 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
202 EFI_ISA_IO_PROTOCOL
*IsaIo
;
203 UART_DEVICE_PATH
*UartNode
;
204 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
205 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControlNode
;
206 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
209 BOOLEAN HasFlowControl
;
212 // Check RemainingDevicePath validation
214 if (RemainingDevicePath
!= NULL
) {
216 // Check if RemainingDevicePath is the End of Device Path Node,
217 // if yes, go on checking other conditions
219 if (!IsDevicePathEnd (RemainingDevicePath
)) {
221 // If RemainingDevicePath isn't the End of Device Path Node,
222 // check its validation
224 Status
= EFI_UNSUPPORTED
;
226 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
227 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
228 UartNode
->Header
.SubType
!= MSG_UART_DP
||
229 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) UartNode
)
234 if (UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
238 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
242 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
246 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
250 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
254 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
258 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (UartNode
);
259 if (IsUartFlowControlNode (FlowControlNode
)) {
261 // If the second node is Flow Control Node,
262 // return error when it request other than hardware flow control.
264 if ((ReadUnaligned32 (&FlowControlNode
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
272 // Open the IO Abstraction(s) needed to perform the supported test
274 Status
= gBS
->OpenProtocol (
276 &gEfiIsaIoProtocolGuid
,
278 This
->DriverBindingHandle
,
280 EFI_OPEN_PROTOCOL_BY_DRIVER
282 if (Status
== EFI_ALREADY_STARTED
) {
283 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
285 // If RemainingDevicePath is NULL or is the End of Device Path Node
290 // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
291 // return unsupported, and vice versa.
293 Status
= gBS
->OpenProtocolInformation (
295 &gEfiIsaIoProtocolGuid
,
299 if (EFI_ERROR (Status
)) {
303 for (Index
= 0; Index
< EntryCount
; Index
++) {
304 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
305 Status
= gBS
->OpenProtocol (
306 OpenInfoBuffer
[Index
].ControllerHandle
,
307 &gEfiDevicePathProtocolGuid
,
308 (VOID
**) &DevicePath
,
309 This
->DriverBindingHandle
,
311 EFI_OPEN_PROTOCOL_GET_PROTOCOL
313 if (!EFI_ERROR (Status
)) {
314 HasFlowControl
= ContainsFlowControl (RemainingDevicePath
);
315 if (HasFlowControl
^ ContainsFlowControl (DevicePath
)) {
316 Status
= EFI_UNSUPPORTED
;
322 FreePool (OpenInfoBuffer
);
326 if (EFI_ERROR (Status
)) {
331 // Close the I/O Abstraction(s) used to perform the supported test
335 &gEfiIsaIoProtocolGuid
,
336 This
->DriverBindingHandle
,
341 // Open the EFI Device Path protocol needed to perform the supported test
343 Status
= gBS
->OpenProtocol (
345 &gEfiDevicePathProtocolGuid
,
346 (VOID
**) &ParentDevicePath
,
347 This
->DriverBindingHandle
,
349 EFI_OPEN_PROTOCOL_BY_DRIVER
351 if (Status
== EFI_ALREADY_STARTED
) {
355 if (EFI_ERROR (Status
)) {
359 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
360 // can be managed by this driver.
362 Status
= EFI_SUCCESS
;
363 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x501)) {
364 Status
= EFI_UNSUPPORTED
;
370 // Close protocol, don't use device path protocol in the Support() function
374 &gEfiDevicePathProtocolGuid
,
375 This
->DriverBindingHandle
,
383 Start to management the controller passed in
385 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
386 @param Controller The handle of the controller to test.
387 @param RemainingDevicePath A pointer to the remaining portion of a device path.
389 @return EFI_SUCCESS Driver is started successfully
394 SerialControllerDriverStart (
395 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
396 IN EFI_HANDLE Controller
,
397 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
402 EFI_ISA_IO_PROTOCOL
*IsaIo
;
403 SERIAL_DEV
*SerialDevice
;
405 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
406 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
408 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
409 UART_DEVICE_PATH
*Uart
;
410 UINT32 FlowControlMap
;
411 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
412 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
417 // Get the Parent Device Path
419 Status
= gBS
->OpenProtocol (
421 &gEfiDevicePathProtocolGuid
,
422 (VOID
**) &ParentDevicePath
,
423 This
->DriverBindingHandle
,
425 EFI_OPEN_PROTOCOL_BY_DRIVER
427 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
431 // Report status code enable the serial
433 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
435 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
440 // Grab the IO abstraction we need to get any work done
442 Status
= gBS
->OpenProtocol (
444 &gEfiIsaIoProtocolGuid
,
446 This
->DriverBindingHandle
,
448 EFI_OPEN_PROTOCOL_BY_DRIVER
450 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
454 if (Status
== EFI_ALREADY_STARTED
) {
456 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
458 // If RemainingDevicePath is NULL or is the End of Device Path Node
464 // Make sure a child handle does not already exist. This driver can only
465 // produce one child per serial port.
467 Status
= gBS
->OpenProtocolInformation (
469 &gEfiIsaIoProtocolGuid
,
473 if (EFI_ERROR (Status
)) {
477 Status
= EFI_ALREADY_STARTED
;
478 for (Index
= 0; Index
< EntryCount
; Index
++) {
479 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
480 Status
= gBS
->OpenProtocol (
481 OpenInfoBuffer
[Index
].ControllerHandle
,
482 &gEfiSerialIoProtocolGuid
,
484 This
->DriverBindingHandle
,
486 EFI_OPEN_PROTOCOL_GET_PROTOCOL
488 if (!EFI_ERROR (Status
)) {
489 Uart
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
490 Status
= SerialIo
->SetAttributes (
493 SerialIo
->Mode
->ReceiveFifoDepth
,
494 SerialIo
->Mode
->Timeout
,
495 (EFI_PARITY_TYPE
) Uart
->Parity
,
497 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
500 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
501 if (!EFI_ERROR (Status
) && IsUartFlowControlNode (FlowControl
)) {
502 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
503 if (!EFI_ERROR (Status
)) {
504 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
505 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
507 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
510 // Clear the bits that are not allowed to pass to SetControl
512 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
513 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
514 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
515 Status
= SerialIo
->SetControl (SerialIo
, Control
);
523 FreePool (OpenInfoBuffer
);
527 if (RemainingDevicePath
!= NULL
) {
528 if (IsDevicePathEnd (RemainingDevicePath
)) {
530 // If RemainingDevicePath is the End of Device Path Node,
531 // skip enumerate any device and return EFI_SUCESSS
538 // Initialize the serial device instance
540 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTempate
);
541 if (SerialDevice
== NULL
) {
542 Status
= EFI_OUT_OF_RESOURCES
;
546 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
547 SerialDevice
->IsaIo
= IsaIo
;
548 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
553 // Check if RemainingDevicePath is NULL,
554 // if yes, use the values from the gSerialDevTempate as no remaining device path was
557 if (RemainingDevicePath
!= NULL
) {
559 // If RemainingDevicePath isn't NULL,
560 // match the configuration of the RemainingDevicePath. IsHandleSupported()
561 // already checked to make sure the RemainingDevicePath contains settings
562 // that we can support.
564 CopyMem (&SerialDevice
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
565 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
566 if (IsUartFlowControlNode (FlowControl
)) {
567 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
573 AddName (SerialDevice
, IsaIo
);
575 for (Index
= 0; SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
576 if (SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
577 SerialDevice
->BaseAddress
= (UINT16
) SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
581 SerialDevice
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
584 // Report status code the serial present
586 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
588 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
592 if (!IsaSerialPortPresent (SerialDevice
)) {
593 Status
= EFI_DEVICE_ERROR
;
594 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
596 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
603 // Build the device path by appending the UART node to the ParentDevicePath.
604 // The Uart setings are zero here, since SetAttribute() will update them to match
605 // the default setings.
607 SerialDevice
->DevicePath
= AppendDevicePathNode (
609 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
612 // Only produce the Flow Control node when remaining device path has it
614 if (FlowControl
!= NULL
) {
615 TempDevicePath
= SerialDevice
->DevicePath
;
616 if (TempDevicePath
!= NULL
) {
617 SerialDevice
->DevicePath
= AppendDevicePathNode (
619 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
621 FreePool (TempDevicePath
);
624 if (SerialDevice
->DevicePath
== NULL
) {
625 Status
= EFI_OUT_OF_RESOURCES
;
630 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
632 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
633 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
634 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
635 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
638 // Issue a reset to initialize the COM port
640 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
641 if (EFI_ERROR (Status
)) {
642 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
644 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
650 // Install protocol interfaces for the serial device.
652 Status
= gBS
->InstallMultipleProtocolInterfaces (
653 &SerialDevice
->Handle
,
654 &gEfiDevicePathProtocolGuid
,
655 SerialDevice
->DevicePath
,
656 &gEfiSerialIoProtocolGuid
,
657 &SerialDevice
->SerialIo
,
660 if (EFI_ERROR (Status
)) {
664 // Open For Child Device
666 Status
= gBS
->OpenProtocol (
668 &gEfiIsaIoProtocolGuid
,
670 This
->DriverBindingHandle
,
671 SerialDevice
->Handle
,
672 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
676 if (EFI_ERROR (Status
)) {
679 &gEfiDevicePathProtocolGuid
,
680 This
->DriverBindingHandle
,
685 &gEfiIsaIoProtocolGuid
,
686 This
->DriverBindingHandle
,
689 if (SerialDevice
!= NULL
) {
690 if (SerialDevice
->DevicePath
!= NULL
) {
691 gBS
->FreePool (SerialDevice
->DevicePath
);
694 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
695 gBS
->FreePool (SerialDevice
);
703 Disconnect this driver with the controller, uninstall related protocol instance
705 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
706 @param Controller The handle of the controller to test.
707 @param NumberOfChildren Number of child device.
708 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
710 @retval EFI_SUCCESS Operation successfully
711 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
716 SerialControllerDriverStop (
717 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
718 IN EFI_HANDLE Controller
,
719 IN UINTN NumberOfChildren
,
720 IN EFI_HANDLE
*ChildHandleBuffer
726 BOOLEAN AllChildrenStopped
;
727 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
728 SERIAL_DEV
*SerialDevice
;
729 EFI_ISA_IO_PROTOCOL
*IsaIo
;
730 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
732 Status
= gBS
->HandleProtocol (
734 &gEfiDevicePathProtocolGuid
,
735 (VOID
**) &DevicePath
739 // Report the status code disable the serial
741 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
743 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
748 // Complete all outstanding transactions to Controller.
749 // Don't allow any new transaction to Controller to be started.
751 if (NumberOfChildren
== 0) {
753 // Close the bus driver
755 Status
= gBS
->CloseProtocol (
757 &gEfiIsaIoProtocolGuid
,
758 This
->DriverBindingHandle
,
762 Status
= gBS
->CloseProtocol (
764 &gEfiDevicePathProtocolGuid
,
765 This
->DriverBindingHandle
,
771 AllChildrenStopped
= TRUE
;
773 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
775 Status
= gBS
->OpenProtocol (
776 ChildHandleBuffer
[Index
],
777 &gEfiSerialIoProtocolGuid
,
779 This
->DriverBindingHandle
,
781 EFI_OPEN_PROTOCOL_GET_PROTOCOL
783 if (!EFI_ERROR (Status
)) {
785 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
787 Status
= gBS
->CloseProtocol (
789 &gEfiIsaIoProtocolGuid
,
790 This
->DriverBindingHandle
,
791 ChildHandleBuffer
[Index
]
794 Status
= gBS
->UninstallMultipleProtocolInterfaces (
795 ChildHandleBuffer
[Index
],
796 &gEfiDevicePathProtocolGuid
,
797 SerialDevice
->DevicePath
,
798 &gEfiSerialIoProtocolGuid
,
799 &SerialDevice
->SerialIo
,
802 if (EFI_ERROR (Status
)) {
805 &gEfiIsaIoProtocolGuid
,
807 This
->DriverBindingHandle
,
808 ChildHandleBuffer
[Index
],
809 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
812 if (SerialDevice
->DevicePath
!= NULL
) {
813 gBS
->FreePool (SerialDevice
->DevicePath
);
816 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
817 gBS
->FreePool (SerialDevice
);
821 if (EFI_ERROR (Status
)) {
822 AllChildrenStopped
= FALSE
;
826 if (!AllChildrenStopped
) {
827 return EFI_DEVICE_ERROR
;
834 Detect whether specific FIFO is full or not.
836 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
838 @return whether specific FIFO is full or not
843 IN SERIAL_DEV_FIFO
*Fifo
847 if (Fifo
->Surplus
== 0) {
855 Detect whether specific FIFO is empty or not.
857 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
859 @return whether specific FIFO is empty or not
864 IN SERIAL_DEV_FIFO
*Fifo
868 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
876 Add data to specific FIFO.
878 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
879 @param Data the data added to FIFO
881 @retval EFI_SUCCESS Add data to specific FIFO successfully
882 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
887 IN SERIAL_DEV_FIFO
*Fifo
,
893 // if FIFO full can not add data
895 if (IsaSerialFifoFull (Fifo
)) {
896 return EFI_OUT_OF_RESOURCES
;
899 // FIFO is not full can add data
901 Fifo
->Data
[Fifo
->Last
] = Data
;
904 if (Fifo
->Last
== SERIAL_MAX_BUFFER_SIZE
) {
912 Remove data from specific FIFO.
914 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
915 @param Data the data removed from FIFO
917 @retval EFI_SUCCESS Remove data from specific FIFO successfully
918 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
922 IsaSerialFifoRemove (
923 IN SERIAL_DEV_FIFO
*Fifo
,
929 // if FIFO is empty, no data can remove
931 if (IsaSerialFifoEmpty (Fifo
)) {
932 return EFI_OUT_OF_RESOURCES
;
935 // FIFO is not empty, can remove data
937 *Data
= Fifo
->Data
[Fifo
->First
];
940 if (Fifo
->First
== SERIAL_MAX_BUFFER_SIZE
) {
948 Reads and writes all avaliable data.
950 @param SerialDevice The device to flush
952 @retval EFI_SUCCESS Data was read/written successfully.
953 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
954 this happens, pending writes are not done.
958 IsaSerialReceiveTransmit (
959 IN SERIAL_DEV
*SerialDevice
965 BOOLEAN ReceiveFifoFull
;
973 // Begin the read or write
975 if (SerialDevice
->SoftwareLoopbackEnable
) {
977 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
978 if (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
979 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
980 if (ReceiveFifoFull
) {
981 return EFI_OUT_OF_RESOURCES
;
984 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
986 } while (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
988 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
990 // For full handshake flow control, tell the peer to send data
991 // if receive buffer is available.
993 if (SerialDevice
->HardwareFlowControl
&&
994 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)&&
997 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
999 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1002 Lsr
.Data
= READ_LSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1005 // Flush incomming data to prevent a an overrun during a long write
1007 if ((Lsr
.Bits
.Dr
== 1) && !ReceiveFifoFull
) {
1008 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
1009 if (!ReceiveFifoFull
) {
1010 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Oe
== 1 || Lsr
.Bits
.Pe
== 1 || Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
1011 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1013 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1014 SerialDevice
->DevicePath
1016 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Pe
== 1|| Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
1017 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1022 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1024 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
1027 // For full handshake flow control, if receive buffer full
1028 // tell the peer to stop sending data.
1030 if (SerialDevice
->HardwareFlowControl
&&
1031 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
) &&
1032 IsaSerialFifoFull (&SerialDevice
->Receive
)
1034 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1036 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1042 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1044 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER
| EFI_PERIPHERAL_SERIAL_PORT
,
1045 SerialDevice
->DevicePath
1052 if (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1054 // Make sure the transmit data will not be missed
1056 if (SerialDevice
->HardwareFlowControl
) {
1058 // For half handshake flow control assert RTS before sending.
1060 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
1061 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1063 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1069 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1070 while ((Msr
.Bits
.Dcd
== 1) && ((Msr
.Bits
.Cts
== 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
1071 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1077 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1080 if ((Msr
.Bits
.Dcd
== 0) || ((Msr
.Bits
.Cts
== 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
1081 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
1082 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
1086 // For half handshake flow control, tell DCE we are done.
1088 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
1089 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1091 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1094 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
1095 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
1098 } while (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
1105 // Interface Functions
1108 Reset serial device.
1110 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1112 @retval EFI_SUCCESS Reset successfully
1113 @retval EFI_DEVICE_ERROR Failed to reset
1119 IN EFI_SERIAL_IO_PROTOCOL
*This
1123 SERIAL_DEV
*SerialDevice
;
1124 SERIAL_PORT_LCR Lcr
;
1125 SERIAL_PORT_IER Ier
;
1126 SERIAL_PORT_MCR Mcr
;
1127 SERIAL_PORT_FCR Fcr
;
1131 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1134 // Report the status code reset the serial
1136 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1138 EFI_P_PC_RESET
| EFI_PERIPHERAL_SERIAL_PORT
,
1139 SerialDevice
->DevicePath
1142 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1145 // Make sure DLAB is 0.
1147 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1149 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1152 // Turn off all interrupts
1154 Ier
.Data
= READ_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1159 WRITE_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Ier
.Data
);
1162 // Disable the FIFO.
1164 Fcr
.Bits
.TrFIFOE
= 0;
1165 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1168 // Turn off loopback and disable device interrupt.
1170 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1174 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1177 // Clear the scratch pad register
1179 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0);
1182 // Go set the current attributes
1184 Status
= This
->SetAttributes (
1186 This
->Mode
->BaudRate
,
1187 This
->Mode
->ReceiveFifoDepth
,
1188 This
->Mode
->Timeout
,
1189 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
1190 (UINT8
) This
->Mode
->DataBits
,
1191 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
1194 if (EFI_ERROR (Status
)) {
1195 gBS
->RestoreTPL (Tpl
);
1196 return EFI_DEVICE_ERROR
;
1199 // Go set the current control bits
1202 if (SerialDevice
->HardwareFlowControl
) {
1203 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1205 if (SerialDevice
->SoftwareLoopbackEnable
) {
1206 Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1208 Status
= This
->SetControl (
1213 if (EFI_ERROR (Status
)) {
1214 gBS
->RestoreTPL (Tpl
);
1215 return EFI_DEVICE_ERROR
;
1218 // for 16550A enable FIFO, 16550 disable FIFO
1220 Fcr
.Bits
.TrFIFOE
= 1;
1221 Fcr
.Bits
.ResetRF
= 1;
1222 Fcr
.Bits
.ResetTF
= 1;
1223 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1226 // Reset the software FIFO
1228 SerialDevice
->Receive
.First
= 0;
1229 SerialDevice
->Receive
.Last
= 0;
1230 SerialDevice
->Receive
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1231 SerialDevice
->Transmit
.First
= 0;
1232 SerialDevice
->Transmit
.Last
= 0;
1233 SerialDevice
->Transmit
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1235 gBS
->RestoreTPL (Tpl
);
1238 // Device reset is complete
1244 Set new attributes to a serial device.
1246 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1247 @param BaudRate The baudrate of the serial device
1248 @param ReceiveFifoDepth The depth of receive FIFO buffer
1249 @param Timeout The request timeout for a single char
1250 @param Parity The type of parity used in serial device
1251 @param DataBits Number of databits used in serial device
1252 @param StopBits Number of stopbits used in serial device
1254 @retval EFI_SUCCESS The new attributes were set
1255 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
1256 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
1257 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
1262 IsaSerialSetAttributes (
1263 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1265 IN UINT32 ReceiveFifoDepth
,
1267 IN EFI_PARITY_TYPE Parity
,
1269 IN EFI_STOP_BITS_TYPE StopBits
1273 SERIAL_DEV
*SerialDevice
;
1276 SERIAL_PORT_LCR Lcr
;
1277 UART_DEVICE_PATH
*Uart
;
1280 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1283 // Check for default settings and fill in actual values.
1285 if (BaudRate
== 0) {
1286 BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
1289 if (ReceiveFifoDepth
== 0) {
1290 ReceiveFifoDepth
= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
;
1294 Timeout
= SERIAL_PORT_DEFAULT_TIMEOUT
;
1297 if (Parity
== DefaultParity
) {
1298 Parity
= (EFI_PARITY_TYPE
)PcdGet8 (PcdUartDefaultParity
);
1301 if (DataBits
== 0) {
1302 DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
1305 if (StopBits
== DefaultStopBits
) {
1306 StopBits
= (EFI_STOP_BITS_TYPE
) PcdGet8 (PcdUartDefaultStopBits
);
1309 // 5 and 6 data bits can not be verified on a 16550A UART
1310 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1312 if ((DataBits
== 5) || (DataBits
== 6)) {
1313 return EFI_INVALID_PARAMETER
;
1316 // Make sure all parameters are valid
1318 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
1319 return EFI_INVALID_PARAMETER
;
1322 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1323 // 38400,57600,115200
1325 if (BaudRate
< 75) {
1327 } else if (BaudRate
< 110) {
1329 } else if (BaudRate
< 134) {
1331 } else if (BaudRate
< 150) {
1333 } else if (BaudRate
< 300) {
1335 } else if (BaudRate
< 600) {
1337 } else if (BaudRate
< 1200) {
1339 } else if (BaudRate
< 1800) {
1341 } else if (BaudRate
< 2000) {
1343 } else if (BaudRate
< 2400) {
1345 } else if (BaudRate
< 3600) {
1347 } else if (BaudRate
< 4800) {
1349 } else if (BaudRate
< 7200) {
1351 } else if (BaudRate
< 9600) {
1353 } else if (BaudRate
< 19200) {
1355 } else if (BaudRate
< 38400) {
1357 } else if (BaudRate
< 57600) {
1359 } else if (BaudRate
< 115200) {
1361 } else if (BaudRate
<= SERIAL_PORT_MAX_BAUD_RATE
) {
1365 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
1366 return EFI_INVALID_PARAMETER
;
1369 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
1370 return EFI_INVALID_PARAMETER
;
1373 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
1374 return EFI_INVALID_PARAMETER
;
1377 if ((DataBits
< 5) || (DataBits
> 8)) {
1378 return EFI_INVALID_PARAMETER
;
1381 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
1382 return EFI_INVALID_PARAMETER
;
1386 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1388 if ((DataBits
>= 6) && (DataBits
<= 8) && (StopBits
== OneFiveStopBits
)) {
1389 return EFI_INVALID_PARAMETER
;
1393 // Compute divisor use to program the baud rate using a round determination
1395 Divisor
= (UINT32
) DivU64x32Remainder (
1396 SERIAL_PORT_INPUT_CLOCK
,
1397 ((UINT32
) BaudRate
* 16),
1400 if (Remained
!= 0) {
1404 if ((Divisor
== 0) || ((Divisor
& 0xffff0000) != 0)) {
1405 return EFI_INVALID_PARAMETER
;
1408 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1411 // Compute the actual baud rate that the serial port will be programmed for.
1413 BaudRate
= SERIAL_PORT_INPUT_CLOCK
/ Divisor
/ 16;
1416 // Put serial port on Divisor Latch Mode
1418 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1420 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1423 // Write the divisor to the serial port
1425 WRITE_DLL (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) (Divisor
& 0xff));
1426 WRITE_DLM (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) ((Divisor
>> 8) & 0xff));
1429 // Put serial port back in normal mode and set remaining attributes.
1436 Lcr
.Bits
.EvenPar
= 0;
1437 Lcr
.Bits
.SticPar
= 0;
1442 Lcr
.Bits
.EvenPar
= 1;
1443 Lcr
.Bits
.SticPar
= 0;
1448 Lcr
.Bits
.EvenPar
= 0;
1449 Lcr
.Bits
.SticPar
= 0;
1454 Lcr
.Bits
.EvenPar
= 1;
1455 Lcr
.Bits
.SticPar
= 1;
1460 Lcr
.Bits
.EvenPar
= 0;
1461 Lcr
.Bits
.SticPar
= 1;
1473 case OneFiveStopBits
:
1484 Lcr
.Bits
.SerialDB
= (UINT8
) ((DataBits
- 5) & 0x03);
1485 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1488 // Set the Serial I/O mode
1490 This
->Mode
->BaudRate
= BaudRate
;
1491 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
1492 This
->Mode
->Timeout
= Timeout
;
1493 This
->Mode
->Parity
= Parity
;
1494 This
->Mode
->DataBits
= DataBits
;
1495 This
->Mode
->StopBits
= StopBits
;
1498 // See if Device Path Node has actually changed
1500 if (SerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
1501 SerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
1502 SerialDevice
->UartDevicePath
.Parity
== Parity
&&
1503 SerialDevice
->UartDevicePath
.StopBits
== StopBits
1505 gBS
->RestoreTPL (Tpl
);
1509 // Update the device path
1511 SerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
1512 SerialDevice
->UartDevicePath
.DataBits
= DataBits
;
1513 SerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1514 SerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1516 Status
= EFI_SUCCESS
;
1517 if (SerialDevice
->Handle
!= NULL
) {
1518 Uart
= (UART_DEVICE_PATH
*) (
1519 (UINTN
) SerialDevice
->DevicePath
1520 + GetDevicePathSize (SerialDevice
->ParentDevicePath
)
1521 - END_DEVICE_PATH_LENGTH
1523 CopyMem (Uart
, &SerialDevice
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
1524 Status
= gBS
->ReinstallProtocolInterface (
1525 SerialDevice
->Handle
,
1526 &gEfiDevicePathProtocolGuid
,
1527 SerialDevice
->DevicePath
,
1528 SerialDevice
->DevicePath
1532 gBS
->RestoreTPL (Tpl
);
1540 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1541 @param Control Control bits that can be settable
1543 @retval EFI_SUCCESS New Control bits were set successfully
1544 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
1549 IsaSerialSetControl (
1550 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1554 SERIAL_DEV
*SerialDevice
;
1555 SERIAL_PORT_MCR Mcr
;
1557 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1561 // The control bits that can be set are :
1562 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1563 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1564 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1565 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1566 // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW
1568 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1571 // first determine the parameter is invalid
1573 if ((Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1574 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1575 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) != 0) {
1576 return EFI_UNSUPPORTED
;
1579 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1581 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1585 SerialDevice
->SoftwareLoopbackEnable
= FALSE
;
1586 SerialDevice
->HardwareFlowControl
= FALSE
;
1588 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
1592 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
1596 if ((Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1600 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1601 SerialDevice
->HardwareFlowControl
= TRUE
;
1604 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1606 if ((Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1607 SerialDevice
->SoftwareLoopbackEnable
= TRUE
;
1610 Status
= EFI_SUCCESS
;
1611 if (SerialDevice
->Handle
!= NULL
) {
1612 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) (
1613 (UINTN
) SerialDevice
->DevicePath
1614 + GetDevicePathSize (SerialDevice
->ParentDevicePath
)
1615 - END_DEVICE_PATH_LENGTH
1616 + sizeof (UART_DEVICE_PATH
)
1618 if (IsUartFlowControlNode (FlowControl
) &&
1619 ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) ^ SerialDevice
->HardwareFlowControl
)) {
1621 // Flow Control setting is changed, need to reinstall device path protocol
1623 WriteUnaligned32 (&FlowControl
->FlowControlMap
, SerialDevice
->HardwareFlowControl
? UART_FLOW_CONTROL_HARDWARE
: 0);
1624 Status
= gBS
->ReinstallProtocolInterface (
1625 SerialDevice
->Handle
,
1626 &gEfiDevicePathProtocolGuid
,
1627 SerialDevice
->DevicePath
,
1628 SerialDevice
->DevicePath
1633 gBS
->RestoreTPL (Tpl
);
1641 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1642 @param Control Control signals of the serial device
1644 @retval EFI_SUCCESS Get Control signals successfully
1649 IsaSerialGetControl (
1650 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1654 SERIAL_DEV
*SerialDevice
;
1655 SERIAL_PORT_MSR Msr
;
1656 SERIAL_PORT_MCR Mcr
;
1659 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1661 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1666 // Read the Modem Status Register
1668 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1670 if (Msr
.Bits
.Cts
== 1) {
1671 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1674 if (Msr
.Bits
.Dsr
== 1) {
1675 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1678 if (Msr
.Bits
.Ri
== 1) {
1679 *Control
|= EFI_SERIAL_RING_INDICATE
;
1682 if (Msr
.Bits
.Dcd
== 1) {
1683 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1686 // Read the Modem Control Register
1688 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1690 if (Mcr
.Bits
.DtrC
== 1) {
1691 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1694 if (Mcr
.Bits
.Rts
== 1) {
1695 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1698 if (Mcr
.Bits
.Lme
== 1) {
1699 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1702 if (SerialDevice
->HardwareFlowControl
) {
1703 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1706 // See if the Transmit FIFO is empty
1708 IsaSerialReceiveTransmit (SerialDevice
);
1710 if (IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1711 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1714 // See if the Receive FIFO is empty.
1716 IsaSerialReceiveTransmit (SerialDevice
);
1718 if (IsaSerialFifoEmpty (&SerialDevice
->Receive
)) {
1719 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1722 if (SerialDevice
->SoftwareLoopbackEnable
) {
1723 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1726 gBS
->RestoreTPL (Tpl
);
1732 Write the specified number of bytes to serial device.
1734 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1735 @param BufferSize On input the size of Buffer, on output the amount of
1736 data actually written
1737 @param Buffer The buffer of data to write
1739 @retval EFI_SUCCESS The data were written successfully
1740 @retval EFI_DEVICE_ERROR The device reported an error
1741 @retval EFI_TIMEOUT The write operation was stopped due to timeout
1747 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1748 IN OUT UINTN
*BufferSize
,
1752 SERIAL_DEV
*SerialDevice
;
1759 UINTN BitsPerCharacter
;
1761 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1765 if (*BufferSize
== 0) {
1769 if (Buffer
== NULL
) {
1770 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1772 EFI_P_EC_OUTPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1773 SerialDevice
->DevicePath
1776 return EFI_DEVICE_ERROR
;
1779 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1781 CharBuffer
= (UINT8
*) Buffer
;
1784 // Compute the number of bits in a single character. This is a start bit,
1785 // followed by the number of data bits, followed by the number of stop bits.
1786 // The number of stop bits is specified by an enumeration that includes
1787 // support for 1.5 stop bits. Treat 1.5 stop bits as 2 stop bits.
1791 This
->Mode
->DataBits
+
1792 ((This
->Mode
->StopBits
== TwoStopBits
) ? 2 : This
->Mode
->StopBits
);
1795 // Compute the timeout in microseconds to wait for a single byte to be
1796 // transmitted. The Mode structure contans a Timeout field that is the
1797 // maximum time to transmit or receive a character. However, many UARTs
1798 // have a FIFO for transmits, so the time required to add one new character
1799 // to the transmit FIFO may be the time required to flush a full FIFO. If
1800 // the Timeout in the Mode structure is smaller than the time required to
1801 // flush a full FIFO at the current baud rate, then use a timeout value that
1802 // is required to flush a full transmit FIFO.
1805 This
->Mode
->Timeout
,
1806 (UINTN
)DivU64x64Remainder (
1807 BitsPerCharacter
* (SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
+ 1) * 1000000,
1808 This
->Mode
->BaudRate
,
1813 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1814 IsaSerialFifoAdd (&SerialDevice
->Transmit
, CharBuffer
[Index
]);
1816 while (IsaSerialReceiveTransmit (SerialDevice
) != EFI_SUCCESS
|| !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1818 // Unsuccessful write so check if timeout has expired, if not,
1819 // stall for a bit, increment time elapsed, and try again
1821 if (Elapsed
>= Timeout
) {
1822 *BufferSize
= ActualWrite
;
1823 gBS
->RestoreTPL (Tpl
);
1827 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1829 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1834 // Successful write so reset timeout
1839 gBS
->RestoreTPL (Tpl
);
1845 Read the specified number of bytes from serial device.
1847 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1848 @param BufferSize On input the size of Buffer, on output the amount of
1849 data returned in buffer
1850 @param Buffer The buffer to return the data into
1852 @retval EFI_SUCCESS The data were read successfully
1853 @retval EFI_DEVICE_ERROR The device reported an error
1854 @retval EFI_TIMEOUT The read operation was stopped due to timeout
1860 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1861 IN OUT UINTN
*BufferSize
,
1865 SERIAL_DEV
*SerialDevice
;
1872 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1875 if (*BufferSize
== 0) {
1879 if (Buffer
== NULL
) {
1880 return EFI_DEVICE_ERROR
;
1883 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1885 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1887 if (EFI_ERROR (Status
)) {
1890 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1892 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1893 SerialDevice
->DevicePath
1896 gBS
->RestoreTPL (Tpl
);
1898 return EFI_DEVICE_ERROR
;
1901 CharBuffer
= (UINT8
*) Buffer
;
1902 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1903 while (IsaSerialFifoRemove (&SerialDevice
->Receive
, &(CharBuffer
[Index
])) != EFI_SUCCESS
) {
1905 // Unsuccessful read so check if timeout has expired, if not,
1906 // stall for a bit, increment time elapsed, and try again
1907 // Need this time out to get conspliter to work.
1909 if (Elapsed
>= This
->Mode
->Timeout
) {
1910 *BufferSize
= Index
;
1911 gBS
->RestoreTPL (Tpl
);
1915 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1916 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1918 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1919 if (Status
== EFI_DEVICE_ERROR
) {
1920 *BufferSize
= Index
;
1921 gBS
->RestoreTPL (Tpl
);
1922 return EFI_DEVICE_ERROR
;
1926 // Successful read so reset timeout
1931 IsaSerialReceiveTransmit (SerialDevice
);
1933 gBS
->RestoreTPL (Tpl
);
1939 Use scratchpad register to test if this serial port is present.
1941 @param SerialDevice Pointer to serial device structure
1943 @return if this serial port is present
1946 IsaSerialPortPresent (
1947 IN SERIAL_DEV
*SerialDevice
1959 Temp
= READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1960 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0xAA);
1962 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0xAA) {
1966 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0x55);
1968 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0x55) {
1974 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Temp
);
1979 Use IsaIo protocol to read serial port.
1981 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1982 @param BaseAddress Serial port register group base address
1983 @param Offset Offset in register group
1985 @return Data read from serial port
1990 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1991 IN UINT16 BaseAddress
,
1998 // Use IsaIo to access IO
2003 BaseAddress
+ Offset
,
2011 Use IsaIo protocol to write serial port.
2013 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
2014 @param BaseAddress Serial port register group base address
2015 @param Offset Offset in register group
2016 @param Data data which is to be written to some serial port register
2020 IsaSerialWritePort (
2021 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
2022 IN UINT16 BaseAddress
,
2028 // Use IsaIo to access IO
2033 BaseAddress
+ Offset
,