2 Serial driver for PCI or SIO UARTS.
4 Copyright (c) 2006 - 2015, 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
21 EFI_DRIVER_BINDING_PROTOCOL gSerialControllerDriver
= {
22 SerialControllerDriverSupported
,
23 SerialControllerDriverStart
,
24 SerialControllerDriverStop
,
30 CONTROLLER_DEVICE_PATH mControllerDevicePathTemplate
= {
35 (UINT8
) (sizeof (CONTROLLER_DEVICE_PATH
)),
36 (UINT8
) ((sizeof (CONTROLLER_DEVICE_PATH
)) >> 8)
42 SERIAL_DEV gSerialDevTemplate
= {
46 SERIAL_IO_INTERFACE_REVISION
,
56 SERIAL_PORT_SUPPORT_CONTROL_MASK
,
57 SERIAL_PORT_DEFAULT_TIMEOUT
,
65 NULL
, // ParentDevicePath
68 MESSAGING_DEVICE_PATH
,
71 (UINT8
) (sizeof (UART_DEVICE_PATH
)),
72 (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8)
81 16, // ReceiveFifoDepth
83 16, // TransmitFifoDepth
84 { 0, 0 }, // Transmit;
85 FALSE
, // SoftwareLoopbackEnable;
86 FALSE
, // HardwareFlowControl;
87 NULL
, // *ControllerNameTable;
88 FALSE
, // ContainsControllerNode;
90 NULL
// *PciDeviceInfo;
94 Check the device path node whether it's the Flow Control node or not.
96 @param[in] FlowControl The device path node to be checked.
98 @retval TRUE It's the Flow Control node.
99 @retval FALSE It's not.
103 IsUartFlowControlDevicePathNode (
104 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
108 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
109 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
110 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
115 The user Entry Point for module PciSioSerial. The user code starts with this function.
117 @param[in] ImageHandle The firmware allocated handle for the EFI image.
118 @param[in] SystemTable A pointer to the EFI System Table.
120 @retval EFI_SUCCESS The entry point is executed successfully.
121 @retval other Some error occurs when executing this entry point.
126 InitializePciSioSerial (
127 IN EFI_HANDLE ImageHandle
,
128 IN EFI_SYSTEM_TABLE
*SystemTable
134 // Install driver model protocol(s).
136 Status
= EfiLibInstallDriverBindingComponentName2 (
139 &gSerialControllerDriver
,
141 &gPciSioSerialComponentName
,
142 &gPciSioSerialComponentName2
144 ASSERT_EFI_ERROR (Status
);
147 // Initialize UART default setting in gSerialDevTempate
149 gSerialDevTemplate
.SerialMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
150 gSerialDevTemplate
.SerialMode
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
151 gSerialDevTemplate
.SerialMode
.Parity
= PcdGet8 (PcdUartDefaultParity
);
152 gSerialDevTemplate
.SerialMode
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
153 gSerialDevTemplate
.UartDevicePath
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
154 gSerialDevTemplate
.UartDevicePath
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
155 gSerialDevTemplate
.UartDevicePath
.Parity
= PcdGet8 (PcdUartDefaultParity
);
156 gSerialDevTemplate
.UartDevicePath
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
157 gSerialDevTemplate
.ClockRate
= PcdGet32 (PcdSerialClockRate
);
163 Return whether the controller is a SIO serial controller.
165 @param Controller The controller handle.
167 @retval EFI_SUCCESS The controller is a SIO serial controller.
168 @retval others The controller is not a SIO serial controller.
171 IsSioSerialController (
172 EFI_HANDLE Controller
176 EFI_SIO_PROTOCOL
*Sio
;
177 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
178 ACPI_HID_DEVICE_PATH
*Acpi
;
181 // Open the IO Abstraction(s) needed to perform the supported test
183 Status
= gBS
->OpenProtocol (
185 &gEfiSioProtocolGuid
,
187 gSerialControllerDriver
.DriverBindingHandle
,
189 EFI_OPEN_PROTOCOL_BY_DRIVER
191 if (Status
== EFI_ALREADY_STARTED
) {
195 if (!EFI_ERROR (Status
)) {
197 // Close the I/O Abstraction(s) used to perform the supported test
201 &gEfiSioProtocolGuid
,
202 gSerialControllerDriver
.DriverBindingHandle
,
206 Status
= gBS
->OpenProtocol (
208 &gEfiDevicePathProtocolGuid
,
209 (VOID
**) &DevicePath
,
210 gSerialControllerDriver
.DriverBindingHandle
,
212 EFI_OPEN_PROTOCOL_BY_DRIVER
214 ASSERT (Status
!= EFI_ALREADY_STARTED
);
216 if (!EFI_ERROR (Status
)) {
218 Acpi
= (ACPI_HID_DEVICE_PATH
*) DevicePath
;
219 DevicePath
= NextDevicePathNode (DevicePath
);
220 } while (!IsDevicePathEnd (DevicePath
));
222 if (DevicePathType (Acpi
) != ACPI_DEVICE_PATH
||
223 (DevicePathSubType (Acpi
) != ACPI_DP
&& DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
) ||
224 Acpi
->HID
!= EISA_PNP_ID (0x501)
226 Status
= EFI_UNSUPPORTED
;
231 // Close protocol, don't use device path protocol in the Support() function
235 &gEfiDevicePathProtocolGuid
,
236 gSerialControllerDriver
.DriverBindingHandle
,
244 Return whether the controller is a PCI serial controller.
246 @param Controller The controller handle.
248 @retval EFI_SUCCESS The controller is a PCI serial controller.
249 @retval others The controller is not a PCI serial controller.
252 IsPciSerialController (
253 EFI_HANDLE Controller
257 EFI_PCI_IO_PROTOCOL
*PciIo
;
258 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
260 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
263 // Open the IO Abstraction(s) needed to perform the supported test
265 Status
= gBS
->OpenProtocol (
267 &gEfiPciIoProtocolGuid
,
269 gSerialControllerDriver
.DriverBindingHandle
,
271 EFI_OPEN_PROTOCOL_BY_DRIVER
273 if (Status
== EFI_ALREADY_STARTED
) {
277 if (!EFI_ERROR (Status
)) {
278 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
279 if (!EFI_ERROR (Status
)) {
280 if (!IS_PCI_16550_SERIAL (&Pci
)) {
281 for (PciSerialParameter
= (PCI_SERIAL_PARAMETER
*) PcdGetPtr (PcdPciSerialParameters
)
282 ; PciSerialParameter
->VendorId
!= 0xFFFF
283 ; PciSerialParameter
++
285 if ((Pci
.Hdr
.VendorId
== PciSerialParameter
->VendorId
) &&
286 (Pci
.Hdr
.DeviceId
== PciSerialParameter
->DeviceId
)
291 if (PciSerialParameter
->VendorId
== 0xFFFF) {
292 Status
= EFI_UNSUPPORTED
;
294 Status
= EFI_SUCCESS
;
300 // Close the I/O Abstraction(s) used to perform the supported test
304 &gEfiPciIoProtocolGuid
,
305 gSerialControllerDriver
.DriverBindingHandle
,
309 if (EFI_ERROR (Status
)) {
314 // Open the EFI Device Path protocol needed to perform the supported test
316 Status
= gBS
->OpenProtocol (
318 &gEfiDevicePathProtocolGuid
,
319 (VOID
**) &DevicePath
,
320 gSerialControllerDriver
.DriverBindingHandle
,
322 EFI_OPEN_PROTOCOL_BY_DRIVER
324 ASSERT (Status
!= EFI_ALREADY_STARTED
);
327 // Close protocol, don't use device path protocol in the Support() function
331 &gEfiDevicePathProtocolGuid
,
332 gSerialControllerDriver
.DriverBindingHandle
,
340 Check to see if this driver supports the given controller
342 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
343 @param Controller The handle of the controller to test.
344 @param RemainingDevicePath A pointer to the remaining portion of a device path.
346 @return EFI_SUCCESS This driver can support the given controller
351 SerialControllerDriverSupported (
352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
353 IN EFI_HANDLE Controller
,
354 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
359 UART_DEVICE_PATH
*Uart
;
360 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
363 // Test RemainingDevicePath
365 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
366 Status
= EFI_UNSUPPORTED
;
368 Uart
= SkipControllerDevicePathNode (RemainingDevicePath
, NULL
, NULL
);
369 if (DevicePathType (Uart
) != MESSAGING_DEVICE_PATH
||
370 DevicePathSubType (Uart
) != MSG_UART_DP
||
371 DevicePathNodeLength (Uart
) != sizeof (UART_DEVICE_PATH
)
373 return EFI_UNSUPPORTED
;
377 // Do a rough check because Clock Rate is unknown until DriverBindingStart()
379 if (!VerifyUartParameters (0, Uart
->BaudRate
, Uart
->DataBits
, Uart
->Parity
, Uart
->StopBits
, NULL
, NULL
)) {
380 return EFI_UNSUPPORTED
;
383 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
384 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
386 // If the second node is Flow Control Node,
387 // return error when it request other than hardware flow control.
389 if ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
390 return EFI_UNSUPPORTED
;
395 Status
= IsSioSerialController (Controller
);
396 if (EFI_ERROR (Status
)) {
397 Status
= IsPciSerialController (Controller
);
403 Create the child serial device instance.
405 @param Controller The parent controller handle.
406 @param Uart Pointer to the UART device path node in RemainingDevicePath,
407 or NULL if RemainingDevicePath is NULL.
408 @param ParentDevicePath Pointer to the parent device path.
409 @param CreateControllerNode TRUE to create the controller node.
410 @param Instance Instance number of the serial device.
411 The value will be set to the controller node
412 if CreateControllerNode is TRUE.
413 @param ParentIo A union type pointer to either Sio or PciIo.
414 @param PciSerialParameter The PCI serial parameter to be used by current serial device.
415 NULL for SIO serial device.
416 @param PciDeviceInfo The PCI device info for the current serial device.
417 NULL for SIO serial device.
419 @retval EFI_SUCCESS The serial device was created successfully.
420 @retval others The serial device wasn't created.
424 IN EFI_HANDLE Controller
,
425 IN UART_DEVICE_PATH
*Uart
,
426 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
427 IN BOOLEAN CreateControllerNode
,
429 IN PARENT_IO_PROTOCOL_PTR ParentIo
,
430 IN PCI_SERIAL_PARAMETER
*PciSerialParameter
, OPTIONAL
431 IN PCI_DEVICE_INFO
*PciDeviceInfo OPTIONAL
435 SERIAL_DEV
*SerialDevice
;
438 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
439 UINT32 FlowControlMap
;
440 ACPI_RESOURCE_HEADER_PTR Resources
;
441 EFI_ACPI_IO_PORT_DESCRIPTOR
*Io
;
442 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIo
;
443 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AddressSpace
;
444 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
452 // Initialize the serial device instance
454 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTemplate
);
455 ASSERT (SerialDevice
!= NULL
);
457 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
458 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
459 SerialDevice
->PciDeviceInfo
= PciDeviceInfo
;
460 SerialDevice
->Instance
= Instance
;
463 CopyMem (&SerialDevice
->UartDevicePath
, Uart
, sizeof (UART_DEVICE_PATH
));
464 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
465 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
466 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
473 // For PCI serial device, use the information from PCD
475 if (PciSerialParameter
!= NULL
) {
476 BarIndex
= (PciSerialParameter
->BarIndex
== PCI_BAR_ALL
) ? 0 : PciSerialParameter
->BarIndex
;
477 Offset
= PciSerialParameter
->Offset
;
478 if (PciSerialParameter
->RegisterStride
!= 0) {
479 SerialDevice
->RegisterStride
= PciSerialParameter
->RegisterStride
;
481 if (PciSerialParameter
->ClockRate
!= 0) {
482 SerialDevice
->ClockRate
= PciSerialParameter
->ClockRate
;
484 if (PciSerialParameter
->ReceiveFifoDepth
!= 0) {
485 SerialDevice
->ReceiveFifoDepth
= PciSerialParameter
->ReceiveFifoDepth
;
487 if (PciSerialParameter
->TransmitFifoDepth
!= 0) {
488 SerialDevice
->TransmitFifoDepth
= PciSerialParameter
->TransmitFifoDepth
;
493 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
494 // DriverBindingStart() shouldn't create a handle with different UART device path.
496 if (!VerifyUartParameters (SerialDevice
->ClockRate
, SerialDevice
->UartDevicePath
.BaudRate
, SerialDevice
->UartDevicePath
.DataBits
,
497 SerialDevice
->UartDevicePath
.Parity
, SerialDevice
->UartDevicePath
.StopBits
, NULL
, NULL
499 Status
= EFI_INVALID_PARAMETER
;
503 if (PciSerialParameter
== NULL
) {
504 Status
= ParentIo
.Sio
->GetResources (ParentIo
.Sio
, &Resources
);
506 Status
= ParentIo
.PciIo
->GetBarAttributes (ParentIo
.PciIo
, BarIndex
, NULL
, (VOID
**) &Resources
);
509 if (!EFI_ERROR (Status
)) {
511 // Get the base address information from ACPI resource descriptor.
512 // ACPI_IO_PORT_DESCRIPTOR and ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR are returned from Sio;
513 // ACPI_ADDRESS_SPACE_DESCRIPTOR is returned from PciIo.
515 while ((Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) && (SerialDevice
->BaseAddress
== 0)) {
516 switch (Resources
.SmallHeader
->Byte
) {
517 case ACPI_IO_PORT_DESCRIPTOR
:
518 Io
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
519 if (Io
->Length
!= 0) {
520 SerialDevice
->BaseAddress
= Io
->BaseAddressMin
;
524 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
525 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
526 if (FixedIo
->Length
!= 0) {
527 SerialDevice
->BaseAddress
= FixedIo
->BaseAddress
;
531 case ACPI_ADDRESS_SPACE_DESCRIPTOR
:
532 AddressSpace
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Resources
.SmallHeader
;
533 if (AddressSpace
->AddrLen
!= 0) {
534 if (AddressSpace
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
535 SerialDevice
->MmioAccess
= TRUE
;
537 SerialDevice
->BaseAddress
= AddressSpace
->AddrRangeMin
+ Offset
;
542 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
543 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) Resources
.SmallHeader
544 + Resources
.SmallHeader
->Bits
.Length
545 + sizeof (*Resources
.SmallHeader
));
547 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) Resources
.LargeHeader
548 + Resources
.LargeHeader
->Length
549 + sizeof (*Resources
.LargeHeader
));
554 if (SerialDevice
->BaseAddress
== 0) {
555 Status
= EFI_INVALID_PARAMETER
;
559 SerialDevice
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
562 // Report status code the serial present
564 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
566 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
567 SerialDevice
->ParentDevicePath
570 if (!SerialPresent (SerialDevice
)) {
571 Status
= EFI_DEVICE_ERROR
;
572 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
574 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
575 SerialDevice
->ParentDevicePath
581 // 1. Append Controller device path node.
583 if (CreateControllerNode
) {
584 mControllerDevicePathTemplate
.ControllerNumber
= SerialDevice
->Instance
;
585 SerialDevice
->DevicePath
= AppendDevicePathNode (
586 SerialDevice
->ParentDevicePath
,
587 (EFI_DEVICE_PATH_PROTOCOL
*) &mControllerDevicePathTemplate
589 SerialDevice
->ContainsControllerNode
= TRUE
;
593 // 2. Append UART device path node.
594 // The Uart setings are zero here.
595 // SetAttribute() will update them to match the default setings.
597 TempDevicePath
= SerialDevice
->DevicePath
;
598 if (TempDevicePath
!= NULL
) {
599 SerialDevice
->DevicePath
= AppendDevicePathNode (
601 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
603 FreePool (TempDevicePath
);
605 SerialDevice
->DevicePath
= AppendDevicePathNode (
606 SerialDevice
->ParentDevicePath
,
607 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
611 // 3. Append the Flow Control device path node.
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 ASSERT (SerialDevice
->DevicePath
!= NULL
);
627 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
629 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
630 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
631 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
632 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
635 // Issue a reset to initialize the COM port
637 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
638 if (EFI_ERROR (Status
)) {
639 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
641 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
642 SerialDevice
->DevicePath
647 AddName (SerialDevice
, Instance
);
649 // Install protocol interfaces for the serial device.
651 Status
= gBS
->InstallMultipleProtocolInterfaces (
652 &SerialDevice
->Handle
,
653 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
654 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
657 if (EFI_ERROR (Status
)) {
661 // Open For Child Device
663 Status
= gBS
->OpenProtocol (
665 PciSerialParameter
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
667 gSerialControllerDriver
.DriverBindingHandle
,
668 SerialDevice
->Handle
,
669 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
672 if (EFI_ERROR (Status
)) {
673 gBS
->UninstallMultipleProtocolInterfaces (
674 &SerialDevice
->Handle
,
675 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
676 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
682 if (EFI_ERROR (Status
)) {
683 if (SerialDevice
->DevicePath
!= NULL
) {
684 FreePool (SerialDevice
->DevicePath
);
686 if (SerialDevice
->ControllerNameTable
!= NULL
) {
687 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
689 FreePool (SerialDevice
);
695 Returns an array of pointers containing all the child serial device pointers.
697 @param Controller The parent controller handle.
698 @param IoProtocolGuid The protocol GUID, either equals to gEfiSioProtocolGuid
699 or equals to gEfiPciIoProtocolGuid.
700 @param Count Count of the serial devices.
702 @return An array of pointers containing all the child serial device pointers.
705 GetChildSerialDevices (
706 IN EFI_HANDLE Controller
,
707 IN EFI_GUID
*IoProtocolGuid
,
713 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
715 SERIAL_DEV
**SerialDevices
;
716 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
717 BOOLEAN OpenByDriver
;
721 // If the SerialIo instance specified by RemainingDevicePath is already created,
722 // update the attributes/control.
724 Status
= gBS
->OpenProtocolInformation (
730 if (EFI_ERROR (Status
)) {
734 SerialDevices
= AllocatePool (EntryCount
* sizeof (SERIAL_DEV
*));
735 ASSERT (SerialDevices
!= NULL
);
738 OpenByDriver
= FALSE
;
739 for (Index
= 0; Index
< EntryCount
; Index
++) {
740 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
741 Status
= gBS
->OpenProtocol (
742 OpenInfoBuffer
[Index
].ControllerHandle
,
743 &gEfiSerialIoProtocolGuid
,
745 gSerialControllerDriver
.DriverBindingHandle
,
747 EFI_OPEN_PROTOCOL_GET_PROTOCOL
749 if (!EFI_ERROR (Status
)) {
750 SerialDevices
[(*Count
)++] = SERIAL_DEV_FROM_THIS (SerialIo
);
755 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
756 ASSERT (OpenInfoBuffer
[Index
].AgentHandle
== gSerialControllerDriver
.DriverBindingHandle
);
760 if (OpenInfoBuffer
!= NULL
) {
761 FreePool (OpenInfoBuffer
);
764 ASSERT ((*Count
== 0) || (OpenByDriver
));
766 return SerialDevices
;
770 Start to management the controller passed in
772 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
773 @param Controller The handle of the controller to test.
774 @param RemainingDevicePath A pointer to the remaining portion of a device path.
776 @return EFI_SUCCESS Driver is started successfully
780 SerialControllerDriverStart (
781 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
782 IN EFI_HANDLE Controller
,
783 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
788 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
789 EFI_DEVICE_PATH_PROTOCOL
*Node
;
790 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
791 UINT32 ControllerNumber
;
792 UART_DEVICE_PATH
*Uart
;
793 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
795 PARENT_IO_PROTOCOL_PTR ParentIo
;
796 ACPI_HID_DEVICE_PATH
*Acpi
;
797 EFI_GUID
*IoProtocolGuid
;
798 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
799 PCI_SERIAL_PARAMETER DefaultPciSerialParameter
;
801 UINT32 PciSerialCount
;
802 SERIAL_DEV
**SerialDevices
;
803 UINTN SerialDeviceCount
;
804 PCI_DEVICE_INFO
*PciDeviceInfo
;
806 BOOLEAN ContainsControllerNode
;
809 // Get the Parent Device Path
811 Status
= gBS
->OpenProtocol (
813 &gEfiDevicePathProtocolGuid
,
814 (VOID
**) &ParentDevicePath
,
815 This
->DriverBindingHandle
,
817 EFI_OPEN_PROTOCOL_BY_DRIVER
819 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
823 // Report status code enable the serial
825 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
827 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
832 // Grab the IO abstraction we need to get any work done
834 IoProtocolGuid
= &gEfiSioProtocolGuid
;
835 Status
= gBS
->OpenProtocol (
839 This
->DriverBindingHandle
,
841 EFI_OPEN_PROTOCOL_BY_DRIVER
843 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
844 IoProtocolGuid
= &gEfiPciIoProtocolGuid
;
845 Status
= gBS
->OpenProtocol (
849 This
->DriverBindingHandle
,
851 EFI_OPEN_PROTOCOL_BY_DRIVER
854 ASSERT (!EFI_ERROR (Status
) || Status
== EFI_ALREADY_STARTED
);
857 // Do nothing for END device path node
859 if ((RemainingDevicePath
!= NULL
) && IsDevicePathEnd (RemainingDevicePath
)) {
863 ControllerNumber
= 0;
864 ContainsControllerNode
= FALSE
;
865 SerialDevices
= GetChildSerialDevices (Controller
, IoProtocolGuid
, &SerialDeviceCount
);
867 // If the SerialIo instance specified by RemainingDevicePath is already created,
868 // update the attributes/control.
870 if ((SerialDeviceCount
!= 0) && (RemainingDevicePath
!= NULL
)) {
871 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
872 for (Index
= 0; Index
< SerialDeviceCount
; Index
++) {
873 ASSERT ((SerialDevices
!= NULL
) && (SerialDevices
[Index
] != NULL
));
874 if ((!SerialDevices
[Index
]->ContainsControllerNode
&& !ContainsControllerNode
) ||
875 (SerialDevices
[Index
]->ContainsControllerNode
&& ContainsControllerNode
&& SerialDevices
[Index
]->Instance
== ControllerNumber
)
877 SerialIo
= &SerialDevices
[Index
]->SerialIo
;
878 Status
= EFI_INVALID_PARAMETER
;
880 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
881 // DriverBindingStart() shouldn't create a handle with different UART device path.
883 if (VerifyUartParameters (SerialDevices
[Index
]->ClockRate
, Uart
->BaudRate
, Uart
->DataBits
,
884 (EFI_PARITY_TYPE
) Uart
->Parity
, (EFI_STOP_BITS_TYPE
) Uart
->StopBits
, NULL
, NULL
)) {
885 Status
= SerialIo
->SetAttributes (
888 SerialIo
->Mode
->ReceiveFifoDepth
,
889 SerialIo
->Mode
->Timeout
,
890 (EFI_PARITY_TYPE
) Uart
->Parity
,
892 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
895 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
896 if (!EFI_ERROR (Status
) && IsUartFlowControlDevicePathNode (FlowControl
)) {
897 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
898 if (!EFI_ERROR (Status
)) {
899 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
900 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
902 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
905 // Clear the bits that are not allowed to pass to SetControl
907 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
908 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
909 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
910 Status
= SerialIo
->SetControl (SerialIo
, Control
);
916 if (Index
!= SerialDeviceCount
) {
918 // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated.
919 // Otherwise continue to create the instance specified by RemainingDevicePath.
921 if (SerialDevices
!= NULL
) {
922 FreePool (SerialDevices
);
928 if (RemainingDevicePath
!= NULL
) {
929 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
934 PciDeviceInfo
= NULL
;
935 if (IoProtocolGuid
== &gEfiSioProtocolGuid
) {
936 Status
= EFI_NOT_FOUND
;
937 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
938 Node
= ParentDevicePath
;
940 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
941 Node
= NextDevicePathNode (Node
);
942 } while (!IsDevicePathEnd (Node
));
943 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, Acpi
->UID
, ParentIo
, NULL
, NULL
);
944 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create SIO child serial device - %r\n", Status
));
947 Status
= ParentIo
.PciIo
->Pci
.Read (ParentIo
.PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
948 if (!EFI_ERROR (Status
)) {
950 // PcdPciSerialParameters takes the higher priority.
953 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
954 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
955 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
)
961 if (SerialDeviceCount
== 0) {
963 // Enable the IO & MEM decoding when creating the first child.
964 // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0).
966 PciDeviceInfo
= AllocatePool (sizeof (PCI_DEVICE_INFO
));
967 ASSERT (PciDeviceInfo
!= NULL
);
968 PciDeviceInfo
->ChildCount
= 0;
969 PciDeviceInfo
->PciIo
= ParentIo
.PciIo
;
970 Status
= ParentIo
.PciIo
->Attributes (
972 EfiPciIoAttributeOperationGet
,
974 &PciDeviceInfo
->PciAttributes
977 if (!EFI_ERROR (Status
)) {
978 Status
= ParentIo
.PciIo
->Attributes (
980 EfiPciIoAttributeOperationSupported
,
984 if (!EFI_ERROR (Status
)) {
985 Supports
&= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
);
986 Status
= ParentIo
.PciIo
->Attributes (
988 EfiPciIoAttributeOperationEnable
,
996 // Re-use the PciDeviceInfo stored in existing children.
998 ASSERT ((SerialDevices
!= NULL
) && (SerialDevices
[0] != NULL
));
999 PciDeviceInfo
= SerialDevices
[0]->PciDeviceInfo
;
1000 ASSERT (PciDeviceInfo
!= NULL
);
1003 Status
= EFI_NOT_FOUND
;
1004 if (PciSerialCount
<= 1) {
1006 // PCI serial device contains only one UART
1008 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
1010 // This PCI serial device is matched by class code in Supported()
1012 if (PciSerialCount
== 0) {
1013 DefaultPciSerialParameter
.VendorId
= Pci
.Hdr
.VendorId
;
1014 DefaultPciSerialParameter
.DeviceId
= Pci
.Hdr
.DeviceId
;
1015 DefaultPciSerialParameter
.BarIndex
= 0;
1016 DefaultPciSerialParameter
.Offset
= 0;
1017 DefaultPciSerialParameter
.RegisterStride
= 0;
1018 DefaultPciSerialParameter
.ClockRate
= 0;
1019 PciSerialParameter
= &DefaultPciSerialParameter
;
1020 } else if (PciSerialCount
== 1) {
1021 PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
);
1024 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, 0, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1025 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status
));
1026 if (!EFI_ERROR (Status
)) {
1027 PciDeviceInfo
->ChildCount
++;
1032 // PCI serial device contains multiple UARTs
1034 if (RemainingDevicePath
== NULL
|| ContainsControllerNode
) {
1036 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
1037 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
1038 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
) &&
1039 ((RemainingDevicePath
== NULL
) || (ControllerNumber
== PciSerialCount
))
1042 // Create controller node when PCI serial device contains multiple UARTs
1044 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, TRUE
, PciSerialCount
, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1046 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status
));
1047 if (!EFI_ERROR (Status
)) {
1048 PciDeviceInfo
->ChildCount
++;
1057 if (SerialDevices
!= NULL
) {
1058 FreePool (SerialDevices
);
1062 // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully
1064 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
!= 0)) {
1065 Status
= EFI_SUCCESS
;
1068 if (EFI_ERROR (Status
) && (SerialDeviceCount
== 0)) {
1069 if (PciDeviceInfo
!= NULL
) {
1070 Status
= ParentIo
.PciIo
->Attributes (
1072 EfiPciIoAttributeOperationSet
,
1073 PciDeviceInfo
->PciAttributes
,
1076 ASSERT_EFI_ERROR (Status
);
1077 FreePool (PciDeviceInfo
);
1079 gBS
->CloseProtocol (
1081 &gEfiDevicePathProtocolGuid
,
1082 This
->DriverBindingHandle
,
1085 gBS
->CloseProtocol (
1088 This
->DriverBindingHandle
,
1097 Disconnect this driver with the controller, uninstall related protocol instance
1099 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1100 @param Controller The handle of the controller to test.
1101 @param NumberOfChildren Number of child device.
1102 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
1104 @retval EFI_SUCCESS Operation successfully
1105 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
1110 SerialControllerDriverStop (
1111 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1112 IN EFI_HANDLE Controller
,
1113 IN UINTN NumberOfChildren
,
1114 IN EFI_HANDLE
*ChildHandleBuffer
1120 BOOLEAN AllChildrenStopped
;
1121 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1122 SERIAL_DEV
*SerialDevice
;
1124 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1125 PCI_DEVICE_INFO
*PciDeviceInfo
;
1127 PciDeviceInfo
= NULL
;
1129 Status
= gBS
->HandleProtocol (
1131 &gEfiDevicePathProtocolGuid
,
1132 (VOID
**) &DevicePath
1136 // Report the status code disable the serial
1138 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1140 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
1144 if (NumberOfChildren
== 0) {
1146 // Close the bus driver
1148 Status
= gBS
->OpenProtocol (
1150 &gEfiPciIoProtocolGuid
,
1152 This
->DriverBindingHandle
,
1154 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1156 gBS
->CloseProtocol (
1158 !EFI_ERROR (Status
) ? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1159 This
->DriverBindingHandle
,
1163 gBS
->CloseProtocol (
1165 &gEfiDevicePathProtocolGuid
,
1166 This
->DriverBindingHandle
,
1172 AllChildrenStopped
= TRUE
;
1174 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1176 Status
= gBS
->OpenProtocol (
1177 ChildHandleBuffer
[Index
],
1178 &gEfiSerialIoProtocolGuid
,
1179 (VOID
**) &SerialIo
,
1180 This
->DriverBindingHandle
,
1182 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1184 if (!EFI_ERROR (Status
)) {
1186 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
1187 ASSERT ((PciDeviceInfo
== NULL
) || (PciDeviceInfo
== SerialDevice
->PciDeviceInfo
));
1188 PciDeviceInfo
= SerialDevice
->PciDeviceInfo
;
1190 Status
= gBS
->CloseProtocol (
1192 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1193 This
->DriverBindingHandle
,
1194 ChildHandleBuffer
[Index
]
1197 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1198 ChildHandleBuffer
[Index
],
1199 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
1200 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
1203 if (EFI_ERROR (Status
)) {
1206 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1208 This
->DriverBindingHandle
,
1209 ChildHandleBuffer
[Index
],
1210 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1213 FreePool (SerialDevice
->DevicePath
);
1214 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
1215 FreePool (SerialDevice
);
1217 if (PciDeviceInfo
!= NULL
) {
1218 ASSERT (PciDeviceInfo
->ChildCount
!= 0);
1219 PciDeviceInfo
->ChildCount
--;
1224 if (EFI_ERROR (Status
)) {
1225 AllChildrenStopped
= FALSE
;
1229 if (!AllChildrenStopped
) {
1230 return EFI_DEVICE_ERROR
;
1233 // If all children are destroyed, restore the PCI attributes.
1235 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
== 0)) {
1236 ASSERT (PciDeviceInfo
->PciIo
!= NULL
);
1237 Status
= PciDeviceInfo
->PciIo
->Attributes (
1238 PciDeviceInfo
->PciIo
,
1239 EfiPciIoAttributeOperationSet
,
1240 PciDeviceInfo
->PciAttributes
,
1243 ASSERT_EFI_ERROR (Status
);
1244 FreePool (PciDeviceInfo
);