]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SataControllerDxe / SataController.c
CommitLineData
fda951df
FT
1/** @file\r
2 This driver module produces IDE_CONTROLLER_INIT protocol for Sata Controllers.\r
3\r
d1102dba 4 Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>\r
24fee052 5 Copyright (c) 2018, ARM Ltd. All rights reserved.<BR>\r
9d510e61 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
fda951df
FT
7\r
8**/\r
9\r
10#include "SataController.h"\r
11\r
12///\r
13/// EFI_DRIVER_BINDING_PROTOCOL instance\r
14///\r
15EFI_DRIVER_BINDING_PROTOCOL gSataControllerDriverBinding = {\r
16 SataControllerSupported,\r
17 SataControllerStart,\r
18 SataControllerStop,\r
19 0xa,\r
20 NULL,\r
21 NULL\r
22};\r
23\r
24/**\r
25 Read AHCI Operation register.\r
26\r
27 @param PciIo The PCI IO protocol instance.\r
28 @param Offset The operation register offset.\r
29\r
30 @return The register content read.\r
31\r
32**/\r
33UINT32\r
34EFIAPI\r
35AhciReadReg (\r
36 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
37 IN UINT32 Offset\r
38 )\r
39{\r
40 UINT32 Data;\r
41\r
42 ASSERT (PciIo != NULL);\r
d1102dba 43\r
fda951df
FT
44 Data = 0;\r
45\r
46 PciIo->Mem.Read (\r
47 PciIo,\r
48 EfiPciIoWidthUint32,\r
49 AHCI_BAR_INDEX,\r
50 (UINT64) Offset,\r
51 1,\r
52 &Data\r
53 );\r
54\r
55 return Data;\r
56}\r
57\r
58/**\r
59 This function is used to calculate the best PIO mode supported by specific IDE device\r
60\r
61 @param IdentifyData The identify data of specific IDE device.\r
62 @param DisPioMode Disqualified PIO modes collection.\r
63 @param SelectedMode Available PIO modes collection.\r
64\r
65 @retval EFI_SUCCESS Best PIO modes are returned.\r
66 @retval EFI_UNSUPPORTED The device doesn't support PIO mode,\r
67 or all supported modes have been disqualified.\r
68**/\r
69EFI_STATUS\r
70CalculateBestPioMode (\r
71 IN EFI_IDENTIFY_DATA *IdentifyData,\r
72 IN UINT16 *DisPioMode OPTIONAL,\r
73 OUT UINT16 *SelectedMode\r
74 )\r
75{\r
76 UINT16 PioMode;\r
77 UINT16 AdvancedPioMode;\r
78 UINT16 Temp;\r
79 UINT16 Index;\r
80 UINT16 MinimumPioCycleTime;\r
81\r
82 Temp = 0xff;\r
83\r
84 PioMode = (UINT8) (((ATA5_IDENTIFY_DATA *) (&(IdentifyData->AtaData)))->pio_cycle_timing >> 8);\r
85\r
86 //\r
87 // See whether Identify Data word 64 - 70 are valid\r
88 //\r
89 if ((IdentifyData->AtaData.field_validity & 0x02) == 0x02) {\r
90\r
91 AdvancedPioMode = IdentifyData->AtaData.advanced_pio_modes;\r
92 DEBUG ((EFI_D_INFO, "CalculateBestPioMode: AdvancedPioMode = %x\n", AdvancedPioMode));\r
93\r
94 for (Index = 0; Index < 8; Index++) {\r
95 if ((AdvancedPioMode & 0x01) != 0) {\r
96 Temp = Index;\r
97 }\r
98\r
99 AdvancedPioMode >>= 1;\r
100 }\r
101\r
102 //\r
103 // If Temp is modified, mean the advanced_pio_modes is not zero;\r
104 // if Temp is not modified, mean there is no advanced PIO mode supported,\r
105 // the best PIO Mode is the value in pio_cycle_timing.\r
106 //\r
107 if (Temp != 0xff) {\r
108 AdvancedPioMode = (UINT16) (Temp + 3);\r
109 } else {\r
110 AdvancedPioMode = PioMode;\r
111 }\r
112\r
113 //\r
114 // Limit the PIO mode to at most PIO4.\r
115 //\r
116 PioMode = (UINT16) MIN (AdvancedPioMode, 4);\r
117\r
118 MinimumPioCycleTime = IdentifyData->AtaData.min_pio_cycle_time_with_flow_control;\r
119\r
120 if (MinimumPioCycleTime <= 120) {\r
121 PioMode = (UINT16) MIN (4, PioMode);\r
122 } else if (MinimumPioCycleTime <= 180) {\r
123 PioMode = (UINT16) MIN (3, PioMode);\r
124 } else if (MinimumPioCycleTime <= 240) {\r
125 PioMode = (UINT16) MIN (2, PioMode);\r
126 } else {\r
127 PioMode = 0;\r
128 }\r
129\r
130 //\r
131 // Degrade the PIO mode if the mode has been disqualified\r
132 //\r
133 if (DisPioMode != NULL) {\r
134 if (*DisPioMode < 2) {\r
135 return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2\r
136 }\r
137\r
138 if (PioMode >= *DisPioMode) {\r
139 PioMode = (UINT16) (*DisPioMode - 1);\r
140 }\r
141 }\r
142\r
143 if (PioMode < 2) {\r
144 *SelectedMode = 1; // ATA_PIO_MODE_BELOW_2;\r
145 } else {\r
146 *SelectedMode = PioMode; // ATA_PIO_MODE_2 to ATA_PIO_MODE_4;\r
147 }\r
148\r
149 } else {\r
150 //\r
151 // Identify Data word 64 - 70 are not valid\r
152 // Degrade the PIO mode if the mode has been disqualified\r
153 //\r
154 if (DisPioMode != NULL) {\r
155 if (*DisPioMode < 2) {\r
156 return EFI_UNSUPPORTED; // no mode below ATA_PIO_MODE_BELOW_2\r
157 }\r
158\r
159 if (PioMode == *DisPioMode) {\r
160 PioMode--;\r
161 }\r
162 }\r
163\r
164 if (PioMode < 2) {\r
165 *SelectedMode = 1; // ATA_PIO_MODE_BELOW_2;\r
166 } else {\r
167 *SelectedMode = 2; // ATA_PIO_MODE_2;\r
168 }\r
169\r
170 }\r
171\r
172 return EFI_SUCCESS;\r
173}\r
174\r
175/**\r
176 This function is used to calculate the best UDMA mode supported by specific IDE device\r
177\r
178 @param IdentifyData The identify data of specific IDE device.\r
179 @param DisUDmaMode Disqualified UDMA modes collection.\r
180 @param SelectedMode Available UDMA modes collection.\r
181\r
182 @retval EFI_SUCCESS Best UDMA modes are returned.\r
183 @retval EFI_UNSUPPORTED The device doesn't support UDMA mode,\r
184 or all supported modes have been disqualified.\r
185**/\r
186EFI_STATUS\r
187CalculateBestUdmaMode (\r
188 IN EFI_IDENTIFY_DATA *IdentifyData,\r
189 IN UINT16 *DisUDmaMode OPTIONAL,\r
190 OUT UINT16 *SelectedMode\r
191 )\r
192{\r
193 UINT16 TempMode;\r
194 UINT16 DeviceUDmaMode;\r
195\r
196 DeviceUDmaMode = 0;\r
197\r
198 //\r
199 // Check whether the WORD 88 (supported UltraDMA by drive) is valid\r
200 //\r
201 if ((IdentifyData->AtaData.field_validity & 0x04) == 0x00) {\r
202 return EFI_UNSUPPORTED;\r
203 }\r
204\r
205 DeviceUDmaMode = IdentifyData->AtaData.ultra_dma_mode;\r
206 DEBUG ((EFI_D_INFO, "CalculateBestUdmaMode: DeviceUDmaMode = %x\n", DeviceUDmaMode));\r
207 DeviceUDmaMode &= 0x3f;\r
208 TempMode = 0; // initialize it to UDMA-0\r
209\r
210 while ((DeviceUDmaMode >>= 1) != 0) {\r
211 TempMode++;\r
212 }\r
213\r
214 //\r
215 // Degrade the UDMA mode if the mode has been disqualified\r
216 //\r
217 if (DisUDmaMode != NULL) {\r
218 if (*DisUDmaMode == 0) {\r
219 *SelectedMode = 0;\r
220 return EFI_UNSUPPORTED; // no mode below ATA_UDMA_MODE_0\r
221 }\r
222\r
223 if (TempMode >= *DisUDmaMode) {\r
224 TempMode = (UINT16) (*DisUDmaMode - 1);\r
225 }\r
226 }\r
227\r
228 //\r
229 // Possible returned mode is between ATA_UDMA_MODE_0 and ATA_UDMA_MODE_5\r
230 //\r
231 *SelectedMode = TempMode;\r
232\r
233 return EFI_SUCCESS;\r
234}\r
235\r
236/**\r
237 The Entry Point of module. It follows the standard UEFI driver model.\r
238\r
d1102dba 239 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
fda951df 240 @param[in] SystemTable A pointer to the EFI System Table.\r
d1102dba 241\r
fda951df
FT
242 @retval EFI_SUCCESS The entry point is executed successfully.\r
243 @retval other Some error occurs when executing this entry point.\r
244\r
245**/\r
246EFI_STATUS\r
247EFIAPI\r
248InitializeSataControllerDriver (\r
249 IN EFI_HANDLE ImageHandle,\r
250 IN EFI_SYSTEM_TABLE *SystemTable\r
251 )\r
252{\r
253 EFI_STATUS Status;\r
254\r
255 //\r
256 // Install driver model protocol(s).\r
257 //\r
258 Status = EfiLibInstallDriverBindingComponentName2 (\r
259 ImageHandle,\r
260 SystemTable,\r
261 &gSataControllerDriverBinding,\r
262 ImageHandle,\r
263 &gSataControllerComponentName,\r
264 &gSataControllerComponentName2\r
265 );\r
266 ASSERT_EFI_ERROR (Status);\r
267\r
268 return Status;\r
269}\r
270\r
271/**\r
272 Supported function of Driver Binding protocol for this driver.\r
273 Test to see if this driver supports ControllerHandle.\r
274\r
275 @param This Protocol instance pointer.\r
276 @param Controller Handle of device to test.\r
277 @param RemainingDevicePath A pointer to the device path.\r
278 it should be ignored by device driver.\r
279\r
280 @retval EFI_SUCCESS This driver supports this device.\r
281 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
282 @retval other This driver does not support this device.\r
283\r
284**/\r
285EFI_STATUS\r
286EFIAPI\r
287SataControllerSupported (\r
288 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
289 IN EFI_HANDLE Controller,\r
290 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
291 )\r
292{\r
293 EFI_STATUS Status;\r
294 EFI_PCI_IO_PROTOCOL *PciIo;\r
295 PCI_TYPE00 PciData;\r
296\r
297 //\r
298 // Attempt to open PCI I/O Protocol\r
299 //\r
300 Status = gBS->OpenProtocol (\r
301 Controller,\r
302 &gEfiPciIoProtocolGuid,\r
303 (VOID **) &PciIo,\r
304 This->DriverBindingHandle,\r
305 Controller,\r
306 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
307 );\r
308 if (EFI_ERROR (Status)) {\r
309 return Status;\r
310 }\r
311\r
312 //\r
313 // Now further check the PCI header: Base Class (offset 0x0B) and\r
314 // Sub Class (offset 0x0A). This controller should be an SATA controller\r
315 //\r
316 Status = PciIo->Pci.Read (\r
317 PciIo,\r
318 EfiPciIoWidthUint8,\r
319 PCI_CLASSCODE_OFFSET,\r
320 sizeof (PciData.Hdr.ClassCode),\r
321 PciData.Hdr.ClassCode\r
322 );\r
323 if (EFI_ERROR (Status)) {\r
324 return EFI_UNSUPPORTED;\r
325 }\r
326\r
327 if (IS_PCI_IDE (&PciData) || IS_PCI_SATADPA (&PciData)) {\r
328 return EFI_SUCCESS;\r
329 }\r
330\r
331 return EFI_UNSUPPORTED;\r
332}\r
333\r
334/**\r
d1102dba 335 This routine is called right after the .Supported() called and\r
fda951df
FT
336 Start this driver on ControllerHandle.\r
337\r
338 @param This Protocol instance pointer.\r
339 @param Controller Handle of device to bind driver to.\r
340 @param RemainingDevicePath A pointer to the device path.\r
341 it should be ignored by device driver.\r
342\r
343 @retval EFI_SUCCESS This driver is added to this device.\r
344 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
345 @retval other Some error occurs when binding this driver to this device.\r
346\r
347**/\r
348EFI_STATUS\r
349EFIAPI\r
350SataControllerStart (\r
351 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
352 IN EFI_HANDLE Controller,\r
353 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
354 )\r
355{\r
356 EFI_STATUS Status;\r
357 EFI_PCI_IO_PROTOCOL *PciIo;\r
358 PCI_TYPE00 PciData;\r
359 EFI_SATA_CONTROLLER_PRIVATE_DATA *Private;\r
360 UINT32 Data32;\r
361 UINTN TotalCount;\r
24fee052 362 UINT64 Supports;\r
aa4240ed 363 UINT8 MaxPortNumber;\r
fda951df
FT
364\r
365 DEBUG ((EFI_D_INFO, "SataControllerStart start\n"));\r
366\r
367 Private = NULL;\r
368\r
369 //\r
370 // Now test and open PCI I/O Protocol\r
371 //\r
372 Status = gBS->OpenProtocol (\r
373 Controller,\r
374 &gEfiPciIoProtocolGuid,\r
375 (VOID **) &PciIo,\r
376 This->DriverBindingHandle,\r
377 Controller,\r
378 EFI_OPEN_PROTOCOL_BY_DRIVER\r
379 );\r
380 if (EFI_ERROR (Status)) {\r
381 DEBUG ((EFI_D_ERROR, "SataControllerStart error. return status = %r\n", Status));\r
382 return Status;\r
383 }\r
384\r
385 //\r
386 // Allocate Sata Private Data structure\r
387 //\r
388 Private = AllocateZeroPool (sizeof (EFI_SATA_CONTROLLER_PRIVATE_DATA));\r
389 if (Private == NULL) {\r
390 Status = EFI_OUT_OF_RESOURCES;\r
391 goto Done;\r
392 }\r
393\r
394 //\r
395 // Initialize Sata Private Data\r
396 //\r
397 Private->Signature = SATA_CONTROLLER_SIGNATURE;\r
398 Private->PciIo = PciIo;\r
399 Private->IdeInit.GetChannelInfo = IdeInitGetChannelInfo;\r
400 Private->IdeInit.NotifyPhase = IdeInitNotifyPhase;\r
401 Private->IdeInit.SubmitData = IdeInitSubmitData;\r
402 Private->IdeInit.DisqualifyMode = IdeInitDisqualifyMode;\r
403 Private->IdeInit.CalculateMode = IdeInitCalculateMode;\r
404 Private->IdeInit.SetTiming = IdeInitSetTiming;\r
405 Private->IdeInit.EnumAll = SATA_ENUMER_ALL;\r
24fee052
SM
406 Private->PciAttributesChanged = FALSE;\r
407\r
408 //\r
409 // Save original PCI attributes\r
410 //\r
411 Status = PciIo->Attributes (\r
412 PciIo,\r
413 EfiPciIoAttributeOperationGet,\r
414 0,\r
415 &Private->OriginalPciAttributes\r
416 );\r
417 if (EFI_ERROR (Status)) {\r
418 goto Done;\r
419 }\r
420\r
421 DEBUG ((\r
422 EFI_D_INFO,\r
423 "Original PCI Attributes = 0x%llx\n",\r
424 Private->OriginalPciAttributes\r
425 ));\r
426\r
427 Status = PciIo->Attributes (\r
428 PciIo,\r
429 EfiPciIoAttributeOperationSupported,\r
430 0,\r
431 &Supports\r
432 );\r
433 if (EFI_ERROR (Status)) {\r
434 goto Done;\r
435 }\r
436\r
437 DEBUG ((EFI_D_INFO, "Supported PCI Attributes = 0x%llx\n", Supports));\r
438\r
439 Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;\r
440 Status = PciIo->Attributes (\r
441 PciIo,\r
442 EfiPciIoAttributeOperationEnable,\r
443 Supports,\r
444 NULL\r
445 );\r
446 if (EFI_ERROR (Status)) {\r
447 goto Done;\r
448 }\r
449\r
450 DEBUG ((EFI_D_INFO, "Enabled PCI Attributes = 0x%llx\n", Supports));\r
451 Private->PciAttributesChanged = TRUE;\r
fda951df
FT
452\r
453 Status = PciIo->Pci.Read (\r
454 PciIo,\r
455 EfiPciIoWidthUint8,\r
456 PCI_CLASSCODE_OFFSET,\r
457 sizeof (PciData.Hdr.ClassCode),\r
458 PciData.Hdr.ClassCode\r
459 );\r
24fee052
SM
460 if (EFI_ERROR (Status)) {\r
461 ASSERT (FALSE);\r
462 goto Done;\r
463 }\r
fda951df
FT
464\r
465 if (IS_PCI_IDE (&PciData)) {\r
466 Private->IdeInit.ChannelCount = IDE_MAX_CHANNEL;\r
467 Private->DeviceCount = IDE_MAX_DEVICES;\r
468 } else if (IS_PCI_SATADPA (&PciData)) {\r
469 //\r
aa4240ed
SZ
470 // Read Ports Implemented(PI) to calculate max port number (0 based).\r
471 //\r
472 Data32 = AhciReadReg (PciIo, R_AHCI_PI);\r
473 DEBUG ((DEBUG_INFO, "Ports Implemented(PI) = 0x%x\n", Data32));\r
474 if (Data32 == 0) {\r
475 Status = EFI_UNSUPPORTED;\r
476 goto Done;\r
477 }\r
478 MaxPortNumber = 31;\r
479 while (MaxPortNumber > 0) {\r
cd69c873 480 if ((Data32 & ((UINT32)1 << MaxPortNumber)) != 0) {\r
aa4240ed
SZ
481 break;\r
482 }\r
483 MaxPortNumber--;\r
484 }\r
485 //\r
486 // Make the ChannelCount equal to the max port number (0 based) plus 1.\r
487 //\r
488 Private->IdeInit.ChannelCount = MaxPortNumber + 1;\r
489\r
490 //\r
491 // Read HBA Capabilities(CAP) to get Supports Port Multiplier(SPM).\r
fda951df
FT
492 //\r
493 Data32 = AhciReadReg (PciIo, R_AHCI_CAP);\r
aa4240ed 494 DEBUG ((DEBUG_INFO, "HBA Capabilities(CAP) = 0x%x\n", Data32));\r
fda951df
FT
495 Private->DeviceCount = AHCI_MAX_DEVICES;\r
496 if ((Data32 & B_AHCI_CAP_SPM) == B_AHCI_CAP_SPM) {\r
497 Private->DeviceCount = AHCI_MULTI_MAX_DEVICES;\r
498 }\r
499 }\r
500\r
501 TotalCount = (UINTN) (Private->IdeInit.ChannelCount) * (UINTN) (Private->DeviceCount);\r
502 Private->DisqualifiedModes = AllocateZeroPool ((sizeof (EFI_ATA_COLLECTIVE_MODE)) * TotalCount);\r
503 if (Private->DisqualifiedModes == NULL) {\r
504 Status = EFI_OUT_OF_RESOURCES;\r
505 goto Done;\r
506 }\r
507\r
508 Private->IdentifyData = AllocateZeroPool ((sizeof (EFI_IDENTIFY_DATA)) * TotalCount);\r
509 if (Private->IdentifyData == NULL) {\r
510 Status = EFI_OUT_OF_RESOURCES;\r
511 goto Done;\r
512 }\r
513\r
514 Private->IdentifyValid = AllocateZeroPool ((sizeof (BOOLEAN)) * TotalCount);\r
515 if (Private->IdentifyValid == NULL) {\r
516 Status = EFI_OUT_OF_RESOURCES;\r
517 goto Done;\r
518 }\r
519\r
520 //\r
521 // Install IDE Controller Init Protocol to this instance\r
522 //\r
523 Status = gBS->InstallMultipleProtocolInterfaces (\r
524 &Controller,\r
525 &gEfiIdeControllerInitProtocolGuid,\r
526 &(Private->IdeInit),\r
527 NULL\r
528 );\r
529\r
530Done:\r
531 if (EFI_ERROR (Status)) {\r
532\r
533 gBS->CloseProtocol (\r
534 Controller,\r
535 &gEfiPciIoProtocolGuid,\r
536 This->DriverBindingHandle,\r
537 Controller\r
538 );\r
539 if (Private != NULL) {\r
540 if (Private->DisqualifiedModes != NULL) {\r
541 FreePool (Private->DisqualifiedModes);\r
542 }\r
543 if (Private->IdentifyData != NULL) {\r
544 FreePool (Private->IdentifyData);\r
545 }\r
546 if (Private->IdentifyValid != NULL) {\r
547 FreePool (Private->IdentifyValid);\r
548 }\r
24fee052
SM
549 if (Private->PciAttributesChanged) {\r
550 //\r
551 // Restore original PCI attributes\r
552 //\r
553 PciIo->Attributes (\r
554 PciIo,\r
555 EfiPciIoAttributeOperationSet,\r
556 Private->OriginalPciAttributes,\r
557 NULL\r
558 );\r
559 }\r
fda951df
FT
560 FreePool (Private);\r
561 }\r
562 }\r
563\r
564 DEBUG ((EFI_D_INFO, "SataControllerStart end with %r\n", Status));\r
565\r
566 return Status;\r
567}\r
568\r
569/**\r
570 Stop this driver on ControllerHandle.\r
571\r
572 @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
573 @param Controller A handle to the device being stopped.\r
574 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
d1102dba 575 @param ChildHandleBuffer An array of child handles to be freed.\r
fda951df
FT
576\r
577 @retval EFI_SUCCESS This driver is removed from this device.\r
578 @retval other Some error occurs when removing this driver from this device.\r
579\r
580**/\r
581EFI_STATUS\r
582EFIAPI\r
583SataControllerStop (\r
584 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
585 IN EFI_HANDLE Controller,\r
586 IN UINTN NumberOfChildren,\r
587 IN EFI_HANDLE *ChildHandleBuffer\r
588 )\r
589{\r
590 EFI_STATUS Status;\r
591 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;\r
592 EFI_SATA_CONTROLLER_PRIVATE_DATA *Private;\r
593\r
594 //\r
595 // Open the produced protocol\r
596 //\r
597 Status = gBS->OpenProtocol (\r
598 Controller,\r
599 &gEfiIdeControllerInitProtocolGuid,\r
600 (VOID **) &IdeInit,\r
601 This->DriverBindingHandle,\r
602 Controller,\r
603 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
604 );\r
605 if (EFI_ERROR (Status)) {\r
606 return EFI_UNSUPPORTED;\r
607 }\r
608\r
609 Private = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (IdeInit);\r
610 ASSERT (Private != NULL);\r
611\r
612 //\r
613 // Uninstall the IDE Controller Init Protocol from this instance\r
614 //\r
615 Status = gBS->UninstallMultipleProtocolInterfaces (\r
616 Controller,\r
617 &gEfiIdeControllerInitProtocolGuid,\r
618 &(Private->IdeInit),\r
619 NULL\r
620 );\r
621 if (EFI_ERROR (Status)) {\r
622 return Status;\r
623 }\r
624\r
625 if (Private != NULL) {\r
626 if (Private->DisqualifiedModes != NULL) {\r
627 FreePool (Private->DisqualifiedModes);\r
628 }\r
629 if (Private->IdentifyData != NULL) {\r
630 FreePool (Private->IdentifyData);\r
631 }\r
632 if (Private->IdentifyValid != NULL) {\r
633 FreePool (Private->IdentifyValid);\r
634 }\r
24fee052
SM
635 if (Private->PciAttributesChanged) {\r
636 //\r
637 // Restore original PCI attributes\r
638 //\r
639 Private->PciIo->Attributes (\r
640 Private->PciIo,\r
641 EfiPciIoAttributeOperationSet,\r
642 Private->OriginalPciAttributes,\r
643 NULL\r
644 );\r
645 }\r
fda951df
FT
646 FreePool (Private);\r
647 }\r
648\r
649 //\r
650 // Close protocols opened by Sata Controller driver\r
651 //\r
652 return gBS->CloseProtocol (\r
653 Controller,\r
654 &gEfiPciIoProtocolGuid,\r
655 This->DriverBindingHandle,\r
656 Controller\r
657 );\r
658}\r
659\r
660/**\r
661 Calculate the flat array subscript of a (Channel, Device) pair.\r
662\r
663 @param[in] Private The private data structure corresponding to the\r
664 SATA controller that attaches the device for\r
665 which the flat array subscript is being\r
666 calculated.\r
667\r
668 @param[in] Channel The channel (ie. port) number on the SATA\r
669 controller that the device is attached to.\r
670\r
671 @param[in] Device The device number on the channel.\r
672\r
673 @return The flat array subscript suitable for indexing DisqualifiedModes,\r
674 IdentifyData, and IdentifyValid.\r
675**/\r
676STATIC\r
677UINTN\r
678FlatDeviceIndex (\r
679 IN CONST EFI_SATA_CONTROLLER_PRIVATE_DATA *Private,\r
680 IN UINTN Channel,\r
681 IN UINTN Device\r
682 )\r
683{\r
684 ASSERT (Private != NULL);\r
685 ASSERT (Channel < Private->IdeInit.ChannelCount);\r
686 ASSERT (Device < Private->DeviceCount);\r
687\r
688 return Channel * Private->DeviceCount + Device;\r
689}\r
690\r
691//\r
692// Interface functions of IDE_CONTROLLER_INIT protocol\r
693//\r
694/**\r
695 Returns the information about the specified IDE channel.\r
d1102dba 696\r
fda951df 697 This function can be used to obtain information about a particular IDE channel.\r
d1102dba
LG
698 The driver entity uses this information during the enumeration process.\r
699\r
700 If Enabled is set to FALSE, the driver entity will not scan the channel. Note\r
fda951df 701 that it will not prevent an operating system driver from scanning the channel.\r
d1102dba
LG
702\r
703 For most of today's controllers, MaxDevices will either be 1 or 2. For SATA\r
704 controllers, this value will always be 1. SATA configurations can contain SATA\r
fda951df 705 port multipliers. SATA port multipliers behave like SATA bridges and can support\r
d1102dba
LG
706 up to 16 devices on the other side. If a SATA port out of the IDE controller\r
707 is connected to a port multiplier, MaxDevices will be set to the number of SATA\r
708 devices that the port multiplier supports. Because today's port multipliers\r
709 support up to fifteen SATA devices, this number can be as large as fifteen. The IDE\r
710 bus driver is required to scan for the presence of port multipliers behind an SATA\r
711 controller and enumerate up to MaxDevices number of devices behind the port\r
712 multiplier.\r
713\r
714 In this context, the devices behind a port multiplier constitute a channel.\r
715\r
fda951df
FT
716 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.\r
717 @param[in] Channel Zero-based channel number.\r
d1102dba 718 @param[out] Enabled TRUE if this channel is enabled. Disabled channels\r
fda951df
FT
719 are not scanned to see if any devices are present.\r
720 @param[out] MaxDevices The maximum number of IDE devices that the bus driver\r
d1102dba
LG
721 can expect on this channel. For the ATA/ATAPI\r
722 specification, version 6, this number will either be\r
723 one or two. For Serial ATA (SATA) configurations with a\r
fda951df
FT
724 port multiplier, this number can be as large as fifteen.\r
725\r
726 @retval EFI_SUCCESS Information was returned without any errors.\r
727 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).\r
728\r
729**/\r
730EFI_STATUS\r
731EFIAPI\r
732IdeInitGetChannelInfo (\r
733 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,\r
734 IN UINT8 Channel,\r
735 OUT BOOLEAN *Enabled,\r
736 OUT UINT8 *MaxDevices\r
737 )\r
738{\r
739 EFI_SATA_CONTROLLER_PRIVATE_DATA *Private;\r
740 Private = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);\r
741 ASSERT (Private != NULL);\r
742\r
743 if (Channel < This->ChannelCount) {\r
744 *Enabled = TRUE;\r
745 *MaxDevices = Private->DeviceCount;\r
746 return EFI_SUCCESS;\r
747 }\r
748\r
749 *Enabled = FALSE;\r
750 return EFI_INVALID_PARAMETER;\r
751}\r
752\r
753/**\r
754 The notifications from the driver entity that it is about to enter a certain\r
755 phase of the IDE channel enumeration process.\r
d1102dba
LG
756\r
757 This function can be used to notify the IDE controller driver to perform\r
758 specific actions, including any chipset-specific initialization, so that the\r
759 chipset is ready to enter the next phase. Seven notification points are defined\r
760 at this time.\r
761\r
762 More synchronization points may be added as required in the future.\r
fda951df
FT
763\r
764 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL\r
765 instance.\r
766 @param[in] Phase The phase during enumeration.\r
767 @param[in] Channel Zero-based channel number.\r
768\r
769 @retval EFI_SUCCESS The notification was accepted without any errors.\r
770 @retval EFI_UNSUPPORTED Phase is not supported.\r
771 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).\r
d1102dba
LG
772 @retval EFI_NOT_READY This phase cannot be entered at this time; for\r
773 example, an attempt was made to enter a Phase\r
774 without having entered one or more previous\r
fda951df
FT
775 Phase.\r
776\r
777**/\r
778EFI_STATUS\r
779EFIAPI\r
780IdeInitNotifyPhase (\r
781 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,\r
782 IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase,\r
783 IN UINT8 Channel\r
784 )\r
785{\r
786 return EFI_SUCCESS;\r
787}\r
788\r
789/**\r
790 Submits the device information to the IDE controller driver.\r
791\r
d1102dba
LG
792 This function is used by the driver entity to pass detailed information about\r
793 a particular device to the IDE controller driver. The driver entity obtains\r
fda951df 794 this information by issuing an ATA or ATAPI IDENTIFY_DEVICE command. IdentifyData\r
d1102dba
LG
795 is the pointer to the response data buffer. The IdentifyData buffer is owned\r
796 by the driver entity, and the IDE controller driver must make a local copy\r
797 of the entire buffer or parts of the buffer as needed. The original IdentifyData\r
fda951df 798 buffer pointer may not be valid when\r
d1102dba 799\r
fda951df
FT
800 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() or\r
801 - EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() is called at a later point.\r
d1102dba
LG
802\r
803 The IDE controller driver may consult various fields of EFI_IDENTIFY_DATA to\r
804 compute the optimum mode for the device. These fields are not limited to the\r
805 timing information. For example, an implementation of the IDE controller driver\r
806 may examine the vendor and type/mode field to match known bad drives.\r
807\r
808 The driver entity may submit drive information in any order, as long as it\r
809 submits information for all the devices belonging to the enumeration group\r
fda951df
FT
810 before EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() is called for any device\r
811 in that enumeration group. If a device is absent, EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()\r
d1102dba
LG
812 should be called with IdentifyData set to NULL. The IDE controller driver may\r
813 not have any other mechanism to know whether a device is present or not. Therefore,\r
814 setting IdentifyData to NULL does not constitute an error condition.\r
815 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData() can be called only once for a\r
816 given (Channel, Device) pair.\r
817\r
fda951df
FT
818 @param[in] This A pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.\r
819 @param[in] Channel Zero-based channel number.\r
820 @param[in] Device Zero-based device number on the Channel.\r
821 @param[in] IdentifyData The device's response to the ATA IDENTIFY_DEVICE command.\r
822\r
823 @retval EFI_SUCCESS The information was accepted without any errors.\r
824 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).\r
825 @retval EFI_INVALID_PARAMETER Device is invalid.\r
826\r
827**/\r
828EFI_STATUS\r
829EFIAPI\r
830IdeInitSubmitData (\r
831 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,\r
832 IN UINT8 Channel,\r
833 IN UINT8 Device,\r
834 IN EFI_IDENTIFY_DATA *IdentifyData\r
835 )\r
836{\r
837 EFI_SATA_CONTROLLER_PRIVATE_DATA *Private;\r
838 UINTN DeviceIndex;\r
839\r
840 Private = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);\r
841 ASSERT (Private != NULL);\r
842\r
843 if ((Channel >= This->ChannelCount) || (Device >= Private->DeviceCount)) {\r
844 return EFI_INVALID_PARAMETER;\r
845 }\r
846\r
847 DeviceIndex = FlatDeviceIndex (Private, Channel, Device);\r
848\r
849 //\r
850 // Make a local copy of device's IdentifyData and mark the valid flag\r
851 //\r
852 if (IdentifyData != NULL) {\r
853 CopyMem (\r
854 &(Private->IdentifyData[DeviceIndex]),\r
855 IdentifyData,\r
856 sizeof (EFI_IDENTIFY_DATA)\r
857 );\r
858\r
859 Private->IdentifyValid[DeviceIndex] = TRUE;\r
860 } else {\r
861 Private->IdentifyValid[DeviceIndex] = FALSE;\r
862 }\r
863\r
864 return EFI_SUCCESS;\r
865}\r
866\r
867/**\r
868 Disqualifies specific modes for an IDE device.\r
869\r
d1102dba 870 This function allows the driver entity or other drivers (such as platform\r
fda951df 871 drivers) to reject certain timing modes and request the IDE controller driver\r
d1102dba
LG
872 to recalculate modes. This function allows the driver entity and the IDE\r
873 controller driver to negotiate the timings on a per-device basis. This function\r
874 is useful in the case of drives that lie about their capabilities. An example\r
875 is when the IDE device fails to accept the timing modes that are calculated\r
fda951df
FT
876 by the IDE controller driver based on the response to the Identify Drive command.\r
877\r
d1102dba
LG
878 If the driver entity does not want to limit the ATA timing modes and leave that\r
879 decision to the IDE controller driver, it can either not call this function for\r
880 the given device or call this function and set the Valid flag to FALSE for all\r
fda951df 881 modes that are listed in EFI_ATA_COLLECTIVE_MODE.\r
d1102dba
LG
882\r
883 The driver entity may disqualify modes for a device in any order and any number\r
fda951df 884 of times.\r
d1102dba
LG
885\r
886 This function can be called multiple times to invalidate multiple modes of the\r
887 same type (e.g., Programmed Input/Output [PIO] modes 3 and 4). See the ATA/ATAPI\r
888 specification for more information on PIO modes.\r
889\r
fda951df
FT
890 For Serial ATA (SATA) controllers, this member function can be used to disqualify\r
891 a higher transfer rate mode on a given channel. For example, a platform driver\r
d1102dba 892 may inform the IDE controller driver to not use second-generation (Gen2) speeds\r
fda951df 893 for a certain SATA drive.\r
d1102dba 894\r
fda951df
FT
895 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.\r
896 @param[in] Channel The zero-based channel number.\r
897 @param[in] Device The zero-based device number on the Channel.\r
898 @param[in] BadModes The modes that the device does not support and that\r
899 should be disqualified.\r
900\r
901 @retval EFI_SUCCESS The modes were accepted without any errors.\r
902 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).\r
903 @retval EFI_INVALID_PARAMETER Device is invalid.\r
904 @retval EFI_INVALID_PARAMETER IdentifyData is NULL.\r
d1102dba 905\r
fda951df
FT
906**/\r
907EFI_STATUS\r
908EFIAPI\r
909IdeInitDisqualifyMode (\r
910 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,\r
911 IN UINT8 Channel,\r
912 IN UINT8 Device,\r
913 IN EFI_ATA_COLLECTIVE_MODE *BadModes\r
914 )\r
915{\r
916 EFI_SATA_CONTROLLER_PRIVATE_DATA *Private;\r
917 UINTN DeviceIndex;\r
918\r
919 Private = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);\r
920 ASSERT (Private != NULL);\r
921\r
922 if ((Channel >= This->ChannelCount) || (BadModes == NULL) || (Device >= Private->DeviceCount)) {\r
923 return EFI_INVALID_PARAMETER;\r
924 }\r
925\r
926 DeviceIndex = FlatDeviceIndex (Private, Channel, Device);\r
927\r
928 //\r
929 // Record the disqualified modes per channel per device. From ATA/ATAPI spec,\r
930 // if a mode is not supported, the modes higher than it is also not supported.\r
931 //\r
932 CopyMem (\r
933 &(Private->DisqualifiedModes[DeviceIndex]),\r
934 BadModes,\r
935 sizeof (EFI_ATA_COLLECTIVE_MODE)\r
936 );\r
937\r
938 return EFI_SUCCESS;\r
939}\r
940\r
941/**\r
942 Returns the information about the optimum modes for the specified IDE device.\r
943\r
944 This function is used by the driver entity to obtain the optimum ATA modes for\r
d1102dba 945 a specific device. The IDE controller driver takes into account the following\r
fda951df
FT
946 while calculating the mode:\r
947 - The IdentifyData inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()\r
948 - The BadModes inputs to EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode()\r
949\r
d1102dba
LG
950 The driver entity is required to call EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()\r
951 for all the devices that belong to an enumeration group before calling\r
952 EFI_IDE_CONTROLLER_INIT_PROTOCOL.CalculateMode() for any device in the same group.\r
953\r
954 The IDE controller driver will use controller- and possibly platform-specific\r
955 algorithms to arrive at SupportedModes. The IDE controller may base its\r
956 decision on user preferences and other considerations as well. This function\r
957 may be called multiple times because the driver entity may renegotiate the mode\r
fda951df 958 with the IDE controller driver using EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode().\r
d1102dba
LG
959\r
960 The driver entity may collect timing information for various devices in any\r
fda951df 961 order. The driver entity is responsible for making sure that all the dependencies\r
d1102dba
LG
962 are satisfied. For example, the SupportedModes information for device A that\r
963 was previously returned may become stale after a call to\r
fda951df 964 EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyMode() for device B.\r
d1102dba
LG
965\r
966 The buffer SupportedModes is allocated by the callee because the caller does\r
967 not necessarily know the size of the buffer. The type EFI_ATA_COLLECTIVE_MODE\r
968 is defined in a way that allows for future extensibility and can be of variable\r
969 length. This memory pool should be deallocated by the caller when it is no\r
970 longer necessary.\r
971\r
972 The IDE controller driver for a Serial ATA (SATA) controller can use this\r
973 member function to force a lower speed (first-generation [Gen1] speeds on a\r
974 second-generation [Gen2]-capable hardware). The IDE controller driver can\r
975 also allow the driver entity to stay with the speed that has been negotiated\r
fda951df 976 by the physical layer.\r
d1102dba 977\r
fda951df
FT
978 @param[in] This The pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.\r
979 @param[in] Channel A zero-based channel number.\r
980 @param[in] Device A zero-based device number on the Channel.\r
981 @param[out] SupportedModes The optimum modes for the device.\r
982\r
983 @retval EFI_SUCCESS SupportedModes was returned.\r
984 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).\r
d1102dba 985 @retval EFI_INVALID_PARAMETER Device is invalid.\r
fda951df 986 @retval EFI_INVALID_PARAMETER SupportedModes is NULL.\r
d1102dba
LG
987 @retval EFI_NOT_READY Modes cannot be calculated due to a lack of\r
988 data. This error may happen if\r
989 EFI_IDE_CONTROLLER_INIT_PROTOCOL.SubmitData()\r
990 and EFI_IDE_CONTROLLER_INIT_PROTOCOL.DisqualifyData()\r
991 were not called for at least one drive in the\r
fda951df
FT
992 same enumeration group.\r
993\r
994**/\r
995EFI_STATUS\r
996EFIAPI\r
997IdeInitCalculateMode (\r
998 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,\r
999 IN UINT8 Channel,\r
1000 IN UINT8 Device,\r
1001 OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes\r
1002 )\r
1003{\r
1004 EFI_SATA_CONTROLLER_PRIVATE_DATA *Private;\r
1005 EFI_IDENTIFY_DATA *IdentifyData;\r
1006 BOOLEAN IdentifyValid;\r
1007 EFI_ATA_COLLECTIVE_MODE *DisqualifiedModes;\r
1008 UINT16 SelectedMode;\r
1009 EFI_STATUS Status;\r
1010 UINTN DeviceIndex;\r
1011\r
1012 Private = SATA_CONTROLLER_PRIVATE_DATA_FROM_THIS (This);\r
1013 ASSERT (Private != NULL);\r
1014\r
1015 if ((Channel >= This->ChannelCount) || (SupportedModes == NULL) || (Device >= Private->DeviceCount)) {\r
1016 return EFI_INVALID_PARAMETER;\r
1017 }\r
1018\r
1019 *SupportedModes = AllocateZeroPool (sizeof (EFI_ATA_COLLECTIVE_MODE));\r
1020 if (*SupportedModes == NULL) {\r
1021 ASSERT (*SupportedModes != NULL);\r
1022 return EFI_OUT_OF_RESOURCES;\r
1023 }\r
1024\r
1025 DeviceIndex = FlatDeviceIndex (Private, Channel, Device);\r
1026\r
1027 IdentifyData = &(Private->IdentifyData[DeviceIndex]);\r
1028 IdentifyValid = Private->IdentifyValid[DeviceIndex];\r
1029 DisqualifiedModes = &(Private->DisqualifiedModes[DeviceIndex]);\r
1030\r
1031 //\r
1032 // Make sure we've got the valid identify data of the device from SubmitData()\r
1033 //\r
1034 if (!IdentifyValid) {\r
1035 FreePool (*SupportedModes);\r
1036 return EFI_NOT_READY;\r
1037 }\r
1038\r
1039 Status = CalculateBestPioMode (\r
1040 IdentifyData,\r
1041 (DisqualifiedModes->PioMode.Valid ? ((UINT16 *) &(DisqualifiedModes->PioMode.Mode)) : NULL),\r
1042 &SelectedMode\r
1043 );\r
1044 if (!EFI_ERROR (Status)) {\r
1045 (*SupportedModes)->PioMode.Valid = TRUE;\r
1046 (*SupportedModes)->PioMode.Mode = SelectedMode;\r
1047\r
1048 } else {\r
1049 (*SupportedModes)->PioMode.Valid = FALSE;\r
1050 }\r
1051 DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: PioMode = %x\n", (*SupportedModes)->PioMode.Mode));\r
1052\r
1053 Status = CalculateBestUdmaMode (\r
1054 IdentifyData,\r
1055 (DisqualifiedModes->UdmaMode.Valid ? ((UINT16 *) &(DisqualifiedModes->UdmaMode.Mode)) : NULL),\r
1056 &SelectedMode\r
1057 );\r
1058\r
1059 if (!EFI_ERROR (Status)) {\r
1060 (*SupportedModes)->UdmaMode.Valid = TRUE;\r
1061 (*SupportedModes)->UdmaMode.Mode = SelectedMode;\r
1062\r
1063 } else {\r
1064 (*SupportedModes)->UdmaMode.Valid = FALSE;\r
1065 }\r
1066 DEBUG ((EFI_D_INFO, "IdeInitCalculateMode: UdmaMode = %x\n", (*SupportedModes)->UdmaMode.Mode));\r
1067\r
1068 //\r
1069 // The modes other than PIO and UDMA are not supported\r
1070 //\r
1071 return EFI_SUCCESS;\r
1072}\r
1073\r
1074/**\r
1075 Commands the IDE controller driver to program the IDE controller hardware\r
1076 so that the specified device can operate at the specified mode.\r
1077\r
d1102dba
LG
1078 This function is used by the driver entity to instruct the IDE controller\r
1079 driver to program the IDE controller hardware to the specified modes. This\r
1080 function can be called only once for a particular device. For a Serial ATA\r
fda951df
FT
1081 (SATA) Advanced Host Controller Interface (AHCI) controller, no controller-\r
1082 specific programming may be required.\r
1083\r
1084 @param[in] This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance.\r
1085 @param[in] Channel Zero-based channel number.\r
1086 @param[in] Device Zero-based device number on the Channel.\r
1087 @param[in] Modes The modes to set.\r
1088\r
1089 @retval EFI_SUCCESS The command was accepted without any errors.\r
1090 @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount).\r
1091 @retval EFI_INVALID_PARAMETER Device is invalid.\r
1092 @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data.\r
1093 @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure.\r
1094 The driver entity should not use this device.\r
1095\r
1096**/\r
1097EFI_STATUS\r
1098EFIAPI\r
1099IdeInitSetTiming (\r
1100 IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This,\r
1101 IN UINT8 Channel,\r
1102 IN UINT8 Device,\r
1103 IN EFI_ATA_COLLECTIVE_MODE *Modes\r
1104 )\r
1105{\r
1106 return EFI_SUCCESS;\r
1107}\r
1108\r