2 Serial driver for PCI or SIO UARTS.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // ISA Serial Driver Global Variables
15 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver
= {
16 SerialControllerDriverSupported
,
17 SerialControllerDriverStart
,
18 SerialControllerDriverStop
,
24 CONTROLLER_DEVICE_PATH mControllerDevicePathTemplate
= {
29 (UINT8
) (sizeof (CONTROLLER_DEVICE_PATH
)),
30 (UINT8
) ((sizeof (CONTROLLER_DEVICE_PATH
)) >> 8)
36 SERIAL_DEV gSerialDevTemplate
= {
40 SERIAL_IO_INTERFACE_REVISION
,
50 SERIAL_PORT_SUPPORT_CONTROL_MASK
,
51 SERIAL_PORT_DEFAULT_TIMEOUT
,
59 NULL
, // ParentDevicePath
62 MESSAGING_DEVICE_PATH
,
65 (UINT8
) (sizeof (UART_DEVICE_PATH
)),
66 (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8)
75 16, // ReceiveFifoDepth
77 16, // TransmitFifoDepth
78 { 0, 0 }, // Transmit;
79 FALSE
, // SoftwareLoopbackEnable;
80 FALSE
, // HardwareFlowControl;
81 NULL
, // *ControllerNameTable;
82 FALSE
, // ContainsControllerNode;
84 NULL
// *PciDeviceInfo;
88 Check the device path node whether it's the Flow Control node or not.
90 @param[in] FlowControl The device path node to be checked.
92 @retval TRUE It's the Flow Control node.
93 @retval FALSE It's not.
97 IsUartFlowControlDevicePathNode (
98 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
102 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
103 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
104 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
109 The user Entry Point for module PciSioSerial. The user code starts with this function.
111 @param[in] ImageHandle The firmware allocated handle for the EFI image.
112 @param[in] SystemTable A pointer to the EFI System Table.
114 @retval EFI_SUCCESS The entry point is executed successfully.
115 @retval other Some error occurs when executing this entry point.
120 InitializePciSioSerial (
121 IN EFI_HANDLE ImageHandle
,
122 IN EFI_SYSTEM_TABLE
*SystemTable
128 // Install driver model protocol(s).
130 Status
= EfiLibInstallDriverBindingComponentName2 (
133 &gSerialControllerDriver
,
135 &gPciSioSerialComponentName
,
136 &gPciSioSerialComponentName2
138 ASSERT_EFI_ERROR (Status
);
141 // Initialize UART default setting in gSerialDevTempate
143 gSerialDevTemplate
.SerialMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
144 gSerialDevTemplate
.SerialMode
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
145 gSerialDevTemplate
.SerialMode
.Parity
= PcdGet8 (PcdUartDefaultParity
);
146 gSerialDevTemplate
.SerialMode
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
147 gSerialDevTemplate
.UartDevicePath
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
148 gSerialDevTemplate
.UartDevicePath
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
149 gSerialDevTemplate
.UartDevicePath
.Parity
= PcdGet8 (PcdUartDefaultParity
);
150 gSerialDevTemplate
.UartDevicePath
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
151 gSerialDevTemplate
.ClockRate
= PcdGet32 (PcdSerialClockRate
);
157 Return whether the controller is a SIO serial controller.
159 @param Controller The controller handle.
161 @retval EFI_SUCCESS The controller is a SIO serial controller.
162 @retval others The controller is not a SIO serial controller.
165 IsSioSerialController (
166 EFI_HANDLE Controller
170 EFI_SIO_PROTOCOL
*Sio
;
171 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
172 ACPI_HID_DEVICE_PATH
*Acpi
;
175 // Open the IO Abstraction(s) needed to perform the supported test
177 Status
= gBS
->OpenProtocol (
179 &gEfiSioProtocolGuid
,
181 gSerialControllerDriver
.DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (Status
== EFI_ALREADY_STARTED
) {
189 if (!EFI_ERROR (Status
)) {
191 // Close the I/O Abstraction(s) used to perform the supported test
195 &gEfiSioProtocolGuid
,
196 gSerialControllerDriver
.DriverBindingHandle
,
200 Status
= gBS
->OpenProtocol (
202 &gEfiDevicePathProtocolGuid
,
203 (VOID
**) &DevicePath
,
204 gSerialControllerDriver
.DriverBindingHandle
,
206 EFI_OPEN_PROTOCOL_BY_DRIVER
208 ASSERT (Status
!= EFI_ALREADY_STARTED
);
210 if (!EFI_ERROR (Status
)) {
212 Acpi
= (ACPI_HID_DEVICE_PATH
*) DevicePath
;
213 DevicePath
= NextDevicePathNode (DevicePath
);
214 } while (!IsDevicePathEnd (DevicePath
));
216 if (DevicePathType (Acpi
) != ACPI_DEVICE_PATH
||
217 (DevicePathSubType (Acpi
) != ACPI_DP
&& DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
) ||
218 Acpi
->HID
!= EISA_PNP_ID (0x501)
220 Status
= EFI_UNSUPPORTED
;
225 // Close protocol, don't use device path protocol in the Support() function
229 &gEfiDevicePathProtocolGuid
,
230 gSerialControllerDriver
.DriverBindingHandle
,
238 Return whether the controller is a PCI serial controller.
240 @param Controller The controller handle.
242 @retval EFI_SUCCESS The controller is a PCI serial controller.
243 @retval others The controller is not a PCI serial controller.
246 IsPciSerialController (
247 EFI_HANDLE Controller
251 EFI_PCI_IO_PROTOCOL
*PciIo
;
252 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
254 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
257 // Open the IO Abstraction(s) needed to perform the supported test
259 Status
= gBS
->OpenProtocol (
261 &gEfiPciIoProtocolGuid
,
263 gSerialControllerDriver
.DriverBindingHandle
,
265 EFI_OPEN_PROTOCOL_BY_DRIVER
267 if (Status
== EFI_ALREADY_STARTED
) {
271 if (!EFI_ERROR (Status
)) {
272 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
273 if (!EFI_ERROR (Status
)) {
274 if (!IS_PCI_16550_SERIAL (&Pci
)) {
275 for (PciSerialParameter
= (PCI_SERIAL_PARAMETER
*) PcdGetPtr (PcdPciSerialParameters
)
276 ; PciSerialParameter
->VendorId
!= 0xFFFF
277 ; PciSerialParameter
++
279 if ((Pci
.Hdr
.VendorId
== PciSerialParameter
->VendorId
) &&
280 (Pci
.Hdr
.DeviceId
== PciSerialParameter
->DeviceId
)
285 if (PciSerialParameter
->VendorId
== 0xFFFF) {
286 Status
= EFI_UNSUPPORTED
;
288 Status
= EFI_SUCCESS
;
294 // Close the I/O Abstraction(s) used to perform the supported test
298 &gEfiPciIoProtocolGuid
,
299 gSerialControllerDriver
.DriverBindingHandle
,
303 if (EFI_ERROR (Status
)) {
308 // Open the EFI Device Path protocol needed to perform the supported test
310 Status
= gBS
->OpenProtocol (
312 &gEfiDevicePathProtocolGuid
,
313 (VOID
**) &DevicePath
,
314 gSerialControllerDriver
.DriverBindingHandle
,
316 EFI_OPEN_PROTOCOL_BY_DRIVER
318 ASSERT (Status
!= EFI_ALREADY_STARTED
);
321 // Close protocol, don't use device path protocol in the Support() function
325 &gEfiDevicePathProtocolGuid
,
326 gSerialControllerDriver
.DriverBindingHandle
,
334 Check to see if this driver supports the given controller
336 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
337 @param Controller The handle of the controller to test.
338 @param RemainingDevicePath A pointer to the remaining portion of a device path.
340 @return EFI_SUCCESS This driver can support the given controller
345 SerialControllerDriverSupported (
346 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
347 IN EFI_HANDLE Controller
,
348 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
353 UART_DEVICE_PATH
*Uart
;
354 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
357 // Test RemainingDevicePath
359 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
360 Status
= EFI_UNSUPPORTED
;
362 Uart
= SkipControllerDevicePathNode (RemainingDevicePath
, NULL
, NULL
);
363 if (DevicePathType (Uart
) != MESSAGING_DEVICE_PATH
||
364 DevicePathSubType (Uart
) != MSG_UART_DP
||
365 DevicePathNodeLength (Uart
) != sizeof (UART_DEVICE_PATH
)
367 return EFI_UNSUPPORTED
;
371 // Do a rough check because Clock Rate is unknown until DriverBindingStart()
373 if (!VerifyUartParameters (0, Uart
->BaudRate
, Uart
->DataBits
, Uart
->Parity
, Uart
->StopBits
, NULL
, NULL
)) {
374 return EFI_UNSUPPORTED
;
377 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
378 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
380 // If the second node is Flow Control Node,
381 // return error when it request other than hardware flow control.
383 if ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
384 return EFI_UNSUPPORTED
;
389 Status
= IsSioSerialController (Controller
);
390 if (EFI_ERROR (Status
)) {
391 Status
= IsPciSerialController (Controller
);
397 Create the child serial device instance.
399 @param Controller The parent controller handle.
400 @param Uart Pointer to the UART device path node in RemainingDevicePath,
401 or NULL if RemainingDevicePath is NULL.
402 @param ParentDevicePath Pointer to the parent device path.
403 @param CreateControllerNode TRUE to create the controller node.
404 @param Instance Instance number of the serial device.
405 The value will be set to the controller node
406 if CreateControllerNode is TRUE.
407 @param ParentIo A union type pointer to either Sio or PciIo.
408 @param PciSerialParameter The PCI serial parameter to be used by current serial device.
409 NULL for SIO serial device.
410 @param PciDeviceInfo The PCI device info for the current serial device.
411 NULL for SIO serial device.
413 @retval EFI_SUCCESS The serial device was created successfully.
414 @retval others The serial device wasn't created.
418 IN EFI_HANDLE Controller
,
419 IN UART_DEVICE_PATH
*Uart
,
420 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
421 IN BOOLEAN CreateControllerNode
,
423 IN PARENT_IO_PROTOCOL_PTR ParentIo
,
424 IN PCI_SERIAL_PARAMETER
*PciSerialParameter
, OPTIONAL
425 IN PCI_DEVICE_INFO
*PciDeviceInfo OPTIONAL
429 SERIAL_DEV
*SerialDevice
;
432 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
433 UINT32 FlowControlMap
;
434 ACPI_RESOURCE_HEADER_PTR Resources
;
435 EFI_ACPI_IO_PORT_DESCRIPTOR
*Io
;
436 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIo
;
437 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AddressSpace
;
438 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
446 // Initialize the serial device instance
448 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTemplate
);
449 ASSERT (SerialDevice
!= NULL
);
451 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
452 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
453 SerialDevice
->PciDeviceInfo
= PciDeviceInfo
;
454 SerialDevice
->Instance
= Instance
;
457 CopyMem (&SerialDevice
->UartDevicePath
, Uart
, sizeof (UART_DEVICE_PATH
));
458 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
459 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
460 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
467 // For PCI serial device, use the information from PCD
469 if (PciSerialParameter
!= NULL
) {
470 BarIndex
= (PciSerialParameter
->BarIndex
== MAX_UINT8
) ? 0 : PciSerialParameter
->BarIndex
;
471 Offset
= PciSerialParameter
->Offset
;
472 if (PciSerialParameter
->RegisterStride
!= 0) {
473 SerialDevice
->RegisterStride
= PciSerialParameter
->RegisterStride
;
475 if (PciSerialParameter
->ClockRate
!= 0) {
476 SerialDevice
->ClockRate
= PciSerialParameter
->ClockRate
;
478 if (PciSerialParameter
->ReceiveFifoDepth
!= 0) {
479 SerialDevice
->ReceiveFifoDepth
= PciSerialParameter
->ReceiveFifoDepth
;
481 if (PciSerialParameter
->TransmitFifoDepth
!= 0) {
482 SerialDevice
->TransmitFifoDepth
= PciSerialParameter
->TransmitFifoDepth
;
487 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
488 // DriverBindingStart() shouldn't create a handle with different UART device path.
490 if (!VerifyUartParameters (SerialDevice
->ClockRate
, SerialDevice
->UartDevicePath
.BaudRate
, SerialDevice
->UartDevicePath
.DataBits
,
491 SerialDevice
->UartDevicePath
.Parity
, SerialDevice
->UartDevicePath
.StopBits
, NULL
, NULL
493 Status
= EFI_INVALID_PARAMETER
;
497 if (PciSerialParameter
== NULL
) {
498 Status
= ParentIo
.Sio
->GetResources (ParentIo
.Sio
, &Resources
);
500 Status
= ParentIo
.PciIo
->GetBarAttributes (ParentIo
.PciIo
, BarIndex
, NULL
, (VOID
**) &Resources
);
503 if (!EFI_ERROR (Status
)) {
505 // Get the base address information from ACPI resource descriptor.
506 // ACPI_IO_PORT_DESCRIPTOR and ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR are returned from Sio;
507 // ACPI_ADDRESS_SPACE_DESCRIPTOR is returned from PciIo.
509 while ((Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) && (SerialDevice
->BaseAddress
== 0)) {
510 switch (Resources
.SmallHeader
->Byte
) {
511 case ACPI_IO_PORT_DESCRIPTOR
:
512 Io
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
513 if (Io
->Length
!= 0) {
514 SerialDevice
->BaseAddress
= Io
->BaseAddressMin
;
518 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
519 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
520 if (FixedIo
->Length
!= 0) {
521 SerialDevice
->BaseAddress
= FixedIo
->BaseAddress
;
525 case ACPI_ADDRESS_SPACE_DESCRIPTOR
:
526 AddressSpace
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Resources
.SmallHeader
;
527 if (AddressSpace
->AddrLen
!= 0) {
528 if (AddressSpace
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
529 SerialDevice
->MmioAccess
= TRUE
;
531 SerialDevice
->BaseAddress
= AddressSpace
->AddrRangeMin
+ Offset
;
536 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
537 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) Resources
.SmallHeader
538 + Resources
.SmallHeader
->Bits
.Length
539 + sizeof (*Resources
.SmallHeader
));
541 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) Resources
.LargeHeader
542 + Resources
.LargeHeader
->Length
543 + sizeof (*Resources
.LargeHeader
));
548 if (SerialDevice
->BaseAddress
== 0) {
549 Status
= EFI_INVALID_PARAMETER
;
553 SerialDevice
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
556 // Report status code the serial present
558 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
560 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
561 SerialDevice
->ParentDevicePath
564 if (!SerialPresent (SerialDevice
)) {
565 Status
= EFI_DEVICE_ERROR
;
566 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
568 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
569 SerialDevice
->ParentDevicePath
575 // 1. Append Controller device path node.
577 if (CreateControllerNode
) {
578 mControllerDevicePathTemplate
.ControllerNumber
= SerialDevice
->Instance
;
579 SerialDevice
->DevicePath
= AppendDevicePathNode (
580 SerialDevice
->ParentDevicePath
,
581 (EFI_DEVICE_PATH_PROTOCOL
*) &mControllerDevicePathTemplate
583 SerialDevice
->ContainsControllerNode
= TRUE
;
587 // 2. Append UART device path node.
588 // The Uart setings are zero here.
589 // SetAttribute() will update them to match the default setings.
591 TempDevicePath
= SerialDevice
->DevicePath
;
592 if (TempDevicePath
!= NULL
) {
593 SerialDevice
->DevicePath
= AppendDevicePathNode (
595 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
597 FreePool (TempDevicePath
);
599 SerialDevice
->DevicePath
= AppendDevicePathNode (
600 SerialDevice
->ParentDevicePath
,
601 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
605 // 3. Append the Flow Control device path node.
606 // Only produce the Flow Control node when remaining device path has it
608 if (FlowControl
!= NULL
) {
609 TempDevicePath
= SerialDevice
->DevicePath
;
610 if (TempDevicePath
!= NULL
) {
611 SerialDevice
->DevicePath
= AppendDevicePathNode (
613 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
615 FreePool (TempDevicePath
);
618 ASSERT (SerialDevice
->DevicePath
!= NULL
);
621 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
623 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
624 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
625 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
626 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
629 // Issue a reset to initialize the COM port
631 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
632 if (EFI_ERROR (Status
)) {
633 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
635 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
636 SerialDevice
->DevicePath
641 AddName (SerialDevice
, Instance
);
643 // Install protocol interfaces for the serial device.
645 Status
= gBS
->InstallMultipleProtocolInterfaces (
646 &SerialDevice
->Handle
,
647 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
648 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
651 if (EFI_ERROR (Status
)) {
655 // Open For Child Device
657 Status
= gBS
->OpenProtocol (
659 PciSerialParameter
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
661 gSerialControllerDriver
.DriverBindingHandle
,
662 SerialDevice
->Handle
,
663 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
666 if (EFI_ERROR (Status
)) {
667 gBS
->UninstallMultipleProtocolInterfaces (
668 SerialDevice
->Handle
,
669 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
670 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
676 if (EFI_ERROR (Status
)) {
677 if (SerialDevice
->DevicePath
!= NULL
) {
678 FreePool (SerialDevice
->DevicePath
);
680 if (SerialDevice
->ControllerNameTable
!= NULL
) {
681 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
683 FreePool (SerialDevice
);
689 Returns an array of pointers containing all the child serial device pointers.
691 @param Controller The parent controller handle.
692 @param IoProtocolGuid The protocol GUID, either equals to gEfiSioProtocolGuid
693 or equals to gEfiPciIoProtocolGuid.
694 @param Count Count of the serial devices.
696 @return An array of pointers containing all the child serial device pointers.
699 GetChildSerialDevices (
700 IN EFI_HANDLE Controller
,
701 IN EFI_GUID
*IoProtocolGuid
,
707 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
709 SERIAL_DEV
**SerialDevices
;
710 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
711 BOOLEAN OpenByDriver
;
715 // If the SerialIo instance specified by RemainingDevicePath is already created,
716 // update the attributes/control.
718 Status
= gBS
->OpenProtocolInformation (
724 if (EFI_ERROR (Status
)) {
728 SerialDevices
= AllocatePool (EntryCount
* sizeof (SERIAL_DEV
*));
729 ASSERT (SerialDevices
!= NULL
);
732 OpenByDriver
= FALSE
;
733 for (Index
= 0; Index
< EntryCount
; Index
++) {
734 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
735 Status
= gBS
->OpenProtocol (
736 OpenInfoBuffer
[Index
].ControllerHandle
,
737 &gEfiSerialIoProtocolGuid
,
739 gSerialControllerDriver
.DriverBindingHandle
,
741 EFI_OPEN_PROTOCOL_GET_PROTOCOL
743 if (!EFI_ERROR (Status
)) {
744 SerialDevices
[(*Count
)++] = SERIAL_DEV_FROM_THIS (SerialIo
);
749 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
750 ASSERT (OpenInfoBuffer
[Index
].AgentHandle
== gSerialControllerDriver
.DriverBindingHandle
);
754 if (OpenInfoBuffer
!= NULL
) {
755 FreePool (OpenInfoBuffer
);
758 ASSERT ((*Count
== 0) || (OpenByDriver
));
760 return SerialDevices
;
764 Start to management the controller passed in
766 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
767 @param Controller The handle of the controller to test.
768 @param RemainingDevicePath A pointer to the remaining portion of a device path.
770 @return EFI_SUCCESS Driver is started successfully
774 SerialControllerDriverStart (
775 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
776 IN EFI_HANDLE Controller
,
777 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
782 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
783 EFI_DEVICE_PATH_PROTOCOL
*Node
;
784 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
785 UINT32 ControllerNumber
;
786 UART_DEVICE_PATH
*Uart
;
787 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
789 PARENT_IO_PROTOCOL_PTR ParentIo
;
790 ACPI_HID_DEVICE_PATH
*Acpi
;
791 EFI_GUID
*IoProtocolGuid
;
792 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
793 PCI_SERIAL_PARAMETER DefaultPciSerialParameter
;
795 UINT32 PciSerialCount
;
796 SERIAL_DEV
**SerialDevices
;
797 UINTN SerialDeviceCount
;
798 PCI_DEVICE_INFO
*PciDeviceInfo
;
800 BOOLEAN ContainsControllerNode
;
803 // Get the Parent Device Path
805 Status
= gBS
->OpenProtocol (
807 &gEfiDevicePathProtocolGuid
,
808 (VOID
**) &ParentDevicePath
,
809 This
->DriverBindingHandle
,
811 EFI_OPEN_PROTOCOL_BY_DRIVER
813 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
817 // Report status code enable the serial
819 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
821 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
826 // Grab the IO abstraction we need to get any work done
828 IoProtocolGuid
= &gEfiSioProtocolGuid
;
829 Status
= gBS
->OpenProtocol (
833 This
->DriverBindingHandle
,
835 EFI_OPEN_PROTOCOL_BY_DRIVER
837 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
838 IoProtocolGuid
= &gEfiPciIoProtocolGuid
;
839 Status
= gBS
->OpenProtocol (
843 This
->DriverBindingHandle
,
845 EFI_OPEN_PROTOCOL_BY_DRIVER
848 ASSERT (!EFI_ERROR (Status
) || Status
== EFI_ALREADY_STARTED
);
851 // Do nothing for END device path node
853 if ((RemainingDevicePath
!= NULL
) && IsDevicePathEnd (RemainingDevicePath
)) {
857 ControllerNumber
= 0;
858 ContainsControllerNode
= FALSE
;
859 SerialDevices
= GetChildSerialDevices (Controller
, IoProtocolGuid
, &SerialDeviceCount
);
861 if (SerialDeviceCount
!= 0) {
862 if (RemainingDevicePath
== NULL
) {
864 // If the SerialIo instance is already created, NULL as RemainingDevicePath is treated
865 // as to create the same SerialIo instance.
870 // Update the attributes/control of the SerialIo instance specified by RemainingDevicePath.
872 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
873 for (Index
= 0; Index
< SerialDeviceCount
; Index
++) {
874 ASSERT ((SerialDevices
!= NULL
) && (SerialDevices
[Index
] != NULL
));
875 if ((!SerialDevices
[Index
]->ContainsControllerNode
&& !ContainsControllerNode
) ||
876 (SerialDevices
[Index
]->ContainsControllerNode
&& ContainsControllerNode
&& SerialDevices
[Index
]->Instance
== ControllerNumber
)
878 SerialIo
= &SerialDevices
[Index
]->SerialIo
;
879 Status
= EFI_INVALID_PARAMETER
;
881 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
882 // DriverBindingStart() shouldn't create a handle with different UART device path.
884 if (VerifyUartParameters (SerialDevices
[Index
]->ClockRate
, Uart
->BaudRate
, Uart
->DataBits
,
885 (EFI_PARITY_TYPE
) Uart
->Parity
, (EFI_STOP_BITS_TYPE
) Uart
->StopBits
, NULL
, NULL
)) {
886 Status
= SerialIo
->SetAttributes (
889 SerialIo
->Mode
->ReceiveFifoDepth
,
890 SerialIo
->Mode
->Timeout
,
891 (EFI_PARITY_TYPE
) Uart
->Parity
,
893 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
896 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
897 if (!EFI_ERROR (Status
) && IsUartFlowControlDevicePathNode (FlowControl
)) {
898 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
899 if (!EFI_ERROR (Status
)) {
900 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
901 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
903 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
906 // Clear the bits that are not allowed to pass to SetControl
908 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
909 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
910 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
911 Status
= SerialIo
->SetControl (SerialIo
, Control
);
917 if (Index
!= SerialDeviceCount
) {
919 // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated.
920 // Otherwise continue to create the instance specified by RemainingDevicePath.
922 if (SerialDevices
!= NULL
) {
923 FreePool (SerialDevices
);
930 if (RemainingDevicePath
!= NULL
) {
931 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
936 PciDeviceInfo
= NULL
;
937 if (IoProtocolGuid
== &gEfiSioProtocolGuid
) {
938 Status
= EFI_NOT_FOUND
;
939 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
940 Node
= ParentDevicePath
;
942 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
943 Node
= NextDevicePathNode (Node
);
944 } while (!IsDevicePathEnd (Node
));
945 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, Acpi
->UID
, ParentIo
, NULL
, NULL
);
946 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create SIO child serial device - %r\n", Status
));
949 Status
= ParentIo
.PciIo
->Pci
.Read (ParentIo
.PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
950 if (!EFI_ERROR (Status
)) {
952 // PcdPciSerialParameters takes the higher priority.
955 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
956 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
957 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
)
963 if (SerialDeviceCount
== 0) {
965 // Enable the IO & MEM decoding when creating the first child.
966 // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0).
968 PciDeviceInfo
= AllocatePool (sizeof (PCI_DEVICE_INFO
));
969 ASSERT (PciDeviceInfo
!= NULL
);
970 PciDeviceInfo
->ChildCount
= 0;
971 PciDeviceInfo
->PciIo
= ParentIo
.PciIo
;
972 Status
= ParentIo
.PciIo
->Attributes (
974 EfiPciIoAttributeOperationGet
,
976 &PciDeviceInfo
->PciAttributes
979 if (!EFI_ERROR (Status
)) {
980 Status
= ParentIo
.PciIo
->Attributes (
982 EfiPciIoAttributeOperationSupported
,
986 if (!EFI_ERROR (Status
)) {
987 Supports
&= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
);
988 Status
= ParentIo
.PciIo
->Attributes (
990 EfiPciIoAttributeOperationEnable
,
998 // Re-use the PciDeviceInfo stored in existing children.
1000 ASSERT ((SerialDevices
!= NULL
) && (SerialDevices
[0] != NULL
));
1001 PciDeviceInfo
= SerialDevices
[0]->PciDeviceInfo
;
1002 ASSERT (PciDeviceInfo
!= NULL
);
1005 Status
= EFI_NOT_FOUND
;
1006 if (PciSerialCount
<= 1) {
1008 // PCI serial device contains only one UART
1010 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
1012 // This PCI serial device is matched by class code in Supported()
1014 if (PciSerialCount
== 0) {
1015 DefaultPciSerialParameter
.VendorId
= Pci
.Hdr
.VendorId
;
1016 DefaultPciSerialParameter
.DeviceId
= Pci
.Hdr
.DeviceId
;
1017 DefaultPciSerialParameter
.BarIndex
= 0;
1018 DefaultPciSerialParameter
.Offset
= 0;
1019 DefaultPciSerialParameter
.RegisterStride
= 0;
1020 DefaultPciSerialParameter
.ClockRate
= 0;
1021 PciSerialParameter
= &DefaultPciSerialParameter
;
1022 } else if (PciSerialCount
== 1) {
1023 PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
);
1026 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, 0, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1027 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status
));
1028 if (!EFI_ERROR (Status
)) {
1029 PciDeviceInfo
->ChildCount
++;
1034 // PCI serial device contains multiple UARTs
1036 if (RemainingDevicePath
== NULL
|| ContainsControllerNode
) {
1038 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
1039 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
1040 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
) &&
1041 ((RemainingDevicePath
== NULL
) || (ControllerNumber
== PciSerialCount
))
1044 // Create controller node when PCI serial device contains multiple UARTs
1046 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, TRUE
, PciSerialCount
, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1048 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status
));
1049 if (!EFI_ERROR (Status
)) {
1050 PciDeviceInfo
->ChildCount
++;
1059 if (SerialDevices
!= NULL
) {
1060 FreePool (SerialDevices
);
1064 // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully
1066 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
!= 0)) {
1067 Status
= EFI_SUCCESS
;
1070 if (EFI_ERROR (Status
) && (SerialDeviceCount
== 0)) {
1071 if (PciDeviceInfo
!= NULL
) {
1072 Status
= ParentIo
.PciIo
->Attributes (
1074 EfiPciIoAttributeOperationSet
,
1075 PciDeviceInfo
->PciAttributes
,
1078 ASSERT_EFI_ERROR (Status
);
1079 FreePool (PciDeviceInfo
);
1081 gBS
->CloseProtocol (
1083 &gEfiDevicePathProtocolGuid
,
1084 This
->DriverBindingHandle
,
1087 gBS
->CloseProtocol (
1090 This
->DriverBindingHandle
,
1099 Disconnect this driver with the controller, uninstall related protocol instance
1101 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1102 @param Controller The handle of the controller to test.
1103 @param NumberOfChildren Number of child device.
1104 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
1106 @retval EFI_SUCCESS Operation successfully
1107 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
1112 SerialControllerDriverStop (
1113 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1114 IN EFI_HANDLE Controller
,
1115 IN UINTN NumberOfChildren
,
1116 IN EFI_HANDLE
*ChildHandleBuffer
1122 BOOLEAN AllChildrenStopped
;
1123 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1124 SERIAL_DEV
*SerialDevice
;
1126 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1127 PCI_DEVICE_INFO
*PciDeviceInfo
;
1129 PciDeviceInfo
= NULL
;
1131 Status
= gBS
->HandleProtocol (
1133 &gEfiDevicePathProtocolGuid
,
1134 (VOID
**) &DevicePath
1138 // Report the status code disable the serial
1140 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1142 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
1146 if (NumberOfChildren
== 0) {
1148 // Close the bus driver
1150 Status
= gBS
->OpenProtocol (
1152 &gEfiPciIoProtocolGuid
,
1154 This
->DriverBindingHandle
,
1156 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1158 gBS
->CloseProtocol (
1160 !EFI_ERROR (Status
) ? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1161 This
->DriverBindingHandle
,
1165 gBS
->CloseProtocol (
1167 &gEfiDevicePathProtocolGuid
,
1168 This
->DriverBindingHandle
,
1174 AllChildrenStopped
= TRUE
;
1176 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1178 Status
= gBS
->OpenProtocol (
1179 ChildHandleBuffer
[Index
],
1180 &gEfiSerialIoProtocolGuid
,
1181 (VOID
**) &SerialIo
,
1182 This
->DriverBindingHandle
,
1184 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1186 if (!EFI_ERROR (Status
)) {
1188 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
1189 ASSERT ((PciDeviceInfo
== NULL
) || (PciDeviceInfo
== SerialDevice
->PciDeviceInfo
));
1190 PciDeviceInfo
= SerialDevice
->PciDeviceInfo
;
1192 Status
= gBS
->CloseProtocol (
1194 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1195 This
->DriverBindingHandle
,
1196 ChildHandleBuffer
[Index
]
1199 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1200 ChildHandleBuffer
[Index
],
1201 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
1202 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
1205 if (EFI_ERROR (Status
)) {
1208 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1210 This
->DriverBindingHandle
,
1211 ChildHandleBuffer
[Index
],
1212 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1215 FreePool (SerialDevice
->DevicePath
);
1216 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
1217 FreePool (SerialDevice
);
1219 if (PciDeviceInfo
!= NULL
) {
1220 ASSERT (PciDeviceInfo
->ChildCount
!= 0);
1221 PciDeviceInfo
->ChildCount
--;
1226 if (EFI_ERROR (Status
)) {
1227 AllChildrenStopped
= FALSE
;
1231 if (!AllChildrenStopped
) {
1232 return EFI_DEVICE_ERROR
;
1235 // If all children are destroyed, restore the PCI attributes.
1237 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
== 0)) {
1238 ASSERT (PciDeviceInfo
->PciIo
!= NULL
);
1239 Status
= PciDeviceInfo
->PciIo
->Attributes (
1240 PciDeviceInfo
->PciIo
,
1241 EfiPciIoAttributeOperationSet
,
1242 PciDeviceInfo
->PciAttributes
,
1245 ASSERT_EFI_ERROR (Status
);
1246 FreePool (PciDeviceInfo
);