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 if ((!SerialDevices
[Index
]->ContainsControllerNode
&& !ContainsControllerNode
) ||
874 (SerialDevices
[Index
]->ContainsControllerNode
&& ContainsControllerNode
&& SerialDevices
[Index
]->Instance
== ControllerNumber
)
876 SerialIo
= &SerialDevices
[Index
]->SerialIo
;
877 Status
= EFI_INVALID_PARAMETER
;
879 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
880 // DriverBindingStart() shouldn't create a handle with different UART device path.
882 if (VerifyUartParameters (SerialDevices
[Index
]->ClockRate
, Uart
->BaudRate
, Uart
->DataBits
,
883 (EFI_PARITY_TYPE
) Uart
->Parity
, (EFI_STOP_BITS_TYPE
) Uart
->StopBits
, NULL
, NULL
)) {
884 Status
= SerialIo
->SetAttributes (
887 SerialIo
->Mode
->ReceiveFifoDepth
,
888 SerialIo
->Mode
->Timeout
,
889 (EFI_PARITY_TYPE
) Uart
->Parity
,
891 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
894 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
895 if (!EFI_ERROR (Status
) && IsUartFlowControlDevicePathNode (FlowControl
)) {
896 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
897 if (!EFI_ERROR (Status
)) {
898 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
899 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
901 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
904 // Clear the bits that are not allowed to pass to SetControl
906 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
907 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
908 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
909 Status
= SerialIo
->SetControl (SerialIo
, Control
);
915 if (Index
!= SerialDeviceCount
) {
917 // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated.
918 // Otherwise continue to create the instance specified by RemainingDevicePath.
920 if (SerialDevices
!= NULL
) {
921 FreePool (SerialDevices
);
927 if (RemainingDevicePath
!= NULL
) {
928 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
933 PciDeviceInfo
= NULL
;
934 if (IoProtocolGuid
== &gEfiSioProtocolGuid
) {
935 Status
= EFI_NOT_FOUND
;
936 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
937 Node
= ParentDevicePath
;
939 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
940 Node
= NextDevicePathNode (Node
);
941 } while (!IsDevicePathEnd (Node
));
942 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, Acpi
->UID
, ParentIo
, NULL
, NULL
);
943 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create SIO child serial device - %r\n", Status
));
946 Status
= ParentIo
.PciIo
->Pci
.Read (ParentIo
.PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
947 if (!EFI_ERROR (Status
)) {
949 // PcdPciSerialParameters takes the higher priority.
952 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
953 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
954 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
)
960 if (SerialDeviceCount
== 0) {
962 // Enable the IO & MEM decoding when creating the first child.
963 // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0).
965 PciDeviceInfo
= AllocatePool (sizeof (PCI_DEVICE_INFO
));
966 PciDeviceInfo
->ChildCount
= 0;
967 PciDeviceInfo
->PciIo
= ParentIo
.PciIo
;
968 Status
= ParentIo
.PciIo
->Attributes (
970 EfiPciIoAttributeOperationGet
,
972 &PciDeviceInfo
->PciAttributes
975 if (!EFI_ERROR (Status
)) {
976 Status
= ParentIo
.PciIo
->Attributes (
978 EfiPciIoAttributeOperationSupported
,
982 if (!EFI_ERROR (Status
)) {
983 Supports
&= EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
;
984 Status
= ParentIo
.PciIo
->Attributes (
986 EfiPciIoAttributeOperationEnable
,
994 // Re-use the PciDeviceInfo stored in existing children.
996 PciDeviceInfo
= SerialDevices
[0]->PciDeviceInfo
;
997 ASSERT (PciDeviceInfo
!= NULL
);
1000 Status
= EFI_NOT_FOUND
;
1001 if (PciSerialCount
<= 1) {
1003 // PCI serial device contains only one UART
1005 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
1007 // This PCI serial device is matched by class code in Supported()
1009 if (PciSerialCount
== 0) {
1010 DefaultPciSerialParameter
.VendorId
= Pci
.Hdr
.VendorId
;
1011 DefaultPciSerialParameter
.DeviceId
= Pci
.Hdr
.DeviceId
;
1012 DefaultPciSerialParameter
.BarIndex
= 0;
1013 DefaultPciSerialParameter
.Offset
= 0;
1014 DefaultPciSerialParameter
.RegisterStride
= 0;
1015 DefaultPciSerialParameter
.ClockRate
= 0;
1016 PciSerialParameter
= &DefaultPciSerialParameter
;
1017 } else if (PciSerialCount
== 1) {
1018 PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
);
1021 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, 0, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1022 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status
));
1023 if (!EFI_ERROR (Status
)) {
1024 PciDeviceInfo
->ChildCount
++;
1029 // PCI serial device contains multiple UARTs
1031 if (RemainingDevicePath
== NULL
|| ContainsControllerNode
) {
1033 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
1034 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
1035 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
) &&
1036 ((RemainingDevicePath
== NULL
) || (ControllerNumber
== PciSerialCount
))
1039 // Create controller node when PCI serial device contains multiple UARTs
1041 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, TRUE
, PciSerialCount
, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1043 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status
));
1044 if (!EFI_ERROR (Status
)) {
1045 PciDeviceInfo
->ChildCount
++;
1054 if (SerialDevices
!= NULL
) {
1055 FreePool (SerialDevices
);
1059 // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully
1061 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
!= 0)) {
1062 Status
= EFI_SUCCESS
;
1065 if (EFI_ERROR (Status
) && (SerialDeviceCount
== 0)) {
1066 if (PciDeviceInfo
!= NULL
) {
1067 Status
= ParentIo
.PciIo
->Attributes (
1069 EfiPciIoAttributeOperationSet
,
1070 PciDeviceInfo
->PciAttributes
,
1073 ASSERT_EFI_ERROR (Status
);
1074 FreePool (PciDeviceInfo
);
1076 gBS
->CloseProtocol (
1078 &gEfiDevicePathProtocolGuid
,
1079 This
->DriverBindingHandle
,
1082 gBS
->CloseProtocol (
1085 This
->DriverBindingHandle
,
1094 Disconnect this driver with the controller, uninstall related protocol instance
1096 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1097 @param Controller The handle of the controller to test.
1098 @param NumberOfChildren Number of child device.
1099 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
1101 @retval EFI_SUCCESS Operation successfully
1102 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
1107 SerialControllerDriverStop (
1108 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1109 IN EFI_HANDLE Controller
,
1110 IN UINTN NumberOfChildren
,
1111 IN EFI_HANDLE
*ChildHandleBuffer
1117 BOOLEAN AllChildrenStopped
;
1118 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1119 SERIAL_DEV
*SerialDevice
;
1121 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1122 PCI_DEVICE_INFO
*PciDeviceInfo
;
1124 PciDeviceInfo
= NULL
;
1126 Status
= gBS
->HandleProtocol (
1128 &gEfiDevicePathProtocolGuid
,
1129 (VOID
**) &DevicePath
1133 // Report the status code disable the serial
1135 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1137 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
1141 if (NumberOfChildren
== 0) {
1143 // Close the bus driver
1145 Status
= gBS
->OpenProtocol (
1147 &gEfiPciIoProtocolGuid
,
1149 This
->DriverBindingHandle
,
1151 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1153 gBS
->CloseProtocol (
1155 !EFI_ERROR (Status
) ? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1156 This
->DriverBindingHandle
,
1160 gBS
->CloseProtocol (
1162 &gEfiDevicePathProtocolGuid
,
1163 This
->DriverBindingHandle
,
1169 AllChildrenStopped
= TRUE
;
1171 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1173 Status
= gBS
->OpenProtocol (
1174 ChildHandleBuffer
[Index
],
1175 &gEfiSerialIoProtocolGuid
,
1176 (VOID
**) &SerialIo
,
1177 This
->DriverBindingHandle
,
1179 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1181 if (!EFI_ERROR (Status
)) {
1183 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
1184 ASSERT ((PciDeviceInfo
== NULL
) || (PciDeviceInfo
== SerialDevice
->PciDeviceInfo
));
1185 PciDeviceInfo
= SerialDevice
->PciDeviceInfo
;
1187 Status
= gBS
->CloseProtocol (
1189 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1190 This
->DriverBindingHandle
,
1191 ChildHandleBuffer
[Index
]
1194 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1195 ChildHandleBuffer
[Index
],
1196 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
1197 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
1200 if (EFI_ERROR (Status
)) {
1203 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1205 This
->DriverBindingHandle
,
1206 ChildHandleBuffer
[Index
],
1207 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1210 FreePool (SerialDevice
->DevicePath
);
1211 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
1212 FreePool (SerialDevice
);
1214 if (PciDeviceInfo
!= NULL
) {
1215 ASSERT (PciDeviceInfo
->ChildCount
!= 0);
1216 PciDeviceInfo
->ChildCount
--;
1221 if (EFI_ERROR (Status
)) {
1222 AllChildrenStopped
= FALSE
;
1226 if (!AllChildrenStopped
) {
1227 return EFI_DEVICE_ERROR
;
1230 // If all children are destroyed, restore the PCI attributes.
1232 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
== 0)) {
1233 ASSERT (PciDeviceInfo
->PciIo
!= NULL
);
1234 Status
= PciDeviceInfo
->PciIo
->Attributes (
1235 PciDeviceInfo
->PciIo
,
1236 EfiPciIoAttributeOperationSet
,
1237 PciDeviceInfo
->PciAttributes
,
1240 ASSERT_EFI_ERROR (Status
);
1241 FreePool (PciDeviceInfo
);