EmbeddedPkg: Fix typos in comments
[mirror_edk2.git] / EmbeddedPkg / Drivers / SataSiI3132Dxe / SataSiI3132.c
CommitLineData
f6342447
OM
1/** @file\r
2* PCIe Sata support for the Silicon Image I3132\r
3*\r
4* Copyright (c) 2011-2015, ARM Limited. All rights reserved.\r
5*\r
6* This program and the accompanying materials\r
7* are licensed and made available under the terms and conditions of the BSD License\r
8* which accompanies this distribution. The full text of the license may be found at\r
9* http://opensource.org/licenses/bsd-license.php\r
10*\r
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13*\r
14**/\r
15\r
16#include "SataSiI3132.h"\r
17\r
18#include <IndustryStandard/Acpi10.h>\r
19\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/UefiBootServicesTableLib.h>\r
22#include <Library/DxeServicesTableLib.h>\r
23#include <Library/BaseLib.h>\r
24\r
25#define ACPI_SPECFLAG_PREFETCHABLE 0x06\r
26\r
27EFI_DRIVER_BINDING_PROTOCOL\r
28gSataSiI3132DriverBinding = {\r
29 SataSiI3132DriverBindingSupported,\r
30 SataSiI3132DriverBindingStart,\r
31 SataSiI3132DriverBindingStop,\r
32 0x30,\r
33 NULL,\r
34 NULL\r
35};\r
36\r
37EFI_STATUS\r
38SataSiI3132PortConstructor (\r
39 IN SATA_SI3132_INSTANCE *SataSiI3132Instance,\r
40 IN UINTN Index\r
41 )\r
42{\r
43 EFI_STATUS Status;\r
44 SATA_SI3132_PORT *Port;\r
45 VOID *HostPRB;\r
46 EFI_PHYSICAL_ADDRESS PhysAddrHostPRB;\r
47 VOID *PciAllocMappingPRB;\r
48 UINTN NumberOfBytes;\r
49\r
50 Port = &(SataSiI3132Instance->Ports[Index]);\r
51\r
52 Port->Index = Index;\r
53 Port->RegBase = Index * 0x2000;\r
54 Port->Instance = SataSiI3132Instance;\r
55 InitializeListHead (&(Port->Devices));\r
56\r
57 NumberOfBytes = sizeof (SATA_SI3132_PRB);\r
58 Status = SataSiI3132Instance->PciIo->AllocateBuffer (\r
59 SataSiI3132Instance->PciIo, AllocateAnyPages, EfiBootServicesData,\r
60 EFI_SIZE_TO_PAGES (NumberOfBytes), &HostPRB, 0\r
61 );\r
62 if (EFI_ERROR (Status)) {\r
63 return Status;\r
64 }\r
65\r
66 // Check the alignment of the PCI Buffer\r
67 ASSERT (((UINTN)HostPRB & (0x1000 - 1)) == 0);\r
68 Status = SataSiI3132Instance->PciIo->Map (\r
69 SataSiI3132Instance->PciIo, EfiPciIoOperationBusMasterCommonBuffer, HostPRB,\r
70 &NumberOfBytes, &PhysAddrHostPRB, &PciAllocMappingPRB\r
71 );\r
72 if (EFI_ERROR (Status)) {\r
73 return Status;\r
74 }\r
75\r
76 Port->HostPRB = HostPRB;\r
77 Port->PhysAddrHostPRB = PhysAddrHostPRB;\r
78 Port->PciAllocMappingPRB = PciAllocMappingPRB;\r
79\r
80 return Status;\r
81}\r
82\r
83STATIC\r
84EFI_STATUS\r
85SataSiI3132Constructor (\r
86 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
87 OUT SATA_SI3132_INSTANCE** SataSiI3132Instance\r
88 )\r
89{\r
90 SATA_SI3132_INSTANCE *Instance;\r
91 EFI_ATA_PASS_THRU_MODE *AtaPassThruMode;\r
92\r
93 if (!SataSiI3132Instance) {\r
94 return EFI_INVALID_PARAMETER;\r
95 }\r
96\r
97 Instance = (SATA_SI3132_INSTANCE*)AllocateZeroPool (sizeof (SATA_SI3132_INSTANCE));\r
98 if (Instance == NULL) {\r
99 return EFI_OUT_OF_RESOURCES;\r
100 }\r
101\r
102 Instance->Signature = SATA_SII3132_SIGNATURE;\r
103 Instance->PciIo = PciIo;\r
104\r
105 AtaPassThruMode = (EFI_ATA_PASS_THRU_MODE*)AllocatePool (sizeof (EFI_ATA_PASS_THRU_MODE));\r
106 AtaPassThruMode->Attributes = EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL;\r
107 AtaPassThruMode->IoAlign = 0x1000;\r
108\r
109 // Initialize SiI3132 ports\r
110 SataSiI3132PortConstructor (Instance, 0);\r
111 SataSiI3132PortConstructor (Instance, 1);\r
112\r
113 // Set ATA Pass Thru Protocol\r
114 Instance->AtaPassThruProtocol.Mode = AtaPassThruMode;\r
115 Instance->AtaPassThruProtocol.PassThru = SiI3132AtaPassThru;\r
116 Instance->AtaPassThruProtocol.GetNextPort = SiI3132GetNextPort;\r
117 Instance->AtaPassThruProtocol.GetNextDevice = SiI3132GetNextDevice;\r
118 Instance->AtaPassThruProtocol.BuildDevicePath = SiI3132BuildDevicePath;\r
119 Instance->AtaPassThruProtocol.GetDevice = SiI3132GetDevice;\r
120 Instance->AtaPassThruProtocol.ResetPort = SiI3132ResetPort;\r
121 Instance->AtaPassThruProtocol.ResetDevice = SiI3132ResetDevice;\r
122\r
123 *SataSiI3132Instance = Instance;\r
124\r
125 return EFI_SUCCESS;\r
126}\r
127\r
128EFI_STATUS\r
129SiI3132SoftResetCommand (\r
130 IN SATA_SI3132_PORT *Port,\r
131 OUT UINT32* Signature\r
132 )\r
133{\r
134 EFI_STATUS Status;\r
135 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
136 EFI_ATA_STATUS_BLOCK Asb;\r
137 EFI_ATA_COMMAND_BLOCK Acb;\r
138 CONST UINT16 PortMultiplierPort = 0;\r
139\r
140 ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));\r
141\r
142 Acb.Reserved1[1] = 0;\r
143\r
144 Packet.Asb = &Asb;\r
145 Packet.Acb = &Acb;\r
146 Packet.Timeout = 100000;\r
147 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_SOFTWARE_RESET;\r
148\r
149 Status = SiI3132AtaPassThruCommand (Port->Instance, Port, PortMultiplierPort, &Packet, 0);\r
150\r
151 if (Status == EFI_SUCCESS) {\r
152 *Signature = (Asb.AtaCylinderHigh << 24) | (Asb.AtaCylinderLow << 16) |\r
153 (Asb.AtaSectorNumber << 8 ) | (Asb.AtaSectorCount);\r
154 }\r
155 return Status;\r
156}\r
157\r
158EFI_STATUS\r
159SataSiI3132PortInitialization (\r
160 IN SATA_SI3132_PORT *Port\r
161 )\r
162{\r
163 UINT32 Value32;\r
164 SATA_SI3132_DEVICE* Device;\r
165 UINT32 Signature;\r
166 EFI_STATUS Status;\r
167 EFI_PCI_IO_PROTOCOL* PciIo;\r
168\r
169 Status = SiI3132HwResetPort (Port);\r
170 if (EFI_ERROR (Status)) {\r
171 return Status;\r
172 }\r
173\r
174 PciIo = Port->Instance->PciIo;\r
175\r
176 // Is a device is present ?\r
177 Status = SATA_PORT_READ32 (Port->RegBase + SII3132_PORT_SSTATUS_REG, &Value32);\r
178 if (!EFI_ERROR (Status) && (Value32 & 0x3)) {\r
179 // Do a soft reset to see if it is a port multiplier\r
180 SATA_TRACE ("SataSiI3132PortInitialization: soft reset - it is a port multiplier\n");\r
181 Status = SiI3132SoftResetCommand (Port, &Signature);\r
182 if (!EFI_ERROR (Status)) {\r
183 if (Signature == SII3132_PORT_SIGNATURE_PMP) {\r
184 SATA_TRACE ("SataSiI3132PortInitialization(): a Port Multiplier is present");\r
185 if (FeaturePcdGet (PcdSataSiI3132FeaturePMPSupport)) {\r
186 ASSERT (0); // Not supported yet\r
187 } else {\r
188 return EFI_UNSUPPORTED;\r
189 }\r
190 } else if (Signature == SII3132_PORT_SIGNATURE_ATAPI) {\r
191 ASSERT (0); // Not supported yet\r
192 SATA_TRACE ("SataSiI3132PortInitialization(): an ATAPI device is present");\r
193 return EFI_UNSUPPORTED;\r
194 } else if (Signature == SII3132_PORT_SIGNATURE_ATA) {\r
195 SATA_TRACE ("SataSiI3132PortInitialization(): an ATA device is present");\r
196 } else {\r
197 SATA_TRACE ("SataSiI3132PortInitialization(): Present device unknown!");\r
198 ASSERT (0); // Not supported\r
199 return EFI_UNSUPPORTED;\r
200 }\r
201\r
202 // Create Device\r
203 Device = (SATA_SI3132_DEVICE*)AllocatePool (sizeof (SATA_SI3132_DEVICE));\r
204 Device->Index = Port->Index; //TODO: Could need to be fixed when SATA Port Multiplier support\r
205 Device->Port = Port;\r
206 Device->BlockSize = 0;\r
207\r
208 // Attached the device to the Sata Port\r
209 InsertTailList (&Port->Devices, &Device->Link);\r
210\r
211 SATA_TRACE ("SataSiI3132PortInitialization(): Port Ready");\r
212 }\r
213 }\r
214 return Status;\r
215}\r
216\r
217EFI_STATUS\r
218SataSiI3132Initialization (\r
219 IN SATA_SI3132_INSTANCE* SataSiI3132Instance\r
220 )\r
221{\r
222 UINTN Index;\r
223 EFI_PCI_IO_PROTOCOL* PciIo;\r
224\r
225 if (!SataSiI3132Instance) {\r
226 return EFI_INVALID_PARAMETER;\r
227 }\r
228\r
229 PciIo = SataSiI3132Instance->PciIo;\r
230\r
231 // Turn Off GPIO\r
232 SATA_GLOBAL_WRITE32 (SII3132_GLOBAL_FLASHADDR_REG, 0x0);\r
233\r
234 // Clear Global Control Register\r
235 SATA_GLOBAL_WRITE32 (SII3132_GLOBAL_CONTROL_REG, 0x0);\r
236\r
237 for (Index = 0; Index < SATA_SII3132_MAXPORT; Index++) {\r
238 SataSiI3132PortInitialization (&(SataSiI3132Instance->Ports[Index]));\r
239 }\r
240\r
241 return EFI_SUCCESS;\r
242}\r
243\r
244/**\r
245 Test to see if this driver supports ControllerHandle.\r
246\r
247 @param This Protocol instance pointer.\r
248 @param Controller Handle of device to test.\r
249 @param RemainingDevicePath Not used.\r
250\r
251 @return EFI_SUCCESS This driver supports this device.\r
252 @return EFI_UNSUPPORTED This driver does not support this device.\r
253\r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257SataSiI3132DriverBindingSupported (\r
258 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
259 IN EFI_HANDLE Controller,\r
260 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
261 )\r
262{\r
263 EFI_STATUS Status;\r
264 EFI_PCI_IO_PROTOCOL *PciIo;\r
265 UINT32 PciID;\r
266\r
267 //\r
268 // Test whether there is PCI IO Protocol attached on the controller handle.\r
269 //\r
270 Status = gBS->OpenProtocol (\r
271 Controller,\r
272 &gEfiPciIoProtocolGuid,\r
273 (VOID **) &PciIo,\r
274 This->DriverBindingHandle,\r
275 Controller,\r
276 EFI_OPEN_PROTOCOL_BY_DRIVER\r
277 );\r
278 if (EFI_ERROR (Status)) {\r
279 return Status;\r
280 }\r
281\r
282 Status = PciIo->Pci.Read (\r
283 PciIo,\r
284 EfiPciIoWidthUint32,\r
285 PCI_VENDOR_ID_OFFSET,\r
286 1,\r
287 &PciID\r
288 );\r
289 if (EFI_ERROR (Status)) {\r
290 Status = EFI_UNSUPPORTED;\r
291 goto ON_EXIT;\r
292 }\r
293\r
294 //\r
295 // Test whether the controller belongs to SATA Mass Storage type\r
296 //\r
297 if (PciID != ((SATA_SII3132_DEVICE_ID << 16) | SATA_SII3132_VENDOR_ID)) {\r
298 Status = EFI_UNSUPPORTED;\r
299 }\r
300\r
301ON_EXIT:\r
302 gBS->CloseProtocol (\r
303 Controller,\r
304 &gEfiPciIoProtocolGuid,\r
305 This->DriverBindingHandle,\r
306 Controller\r
307 );\r
308\r
309 return Status;\r
310}\r
311\r
312BOOLEAN mbStarted = FALSE;\r
313\r
314/**\r
315 Starting the Pci SATA Driver.\r
316\r
317 @param This Protocol instance pointer.\r
318 @param Controller Handle of device to test.\r
319 @param RemainingDevicePath Not used.\r
320\r
321 @return EFI_SUCCESS supports this device.\r
322 @return EFI_UNSUPPORTED do not support this device.\r
323 @return EFI_DEVICE_ERROR cannot be started due to device Error.\r
324 @return EFI_OUT_OF_RESOURCES cannot allocate resources.\r
325\r
326**/\r
327EFI_STATUS\r
328EFIAPI\r
329SataSiI3132DriverBindingStart (\r
330 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
331 IN EFI_HANDLE Controller,\r
332 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
333 )\r
334{\r
335 EFI_STATUS Status;\r
336 EFI_PCI_IO_PROTOCOL *PciIo;\r
337 UINT64 Supports;\r
338 UINT64 OriginalPciAttributes;\r
339 BOOLEAN PciAttributesSaved;\r
340 UINT32 PciID;\r
341 SATA_SI3132_INSTANCE *SataSiI3132Instance = NULL;\r
342\r
343 SATA_TRACE ("SataSiI3132DriverBindingStart()");\r
344\r
345 //TODO: Find a nicer way to do it !\r
346 if (mbStarted) {\r
347 return EFI_SUCCESS; // Don't restart me !\r
348 }\r
349\r
350 //\r
351 // Open the PciIo Protocol\r
352 //\r
353 Status = gBS->OpenProtocol (\r
354 Controller,\r
355 &gEfiPciIoProtocolGuid,\r
356 (VOID **) &PciIo,\r
357 This->DriverBindingHandle,\r
358 Controller,\r
359 EFI_OPEN_PROTOCOL_BY_DRIVER\r
360 );\r
361 if (EFI_ERROR (Status)) {\r
362 return Status;\r
363 }\r
364\r
365 PciAttributesSaved = FALSE;\r
366 //\r
367 // Save original PCI attributes\r
368 //\r
369 Status = PciIo->Attributes (\r
370 PciIo,\r
371 EfiPciIoAttributeOperationGet,\r
372 0,\r
373 &OriginalPciAttributes\r
374 );\r
375 if (EFI_ERROR (Status)) {\r
376 goto CLOSE_PCIIO;\r
377 }\r
378 PciAttributesSaved = TRUE;\r
379\r
380 Status = PciIo->Attributes (\r
381 PciIo,\r
382 EfiPciIoAttributeOperationSupported,\r
383 0,\r
384 &Supports\r
385 );\r
386 if (!EFI_ERROR (Status)) {\r
387 Supports &= EFI_PCI_DEVICE_ENABLE;\r
388 Status = PciIo->Attributes (\r
389 PciIo,\r
390 EfiPciIoAttributeOperationEnable,\r
391 Supports,\r
392 NULL\r
393 );\r
394 }\r
395 if (EFI_ERROR (Status)) {\r
396 DEBUG ((EFI_D_ERROR, "SataSiI3132DriverBindingStart: failed to enable controller\n"));\r
397 goto CLOSE_PCIIO;\r
398 }\r
399\r
400 //\r
401 // Get the Pci device class code.\r
402 //\r
403 Status = PciIo->Pci.Read (\r
404 PciIo,\r
405 EfiPciIoWidthUint32,\r
406 PCI_VENDOR_ID_OFFSET,\r
407 1,\r
408 &PciID\r
409 );\r
410 if (EFI_ERROR (Status)) {\r
411 Status = EFI_UNSUPPORTED;\r
412 goto CLOSE_PCIIO;\r
413 }\r
414\r
415 //\r
416 // Test whether the controller belongs to SATA Mass Storage type\r
417 //\r
418 if (PciID != ((SATA_SII3132_DEVICE_ID << 16) | SATA_SII3132_VENDOR_ID)) {\r
419 Status = EFI_UNSUPPORTED;\r
420 goto CLOSE_PCIIO;\r
421 }\r
422\r
423 // Create SiI3132 Sata Instance\r
424 Status = SataSiI3132Constructor (PciIo, &SataSiI3132Instance);\r
425 if (EFI_ERROR (Status)) {\r
426 return Status;\r
427 }\r
428\r
429 // Initialize SiI3132 Sata Controller\r
430 Status = SataSiI3132Initialization (SataSiI3132Instance);\r
431 if (EFI_ERROR (Status)) {\r
432 return Status;\r
433 }\r
434\r
435 // Install Ata Pass Thru Protocol\r
436 Status = gBS->InstallProtocolInterface (\r
437 &Controller,\r
438 &gEfiAtaPassThruProtocolGuid,\r
439 EFI_NATIVE_INTERFACE,\r
440 &(SataSiI3132Instance->AtaPassThruProtocol)\r
441 );\r
442 if (EFI_ERROR (Status)) {\r
443 goto FREE_POOL;\r
444 }\r
445\r
446/* //\r
447 // Create event to stop the HC when exit boot service.\r
448 //\r
449 Status = gBS->CreateEventEx (\r
450 EVT_NOTIFY_SIGNAL,\r
451 TPL_NOTIFY,\r
452 EhcExitBootService,\r
453 Ehc,\r
454 &gEfiEventExitBootServicesGuid,\r
455 &Ehc->ExitBootServiceEvent\r
456 );\r
457 if (EFI_ERROR (Status)) {\r
458 goto UNINSTALL_USBHC;\r
459 }*/\r
460\r
461 mbStarted = TRUE;\r
462\r
463 SATA_TRACE ("SataSiI3132DriverBindingStart() Success!");\r
464 return EFI_SUCCESS;\r
465\r
466FREE_POOL:\r
467 //TODO: Free SATA Instance\r
468\r
469CLOSE_PCIIO:\r
470 if (PciAttributesSaved) {\r
471 //\r
472 // Restore original PCI attributes\r
473 //\r
474 PciIo->Attributes (\r
475 PciIo,\r
476 EfiPciIoAttributeOperationSet,\r
477 OriginalPciAttributes,\r
478 NULL\r
479 );\r
480 }\r
481\r
482 gBS->CloseProtocol (\r
483 Controller,\r
484 &gEfiPciIoProtocolGuid,\r
485 This->DriverBindingHandle,\r
486 Controller\r
487 );\r
488\r
489 return Status;\r
490}\r
491\r
492/**\r
4f0624e8 493 Stop this driver on ControllerHandle. Support stopping any child handles\r
f6342447
OM
494 created by this driver.\r
495\r
496 @param This Protocol instance pointer.\r
497 @param Controller Handle of device to stop driver on.\r
498 @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
499 @param ChildHandleBuffer List of handles for the children we need to stop.\r
500\r
501 @return EFI_SUCCESS Success.\r
502 @return EFI_DEVICE_ERROR Fail.\r
503\r
504**/\r
505EFI_STATUS\r
506EFIAPI\r
507SataSiI3132DriverBindingStop (\r
508 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
509 IN EFI_HANDLE Controller,\r
510 IN UINTN NumberOfChildren,\r
511 IN EFI_HANDLE *ChildHandleBuffer\r
512 )\r
513{\r
514 SATA_TRACE ("SataSiI3132DriverBindingStop()");\r
515 return EFI_UNSUPPORTED;\r
516}\r
517\r
518/**\r
519 Entry point of this driver\r
520\r
521 @param ImageHandle Handle of driver image\r
522 @param SystemTable Point to EFI_SYSTEM_TABLE\r
523\r
524 @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource\r
525 @retval EFI_DEVICE_ERROR Can not install the protocol instance\r
526 @retval EFI_SUCCESS Success to initialize the Pci host bridge.\r
527**/\r
528EFI_STATUS\r
529EFIAPI\r
530InitializeSataSiI3132 (\r
531 IN EFI_HANDLE ImageHandle,\r
532 IN EFI_SYSTEM_TABLE *SystemTable\r
533 )\r
534{\r
535 SATA_TRACE ("InitializeSataSiI3132 ()");\r
536\r
537 return EfiLibInstallDriverBindingComponentName2 (\r
538 ImageHandle,\r
539 SystemTable,\r
540 &gSataSiI3132DriverBinding,\r
541 ImageHandle,\r
542 &gSataSiI3132ComponentName,\r
543 &gSataSiI3132ComponentName2\r
544 );\r
545}\r