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) {
91 AdvancedPioMode
= IdentifyData
->AtaData
.advanced_pio_modes
;
92 DEBUG ((EFI_D_INFO
, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode
));
94 for (Index
= 0; Index
< 8; Index
++) {
95 if ((AdvancedPioMode
& 0x01) != 0) {
99 AdvancedPioMode
>>= 1;
103 // If Temp is modified, mean the advanced_pio_modes is not zero;
104 // if Temp is not modified, mean there is no advanced PIO mode supported,
105 // the best PIO Mode is the value in pio_cycle_timing.
108 AdvancedPioMode
= (UINT16
) (Temp
+ 3);
110 AdvancedPioMode
= PioMode
;
114 // Limit the PIO mode to at most PIO4.
116 PioMode
= (UINT16
) MIN (AdvancedPioMode
, 4);
118 MinimumPioCycleTime
= IdentifyData
->AtaData
.min_pio_cycle_time_with_flow_control
;
120 if (MinimumPioCycleTime
<= 120) {
121 PioMode
= (UINT16
) MIN (4, PioMode
);
122 } else if (MinimumPioCycleTime
<= 180) {
123 PioMode
= (UINT16
) MIN (3, PioMode
);
124 } else if (MinimumPioCycleTime
<= 240) {
125 PioMode
= (UINT16
) MIN (2, PioMode
);
131 // Degrade the PIO mode if the mode has been disqualified
133 if (DisPioMode
!= NULL
) {
134 if (*DisPioMode
< 2) {
135 return EFI_UNSUPPORTED
; // no mode below ATA_PIO_MODE_BELOW_2
138 if (PioMode
>= *DisPioMode
) {
139 PioMode
= (UINT16
) (*DisPioMode
- 1);
144 *SelectedMode
= 1; // ATA_PIO_MODE_BELOW_2;
146 *SelectedMode
= PioMode
; // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;
151 // Identify Data word 64 - 70 are not valid
152 // Degrade the PIO mode if the mode has been disqualified
154 if (DisPioMode
!= NULL
) {
155 if (*DisPioMode
< 2) {
156 return EFI_UNSUPPORTED
; // no mode below ATA_PIO_MODE_BELOW_2
159 if (PioMode
== *DisPioMode
) {
165 *SelectedMode
= 1; // ATA_PIO_MODE_BELOW_2;
167 *SelectedMode
= 2; // ATA_PIO_MODE_2;
176 This function is used to calculate the best UDMA mode supported by specific IDE device
178 @param IdentifyData The identify data of specific IDE device.
179 @param DisUDmaMode Disqualified UDMA modes collection.
180 @param SelectedMode Available UDMA modes collection.
182 @retval EFI_SUCCESS Best UDMA modes are returned.
183 @retval EFI_UNSUPPORTED The device doesn't support UDMA mode,
184 or all supported modes have been disqualified.
187 CalculateBestUdmaMode (
188 IN EFI_IDENTIFY_DATA
*IdentifyData
,
189 IN UINT16
*DisUDmaMode OPTIONAL
,
190 OUT UINT16
*SelectedMode
194 UINT16 DeviceUDmaMode
;
199 // Check whether the WORD 88 (supported UltraDMA by drive) is valid
201 if ((IdentifyData
->AtaData
.field_validity
& 0x04) == 0x00) {
202 return EFI_UNSUPPORTED
;
205 DeviceUDmaMode
= IdentifyData
->AtaData
.ultra_dma_mode
;
206 DEBUG ((EFI_D_INFO
, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode
));
207 DeviceUDmaMode
&= 0x3f;
208 TempMode
= 0; // initialize it to UDMA-0
210 while ((DeviceUDmaMode
>>= 1) != 0) {
215 // Degrade the UDMA mode if the mode has been disqualified
217 if (DisUDmaMode
!= NULL
) {
218 if (*DisUDmaMode
== 0) {
220 return EFI_UNSUPPORTED
; // no mode below ATA_UDMA_MODE_0
223 if (TempMode
>= *DisUDmaMode
) {
224 TempMode
= (UINT16
) (*DisUDmaMode
- 1);
229 // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5
231 *SelectedMode
= TempMode
;
237 The Entry Point of module. It follows the standard UEFI driver model.
239 @param[in] ImageHandle The firmware allocated handle for the EFI image.
240 @param[in] SystemTable A pointer to the EFI System Table.
242 @retval EFI_SUCCESS The entry point is executed successfully.
243 @retval other Some error occurs when executing this entry point.
248 InitializeSataControllerDriver (
249 IN EFI_HANDLE ImageHandle
,
250 IN EFI_SYSTEM_TABLE
*SystemTable
256 // Install driver model protocol(s).
258 Status
= EfiLibInstallDriverBindingComponentName2 (
261 &gSataControllerDriverBinding
,
263 &gSataControllerComponentName
,
264 &gSataControllerComponentName2
266 ASSERT_EFI_ERROR (Status
);
272 Supported function of Driver Binding protocol for this driver.
273 Test to see if this driver supports ControllerHandle.
275 @param This Protocol instance pointer.
276 @param Controller Handle of device to test.
277 @param RemainingDevicePath A pointer to the device path.
278 it should be ignored by device driver.
280 @retval EFI_SUCCESS This driver supports this device.
281 @retval EFI_ALREADY_STARTED This driver is already running on this device.
282 @retval other This driver does not support this device.
287 SataControllerSupported (
288 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
289 IN EFI_HANDLE Controller
,
290 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
294 EFI_PCI_IO_PROTOCOL
*PciIo
;
298 // Attempt to open PCI I/O Protocol
300 Status
= gBS
->OpenProtocol (
302 &gEfiPciIoProtocolGuid
,
304 This
->DriverBindingHandle
,
306 EFI_OPEN_PROTOCOL_GET_PROTOCOL
308 if (EFI_ERROR (Status
)) {
313 // Now further check the PCI header: Base Class (offset 0x0B) and
314 // Sub Class (offset 0x0A). This controller should be an SATA controller
316 Status
= PciIo
->Pci
.Read (
319 PCI_CLASSCODE_OFFSET
,
320 sizeof (PciData
.Hdr
.ClassCode
),
321 PciData
.Hdr
.ClassCode
323 if (EFI_ERROR (Status
)) {
324 return EFI_UNSUPPORTED
;
327 if (IS_PCI_IDE (&PciData
) || IS_PCI_SATADPA (&PciData
)) {
331 return EFI_UNSUPPORTED
;
335 This routine is called right after the .Supported() called and
336 Start this driver on ControllerHandle.
338 @param This Protocol instance pointer.
339 @param Controller Handle of device to bind driver to.
340 @param RemainingDevicePath A pointer to the device path.
341 it should be ignored by device driver.
343 @retval EFI_SUCCESS This driver is added to this device.
344 @retval EFI_ALREADY_STARTED This driver is already running on this device.
345 @retval other Some error occurs when binding this driver to this device.
350 SataControllerStart (
351 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
352 IN EFI_HANDLE Controller
,
353 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
357 EFI_PCI_IO_PROTOCOL
*PciIo
;
359 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
365 DEBUG ((EFI_D_INFO
, "SataControllerStart start\n"));
370 // Now test and open PCI I/O Protocol
372 Status
= gBS
->OpenProtocol (
374 &gEfiPciIoProtocolGuid
,
376 This
->DriverBindingHandle
,
378 EFI_OPEN_PROTOCOL_BY_DRIVER
380 if (EFI_ERROR (Status
)) {
381 DEBUG ((EFI_D_ERROR
, "SataControllerStart error. return status = %r\n", Status
));
386 // Allocate Sata Private Data structure
388 Private
= AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA
));
389 if (Private
== NULL
) {
390 Status
= EFI_OUT_OF_RESOURCES
;
395 // Initialize Sata Private Data
397 Private
->Signature
= SATA_CONTROLLER_SIGNATURE
;
398 Private
->PciIo
= PciIo
;
399 Private
->IdeInit
.GetChannelInfo
= IdeInitGetChannelInfo
;
400 Private
->IdeInit
.NotifyPhase
= IdeInitNotifyPhase
;
401 Private
->IdeInit
.SubmitData
= IdeInitSubmitData
;
402 Private
->IdeInit
.DisqualifyMode
= IdeInitDisqualifyMode
;
403 Private
->IdeInit
.CalculateMode
= IdeInitCalculateMode
;
404 Private
->IdeInit
.SetTiming
= IdeInitSetTiming
;
405 Private
->IdeInit
.EnumAll
= SATA_ENUMER_ALL
;
406 Private
->PciAttributesChanged
= FALSE
;
409 // Save original PCI attributes
411 Status
= PciIo
->Attributes (
413 EfiPciIoAttributeOperationGet
,
415 &Private
->OriginalPciAttributes
417 if (EFI_ERROR (Status
)) {
423 "Original PCI Attributes = 0x%llx\n",
424 Private
->OriginalPciAttributes
427 Status
= PciIo
->Attributes (
429 EfiPciIoAttributeOperationSupported
,
433 if (EFI_ERROR (Status
)) {
437 DEBUG ((EFI_D_INFO
, "Supported PCI Attributes = 0x%llx\n", Supports
));
439 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
440 Status
= PciIo
->Attributes (
442 EfiPciIoAttributeOperationEnable
,
446 if (EFI_ERROR (Status
)) {
450 DEBUG ((EFI_D_INFO
, "Enabled PCI Attributes = 0x%llx\n", Supports
));
451 Private
->PciAttributesChanged
= TRUE
;
453 Status
= PciIo
->Pci
.Read (
456 PCI_CLASSCODE_OFFSET
,
457 sizeof (PciData
.Hdr
.ClassCode
),
458 PciData
.Hdr
.ClassCode
460 if (EFI_ERROR (Status
)) {
465 if (IS_PCI_IDE (&PciData
)) {
466 Private
->IdeInit
.ChannelCount
= IDE_MAX_CHANNEL
;
467 Private
->DeviceCount
= IDE_MAX_DEVICES
;
468 } else if (IS_PCI_SATADPA (&PciData
)) {
470 // Read Ports Implemented(PI) to calculate max port number (0 based).
472 Data32
= AhciReadReg (PciIo
, R_AHCI_PI
);
473 DEBUG ((DEBUG_INFO
, "Ports Implemented(PI) = 0x%x\n", Data32
));
475 Status
= EFI_UNSUPPORTED
;
479 while (MaxPortNumber
> 0) {
480 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
)) {
535 &gEfiPciIoProtocolGuid
,
536 This
->DriverBindingHandle
,
539 if (Private
!= NULL
) {
540 if (Private
->DisqualifiedModes
!= NULL
) {
541 FreePool (Private
->DisqualifiedModes
);
543 if (Private
->IdentifyData
!= NULL
) {
544 FreePool (Private
->IdentifyData
);
546 if (Private
->IdentifyValid
!= NULL
) {
547 FreePool (Private
->IdentifyValid
);
549 if (Private
->PciAttributesChanged
) {
551 // Restore original PCI attributes
555 EfiPciIoAttributeOperationSet
,
556 Private
->OriginalPciAttributes
,
564 DEBUG ((EFI_D_INFO
, "SataControllerStart end with %r\n", Status
));
570 Stop this driver on ControllerHandle.
572 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
573 @param Controller A handle to the device being stopped.
574 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
575 @param ChildHandleBuffer An array of child handles to be freed.
577 @retval EFI_SUCCESS This driver is removed from this device.
578 @retval other Some error occurs when removing this driver from this device.
584 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
585 IN EFI_HANDLE Controller
,
586 IN UINTN NumberOfChildren
,
587 IN EFI_HANDLE
*ChildHandleBuffer
591 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
592 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
595 // Open the produced protocol
597 Status
= gBS
->OpenProtocol (
599 &gEfiIdeControllerInitProtocolGuid
,
601 This
->DriverBindingHandle
,
603 EFI_OPEN_PROTOCOL_GET_PROTOCOL
605 if (EFI_ERROR (Status
)) {
606 return EFI_UNSUPPORTED
;
609 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit
);
610 ASSERT (Private
!= NULL
);
613 // Uninstall the IDE Controller Init Protocol from this instance
615 Status
= gBS
->UninstallMultipleProtocolInterfaces (
617 &gEfiIdeControllerInitProtocolGuid
,
621 if (EFI_ERROR (Status
)) {
625 if (Private
!= NULL
) {
626 if (Private
->DisqualifiedModes
!= NULL
) {
627 FreePool (Private
->DisqualifiedModes
);
629 if (Private
->IdentifyData
!= NULL
) {
630 FreePool (Private
->IdentifyData
);
632 if (Private
->IdentifyValid
!= NULL
) {
633 FreePool (Private
->IdentifyValid
);
635 if (Private
->PciAttributesChanged
) {
637 // Restore original PCI attributes
639 Private
->PciIo
->Attributes (
641 EfiPciIoAttributeOperationSet
,
642 Private
->OriginalPciAttributes
,
650 // Close protocols opened by Sata Controller driver
652 return gBS
->CloseProtocol (
654 &gEfiPciIoProtocolGuid
,
655 This
->DriverBindingHandle
,
661 Calculate the flat array subscript of a (Channel, Device) pair.
663 @param[in] Private The private data structure corresponding to the
664 SATA controller that attaches the device for
665 which the flat array subscript is being
668 @param[in] Channel The channel (ie. port) number on the SATA
669 controller that the device is attached to.
671 @param[in] Device The device number on the channel.
673 @return The flat array subscript suitable for indexing DisqualifiedModes,
674 IdentifyData, and IdentifyValid.
679 IN CONST EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
,
684 ASSERT (Private
!= NULL
);
685 ASSERT (Channel
< Private
->IdeInit
.ChannelCount
);
686 ASSERT (Device
< Private
->DeviceCount
);
688 return Channel
* Private
->DeviceCount
+ Device
;
692 // Interface functions of IDE_CONTROLLER_INIT protocol
695 Returns the information about the specified IDE channel.
697 This function can be used to obtain information about a particular IDE channel.
698 The driver entity uses this information during the enumeration process.
700 If Enabled is set to FALSE, the driver entity will not scan the channel. Note
701 that it will not prevent an operating system driver from scanning the channel.
703 For most of today's controllers, MaxDevices will either be 1 or 2. For SATA
704 controllers, this value will always be 1. SATA configurations can contain SATA
705 port multipliers. SATA port multipliers behave like SATA bridges and can support
706 up to 16 devices on the other side. If a SATA port out of the IDE controller
707 is connected to a port multiplier, MaxDevices will be set to the number of SATA
708 devices that the port multiplier supports. Because today's port multipliers
709 support up to fifteen SATA devices, this number can be as large as fifteen. The IDE
710 bus driver is required to scan for the presence of port multipliers behind an SATA
711 controller and enumerate up to MaxDevices number of devices behind the port
714 In this context, the devices behind a port multiplier constitute a channel.
716 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
717 @param[in] Channel Zero-based channel number.
718 @param[out] Enabled TRUE if this channel is enabled. Disabled channels
719 are not scanned to see if any devices are present.
720 @param[out] MaxDevices The maximum number of IDE devices that the bus driver
721 can expect on this channel. For the ATA/ATAPI
722 specification, version 6, this number will either be
723 one or two. For Serial ATA (SATA) configurations with a
724 port multiplier, this number can be as large as fifteen.
726 @retval EFI_SUCCESS Information was returned without any errors.
727 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
732 IdeInitGetChannelInfo (
733 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
735 OUT BOOLEAN
*Enabled
,
736 OUT UINT8
*MaxDevices
739 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
740 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
741 ASSERT (Private
!= NULL
);
743 if (Channel
< This
->ChannelCount
) {
745 *MaxDevices
= Private
->DeviceCount
;
750 return EFI_INVALID_PARAMETER
;
754 The notifications from the driver entity that it is about to enter a certain
755 phase of the IDE channel enumeration process.
757 This function can be used to notify the IDE controller driver to perform
758 specific actions, including any chipset-specific initialization, so that the
759 chipset is ready to enter the next phase. Seven notification points are defined
762 More synchronization points may be added as required in the future.
764 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL
766 @param[in] Phase The phase during enumeration.
767 @param[in] Channel Zero-based channel number.
769 @retval EFI_SUCCESS The notification was accepted without any errors.
770 @retval EFI_UNSUPPORTED Phase is not supported.
771 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
772 @retval EFI_NOT_READY This phase cannot be entered at this time; for
773 example, an attempt was made to enter a Phase
774 without having entered one or more previous
781 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
782 IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase
,
790 Submits the device information to the IDE controller driver.
792 This function is used by the driver entity to pass detailed information about
793 a particular device to the IDE controller driver. The driver entity obtains
794 this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
795 is the pointer to the response data buffer. The IdentifyData buffer is owned
796 by the driver entity, and the IDE controller driver must make a local copy
797 of the entire buffer or parts of the buffer as needed. The original IdentifyData
798 buffer pointer may not be valid when
800 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
801 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
803 The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to
804 compute the optimum mode for the device. These fields are not limited to the
805 timing information. For example, an implementation of the IDE controller driver
806 may examine the vendor and type/mode field to match known bad drives.
808 The driver entity may submit drive information in any order, as long as it
809 submits information for all the devices belonging to the enumeration group
810 before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
811 in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
812 should be called with IdentifyData set to NULL. The IDE controller driver may
813 not have any other mechanism to know whether a device is present or not. Therefore,
814 setting IdentifyData to NULL does not constitute an error condition.
815 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a
816 given (Channel, Device) pair.
818 @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
819 @param[in] Channel Zero-based channel number.
820 @param[in] Device Zero-based device number on the Channel.
821 @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command.
823 @retval EFI_SUCCESS The information was accepted without any errors.
824 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
825 @retval EFI_INVALID_PARAMETER Device is invalid.
831 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
834 IN EFI_IDENTIFY_DATA
*IdentifyData
837 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
840 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
841 ASSERT (Private
!= NULL
);
843 if ((Channel
>= This
->ChannelCount
) || (Device
>= Private
->DeviceCount
)) {
844 return EFI_INVALID_PARAMETER
;
847 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
850 // Make a local copy of device's IdentifyData and mark the valid flag
852 if (IdentifyData
!= NULL
) {
854 &(Private
->IdentifyData
[DeviceIndex
]),
856 sizeof (EFI_IDENTIFY_DATA
)
859 Private
->IdentifyValid
[DeviceIndex
] = TRUE
;
861 Private
->IdentifyValid
[DeviceIndex
] = FALSE
;
868 Disqualifies specific modes for an IDE device.
870 This function allows the driver entity or other drivers (such as platform
871 drivers) to reject certain timing modes and request the IDE controller driver
872 to recalculate modes. This function allows the driver entity and the IDE
873 controller driver to negotiate the timings on a per-device basis. This function
874 is useful in the case of drives that lie about their capabilities. An example
875 is when the IDE device fails to accept the timing modes that are calculated
876 by the IDE controller driver based on the response to the Identify Drive command.
878 If the driver entity does not want to limit the ATA timing modes and leave that
879 decision to the IDE controller driver, it can either not call this function for
880 the given device or call this function and set the Valid flag to FALSE for all
881 modes that are listed in EFI_ATA_COLLECTIVE_MODE.
883 The driver entity may disqualify modes for a device in any order and any number
886 This function can be called multiple times to invalidate multiple modes of the
887 same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI
888 specification for more information on PIO modes.
890 For Serial ATA (SATA) controllers, this member function can be used to disqualify
891 a higher transfer rate mode on a given channel. For example, a platform driver
892 may inform the IDE controller driver to not use second-generation (Gen2) speeds
893 for a certain SATA drive.
895 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
896 @param[in] Channel The zero-based channel number.
897 @param[in] Device The zero-based device number on the Channel.
898 @param[in] BadModes The modes that the device does not support and that
899 should be disqualified.
901 @retval EFI_SUCCESS The modes were accepted without any errors.
902 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
903 @retval EFI_INVALID_PARAMETER Device is invalid.
904 @retval EFI_INVALID_PARAMETER IdentifyData is NULL.
909 IdeInitDisqualifyMode (
910 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
913 IN EFI_ATA_COLLECTIVE_MODE
*BadModes
916 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
919 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
920 ASSERT (Private
!= NULL
);
922 if ((Channel
>= This
->ChannelCount
) || (BadModes
== NULL
) || (Device
>= Private
->DeviceCount
)) {
923 return EFI_INVALID_PARAMETER
;
926 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
929 // Record the disqualified modes per channel per device. From ATA/ATAPI spec,
930 // if a mode is not supported, the modes higher than it is also not supported.
933 &(Private
->DisqualifiedModes
[DeviceIndex
]),
935 sizeof (EFI_ATA_COLLECTIVE_MODE
)
942 Returns the information about the optimum modes for the specified IDE device.
944 This function is used by the driver entity to obtain the optimum ATA modes for
945 a specific device. The IDE controller driver takes into account the following
946 while calculating the mode:
947 - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
948 - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
950 The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
951 for all the devices that belong to an enumeration group before calling
952 EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.
954 The IDE controller driver will use controller- and possibly platform-specific
955 algorithms to arrive at SupportedModes. The IDE controller may base its
956 decision on user preferences and other considerations as well. This function
957 may be called multiple times because the driver entity may renegotiate the mode
958 with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
960 The driver entity may collect timing information for various devices in any
961 order. The driver entity is responsible for making sure that all the dependencies
962 are satisfied. For example, the SupportedModes information for device A that
963 was previously returned may become stale after a call to
964 EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
966 The buffer SupportedModes is allocated by the callee because the caller does
967 not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE
968 is defined in a way that allows for future extensibility and can be of variable
969 length. This memory pool should be deallocated by the caller when it is no
972 The IDE controller driver for a Serial ATA (SATA) controller can use this
973 member function to force a lower speed (first-generation [Gen1] speeds on a
974 second-generation [Gen2]-capable hardware). The IDE controller driver can
975 also allow the driver entity to stay with the speed that has been negotiated
976 by the physical layer.
978 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
979 @param[in] Channel A zero-based channel number.
980 @param[in] Device A zero-based device number on the Channel.
981 @param[out] SupportedModes The optimum modes for the device.
983 @retval EFI_SUCCESS SupportedModes was returned.
984 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
985 @retval EFI_INVALID_PARAMETER Device is invalid.
986 @retval EFI_INVALID_PARAMETER SupportedModes is NULL.
987 @retval EFI_NOT_READY Modes cannot be calculated due to a lack of
988 data. This error may happen if
989 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
990 and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData()
991 were not called for at least one drive in the
992 same enumeration group.
997 IdeInitCalculateMode (
998 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
1001 OUT EFI_ATA_COLLECTIVE_MODE
**SupportedModes
1004 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
1005 EFI_IDENTIFY_DATA
*IdentifyData
;
1006 BOOLEAN IdentifyValid
;
1007 EFI_ATA_COLLECTIVE_MODE
*DisqualifiedModes
;
1008 UINT16 SelectedMode
;
1012 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
1013 ASSERT (Private
!= NULL
);
1015 if ((Channel
>= This
->ChannelCount
) || (SupportedModes
== NULL
) || (Device
>= Private
->DeviceCount
)) {
1016 return EFI_INVALID_PARAMETER
;
1019 *SupportedModes
= AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE
));
1020 if (*SupportedModes
== NULL
) {
1021 ASSERT (*SupportedModes
!= NULL
);
1022 return EFI_OUT_OF_RESOURCES
;
1025 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
1027 IdentifyData
= &(Private
->IdentifyData
[DeviceIndex
]);
1028 IdentifyValid
= Private
->IdentifyValid
[DeviceIndex
];
1029 DisqualifiedModes
= &(Private
->DisqualifiedModes
[DeviceIndex
]);
1032 // Make sure we've got the valid identify data of the device from SubmitData()
1034 if (!IdentifyValid
) {
1035 FreePool (*SupportedModes
);
1036 return EFI_NOT_READY
;
1039 Status
= CalculateBestPioMode (
1041 (DisqualifiedModes
->PioMode
.Valid
? ((UINT16
*) &(DisqualifiedModes
->PioMode
.Mode
)) : NULL
),
1044 if (!EFI_ERROR (Status
)) {
1045 (*SupportedModes
)->PioMode
.Valid
= TRUE
;
1046 (*SupportedModes
)->PioMode
.Mode
= SelectedMode
;
1049 (*SupportedModes
)->PioMode
.Valid
= FALSE
;
1051 DEBUG ((EFI_D_INFO
, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes
)->PioMode
.Mode
));
1053 Status
= CalculateBestUdmaMode (
1055 (DisqualifiedModes
->UdmaMode
.Valid
? ((UINT16
*) &(DisqualifiedModes
->UdmaMode
.Mode
)) : NULL
),
1059 if (!EFI_ERROR (Status
)) {
1060 (*SupportedModes
)->UdmaMode
.Valid
= TRUE
;
1061 (*SupportedModes
)->UdmaMode
.Mode
= SelectedMode
;
1064 (*SupportedModes
)->UdmaMode
.Valid
= FALSE
;
1066 DEBUG ((EFI_D_INFO
, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes
)->UdmaMode
.Mode
));
1069 // The modes other than PIO and UDMA are not supported
1075 Commands the IDE controller driver to program the IDE controller hardware
1076 so that the specified device can operate at the specified mode.
1078 This function is used by the driver entity to instruct the IDE controller
1079 driver to program the IDE controller hardware to the specified modes. This
1080 function can be called only once for a particular device. For a Serial ATA
1081 (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
1082 specific programming may be required.
1084 @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
1085 @param[in] Channel Zero-based channel number.
1086 @param[in] Device Zero-based device number on the Channel.
1087 @param[in] Modes The modes to set.
1089 @retval EFI_SUCCESS The command was accepted without any errors.
1090 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
1091 @retval EFI_INVALID_PARAMETER Device is invalid.
1092 @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data.
1093 @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure.
1094 The driver entity should not use this device.
1100 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
1103 IN EFI_ATA_COLLECTIVE_MODE
*Modes