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
= {
34 sizeof (CONTROLLER_DEVICE_PATH
),
40 SERIAL_DEV gSerialDevTemplate
= {
44 SERIAL_IO_INTERFACE_REVISION
,
54 SERIAL_PORT_SUPPORT_CONTROL_MASK
,
55 SERIAL_PORT_DEFAULT_TIMEOUT
,
63 NULL
, // ParentDevicePath
66 MESSAGING_DEVICE_PATH
,
69 (UINT8
) (sizeof (UART_DEVICE_PATH
)),
70 (UINT8
) ((sizeof (UART_DEVICE_PATH
)) >> 8)
79 16, // ReceiveFifoDepth
81 16, // TransmitFifoDepth
82 { 0, 0 }, // Transmit;
83 FALSE
, // SoftwareLoopbackEnable;
84 FALSE
, // HardwareFlowControl;
85 NULL
, // *ControllerNameTable;
86 FALSE
, // ContainsControllerNode;
88 NULL
// *PciDeviceInfo;
92 Check the device path node whether it's the Flow Control node or not.
94 @param[in] FlowControl The device path node to be checked.
96 @retval TRUE It's the Flow Control node.
97 @retval FALSE It's not.
101 IsUartFlowControlDevicePathNode (
102 IN UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
106 (DevicePathType (FlowControl
) == MESSAGING_DEVICE_PATH
) &&
107 (DevicePathSubType (FlowControl
) == MSG_VENDOR_DP
) &&
108 (CompareGuid (&FlowControl
->Guid
, &gEfiUartDevicePathGuid
))
113 The user Entry Point for module PciSioSerial. The user code starts with this function.
115 @param[in] ImageHandle The firmware allocated handle for the EFI image.
116 @param[in] SystemTable A pointer to the EFI System Table.
118 @retval EFI_SUCCESS The entry point is executed successfully.
119 @retval other Some error occurs when executing this entry point.
124 InitializePciSioSerial (
125 IN EFI_HANDLE ImageHandle
,
126 IN EFI_SYSTEM_TABLE
*SystemTable
132 // Install driver model protocol(s).
134 Status
= EfiLibInstallDriverBindingComponentName2 (
137 &gSerialControllerDriver
,
139 &gPciSioSerialComponentName
,
140 &gPciSioSerialComponentName2
142 ASSERT_EFI_ERROR (Status
);
145 // Initialize UART default setting in gSerialDevTempate
147 gSerialDevTemplate
.SerialMode
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
148 gSerialDevTemplate
.SerialMode
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
149 gSerialDevTemplate
.SerialMode
.Parity
= PcdGet8 (PcdUartDefaultParity
);
150 gSerialDevTemplate
.SerialMode
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
151 gSerialDevTemplate
.UartDevicePath
.BaudRate
= PcdGet64 (PcdUartDefaultBaudRate
);
152 gSerialDevTemplate
.UartDevicePath
.DataBits
= PcdGet8 (PcdUartDefaultDataBits
);
153 gSerialDevTemplate
.UartDevicePath
.Parity
= PcdGet8 (PcdUartDefaultParity
);
154 gSerialDevTemplate
.UartDevicePath
.StopBits
= PcdGet8 (PcdUartDefaultStopBits
);
155 gSerialDevTemplate
.ClockRate
= PcdGet32 (PcdSerialClockRate
);
161 Return whether the controller is a SIO serial controller.
163 @param Controller The controller handle.
165 @retval EFI_SUCCESS The controller is a SIO serial controller.
166 @retval others The controller is not a SIO serial controller.
169 IsSioSerialController (
170 EFI_HANDLE Controller
174 EFI_SIO_PROTOCOL
*Sio
;
175 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
176 ACPI_HID_DEVICE_PATH
*Acpi
;
179 // Open the IO Abstraction(s) needed to perform the supported test
181 Status
= gBS
->OpenProtocol (
183 &gEfiSioProtocolGuid
,
185 gSerialControllerDriver
.DriverBindingHandle
,
187 EFI_OPEN_PROTOCOL_BY_DRIVER
189 if (Status
== EFI_ALREADY_STARTED
) {
193 if (!EFI_ERROR (Status
)) {
195 // Close the I/O Abstraction(s) used to perform the supported test
199 &gEfiSioProtocolGuid
,
200 gSerialControllerDriver
.DriverBindingHandle
,
204 Status
= gBS
->OpenProtocol (
206 &gEfiDevicePathProtocolGuid
,
207 (VOID
**) &DevicePath
,
208 gSerialControllerDriver
.DriverBindingHandle
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 ASSERT (Status
!= EFI_ALREADY_STARTED
);
214 if (!EFI_ERROR (Status
)) {
216 Acpi
= (ACPI_HID_DEVICE_PATH
*) DevicePath
;
217 DevicePath
= NextDevicePathNode (DevicePath
);
218 } while (!IsDevicePathEnd (DevicePath
));
220 if (DevicePathType (Acpi
) != ACPI_DEVICE_PATH
||
221 (DevicePathSubType (Acpi
) != ACPI_DP
&& DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
) ||
222 Acpi
->HID
!= EISA_PNP_ID (0x501)
224 Status
= EFI_UNSUPPORTED
;
229 // Close protocol, don't use device path protocol in the Support() function
233 &gEfiDevicePathProtocolGuid
,
234 gSerialControllerDriver
.DriverBindingHandle
,
242 Return whether the controller is a PCI serial controller.
244 @param Controller The controller handle.
246 @retval EFI_SUCCESS The controller is a PCI serial controller.
247 @retval others The controller is not a PCI serial controller.
250 IsPciSerialController (
251 EFI_HANDLE Controller
255 EFI_PCI_IO_PROTOCOL
*PciIo
;
256 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
258 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
261 // Open the IO Abstraction(s) needed to perform the supported test
263 Status
= gBS
->OpenProtocol (
265 &gEfiPciIoProtocolGuid
,
267 gSerialControllerDriver
.DriverBindingHandle
,
269 EFI_OPEN_PROTOCOL_BY_DRIVER
271 if (Status
== EFI_ALREADY_STARTED
) {
275 if (!EFI_ERROR (Status
)) {
276 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
277 if (!EFI_ERROR (Status
)) {
278 if (!IS_PCI_16550_SERIAL (&Pci
)) {
279 for (PciSerialParameter
= (PCI_SERIAL_PARAMETER
*) PcdGetPtr (PcdPciSerialParameters
)
280 ; PciSerialParameter
->VendorId
!= 0xFFFF
281 ; PciSerialParameter
++
283 if ((Pci
.Hdr
.VendorId
== PciSerialParameter
->VendorId
) &&
284 (Pci
.Hdr
.DeviceId
== PciSerialParameter
->DeviceId
)
289 if (PciSerialParameter
->VendorId
== 0xFFFF) {
290 Status
= EFI_UNSUPPORTED
;
292 Status
= EFI_SUCCESS
;
298 // Close the I/O Abstraction(s) used to perform the supported test
302 &gEfiPciIoProtocolGuid
,
303 gSerialControllerDriver
.DriverBindingHandle
,
307 if (EFI_ERROR (Status
)) {
312 // Open the EFI Device Path protocol needed to perform the supported test
314 Status
= gBS
->OpenProtocol (
316 &gEfiDevicePathProtocolGuid
,
317 (VOID
**) &DevicePath
,
318 gSerialControllerDriver
.DriverBindingHandle
,
320 EFI_OPEN_PROTOCOL_BY_DRIVER
322 ASSERT (Status
!= EFI_ALREADY_STARTED
);
325 // Close protocol, don't use device path protocol in the Support() function
329 &gEfiDevicePathProtocolGuid
,
330 gSerialControllerDriver
.DriverBindingHandle
,
338 Check to see if this driver supports the given controller
340 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
341 @param Controller The handle of the controller to test.
342 @param RemainingDevicePath A pointer to the remaining portion of a device path.
344 @return EFI_SUCCESS This driver can support the given controller
349 SerialControllerDriverSupported (
350 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
351 IN EFI_HANDLE Controller
,
352 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
357 UART_DEVICE_PATH
*Uart
;
358 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
361 // Test RemainingDevicePath
363 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
364 Status
= EFI_UNSUPPORTED
;
366 Uart
= SkipControllerDevicePathNode (RemainingDevicePath
, NULL
, NULL
);
367 if (DevicePathType (Uart
) != MESSAGING_DEVICE_PATH
||
368 DevicePathSubType (Uart
) != MSG_UART_DP
||
369 DevicePathNodeLength (Uart
) != sizeof (UART_DEVICE_PATH
)
371 return EFI_UNSUPPORTED
;
375 // Do a rough check because Clock Rate is unknown until DriverBindingStart()
377 if (!VerifyUartParameters (0, Uart
->BaudRate
, Uart
->DataBits
, Uart
->Parity
, Uart
->StopBits
, NULL
, NULL
)) {
378 return EFI_UNSUPPORTED
;
381 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
382 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
384 // If the second node is Flow Control Node,
385 // return error when it request other than hardware flow control.
387 if ((ReadUnaligned32 (&FlowControl
->FlowControlMap
) & ~UART_FLOW_CONTROL_HARDWARE
) != 0) {
388 return EFI_UNSUPPORTED
;
393 Status
= IsSioSerialController (Controller
);
394 if (EFI_ERROR (Status
)) {
395 Status
= IsPciSerialController (Controller
);
401 Create the child serial device instance.
403 @param Controller The parent controller handle.
404 @param Uart Pointer to the UART device path node in RemainingDevicePath,
405 or NULL if RemainingDevicePath is NULL.
406 @param ParentDevicePath Pointer to the parent device path.
407 @param CreateControllerNode TRUE to create the controller node.
408 @param Instance Instance number of the serial device.
409 The value will be set to the controller node
410 if CreateControllerNode is TRUE.
411 @param ParentIo A union type pointer to either Sio or PciIo.
412 @param PciSerialParameter The PCI serial parameter to be used by current serial device.
413 NULL for SIO serial device.
414 @param PciDeviceInfo The PCI device info for the current serial device.
415 NULL for SIO serial device.
417 @retval EFI_SUCCESS The serial device was created successfully.
418 @retval others The serial device wasn't created.
422 IN EFI_HANDLE Controller
,
423 IN UART_DEVICE_PATH
*Uart
,
424 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
425 IN BOOLEAN CreateControllerNode
,
427 IN PARENT_IO_PROTOCOL_PTR ParentIo
,
428 IN PCI_SERIAL_PARAMETER
*PciSerialParameter
, OPTIONAL
429 IN PCI_DEVICE_INFO
*PciDeviceInfo OPTIONAL
433 SERIAL_DEV
*SerialDevice
;
436 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
437 UINT32 FlowControlMap
;
438 ACPI_RESOURCE_HEADER_PTR Resources
;
439 EFI_ACPI_IO_PORT_DESCRIPTOR
*Io
;
440 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIo
;
441 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*AddressSpace
;
442 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
450 // Initialize the serial device instance
452 SerialDevice
= AllocateCopyPool (sizeof (SERIAL_DEV
), &gSerialDevTemplate
);
453 ASSERT (SerialDevice
!= NULL
);
455 SerialDevice
->SerialIo
.Mode
= &(SerialDevice
->SerialMode
);
456 SerialDevice
->ParentDevicePath
= ParentDevicePath
;
457 SerialDevice
->PciDeviceInfo
= PciDeviceInfo
;
458 SerialDevice
->Instance
= Instance
;
461 CopyMem (&SerialDevice
->UartDevicePath
, Uart
, sizeof (UART_DEVICE_PATH
));
462 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
463 if (IsUartFlowControlDevicePathNode (FlowControl
)) {
464 FlowControlMap
= ReadUnaligned32 (&FlowControl
->FlowControlMap
);
471 // For PCI serial device, use the information from PCD
473 if (PciSerialParameter
!= NULL
) {
474 BarIndex
= (PciSerialParameter
->BarIndex
== PCI_BAR_ALL
) ? 0 : PciSerialParameter
->BarIndex
;
475 Offset
= PciSerialParameter
->Offset
;
476 if (PciSerialParameter
->RegisterStride
!= 0) {
477 SerialDevice
->RegisterStride
= PciSerialParameter
->RegisterStride
;
479 if (PciSerialParameter
->ClockRate
!= 0) {
480 SerialDevice
->ClockRate
= PciSerialParameter
->ClockRate
;
482 if (PciSerialParameter
->ReceiveFifoDepth
!= 0) {
483 SerialDevice
->ReceiveFifoDepth
= PciSerialParameter
->ReceiveFifoDepth
;
485 if (PciSerialParameter
->TransmitFifoDepth
!= 0) {
486 SerialDevice
->TransmitFifoDepth
= PciSerialParameter
->TransmitFifoDepth
;
491 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
492 // DriverBindingStart() shouldn't create a handle with different UART device path.
494 if (!VerifyUartParameters (SerialDevice
->ClockRate
, SerialDevice
->UartDevicePath
.BaudRate
, SerialDevice
->UartDevicePath
.DataBits
,
495 SerialDevice
->UartDevicePath
.Parity
, SerialDevice
->UartDevicePath
.StopBits
, NULL
, NULL
497 Status
= EFI_INVALID_PARAMETER
;
501 if (PciSerialParameter
== NULL
) {
502 Status
= ParentIo
.Sio
->GetResources (ParentIo
.Sio
, &Resources
);
504 Status
= ParentIo
.PciIo
->GetBarAttributes (ParentIo
.PciIo
, BarIndex
, NULL
, (VOID
**) &Resources
);
507 if (!EFI_ERROR (Status
)) {
509 // Get the base address information from ACPI resource descriptor.
510 // ACPI_IO_PORT_DESCRIPTOR and ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR are returned from Sio;
511 // ACPI_ADDRESS_SPACE_DESCRIPTOR is returned from PciIo.
513 while ((Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) && (SerialDevice
->BaseAddress
== 0)) {
514 switch (Resources
.SmallHeader
->Byte
) {
515 case ACPI_IO_PORT_DESCRIPTOR
:
516 Io
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
517 if (Io
->Length
!= 0) {
518 SerialDevice
->BaseAddress
= Io
->BaseAddressMin
;
522 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
523 FixedIo
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
524 if (FixedIo
->Length
!= 0) {
525 SerialDevice
->BaseAddress
= FixedIo
->BaseAddress
;
529 case ACPI_ADDRESS_SPACE_DESCRIPTOR
:
530 AddressSpace
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Resources
.SmallHeader
;
531 if (AddressSpace
->AddrLen
!= 0) {
532 if (AddressSpace
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
533 SerialDevice
->MmioAccess
= TRUE
;
535 SerialDevice
->BaseAddress
= AddressSpace
->AddrRangeMin
+ Offset
;
540 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
541 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) Resources
.SmallHeader
542 + Resources
.SmallHeader
->Bits
.Length
543 + sizeof (*Resources
.SmallHeader
));
545 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) Resources
.LargeHeader
546 + Resources
.LargeHeader
->Length
547 + sizeof (*Resources
.LargeHeader
));
552 if (SerialDevice
->BaseAddress
== 0) {
553 Status
= EFI_INVALID_PARAMETER
;
557 SerialDevice
->HardwareFlowControl
= (BOOLEAN
) (FlowControlMap
== UART_FLOW_CONTROL_HARDWARE
);
560 // Report status code the serial present
562 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
564 EFI_P_PC_PRESENCE_DETECT
| EFI_PERIPHERAL_SERIAL_PORT
,
565 SerialDevice
->ParentDevicePath
568 if (!SerialPresent (SerialDevice
)) {
569 Status
= EFI_DEVICE_ERROR
;
570 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
572 EFI_P_EC_NOT_DETECTED
| EFI_PERIPHERAL_SERIAL_PORT
,
573 SerialDevice
->ParentDevicePath
579 // 1. Append Controller device path node.
581 if (CreateControllerNode
) {
582 mControllerDevicePathTemplate
.ControllerNumber
= SerialDevice
->Instance
;
583 SerialDevice
->DevicePath
= AppendDevicePathNode (
584 SerialDevice
->ParentDevicePath
,
585 (EFI_DEVICE_PATH_PROTOCOL
*) &mControllerDevicePathTemplate
587 SerialDevice
->ContainsControllerNode
= TRUE
;
591 // 2. Append UART device path node.
592 // The Uart setings are zero here.
593 // SetAttribute() will update them to match the default setings.
595 TempDevicePath
= SerialDevice
->DevicePath
;
596 if (TempDevicePath
!= NULL
) {
597 SerialDevice
->DevicePath
= AppendDevicePathNode (
599 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
601 FreePool (TempDevicePath
);
603 SerialDevice
->DevicePath
= AppendDevicePathNode (
604 SerialDevice
->ParentDevicePath
,
605 (EFI_DEVICE_PATH_PROTOCOL
*) &SerialDevice
->UartDevicePath
609 // 3. Append the Flow Control device path node.
610 // Only produce the Flow Control node when remaining device path has it
612 if (FlowControl
!= NULL
) {
613 TempDevicePath
= SerialDevice
->DevicePath
;
614 if (TempDevicePath
!= NULL
) {
615 SerialDevice
->DevicePath
= AppendDevicePathNode (
617 (EFI_DEVICE_PATH_PROTOCOL
*) FlowControl
619 FreePool (TempDevicePath
);
622 ASSERT (SerialDevice
->DevicePath
!= NULL
);
625 // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
627 SerialDevice
->SerialMode
.BaudRate
= SerialDevice
->UartDevicePath
.BaudRate
;
628 SerialDevice
->SerialMode
.DataBits
= SerialDevice
->UartDevicePath
.DataBits
;
629 SerialDevice
->SerialMode
.Parity
= SerialDevice
->UartDevicePath
.Parity
;
630 SerialDevice
->SerialMode
.StopBits
= SerialDevice
->UartDevicePath
.StopBits
;
633 // Issue a reset to initialize the COM port
635 Status
= SerialDevice
->SerialIo
.Reset (&SerialDevice
->SerialIo
);
636 if (EFI_ERROR (Status
)) {
637 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
639 EFI_P_EC_CONTROLLER_ERROR
| EFI_PERIPHERAL_SERIAL_PORT
,
640 SerialDevice
->DevicePath
645 AddName (SerialDevice
, Instance
);
647 // Install protocol interfaces for the serial device.
649 Status
= gBS
->InstallMultipleProtocolInterfaces (
650 &SerialDevice
->Handle
,
651 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
652 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
655 if (EFI_ERROR (Status
)) {
659 // Open For Child Device
661 Status
= gBS
->OpenProtocol (
663 PciSerialParameter
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
665 gSerialControllerDriver
.DriverBindingHandle
,
666 SerialDevice
->Handle
,
667 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
670 if (EFI_ERROR (Status
)) {
671 gBS
->UninstallMultipleProtocolInterfaces (
672 &SerialDevice
->Handle
,
673 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
674 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
680 if (EFI_ERROR (Status
)) {
681 if (SerialDevice
->DevicePath
!= NULL
) {
682 FreePool (SerialDevice
->DevicePath
);
684 if (SerialDevice
->ControllerNameTable
!= NULL
) {
685 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
687 FreePool (SerialDevice
);
693 Returns an array of pointers containing all the child serial device pointers.
695 @param Controller The parent controller handle.
696 @param IoProtocolGuid The protocol GUID, either equals to gEfiSioProtocolGuid
697 or equals to gEfiPciIoProtocolGuid.
698 @param Count Count of the serial devices.
700 @return An array of pointers containing all the child serial device pointers.
703 GetChildSerialDevices (
704 IN EFI_HANDLE Controller
,
705 IN EFI_GUID
*IoProtocolGuid
,
711 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
713 SERIAL_DEV
**SerialDevices
;
714 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
715 BOOLEAN OpenByDriver
;
719 // If the SerialIo instance specified by RemainingDevicePath is already created,
720 // update the attributes/control.
722 Status
= gBS
->OpenProtocolInformation (
728 if (EFI_ERROR (Status
)) {
732 SerialDevices
= AllocatePool (EntryCount
* sizeof (SERIAL_DEV
*));
733 ASSERT (SerialDevices
!= NULL
);
736 OpenByDriver
= FALSE
;
737 for (Index
= 0; Index
< EntryCount
; Index
++) {
738 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
739 Status
= gBS
->OpenProtocol (
740 OpenInfoBuffer
[Index
].ControllerHandle
,
741 &gEfiSerialIoProtocolGuid
,
743 gSerialControllerDriver
.DriverBindingHandle
,
745 EFI_OPEN_PROTOCOL_GET_PROTOCOL
747 if (!EFI_ERROR (Status
)) {
748 SerialDevices
[(*Count
)++] = SERIAL_DEV_FROM_THIS (SerialIo
);
753 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
754 ASSERT (OpenInfoBuffer
[Index
].AgentHandle
== gSerialControllerDriver
.DriverBindingHandle
);
758 if (OpenInfoBuffer
!= NULL
) {
759 FreePool (OpenInfoBuffer
);
762 ASSERT ((*Count
== 0) || (OpenByDriver
));
764 return SerialDevices
;
768 Start to management the controller passed in
770 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
771 @param Controller The handle of the controller to test.
772 @param RemainingDevicePath A pointer to the remaining portion of a device path.
774 @return EFI_SUCCESS Driver is started successfully
778 SerialControllerDriverStart (
779 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
780 IN EFI_HANDLE Controller
,
781 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
786 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
787 EFI_DEVICE_PATH_PROTOCOL
*Node
;
788 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
789 UINT32 ControllerNumber
;
790 UART_DEVICE_PATH
*Uart
;
791 UART_FLOW_CONTROL_DEVICE_PATH
*FlowControl
;
793 PARENT_IO_PROTOCOL_PTR ParentIo
;
794 ACPI_HID_DEVICE_PATH
*Acpi
;
795 EFI_GUID
*IoProtocolGuid
;
796 PCI_SERIAL_PARAMETER
*PciSerialParameter
;
797 PCI_SERIAL_PARAMETER DefaultPciSerialParameter
;
799 UINT32 PciSerialCount
;
800 SERIAL_DEV
**SerialDevices
;
801 UINTN SerialDeviceCount
;
802 PCI_DEVICE_INFO
*PciDeviceInfo
;
804 BOOLEAN ContainsControllerNode
;
807 // Get the Parent Device Path
809 Status
= gBS
->OpenProtocol (
811 &gEfiDevicePathProtocolGuid
,
812 (VOID
**) &ParentDevicePath
,
813 This
->DriverBindingHandle
,
815 EFI_OPEN_PROTOCOL_BY_DRIVER
817 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
821 // Report status code enable the serial
823 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
825 EFI_P_PC_ENABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
830 // Grab the IO abstraction we need to get any work done
832 IoProtocolGuid
= &gEfiSioProtocolGuid
;
833 Status
= gBS
->OpenProtocol (
837 This
->DriverBindingHandle
,
839 EFI_OPEN_PROTOCOL_BY_DRIVER
841 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
842 IoProtocolGuid
= &gEfiPciIoProtocolGuid
;
843 Status
= gBS
->OpenProtocol (
847 This
->DriverBindingHandle
,
849 EFI_OPEN_PROTOCOL_BY_DRIVER
852 ASSERT (!EFI_ERROR (Status
) || Status
== EFI_ALREADY_STARTED
);
855 // Do nothing for END device path node
857 if ((RemainingDevicePath
!= NULL
) && IsDevicePathEnd (RemainingDevicePath
)) {
862 SerialDevices
= GetChildSerialDevices (Controller
, IoProtocolGuid
, &SerialDeviceCount
);
864 // If the SerialIo instance specified by RemainingDevicePath is already created,
865 // update the attributes/control.
867 if ((SerialDeviceCount
!= 0) && (RemainingDevicePath
!= NULL
)) {
868 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
869 for (Index
= 0; Index
< SerialDeviceCount
; Index
++) {
870 if ((!SerialDevices
[Index
]->ContainsControllerNode
&& !ContainsControllerNode
) ||
871 (SerialDevices
[Index
]->ContainsControllerNode
&& ContainsControllerNode
&& SerialDevices
[Index
]->Instance
== ControllerNumber
)
873 Status
= EFI_INVALID_PARAMETER
;
875 // Pass NULL ActualBaudRate to VerifyUartParameters to disallow baudrate degrade.
876 // DriverBindingStart() shouldn't create a handle with different UART device path.
878 if (VerifyUartParameters (SerialDevices
[Index
]->ClockRate
, Uart
->BaudRate
, Uart
->DataBits
,
879 (EFI_PARITY_TYPE
) Uart
->Parity
, (EFI_STOP_BITS_TYPE
) Uart
->StopBits
, NULL
, NULL
)) {
880 SerialIo
= &SerialDevices
[Index
]->SerialIo
;
881 Status
= SerialIo
->SetAttributes (
884 SerialIo
->Mode
->ReceiveFifoDepth
,
885 SerialIo
->Mode
->Timeout
,
886 (EFI_PARITY_TYPE
) Uart
->Parity
,
888 (EFI_STOP_BITS_TYPE
) Uart
->StopBits
891 FlowControl
= (UART_FLOW_CONTROL_DEVICE_PATH
*) NextDevicePathNode (Uart
);
892 if (!EFI_ERROR (Status
) && IsUartFlowControlDevicePathNode (FlowControl
)) {
893 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
894 if (!EFI_ERROR (Status
)) {
895 if (ReadUnaligned32 (&FlowControl
->FlowControlMap
) == UART_FLOW_CONTROL_HARDWARE
) {
896 Control
|= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
898 Control
&= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
;
901 // Clear the bits that are not allowed to pass to SetControl
903 Control
&= (EFI_SERIAL_REQUEST_TO_SEND
| EFI_SERIAL_DATA_TERMINAL_READY
|
904 EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE
| EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE
|
905 EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
);
906 Status
= SerialIo
->SetControl (SerialIo
, Control
);
912 if (Index
!= SerialDeviceCount
) {
914 // Directly return if the SerialIo instance specified by RemainingDevicePath is found and updated.
915 // Otherwise continue to create the instance specified by RemainingDevicePath.
917 if (SerialDevices
!= NULL
) {
918 FreePool (SerialDevices
);
924 if (RemainingDevicePath
!= NULL
) {
925 Uart
= (UART_DEVICE_PATH
*) SkipControllerDevicePathNode (RemainingDevicePath
, &ContainsControllerNode
, &ControllerNumber
);
930 PciDeviceInfo
= NULL
;
931 if (IoProtocolGuid
== &gEfiSioProtocolGuid
) {
932 Status
= EFI_NOT_FOUND
;
933 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
934 Node
= ParentDevicePath
;
936 Acpi
= (ACPI_HID_DEVICE_PATH
*) Node
;
937 Node
= NextDevicePathNode (Node
);
938 } while (!IsDevicePathEnd (Node
));
939 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, Acpi
->UID
, ParentIo
, NULL
, NULL
);
940 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create SIO child serial device - %r\n", Status
));
943 Status
= ParentIo
.PciIo
->Pci
.Read (ParentIo
.PciIo
, EfiPciIoWidthUint8
, 0, sizeof (Pci
), &Pci
);
944 if (!EFI_ERROR (Status
)) {
946 // PcdPciSerialParameters takes the higher priority.
949 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
950 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
951 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
)
957 if (SerialDeviceCount
== 0) {
959 // Enable the IO & MEM decoding when creating the first child.
960 // Restore the PCI attributes when all children is destroyed (PciDeviceInfo->ChildCount == 0).
962 PciDeviceInfo
= AllocatePool (sizeof (PCI_DEVICE_INFO
));
963 PciDeviceInfo
->ChildCount
= 0;
964 PciDeviceInfo
->PciIo
= ParentIo
.PciIo
;
965 Status
= ParentIo
.PciIo
->Attributes (
967 EfiPciIoAttributeOperationGet
,
969 &PciDeviceInfo
->PciAttributes
972 if (!EFI_ERROR (Status
)) {
973 Status
= ParentIo
.PciIo
->Attributes (
975 EfiPciIoAttributeOperationSupported
,
979 if (!EFI_ERROR (Status
)) {
980 Supports
&= EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
;
981 Status
= ParentIo
.PciIo
->Attributes (
983 EfiPciIoAttributeOperationEnable
,
991 // Re-use the PciDeviceInfo stored in existing children.
993 PciDeviceInfo
= SerialDevices
[0]->PciDeviceInfo
;
994 ASSERT (PciDeviceInfo
!= NULL
);
997 Status
= EFI_NOT_FOUND
;
998 if (PciSerialCount
<= 1) {
1000 // PCI serial device contains only one UART
1002 if (RemainingDevicePath
== NULL
|| !ContainsControllerNode
) {
1004 // This PCI serial device is matched by class code in Supported()
1006 if (PciSerialCount
== 0) {
1007 DefaultPciSerialParameter
.VendorId
= Pci
.Hdr
.VendorId
;
1008 DefaultPciSerialParameter
.DeviceId
= Pci
.Hdr
.DeviceId
;
1009 DefaultPciSerialParameter
.BarIndex
= 0;
1010 DefaultPciSerialParameter
.Offset
= 0;
1011 DefaultPciSerialParameter
.RegisterStride
= 0;
1012 DefaultPciSerialParameter
.ClockRate
= 0;
1013 PciSerialParameter
= &DefaultPciSerialParameter
;
1014 } else if (PciSerialCount
== 1) {
1015 PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
);
1018 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, FALSE
, 0, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1019 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (single) - %r\n", Status
));
1020 if (!EFI_ERROR (Status
)) {
1021 PciDeviceInfo
->ChildCount
++;
1026 // PCI serial device contains multiple UARTs
1028 if (RemainingDevicePath
== NULL
|| ContainsControllerNode
) {
1030 for (PciSerialParameter
= PcdGetPtr (PcdPciSerialParameters
); PciSerialParameter
->VendorId
!= 0xFFFF; PciSerialParameter
++) {
1031 if ((PciSerialParameter
->VendorId
== Pci
.Hdr
.VendorId
) &&
1032 (PciSerialParameter
->DeviceId
== Pci
.Hdr
.DeviceId
) &&
1033 ((RemainingDevicePath
== NULL
) || (ControllerNumber
== PciSerialCount
))
1036 // Create controller node when PCI serial device contains multiple UARTs
1038 Status
= CreateSerialDevice (Controller
, Uart
, ParentDevicePath
, TRUE
, PciSerialCount
, ParentIo
, PciSerialParameter
, PciDeviceInfo
);
1040 DEBUG ((EFI_D_INFO
, "PciSioSerial: Create PCI child serial device (multiple) - %r\n", Status
));
1041 if (!EFI_ERROR (Status
)) {
1042 PciDeviceInfo
->ChildCount
++;
1051 if (SerialDevices
!= NULL
) {
1052 FreePool (SerialDevices
);
1056 // For multiple PCI serial devices, set Status to SUCCESS if one child is created successfully
1058 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
!= 0)) {
1059 Status
= EFI_SUCCESS
;
1062 if (EFI_ERROR (Status
) && (SerialDeviceCount
== 0)) {
1063 if (PciDeviceInfo
!= NULL
) {
1064 Status
= ParentIo
.PciIo
->Attributes (
1066 EfiPciIoAttributeOperationSet
,
1067 PciDeviceInfo
->PciAttributes
,
1070 ASSERT_EFI_ERROR (Status
);
1071 FreePool (PciDeviceInfo
);
1073 gBS
->CloseProtocol (
1075 &gEfiDevicePathProtocolGuid
,
1076 This
->DriverBindingHandle
,
1079 gBS
->CloseProtocol (
1082 This
->DriverBindingHandle
,
1091 Disconnect this driver with the controller, uninstall related protocol instance
1093 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1094 @param Controller The handle of the controller to test.
1095 @param NumberOfChildren Number of child device.
1096 @param ChildHandleBuffer A pointer to the remaining portion of a device path.
1098 @retval EFI_SUCCESS Operation successfully
1099 @retval EFI_DEVICE_ERROR Cannot stop the driver successfully
1104 SerialControllerDriverStop (
1105 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1106 IN EFI_HANDLE Controller
,
1107 IN UINTN NumberOfChildren
,
1108 IN EFI_HANDLE
*ChildHandleBuffer
1114 BOOLEAN AllChildrenStopped
;
1115 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
1116 SERIAL_DEV
*SerialDevice
;
1118 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1119 PCI_DEVICE_INFO
*PciDeviceInfo
;
1121 PciDeviceInfo
= NULL
;
1123 Status
= gBS
->HandleProtocol (
1125 &gEfiDevicePathProtocolGuid
,
1126 (VOID
**) &DevicePath
1130 // Report the status code disable the serial
1132 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1134 EFI_P_PC_DISABLE
| EFI_PERIPHERAL_SERIAL_PORT
,
1138 if (NumberOfChildren
== 0) {
1140 // Close the bus driver
1142 Status
= gBS
->OpenProtocol (
1144 &gEfiPciIoProtocolGuid
,
1146 This
->DriverBindingHandle
,
1148 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1150 gBS
->CloseProtocol (
1152 !EFI_ERROR (Status
) ? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1153 This
->DriverBindingHandle
,
1157 gBS
->CloseProtocol (
1159 &gEfiDevicePathProtocolGuid
,
1160 This
->DriverBindingHandle
,
1166 AllChildrenStopped
= TRUE
;
1168 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1170 Status
= gBS
->OpenProtocol (
1171 ChildHandleBuffer
[Index
],
1172 &gEfiSerialIoProtocolGuid
,
1173 (VOID
**) &SerialIo
,
1174 This
->DriverBindingHandle
,
1176 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1178 if (!EFI_ERROR (Status
)) {
1180 SerialDevice
= SERIAL_DEV_FROM_THIS (SerialIo
);
1181 ASSERT ((PciDeviceInfo
== NULL
) || (PciDeviceInfo
== SerialDevice
->PciDeviceInfo
));
1182 PciDeviceInfo
= SerialDevice
->PciDeviceInfo
;
1184 Status
= gBS
->CloseProtocol (
1186 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1187 This
->DriverBindingHandle
,
1188 ChildHandleBuffer
[Index
]
1191 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1192 ChildHandleBuffer
[Index
],
1193 &gEfiDevicePathProtocolGuid
, SerialDevice
->DevicePath
,
1194 &gEfiSerialIoProtocolGuid
, &SerialDevice
->SerialIo
,
1197 if (EFI_ERROR (Status
)) {
1200 PciDeviceInfo
!= NULL
? &gEfiPciIoProtocolGuid
: &gEfiSioProtocolGuid
,
1202 This
->DriverBindingHandle
,
1203 ChildHandleBuffer
[Index
],
1204 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1207 FreePool (SerialDevice
->DevicePath
);
1208 FreeUnicodeStringTable (SerialDevice
->ControllerNameTable
);
1209 FreePool (SerialDevice
);
1211 if (PciDeviceInfo
!= NULL
) {
1212 ASSERT (PciDeviceInfo
->ChildCount
!= 0);
1213 PciDeviceInfo
->ChildCount
--;
1218 if (EFI_ERROR (Status
)) {
1219 AllChildrenStopped
= FALSE
;
1223 if (!AllChildrenStopped
) {
1224 return EFI_DEVICE_ERROR
;
1227 // If all children are destroyed, restore the PCI attributes.
1229 if ((PciDeviceInfo
!= NULL
) && (PciDeviceInfo
->ChildCount
== 0)) {
1230 ASSERT (PciDeviceInfo
->PciIo
!= NULL
);
1231 Status
= PciDeviceInfo
->PciIo
->Attributes (
1232 PciDeviceInfo
->PciIo
,
1233 EfiPciIoAttributeOperationSet
,
1234 PciDeviceInfo
->PciAttributes
,
1237 ASSERT_EFI_ERROR (Status
);
1238 FreePool (PciDeviceInfo
);