PciRootBridgeIo.c 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663
  1. /** @file
  2. IIO PCI Root Bridge Io Protocol code. Generic enough to work for all IIOs.
  3. Does not support configuration accesses to the extended PCI Express registers yet.
  4. @copyright
  5. Copyright 1999 - 2021 Intel Corporation. <BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include "PciHostBridge.h"
  9. #include "PciRootBridge.h"
  10. #include <Protocol/IioUds.h>
  11. #include <Protocol/DynamicSiLibraryProtocol.h>
  12. #include "PciRebalance.h"
  13. extern EFI_IIO_UDS_PROTOCOL *mIioUds;
  14. //
  15. // Pci Root Bridge Io Module Variables
  16. //
  17. EFI_CPU_IO2_PROTOCOL *mCpuIo;
  18. STATIC DYNAMIC_SI_LIBARY_PROTOCOL *mDynamicSiLibraryProtocol;
  19. /**
  20. Construct the Pci Root Bridge Io protocol.
  21. @param[out] Protocol - Protocol to initialize.
  22. @param[in] HostBridgeHandle - Handle to the HostBridge.
  23. @param[in] ResAperture - Resource apperture of the root bridge.
  24. @param[in] SegmentNumber - PCI segment of this root bridge
  25. @param[in] AllocAttributes - Attribute of resouce allocated.
  26. @retval EFI_SUCCESS - Success.
  27. @retval Others - Fail.
  28. **/
  29. EFI_STATUS
  30. SimpleIioRootBridgeConstructor (
  31. OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
  32. IN EFI_HANDLE HostBridgeHandle,
  33. IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture,
  34. IN UINT16 SegmentNumber,
  35. IN UINT64 AllocAttributes
  36. )
  37. {
  38. EFI_STATUS Status;
  39. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  40. PCI_RESOURCE_TYPE Index;
  41. UINT32 HecBase;
  42. UINT32 HecSize;
  43. RootBridge = ROOT_BRIDGE_FROM_THIS (Protocol);
  44. //
  45. // Initialize the apertures with default values
  46. //
  47. CopyMem (
  48. &RootBridge->Aperture,
  49. ResAperture,
  50. sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE)
  51. );
  52. for (Index = TypeIo; Index < TypeMax; Index++) {
  53. RootBridge->ResAllocNode[Index].Type = Index;
  54. RootBridge->ResAllocNode[Index].Base = 0;
  55. RootBridge->ResAllocNode[Index].Length = 0;
  56. RootBridge->ResAllocNode[Index].Status = ResNone;
  57. }
  58. EfiInitializeLock (&RootBridge->PciLock, TPL_HIGH_LEVEL);
  59. RootBridge->PciAddress = 0xCF8;
  60. RootBridge->PciData = 0xCFC;
  61. RootBridge->AllocationAttributes = AllocAttributes;
  62. RootBridge->Attributes = 0;
  63. RootBridge->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO |
  64. EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO |
  65. EFI_PCI_ATTRIBUTE_ISA_IO_16 |
  66. EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 |
  67. EFI_PCI_ATTRIBUTE_VGA_MEMORY |
  68. EFI_PCI_ATTRIBUTE_VGA_IO_16;
  69. //
  70. // Don't support BASE above 4GB currently
  71. // Position to bit 39:28
  72. //
  73. HecBase = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
  74. HecSize = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressSize;
  75. ASSERT (HecBase != 0);
  76. RootBridge->HecBase = HecBase;
  77. RootBridge->HecLen = HecSize;
  78. RootBridge->BusNumberAssigned = FALSE;
  79. RootBridge->BusScanCount = 0;
  80. Protocol->ParentHandle = HostBridgeHandle;
  81. Protocol->PollMem = RootBridgeIoPollMem;
  82. Protocol->PollIo = RootBridgeIoPollIo;
  83. Protocol->Mem.Read = RootBridgeIoMemRead;
  84. Protocol->Mem.Write = RootBridgeIoMemWrite;
  85. Protocol->Io.Read = RootBridgeIoIoRead;
  86. Protocol->Io.Write = RootBridgeIoIoWrite;
  87. Protocol->CopyMem = RootBridgeIoCopyMem;
  88. Protocol->Pci.Read = RootBridgeIoPciRead;
  89. Protocol->Pci.Write = RootBridgeIoPciWrite;
  90. Protocol->Map = RootBridgeIoMap;
  91. Protocol->Unmap = RootBridgeIoUnmap;
  92. Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
  93. Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
  94. Protocol->Flush = RootBridgeIoFlush;
  95. Protocol->GetAttributes = RootBridgeIoGetAttributes;
  96. Protocol->SetAttributes = RootBridgeIoSetAttributes;
  97. Protocol->Configuration = RootBridgeIoConfiguration;
  98. Protocol->SegmentNumber = SegmentNumber;
  99. Status = gBS->LocateProtocol (
  100. &gEfiCpuIo2ProtocolGuid,
  101. NULL,
  102. (VOID **) &mCpuIo
  103. );
  104. ASSERT_EFI_ERROR (Status);
  105. Status = gBS->LocateProtocol (&gDynamicSiLibraryProtocolGuid, NULL, (VOID **) &mDynamicSiLibraryProtocol);
  106. ASSERT_EFI_ERROR (Status);
  107. return EFI_SUCCESS;
  108. }
  109. /**
  110. Return the result of (Multiplicand * Multiplier / Divisor).
  111. @param Multiplicand A 64-bit unsigned value.
  112. @param Multiplier A 64-bit unsigned value.
  113. @param Divisor A 32-bit unsigned value.
  114. @param Remainder A pointer to a 32-bit unsigned value. This parameter is
  115. optional and may be NULL.
  116. @return Multiplicand * Multiplier / Divisor.
  117. **/
  118. UINT64
  119. MultThenDivU64x64x32 (
  120. IN UINT64 Multiplicand,
  121. IN UINT64 Multiplier,
  122. IN UINT32 Divisor,
  123. OUT UINT32 *Remainder OPTIONAL
  124. )
  125. {
  126. UINT64 Uint64;
  127. UINT32 LocalRemainder;
  128. UINT32 Uint32;
  129. if (Multiplicand > DivU64x64Remainder (MAX_UINT64, Multiplier, NULL)) {
  130. //
  131. // Make sure Multiplicand is the bigger one.
  132. //
  133. if (Multiplicand < Multiplier) {
  134. Uint64 = Multiplicand;
  135. Multiplicand = Multiplier;
  136. Multiplier = Uint64;
  137. }
  138. //
  139. // Because Multiplicand * Multiplier overflows,
  140. // Multiplicand * Multiplier / Divisor
  141. // = (2 * Multiplicand' + 1) * Multiplier / Divisor
  142. // = 2 * (Multiplicand' * Multiplier / Divisor) + Multiplier / Divisor
  143. //
  144. Uint64 = MultThenDivU64x64x32 (RShiftU64 (Multiplicand, 1), Multiplier, Divisor, &LocalRemainder);
  145. Uint64 = LShiftU64 (Uint64, 1);
  146. Uint32 = 0;
  147. if ((Multiplicand & 0x1) == 1) {
  148. Uint64 += DivU64x32Remainder (Multiplier, Divisor, &Uint32);
  149. }
  150. return Uint64 + DivU64x32Remainder (Uint32 + LShiftU64 (LocalRemainder, 1), Divisor, Remainder);
  151. } else {
  152. return DivU64x32Remainder (MultU64x64 (Multiplicand, Multiplier), Divisor, Remainder);
  153. }
  154. }
  155. /**
  156. Return the elapsed tick count from CurrentTick.
  157. @param CurrentTick On input, the previous tick count.
  158. On output, the current tick count.
  159. @param StartTick The value the performance counter starts with when it
  160. rolls over.
  161. @param EndTick The value that the performance counter ends with before
  162. it rolls over.
  163. @return The elapsed tick count from CurrentTick.
  164. **/
  165. UINT64
  166. GetElapsedTick (
  167. UINT64 *CurrentTick,
  168. UINT64 StartTick,
  169. UINT64 EndTick
  170. )
  171. {
  172. UINT64 PreviousTick;
  173. PreviousTick = *CurrentTick;
  174. *CurrentTick = GetPerformanceCounter();
  175. if (StartTick < EndTick) {
  176. return *CurrentTick - PreviousTick;
  177. } else {
  178. return PreviousTick - *CurrentTick;
  179. }
  180. }
  181. /**
  182. Polls an address in memory mapped I/O space until an exit condition is met,
  183. or a timeout occurs.
  184. This function provides a standard way to poll a PCI memory location. A PCI
  185. memory read operation is performed at the PCI memory address specified by
  186. Address for the width specified by Width. The result of this PCI memory read
  187. operation is stored in Result. This PCI memory read operation is repeated
  188. until either a timeout of Delay 100 ns units has expired, or (Result & Mask)
  189. is equal to Value.
  190. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  191. @param[in] Width Signifies the width of the memory operations.
  192. @param[in] Address The base address of the memory operations. The caller
  193. is responsible for aligning Address if required.
  194. @param[in] Mask Mask used for the polling criteria. Bytes above Width
  195. in Mask are ignored. The bits in the bytes below Width
  196. which are zero in Mask are ignored when polling the
  197. memory address.
  198. @param[in] Value The comparison value used for the polling exit
  199. criteria.
  200. @param[in] Delay The number of 100 ns units to poll. Note that timer
  201. available may be of poorer granularity.
  202. @param[out] Result Pointer to the last value read from the memory
  203. location.
  204. @retval EFI_SUCCESS The last data returned from the access matched
  205. the poll exit criteria.
  206. @retval EFI_INVALID_PARAMETER Width is invalid.
  207. @retval EFI_INVALID_PARAMETER Result is NULL.
  208. @retval EFI_TIMEOUT Delay expired before a match occurred.
  209. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  210. lack of resources.
  211. **/
  212. EFI_STATUS
  213. EFIAPI
  214. RootBridgeIoPollMem (
  215. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  216. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  217. IN UINT64 Address,
  218. IN UINT64 Mask,
  219. IN UINT64 Value,
  220. IN UINT64 Delay,
  221. OUT UINT64 *Result
  222. )
  223. {
  224. EFI_STATUS Status;
  225. UINT64 NumberOfTicks;
  226. UINT32 Remainder;
  227. UINT64 StartTick;
  228. UINT64 EndTick;
  229. UINT64 CurrentTick;
  230. UINT64 ElapsedTick;
  231. UINT64 Frequency;
  232. if (Result == NULL) {
  233. return EFI_INVALID_PARAMETER;
  234. }
  235. if ((UINT32)Width > EfiPciWidthUint64) {
  236. return EFI_INVALID_PARAMETER;
  237. }
  238. //
  239. // No matter what, always do a single poll.
  240. //
  241. Status = This->Mem.Read (This, Width, Address, 1, Result);
  242. if (EFI_ERROR (Status)) {
  243. return Status;
  244. }
  245. if ((*Result & Mask) == Value) {
  246. return EFI_SUCCESS;
  247. }
  248. if (Delay == 0) {
  249. return EFI_SUCCESS;
  250. } else {
  251. //
  252. // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
  253. //
  254. Frequency = GetPerformanceCounterProperties (&StartTick, &EndTick);
  255. NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS(1), &Remainder);
  256. if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
  257. NumberOfTicks++;
  258. }
  259. for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter()
  260. ; ElapsedTick <= NumberOfTicks
  261. ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)
  262. ) {
  263. Status = This->Mem.Read (This, Width, Address, 1, Result);
  264. if (EFI_ERROR (Status)) {
  265. return Status;
  266. }
  267. if ((*Result & Mask) == Value) {
  268. return EFI_SUCCESS;
  269. }
  270. }
  271. }
  272. return EFI_TIMEOUT;
  273. }
  274. /**
  275. Reads from the I/O space of a PCI Root Bridge. Returns when either the
  276. polling exit criteria is satisfied or after a defined duration.
  277. This function provides a standard way to poll a PCI I/O location. A PCI I/O
  278. read operation is performed at the PCI I/O address specified by Address for
  279. the width specified by Width.
  280. The result of this PCI I/O read operation is stored in Result. This PCI I/O
  281. read operation is repeated until either a timeout of Delay 100 ns units has
  282. expired, or (Result & Mask) is equal to Value.
  283. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  284. @param[in] Width Signifies the width of the I/O operations.
  285. @param[in] Address The base address of the I/O operations. The caller is
  286. responsible for aligning Address if required.
  287. @param[in] Mask Mask used for the polling criteria. Bytes above Width in
  288. Mask are ignored. The bits in the bytes below Width
  289. which are zero in Mask are ignored when polling the I/O
  290. address.
  291. @param[in] Value The comparison value used for the polling exit criteria.
  292. @param[in] Delay The number of 100 ns units to poll. Note that timer
  293. available may be of poorer granularity.
  294. @param[out] Result Pointer to the last value read from the memory location.
  295. @retval EFI_SUCCESS The last data returned from the access matched
  296. the poll exit criteria.
  297. @retval EFI_INVALID_PARAMETER Width is invalid.
  298. @retval EFI_INVALID_PARAMETER Result is NULL.
  299. @retval EFI_TIMEOUT Delay expired before a match occurred.
  300. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  301. lack of resources.
  302. **/
  303. EFI_STATUS
  304. EFIAPI
  305. RootBridgeIoPollIo (
  306. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  307. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  308. IN UINT64 Address,
  309. IN UINT64 Mask,
  310. IN UINT64 Value,
  311. IN UINT64 Delay,
  312. OUT UINT64 *Result
  313. )
  314. {
  315. EFI_STATUS Status;
  316. UINT64 NumberOfTicks;
  317. UINT32 Remainder;
  318. UINT64 StartTick;
  319. UINT64 EndTick;
  320. UINT64 CurrentTick;
  321. UINT64 ElapsedTick;
  322. UINT64 Frequency;
  323. //
  324. // No matter what, always do a single poll.
  325. //
  326. if (Result == NULL) {
  327. return EFI_INVALID_PARAMETER;
  328. }
  329. if ((UINT32)Width > EfiPciWidthUint64) {
  330. return EFI_INVALID_PARAMETER;
  331. }
  332. Status = This->Io.Read (This, Width, Address, 1, Result);
  333. if (EFI_ERROR (Status)) {
  334. return Status;
  335. }
  336. if ((*Result & Mask) == Value) {
  337. return EFI_SUCCESS;
  338. }
  339. if (Delay == 0) {
  340. return EFI_SUCCESS;
  341. } else {
  342. //
  343. // NumberOfTicks = Frenquency * Delay / EFI_TIMER_PERIOD_SECONDS(1)
  344. //
  345. Frequency = GetPerformanceCounterProperties (&StartTick, &EndTick);
  346. NumberOfTicks = MultThenDivU64x64x32 (Frequency, Delay, (UINT32)EFI_TIMER_PERIOD_SECONDS(1), &Remainder);
  347. if (Remainder >= (UINTN)EFI_TIMER_PERIOD_SECONDS(1) / 2) {
  348. NumberOfTicks++;
  349. }
  350. for ( ElapsedTick = 0, CurrentTick = GetPerformanceCounter()
  351. ; ElapsedTick <= NumberOfTicks
  352. ; ElapsedTick += GetElapsedTick (&CurrentTick, StartTick, EndTick)
  353. ) {
  354. Status = This->Io.Read (This, Width, Address, 1, Result);
  355. if (EFI_ERROR (Status)) {
  356. return Status;
  357. }
  358. if ((*Result & Mask) == Value) {
  359. return EFI_SUCCESS;
  360. }
  361. }
  362. }
  363. return EFI_TIMEOUT;
  364. }
  365. /**
  366. Enables a PCI driver to access PCI controller registers in the PCI root
  367. bridge memory space.
  368. The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
  369. controller registers in the PCI root bridge memory space.
  370. The memory operations are carried out exactly as requested. The caller is
  371. responsible for satisfying any alignment and memory width restrictions that a
  372. PCI Root Bridge on a platform might require.
  373. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  374. @param[in] Width Signifies the width of the memory operation.
  375. @param[in] Address The base address of the memory operation. The caller
  376. is responsible for aligning the Address if required.
  377. @param[in] Count The number of memory operations to perform. Bytes
  378. moved is Width size * Count, starting at Address.
  379. @param[out] Buffer For read operations, the destination buffer to store
  380. the results. For write operations, the source buffer
  381. to write data from.
  382. @retval EFI_SUCCESS The data was read from or written to the PCI
  383. root bridge.
  384. @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
  385. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  386. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  387. lack of resources.
  388. **/
  389. EFI_STATUS
  390. EFIAPI
  391. RootBridgeIoMemRead (
  392. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  393. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  394. IN UINT64 Address,
  395. IN UINTN Count,
  396. OUT VOID *Buffer
  397. )
  398. {
  399. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  400. if (Buffer == NULL) {
  401. return EFI_INVALID_PARAMETER;
  402. }
  403. if (Width < 0 ||Width >= EfiPciWidthMaximum ) {
  404. return EFI_INVALID_PARAMETER;
  405. }
  406. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  407. //
  408. // Check memory access limit
  409. //
  410. if (RootBridge->Aperture.Mem64Limit > RootBridge->Aperture.Mem64Base) {
  411. if (Address > RootBridge->Aperture.Mem64Limit) {
  412. return EFI_INVALID_PARAMETER;
  413. }
  414. } else {
  415. if (Address > RootBridge->Aperture.Mem32Limit) {
  416. return EFI_INVALID_PARAMETER;
  417. }
  418. }
  419. return mCpuIo->Mem.Read (
  420. mCpuIo,
  421. (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
  422. Address,
  423. Count,
  424. Buffer
  425. );
  426. }
  427. /**
  428. Enables a PCI driver to access PCI controller registers in the PCI root
  429. bridge memory space.
  430. The Mem.Read(), and Mem.Write() functions enable a driver to access PCI
  431. controller registers in the PCI root bridge memory space.
  432. The memory operations are carried out exactly as requested. The caller is
  433. responsible for satisfying any alignment and memory width restrictions that a
  434. PCI Root Bridge on a platform might require.
  435. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  436. @param[in] Width Signifies the width of the memory operation.
  437. @param[in] Address The base address of the memory operation. The caller
  438. is responsible for aligning the Address if required.
  439. @param[in] Count The number of memory operations to perform. Bytes
  440. moved is Width size * Count, starting at Address.
  441. @param[in] Buffer For read operations, the destination buffer to store
  442. the results. For write operations, the source buffer
  443. to write data from.
  444. @retval EFI_SUCCESS The data was read from or written to the PCI
  445. root bridge.
  446. @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
  447. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  448. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  449. lack of resources.
  450. **/
  451. EFI_STATUS
  452. EFIAPI
  453. RootBridgeIoMemWrite (
  454. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  455. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  456. IN UINT64 Address,
  457. IN UINTN Count,
  458. IN VOID *Buffer
  459. )
  460. {
  461. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  462. if (Buffer == NULL) {
  463. return EFI_INVALID_PARAMETER;
  464. }
  465. if (Width < 0 || Width >= EfiPciWidthMaximum ) {
  466. return EFI_INVALID_PARAMETER;
  467. }
  468. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  469. //
  470. // Check memory access limit
  471. //
  472. if (RootBridge->Aperture.Mem64Limit > RootBridge->Aperture.Mem64Base) {
  473. if (Address > RootBridge->Aperture.Mem64Limit) {
  474. return EFI_INVALID_PARAMETER;
  475. }
  476. } else {
  477. if (Address > RootBridge->Aperture.Mem32Limit) {
  478. return EFI_INVALID_PARAMETER;
  479. }
  480. }
  481. return mCpuIo->Mem.Write (
  482. mCpuIo,
  483. (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
  484. Address,
  485. Count,
  486. Buffer
  487. );
  488. }
  489. /**
  490. Enables a PCI driver to access PCI controller registers in the PCI root
  491. bridge I/O space.
  492. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  493. @param[in] Width Signifies the width of the memory operations.
  494. @param[in] Address The base address of the I/O operation. The caller is
  495. responsible for aligning the Address if required.
  496. @param[in] Count The number of I/O operations to perform. Bytes moved
  497. is Width size * Count, starting at Address.
  498. @param[out] Buffer For read operations, the destination buffer to store
  499. the results. For write operations, the source buffer
  500. to write data from.
  501. @retval EFI_SUCCESS The data was read from or written to the PCI
  502. root bridge.
  503. @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
  504. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  505. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  506. lack of resources.
  507. **/
  508. EFI_STATUS
  509. EFIAPI
  510. RootBridgeIoIoRead (
  511. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  512. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  513. IN UINT64 Address,
  514. IN UINTN Count,
  515. OUT VOID *Buffer
  516. )
  517. {
  518. UINTN AlignMask;
  519. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  520. if (Buffer == NULL) {
  521. return EFI_INVALID_PARAMETER;
  522. }
  523. if (Width < 0 || Width >= EfiPciWidthMaximum ) {
  524. return EFI_INVALID_PARAMETER;
  525. }
  526. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  527. //
  528. // AlignMask = (1 << Width) - 1;
  529. //
  530. AlignMask = (1 << (Width & 0x03)) - 1;
  531. //
  532. // check Io access limit
  533. //
  534. if (Address > RootBridge->Aperture.IoLimit) {
  535. return EFI_INVALID_PARAMETER;
  536. }
  537. if (Address & AlignMask) {
  538. return EFI_INVALID_PARAMETER;
  539. }
  540. return mCpuIo->Io.Read (
  541. mCpuIo,
  542. (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
  543. Address,
  544. Count,
  545. Buffer
  546. );
  547. }
  548. /**
  549. Enables a PCI driver to access PCI controller registers in the PCI root
  550. bridge I/O space.
  551. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  552. @param[in] Width Signifies the width of the memory operations.
  553. @param[in] Address The base address of the I/O operation. The caller is
  554. responsible for aligning the Address if required.
  555. @param[in] Count The number of I/O operations to perform. Bytes moved
  556. is Width size * Count, starting at Address.
  557. @param[in] Buffer For read operations, the destination buffer to store
  558. the results. For write operations, the source buffer
  559. to write data from.
  560. @retval EFI_SUCCESS The data was read from or written to the PCI
  561. root bridge.
  562. @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
  563. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  564. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  565. lack of resources.
  566. **/
  567. EFI_STATUS
  568. EFIAPI
  569. RootBridgeIoIoWrite (
  570. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  571. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  572. IN UINT64 Address,
  573. IN UINTN Count,
  574. IN VOID *Buffer
  575. )
  576. {
  577. UINTN AlignMask;
  578. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  579. if (Buffer == NULL) {
  580. return EFI_INVALID_PARAMETER;
  581. }
  582. if (Width < 0 || Width >= EfiPciWidthMaximum ) {
  583. return EFI_INVALID_PARAMETER;
  584. }
  585. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  586. //
  587. // AlignMask = (1 << Width) - 1;
  588. //
  589. AlignMask = (1 << (Width & 0x03)) - 1;
  590. //
  591. // Check Io access limit
  592. //
  593. if (Address > RootBridge->Aperture.IoLimit) {
  594. return EFI_INVALID_PARAMETER;
  595. }
  596. if (Address & AlignMask) {
  597. return EFI_INVALID_PARAMETER;
  598. }
  599. return mCpuIo->Io.Write (
  600. mCpuIo,
  601. (EFI_CPU_IO_PROTOCOL_WIDTH) Width,
  602. Address,
  603. Count,
  604. Buffer
  605. );
  606. }
  607. /**
  608. Enables a PCI driver to copy one region of PCI root bridge memory space to
  609. another region of PCI root bridge memory space.
  610. The CopyMem() function enables a PCI driver to copy one region of PCI root
  611. bridge memory space to another region of PCI root bridge memory space. This
  612. is especially useful for video scroll operation on a memory mapped video
  613. buffer.
  614. The memory operations are carried out exactly as requested. The caller is
  615. responsible for satisfying any alignment and memory width restrictions that a
  616. PCI root bridge on a platform might require.
  617. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
  618. instance.
  619. @param[in] Width Signifies the width of the memory operations.
  620. @param[in] DestAddress The destination address of the memory operation. The
  621. caller is responsible for aligning the DestAddress if
  622. required.
  623. @param[in] SrcAddress The source address of the memory operation. The caller
  624. is responsible for aligning the SrcAddress if
  625. required.
  626. @param[in] Count The number of memory operations to perform. Bytes
  627. moved is Width size * Count, starting at DestAddress
  628. and SrcAddress.
  629. @retval EFI_SUCCESS The data was copied from one memory region
  630. to another memory region.
  631. @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
  632. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
  633. lack of resources.
  634. **/
  635. EFI_STATUS
  636. EFIAPI
  637. RootBridgeIoCopyMem (
  638. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  639. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  640. IN UINT64 DestAddress,
  641. IN UINT64 SrcAddress,
  642. IN UINTN Count
  643. )
  644. {
  645. EFI_STATUS Status;
  646. BOOLEAN Forward;
  647. UINTN Stride;
  648. UINTN Index;
  649. UINT64 Result;
  650. if ((UINT32) Width > EfiPciWidthUint64) {
  651. return EFI_INVALID_PARAMETER;
  652. }
  653. if (DestAddress == SrcAddress) {
  654. return EFI_SUCCESS;
  655. }
  656. Stride = (UINTN)1 << Width;
  657. Forward = TRUE;
  658. if ((DestAddress > SrcAddress) &&
  659. (DestAddress < (SrcAddress + Count * Stride))) {
  660. Forward = FALSE;
  661. SrcAddress = SrcAddress + (Count - 1) * Stride;
  662. DestAddress = DestAddress + (Count - 1) * Stride;
  663. }
  664. for (Index = 0; Index < Count; Index++) {
  665. Status = RootBridgeIoMemRead (
  666. This,
  667. Width,
  668. SrcAddress,
  669. 1,
  670. &Result
  671. );
  672. if (EFI_ERROR (Status)) {
  673. return Status;
  674. }
  675. Status = RootBridgeIoMemWrite (
  676. This,
  677. Width,
  678. DestAddress,
  679. 1,
  680. &Result
  681. );
  682. if (EFI_ERROR (Status)) {
  683. return Status;
  684. }
  685. if (Forward) {
  686. SrcAddress += Stride;
  687. DestAddress += Stride;
  688. } else {
  689. SrcAddress -= Stride;
  690. DestAddress -= Stride;
  691. }
  692. }
  693. return EFI_SUCCESS;
  694. }
  695. /**
  696. Arguments:
  697. **/
  698. STATIC
  699. EFI_STATUS
  700. RootBridgeIoPciRW (
  701. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  702. IN BOOLEAN Write,
  703. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  704. IN UINT64 UserAddress,
  705. IN UINTN Count,
  706. IN OUT VOID *UserBuffer
  707. )
  708. {
  709. PCI_CONFIG_ACCESS_CF8 Pci;
  710. PCI_CONFIG_ACCESS_CF8 PciAligned;
  711. UINT32 Stride;
  712. UINTN PciData;
  713. UINTN PciDataStride;
  714. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  715. if (Width >= EfiPciWidthMaximum) {
  716. return EFI_INVALID_PARAMETER;
  717. }
  718. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  719. ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00);
  720. Stride = 1 << Width;
  721. Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register;
  722. Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function;
  723. Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device;
  724. Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus;
  725. Pci.Bits.Reserved = 0;
  726. Pci.Bits.Enable = 1;
  727. //
  728. // PCI Configure access are all 32-bit aligned, but by accessing the
  729. // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
  730. // are possible on PCI.
  731. //
  732. // To read a byte of PCI configuration space you load 0xcf8 and
  733. // read 0xcfc, 0xcfd, 0xcfe, 0xcff
  734. //
  735. PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03;
  736. while (Count) {
  737. PciAligned = Pci;
  738. PciAligned.Bits.Reg &= 0xfc;
  739. PciData = RootBridge->PciData + PciDataStride;
  740. EfiAcquireLock(&RootBridge->PciLock);
  741. This->Io.Write (This, EfiPciWidthUint32, \
  742. RootBridge->PciAddress, 1, &PciAligned);
  743. if (Write) {
  744. This->Io.Write (This, Width, PciData, 1, UserBuffer);
  745. } else {
  746. This->Io.Read (This, Width, PciData, 1, UserBuffer);
  747. }
  748. EfiReleaseLock(&RootBridge->PciLock);
  749. UserBuffer = ((UINT8 *)UserBuffer) + Stride;
  750. PciDataStride = (PciDataStride + Stride) % 4;
  751. Count -= 1;
  752. //
  753. // Only increment the PCI address if Width is not a FIFO.
  754. //
  755. if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) {
  756. Pci.Bits.Reg += Stride;
  757. }
  758. }
  759. return EFI_SUCCESS;
  760. }
  761. /**
  762. Allows read from PCI configuration space.
  763. @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
  764. @param Width Signifies the width of the memory operation.
  765. @param Address The address within the PCI configuration space
  766. for the PCI controller.
  767. @param Count The number of PCI configuration operations
  768. to perform.
  769. @param Buffer The destination buffer to store the results.
  770. @retval EFI_SUCCESS The data was read from the PCI root bridge.
  771. @retval EFI_INVALID_PARAMETER Invalid parameters found.
  772. **/
  773. EFI_STATUS
  774. EFIAPI
  775. RootBridgeIoPciRead (
  776. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  777. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  778. IN UINT64 Address,
  779. IN UINTN Count,
  780. IN OUT VOID *Buffer
  781. )
  782. {
  783. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  784. UINT32 PciBus;
  785. UINT32 PciDev;
  786. UINT32 PciFn;
  787. UINT32 PciExtReg;
  788. USRA_ADDRESS EndPointPciAddress;
  789. UINT8 *pData8 = Buffer;
  790. UINT8 Size;
  791. Size = 1 << (Width & 0x3);
  792. if (Buffer == NULL) {
  793. return EFI_INVALID_PARAMETER;
  794. }
  795. if (Width < 0 || Width >= EfiPciWidthMaximum ) {
  796. return EFI_INVALID_PARAMETER;
  797. }
  798. //
  799. // Read Pci configuration space
  800. //
  801. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  802. if (RootBridge->HecBase == 0) {
  803. return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
  804. }
  805. if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
  806. PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
  807. } else {
  808. PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
  809. }
  810. PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
  811. PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
  812. PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
  813. USRA_BLOCK_PCIE_ADDRESS (EndPointPciAddress, Width, Count, This->SegmentNumber, PciBus, PciDev, PciFn, PciExtReg);
  814. mDynamicSiLibraryProtocol->RegisterRead (&EndPointPciAddress, pData8);
  815. return EFI_SUCCESS;
  816. }
  817. /**
  818. Allows write to PCI configuration space.
  819. @param This A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
  820. @param Width Signifies the width of the memory operation.
  821. @param Address The address within the PCI configuration space
  822. for the PCI controller.
  823. @param Count The number of PCI configuration operations
  824. to perform.
  825. @param Buffer The source buffer to get the results.
  826. @retval EFI_SUCCESS The data was written to the PCI root bridge.
  827. @retval EFI_INVALID_PARAMETER Invalid parameters found.
  828. **/
  829. EFI_STATUS
  830. EFIAPI
  831. RootBridgeIoPciWrite (
  832. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  833. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
  834. IN UINT64 Address,
  835. IN UINTN Count,
  836. IN OUT VOID *Buffer
  837. )
  838. {
  839. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  840. UINT32 PciBus;
  841. UINT32 PciDev;
  842. UINT32 PciFn;
  843. UINT32 PciExtReg;
  844. USRA_ADDRESS EndPointPciAddress;
  845. UINT8 *pData8 = Buffer;
  846. UINT8 Size;
  847. Size = 1 << (Width & 0x3);
  848. if (Buffer == NULL) {
  849. return EFI_INVALID_PARAMETER;
  850. }
  851. if (Width < 0 || Width >= EfiPciWidthMaximum) {
  852. return EFI_INVALID_PARAMETER;
  853. }
  854. //
  855. // Write Pci configuration space
  856. //
  857. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  858. if (RootBridge->HecBase == 0) {
  859. return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
  860. }
  861. if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) {
  862. PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register;
  863. } else {
  864. PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF;
  865. }
  866. PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus;
  867. PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device;
  868. PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function;
  869. USRA_BLOCK_PCIE_ADDRESS (EndPointPciAddress, Width, Count, This->SegmentNumber, PciBus, PciDev, PciFn, PciExtReg);
  870. mDynamicSiLibraryProtocol->RegisterWrite (&EndPointPciAddress, pData8);
  871. return EFI_SUCCESS;
  872. }
  873. /**
  874. Provides the PCI controller-specific address needed to access
  875. system memory for DMA.
  876. @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  877. @param Operation Indicate if the bus master is going to read or write
  878. to system memory.
  879. @param HostAddress The system memory address to map on the PCI controller.
  880. @param NumberOfBytes On input the number of bytes to map.
  881. On output the number of bytes that were mapped.
  882. @param DeviceAddress The resulting map address for the bus master PCI
  883. controller to use to access the system memory's HostAddress.
  884. @param Mapping The value to pass to Unmap() when the bus master DMA
  885. operation is complete.
  886. @retval EFI_SUCCESS Success.
  887. @retval EFI_INVALID_PARAMETER Invalid parameters found.
  888. @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
  889. @retval EFI_DEVICE_ERROR The System hardware could not map the requested address.
  890. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to lack of resources.
  891. **/
  892. EFI_STATUS
  893. EFIAPI
  894. RootBridgeIoMap (
  895. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  896. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
  897. IN VOID *HostAddress,
  898. IN OUT UINTN *NumberOfBytes,
  899. OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
  900. OUT VOID **Mapping
  901. )
  902. {
  903. EFI_STATUS Status;
  904. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  905. EFI_PHYSICAL_ADDRESS PhysicalAddress;
  906. MAP_INFO *MapInfo;
  907. if (NumberOfBytes == NULL || Mapping == NULL || DeviceAddress == NULL || HostAddress == NULL) {
  908. return EFI_INVALID_PARAMETER;
  909. }
  910. //
  911. // Initialize the return values to their defaults
  912. //
  913. *Mapping = NULL;
  914. //
  915. // Make sure that Operation is valid
  916. //
  917. if ((UINT32) Operation >= EfiPciOperationMaximum) {
  918. return EFI_INVALID_PARAMETER;
  919. }
  920. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  921. if (mIoMmu != NULL) {
  922. if (!RootBridge->DmaAbove4G) {
  923. //
  924. // Clear 64bit support
  925. //
  926. if (Operation > EfiPciOperationBusMasterCommonBuffer) {
  927. Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64);
  928. }
  929. }
  930. Status = mIoMmu->Map (
  931. mIoMmu,
  932. (EDKII_IOMMU_OPERATION) Operation,
  933. HostAddress,
  934. NumberOfBytes,
  935. DeviceAddress,
  936. Mapping
  937. );
  938. return Status;
  939. }
  940. //
  941. // Most PCAT like chipsets can not handle performing DMA above 4GB.
  942. // If any part of the DMA transfer being mapped is above 4GB, then
  943. // map the DMA transfer to a buffer below 4GB.
  944. //
  945. PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
  946. if ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB) {
  947. //
  948. // Common Buffer operations can not be remapped. If the common buffer
  949. // if above 4GB, then it is not possible to generate a mapping, so return
  950. // an error.
  951. //
  952. if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
  953. return EFI_INVALID_PARAMETER;
  954. }
  955. //
  956. // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
  957. // called later.
  958. //
  959. MapInfo = AllocatePool (sizeof (MAP_INFO));
  960. if (MapInfo == NULL) {
  961. *NumberOfBytes = 0;
  962. return EFI_OUT_OF_RESOURCES;
  963. }
  964. //
  965. // Return a pointer to the MAP_INFO structure in Mapping
  966. //
  967. *Mapping = MapInfo;
  968. //
  969. // Initialize the MAP_INFO structure
  970. //
  971. MapInfo->Operation = Operation;
  972. MapInfo->NumberOfBytes = *NumberOfBytes;
  973. MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
  974. MapInfo->HostAddress = PhysicalAddress;
  975. MapInfo->MappedHostAddress = SIZE_4GB - 1;
  976. //
  977. // Allocate a buffer below 4GB to map the transfer to.
  978. //
  979. Status = gBS->AllocatePages (
  980. AllocateMaxAddress,
  981. EfiBootServicesData,
  982. MapInfo->NumberOfPages,
  983. &MapInfo->MappedHostAddress
  984. );
  985. if (EFI_ERROR (Status)) {
  986. FreePool (MapInfo);
  987. *NumberOfBytes = 0;
  988. return Status;
  989. }
  990. //
  991. // If this is a read operation from the Bus Master's point of view,
  992. // then copy the contents of the real buffer into the mapped buffer
  993. // so the Bus Master can read the contents of the real buffer.
  994. //
  995. if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
  996. CopyMem (
  997. (VOID *) (UINTN) MapInfo->MappedHostAddress,
  998. (VOID *) (UINTN) MapInfo->HostAddress,
  999. MapInfo->NumberOfBytes
  1000. );
  1001. }
  1002. //
  1003. // The DeviceAddress is the address of the maped buffer below 4GB
  1004. //
  1005. *DeviceAddress = MapInfo->MappedHostAddress;
  1006. } else {
  1007. //
  1008. // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
  1009. //
  1010. *DeviceAddress = PhysicalAddress;
  1011. }
  1012. return EFI_SUCCESS;
  1013. }
  1014. /**
  1015. Completes the Map() operation and releases any corresponding resources.
  1016. The Unmap() function completes the Map() operation and releases any
  1017. corresponding resources.
  1018. If the operation was an EfiPciOperationBusMasterWrite or
  1019. EfiPciOperationBusMasterWrite64, the data is committed to the target system
  1020. memory.
  1021. Any resources used for the mapping are freed.
  1022. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1023. @param[in] Mapping The mapping value returned from Map().
  1024. @retval EFI_SUCCESS The range was unmapped.
  1025. @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
  1026. @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
  1027. **/
  1028. EFI_STATUS
  1029. EFIAPI
  1030. RootBridgeIoUnmap (
  1031. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  1032. IN VOID *Mapping
  1033. )
  1034. {
  1035. EFI_STATUS Status;
  1036. MAP_INFO *MapInfo;
  1037. if (mIoMmu != NULL) {
  1038. Status = mIoMmu->Unmap (
  1039. mIoMmu,
  1040. Mapping
  1041. );
  1042. return Status;
  1043. }
  1044. //
  1045. // See if the Map() operation associated with this Unmap() required a mapping buffer.
  1046. // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
  1047. //
  1048. if (Mapping != NULL) {
  1049. //
  1050. // Get the MAP_INFO structure from Mapping
  1051. //
  1052. MapInfo = (MAP_INFO *) Mapping;
  1053. //
  1054. // If this is a write operation from the Bus Master's point of view,
  1055. // then copy the contents of the mapped buffer into the real buffer
  1056. // so the processor can read the contents of the real buffer.
  1057. //
  1058. if ((MapInfo->Operation == EfiPciOperationBusMasterWrite) ||
  1059. (MapInfo->Operation == EfiPciOperationBusMasterWrite64)
  1060. ) {
  1061. CopyMem (
  1062. (VOID *) (UINTN) MapInfo->HostAddress,
  1063. (VOID *) (UINTN) MapInfo->MappedHostAddress,
  1064. MapInfo->NumberOfBytes
  1065. );
  1066. }
  1067. //
  1068. // Free the mapped buffer and the MAP_INFO structure.
  1069. //
  1070. gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
  1071. FreePool (Mapping);
  1072. }
  1073. return EFI_SUCCESS;
  1074. }
  1075. /**
  1076. Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer
  1077. or EfiPciOperationBusMasterCommonBuffer64 mapping.
  1078. @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1079. @param Type This parameter is not used and must be ignored.
  1080. @param MemoryType The type of memory to allocate, EfiBootServicesData or
  1081. EfiRuntimeServicesData.
  1082. @param Pages The number of pages to allocate.
  1083. @param HostAddress A pointer to store the base system memory address of the
  1084. allocated range.
  1085. @param Attributes The requested bit mask of attributes for the allocated
  1086. range. Only the attributes
  1087. EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE,
  1088. EFI_PCI_ATTRIBUTE_MEMORY_CACHED, and
  1089. EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this
  1090. function.
  1091. @retval EFI_SUCCESS The requested memory pages were allocated.
  1092. @retval EFI_INVALID_PARAMETER MemoryType is invalid.
  1093. @retval EFI_INVALID_PARAMETER HostAddress is NULL.
  1094. @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal
  1095. attribute bits are MEMORY_WRITE_COMBINE,
  1096. MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
  1097. @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
  1098. **/
  1099. EFI_STATUS
  1100. EFIAPI
  1101. RootBridgeIoAllocateBuffer (
  1102. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  1103. IN EFI_ALLOCATE_TYPE Type,
  1104. IN EFI_MEMORY_TYPE MemoryType,
  1105. IN UINTN Pages,
  1106. OUT VOID **HostAddress,
  1107. IN UINT64 Attributes
  1108. )
  1109. {
  1110. EFI_STATUS Status;
  1111. EFI_PHYSICAL_ADDRESS PhysicalAddress;
  1112. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  1113. //
  1114. // Validate Attributes
  1115. //
  1116. if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
  1117. return EFI_UNSUPPORTED;
  1118. }
  1119. //
  1120. // Check for invalid inputs
  1121. //
  1122. if (HostAddress == NULL) {
  1123. return EFI_INVALID_PARAMETER;
  1124. }
  1125. //
  1126. // The only valid memory types are EfiBootServicesData and
  1127. // EfiRuntimeServicesData
  1128. //
  1129. if (MemoryType != EfiBootServicesData &&
  1130. MemoryType != EfiRuntimeServicesData) {
  1131. return EFI_INVALID_PARAMETER;
  1132. }
  1133. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  1134. if (mIoMmu != NULL) {
  1135. if (!RootBridge->DmaAbove4G) {
  1136. //
  1137. // Clear DUAL_ADDRESS_CYCLE
  1138. //
  1139. Attributes &= ~((UINT64) EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
  1140. }
  1141. Status = mIoMmu->AllocateBuffer (
  1142. mIoMmu,
  1143. Type,
  1144. MemoryType,
  1145. Pages,
  1146. HostAddress,
  1147. Attributes
  1148. );
  1149. return Status;
  1150. }
  1151. //
  1152. // Limit allocations to memory below 4GB
  1153. //
  1154. PhysicalAddress = SIZE_4GB - 1;
  1155. Status = gBS->AllocatePages (
  1156. AllocateMaxAddress,
  1157. MemoryType,
  1158. Pages,
  1159. &PhysicalAddress
  1160. );
  1161. if (EFI_ERROR (Status)) {
  1162. return Status;
  1163. }
  1164. *HostAddress = (VOID *) (UINTN) PhysicalAddress;
  1165. return EFI_SUCCESS;
  1166. }
  1167. /**
  1168. Frees memory that was allocated with AllocateBuffer().
  1169. The FreeBuffer() function frees memory that was allocated with
  1170. AllocateBuffer().
  1171. @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1172. @param Pages The number of pages to free.
  1173. @param HostAddress The base system memory address of the allocated range.
  1174. @retval EFI_SUCCESS The requested memory pages were freed.
  1175. @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
  1176. Pages was not allocated with AllocateBuffer().
  1177. **/
  1178. EFI_STATUS
  1179. EFIAPI
  1180. RootBridgeIoFreeBuffer (
  1181. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  1182. IN UINTN Pages,
  1183. OUT VOID *HostAddress
  1184. )
  1185. {
  1186. EFI_STATUS Status;
  1187. if (mIoMmu != NULL) {
  1188. Status = mIoMmu->FreeBuffer (
  1189. mIoMmu,
  1190. Pages,
  1191. HostAddress
  1192. );
  1193. return Status;
  1194. }
  1195. return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
  1196. }
  1197. /**
  1198. Flushes all PCI posted write transactions from a PCI host bridge to system
  1199. memory.
  1200. The Flush() function flushes any PCI posted write transactions from a PCI
  1201. host bridge to system memory. Posted write transactions are generated by PCI
  1202. bus masters when they perform write transactions to target addresses in
  1203. system memory.
  1204. This function does not flush posted write transactions from any PCI bridges.
  1205. A PCI controller specific action must be taken to guarantee that the posted
  1206. write transactions have been flushed from the PCI controller and from all the
  1207. PCI bridges into the PCI host bridge. This is typically done with a PCI read
  1208. transaction from the PCI controller prior to calling Flush().
  1209. @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1210. @retval EFI_SUCCESS The PCI posted write transactions were flushed
  1211. from the PCI host bridge to system memory.
  1212. @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed
  1213. from the PCI host bridge due to a hardware error.
  1214. **/
  1215. EFI_STATUS
  1216. EFIAPI
  1217. RootBridgeIoFlush (
  1218. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
  1219. )
  1220. {
  1221. return EFI_SUCCESS;
  1222. }
  1223. /**
  1224. Gets the attributes that a PCI root bridge supports setting with
  1225. SetAttributes(), and the attributes that a PCI root bridge is currently
  1226. using.
  1227. The GetAttributes() function returns the mask of attributes that this PCI
  1228. root bridge supports and the mask of attributes that the PCI root bridge is
  1229. currently using.
  1230. @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1231. @param Supported A pointer to the mask of attributes that this PCI root
  1232. bridge supports setting with SetAttributes().
  1233. @param Attributes A pointer to the mask of attributes that this PCI root
  1234. bridge is currently using.
  1235. @retval EFI_SUCCESS If Supports is not NULL, then the attributes
  1236. that the PCI root bridge supports is returned
  1237. in Supports. If Attributes is not NULL, then
  1238. the attributes that the PCI root bridge is
  1239. currently using is returned in Attributes.
  1240. @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
  1241. **/
  1242. EFI_STATUS
  1243. EFIAPI
  1244. RootBridgeIoGetAttributes (
  1245. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  1246. OUT UINT64 *Supported,
  1247. OUT UINT64 *Attributes
  1248. )
  1249. {
  1250. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  1251. if (Attributes == NULL && Supported == NULL) {
  1252. return EFI_INVALID_PARAMETER;
  1253. }
  1254. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  1255. //
  1256. // Set the return value for Supported and Attributes
  1257. //
  1258. if (Supported != NULL) {
  1259. *Supported = RootBridge->Supports;
  1260. }
  1261. if (Attributes != NULL) {
  1262. *Attributes = RootBridge->Attributes;
  1263. }
  1264. return EFI_SUCCESS;
  1265. }
  1266. /**
  1267. Sets attributes for a resource range on a PCI root bridge.
  1268. The SetAttributes() function sets the attributes specified in Attributes for
  1269. the PCI root bridge on the resource range specified by ResourceBase and
  1270. ResourceLength. Since the granularity of setting these attributes may vary
  1271. from resource type to resource type, and from platform to platform, the
  1272. actual resource range and the one passed in by the caller may differ. As a
  1273. result, this function may set the attributes specified by Attributes on a
  1274. larger resource range than the caller requested. The actual range is returned
  1275. in ResourceBase and ResourceLength. The caller is responsible for verifying
  1276. that the actual range for which the attributes were set is acceptable.
  1277. @param This A pointer to the
  1278. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1279. @param Attributes The mask of attributes to set. If the
  1280. attribute bit MEMORY_WRITE_COMBINE,
  1281. MEMORY_CACHED, or MEMORY_DISABLE is set,
  1282. then the resource range is specified by
  1283. ResourceBase and ResourceLength. If
  1284. MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
  1285. MEMORY_DISABLE are not set, then
  1286. ResourceBase and ResourceLength are ignored,
  1287. and may be NULL.
  1288. @param ResourceBase A pointer to the base address of the
  1289. resource range to be modified by the
  1290. attributes specified by Attributes.
  1291. @param ResourceLength A pointer to the length of the resource
  1292. range to be modified by the attributes
  1293. specified by Attributes.
  1294. @retval EFI_SUCCESS The current configuration of this PCI root bridge
  1295. was returned in Resources.
  1296. @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
  1297. could not be retrieved.
  1298. **/
  1299. EFI_STATUS
  1300. EFIAPI
  1301. RootBridgeIoSetAttributes (
  1302. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  1303. IN UINT64 Attributes,
  1304. IN OUT UINT64 *ResourceBase,
  1305. IN OUT UINT64 *ResourceLength
  1306. )
  1307. {
  1308. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  1309. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  1310. if ((Attributes & (~RootBridge->Supports)) != 0) {
  1311. return EFI_UNSUPPORTED;
  1312. }
  1313. RootBridge->Attributes = Attributes;
  1314. return EFI_SUCCESS;
  1315. }
  1316. /**
  1317. Retrieves the current resource settings of this PCI root bridge in the form
  1318. of a set of ACPI resource descriptors.
  1319. There are only two resource descriptor types from the ACPI Specification that
  1320. may be used to describe the current resources allocated to a PCI root bridge.
  1321. These are the QWORD Address Space Descriptor, and the End Tag. The QWORD
  1322. Address Space Descriptor can describe memory, I/O, and bus number ranges for
  1323. dynamic or fixed resources. The configuration of a PCI root bridge is described
  1324. with one or more QWORD Address Space Descriptors followed by an End Tag.
  1325. @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  1326. @param[out] Resources A pointer to the resource descriptors that
  1327. describe the current configuration of this PCI root
  1328. bridge. The storage for the resource
  1329. descriptors is allocated by this function. The
  1330. caller must treat the return buffer as read-only
  1331. data, and the buffer must not be freed by the
  1332. caller.
  1333. @retval EFI_SUCCESS The current configuration of this PCI root bridge
  1334. was returned in Resources.
  1335. @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge
  1336. could not be retrieved.
  1337. **/
  1338. EFI_STATUS
  1339. EFIAPI
  1340. RootBridgeIoConfiguration (
  1341. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
  1342. OUT VOID **Resources
  1343. )
  1344. {
  1345. EFI_STATUS Status;
  1346. UINTN Idx;
  1347. PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
  1348. PCI_RES_NODE *ResAllocNode;
  1349. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config;
  1350. //
  1351. // Get this instance of the Root Bridge.
  1352. //
  1353. RootBridge = ROOT_BRIDGE_FROM_THIS (This);
  1354. //
  1355. // If the pointer is not NULL, it points to a buffer already allocated.
  1356. //
  1357. if (RootBridge->ConfigBuffer == NULL) {
  1358. Status = gBS->AllocatePool (
  1359. EfiBootServicesData,
  1360. TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
  1361. &RootBridge->ConfigBuffer
  1362. );
  1363. if (EFI_ERROR (Status)) {
  1364. return EFI_OUT_OF_RESOURCES;
  1365. }
  1366. }
  1367. Config = RootBridge->ConfigBuffer;
  1368. ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
  1369. for (Idx = 0; Idx < TypeMax; Idx++) {
  1370. ResAllocNode = &RootBridge->ResAllocNode[Idx];
  1371. if (ResAllocNode->Status != ResAllocated) {
  1372. continue;
  1373. }
  1374. switch (ResAllocNode->Type) {
  1375. case TypeIo:
  1376. Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1377. Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
  1378. Config->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
  1379. Config->AddrRangeMin = ResAllocNode->Base;
  1380. Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
  1381. Config->AddrLen = ResAllocNode->Length;
  1382. break;
  1383. case TypeMem32:
  1384. Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1385. Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
  1386. Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1387. Config->AddrSpaceGranularity = 32;
  1388. Config->AddrRangeMin = ResAllocNode->Base;
  1389. Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
  1390. Config->AddrLen = ResAllocNode->Length;
  1391. break;
  1392. case TypePMem32:
  1393. Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1394. Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
  1395. Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1396. Config->SpecificFlag = 6;
  1397. Config->AddrSpaceGranularity = 32;
  1398. Config->AddrRangeMin = ResAllocNode->Base;
  1399. Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
  1400. Config->AddrLen = ResAllocNode->Length;
  1401. break;
  1402. case TypeMem64:
  1403. Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1404. Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
  1405. Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1406. Config->SpecificFlag = 6;
  1407. Config->AddrSpaceGranularity = 64;
  1408. Config->AddrRangeMin = ResAllocNode->Base;
  1409. Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
  1410. Config->AddrLen = ResAllocNode->Length;
  1411. break;
  1412. case TypePMem64:
  1413. Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1414. Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
  1415. Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
  1416. Config->SpecificFlag = 6;
  1417. Config->AddrSpaceGranularity = 64;
  1418. Config->AddrRangeMin = ResAllocNode->Base;
  1419. Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
  1420. Config->AddrLen = ResAllocNode->Length;
  1421. break;
  1422. case TypeBus:
  1423. Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
  1424. Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
  1425. Config->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
  1426. Config->AddrRangeMin = ResAllocNode->Base;
  1427. Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1;
  1428. Config->AddrLen = ResAllocNode->Length;
  1429. break;
  1430. default:
  1431. break;
  1432. }
  1433. Config++;
  1434. }
  1435. //
  1436. // Terminate the entries.
  1437. //
  1438. ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc = ACPI_END_TAG_DESCRIPTOR;
  1439. ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum = 0x0;
  1440. *Resources = RootBridge->ConfigBuffer;
  1441. return EFI_SUCCESS;
  1442. }