2 This driver module produces IDE_CONTROLLER_INIT protocol for Sata Controllers.
4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2018, ARM Ltd. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "SataController.h"
13 /// EFI_DRIVER_BINDING_PROTOCOL instance
15 EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding
= {
16 SataControllerSupported
,
25 Read AHCI Operation register.
27 @param PciIo The PCI IO protocol instance.
28 @param Offset The operation register offset.
30 @return The register content read.
36 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
42 ASSERT (PciIo
!= NULL
);
59 This function is used to calculate the best PIO mode supported by specific IDE device
61 @param IdentifyData The identify data of specific IDE device.
62 @param DisPioMode Disqualified PIO modes collection.
63 @param SelectedMode Available PIO modes collection.
65 @retval EFI_SUCCESS Best PIO modes are returned.
66 @retval EFI_UNSUPPORTED The device doesn't support PIO mode,
67 or all supported modes have been disqualified.
70 CalculateBestPioMode (
71 IN EFI_IDENTIFY_DATA
*IdentifyData
,
72 IN UINT16
*DisPioMode OPTIONAL
,
73 OUT UINT16
*SelectedMode
77 UINT16 AdvancedPioMode
;
80 UINT16 MinimumPioCycleTime
;
84 PioMode
= (UINT8
)(((ATA5_IDENTIFY_DATA
*)(&(IdentifyData
->AtaData
)))->pio_cycle_timing
>> 8);
87 // See whether Identify Data word 64 - 70 are valid
89 if ((IdentifyData
->AtaData
.field_validity
& 0x02) == 0x02) {
90 AdvancedPioMode
= IdentifyData
->AtaData
.advanced_pio_modes
;
91 DEBUG ((DEBUG_INFO
, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode
));
93 for (Index
= 0; Index
< 8; Index
++) {
94 if ((AdvancedPioMode
& 0x01) != 0) {
98 AdvancedPioMode
>>= 1;
102 // If Temp is modified, mean the advanced_pio_modes is not zero;
103 // if Temp is not modified, mean there is no advanced PIO mode supported,
104 // the best PIO Mode is the value in pio_cycle_timing.
107 AdvancedPioMode
= (UINT16
)(Temp
+ 3);
109 AdvancedPioMode
= PioMode
;
113 // Limit the PIO mode to at most PIO4.
115 PioMode
= (UINT16
)MIN (AdvancedPioMode
, 4);
117 MinimumPioCycleTime
= IdentifyData
->AtaData
.min_pio_cycle_time_with_flow_control
;
119 if (MinimumPioCycleTime
<= 120) {
120 PioMode
= (UINT16
)MIN (4, PioMode
);
121 } else if (MinimumPioCycleTime
<= 180) {
122 PioMode
= (UINT16
)MIN (3, PioMode
);
123 } else if (MinimumPioCycleTime
<= 240) {
124 PioMode
= (UINT16
)MIN (2, PioMode
);
130 // Degrade the PIO mode if the mode has been disqualified
132 if (DisPioMode
!= NULL
) {
133 if (*DisPioMode
< 2) {
134 return EFI_UNSUPPORTED
; // no mode below ATA_PIO_MODE_BELOW_2
137 if (PioMode
>= *DisPioMode
) {
138 PioMode
= (UINT16
)(*DisPioMode
- 1);
143 *SelectedMode
= 1; // ATA_PIO_MODE_BELOW_2;
145 *SelectedMode
= PioMode
; // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;
149 // Identify Data word 64 - 70 are not valid
150 // Degrade the PIO mode if the mode has been disqualified
152 if (DisPioMode
!= NULL
) {
153 if (*DisPioMode
< 2) {
154 return EFI_UNSUPPORTED
; // no mode below ATA_PIO_MODE_BELOW_2
157 if (PioMode
== *DisPioMode
) {
163 *SelectedMode
= 1; // ATA_PIO_MODE_BELOW_2;
165 *SelectedMode
= 2; // ATA_PIO_MODE_2;
173 This function is used to calculate the best UDMA mode supported by specific IDE device
175 @param IdentifyData The identify data of specific IDE device.
176 @param DisUDmaMode Disqualified UDMA modes collection.
177 @param SelectedMode Available UDMA modes collection.
179 @retval EFI_SUCCESS Best UDMA modes are returned.
180 @retval EFI_UNSUPPORTED The device doesn't support UDMA mode,
181 or all supported modes have been disqualified.
184 CalculateBestUdmaMode (
185 IN EFI_IDENTIFY_DATA
*IdentifyData
,
186 IN UINT16
*DisUDmaMode OPTIONAL
,
187 OUT UINT16
*SelectedMode
191 UINT16 DeviceUDmaMode
;
196 // Check whether the WORD 88 (supported UltraDMA by drive) is valid
198 if ((IdentifyData
->AtaData
.field_validity
& 0x04) == 0x00) {
199 return EFI_UNSUPPORTED
;
202 DeviceUDmaMode
= IdentifyData
->AtaData
.ultra_dma_mode
;
203 DEBUG ((DEBUG_INFO
, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode
));
204 DeviceUDmaMode
&= 0x3f;
205 TempMode
= 0; // initialize it to UDMA-0
207 while ((DeviceUDmaMode
>>= 1) != 0) {
212 // Degrade the UDMA mode if the mode has been disqualified
214 if (DisUDmaMode
!= NULL
) {
215 if (*DisUDmaMode
== 0) {
217 return EFI_UNSUPPORTED
; // no mode below ATA_UDMA_MODE_0
220 if (TempMode
>= *DisUDmaMode
) {
221 TempMode
= (UINT16
)(*DisUDmaMode
- 1);
226 // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5
228 *SelectedMode
= TempMode
;
234 The Entry Point of module. It follows the standard UEFI driver model.
236 @param[in] ImageHandle The firmware allocated handle for the EFI image.
237 @param[in] SystemTable A pointer to the EFI System Table.
239 @retval EFI_SUCCESS The entry point is executed successfully.
240 @retval other Some error occurs when executing this entry point.
245 InitializeSataControllerDriver (
246 IN EFI_HANDLE ImageHandle
,
247 IN EFI_SYSTEM_TABLE
*SystemTable
253 // Install driver model protocol(s).
255 Status
= EfiLibInstallDriverBindingComponentName2 (
258 &gSataControllerDriverBinding
,
260 &gSataControllerComponentName
,
261 &gSataControllerComponentName2
263 ASSERT_EFI_ERROR (Status
);
269 Supported function of Driver Binding protocol for this driver.
270 Test to see if this driver supports ControllerHandle.
272 @param This Protocol instance pointer.
273 @param Controller Handle of device to test.
274 @param RemainingDevicePath A pointer to the device path.
275 it should be ignored by device driver.
277 @retval EFI_SUCCESS This driver supports this device.
278 @retval EFI_ALREADY_STARTED This driver is already running on this device.
279 @retval other This driver does not support this device.
284 SataControllerSupported (
285 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
286 IN EFI_HANDLE Controller
,
287 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
291 EFI_PCI_IO_PROTOCOL
*PciIo
;
295 // Attempt to open PCI I/O Protocol
297 Status
= gBS
->OpenProtocol (
299 &gEfiPciIoProtocolGuid
,
301 This
->DriverBindingHandle
,
303 EFI_OPEN_PROTOCOL_GET_PROTOCOL
305 if (EFI_ERROR (Status
)) {
310 // Now further check the PCI header: Base Class (offset 0x0B) and
311 // Sub Class (offset 0x0A). This controller should be an SATA controller
313 Status
= PciIo
->Pci
.Read (
316 PCI_CLASSCODE_OFFSET
,
317 sizeof (PciData
.Hdr
.ClassCode
),
318 PciData
.Hdr
.ClassCode
320 if (EFI_ERROR (Status
)) {
321 return EFI_UNSUPPORTED
;
324 if (IS_PCI_IDE (&PciData
) || IS_PCI_SATADPA (&PciData
)) {
328 return EFI_UNSUPPORTED
;
332 This routine is called right after the .Supported() called and
333 Start this driver on ControllerHandle.
335 @param This Protocol instance pointer.
336 @param Controller Handle of device to bind driver to.
337 @param RemainingDevicePath A pointer to the device path.
338 it should be ignored by device driver.
340 @retval EFI_SUCCESS This driver is added to this device.
341 @retval EFI_ALREADY_STARTED This driver is already running on this device.
342 @retval other Some error occurs when binding this driver to this device.
347 SataControllerStart (
348 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
349 IN EFI_HANDLE Controller
,
350 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
354 EFI_PCI_IO_PROTOCOL
*PciIo
;
356 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
362 DEBUG ((DEBUG_INFO
, "SataControllerStart start\n"));
367 // Now test and open PCI I/O Protocol
369 Status
= gBS
->OpenProtocol (
371 &gEfiPciIoProtocolGuid
,
373 This
->DriverBindingHandle
,
375 EFI_OPEN_PROTOCOL_BY_DRIVER
377 if (EFI_ERROR (Status
)) {
378 DEBUG ((DEBUG_ERROR
, "SataControllerStart error. return status = %r\n", Status
));
383 // Allocate Sata Private Data structure
385 Private
= AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA
));
386 if (Private
== NULL
) {
387 Status
= EFI_OUT_OF_RESOURCES
;
392 // Initialize Sata Private Data
394 Private
->Signature
= SATA_CONTROLLER_SIGNATURE
;
395 Private
->PciIo
= PciIo
;
396 Private
->IdeInit
.GetChannelInfo
= IdeInitGetChannelInfo
;
397 Private
->IdeInit
.NotifyPhase
= IdeInitNotifyPhase
;
398 Private
->IdeInit
.SubmitData
= IdeInitSubmitData
;
399 Private
->IdeInit
.DisqualifyMode
= IdeInitDisqualifyMode
;
400 Private
->IdeInit
.CalculateMode
= IdeInitCalculateMode
;
401 Private
->IdeInit
.SetTiming
= IdeInitSetTiming
;
402 Private
->IdeInit
.EnumAll
= SATA_ENUMER_ALL
;
403 Private
->PciAttributesChanged
= FALSE
;
406 // Save original PCI attributes
408 Status
= PciIo
->Attributes (
410 EfiPciIoAttributeOperationGet
,
412 &Private
->OriginalPciAttributes
414 if (EFI_ERROR (Status
)) {
420 "Original PCI Attributes = 0x%llx\n",
421 Private
->OriginalPciAttributes
424 Status
= PciIo
->Attributes (
426 EfiPciIoAttributeOperationSupported
,
430 if (EFI_ERROR (Status
)) {
434 DEBUG ((DEBUG_INFO
, "Supported PCI Attributes = 0x%llx\n", Supports
));
436 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
437 Status
= PciIo
->Attributes (
439 EfiPciIoAttributeOperationEnable
,
443 if (EFI_ERROR (Status
)) {
447 DEBUG ((DEBUG_INFO
, "Enabled PCI Attributes = 0x%llx\n", Supports
));
448 Private
->PciAttributesChanged
= TRUE
;
450 Status
= PciIo
->Pci
.Read (
453 PCI_CLASSCODE_OFFSET
,
454 sizeof (PciData
.Hdr
.ClassCode
),
455 PciData
.Hdr
.ClassCode
457 if (EFI_ERROR (Status
)) {
462 if (IS_PCI_IDE (&PciData
)) {
463 Private
->IdeInit
.ChannelCount
= IDE_MAX_CHANNEL
;
464 Private
->DeviceCount
= IDE_MAX_DEVICES
;
465 } else if (IS_PCI_SATADPA (&PciData
)) {
467 // Read Ports Implemented(PI) to calculate max port number (0 based).
469 Data32
= AhciReadReg (PciIo
, R_AHCI_PI
);
470 DEBUG ((DEBUG_INFO
, "Ports Implemented(PI) = 0x%x\n", Data32
));
472 Status
= EFI_UNSUPPORTED
;
477 while (MaxPortNumber
> 0) {
478 if ((Data32
& ((UINT32
)1 << MaxPortNumber
)) != 0) {
486 // Make the ChannelCount equal to the max port number (0 based) plus 1.
488 Private
->IdeInit
.ChannelCount
= MaxPortNumber
+ 1;
491 // Read HBA Capabilities(CAP) to get Supports Port Multiplier(SPM).
493 Data32
= AhciReadReg (PciIo
, R_AHCI_CAP
);
494 DEBUG ((DEBUG_INFO
, "HBA Capabilities(CAP) = 0x%x\n", Data32
));
495 Private
->DeviceCount
= AHCI_MAX_DEVICES
;
496 if ((Data32
& B_AHCI_CAP_SPM
) == B_AHCI_CAP_SPM
) {
497 Private
->DeviceCount
= AHCI_MULTI_MAX_DEVICES
;
501 TotalCount
= (UINTN
)(Private
->IdeInit
.ChannelCount
) * (UINTN
)(Private
->DeviceCount
);
502 Private
->DisqualifiedModes
= AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE
)) * TotalCount
);
503 if (Private
->DisqualifiedModes
== NULL
) {
504 Status
= EFI_OUT_OF_RESOURCES
;
508 Private
->IdentifyData
= AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA
)) * TotalCount
);
509 if (Private
->IdentifyData
== NULL
) {
510 Status
= EFI_OUT_OF_RESOURCES
;
514 Private
->IdentifyValid
= AllocateZeroPool ((sizeof (BOOLEAN
)) * TotalCount
);
515 if (Private
->IdentifyValid
== NULL
) {
516 Status
= EFI_OUT_OF_RESOURCES
;
521 // Install IDE Controller Init Protocol to this instance
523 Status
= gBS
->InstallMultipleProtocolInterfaces (
525 &gEfiIdeControllerInitProtocolGuid
,
531 if (EFI_ERROR (Status
)) {
534 &gEfiPciIoProtocolGuid
,
535 This
->DriverBindingHandle
,
538 if (Private
!= NULL
) {
539 if (Private
->DisqualifiedModes
!= NULL
) {
540 FreePool (Private
->DisqualifiedModes
);
543 if (Private
->IdentifyData
!= NULL
) {
544 FreePool (Private
->IdentifyData
);
547 if (Private
->IdentifyValid
!= NULL
) {
548 FreePool (Private
->IdentifyValid
);
551 if (Private
->PciAttributesChanged
) {
553 // Restore original PCI attributes
557 EfiPciIoAttributeOperationSet
,
558 Private
->OriginalPciAttributes
,
567 DEBUG ((DEBUG_INFO
, "SataControllerStart end with %r\n", Status
));
573 Stop this driver on ControllerHandle.
575 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
576 @param Controller A handle to the device being stopped.
577 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
578 @param ChildHandleBuffer An array of child handles to be freed.
580 @retval EFI_SUCCESS This driver is removed from this device.
581 @retval other Some error occurs when removing this driver from this device.
587 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
588 IN EFI_HANDLE Controller
,
589 IN UINTN NumberOfChildren
,
590 IN EFI_HANDLE
*ChildHandleBuffer
594 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
595 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
598 // Open the produced protocol
600 Status
= gBS
->OpenProtocol (
602 &gEfiIdeControllerInitProtocolGuid
,
604 This
->DriverBindingHandle
,
606 EFI_OPEN_PROTOCOL_GET_PROTOCOL
608 if (EFI_ERROR (Status
)) {
609 return EFI_UNSUPPORTED
;
612 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit
);
613 ASSERT (Private
!= NULL
);
616 // Uninstall the IDE Controller Init Protocol from this instance
618 Status
= gBS
->UninstallMultipleProtocolInterfaces (
620 &gEfiIdeControllerInitProtocolGuid
,
624 if (EFI_ERROR (Status
)) {
628 if (Private
!= NULL
) {
629 if (Private
->DisqualifiedModes
!= NULL
) {
630 FreePool (Private
->DisqualifiedModes
);
633 if (Private
->IdentifyData
!= NULL
) {
634 FreePool (Private
->IdentifyData
);
637 if (Private
->IdentifyValid
!= NULL
) {
638 FreePool (Private
->IdentifyValid
);
641 if (Private
->PciAttributesChanged
) {
643 // Restore original PCI attributes
645 Private
->PciIo
->Attributes (
647 EfiPciIoAttributeOperationSet
,
648 Private
->OriginalPciAttributes
,
657 // Close protocols opened by Sata Controller driver
659 return gBS
->CloseProtocol (
661 &gEfiPciIoProtocolGuid
,
662 This
->DriverBindingHandle
,
668 Calculate the flat array subscript of a (Channel, Device) pair.
670 @param[in] Private The private data structure corresponding to the
671 SATA controller that attaches the device for
672 which the flat array subscript is being
675 @param[in] Channel The channel (ie. port) number on the SATA
676 controller that the device is attached to.
678 @param[in] Device The device number on the channel.
680 @return The flat array subscript suitable for indexing DisqualifiedModes,
681 IdentifyData, and IdentifyValid.
686 IN CONST EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
,
691 ASSERT (Private
!= NULL
);
692 ASSERT (Channel
< Private
->IdeInit
.ChannelCount
);
693 ASSERT (Device
< Private
->DeviceCount
);
695 return Channel
* Private
->DeviceCount
+ Device
;
699 // Interface functions of IDE_CONTROLLER_INIT protocol
703 Returns the information about the specified IDE channel.
705 This function can be used to obtain information about a particular IDE channel.
706 The driver entity uses this information during the enumeration process.
708 If Enabled is set to FALSE, the driver entity will not scan the channel. Note
709 that it will not prevent an operating system driver from scanning the channel.
711 For most of today's controllers, MaxDevices will either be 1 or 2. For SATA
712 controllers, this value will always be 1. SATA configurations can contain SATA
713 port multipliers. SATA port multipliers behave like SATA bridges and can support
714 up to 16 devices on the other side. If a SATA port out of the IDE controller
715 is connected to a port multiplier, MaxDevices will be set to the number of SATA
716 devices that the port multiplier supports. Because today's port multipliers
717 support up to fifteen SATA devices, this number can be as large as fifteen. The IDE
718 bus driver is required to scan for the presence of port multipliers behind an SATA
719 controller and enumerate up to MaxDevices number of devices behind the port
722 In this context, the devices behind a port multiplier constitute a channel.
724 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
725 @param[in] Channel Zero-based channel number.
726 @param[out] Enabled TRUE if this channel is enabled. Disabled channels
727 are not scanned to see if any devices are present.
728 @param[out] MaxDevices The maximum number of IDE devices that the bus driver
729 can expect on this channel. For the ATA/ATAPI
730 specification, version 6, this number will either be
731 one or two. For Serial ATA (SATA) configurations with a
732 port multiplier, this number can be as large as fifteen.
734 @retval EFI_SUCCESS Information was returned without any errors.
735 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
740 IdeInitGetChannelInfo (
741 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
743 OUT BOOLEAN
*Enabled
,
744 OUT UINT8
*MaxDevices
747 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
749 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
750 ASSERT (Private
!= NULL
);
752 if (Channel
< This
->ChannelCount
) {
754 *MaxDevices
= Private
->DeviceCount
;
759 return EFI_INVALID_PARAMETER
;
763 The notifications from the driver entity that it is about to enter a certain
764 phase of the IDE channel enumeration process.
766 This function can be used to notify the IDE controller driver to perform
767 specific actions, including any chipset-specific initialization, so that the
768 chipset is ready to enter the next phase. Seven notification points are defined
771 More synchronization points may be added as required in the future.
773 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL
775 @param[in] Phase The phase during enumeration.
776 @param[in] Channel Zero-based channel number.
778 @retval EFI_SUCCESS The notification was accepted without any errors.
779 @retval EFI_UNSUPPORTED Phase is not supported.
780 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
781 @retval EFI_NOT_READY This phase cannot be entered at this time; for
782 example, an attempt was made to enter a Phase
783 without having entered one or more previous
790 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
791 IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase
,
799 Submits the device information to the IDE controller driver.
801 This function is used by the driver entity to pass detailed information about
802 a particular device to the IDE controller driver. The driver entity obtains
803 this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
804 is the pointer to the response data buffer. The IdentifyData buffer is owned
805 by the driver entity, and the IDE controller driver must make a local copy
806 of the entire buffer or parts of the buffer as needed. The original IdentifyData
807 buffer pointer may not be valid when
809 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
810 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
812 The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to
813 compute the optimum mode for the device. These fields are not limited to the
814 timing information. For example, an implementation of the IDE controller driver
815 may examine the vendor and type/mode field to match known bad drives.
817 The driver entity may submit drive information in any order, as long as it
818 submits information for all the devices belonging to the enumeration group
819 before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
820 in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
821 should be called with IdentifyData set to NULL. The IDE controller driver may
822 not have any other mechanism to know whether a device is present or not. Therefore,
823 setting IdentifyData to NULL does not constitute an error condition.
824 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a
825 given (Channel, Device) pair.
827 @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
828 @param[in] Channel Zero-based channel number.
829 @param[in] Device Zero-based device number on the Channel.
830 @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command.
832 @retval EFI_SUCCESS The information was accepted without any errors.
833 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
834 @retval EFI_INVALID_PARAMETER Device is invalid.
840 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
843 IN EFI_IDENTIFY_DATA
*IdentifyData
846 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
849 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
850 ASSERT (Private
!= NULL
);
852 if ((Channel
>= This
->ChannelCount
) || (Device
>= Private
->DeviceCount
)) {
853 return EFI_INVALID_PARAMETER
;
856 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
859 // Make a local copy of device's IdentifyData and mark the valid flag
861 if (IdentifyData
!= NULL
) {
863 &(Private
->IdentifyData
[DeviceIndex
]),
865 sizeof (EFI_IDENTIFY_DATA
)
868 Private
->IdentifyValid
[DeviceIndex
] = TRUE
;
870 Private
->IdentifyValid
[DeviceIndex
] = FALSE
;
877 Disqualifies specific modes for an IDE device.
879 This function allows the driver entity or other drivers (such as platform
880 drivers) to reject certain timing modes and request the IDE controller driver
881 to recalculate modes. This function allows the driver entity and the IDE
882 controller driver to negotiate the timings on a per-device basis. This function
883 is useful in the case of drives that lie about their capabilities. An example
884 is when the IDE device fails to accept the timing modes that are calculated
885 by the IDE controller driver based on the response to the Identify Drive command.
887 If the driver entity does not want to limit the ATA timing modes and leave that
888 decision to the IDE controller driver, it can either not call this function for
889 the given device or call this function and set the Valid flag to FALSE for all
890 modes that are listed in EFI_ATA_COLLECTIVE_MODE.
892 The driver entity may disqualify modes for a device in any order and any number
895 This function can be called multiple times to invalidate multiple modes of the
896 same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI
897 specification for more information on PIO modes.
899 For Serial ATA (SATA) controllers, this member function can be used to disqualify
900 a higher transfer rate mode on a given channel. For example, a platform driver
901 may inform the IDE controller driver to not use second-generation (Gen2) speeds
902 for a certain SATA drive.
904 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
905 @param[in] Channel The zero-based channel number.
906 @param[in] Device The zero-based device number on the Channel.
907 @param[in] BadModes The modes that the device does not support and that
908 should be disqualified.
910 @retval EFI_SUCCESS The modes were accepted without any errors.
911 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
912 @retval EFI_INVALID_PARAMETER Device is invalid.
913 @retval EFI_INVALID_PARAMETER IdentifyData is NULL.
918 IdeInitDisqualifyMode (
919 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
922 IN EFI_ATA_COLLECTIVE_MODE
*BadModes
925 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
928 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
929 ASSERT (Private
!= NULL
);
931 if ((Channel
>= This
->ChannelCount
) || (BadModes
== NULL
) || (Device
>= Private
->DeviceCount
)) {
932 return EFI_INVALID_PARAMETER
;
935 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
938 // Record the disqualified modes per channel per device. From ATA/ATAPI spec,
939 // if a mode is not supported, the modes higher than it is also not supported.
942 &(Private
->DisqualifiedModes
[DeviceIndex
]),
944 sizeof (EFI_ATA_COLLECTIVE_MODE
)
951 Returns the information about the optimum modes for the specified IDE device.
953 This function is used by the driver entity to obtain the optimum ATA modes for
954 a specific device. The IDE controller driver takes into account the following
955 while calculating the mode:
956 - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
957 - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
959 The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
960 for all the devices that belong to an enumeration group before calling
961 EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.
963 The IDE controller driver will use controller- and possibly platform-specific
964 algorithms to arrive at SupportedModes. The IDE controller may base its
965 decision on user preferences and other considerations as well. This function
966 may be called multiple times because the driver entity may renegotiate the mode
967 with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
969 The driver entity may collect timing information for various devices in any
970 order. The driver entity is responsible for making sure that all the dependencies
971 are satisfied. For example, the SupportedModes information for device A that
972 was previously returned may become stale after a call to
973 EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
975 The buffer SupportedModes is allocated by the callee because the caller does
976 not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE
977 is defined in a way that allows for future extensibility and can be of variable
978 length. This memory pool should be deallocated by the caller when it is no
981 The IDE controller driver for a Serial ATA (SATA) controller can use this
982 member function to force a lower speed (first-generation [Gen1] speeds on a
983 second-generation [Gen2]-capable hardware). The IDE controller driver can
984 also allow the driver entity to stay with the speed that has been negotiated
985 by the physical layer.
987 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
988 @param[in] Channel A zero-based channel number.
989 @param[in] Device A zero-based device number on the Channel.
990 @param[out] SupportedModes The optimum modes for the device.
992 @retval EFI_SUCCESS SupportedModes was returned.
993 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
994 @retval EFI_INVALID_PARAMETER Device is invalid.
995 @retval EFI_INVALID_PARAMETER SupportedModes is NULL.
996 @retval EFI_NOT_READY Modes cannot be calculated due to a lack of
997 data. This error may happen if
998 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
999 and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData()
1000 were not called for at least one drive in the
1001 same enumeration group.
1006 IdeInitCalculateMode (
1007 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
1010 OUT EFI_ATA_COLLECTIVE_MODE
**SupportedModes
1013 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
1014 EFI_IDENTIFY_DATA
*IdentifyData
;
1015 BOOLEAN IdentifyValid
;
1016 EFI_ATA_COLLECTIVE_MODE
*DisqualifiedModes
;
1017 UINT16 SelectedMode
;
1021 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
1022 ASSERT (Private
!= NULL
);
1024 if ((Channel
>= This
->ChannelCount
) || (SupportedModes
== NULL
) || (Device
>= Private
->DeviceCount
)) {
1025 return EFI_INVALID_PARAMETER
;
1028 *SupportedModes
= AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE
));
1029 if (*SupportedModes
== NULL
) {
1030 ASSERT (*SupportedModes
!= NULL
);
1031 return EFI_OUT_OF_RESOURCES
;
1034 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
1036 IdentifyData
= &(Private
->IdentifyData
[DeviceIndex
]);
1037 IdentifyValid
= Private
->IdentifyValid
[DeviceIndex
];
1038 DisqualifiedModes
= &(Private
->DisqualifiedModes
[DeviceIndex
]);
1041 // Make sure we've got the valid identify data of the device from SubmitData()
1043 if (!IdentifyValid
) {
1044 FreePool (*SupportedModes
);
1045 return EFI_NOT_READY
;
1048 Status
= CalculateBestPioMode (
1050 (DisqualifiedModes
->PioMode
.Valid
? ((UINT16
*)&(DisqualifiedModes
->PioMode
.Mode
)) : NULL
),
1053 if (!EFI_ERROR (Status
)) {
1054 (*SupportedModes
)->PioMode
.Valid
= TRUE
;
1055 (*SupportedModes
)->PioMode
.Mode
= SelectedMode
;
1057 (*SupportedModes
)->PioMode
.Valid
= FALSE
;
1060 DEBUG ((DEBUG_INFO
, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes
)->PioMode
.Mode
));
1062 Status
= CalculateBestUdmaMode (
1064 (DisqualifiedModes
->UdmaMode
.Valid
? ((UINT16
*)&(DisqualifiedModes
->UdmaMode
.Mode
)) : NULL
),
1068 if (!EFI_ERROR (Status
)) {
1069 (*SupportedModes
)->UdmaMode
.Valid
= TRUE
;
1070 (*SupportedModes
)->UdmaMode
.Mode
= SelectedMode
;
1072 (*SupportedModes
)->UdmaMode
.Valid
= FALSE
;
1075 DEBUG ((DEBUG_INFO
, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes
)->UdmaMode
.Mode
));
1078 // The modes other than PIO and UDMA are not supported
1084 Commands the IDE controller driver to program the IDE controller hardware
1085 so that the specified device can operate at the specified mode.
1087 This function is used by the driver entity to instruct the IDE controller
1088 driver to program the IDE controller hardware to the specified modes. This
1089 function can be called only once for a particular device. For a Serial ATA
1090 (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
1091 specific programming may be required.
1093 @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
1094 @param[in] Channel Zero-based channel number.
1095 @param[in] Device Zero-based device number on the Channel.
1096 @param[in] Modes The modes to set.
1098 @retval EFI_SUCCESS The command was accepted without any errors.
1099 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
1100 @retval EFI_INVALID_PARAMETER Device is invalid.
1101 @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data.
1102 @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure.
1103 The driver entity should not use this device.
1109 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
1112 IN EFI_ATA_COLLECTIVE_MODE
*Modes