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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "SataController.h"
19 /// EFI_DRIVER_BINDING_PROTOCOL instance
21 EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding
= {
22 SataControllerSupported
,
31 Read AHCI Operation register.
33 @param PciIo The PCI IO protocol instance.
34 @param Offset The operation register offset.
36 @return The register content read.
42 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
48 ASSERT (PciIo
!= NULL
);
65 This function is used to calculate the best PIO mode supported by specific IDE device
67 @param IdentifyData The identify data of specific IDE device.
68 @param DisPioMode Disqualified PIO modes collection.
69 @param SelectedMode Available PIO modes collection.
71 @retval EFI_SUCCESS Best PIO modes are returned.
72 @retval EFI_UNSUPPORTED The device doesn't support PIO mode,
73 or all supported modes have been disqualified.
76 CalculateBestPioMode (
77 IN EFI_IDENTIFY_DATA
*IdentifyData
,
78 IN UINT16
*DisPioMode OPTIONAL
,
79 OUT UINT16
*SelectedMode
83 UINT16 AdvancedPioMode
;
86 UINT16 MinimumPioCycleTime
;
90 PioMode
= (UINT8
) (((ATA5_IDENTIFY_DATA
*) (&(IdentifyData
->AtaData
)))->pio_cycle_timing
>> 8);
93 // See whether Identify Data word 64 - 70 are valid
95 if ((IdentifyData
->AtaData
.field_validity
& 0x02) == 0x02) {
97 AdvancedPioMode
= IdentifyData
->AtaData
.advanced_pio_modes
;
98 DEBUG ((EFI_D_INFO
, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode
));
100 for (Index
= 0; Index
< 8; Index
++) {
101 if ((AdvancedPioMode
& 0x01) != 0) {
105 AdvancedPioMode
>>= 1;
109 // If Temp is modified, mean the advanced_pio_modes is not zero;
110 // if Temp is not modified, mean there is no advanced PIO mode supported,
111 // the best PIO Mode is the value in pio_cycle_timing.
114 AdvancedPioMode
= (UINT16
) (Temp
+ 3);
116 AdvancedPioMode
= PioMode
;
120 // Limit the PIO mode to at most PIO4.
122 PioMode
= (UINT16
) MIN (AdvancedPioMode
, 4);
124 MinimumPioCycleTime
= IdentifyData
->AtaData
.min_pio_cycle_time_with_flow_control
;
126 if (MinimumPioCycleTime
<= 120) {
127 PioMode
= (UINT16
) MIN (4, PioMode
);
128 } else if (MinimumPioCycleTime
<= 180) {
129 PioMode
= (UINT16
) MIN (3, PioMode
);
130 } else if (MinimumPioCycleTime
<= 240) {
131 PioMode
= (UINT16
) MIN (2, PioMode
);
137 // Degrade the PIO mode if the mode has been disqualified
139 if (DisPioMode
!= NULL
) {
140 if (*DisPioMode
< 2) {
141 return EFI_UNSUPPORTED
; // no mode below ATA_PIO_MODE_BELOW_2
144 if (PioMode
>= *DisPioMode
) {
145 PioMode
= (UINT16
) (*DisPioMode
- 1);
150 *SelectedMode
= 1; // ATA_PIO_MODE_BELOW_2;
152 *SelectedMode
= PioMode
; // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;
157 // Identify Data word 64 - 70 are not valid
158 // Degrade the PIO mode if the mode has been disqualified
160 if (DisPioMode
!= NULL
) {
161 if (*DisPioMode
< 2) {
162 return EFI_UNSUPPORTED
; // no mode below ATA_PIO_MODE_BELOW_2
165 if (PioMode
== *DisPioMode
) {
171 *SelectedMode
= 1; // ATA_PIO_MODE_BELOW_2;
173 *SelectedMode
= 2; // ATA_PIO_MODE_2;
182 This function is used to calculate the best UDMA mode supported by specific IDE device
184 @param IdentifyData The identify data of specific IDE device.
185 @param DisUDmaMode Disqualified UDMA modes collection.
186 @param SelectedMode Available UDMA modes collection.
188 @retval EFI_SUCCESS Best UDMA modes are returned.
189 @retval EFI_UNSUPPORTED The device doesn't support UDMA mode,
190 or all supported modes have been disqualified.
193 CalculateBestUdmaMode (
194 IN EFI_IDENTIFY_DATA
*IdentifyData
,
195 IN UINT16
*DisUDmaMode OPTIONAL
,
196 OUT UINT16
*SelectedMode
200 UINT16 DeviceUDmaMode
;
205 // Check whether the WORD 88 (supported UltraDMA by drive) is valid
207 if ((IdentifyData
->AtaData
.field_validity
& 0x04) == 0x00) {
208 return EFI_UNSUPPORTED
;
211 DeviceUDmaMode
= IdentifyData
->AtaData
.ultra_dma_mode
;
212 DEBUG ((EFI_D_INFO
, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode
));
213 DeviceUDmaMode
&= 0x3f;
214 TempMode
= 0; // initialize it to UDMA-0
216 while ((DeviceUDmaMode
>>= 1) != 0) {
221 // Degrade the UDMA mode if the mode has been disqualified
223 if (DisUDmaMode
!= NULL
) {
224 if (*DisUDmaMode
== 0) {
226 return EFI_UNSUPPORTED
; // no mode below ATA_UDMA_MODE_0
229 if (TempMode
>= *DisUDmaMode
) {
230 TempMode
= (UINT16
) (*DisUDmaMode
- 1);
235 // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5
237 *SelectedMode
= TempMode
;
243 The Entry Point of module. It follows the standard UEFI driver model.
245 @param[in] ImageHandle The firmware allocated handle for the EFI image.
246 @param[in] SystemTable A pointer to the EFI System Table.
248 @retval EFI_SUCCESS The entry point is executed successfully.
249 @retval other Some error occurs when executing this entry point.
254 InitializeSataControllerDriver (
255 IN EFI_HANDLE ImageHandle
,
256 IN EFI_SYSTEM_TABLE
*SystemTable
262 // Install driver model protocol(s).
264 Status
= EfiLibInstallDriverBindingComponentName2 (
267 &gSataControllerDriverBinding
,
269 &gSataControllerComponentName
,
270 &gSataControllerComponentName2
272 ASSERT_EFI_ERROR (Status
);
278 Supported function of Driver Binding protocol for this driver.
279 Test to see if this driver supports ControllerHandle.
281 @param This Protocol instance pointer.
282 @param Controller Handle of device to test.
283 @param RemainingDevicePath A pointer to the device path.
284 it should be ignored by device driver.
286 @retval EFI_SUCCESS This driver supports this device.
287 @retval EFI_ALREADY_STARTED This driver is already running on this device.
288 @retval other This driver does not support this device.
293 SataControllerSupported (
294 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
295 IN EFI_HANDLE Controller
,
296 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
300 EFI_PCI_IO_PROTOCOL
*PciIo
;
304 // Attempt to open PCI I/O Protocol
306 Status
= gBS
->OpenProtocol (
308 &gEfiPciIoProtocolGuid
,
310 This
->DriverBindingHandle
,
312 EFI_OPEN_PROTOCOL_GET_PROTOCOL
314 if (EFI_ERROR (Status
)) {
319 // Now further check the PCI header: Base Class (offset 0x0B) and
320 // Sub Class (offset 0x0A). This controller should be an SATA controller
322 Status
= PciIo
->Pci
.Read (
325 PCI_CLASSCODE_OFFSET
,
326 sizeof (PciData
.Hdr
.ClassCode
),
327 PciData
.Hdr
.ClassCode
329 if (EFI_ERROR (Status
)) {
330 return EFI_UNSUPPORTED
;
333 if (IS_PCI_IDE (&PciData
) || IS_PCI_SATADPA (&PciData
)) {
337 return EFI_UNSUPPORTED
;
341 This routine is called right after the .Supported() called and
342 Start this driver on ControllerHandle.
344 @param This Protocol instance pointer.
345 @param Controller Handle of device to bind driver to.
346 @param RemainingDevicePath A pointer to the device path.
347 it should be ignored by device driver.
349 @retval EFI_SUCCESS This driver is added to this device.
350 @retval EFI_ALREADY_STARTED This driver is already running on this device.
351 @retval other Some error occurs when binding this driver to this device.
356 SataControllerStart (
357 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
358 IN EFI_HANDLE Controller
,
359 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
363 EFI_PCI_IO_PROTOCOL
*PciIo
;
365 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
371 DEBUG ((EFI_D_INFO
, "SataControllerStart start\n"));
376 // Now test and open PCI I/O Protocol
378 Status
= gBS
->OpenProtocol (
380 &gEfiPciIoProtocolGuid
,
382 This
->DriverBindingHandle
,
384 EFI_OPEN_PROTOCOL_BY_DRIVER
386 if (EFI_ERROR (Status
)) {
387 DEBUG ((EFI_D_ERROR
, "SataControllerStart error. return status = %r\n", Status
));
392 // Allocate Sata Private Data structure
394 Private
= AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA
));
395 if (Private
== NULL
) {
396 Status
= EFI_OUT_OF_RESOURCES
;
401 // Initialize Sata Private Data
403 Private
->Signature
= SATA_CONTROLLER_SIGNATURE
;
404 Private
->PciIo
= PciIo
;
405 Private
->IdeInit
.GetChannelInfo
= IdeInitGetChannelInfo
;
406 Private
->IdeInit
.NotifyPhase
= IdeInitNotifyPhase
;
407 Private
->IdeInit
.SubmitData
= IdeInitSubmitData
;
408 Private
->IdeInit
.DisqualifyMode
= IdeInitDisqualifyMode
;
409 Private
->IdeInit
.CalculateMode
= IdeInitCalculateMode
;
410 Private
->IdeInit
.SetTiming
= IdeInitSetTiming
;
411 Private
->IdeInit
.EnumAll
= SATA_ENUMER_ALL
;
412 Private
->PciAttributesChanged
= FALSE
;
415 // Save original PCI attributes
417 Status
= PciIo
->Attributes (
419 EfiPciIoAttributeOperationGet
,
421 &Private
->OriginalPciAttributes
423 if (EFI_ERROR (Status
)) {
429 "Original PCI Attributes = 0x%llx\n",
430 Private
->OriginalPciAttributes
433 Status
= PciIo
->Attributes (
435 EfiPciIoAttributeOperationSupported
,
439 if (EFI_ERROR (Status
)) {
443 DEBUG ((EFI_D_INFO
, "Supported PCI Attributes = 0x%llx\n", Supports
));
445 Supports
&= (UINT64
)EFI_PCI_DEVICE_ENABLE
;
446 Status
= PciIo
->Attributes (
448 EfiPciIoAttributeOperationEnable
,
452 if (EFI_ERROR (Status
)) {
456 DEBUG ((EFI_D_INFO
, "Enabled PCI Attributes = 0x%llx\n", Supports
));
457 Private
->PciAttributesChanged
= TRUE
;
459 Status
= PciIo
->Pci
.Read (
462 PCI_CLASSCODE_OFFSET
,
463 sizeof (PciData
.Hdr
.ClassCode
),
464 PciData
.Hdr
.ClassCode
466 if (EFI_ERROR (Status
)) {
471 if (IS_PCI_IDE (&PciData
)) {
472 Private
->IdeInit
.ChannelCount
= IDE_MAX_CHANNEL
;
473 Private
->DeviceCount
= IDE_MAX_DEVICES
;
474 } else if (IS_PCI_SATADPA (&PciData
)) {
476 // Read Ports Implemented(PI) to calculate max port number (0 based).
478 Data32
= AhciReadReg (PciIo
, R_AHCI_PI
);
479 DEBUG ((DEBUG_INFO
, "Ports Implemented(PI) = 0x%x\n", Data32
));
481 Status
= EFI_UNSUPPORTED
;
485 while (MaxPortNumber
> 0) {
486 if (Data32
& (1 << MaxPortNumber
)) {
492 // Make the ChannelCount equal to the max port number (0 based) plus 1.
494 Private
->IdeInit
.ChannelCount
= MaxPortNumber
+ 1;
497 // Read HBA Capabilities(CAP) to get Supports Port Multiplier(SPM).
499 Data32
= AhciReadReg (PciIo
, R_AHCI_CAP
);
500 DEBUG ((DEBUG_INFO
, "HBA Capabilities(CAP) = 0x%x\n", Data32
));
501 Private
->DeviceCount
= AHCI_MAX_DEVICES
;
502 if ((Data32
& B_AHCI_CAP_SPM
) == B_AHCI_CAP_SPM
) {
503 Private
->DeviceCount
= AHCI_MULTI_MAX_DEVICES
;
507 TotalCount
= (UINTN
) (Private
->IdeInit
.ChannelCount
) * (UINTN
) (Private
->DeviceCount
);
508 Private
->DisqualifiedModes
= AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE
)) * TotalCount
);
509 if (Private
->DisqualifiedModes
== NULL
) {
510 Status
= EFI_OUT_OF_RESOURCES
;
514 Private
->IdentifyData
= AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA
)) * TotalCount
);
515 if (Private
->IdentifyData
== NULL
) {
516 Status
= EFI_OUT_OF_RESOURCES
;
520 Private
->IdentifyValid
= AllocateZeroPool ((sizeof (BOOLEAN
)) * TotalCount
);
521 if (Private
->IdentifyValid
== NULL
) {
522 Status
= EFI_OUT_OF_RESOURCES
;
527 // Install IDE Controller Init Protocol to this instance
529 Status
= gBS
->InstallMultipleProtocolInterfaces (
531 &gEfiIdeControllerInitProtocolGuid
,
537 if (EFI_ERROR (Status
)) {
541 &gEfiPciIoProtocolGuid
,
542 This
->DriverBindingHandle
,
545 if (Private
!= NULL
) {
546 if (Private
->DisqualifiedModes
!= NULL
) {
547 FreePool (Private
->DisqualifiedModes
);
549 if (Private
->IdentifyData
!= NULL
) {
550 FreePool (Private
->IdentifyData
);
552 if (Private
->IdentifyValid
!= NULL
) {
553 FreePool (Private
->IdentifyValid
);
555 if (Private
->PciAttributesChanged
) {
557 // Restore original PCI attributes
561 EfiPciIoAttributeOperationSet
,
562 Private
->OriginalPciAttributes
,
570 DEBUG ((EFI_D_INFO
, "SataControllerStart end with %r\n", Status
));
576 Stop this driver on ControllerHandle.
578 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
579 @param Controller A handle to the device being stopped.
580 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
581 @param ChildHandleBuffer An array of child handles to be freed.
583 @retval EFI_SUCCESS This driver is removed from this device.
584 @retval other Some error occurs when removing this driver from this device.
590 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
591 IN EFI_HANDLE Controller
,
592 IN UINTN NumberOfChildren
,
593 IN EFI_HANDLE
*ChildHandleBuffer
597 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
598 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
601 // Open the produced protocol
603 Status
= gBS
->OpenProtocol (
605 &gEfiIdeControllerInitProtocolGuid
,
607 This
->DriverBindingHandle
,
609 EFI_OPEN_PROTOCOL_GET_PROTOCOL
611 if (EFI_ERROR (Status
)) {
612 return EFI_UNSUPPORTED
;
615 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit
);
616 ASSERT (Private
!= NULL
);
619 // Uninstall the IDE Controller Init Protocol from this instance
621 Status
= gBS
->UninstallMultipleProtocolInterfaces (
623 &gEfiIdeControllerInitProtocolGuid
,
627 if (EFI_ERROR (Status
)) {
631 if (Private
!= NULL
) {
632 if (Private
->DisqualifiedModes
!= NULL
) {
633 FreePool (Private
->DisqualifiedModes
);
635 if (Private
->IdentifyData
!= NULL
) {
636 FreePool (Private
->IdentifyData
);
638 if (Private
->IdentifyValid
!= NULL
) {
639 FreePool (Private
->IdentifyValid
);
641 if (Private
->PciAttributesChanged
) {
643 // Restore original PCI attributes
645 Private
->PciIo
->Attributes (
647 EfiPciIoAttributeOperationSet
,
648 Private
->OriginalPciAttributes
,
656 // Close protocols opened by Sata Controller driver
658 return gBS
->CloseProtocol (
660 &gEfiPciIoProtocolGuid
,
661 This
->DriverBindingHandle
,
667 Calculate the flat array subscript of a (Channel, Device) pair.
669 @param[in] Private The private data structure corresponding to the
670 SATA controller that attaches the device for
671 which the flat array subscript is being
674 @param[in] Channel The channel (ie. port) number on the SATA
675 controller that the device is attached to.
677 @param[in] Device The device number on the channel.
679 @return The flat array subscript suitable for indexing DisqualifiedModes,
680 IdentifyData, and IdentifyValid.
685 IN CONST EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
,
690 ASSERT (Private
!= NULL
);
691 ASSERT (Channel
< Private
->IdeInit
.ChannelCount
);
692 ASSERT (Device
< Private
->DeviceCount
);
694 return Channel
* Private
->DeviceCount
+ Device
;
698 // Interface functions of IDE_CONTROLLER_INIT protocol
701 Returns the information about the specified IDE channel.
703 This function can be used to obtain information about a particular IDE channel.
704 The driver entity uses this information during the enumeration process.
706 If Enabled is set to FALSE, the driver entity will not scan the channel. Note
707 that it will not prevent an operating system driver from scanning the channel.
709 For most of today's controllers, MaxDevices will either be 1 or 2. For SATA
710 controllers, this value will always be 1. SATA configurations can contain SATA
711 port multipliers. SATA port multipliers behave like SATA bridges and can support
712 up to 16 devices on the other side. If a SATA port out of the IDE controller
713 is connected to a port multiplier, MaxDevices will be set to the number of SATA
714 devices that the port multiplier supports. Because today's port multipliers
715 support up to fifteen SATA devices, this number can be as large as fifteen. The IDE
716 bus driver is required to scan for the presence of port multipliers behind an SATA
717 controller and enumerate up to MaxDevices number of devices behind the port
720 In this context, the devices behind a port multiplier constitute a channel.
722 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
723 @param[in] Channel Zero-based channel number.
724 @param[out] Enabled TRUE if this channel is enabled. Disabled channels
725 are not scanned to see if any devices are present.
726 @param[out] MaxDevices The maximum number of IDE devices that the bus driver
727 can expect on this channel. For the ATA/ATAPI
728 specification, version 6, this number will either be
729 one or two. For Serial ATA (SATA) configurations with a
730 port multiplier, this number can be as large as fifteen.
732 @retval EFI_SUCCESS Information was returned without any errors.
733 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
738 IdeInitGetChannelInfo (
739 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
741 OUT BOOLEAN
*Enabled
,
742 OUT UINT8
*MaxDevices
745 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
746 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
747 ASSERT (Private
!= NULL
);
749 if (Channel
< This
->ChannelCount
) {
751 *MaxDevices
= Private
->DeviceCount
;
756 return EFI_INVALID_PARAMETER
;
760 The notifications from the driver entity that it is about to enter a certain
761 phase of the IDE channel enumeration process.
763 This function can be used to notify the IDE controller driver to perform
764 specific actions, including any chipset-specific initialization, so that the
765 chipset is ready to enter the next phase. Seven notification points are defined
768 More synchronization points may be added as required in the future.
770 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL
772 @param[in] Phase The phase during enumeration.
773 @param[in] Channel Zero-based channel number.
775 @retval EFI_SUCCESS The notification was accepted without any errors.
776 @retval EFI_UNSUPPORTED Phase is not supported.
777 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
778 @retval EFI_NOT_READY This phase cannot be entered at this time; for
779 example, an attempt was made to enter a Phase
780 without having entered one or more previous
787 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
788 IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase
,
796 Submits the device information to the IDE controller driver.
798 This function is used by the driver entity to pass detailed information about
799 a particular device to the IDE controller driver. The driver entity obtains
800 this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData
801 is the pointer to the response data buffer. The IdentifyData buffer is owned
802 by the driver entity, and the IDE controller driver must make a local copy
803 of the entire buffer or parts of the buffer as needed. The original IdentifyData
804 buffer pointer may not be valid when
806 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or
807 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.
809 The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to
810 compute the optimum mode for the device. These fields are not limited to the
811 timing information. For example, an implementation of the IDE controller driver
812 may examine the vendor and type/mode field to match known bad drives.
814 The driver entity may submit drive information in any order, as long as it
815 submits information for all the devices belonging to the enumeration group
816 before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device
817 in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
818 should be called with IdentifyData set to NULL. The IDE controller driver may
819 not have any other mechanism to know whether a device is present or not. Therefore,
820 setting IdentifyData to NULL does not constitute an error condition.
821 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a
822 given (Channel, Device) pair.
824 @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
825 @param[in] Channel Zero-based channel number.
826 @param[in] Device Zero-based device number on the Channel.
827 @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command.
829 @retval EFI_SUCCESS The information was accepted without any errors.
830 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
831 @retval EFI_INVALID_PARAMETER Device is invalid.
837 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
840 IN EFI_IDENTIFY_DATA
*IdentifyData
843 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
846 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
847 ASSERT (Private
!= NULL
);
849 if ((Channel
>= This
->ChannelCount
) || (Device
>= Private
->DeviceCount
)) {
850 return EFI_INVALID_PARAMETER
;
853 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
856 // Make a local copy of device's IdentifyData and mark the valid flag
858 if (IdentifyData
!= NULL
) {
860 &(Private
->IdentifyData
[DeviceIndex
]),
862 sizeof (EFI_IDENTIFY_DATA
)
865 Private
->IdentifyValid
[DeviceIndex
] = TRUE
;
867 Private
->IdentifyValid
[DeviceIndex
] = FALSE
;
874 Disqualifies specific modes for an IDE device.
876 This function allows the driver entity or other drivers (such as platform
877 drivers) to reject certain timing modes and request the IDE controller driver
878 to recalculate modes. This function allows the driver entity and the IDE
879 controller driver to negotiate the timings on a per-device basis. This function
880 is useful in the case of drives that lie about their capabilities. An example
881 is when the IDE device fails to accept the timing modes that are calculated
882 by the IDE controller driver based on the response to the Identify Drive command.
884 If the driver entity does not want to limit the ATA timing modes and leave that
885 decision to the IDE controller driver, it can either not call this function for
886 the given device or call this function and set the Valid flag to FALSE for all
887 modes that are listed in EFI_ATA_COLLECTIVE_MODE.
889 The driver entity may disqualify modes for a device in any order and any number
892 This function can be called multiple times to invalidate multiple modes of the
893 same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI
894 specification for more information on PIO modes.
896 For Serial ATA (SATA) controllers, this member function can be used to disqualify
897 a higher transfer rate mode on a given channel. For example, a platform driver
898 may inform the IDE controller driver to not use second-generation (Gen2) speeds
899 for a certain SATA drive.
901 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
902 @param[in] Channel The zero-based channel number.
903 @param[in] Device The zero-based device number on the Channel.
904 @param[in] BadModes The modes that the device does not support and that
905 should be disqualified.
907 @retval EFI_SUCCESS The modes were accepted without any errors.
908 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
909 @retval EFI_INVALID_PARAMETER Device is invalid.
910 @retval EFI_INVALID_PARAMETER IdentifyData is NULL.
915 IdeInitDisqualifyMode (
916 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
919 IN EFI_ATA_COLLECTIVE_MODE
*BadModes
922 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
925 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
926 ASSERT (Private
!= NULL
);
928 if ((Channel
>= This
->ChannelCount
) || (BadModes
== NULL
) || (Device
>= Private
->DeviceCount
)) {
929 return EFI_INVALID_PARAMETER
;
932 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
935 // Record the disqualified modes per channel per device. From ATA/ATAPI spec,
936 // if a mode is not supported, the modes higher than it is also not supported.
939 &(Private
->DisqualifiedModes
[DeviceIndex
]),
941 sizeof (EFI_ATA_COLLECTIVE_MODE
)
948 Returns the information about the optimum modes for the specified IDE device.
950 This function is used by the driver entity to obtain the optimum ATA modes for
951 a specific device. The IDE controller driver takes into account the following
952 while calculating the mode:
953 - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
954 - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()
956 The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
957 for all the devices that belong to an enumeration group before calling
958 EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.
960 The IDE controller driver will use controller- and possibly platform-specific
961 algorithms to arrive at SupportedModes. The IDE controller may base its
962 decision on user preferences and other considerations as well. This function
963 may be called multiple times because the driver entity may renegotiate the mode
964 with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().
966 The driver entity may collect timing information for various devices in any
967 order. The driver entity is responsible for making sure that all the dependencies
968 are satisfied. For example, the SupportedModes information for device A that
969 was previously returned may become stale after a call to
970 EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.
972 The buffer SupportedModes is allocated by the callee because the caller does
973 not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE
974 is defined in a way that allows for future extensibility and can be of variable
975 length. This memory pool should be deallocated by the caller when it is no
978 The IDE controller driver for a Serial ATA (SATA) controller can use this
979 member function to force a lower speed (first-generation [Gen1] speeds on a
980 second-generation [Gen2]-capable hardware). The IDE controller driver can
981 also allow the driver entity to stay with the speed that has been negotiated
982 by the physical layer.
984 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
985 @param[in] Channel A zero-based channel number.
986 @param[in] Device A zero-based device number on the Channel.
987 @param[out] SupportedModes The optimum modes for the device.
989 @retval EFI_SUCCESS SupportedModes was returned.
990 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
991 @retval EFI_INVALID_PARAMETER Device is invalid.
992 @retval EFI_INVALID_PARAMETER SupportedModes is NULL.
993 @retval EFI_NOT_READY Modes cannot be calculated due to a lack of
994 data. This error may happen if
995 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()
996 and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData()
997 were not called for at least one drive in the
998 same enumeration group.
1003 IdeInitCalculateMode (
1004 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
1007 OUT EFI_ATA_COLLECTIVE_MODE
**SupportedModes
1010 EFI_SATA_CONTROLLER_PRIVATE_DATA
*Private
;
1011 EFI_IDENTIFY_DATA
*IdentifyData
;
1012 BOOLEAN IdentifyValid
;
1013 EFI_ATA_COLLECTIVE_MODE
*DisqualifiedModes
;
1014 UINT16 SelectedMode
;
1018 Private
= SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This
);
1019 ASSERT (Private
!= NULL
);
1021 if ((Channel
>= This
->ChannelCount
) || (SupportedModes
== NULL
) || (Device
>= Private
->DeviceCount
)) {
1022 return EFI_INVALID_PARAMETER
;
1025 *SupportedModes
= AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE
));
1026 if (*SupportedModes
== NULL
) {
1027 ASSERT (*SupportedModes
!= NULL
);
1028 return EFI_OUT_OF_RESOURCES
;
1031 DeviceIndex
= FlatDeviceIndex (Private
, Channel
, Device
);
1033 IdentifyData
= &(Private
->IdentifyData
[DeviceIndex
]);
1034 IdentifyValid
= Private
->IdentifyValid
[DeviceIndex
];
1035 DisqualifiedModes
= &(Private
->DisqualifiedModes
[DeviceIndex
]);
1038 // Make sure we've got the valid identify data of the device from SubmitData()
1040 if (!IdentifyValid
) {
1041 FreePool (*SupportedModes
);
1042 return EFI_NOT_READY
;
1045 Status
= CalculateBestPioMode (
1047 (DisqualifiedModes
->PioMode
.Valid
? ((UINT16
*) &(DisqualifiedModes
->PioMode
.Mode
)) : NULL
),
1050 if (!EFI_ERROR (Status
)) {
1051 (*SupportedModes
)->PioMode
.Valid
= TRUE
;
1052 (*SupportedModes
)->PioMode
.Mode
= SelectedMode
;
1055 (*SupportedModes
)->PioMode
.Valid
= FALSE
;
1057 DEBUG ((EFI_D_INFO
, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes
)->PioMode
.Mode
));
1059 Status
= CalculateBestUdmaMode (
1061 (DisqualifiedModes
->UdmaMode
.Valid
? ((UINT16
*) &(DisqualifiedModes
->UdmaMode
.Mode
)) : NULL
),
1065 if (!EFI_ERROR (Status
)) {
1066 (*SupportedModes
)->UdmaMode
.Valid
= TRUE
;
1067 (*SupportedModes
)->UdmaMode
.Mode
= SelectedMode
;
1070 (*SupportedModes
)->UdmaMode
.Valid
= FALSE
;
1072 DEBUG ((EFI_D_INFO
, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes
)->UdmaMode
.Mode
));
1075 // The modes other than PIO and UDMA are not supported
1081 Commands the IDE controller driver to program the IDE controller hardware
1082 so that the specified device can operate at the specified mode.
1084 This function is used by the driver entity to instruct the IDE controller
1085 driver to program the IDE controller hardware to the specified modes. This
1086 function can be called only once for a particular device. For a Serial ATA
1087 (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-
1088 specific programming may be required.
1090 @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.
1091 @param[in] Channel Zero-based channel number.
1092 @param[in] Device Zero-based device number on the Channel.
1093 @param[in] Modes The modes to set.
1095 @retval EFI_SUCCESS The command was accepted without any errors.
1096 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).
1097 @retval EFI_INVALID_PARAMETER Device is invalid.
1098 @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data.
1099 @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure.
1100 The driver entity should not use this device.
1106 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL
*This
,
1109 IN EFI_ATA_COLLECTIVE_MODE
*Modes