SataSiI3132.c 15 KB

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