2 Serial driver for standard UARTS on an ISA bus.
4 Copyright (c) 2006 - 2010, Intel Corporation<BR>
5 All rights reserved. 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
;
200 // Check RemainingDevicePath validation
202 if (RemainingDevicePath
!= NULL
) {
204 // Check if RemainingDevicePath is the End of Device Path Node,
205 // if yes, go on checking other conditions
207 if (!IsDevicePathEnd (RemainingDevicePath
)) {
209 // If RemainingDevicePath isn't the End of Device Path Node,
210 // check its validation
212 Status
= EFI_UNSUPPORTED
;
214 UartNode
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
215 if (UartNode
->Header
.Type
!= MESSAGING_DEVICE_PATH
||
216 UartNode
->Header
.SubType
!= MSG_UART_DP
||
217 sizeof (UART_DEVICE_PATH
) != DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL
*) UartNode
)
222 if (UartNode
->BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) {
226 if (UartNode
->Parity
< NoParity
|| UartNode
->Parity
> SpaceParity
) {
230 if (UartNode
->DataBits
< 5 || UartNode
->DataBits
> 8) {
234 if (UartNode
->StopBits
< OneStopBit
|| UartNode
->StopBits
> TwoStopBits
) {
238 if ((UartNode
->DataBits
== 5) && (UartNode
->StopBits
== TwoStopBits
)) {
242 if ((UartNode
->DataBits
>= 6) && (UartNode
->DataBits
<= 8) && (UartNode
->StopBits
== OneFiveStopBits
)) {
246 FlowControlNode
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (UartNode
);
247 if (IsUartFlowControlNode (FlowControlNode
)) {
249 // If the second node is Flow Control Node,
250 // return error when it request other than hardware flow control.
252 if ((ReadUnaligned32 (&FlowControlNode
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
260 // Open the IO Abstraction(s) needed to perform the supported test
262 Status
= gBS
->OpenProtocol (
264 &gEfiIsaIoProtocolGuid
,
266 This
->DriverBindingHandle
,
268 EFI_OPEN_PROTOCOL_BY_DRIVER
270 if (Status
== EFI_ALREADY_STARTED
) {
271 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
273 // If RemainingDevicePath is NULL or is the End of Device Path Node
278 // When the driver has produced device path with flow control node but RemainingDevicePath only contains UART node,
279 // return unsupported, and vice versa.
281 Status
= gBS
->OpenProtocolInformation (
283 &gEfiIsaIoProtocolGuid
,
287 if (EFI_ERROR (Status
)) {
291 for (Index
= 0; Index
< EntryCount
; Index
++) {
292 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
293 Status
= gBS
->OpenProtocol (
294 OpenInfoBuffer
[Index
].ControllerHandle
,
295 &gEfiDevicePathProtocolGuid
,
296 (VOID
**) &DevicePath
,
297 This
->DriverBindingHandle
,
299 EFI_OPEN_PROTOCOL_GET_PROTOCOL
301 if (!EFI_ERROR (Status
) &&
302 (ContainsFlowControl (RemainingDevicePath
) ^ ContainsFlowControl (DevicePath
))) {
303 Status
= EFI_UNSUPPORTED
;
308 FreePool (OpenInfoBuffer
);
312 if (EFI_ERROR (Status
)) {
317 // Close the I/O Abstraction(s) used to perform the supported test
321 &gEfiIsaIoProtocolGuid
,
322 This
->DriverBindingHandle
,
327 // Open the EFI Device Path protocol needed to perform the supported test
329 Status
= gBS
->OpenProtocol (
331 &gEfiDevicePathProtocolGuid
,
332 (VOID
**) &ParentDevicePath
,
333 This
->DriverBindingHandle
,
335 EFI_OPEN_PROTOCOL_BY_DRIVER
337 if (Status
== EFI_ALREADY_STARTED
) {
341 if (EFI_ERROR (Status
)) {
345 // Use the ISA I/O Protocol to see if Controller is standard ISA UART that
346 // can be managed by this driver.
348 Status
= EFI_SUCCESS
;
349 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x501)) {
350 Status
= EFI_UNSUPPORTED
;
356 // Close protocol, don't use device path protocol in the Support() function
360 &gEfiDevicePathProtocolGuid
,
361 This
->DriverBindingHandle
,
369 Start to management the controller passed in
371 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
372 @param Controller The handle of the controller to test.
373 @param RemainingDevicePath A pointer to the remaining portion of a device path.
375 @return EFI_SUCCESS Driver is started successfully
380 SerialControllerDriverStart (
381 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
382 IN EFI_HANDLE Controller
,
383 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
388 EFI_ISA_IO_PROTOCOL
*IsaIo
;
389 SERIAL_DEV
*SerialDevice
;
391 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
392 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
394 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
395 UART_DEVICE_PATH
*Uart
;
396 UINT32 FlowControlMap
;
397 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
398 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
403 // Get the Parent Device Path
405 Status
= gBS
->OpenProtocol (
407 &gEfiDevicePathProtocolGuid
,
408 (VOID
**) &ParentDevicePath
,
409 This
->DriverBindingHandle
,
411 EFI_OPEN_PROTOCOL_BY_DRIVER
413 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
417 // Report status code enable the serial
419 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
421 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
426 // Grab the IO abstraction we need to get any work done
428 Status
= gBS
->OpenProtocol (
430 &gEfiIsaIoProtocolGuid
,
432 This
->DriverBindingHandle
,
434 EFI_OPEN_PROTOCOL_BY_DRIVER
436 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
440 if (Status
== EFI_ALREADY_STARTED
) {
442 if (RemainingDevicePath
== NULL
|| IsDevicePathEnd (RemainingDevicePath
)) {
444 // If RemainingDevicePath is NULL or is the End of Device Path Node
450 // Make sure a child handle does not already exist. This driver can only
451 // produce one child per serial port.
453 Status
= gBS
->OpenProtocolInformation (
455 &gEfiIsaIoProtocolGuid
,
459 if (EFI_ERROR (Status
)) {
463 Status
= EFI_ALREADY_STARTED
;
464 for (Index
= 0; Index
< EntryCount
; Index
++) {
465 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
466 Status
= gBS
->OpenProtocol (
467 OpenInfoBuffer
[Index
].ControllerHandle
,
468 &gEfiSerialIoProtocolGuid
,
470 This
->DriverBindingHandle
,
472 EFI_OPEN_PROTOCOL_GET_PROTOCOL
474 if (!EFI_ERROR (Status
)) {
475 Uart
= (UART_DEVICE_PATH
*) RemainingDevicePath
;
476 Status
= SerialIo
->SetAttributes (
479 SerialIo
->Mode
->ReceiveFifoDepth
,
480 SerialIo
->Mode
->Timeout
,
481 (EFI_PARITY_TYPE
) Uart
->Parity
,
483 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
486 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
487 if (!EFI_ERROR (Status
) && IsUartFlowControlNode (FlowControl
)) {
488 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
489 if (!EFI_ERROR (Status
)) {
490 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
491 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
493 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
496 // Clear the bits that are not allowed to pass to SetControl
498 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
499 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
500 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
501 Status
= SerialIo
->SetControl (SerialIo
, Control
);
509 FreePool (OpenInfoBuffer
);
513 if (RemainingDevicePath
!= NULL
) {
514 if (IsDevicePathEnd (RemainingDevicePath
)) {
516 // If RemainingDevicePath is the End of Device Path Node,
517 // skip enumerate any device and return EFI_SUCESSS
524 // Initialize the serial device instance
526 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTempate
);
527 if (SerialDevice
== NULL
) {
528 Status
= EFI_OUT_OF_RESOURCES
;
532 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
533 SerialDevice
->IsaIo
= IsaIo
;
534 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
539 // Check if RemainingDevicePath is NULL,
540 // if yes, use the values from the gSerialDevTempate as no remaining device path was
543 if (RemainingDevicePath
!= NULL
) {
545 // If RemainingDevicePath isn't NULL,
546 // match the configuration of the RemainingDevicePath. IsHandleSupported()
547 // already checked to make sure the RemainingDevicePath contains settings
548 // that we can support.
550 CopyMem (&SerialDevice
->UartDevicePath
, RemainingDevicePath
, sizeof (UART_DEVICE_PATH
));
551 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (RemainingDevicePath
);
552 if (IsUartFlowControlNode (FlowControl
)) {
553 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
559 AddName (SerialDevice
, IsaIo
);
561 for (Index
= 0; SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
562 if (SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
563 SerialDevice
->BaseAddress
= (UINT16
) SerialDevice
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
567 SerialDevice
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
570 // Report status code the serial present
572 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
574 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
578 if (!IsaSerialPortPresent (SerialDevice
)) {
579 Status
= EFI_DEVICE_ERROR
;
580 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
582 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
589 // Build the device path by appending the UART node to the ParentDevicePath.
590 // The Uart setings are zero here, since SetAttribute() will update them to match
591 // the default setings.
593 SerialDevice
->DevicePath
= AppendDevicePathNode (
595 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
598 // Only produce the Flow Control node when remaining device path has it
600 if (FlowControl
!= NULL
) {
601 TempDevicePath
= SerialDevice
->DevicePath
;
602 if (TempDevicePath
!= NULL
) {
603 SerialDevice
->DevicePath
= AppendDevicePathNode (
605 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
607 FreePool (TempDevicePath
);
610 if (SerialDevice
->DevicePath
== NULL
) {
611 Status
= EFI_OUT_OF_RESOURCES
;
616 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
618 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
619 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
620 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
621 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
624 // Issue a reset to initialize the COM port
626 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
627 if (EFI_ERROR (Status
)) {
628 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
630 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
636 // Install protocol interfaces for the serial device.
638 Status
= gBS
->InstallMultipleProtocolInterfaces (
639 &SerialDevice
->Handle
,
640 &gEfiDevicePathProtocolGuid
,
641 SerialDevice
->DevicePath
,
642 &gEfiSerialIoProtocolGuid
,
643 &SerialDevice
->SerialIo
,
646 if (EFI_ERROR (Status
)) {
650 // Open For Child Device
652 Status
= gBS
->OpenProtocol (
654 &gEfiIsaIoProtocolGuid
,
656 This
->DriverBindingHandle
,
657 SerialDevice
->Handle
,
658 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
662 if (EFI_ERROR (Status
)) {
665 &gEfiDevicePathProtocolGuid
,
666 This
->DriverBindingHandle
,
671 &gEfiIsaIoProtocolGuid
,
672 This
->DriverBindingHandle
,
675 if (SerialDevice
!= NULL
) {
676 if (SerialDevice
->DevicePath
!= NULL
) {
677 gBS
->FreePool (SerialDevice
->DevicePath
);
680 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
681 gBS
->FreePool (SerialDevice
);
689 Disconnect this driver with the controller, uninstall related protocol instance
691 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
692 @param Controller The handle of the controller to test.
693 @param NumberOfChildren Number of child device.
694 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
696 @retval EFI_SUCCESS Operation successfully
697 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
702 SerialControllerDriverStop (
703 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
704 IN EFI_HANDLE Controller
,
705 IN UINTN NumberOfChildren
,
706 IN EFI_HANDLE
*ChildHandleBuffer
712 BOOLEAN AllChildrenStopped
;
713 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
714 SERIAL_DEV
*SerialDevice
;
715 EFI_ISA_IO_PROTOCOL
*IsaIo
;
716 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
718 Status
= gBS
->HandleProtocol (
720 &gEfiDevicePathProtocolGuid
,
721 (VOID
**) &DevicePath
725 // Report the status code disable the serial
727 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
729 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
734 // Complete all outstanding transactions to Controller.
735 // Don't allow any new transaction to Controller to be started.
737 if (NumberOfChildren
== 0) {
739 // Close the bus driver
741 Status
= gBS
->CloseProtocol (
743 &gEfiIsaIoProtocolGuid
,
744 This
->DriverBindingHandle
,
748 Status
= gBS
->CloseProtocol (
750 &gEfiDevicePathProtocolGuid
,
751 This
->DriverBindingHandle
,
757 AllChildrenStopped
= TRUE
;
759 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
761 Status
= gBS
->OpenProtocol (
762 ChildHandleBuffer
[Index
],
763 &gEfiSerialIoProtocolGuid
,
765 This
->DriverBindingHandle
,
767 EFI_OPEN_PROTOCOL_GET_PROTOCOL
769 if (!EFI_ERROR (Status
)) {
771 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
773 Status
= gBS
->CloseProtocol (
775 &gEfiIsaIoProtocolGuid
,
776 This
->DriverBindingHandle
,
777 ChildHandleBuffer
[Index
]
780 Status
= gBS
->UninstallMultipleProtocolInterfaces (
781 ChildHandleBuffer
[Index
],
782 &gEfiDevicePathProtocolGuid
,
783 SerialDevice
->DevicePath
,
784 &gEfiSerialIoProtocolGuid
,
785 &SerialDevice
->SerialIo
,
788 if (EFI_ERROR (Status
)) {
791 &gEfiIsaIoProtocolGuid
,
793 This
->DriverBindingHandle
,
794 ChildHandleBuffer
[Index
],
795 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
798 if (SerialDevice
->DevicePath
!= NULL
) {
799 gBS
->FreePool (SerialDevice
->DevicePath
);
802 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
803 gBS
->FreePool (SerialDevice
);
807 if (EFI_ERROR (Status
)) {
808 AllChildrenStopped
= FALSE
;
812 if (!AllChildrenStopped
) {
813 return EFI_DEVICE_ERROR
;
820 Detect whether specific FIFO is full or not.
822 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
824 @return whether specific FIFO is full or not
829 IN SERIAL_DEV_FIFO
*Fifo
833 if (Fifo
->Surplus
== 0) {
841 Detect whether specific FIFO is empty or not.
843 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
845 @return whether specific FIFO is empty or not
850 IN SERIAL_DEV_FIFO
*Fifo
854 if (Fifo
->Surplus
== SERIAL_MAX_BUFFER_SIZE
) {
862 Add data to specific FIFO.
864 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
865 @param Data the data added to FIFO
867 @retval EFI_SUCCESS Add data to specific FIFO successfully
868 @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full
873 IN SERIAL_DEV_FIFO
*Fifo
,
879 // if FIFO full can not add data
881 if (IsaSerialFifoFull (Fifo
)) {
882 return EFI_OUT_OF_RESOURCES
;
885 // FIFO is not full can add data
887 Fifo
->Data
[Fifo
->Last
] = Data
;
890 if (Fifo
->Last
== SERIAL_MAX_BUFFER_SIZE
) {
898 Remove data from specific FIFO.
900 @param Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
901 @param Data the data removed from FIFO
903 @retval EFI_SUCCESS Remove data from specific FIFO successfully
904 @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty
908 IsaSerialFifoRemove (
909 IN SERIAL_DEV_FIFO
*Fifo
,
915 // if FIFO is empty, no data can remove
917 if (IsaSerialFifoEmpty (Fifo
)) {
918 return EFI_OUT_OF_RESOURCES
;
921 // FIFO is not empty, can remove data
923 *Data
= Fifo
->Data
[Fifo
->First
];
926 if (Fifo
->First
== SERIAL_MAX_BUFFER_SIZE
) {
934 Reads and writes all avaliable data.
936 @param SerialDevice The device to flush
938 @retval EFI_SUCCESS Data was read/written successfully.
939 @retval EFI_OUT_OF_RESOURCE Failed because software receive FIFO is full. Note, when
940 this happens, pending writes are not done.
944 IsaSerialReceiveTransmit (
945 IN SERIAL_DEV
*SerialDevice
951 BOOLEAN ReceiveFifoFull
;
959 // Begin the read or write
961 if (SerialDevice
->SoftwareLoopbackEnable
) {
963 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
964 if (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
965 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
966 if (ReceiveFifoFull
) {
967 return EFI_OUT_OF_RESOURCES
;
970 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
972 } while (!IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
974 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
976 // For full handshake flow control, tell the peer to send data
977 // if receive buffer is available.
979 if (SerialDevice
->HardwareFlowControl
&&
980 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)&&
983 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
985 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
988 Lsr
.Data
= READ_LSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
991 // Flush incomming data to prevent a an overrun during a long write
993 if ((Lsr
.Bits
.Dr
== 1) && !ReceiveFifoFull
) {
994 ReceiveFifoFull
= IsaSerialFifoFull (&SerialDevice
->Receive
);
995 if (!ReceiveFifoFull
) {
996 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Oe
== 1 || Lsr
.Bits
.Pe
== 1 || Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
997 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
999 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1000 SerialDevice
->DevicePath
1002 if (Lsr
.Bits
.FIFOe
== 1 || Lsr
.Bits
.Pe
== 1|| Lsr
.Bits
.Fe
== 1 || Lsr
.Bits
.Bi
== 1) {
1003 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1008 Data
= READ_RBR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1010 IsaSerialFifoAdd (&SerialDevice
->Receive
, Data
);
1013 // For full handshake flow control, if receive buffer full
1014 // tell the peer to stop sending data.
1016 if (SerialDevice
->HardwareFlowControl
&&
1017 !FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
) &&
1018 IsaSerialFifoFull (&SerialDevice
->Receive
)
1020 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1022 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1028 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1030 EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER
| EFI_PERIPHERAL_SERIAL_PORT
,
1031 SerialDevice
->DevicePath
1038 if (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1040 // Make sure the transmit data will not be missed
1042 if (SerialDevice
->HardwareFlowControl
) {
1044 // For half handshake flow control assert RTS before sending.
1046 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
1047 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1049 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1055 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1056 while ((Msr
.Bits
.Dcd
== 1) && ((Msr
.Bits
.Cts
== 0) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
1057 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1063 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1066 if ((Msr
.Bits
.Dcd
== 0) || ((Msr
.Bits
.Cts
== 1) ^ FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
))) {
1067 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
1068 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
1072 // For half handshake flow control, tell DCE we are done.
1074 if (FeaturePcdGet(PcdIsaBusSerialUseHalfHandshake
)) {
1075 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1077 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1080 IsaSerialFifoRemove (&SerialDevice
->Transmit
, &Data
);
1081 WRITE_THR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Data
);
1084 } while (Lsr
.Bits
.Thre
== 1 && !IsaSerialFifoEmpty (&SerialDevice
->Transmit
));
1091 // Interface Functions
1094 Reset serial device.
1096 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1098 @retval EFI_SUCCESS Reset successfully
1099 @retval EFI_DEVICE_ERROR Failed to reset
1105 IN EFI_SERIAL_IO_PROTOCOL
*This
1109 SERIAL_DEV
*SerialDevice
;
1110 SERIAL_PORT_LCR Lcr
;
1111 SERIAL_PORT_IER Ier
;
1112 SERIAL_PORT_MCR Mcr
;
1113 SERIAL_PORT_FCR Fcr
;
1117 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1120 // Report the status code reset the serial
1122 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1124 EFI_P_PC_RESET
| EFI_PERIPHERAL_SERIAL_PORT
,
1125 SerialDevice
->DevicePath
1128 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1131 // Make sure DLAB is 0.
1133 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1135 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1138 // Turn off all interrupts
1140 Ier
.Data
= READ_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1145 WRITE_IER (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Ier
.Data
);
1148 // Disable the FIFO.
1150 Fcr
.Bits
.TrFIFOE
= 0;
1151 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1154 // Turn off loopback and disable device interrupt.
1156 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1160 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1163 // Clear the scratch pad register
1165 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0);
1168 // Go set the current attributes
1170 Status
= This
->SetAttributes (
1172 This
->Mode
->BaudRate
,
1173 This
->Mode
->ReceiveFifoDepth
,
1174 This
->Mode
->Timeout
,
1175 (EFI_PARITY_TYPE
) This
->Mode
->Parity
,
1176 (UINT8
) This
->Mode
->DataBits
,
1177 (EFI_STOP_BITS_TYPE
) This
->Mode
->StopBits
1180 if (EFI_ERROR (Status
)) {
1181 gBS
->RestoreTPL (Tpl
);
1182 return EFI_DEVICE_ERROR
;
1185 // Go set the current control bits
1188 if (SerialDevice
->HardwareFlowControl
) {
1189 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1191 if (SerialDevice
->SoftwareLoopbackEnable
) {
1192 Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1194 Status
= This
->SetControl (
1199 if (EFI_ERROR (Status
)) {
1200 gBS
->RestoreTPL (Tpl
);
1201 return EFI_DEVICE_ERROR
;
1204 // for 16550A enable FIFO, 16550 disable FIFO
1206 Fcr
.Bits
.TrFIFOE
= 1;
1207 Fcr
.Bits
.ResetRF
= 1;
1208 Fcr
.Bits
.ResetTF
= 1;
1209 WRITE_FCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Fcr
.Data
);
1212 // Reset the software FIFO
1214 SerialDevice
->Receive
.First
= 0;
1215 SerialDevice
->Receive
.Last
= 0;
1216 SerialDevice
->Receive
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1217 SerialDevice
->Transmit
.First
= 0;
1218 SerialDevice
->Transmit
.Last
= 0;
1219 SerialDevice
->Transmit
.Surplus
= SERIAL_MAX_BUFFER_SIZE
;
1221 gBS
->RestoreTPL (Tpl
);
1224 // Device reset is complete
1230 Set new attributes to a serial device.
1232 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1233 @param BaudRate The baudrate of the serial device
1234 @param ReceiveFifoDepth The depth of receive FIFO buffer
1235 @param Timeout The request timeout for a single char
1236 @param Parity The type of parity used in serial device
1237 @param DataBits Number of databits used in serial device
1238 @param StopBits Number of stopbits used in serial device
1240 @retval EFI_SUCCESS The new attributes were set
1241 @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
1242 @retval EFI_UNSUPPORTED Data Bits can not set to 5 or 6
1243 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
1248 IsaSerialSetAttributes (
1249 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1251 IN UINT32 ReceiveFifoDepth
,
1253 IN EFI_PARITY_TYPE Parity
,
1255 IN EFI_STOP_BITS_TYPE StopBits
1259 SERIAL_DEV
*SerialDevice
;
1262 SERIAL_PORT_LCR Lcr
;
1263 UART_DEVICE_PATH
*Uart
;
1266 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1269 // Check for default settings and fill in actual values.
1271 if (BaudRate
== 0) {
1272 BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
1275 if (ReceiveFifoDepth
== 0) {
1276 ReceiveFifoDepth
= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH
;
1280 Timeout
= SERIAL_PORT_DEFAULT_TIMEOUT
;
1283 if (Parity
== DefaultParity
) {
1284 Parity
= (EFI_PARITY_TYPE
)PcdGet8 (PcdUartDefaultParity
);
1287 if (DataBits
== 0) {
1288 DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
1291 if (StopBits
== DefaultStopBits
) {
1292 StopBits
= (EFI_STOP_BITS_TYPE
) PcdGet8 (PcdUartDefaultStopBits
);
1295 // 5 and 6 data bits can not be verified on a 16550A UART
1296 // Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
1298 if ((DataBits
== 5) || (DataBits
== 6)) {
1299 return EFI_INVALID_PARAMETER
;
1302 // Make sure all parameters are valid
1304 if ((BaudRate
> SERIAL_PORT_MAX_BAUD_RATE
) || (BaudRate
< SERIAL_PORT_MIN_BAUD_RATE
)) {
1305 return EFI_INVALID_PARAMETER
;
1308 // 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
1309 // 38400,57600,115200
1311 if (BaudRate
< 75) {
1313 } else if (BaudRate
< 110) {
1315 } else if (BaudRate
< 134) {
1317 } else if (BaudRate
< 150) {
1319 } else if (BaudRate
< 300) {
1321 } else if (BaudRate
< 600) {
1323 } else if (BaudRate
< 1200) {
1325 } else if (BaudRate
< 1800) {
1327 } else if (BaudRate
< 2000) {
1329 } else if (BaudRate
< 2400) {
1331 } else if (BaudRate
< 3600) {
1333 } else if (BaudRate
< 4800) {
1335 } else if (BaudRate
< 7200) {
1337 } else if (BaudRate
< 9600) {
1339 } else if (BaudRate
< 19200) {
1341 } else if (BaudRate
< 38400) {
1343 } else if (BaudRate
< 57600) {
1345 } else if (BaudRate
< 115200) {
1347 } else if (BaudRate
<= SERIAL_PORT_MAX_BAUD_RATE
) {
1351 if ((ReceiveFifoDepth
< 1) || (ReceiveFifoDepth
> SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH
)) {
1352 return EFI_INVALID_PARAMETER
;
1355 if ((Timeout
< SERIAL_PORT_MIN_TIMEOUT
) || (Timeout
> SERIAL_PORT_MAX_TIMEOUT
)) {
1356 return EFI_INVALID_PARAMETER
;
1359 if ((Parity
< NoParity
) || (Parity
> SpaceParity
)) {
1360 return EFI_INVALID_PARAMETER
;
1363 if ((DataBits
< 5) || (DataBits
> 8)) {
1364 return EFI_INVALID_PARAMETER
;
1367 if ((StopBits
< OneStopBit
) || (StopBits
> TwoStopBits
)) {
1368 return EFI_INVALID_PARAMETER
;
1372 // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
1374 if ((DataBits
>= 6) && (DataBits
<= 8) && (StopBits
== OneFiveStopBits
)) {
1375 return EFI_INVALID_PARAMETER
;
1379 // Compute divisor use to program the baud rate using a round determination
1381 Divisor
= (UINT32
) DivU64x32Remainder (
1382 SERIAL_PORT_INPUT_CLOCK
,
1383 ((UINT32
) BaudRate
* 16),
1386 if (Remained
!= 0) {
1390 if ((Divisor
== 0) || ((Divisor
& 0xffff0000) != 0)) {
1391 return EFI_INVALID_PARAMETER
;
1394 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1397 // Compute the actual baud rate that the serial port will be programmed for.
1399 BaudRate
= SERIAL_PORT_INPUT_CLOCK
/ Divisor
/ 16;
1402 // Put serial port on Divisor Latch Mode
1404 Lcr
.Data
= READ_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1406 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1409 // Write the divisor to the serial port
1411 WRITE_DLL (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) (Divisor
& 0xff));
1412 WRITE_DLM (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, (UINT8
) ((Divisor
>> 8) & 0xff));
1415 // Put serial port back in normal mode and set remaining attributes.
1422 Lcr
.Bits
.EvenPar
= 0;
1423 Lcr
.Bits
.SticPar
= 0;
1428 Lcr
.Bits
.EvenPar
= 1;
1429 Lcr
.Bits
.SticPar
= 0;
1434 Lcr
.Bits
.EvenPar
= 0;
1435 Lcr
.Bits
.SticPar
= 0;
1440 Lcr
.Bits
.EvenPar
= 1;
1441 Lcr
.Bits
.SticPar
= 1;
1446 Lcr
.Bits
.EvenPar
= 0;
1447 Lcr
.Bits
.SticPar
= 1;
1459 case OneFiveStopBits
:
1470 Lcr
.Bits
.SerialDB
= (UINT8
) ((DataBits
- 5) & 0x03);
1471 WRITE_LCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Lcr
.Data
);
1474 // Set the Serial I/O mode
1476 This
->Mode
->BaudRate
= BaudRate
;
1477 This
->Mode
->ReceiveFifoDepth
= ReceiveFifoDepth
;
1478 This
->Mode
->Timeout
= Timeout
;
1479 This
->Mode
->Parity
= Parity
;
1480 This
->Mode
->DataBits
= DataBits
;
1481 This
->Mode
->StopBits
= StopBits
;
1484 // See if Device Path Node has actually changed
1486 if (SerialDevice
->UartDevicePath
.BaudRate
== BaudRate
&&
1487 SerialDevice
->UartDevicePath
.DataBits
== DataBits
&&
1488 SerialDevice
->UartDevicePath
.Parity
== Parity
&&
1489 SerialDevice
->UartDevicePath
.StopBits
== StopBits
1491 gBS
->RestoreTPL (Tpl
);
1495 // Update the device path
1497 SerialDevice
->UartDevicePath
.BaudRate
= BaudRate
;
1498 SerialDevice
->UartDevicePath
.DataBits
= DataBits
;
1499 SerialDevice
->UartDevicePath
.Parity
= (UINT8
) Parity
;
1500 SerialDevice
->UartDevicePath
.StopBits
= (UINT8
) StopBits
;
1502 Status
= EFI_SUCCESS
;
1503 if (SerialDevice
->Handle
!= NULL
) {
1504 Uart
= (UART_DEVICE_PATH
*) (
1505 (UINTN
) SerialDevice
->DevicePath
1506 + GetDevicePathSize (SerialDevice
->ParentDevicePath
)
1507 - END_DEVICE_PATH_LENGTH
1509 CopyMem (Uart
, &SerialDevice
->UartDevicePath
, sizeof (UART_DEVICE_PATH
));
1510 Status
= gBS
->ReinstallProtocolInterface (
1511 SerialDevice
->Handle
,
1512 &gEfiDevicePathProtocolGuid
,
1513 SerialDevice
->DevicePath
,
1514 SerialDevice
->DevicePath
1518 gBS
->RestoreTPL (Tpl
);
1526 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1527 @param Control Control bits that can be settable
1529 @retval EFI_SUCCESS New Control bits were set successfully
1530 @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
1535 IsaSerialSetControl (
1536 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1540 SERIAL_DEV
*SerialDevice
;
1541 SERIAL_PORT_MCR Mcr
;
1543 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
1547 // The control bits that can be set are :
1548 // EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
1549 // EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
1550 // EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
1551 // EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
1552 // EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE: 0x4000 // RW
1554 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1557 // first determine the parameter is invalid
1559 if (Control
& (~(EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
1560 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
1561 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
))) {
1562 return EFI_UNSUPPORTED
;
1565 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1567 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1571 SerialDevice
->SoftwareLoopbackEnable
= FALSE
;
1572 SerialDevice
->HardwareFlowControl
= FALSE
;
1574 if ((Control
& EFI_SERIAL_DATA_TERMINAL_READY
) == EFI_SERIAL_DATA_TERMINAL_READY
) {
1578 if ((Control
& EFI_SERIAL_REQUEST_TO_SEND
) == EFI_SERIAL_REQUEST_TO_SEND
) {
1582 if ((Control
& EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
) {
1586 if ((Control
& EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) == EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
) {
1587 SerialDevice
->HardwareFlowControl
= TRUE
;
1590 WRITE_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Mcr
.Data
);
1592 if ((Control
& EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) == EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
) {
1593 SerialDevice
->SoftwareLoopbackEnable
= TRUE
;
1596 Status
= EFI_SUCCESS
;
1597 if (SerialDevice
->Handle
!= NULL
) {
1598 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) (
1599 (UINTN
) SerialDevice
->DevicePath
1600 + GetDevicePathSize (SerialDevice
->ParentDevicePath
)
1601 - END_DEVICE_PATH_LENGTH
1602 + sizeof (UART_DEVICE_PATH
)
1604 if (IsUartFlowControlNode (FlowControl
) &&
1605 ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) ^ SerialDevice
->HardwareFlowControl
)) {
1607 // Flow Control setting is changed, need to reinstall device path protocol
1609 WriteUnaligned32 (&FlowControl
->FlowControlMap
, SerialDevice
->HardwareFlowControl
? UART_FLOW_CONTROL_HARDWARE
: 0);
1610 Status
= gBS
->ReinstallProtocolInterface (
1611 SerialDevice
->Handle
,
1612 &gEfiDevicePathProtocolGuid
,
1613 SerialDevice
->DevicePath
,
1614 SerialDevice
->DevicePath
1619 gBS
->RestoreTPL (Tpl
);
1627 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1628 @param Control Control signals of the serial device
1630 @retval EFI_SUCCESS Get Control signals successfully
1635 IsaSerialGetControl (
1636 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1640 SERIAL_DEV
*SerialDevice
;
1641 SERIAL_PORT_MSR Msr
;
1642 SERIAL_PORT_MCR Mcr
;
1645 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1647 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1652 // Read the Modem Status Register
1654 Msr
.Data
= READ_MSR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1656 if (Msr
.Bits
.Cts
== 1) {
1657 *Control
|= EFI_SERIAL_CLEAR_TO_SEND
;
1660 if (Msr
.Bits
.Dsr
== 1) {
1661 *Control
|= EFI_SERIAL_DATA_SET_READY
;
1664 if (Msr
.Bits
.Ri
== 1) {
1665 *Control
|= EFI_SERIAL_RING_INDICATE
;
1668 if (Msr
.Bits
.Dcd
== 1) {
1669 *Control
|= EFI_SERIAL_CARRIER_DETECT
;
1672 // Read the Modem Control Register
1674 Mcr
.Data
= READ_MCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1676 if (Mcr
.Bits
.DtrC
== 1) {
1677 *Control
|= EFI_SERIAL_DATA_TERMINAL_READY
;
1680 if (Mcr
.Bits
.Rts
== 1) {
1681 *Control
|= EFI_SERIAL_REQUEST_TO_SEND
;
1684 if (Mcr
.Bits
.Lme
== 1) {
1685 *Control
|= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
;
1688 if (SerialDevice
->HardwareFlowControl
) {
1689 *Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
1692 // See if the Transmit FIFO is empty
1694 IsaSerialReceiveTransmit (SerialDevice
);
1696 if (IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1697 *Control
|= EFI_SERIAL_OUTPUT_BUFFER_EMPTY
;
1700 // See if the Receive FIFO is empty.
1702 IsaSerialReceiveTransmit (SerialDevice
);
1704 if (IsaSerialFifoEmpty (&SerialDevice
->Receive
)) {
1705 *Control
|= EFI_SERIAL_INPUT_BUFFER_EMPTY
;
1708 if (SerialDevice
->SoftwareLoopbackEnable
) {
1709 *Control
|= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
;
1712 gBS
->RestoreTPL (Tpl
);
1718 Write the specified number of bytes to serial device.
1720 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1721 @param BufferSize On input the size of Buffer, on output the amount of
1722 data actually written
1723 @param Buffer The buffer of data to write
1725 @retval EFI_SUCCESS The data were written successfully
1726 @retval EFI_DEVICE_ERROR The device reported an error
1727 @retval EFI_TIMEOUT The write operation was stopped due to timeout
1733 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1734 IN OUT UINTN
*BufferSize
,
1738 SERIAL_DEV
*SerialDevice
;
1745 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1749 if (*BufferSize
== 0) {
1753 if (Buffer
== NULL
) {
1754 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1756 EFI_P_EC_OUTPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1757 SerialDevice
->DevicePath
1760 return EFI_DEVICE_ERROR
;
1763 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1765 CharBuffer
= (UINT8
*) Buffer
;
1767 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1768 IsaSerialFifoAdd (&SerialDevice
->Transmit
, CharBuffer
[Index
]);
1770 while (IsaSerialReceiveTransmit (SerialDevice
) != EFI_SUCCESS
|| !IsaSerialFifoEmpty (&SerialDevice
->Transmit
)) {
1772 // Unsuccessful write so check if timeout has expired, if not,
1773 // stall for a bit, increment time elapsed, and try again
1775 if (Elapsed
>= This
->Mode
->Timeout
) {
1776 *BufferSize
= ActualWrite
;
1777 gBS
->RestoreTPL (Tpl
);
1781 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1783 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1788 // Successful write so reset timeout
1793 gBS
->RestoreTPL (Tpl
);
1799 Read the specified number of bytes from serial device.
1801 @param This Pointer to EFI_SERIAL_IO_PROTOCOL
1802 @param BufferSize On input the size of Buffer, on output the amount of
1803 data returned in buffer
1804 @param Buffer The buffer to return the data into
1806 @retval EFI_SUCCESS The data were read successfully
1807 @retval EFI_DEVICE_ERROR The device reported an error
1808 @retval EFI_TIMEOUT The read operation was stopped due to timeout
1814 IN EFI_SERIAL_IO_PROTOCOL
*This
,
1815 IN OUT UINTN
*BufferSize
,
1819 SERIAL_DEV
*SerialDevice
;
1826 SerialDevice
= SERIAL_DEV_FROM_THIS (This
);
1829 if (*BufferSize
== 0) {
1833 if (Buffer
== NULL
) {
1834 return EFI_DEVICE_ERROR
;
1837 Tpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1839 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1841 if (EFI_ERROR (Status
)) {
1844 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1846 EFI_P_EC_INPUT_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
1847 SerialDevice
->DevicePath
1850 gBS
->RestoreTPL (Tpl
);
1852 return EFI_DEVICE_ERROR
;
1855 CharBuffer
= (UINT8
*) Buffer
;
1856 for (Index
= 0; Index
< *BufferSize
; Index
++) {
1857 while (IsaSerialFifoRemove (&SerialDevice
->Receive
, &(CharBuffer
[Index
])) != EFI_SUCCESS
) {
1859 // Unsuccessful read so check if timeout has expired, if not,
1860 // stall for a bit, increment time elapsed, and try again
1861 // Need this time out to get conspliter to work.
1863 if (Elapsed
>= This
->Mode
->Timeout
) {
1864 *BufferSize
= Index
;
1865 gBS
->RestoreTPL (Tpl
);
1869 gBS
->Stall (TIMEOUT_STALL_INTERVAL
);
1870 Elapsed
+= TIMEOUT_STALL_INTERVAL
;
1872 Status
= IsaSerialReceiveTransmit (SerialDevice
);
1873 if (Status
== EFI_DEVICE_ERROR
) {
1874 *BufferSize
= Index
;
1875 gBS
->RestoreTPL (Tpl
);
1876 return EFI_DEVICE_ERROR
;
1880 // Successful read so reset timeout
1885 IsaSerialReceiveTransmit (SerialDevice
);
1887 gBS
->RestoreTPL (Tpl
);
1893 Use scratchpad register to test if this serial port is present.
1895 @param SerialDevice Pointer to serial device structure
1897 @return if this serial port is present
1900 IsaSerialPortPresent (
1901 IN SERIAL_DEV
*SerialDevice
1913 Temp
= READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
);
1914 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0xAA);
1916 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0xAA) {
1920 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, 0x55);
1922 if (READ_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
) != 0x55) {
1928 WRITE_SCR (SerialDevice
->IsaIo
, SerialDevice
->BaseAddress
, Temp
);
1933 Use IsaIo protocol to read serial port.
1935 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1936 @param BaseAddress Serial port register group base address
1937 @param Offset Offset in register group
1939 @return Data read from serial port
1944 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1945 IN UINT16 BaseAddress
,
1952 // Use IsaIo to access IO
1957 BaseAddress
+ Offset
,
1965 Use IsaIo protocol to write serial port.
1967 @param IsaIo Pointer to EFI_ISA_IO_PROTOCOL instance
1968 @param BaseAddress Serial port register group base address
1969 @param Offset Offset in register group
1970 @param Data data which is to be written to some serial port register
1974 IsaSerialWritePort (
1975 IN EFI_ISA_IO_PROTOCOL
*IsaIo
,
1976 IN UINT16 BaseAddress
,
1982 // Use IsaIo to access IO
1987 BaseAddress
+ Offset
,