PciEnumeratorSupport.c 83 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888
  1. /** @file
  2. PCI emumeration support functions implementation for PCI Bus module.
  3. Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
  4. (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "PciBus.h"
  8. extern CHAR16 *mBarTypeStr[];
  9. extern EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
  10. #define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
  11. #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
  12. #define SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL
  13. #define DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL
  14. /**
  15. This routine is used to check whether the pci device is present.
  16. @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
  17. @param Pci Output buffer for PCI device configuration space.
  18. @param Bus PCI bus NO.
  19. @param Device PCI device NO.
  20. @param Func PCI Func NO.
  21. @retval EFI_NOT_FOUND PCI device not present.
  22. @retval EFI_SUCCESS PCI device is found.
  23. **/
  24. EFI_STATUS
  25. PciDevicePresent (
  26. IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
  27. OUT PCI_TYPE00 *Pci,
  28. IN UINT8 Bus,
  29. IN UINT8 Device,
  30. IN UINT8 Func
  31. )
  32. {
  33. UINT64 Address;
  34. EFI_STATUS Status;
  35. //
  36. // Create PCI address map in terms of Bus, Device and Func
  37. //
  38. Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
  39. //
  40. // Read the Vendor ID register
  41. //
  42. Status = PciRootBridgeIo->Pci.Read (
  43. PciRootBridgeIo,
  44. EfiPciWidthUint32,
  45. Address,
  46. 1,
  47. Pci
  48. );
  49. if (!EFI_ERROR (Status) && ((Pci->Hdr).VendorId != 0xffff)) {
  50. //
  51. // Read the entire config header for the device
  52. //
  53. Status = PciRootBridgeIo->Pci.Read (
  54. PciRootBridgeIo,
  55. EfiPciWidthUint32,
  56. Address,
  57. sizeof (PCI_TYPE00) / sizeof (UINT32),
  58. Pci
  59. );
  60. return EFI_SUCCESS;
  61. }
  62. return EFI_NOT_FOUND;
  63. }
  64. /**
  65. Collect all the resource information under this root bridge.
  66. A database that records all the information about pci device subject to this
  67. root bridge will then be created.
  68. @param Bridge Parent bridge instance.
  69. @param StartBusNumber Bus number of beginning.
  70. @retval EFI_SUCCESS PCI device is found.
  71. @retval other Some error occurred when reading PCI bridge information.
  72. **/
  73. EFI_STATUS
  74. PciPciDeviceInfoCollector (
  75. IN PCI_IO_DEVICE *Bridge,
  76. IN UINT8 StartBusNumber
  77. )
  78. {
  79. EFI_STATUS Status;
  80. PCI_TYPE00 Pci;
  81. UINT8 Device;
  82. UINT8 Func;
  83. UINT8 SecBus;
  84. PCI_IO_DEVICE *PciIoDevice;
  85. EFI_PCI_IO_PROTOCOL *PciIo;
  86. Status = EFI_SUCCESS;
  87. SecBus = 0;
  88. for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
  89. for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
  90. //
  91. // Check to see whether PCI device is present
  92. //
  93. Status = PciDevicePresent (
  94. Bridge->PciRootBridgeIo,
  95. &Pci,
  96. (UINT8)StartBusNumber,
  97. (UINT8)Device,
  98. (UINT8)Func
  99. );
  100. if (EFI_ERROR (Status) && (Func == 0)) {
  101. //
  102. // go to next device if there is no Function 0
  103. //
  104. break;
  105. }
  106. if (!EFI_ERROR (Status)) {
  107. //
  108. // Call back to host bridge function
  109. //
  110. PreprocessController (Bridge, (UINT8)StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
  111. //
  112. // Collect all the information about the PCI device discovered
  113. //
  114. Status = PciSearchDevice (
  115. Bridge,
  116. &Pci,
  117. (UINT8)StartBusNumber,
  118. Device,
  119. Func,
  120. &PciIoDevice
  121. );
  122. //
  123. // Recursively scan PCI busses on the other side of PCI-PCI bridges
  124. //
  125. //
  126. if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
  127. //
  128. // If it is PPB, we need to get the secondary bus to continue the enumeration
  129. //
  130. PciIo = &(PciIoDevice->PciIo);
  131. Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 1, &SecBus);
  132. if (EFI_ERROR (Status)) {
  133. return Status;
  134. }
  135. //
  136. // Ensure secondary bus number is greater than the primary bus number to avoid
  137. // any potential dead loop when PcdPciDisableBusEnumeration is set to TRUE
  138. //
  139. if (SecBus <= StartBusNumber) {
  140. break;
  141. }
  142. //
  143. // Get resource padding for PPB
  144. //
  145. GetResourcePaddingPpb (PciIoDevice);
  146. //
  147. // Deep enumerate the next level bus
  148. //
  149. Status = PciPciDeviceInfoCollector (
  150. PciIoDevice,
  151. (UINT8)(SecBus)
  152. );
  153. }
  154. if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
  155. //
  156. // Skip sub functions, this is not a multi function device
  157. //
  158. Func = PCI_MAX_FUNC;
  159. }
  160. }
  161. }
  162. }
  163. return EFI_SUCCESS;
  164. }
  165. /**
  166. Search required device and create PCI device instance.
  167. @param Bridge Parent bridge instance.
  168. @param Pci Input PCI device information block.
  169. @param Bus PCI bus NO.
  170. @param Device PCI device NO.
  171. @param Func PCI func NO.
  172. @param PciDevice Output of searched PCI device instance.
  173. @retval EFI_SUCCESS Successfully created PCI device instance.
  174. @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
  175. **/
  176. EFI_STATUS
  177. PciSearchDevice (
  178. IN PCI_IO_DEVICE *Bridge,
  179. IN PCI_TYPE00 *Pci,
  180. IN UINT8 Bus,
  181. IN UINT8 Device,
  182. IN UINT8 Func,
  183. OUT PCI_IO_DEVICE **PciDevice
  184. )
  185. {
  186. PCI_IO_DEVICE *PciIoDevice;
  187. BOOLEAN IgnoreOptionRom;
  188. PciIoDevice = NULL;
  189. IgnoreOptionRom = FALSE;
  190. DEBUG ((
  191. DEBUG_INFO,
  192. "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
  193. IS_PCI_BRIDGE (Pci) ? L"PPB" :
  194. IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
  195. L"PCI",
  196. Bus,
  197. Device,
  198. Func
  199. ));
  200. if (!IS_PCI_BRIDGE (Pci)) {
  201. if (IS_CARDBUS_BRIDGE (Pci)) {
  202. PciIoDevice = GatherP2CInfo (
  203. Bridge,
  204. Pci,
  205. Bus,
  206. Device,
  207. Func
  208. );
  209. if ((PciIoDevice != NULL) && gFullEnumeration) {
  210. InitializeP2C (PciIoDevice);
  211. }
  212. } else {
  213. //
  214. // Create private data for Pci Device
  215. //
  216. PciIoDevice = GatherDeviceInfo (
  217. Bridge,
  218. Pci,
  219. Bus,
  220. Device,
  221. Func
  222. );
  223. }
  224. } else {
  225. //
  226. // Create private data for PPB
  227. //
  228. PciIoDevice = GatherPpbInfo (
  229. Bridge,
  230. Pci,
  231. Bus,
  232. Device,
  233. Func
  234. );
  235. //
  236. // Special initialization for PPB including making the PPB quiet
  237. //
  238. if ((PciIoDevice != NULL) && gFullEnumeration) {
  239. InitializePpb (PciIoDevice);
  240. }
  241. }
  242. if (PciIoDevice == NULL) {
  243. return EFI_OUT_OF_RESOURCES;
  244. }
  245. //
  246. // Update the bar information for this PCI device so as to support some specific device
  247. //
  248. UpdatePciInfo (PciIoDevice, &IgnoreOptionRom);
  249. if (PciIoDevice->DevicePath == NULL) {
  250. return EFI_OUT_OF_RESOURCES;
  251. }
  252. //
  253. // Detect this function has option rom
  254. //
  255. if (gFullEnumeration) {
  256. if (!IS_CARDBUS_BRIDGE (Pci) && !IgnoreOptionRom) {
  257. GetOpRomInfo (PciIoDevice);
  258. }
  259. ResetPowerManagementFeature (PciIoDevice);
  260. }
  261. //
  262. // Insert it into a global tree for future reference
  263. //
  264. InsertPciDevice (Bridge, PciIoDevice);
  265. //
  266. // Determine PCI device attributes
  267. //
  268. if (PciDevice != NULL) {
  269. *PciDevice = PciIoDevice;
  270. }
  271. return EFI_SUCCESS;
  272. }
  273. /**
  274. Dump the PPB padding resource information.
  275. @param PciIoDevice PCI IO instance.
  276. @param ResourceType The desired resource type to dump.
  277. PciBarTypeUnknown means to dump all types of resources.
  278. **/
  279. VOID
  280. DumpPpbPaddingResource (
  281. IN PCI_IO_DEVICE *PciIoDevice,
  282. IN PCI_BAR_TYPE ResourceType
  283. )
  284. {
  285. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
  286. PCI_BAR_TYPE Type;
  287. if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
  288. return;
  289. }
  290. if ((ResourceType == PciBarTypeIo16) || (ResourceType == PciBarTypeIo32)) {
  291. ResourceType = PciBarTypeIo;
  292. }
  293. for (Descriptor = PciIoDevice->ResourcePaddingDescriptors; Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR; Descriptor++) {
  294. Type = PciBarTypeUnknown;
  295. if ((Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {
  296. Type = PciBarTypeIo;
  297. } else if ((Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {
  298. if (Descriptor->AddrSpaceGranularity == 32) {
  299. //
  300. // prefetchable
  301. //
  302. if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
  303. Type = PciBarTypePMem32;
  304. }
  305. //
  306. // Non-prefetchable
  307. //
  308. if (Descriptor->SpecificFlag == 0) {
  309. Type = PciBarTypeMem32;
  310. }
  311. }
  312. if (Descriptor->AddrSpaceGranularity == 64) {
  313. //
  314. // prefetchable
  315. //
  316. if (Descriptor->SpecificFlag == EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) {
  317. Type = PciBarTypePMem64;
  318. }
  319. //
  320. // Non-prefetchable
  321. //
  322. if (Descriptor->SpecificFlag == 0) {
  323. Type = PciBarTypeMem64;
  324. }
  325. }
  326. }
  327. if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
  328. DEBUG ((
  329. DEBUG_INFO,
  330. " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
  331. mBarTypeStr[Type],
  332. Descriptor->AddrRangeMax,
  333. Descriptor->AddrLen
  334. ));
  335. }
  336. }
  337. }
  338. /**
  339. Dump the PCI BAR information.
  340. @param PciIoDevice PCI IO instance.
  341. **/
  342. VOID
  343. DumpPciBars (
  344. IN PCI_IO_DEVICE *PciIoDevice
  345. )
  346. {
  347. UINTN Index;
  348. for (Index = 0; Index < PCI_MAX_BAR; Index++) {
  349. if (PciIoDevice->PciBar[Index].BarType == PciBarTypeUnknown) {
  350. continue;
  351. }
  352. DEBUG ((
  353. DEBUG_INFO,
  354. " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
  355. Index,
  356. mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
  357. PciIoDevice->PciBar[Index].Alignment,
  358. PciIoDevice->PciBar[Index].Length,
  359. PciIoDevice->PciBar[Index].Offset
  360. ));
  361. }
  362. for (Index = 0; Index < PCI_MAX_BAR; Index++) {
  363. if ((PciIoDevice->VfPciBar[Index].BarType == PciBarTypeUnknown) && (PciIoDevice->VfPciBar[Index].Length == 0)) {
  364. continue;
  365. }
  366. DEBUG ((
  367. DEBUG_INFO,
  368. " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
  369. Index,
  370. mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
  371. PciIoDevice->VfPciBar[Index].Alignment,
  372. PciIoDevice->VfPciBar[Index].Length,
  373. PciIoDevice->VfPciBar[Index].Offset
  374. ));
  375. }
  376. DEBUG ((DEBUG_INFO, "\n"));
  377. }
  378. /**
  379. Create PCI device instance for PCI device.
  380. @param Bridge Parent bridge instance.
  381. @param Pci Input PCI device information block.
  382. @param Bus PCI device Bus NO.
  383. @param Device PCI device Device NO.
  384. @param Func PCI device's func NO.
  385. @return Created PCI device instance.
  386. **/
  387. PCI_IO_DEVICE *
  388. GatherDeviceInfo (
  389. IN PCI_IO_DEVICE *Bridge,
  390. IN PCI_TYPE00 *Pci,
  391. IN UINT8 Bus,
  392. IN UINT8 Device,
  393. IN UINT8 Func
  394. )
  395. {
  396. UINTN Offset;
  397. UINTN BarIndex;
  398. PCI_IO_DEVICE *PciIoDevice;
  399. PciIoDevice = CreatePciIoDevice (
  400. Bridge,
  401. Pci,
  402. Bus,
  403. Device,
  404. Func
  405. );
  406. if (PciIoDevice == NULL) {
  407. return NULL;
  408. }
  409. //
  410. // If it is a full enumeration, disconnect the device in advance
  411. //
  412. if (gFullEnumeration) {
  413. PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  414. }
  415. //
  416. // Start to parse the bars
  417. //
  418. for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
  419. Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
  420. }
  421. //
  422. // Parse the SR-IOV VF bars
  423. //
  424. if (PcdGetBool (PcdSrIovSupport) && (PciIoDevice->SrIovCapabilityOffset != 0)) {
  425. for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;
  426. Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;
  427. BarIndex++)
  428. {
  429. ASSERT (BarIndex < PCI_MAX_BAR);
  430. Offset = PciIovParseVfBar (PciIoDevice, Offset, BarIndex);
  431. }
  432. }
  433. DEBUG_CODE (
  434. DumpPciBars (PciIoDevice);
  435. );
  436. return PciIoDevice;
  437. }
  438. /**
  439. Create PCI device instance for PCI-PCI bridge.
  440. @param Bridge Parent bridge instance.
  441. @param Pci Input PCI device information block.
  442. @param Bus PCI device Bus NO.
  443. @param Device PCI device Device NO.
  444. @param Func PCI device's func NO.
  445. @return Created PCI device instance.
  446. **/
  447. PCI_IO_DEVICE *
  448. GatherPpbInfo (
  449. IN PCI_IO_DEVICE *Bridge,
  450. IN PCI_TYPE00 *Pci,
  451. IN UINT8 Bus,
  452. IN UINT8 Device,
  453. IN UINT8 Func
  454. )
  455. {
  456. PCI_IO_DEVICE *PciIoDevice;
  457. EFI_STATUS Status;
  458. UINT8 Value;
  459. EFI_PCI_IO_PROTOCOL *PciIo;
  460. UINT8 Temp;
  461. UINT32 PMemBaseLimit;
  462. UINT16 PrefetchableMemoryBase;
  463. UINT16 PrefetchableMemoryLimit;
  464. PciIoDevice = CreatePciIoDevice (
  465. Bridge,
  466. Pci,
  467. Bus,
  468. Device,
  469. Func
  470. );
  471. if (PciIoDevice == NULL) {
  472. return NULL;
  473. }
  474. if (gFullEnumeration) {
  475. PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  476. //
  477. // Initialize the bridge control register
  478. //
  479. PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
  480. }
  481. //
  482. // PPB can have two BARs
  483. //
  484. if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
  485. //
  486. // Not 64-bit bar
  487. //
  488. PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
  489. }
  490. PciIo = &PciIoDevice->PciIo;
  491. //
  492. // Test whether it support 32 decode or not
  493. //
  494. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  495. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
  496. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  497. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  498. if (Value != 0) {
  499. if ((Value & 0x01) != 0) {
  500. PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
  501. } else {
  502. PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
  503. }
  504. }
  505. //
  506. // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
  507. // PCI bridge supporting non-standard I/O window alignment less than 4K.
  508. //
  509. PciIoDevice->BridgeIoAlignment = 0xFFF;
  510. if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe)) {
  511. //
  512. // Check any bits of bit 3-1 of I/O Base Register are writable.
  513. // if so, it is assumed non-standard I/O window alignment is supported by this bridge.
  514. // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
  515. //
  516. Value = (UINT8)(Temp ^ (BIT3 | BIT2 | BIT1));
  517. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  518. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
  519. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
  520. Value = (UINT8)((Value ^ Temp) & (BIT3 | BIT2 | BIT1));
  521. switch (Value) {
  522. case BIT3:
  523. PciIoDevice->BridgeIoAlignment = 0x7FF;
  524. break;
  525. case BIT3 | BIT2:
  526. PciIoDevice->BridgeIoAlignment = 0x3FF;
  527. break;
  528. case BIT3 | BIT2 | BIT1:
  529. PciIoDevice->BridgeIoAlignment = 0x1FF;
  530. break;
  531. }
  532. }
  533. Status = BarExisted (
  534. PciIoDevice,
  535. 0x24,
  536. NULL,
  537. &PMemBaseLimit
  538. );
  539. //
  540. // Test if it supports 64 memory or not
  541. //
  542. // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
  543. // registers:
  544. // 0 - the bridge supports only 32 bit addresses.
  545. // 1 - the bridge supports 64-bit addresses.
  546. //
  547. PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);
  548. PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);
  549. if (!EFI_ERROR (Status) &&
  550. ((PrefetchableMemoryBase & 0x000f) == 0x0001) &&
  551. ((PrefetchableMemoryLimit & 0x000f) == 0x0001))
  552. {
  553. Status = BarExisted (
  554. PciIoDevice,
  555. 0x28,
  556. NULL,
  557. NULL
  558. );
  559. if (!EFI_ERROR (Status)) {
  560. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
  561. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
  562. } else {
  563. PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
  564. }
  565. }
  566. //
  567. // Memory 32 code is required for ppb
  568. //
  569. PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
  570. GetResourcePaddingPpb (PciIoDevice);
  571. DEBUG_CODE (
  572. DumpPpbPaddingResource (PciIoDevice, PciBarTypeUnknown);
  573. DumpPciBars (PciIoDevice);
  574. );
  575. return PciIoDevice;
  576. }
  577. /**
  578. Create PCI device instance for PCI Card bridge device.
  579. @param Bridge Parent bridge instance.
  580. @param Pci Input PCI device information block.
  581. @param Bus PCI device Bus NO.
  582. @param Device PCI device Device NO.
  583. @param Func PCI device's func NO.
  584. @return Created PCI device instance.
  585. **/
  586. PCI_IO_DEVICE *
  587. GatherP2CInfo (
  588. IN PCI_IO_DEVICE *Bridge,
  589. IN PCI_TYPE00 *Pci,
  590. IN UINT8 Bus,
  591. IN UINT8 Device,
  592. IN UINT8 Func
  593. )
  594. {
  595. PCI_IO_DEVICE *PciIoDevice;
  596. PciIoDevice = CreatePciIoDevice (
  597. Bridge,
  598. Pci,
  599. Bus,
  600. Device,
  601. Func
  602. );
  603. if (PciIoDevice == NULL) {
  604. return NULL;
  605. }
  606. if (gFullEnumeration) {
  607. PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);
  608. //
  609. // Initialize the bridge control register
  610. //
  611. PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);
  612. }
  613. //
  614. // P2C only has one bar that is in 0x10
  615. //
  616. PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
  617. //
  618. // Read PciBar information from the bar register
  619. //
  620. GetBackPcCardBar (PciIoDevice);
  621. PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
  622. EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
  623. EFI_BRIDGE_IO32_DECODE_SUPPORTED;
  624. DEBUG_CODE (
  625. DumpPciBars (PciIoDevice);
  626. );
  627. return PciIoDevice;
  628. }
  629. /**
  630. Create device path for pci device.
  631. @param ParentDevicePath Parent bridge's path.
  632. @param PciIoDevice Pci device instance.
  633. @return Device path protocol instance for specific pci device.
  634. **/
  635. EFI_DEVICE_PATH_PROTOCOL *
  636. CreatePciDevicePath (
  637. IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  638. IN PCI_IO_DEVICE *PciIoDevice
  639. )
  640. {
  641. PCI_DEVICE_PATH PciNode;
  642. //
  643. // Create PCI device path
  644. //
  645. PciNode.Header.Type = HARDWARE_DEVICE_PATH;
  646. PciNode.Header.SubType = HW_PCI_DP;
  647. SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
  648. PciNode.Device = PciIoDevice->DeviceNumber;
  649. PciNode.Function = PciIoDevice->FunctionNumber;
  650. PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
  651. return PciIoDevice->DevicePath;
  652. }
  653. /**
  654. Check whether the PCI IOV VF bar is existed or not.
  655. @param PciIoDevice A pointer to the PCI_IO_DEVICE.
  656. @param Offset The offset.
  657. @param BarLengthValue The bar length value returned.
  658. @param OriginalBarValue The original bar value returned.
  659. @retval EFI_NOT_FOUND The bar doesn't exist.
  660. @retval EFI_SUCCESS The bar exist.
  661. **/
  662. EFI_STATUS
  663. VfBarExisted (
  664. IN PCI_IO_DEVICE *PciIoDevice,
  665. IN UINTN Offset,
  666. OUT UINT32 *BarLengthValue,
  667. OUT UINT32 *OriginalBarValue
  668. )
  669. {
  670. EFI_PCI_IO_PROTOCOL *PciIo;
  671. UINT32 OriginalValue;
  672. UINT32 Value;
  673. EFI_TPL OldTpl;
  674. //
  675. // Ensure it is called properly
  676. //
  677. ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
  678. if (PciIoDevice->SrIovCapabilityOffset == 0) {
  679. return EFI_NOT_FOUND;
  680. }
  681. PciIo = &PciIoDevice->PciIo;
  682. //
  683. // Preserve the original value
  684. //
  685. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
  686. //
  687. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  688. //
  689. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  690. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &gAllOne);
  691. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &Value);
  692. //
  693. // Write back the original value
  694. //
  695. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT32)Offset, 1, &OriginalValue);
  696. //
  697. // Restore TPL to its original level
  698. //
  699. gBS->RestoreTPL (OldTpl);
  700. if (BarLengthValue != NULL) {
  701. *BarLengthValue = Value;
  702. }
  703. if (OriginalBarValue != NULL) {
  704. *OriginalBarValue = OriginalValue;
  705. }
  706. if (Value == 0) {
  707. return EFI_NOT_FOUND;
  708. } else {
  709. return EFI_SUCCESS;
  710. }
  711. }
  712. /**
  713. Check whether the bar is existed or not.
  714. @param PciIoDevice A pointer to the PCI_IO_DEVICE.
  715. @param Offset The offset.
  716. @param BarLengthValue The bar length value returned.
  717. @param OriginalBarValue The original bar value returned.
  718. @retval EFI_NOT_FOUND The bar doesn't exist.
  719. @retval EFI_SUCCESS The bar exist.
  720. **/
  721. EFI_STATUS
  722. BarExisted (
  723. IN PCI_IO_DEVICE *PciIoDevice,
  724. IN UINTN Offset,
  725. OUT UINT32 *BarLengthValue,
  726. OUT UINT32 *OriginalBarValue
  727. )
  728. {
  729. EFI_PCI_IO_PROTOCOL *PciIo;
  730. UINT32 OriginalValue;
  731. UINT32 Value;
  732. EFI_TPL OldTpl;
  733. PciIo = &PciIoDevice->PciIo;
  734. //
  735. // Preserve the original value
  736. //
  737. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &OriginalValue);
  738. //
  739. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  740. //
  741. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  742. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &gAllOne);
  743. PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &Value);
  744. //
  745. // Write back the original value
  746. //
  747. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8)Offset, 1, &OriginalValue);
  748. //
  749. // Restore TPL to its original level
  750. //
  751. gBS->RestoreTPL (OldTpl);
  752. if (BarLengthValue != NULL) {
  753. *BarLengthValue = Value;
  754. }
  755. if (OriginalBarValue != NULL) {
  756. *OriginalBarValue = OriginalValue;
  757. }
  758. if (Value == 0) {
  759. return EFI_NOT_FOUND;
  760. } else {
  761. return EFI_SUCCESS;
  762. }
  763. }
  764. /**
  765. Test whether the device can support given attributes.
  766. @param PciIoDevice Pci device instance.
  767. @param Command Input command register value, and
  768. returned supported register value.
  769. @param BridgeControl Input bridge control value for PPB or P2C, and
  770. returned supported bridge control value.
  771. @param OldCommand Returned and stored old command register offset.
  772. @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
  773. **/
  774. VOID
  775. PciTestSupportedAttribute (
  776. IN PCI_IO_DEVICE *PciIoDevice,
  777. IN OUT UINT16 *Command,
  778. IN OUT UINT16 *BridgeControl,
  779. OUT UINT16 *OldCommand,
  780. OUT UINT16 *OldBridgeControl
  781. )
  782. {
  783. EFI_TPL OldTpl;
  784. UINT16 CommandValue;
  785. //
  786. // Preserve the original value
  787. //
  788. PCI_READ_COMMAND_REGISTER (PciIoDevice, OldCommand);
  789. //
  790. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  791. //
  792. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  793. CommandValue = *Command | *OldCommand;
  794. PCI_SET_COMMAND_REGISTER (PciIoDevice, CommandValue);
  795. PCI_READ_COMMAND_REGISTER (PciIoDevice, &CommandValue);
  796. *Command = *Command & CommandValue;
  797. //
  798. // Write back the original value
  799. //
  800. PCI_SET_COMMAND_REGISTER (PciIoDevice, *OldCommand);
  801. //
  802. // Restore TPL to its original level
  803. //
  804. gBS->RestoreTPL (OldTpl);
  805. if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  806. //
  807. // Preserve the original value
  808. //
  809. PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, OldBridgeControl);
  810. //
  811. // Raise TPL to high level to disable timer interrupt while the BAR is probed
  812. //
  813. OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
  814. PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *BridgeControl);
  815. PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
  816. //
  817. // Write back the original value
  818. //
  819. PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice, *OldBridgeControl);
  820. //
  821. // Restore TPL to its original level
  822. //
  823. gBS->RestoreTPL (OldTpl);
  824. } else {
  825. *OldBridgeControl = 0;
  826. *BridgeControl = 0;
  827. }
  828. }
  829. /**
  830. Set the supported or current attributes of a PCI device.
  831. @param PciIoDevice Structure pointer for PCI device.
  832. @param Command Command register value.
  833. @param BridgeControl Bridge control value for PPB or P2C.
  834. @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
  835. **/
  836. VOID
  837. PciSetDeviceAttribute (
  838. IN PCI_IO_DEVICE *PciIoDevice,
  839. IN UINT16 Command,
  840. IN UINT16 BridgeControl,
  841. IN UINTN Option
  842. )
  843. {
  844. UINT64 Attributes;
  845. Attributes = 0;
  846. if ((Command & EFI_PCI_COMMAND_IO_SPACE) != 0) {
  847. Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
  848. }
  849. if ((Command & EFI_PCI_COMMAND_MEMORY_SPACE) != 0) {
  850. Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
  851. }
  852. if ((Command & EFI_PCI_COMMAND_BUS_MASTER) != 0) {
  853. Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
  854. }
  855. if ((Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
  856. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
  857. }
  858. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) != 0) {
  859. Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
  860. }
  861. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) != 0) {
  862. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
  863. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  864. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
  865. }
  866. if ((BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) != 0) {
  867. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;
  868. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;
  869. }
  870. if (Option == EFI_SET_SUPPORTS) {
  871. Attributes |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
  872. EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
  873. EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
  874. EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
  875. EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
  876. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
  877. if (IS_PCI_LPC (&PciIoDevice->Pci)) {
  878. Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
  879. Attributes |= (mReserveIsaAliases ? (UINT64)EFI_PCI_IO_ATTRIBUTE_ISA_IO : \
  880. (UINT64)EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
  881. }
  882. if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  883. //
  884. // For bridge, it should support IDE attributes
  885. //
  886. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
  887. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
  888. if (mReserveVgaAliases) {
  889. Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 | \
  890. EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16);
  891. } else {
  892. Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | \
  893. EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
  894. }
  895. } else {
  896. if (IS_PCI_IDE (&PciIoDevice->Pci)) {
  897. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
  898. Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
  899. }
  900. if (IS_PCI_VGA (&PciIoDevice->Pci)) {
  901. Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
  902. Attributes |= (mReserveVgaAliases ? (UINT64)EFI_PCI_IO_ATTRIBUTE_VGA_IO : \
  903. (UINT64)EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
  904. }
  905. }
  906. PciIoDevice->Supports = Attributes;
  907. PciIoDevice->Supports &= ((PciIoDevice->Parent->Supports) | \
  908. EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
  909. EFI_PCI_IO_ATTRIBUTE_BUS_MASTER);
  910. } else {
  911. //
  912. // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
  913. // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
  914. // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
  915. // fields is not from the the ROM BAR of the PCI controller.
  916. //
  917. if (!PciIoDevice->EmbeddedRom) {
  918. Attributes |= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM;
  919. }
  920. PciIoDevice->Attributes = Attributes;
  921. }
  922. }
  923. /**
  924. Determine if the device can support Fast Back to Back attribute.
  925. @param PciIoDevice Pci device instance.
  926. @param StatusIndex Status register value.
  927. @retval EFI_SUCCESS This device support Fast Back to Back attribute.
  928. @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
  929. **/
  930. EFI_STATUS
  931. GetFastBackToBackSupport (
  932. IN PCI_IO_DEVICE *PciIoDevice,
  933. IN UINT8 StatusIndex
  934. )
  935. {
  936. EFI_PCI_IO_PROTOCOL *PciIo;
  937. EFI_STATUS Status;
  938. UINT32 StatusRegister;
  939. //
  940. // Read the status register
  941. //
  942. PciIo = &PciIoDevice->PciIo;
  943. Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
  944. if (EFI_ERROR (Status)) {
  945. return EFI_UNSUPPORTED;
  946. }
  947. //
  948. // Check the Fast B2B bit
  949. //
  950. if ((StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) != 0) {
  951. return EFI_SUCCESS;
  952. } else {
  953. return EFI_UNSUPPORTED;
  954. }
  955. }
  956. /**
  957. Process the option ROM for all the children of the specified parent PCI device.
  958. It can only be used after the first full Option ROM process.
  959. @param PciIoDevice Pci device instance.
  960. **/
  961. VOID
  962. ProcessOptionRomLight (
  963. IN PCI_IO_DEVICE *PciIoDevice
  964. )
  965. {
  966. PCI_IO_DEVICE *Temp;
  967. LIST_ENTRY *CurrentLink;
  968. //
  969. // For RootBridge, PPB , P2C, go recursively to traverse all its children
  970. //
  971. CurrentLink = PciIoDevice->ChildList.ForwardLink;
  972. while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
  973. Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
  974. if (!IsListEmpty (&Temp->ChildList)) {
  975. ProcessOptionRomLight (Temp);
  976. }
  977. Temp->AllOpRomProcessed = PciRomGetImageMapping (Temp);
  978. CurrentLink = CurrentLink->ForwardLink;
  979. }
  980. }
  981. /**
  982. Determine the related attributes of all devices under a Root Bridge.
  983. @param PciIoDevice PCI device instance.
  984. **/
  985. EFI_STATUS
  986. DetermineDeviceAttribute (
  987. IN PCI_IO_DEVICE *PciIoDevice
  988. )
  989. {
  990. UINT16 Command;
  991. UINT16 BridgeControl;
  992. UINT16 OldCommand;
  993. UINT16 OldBridgeControl;
  994. BOOLEAN FastB2BSupport;
  995. PCI_IO_DEVICE *Temp;
  996. LIST_ENTRY *CurrentLink;
  997. EFI_STATUS Status;
  998. //
  999. // For Root Bridge, just copy it by RootBridgeIo protocol
  1000. // so as to keep consistent with the actual attribute
  1001. //
  1002. if (PciIoDevice->Parent == NULL) {
  1003. Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
  1004. PciIoDevice->PciRootBridgeIo,
  1005. &PciIoDevice->Supports,
  1006. &PciIoDevice->Attributes
  1007. );
  1008. if (EFI_ERROR (Status)) {
  1009. return Status;
  1010. }
  1011. //
  1012. // Assume the PCI Root Bridge supports DAC
  1013. //
  1014. PciIoDevice->Supports |= (UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
  1015. EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
  1016. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
  1017. } else {
  1018. //
  1019. // Set the attributes to be checked for common PCI devices and PPB or P2C
  1020. // Since some devices only support part of them, it is better to set the
  1021. // attribute according to its command or bridge control register
  1022. //
  1023. Command = EFI_PCI_COMMAND_IO_SPACE |
  1024. EFI_PCI_COMMAND_MEMORY_SPACE |
  1025. EFI_PCI_COMMAND_BUS_MASTER |
  1026. EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
  1027. BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;
  1028. //
  1029. // Test whether the device can support attributes above
  1030. //
  1031. PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
  1032. //
  1033. // Set the supported attributes for specified PCI device
  1034. //
  1035. PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
  1036. //
  1037. // Set the current attributes for specified PCI device
  1038. //
  1039. PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
  1040. //
  1041. // Enable other PCI supported attributes but not defined in PCI_IO_PROTOCOL
  1042. // For PCI Express devices, Memory Write and Invalidate is hardwired to 0b so only enable it for PCI devices.
  1043. if (!PciIoDevice->IsPciExp) {
  1044. PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
  1045. }
  1046. }
  1047. FastB2BSupport = TRUE;
  1048. //
  1049. // P2C can not support FB2B on the secondary side
  1050. //
  1051. if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  1052. FastB2BSupport = FALSE;
  1053. }
  1054. //
  1055. // For RootBridge, PPB , P2C, go recursively to traverse all its children
  1056. //
  1057. CurrentLink = PciIoDevice->ChildList.ForwardLink;
  1058. while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
  1059. Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
  1060. Status = DetermineDeviceAttribute (Temp);
  1061. if (EFI_ERROR (Status)) {
  1062. return Status;
  1063. }
  1064. //
  1065. // Detect Fast Back to Back support for the device under the bridge
  1066. //
  1067. Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
  1068. if (FastB2BSupport && EFI_ERROR (Status)) {
  1069. FastB2BSupport = FALSE;
  1070. }
  1071. CurrentLink = CurrentLink->ForwardLink;
  1072. }
  1073. //
  1074. // Set or clear Fast Back to Back bit for the whole bridge
  1075. //
  1076. if (!IsListEmpty (&PciIoDevice->ChildList)) {
  1077. if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
  1078. Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
  1079. if (EFI_ERROR (Status) || (!FastB2BSupport)) {
  1080. FastB2BSupport = FALSE;
  1081. PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
  1082. } else {
  1083. PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
  1084. }
  1085. }
  1086. CurrentLink = PciIoDevice->ChildList.ForwardLink;
  1087. while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {
  1088. Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
  1089. if (FastB2BSupport) {
  1090. PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
  1091. } else {
  1092. PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
  1093. }
  1094. CurrentLink = CurrentLink->ForwardLink;
  1095. }
  1096. }
  1097. //
  1098. // End for IsListEmpty
  1099. //
  1100. return EFI_SUCCESS;
  1101. }
  1102. /**
  1103. This routine is used to update the bar information for those incompatible PCI device.
  1104. @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
  1105. Bar information.
  1106. @param IgnoreOptionRom Output If the option rom of incompatible device need to be ignored.
  1107. @retval EFI_SUCCESS Successfully updated bar information.
  1108. @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
  1109. **/
  1110. EFI_STATUS
  1111. UpdatePciInfo (
  1112. IN OUT PCI_IO_DEVICE *PciIoDevice,
  1113. OUT BOOLEAN *IgnoreOptionRom
  1114. )
  1115. {
  1116. EFI_STATUS Status;
  1117. UINTN BarIndex;
  1118. BOOLEAN SetFlag;
  1119. VOID *Configuration;
  1120. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
  1121. Configuration = NULL;
  1122. Status = EFI_SUCCESS;
  1123. if (gIncompatiblePciDeviceSupport == NULL) {
  1124. //
  1125. // It can only be supported after the Incompatible PCI Device
  1126. // Support Protocol has been installed
  1127. //
  1128. Status = gBS->LocateProtocol (
  1129. &gEfiIncompatiblePciDeviceSupportProtocolGuid,
  1130. NULL,
  1131. (VOID **)&gIncompatiblePciDeviceSupport
  1132. );
  1133. }
  1134. if (Status == EFI_SUCCESS) {
  1135. //
  1136. // Check whether the device belongs to incompatible devices from protocol or not
  1137. // If it is , then get its special requirement in the ACPI table
  1138. //
  1139. Status = gIncompatiblePciDeviceSupport->CheckDevice (
  1140. gIncompatiblePciDeviceSupport,
  1141. PciIoDevice->Pci.Hdr.VendorId,
  1142. PciIoDevice->Pci.Hdr.DeviceId,
  1143. PciIoDevice->Pci.Hdr.RevisionID,
  1144. PciIoDevice->Pci.Device.SubsystemVendorID,
  1145. PciIoDevice->Pci.Device.SubsystemID,
  1146. &Configuration
  1147. );
  1148. }
  1149. if (EFI_ERROR (Status) || (Configuration == NULL)) {
  1150. return EFI_UNSUPPORTED;
  1151. }
  1152. //
  1153. // Update PCI device information from the ACPI table
  1154. //
  1155. Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
  1156. while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
  1157. if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
  1158. //
  1159. // The format is not support
  1160. //
  1161. break;
  1162. }
  1163. //
  1164. // According to "Table 20. ACPI 2.0 & 3.0 QWORD Address Space Descriptor Usage"
  1165. // in PI Spec 1.7, Type-specific flags can be set to 0 when Address Translation
  1166. // Offset == 6 to skip device option ROM (do not probe option rom BAR).
  1167. //
  1168. if (((Ptr->AddrTranslationOffset == PCI_MAX_BAR) && (Ptr->SpecificFlag == 0))) {
  1169. *IgnoreOptionRom = TRUE;
  1170. Ptr++;
  1171. continue;
  1172. }
  1173. for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
  1174. if ((Ptr->AddrTranslationOffset != MAX_UINT64) &&
  1175. (Ptr->AddrTranslationOffset != MAX_UINT8) &&
  1176. (Ptr->AddrTranslationOffset != BarIndex)
  1177. )
  1178. {
  1179. //
  1180. // Skip updating when AddrTranslationOffset is not MAX_UINT64 or MAX_UINT8 (wide match).
  1181. // Skip updating when current BarIndex doesn't equal to AddrTranslationOffset.
  1182. // Comparing against MAX_UINT8 is to keep backward compatibility.
  1183. //
  1184. continue;
  1185. }
  1186. SetFlag = FALSE;
  1187. switch (Ptr->ResType) {
  1188. case ACPI_ADDRESS_SPACE_TYPE_MEM:
  1189. //
  1190. // Make sure the bar is memory type
  1191. //
  1192. if (CheckBarType (PciIoDevice, (UINT8)BarIndex, PciBarTypeMem)) {
  1193. SetFlag = TRUE;
  1194. //
  1195. // Ignored if granularity is 0.
  1196. // Ignored if PCI BAR is I/O or 32-bit memory.
  1197. // If PCI BAR is 64-bit memory and granularity is 32, then
  1198. // the PCI BAR resource is allocated below 4GB.
  1199. // If PCI BAR is 64-bit memory and granularity is 64, then
  1200. // the PCI BAR resource is allocated above 4GB.
  1201. //
  1202. if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeMem64) {
  1203. switch (Ptr->AddrSpaceGranularity) {
  1204. case 32:
  1205. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
  1206. case 64:
  1207. PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
  1208. break;
  1209. default:
  1210. break;
  1211. }
  1212. }
  1213. if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypePMem64) {
  1214. switch (Ptr->AddrSpaceGranularity) {
  1215. case 32:
  1216. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
  1217. case 64:
  1218. PciIoDevice->PciBar[BarIndex].BarTypeFixed = TRUE;
  1219. break;
  1220. default:
  1221. break;
  1222. }
  1223. }
  1224. }
  1225. break;
  1226. case ACPI_ADDRESS_SPACE_TYPE_IO:
  1227. //
  1228. // Make sure the bar is IO type
  1229. //
  1230. if (CheckBarType (PciIoDevice, (UINT8)BarIndex, PciBarTypeIo)) {
  1231. SetFlag = TRUE;
  1232. }
  1233. break;
  1234. }
  1235. if (SetFlag) {
  1236. //
  1237. // Update the new alignment for the device
  1238. //
  1239. SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
  1240. //
  1241. // Update the new length for the device
  1242. //
  1243. if (Ptr->AddrLen != 0) {
  1244. PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
  1245. }
  1246. }
  1247. }
  1248. Ptr++;
  1249. }
  1250. FreePool (Configuration);
  1251. return EFI_SUCCESS;
  1252. }
  1253. /**
  1254. This routine will update the alignment with the new alignment.
  1255. Compare with OLD_ALIGN/EVEN_ALIGN/SQUAD_ALIGN/DQUAD_ALIGN is to keep
  1256. backward compatibility.
  1257. @param Alignment Input Old alignment. Output updated alignment.
  1258. @param NewAlignment New alignment.
  1259. **/
  1260. VOID
  1261. SetNewAlign (
  1262. IN OUT UINT64 *Alignment,
  1263. IN UINT64 NewAlignment
  1264. )
  1265. {
  1266. UINT64 OldAlignment;
  1267. UINTN ShiftBit;
  1268. //
  1269. // The new alignment is the same as the original,
  1270. // so skip it
  1271. //
  1272. if ((NewAlignment == 0) || (NewAlignment == OLD_ALIGN)) {
  1273. return;
  1274. }
  1275. //
  1276. // Check the validity of the parameter
  1277. //
  1278. if ((NewAlignment != EVEN_ALIGN) &&
  1279. (NewAlignment != SQUAD_ALIGN) &&
  1280. (NewAlignment != DQUAD_ALIGN))
  1281. {
  1282. *Alignment = NewAlignment;
  1283. return;
  1284. }
  1285. OldAlignment = (*Alignment) + 1;
  1286. ShiftBit = 0;
  1287. //
  1288. // Get the first non-zero hex value of the length
  1289. //
  1290. while ((OldAlignment & 0x0F) == 0x00) {
  1291. OldAlignment = RShiftU64 (OldAlignment, 4);
  1292. ShiftBit += 4;
  1293. }
  1294. //
  1295. // Adjust the alignment to even, quad or double quad boundary
  1296. //
  1297. if (NewAlignment == EVEN_ALIGN) {
  1298. if ((OldAlignment & 0x01) != 0) {
  1299. OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
  1300. }
  1301. } else if (NewAlignment == SQUAD_ALIGN) {
  1302. if ((OldAlignment & 0x03) != 0) {
  1303. OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
  1304. }
  1305. } else if (NewAlignment == DQUAD_ALIGN) {
  1306. if ((OldAlignment & 0x07) != 0) {
  1307. OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
  1308. }
  1309. }
  1310. //
  1311. // Update the old value
  1312. //
  1313. NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
  1314. *Alignment = NewAlignment;
  1315. return;
  1316. }
  1317. /**
  1318. Parse PCI IOV VF bar information and fill them into PCI device instance.
  1319. @param PciIoDevice Pci device instance.
  1320. @param Offset Bar offset.
  1321. @param BarIndex Bar index.
  1322. @return Next bar offset.
  1323. **/
  1324. UINTN
  1325. PciIovParseVfBar (
  1326. IN PCI_IO_DEVICE *PciIoDevice,
  1327. IN UINTN Offset,
  1328. IN UINTN BarIndex
  1329. )
  1330. {
  1331. UINT32 Value;
  1332. UINT32 OriginalValue;
  1333. UINT32 Mask;
  1334. EFI_STATUS Status;
  1335. //
  1336. // Ensure it is called properly
  1337. //
  1338. ASSERT (PciIoDevice->SrIovCapabilityOffset != 0);
  1339. if (PciIoDevice->SrIovCapabilityOffset == 0) {
  1340. return 0;
  1341. }
  1342. OriginalValue = 0;
  1343. Value = 0;
  1344. Status = VfBarExisted (
  1345. PciIoDevice,
  1346. Offset,
  1347. &Value,
  1348. &OriginalValue
  1349. );
  1350. if (EFI_ERROR (Status)) {
  1351. PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
  1352. PciIoDevice->VfPciBar[BarIndex].Length = 0;
  1353. PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
  1354. //
  1355. // Scan all the BARs anyway
  1356. //
  1357. PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16)Offset;
  1358. return Offset + 4;
  1359. }
  1360. PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16)Offset;
  1361. if ((Value & 0x01) != 0) {
  1362. //
  1363. // Device I/Os. Impossible
  1364. //
  1365. ASSERT (FALSE);
  1366. return Offset + 4;
  1367. } else {
  1368. Mask = 0xfffffff0;
  1369. PciIoDevice->VfPciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  1370. switch (Value & 0x07) {
  1371. //
  1372. // memory space; anywhere in 32 bit address space
  1373. //
  1374. case 0x00:
  1375. if ((Value & 0x08) != 0) {
  1376. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
  1377. } else {
  1378. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;
  1379. }
  1380. PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1381. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1382. //
  1383. // Adjust Length
  1384. //
  1385. PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
  1386. //
  1387. // Adjust Alignment
  1388. //
  1389. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1390. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1391. }
  1392. break;
  1393. //
  1394. // memory space; anywhere in 64 bit address space
  1395. //
  1396. case 0x04:
  1397. if ((Value & 0x08) != 0) {
  1398. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
  1399. } else {
  1400. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
  1401. }
  1402. //
  1403. // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
  1404. // is regarded as an extension for the first bar. As a result
  1405. // the sizing will be conducted on combined 64 bit value
  1406. // Here just store the masked first 32bit value for future size
  1407. // calculation
  1408. //
  1409. PciIoDevice->VfPciBar[BarIndex].Length = Value & Mask;
  1410. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1411. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1412. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1413. }
  1414. //
  1415. // Increment the offset to point to next DWORD
  1416. //
  1417. Offset += 4;
  1418. Status = VfBarExisted (
  1419. PciIoDevice,
  1420. Offset,
  1421. &Value,
  1422. &OriginalValue
  1423. );
  1424. if (EFI_ERROR (Status)) {
  1425. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
  1426. return Offset + 4;
  1427. }
  1428. //
  1429. // Fix the length to support some special 64 bit BAR
  1430. //
  1431. Value |= ((UINT32)-1 << HighBitSet32 (Value));
  1432. //
  1433. // Calculate the size of 64bit bar
  1434. //
  1435. PciIoDevice->VfPciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);
  1436. PciIoDevice->VfPciBar[BarIndex].Length = PciIoDevice->VfPciBar[BarIndex].Length | LShiftU64 ((UINT64)Value, 32);
  1437. PciIoDevice->VfPciBar[BarIndex].Length = (~(PciIoDevice->VfPciBar[BarIndex].Length)) + 1;
  1438. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1439. //
  1440. // Adjust Length
  1441. //
  1442. PciIoDevice->VfPciBar[BarIndex].Length = MultU64x32 (PciIoDevice->VfPciBar[BarIndex].Length, PciIoDevice->InitialVFs);
  1443. //
  1444. // Adjust Alignment
  1445. //
  1446. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1447. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1448. }
  1449. break;
  1450. //
  1451. // reserved
  1452. //
  1453. default:
  1454. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
  1455. PciIoDevice->VfPciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1456. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->VfPciBar[BarIndex].Length - 1;
  1457. if (PciIoDevice->VfPciBar[BarIndex].Alignment < PciIoDevice->SystemPageSize - 1) {
  1458. PciIoDevice->VfPciBar[BarIndex].Alignment = PciIoDevice->SystemPageSize - 1;
  1459. }
  1460. break;
  1461. }
  1462. }
  1463. //
  1464. // Check the length again so as to keep compatible with some special bars
  1465. //
  1466. if (PciIoDevice->VfPciBar[BarIndex].Length == 0) {
  1467. PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
  1468. PciIoDevice->VfPciBar[BarIndex].BaseAddress = 0;
  1469. PciIoDevice->VfPciBar[BarIndex].Alignment = 0;
  1470. }
  1471. //
  1472. // Increment number of bar
  1473. //
  1474. return Offset + 4;
  1475. }
  1476. /**
  1477. Parse PCI bar information and fill them into PCI device instance.
  1478. @param PciIoDevice Pci device instance.
  1479. @param Offset Bar offset.
  1480. @param BarIndex Bar index.
  1481. @return Next bar offset.
  1482. **/
  1483. UINTN
  1484. PciParseBar (
  1485. IN PCI_IO_DEVICE *PciIoDevice,
  1486. IN UINTN Offset,
  1487. IN UINTN BarIndex
  1488. )
  1489. {
  1490. UINT32 Value;
  1491. UINT32 OriginalValue;
  1492. UINT32 Mask;
  1493. EFI_STATUS Status;
  1494. OriginalValue = 0;
  1495. Value = 0;
  1496. Status = BarExisted (
  1497. PciIoDevice,
  1498. Offset,
  1499. &Value,
  1500. &OriginalValue
  1501. );
  1502. if (EFI_ERROR (Status)) {
  1503. PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
  1504. PciIoDevice->PciBar[BarIndex].Length = 0;
  1505. PciIoDevice->PciBar[BarIndex].Alignment = 0;
  1506. //
  1507. // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
  1508. //
  1509. PciIoDevice->PciBar[BarIndex].Offset = (UINT8)Offset;
  1510. return Offset + 4;
  1511. }
  1512. PciIoDevice->PciBar[BarIndex].BarTypeFixed = FALSE;
  1513. PciIoDevice->PciBar[BarIndex].Offset = (UINT8)Offset;
  1514. if ((Value & 0x01) != 0) {
  1515. //
  1516. // Device I/Os
  1517. //
  1518. Mask = 0xfffffffc;
  1519. if ((Value & 0xFFFF0000) != 0) {
  1520. //
  1521. // It is a IO32 bar
  1522. //
  1523. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
  1524. PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
  1525. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1526. } else {
  1527. //
  1528. // It is a IO16 bar
  1529. //
  1530. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
  1531. PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
  1532. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1533. }
  1534. //
  1535. // Workaround. Some platforms implement IO bar with 0 length
  1536. // Need to treat it as no-bar
  1537. //
  1538. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  1539. PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE)0;
  1540. }
  1541. PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  1542. } else {
  1543. Mask = 0xfffffff0;
  1544. PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
  1545. switch (Value & 0x07) {
  1546. //
  1547. // memory space; anywhere in 32 bit address space
  1548. //
  1549. case 0x00:
  1550. if ((Value & 0x08) != 0) {
  1551. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
  1552. } else {
  1553. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
  1554. }
  1555. PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1556. if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
  1557. //
  1558. // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
  1559. //
  1560. PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
  1561. } else {
  1562. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1563. }
  1564. break;
  1565. //
  1566. // memory space; anywhere in 64 bit address space
  1567. //
  1568. case 0x04:
  1569. if ((Value & 0x08) != 0) {
  1570. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
  1571. } else {
  1572. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
  1573. }
  1574. //
  1575. // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
  1576. // is regarded as an extension for the first bar. As a result
  1577. // the sizing will be conducted on combined 64 bit value
  1578. // Here just store the masked first 32bit value for future size
  1579. // calculation
  1580. //
  1581. PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
  1582. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1583. //
  1584. // Increment the offset to point to next DWORD
  1585. //
  1586. Offset += 4;
  1587. Status = BarExisted (
  1588. PciIoDevice,
  1589. Offset,
  1590. &Value,
  1591. &OriginalValue
  1592. );
  1593. if (EFI_ERROR (Status)) {
  1594. //
  1595. // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
  1596. //
  1597. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  1598. //
  1599. // some device implement MMIO bar with 0 length, need to treat it as no-bar
  1600. //
  1601. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  1602. return Offset + 4;
  1603. }
  1604. }
  1605. //
  1606. // Fix the length to support some special 64 bit BAR
  1607. //
  1608. if (Value == 0) {
  1609. DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
  1610. Value = (UINT32)-1;
  1611. } else {
  1612. Value |= ((UINT32)(-1) << HighBitSet32 (Value));
  1613. }
  1614. //
  1615. // Calculate the size of 64bit bar
  1616. //
  1617. PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64)OriginalValue, 32);
  1618. PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64)Value, 32);
  1619. PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
  1620. if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
  1621. //
  1622. // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
  1623. //
  1624. PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
  1625. } else {
  1626. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1627. }
  1628. break;
  1629. //
  1630. // reserved
  1631. //
  1632. default:
  1633. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  1634. PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
  1635. if (PciIoDevice->PciBar[BarIndex].Length < (SIZE_4KB)) {
  1636. //
  1637. // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
  1638. //
  1639. PciIoDevice->PciBar[BarIndex].Alignment = (SIZE_4KB - 1);
  1640. } else {
  1641. PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
  1642. }
  1643. break;
  1644. }
  1645. }
  1646. //
  1647. // Check the length again so as to keep compatible with some special bars
  1648. //
  1649. if (PciIoDevice->PciBar[BarIndex].Length == 0) {
  1650. PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
  1651. PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
  1652. PciIoDevice->PciBar[BarIndex].Alignment = 0;
  1653. }
  1654. //
  1655. // Increment number of bar
  1656. //
  1657. return Offset + 4;
  1658. }
  1659. /**
  1660. This routine is used to initialize the bar of a PCI device.
  1661. @param PciIoDevice Pci device instance.
  1662. @note It can be called typically when a device is going to be rejected.
  1663. **/
  1664. VOID
  1665. InitializePciDevice (
  1666. IN PCI_IO_DEVICE *PciIoDevice
  1667. )
  1668. {
  1669. EFI_PCI_IO_PROTOCOL *PciIo;
  1670. UINT8 Offset;
  1671. PciIo = &(PciIoDevice->PciIo);
  1672. //
  1673. // Put all the resource apertures
  1674. // Resource base is set to all ones so as to indicate its resource
  1675. // has not been allocated
  1676. //
  1677. for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
  1678. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
  1679. }
  1680. }
  1681. /**
  1682. This routine is used to initialize the bar of a PCI-PCI Bridge device.
  1683. @param PciIoDevice PCI-PCI bridge device instance.
  1684. **/
  1685. VOID
  1686. InitializePpb (
  1687. IN PCI_IO_DEVICE *PciIoDevice
  1688. )
  1689. {
  1690. EFI_PCI_IO_PROTOCOL *PciIo;
  1691. PciIo = &(PciIoDevice->PciIo);
  1692. //
  1693. // Put all the resource apertures including IO16
  1694. // Io32, pMem32, pMem64 to quiescent state
  1695. // Resource base all ones, Resource limit all zeros
  1696. //
  1697. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
  1698. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
  1699. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
  1700. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
  1701. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
  1702. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
  1703. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
  1704. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
  1705. //
  1706. // Don't support use io32 as for now
  1707. //
  1708. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
  1709. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
  1710. //
  1711. // Force Interrupt line to zero for cards that come up randomly
  1712. //
  1713. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
  1714. }
  1715. /**
  1716. This routine is used to initialize the bar of a PCI Card Bridge device.
  1717. @param PciIoDevice PCI Card bridge device.
  1718. **/
  1719. VOID
  1720. InitializeP2C (
  1721. IN PCI_IO_DEVICE *PciIoDevice
  1722. )
  1723. {
  1724. EFI_PCI_IO_PROTOCOL *PciIo;
  1725. PciIo = &(PciIoDevice->PciIo);
  1726. //
  1727. // Put all the resource apertures including IO16
  1728. // Io32, pMem32, pMem64 to quiescent state(
  1729. // Resource base all ones, Resource limit all zeros
  1730. //
  1731. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
  1732. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
  1733. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
  1734. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
  1735. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
  1736. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
  1737. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
  1738. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
  1739. //
  1740. // Force Interrupt line to zero for cards that come up randomly
  1741. //
  1742. PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
  1743. }
  1744. /**
  1745. Authenticate the PCI device by using DeviceSecurityProtocol.
  1746. @param PciIoDevice PCI device.
  1747. @retval EFI_SUCCESS The device passes the authentication.
  1748. @return not EFI_SUCCESS The device failes the authentication or
  1749. unexpected error happen during authentication.
  1750. **/
  1751. EFI_STATUS
  1752. AuthenticatePciDevice (
  1753. IN PCI_IO_DEVICE *PciIoDevice
  1754. )
  1755. {
  1756. EDKII_DEVICE_IDENTIFIER DeviceIdentifier;
  1757. EFI_STATUS Status;
  1758. if (mDeviceSecurityProtocol != NULL) {
  1759. //
  1760. // Prepare the parameter
  1761. //
  1762. DeviceIdentifier.Version = EDKII_DEVICE_IDENTIFIER_REVISION;
  1763. CopyGuid (&DeviceIdentifier.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid);
  1764. DeviceIdentifier.DeviceHandle = NULL;
  1765. Status = gBS->InstallMultipleProtocolInterfaces (
  1766. &DeviceIdentifier.DeviceHandle,
  1767. &gEfiDevicePathProtocolGuid,
  1768. PciIoDevice->DevicePath,
  1769. &gEdkiiDeviceIdentifierTypePciGuid,
  1770. &PciIoDevice->PciIo,
  1771. NULL
  1772. );
  1773. if (EFI_ERROR (Status)) {
  1774. return Status;
  1775. }
  1776. //
  1777. // Do DeviceAuthentication
  1778. //
  1779. Status = mDeviceSecurityProtocol->DeviceAuthenticate (mDeviceSecurityProtocol, &DeviceIdentifier);
  1780. //
  1781. // Always uninstall, because they are only for Authentication.
  1782. // No need to check return Status.
  1783. //
  1784. gBS->UninstallMultipleProtocolInterfaces (
  1785. DeviceIdentifier.DeviceHandle,
  1786. &gEfiDevicePathProtocolGuid,
  1787. PciIoDevice->DevicePath,
  1788. &gEdkiiDeviceIdentifierTypePciGuid,
  1789. &PciIoDevice->PciIo,
  1790. NULL
  1791. );
  1792. return Status;
  1793. }
  1794. //
  1795. // Device Security Protocol is not found, just return success
  1796. //
  1797. return EFI_SUCCESS;
  1798. }
  1799. /**
  1800. Checks if PCI device is Root Bridge.
  1801. @param PciIoDevice Instance of PCI device
  1802. @retval TRUE Device is Root Bridge
  1803. @retval FALSE Device is not Root Bridge
  1804. **/
  1805. BOOLEAN
  1806. IsRootBridge (
  1807. IN PCI_IO_DEVICE *PciIoDevice
  1808. )
  1809. {
  1810. if (PciIoDevice->Parent == NULL) {
  1811. return TRUE;
  1812. } else {
  1813. return FALSE;
  1814. }
  1815. }
  1816. /**
  1817. Create and initialize general PCI I/O device instance for
  1818. PCI device/bridge device/hotplug bridge device.
  1819. @param Bridge Parent bridge instance.
  1820. @param Pci Input Pci information block.
  1821. @param Bus Device Bus NO.
  1822. @param Device Device device NO.
  1823. @param Func Device func NO.
  1824. @return Instance of PCI device. NULL means no instance created.
  1825. **/
  1826. PCI_IO_DEVICE *
  1827. CreatePciIoDevice (
  1828. IN PCI_IO_DEVICE *Bridge,
  1829. IN PCI_TYPE00 *Pci,
  1830. IN UINT8 Bus,
  1831. IN UINT8 Device,
  1832. IN UINT8 Func
  1833. )
  1834. {
  1835. PCI_IO_DEVICE *PciIoDevice;
  1836. EFI_PCI_IO_PROTOCOL *PciIo;
  1837. EFI_STATUS Status;
  1838. PciIoDevice = AllocateZeroPool (sizeof (PCI_IO_DEVICE));
  1839. if (PciIoDevice == NULL) {
  1840. return NULL;
  1841. }
  1842. PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
  1843. PciIoDevice->Handle = NULL;
  1844. PciIoDevice->PciRootBridgeIo = Bridge->PciRootBridgeIo;
  1845. PciIoDevice->DevicePath = NULL;
  1846. PciIoDevice->BusNumber = Bus;
  1847. PciIoDevice->DeviceNumber = Device;
  1848. PciIoDevice->FunctionNumber = Func;
  1849. PciIoDevice->Decodes = 0;
  1850. if (gFullEnumeration) {
  1851. PciIoDevice->Allocated = FALSE;
  1852. } else {
  1853. PciIoDevice->Allocated = TRUE;
  1854. }
  1855. PciIoDevice->Registered = FALSE;
  1856. PciIoDevice->Attributes = 0;
  1857. PciIoDevice->Supports = 0;
  1858. PciIoDevice->BusOverride = FALSE;
  1859. PciIoDevice->AllOpRomProcessed = FALSE;
  1860. PciIoDevice->IsPciExp = FALSE;
  1861. CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
  1862. //
  1863. // Initialize the PCI I/O instance structure
  1864. //
  1865. InitializePciIoInstance (PciIoDevice);
  1866. InitializePciDriverOverrideInstance (PciIoDevice);
  1867. InitializePciLoadFile2 (PciIoDevice);
  1868. PciIo = &PciIoDevice->PciIo;
  1869. //
  1870. // Create a device path for this PCI device and store it into its private data
  1871. //
  1872. CreatePciDevicePath (
  1873. Bridge->DevicePath,
  1874. PciIoDevice
  1875. );
  1876. //
  1877. // Detect if PCI Express Device
  1878. //
  1879. PciIoDevice->PciExpressCapabilityOffset = 0;
  1880. Status = LocateCapabilityRegBlock (
  1881. PciIoDevice,
  1882. EFI_PCI_CAPABILITY_ID_PCIEXP,
  1883. &PciIoDevice->PciExpressCapabilityOffset,
  1884. NULL
  1885. );
  1886. if (!EFI_ERROR (Status)) {
  1887. PciIoDevice->IsPciExp = TRUE;
  1888. }
  1889. //
  1890. // Now we can do the authentication check for the device.
  1891. //
  1892. Status = AuthenticatePciDevice (PciIoDevice);
  1893. //
  1894. // If authentication fails, skip this device.
  1895. //
  1896. if (EFI_ERROR (Status)) {
  1897. if (PciIoDevice->DevicePath != NULL) {
  1898. FreePool (PciIoDevice->DevicePath);
  1899. }
  1900. FreePool (PciIoDevice);
  1901. return NULL;
  1902. }
  1903. //
  1904. // Check if device's parent is not Root Bridge
  1905. //
  1906. if (PcdGetBool (PcdAriSupport) && !IsRootBridge (Bridge)) {
  1907. //
  1908. // Check if the device is an ARI device.
  1909. //
  1910. Status = LocatePciExpressCapabilityRegBlock (
  1911. PciIoDevice,
  1912. EFI_PCIE_CAPABILITY_ID_ARI,
  1913. &PciIoDevice->AriCapabilityOffset,
  1914. NULL
  1915. );
  1916. if (!EFI_ERROR (Status)) {
  1917. //
  1918. // We need to enable ARI feature before calculate BusReservation,
  1919. // because FirstVFOffset and VFStride may change after that.
  1920. //
  1921. EFI_PCI_IO_PROTOCOL *ParentPciIo;
  1922. UINT32 Data32;
  1923. //
  1924. // Check if its parent supports ARI forwarding.
  1925. //
  1926. ParentPciIo = &Bridge->PciIo;
  1927. ParentPciIo->Pci.Read (
  1928. ParentPciIo,
  1929. EfiPciIoWidthUint32,
  1930. Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
  1931. 1,
  1932. &Data32
  1933. );
  1934. if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
  1935. //
  1936. // ARI forward support in bridge, so enable it.
  1937. //
  1938. ParentPciIo->Pci.Read (
  1939. ParentPciIo,
  1940. EfiPciIoWidthUint32,
  1941. Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
  1942. 1,
  1943. &Data32
  1944. );
  1945. if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
  1946. Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
  1947. ParentPciIo->Pci.Write (
  1948. ParentPciIo,
  1949. EfiPciIoWidthUint32,
  1950. Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
  1951. 1,
  1952. &Data32
  1953. );
  1954. DEBUG ((
  1955. DEBUG_INFO,
  1956. " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
  1957. Bridge->BusNumber,
  1958. Bridge->DeviceNumber,
  1959. Bridge->FunctionNumber
  1960. ));
  1961. }
  1962. }
  1963. DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
  1964. }
  1965. }
  1966. //
  1967. // Initialization for SR-IOV
  1968. //
  1969. if (PcdGetBool (PcdSrIovSupport)) {
  1970. Status = LocatePciExpressCapabilityRegBlock (
  1971. PciIoDevice,
  1972. EFI_PCIE_CAPABILITY_ID_SRIOV,
  1973. &PciIoDevice->SrIovCapabilityOffset,
  1974. NULL
  1975. );
  1976. if (!EFI_ERROR (Status)) {
  1977. UINT32 SupportedPageSize;
  1978. UINT16 VFStride;
  1979. UINT16 FirstVFOffset;
  1980. UINT16 Data16;
  1981. UINT32 PFRid;
  1982. UINT32 LastVF;
  1983. //
  1984. // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
  1985. //
  1986. if (PcdGetBool (PcdAriSupport) && (PciIoDevice->AriCapabilityOffset != 0)) {
  1987. PciIo->Pci.Read (
  1988. PciIo,
  1989. EfiPciIoWidthUint16,
  1990. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
  1991. 1,
  1992. &Data16
  1993. );
  1994. Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
  1995. PciIo->Pci.Write (
  1996. PciIo,
  1997. EfiPciIoWidthUint16,
  1998. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
  1999. 1,
  2000. &Data16
  2001. );
  2002. }
  2003. //
  2004. // Calculate SystemPageSize
  2005. //
  2006. PciIo->Pci.Read (
  2007. PciIo,
  2008. EfiPciIoWidthUint32,
  2009. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
  2010. 1,
  2011. &SupportedPageSize
  2012. );
  2013. PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & SupportedPageSize);
  2014. ASSERT (PciIoDevice->SystemPageSize != 0);
  2015. PciIo->Pci.Write (
  2016. PciIo,
  2017. EfiPciIoWidthUint32,
  2018. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
  2019. 1,
  2020. &PciIoDevice->SystemPageSize
  2021. );
  2022. //
  2023. // Adjust SystemPageSize for Alignment usage later
  2024. //
  2025. PciIoDevice->SystemPageSize <<= 12;
  2026. //
  2027. // Calculate BusReservation for PCI IOV
  2028. //
  2029. //
  2030. // Read First FirstVFOffset, InitialVFs, and VFStride
  2031. //
  2032. PciIo->Pci.Read (
  2033. PciIo,
  2034. EfiPciIoWidthUint16,
  2035. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
  2036. 1,
  2037. &FirstVFOffset
  2038. );
  2039. PciIo->Pci.Read (
  2040. PciIo,
  2041. EfiPciIoWidthUint16,
  2042. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
  2043. 1,
  2044. &PciIoDevice->InitialVFs
  2045. );
  2046. PciIo->Pci.Read (
  2047. PciIo,
  2048. EfiPciIoWidthUint16,
  2049. PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
  2050. 1,
  2051. &VFStride
  2052. );
  2053. //
  2054. // Calculate LastVF
  2055. //
  2056. if (PciIoDevice->InitialVFs == 0) {
  2057. PciIoDevice->ReservedBusNum = 0;
  2058. } else {
  2059. PFRid = EFI_PCI_RID (Bus, Device, Func);
  2060. LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
  2061. //
  2062. // Calculate ReservedBusNum for this PF
  2063. //
  2064. PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
  2065. }
  2066. DEBUG ((
  2067. DEBUG_INFO,
  2068. " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
  2069. SupportedPageSize,
  2070. PciIoDevice->SystemPageSize >> 12,
  2071. FirstVFOffset
  2072. ));
  2073. DEBUG ((
  2074. DEBUG_INFO,
  2075. " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
  2076. PciIoDevice->InitialVFs,
  2077. PciIoDevice->ReservedBusNum,
  2078. PciIoDevice->SrIovCapabilityOffset
  2079. ));
  2080. }
  2081. }
  2082. if (PcdGetBool (PcdMrIovSupport)) {
  2083. Status = LocatePciExpressCapabilityRegBlock (
  2084. PciIoDevice,
  2085. EFI_PCIE_CAPABILITY_ID_MRIOV,
  2086. &PciIoDevice->MrIovCapabilityOffset,
  2087. NULL
  2088. );
  2089. if (!EFI_ERROR (Status)) {
  2090. DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
  2091. }
  2092. }
  2093. PciIoDevice->ResizableBarOffset = 0;
  2094. if (PcdGetBool (PcdPcieResizableBarSupport)) {
  2095. Status = LocatePciExpressCapabilityRegBlock (
  2096. PciIoDevice,
  2097. PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
  2098. &PciIoDevice->ResizableBarOffset,
  2099. NULL
  2100. );
  2101. if (!EFI_ERROR (Status)) {
  2102. PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
  2103. UINT32 Offset;
  2104. Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
  2105. + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY),
  2106. PciIo->Pci.Read (
  2107. PciIo,
  2108. EfiPciIoWidthUint8,
  2109. Offset,
  2110. sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
  2111. &ResizableBarControl
  2112. );
  2113. PciIoDevice->ResizableBarNumber = ResizableBarControl.Bits.ResizableBarNumber;
  2114. PciProgramResizableBar (PciIoDevice, PciResizableBarMax);
  2115. }
  2116. }
  2117. //
  2118. // Initialize the reserved resource list
  2119. //
  2120. InitializeListHead (&PciIoDevice->ReservedResourceList);
  2121. //
  2122. // Initialize the driver list
  2123. //
  2124. InitializeListHead (&PciIoDevice->OptionRomDriverList);
  2125. //
  2126. // Initialize the child list
  2127. //
  2128. InitializeListHead (&PciIoDevice->ChildList);
  2129. return PciIoDevice;
  2130. }
  2131. /**
  2132. This routine is used to enumerate entire pci bus system
  2133. in a given platform.
  2134. It is only called on the second start on the same Root Bridge.
  2135. @param Controller Parent bridge handler.
  2136. @retval EFI_SUCCESS PCI enumeration finished successfully.
  2137. @retval other Some error occurred when enumerating the pci bus system.
  2138. **/
  2139. EFI_STATUS
  2140. PciEnumeratorLight (
  2141. IN EFI_HANDLE Controller
  2142. )
  2143. {
  2144. EFI_STATUS Status;
  2145. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  2146. PCI_IO_DEVICE *RootBridgeDev;
  2147. UINT16 MinBus;
  2148. UINT16 MaxBus;
  2149. EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
  2150. MinBus = 0;
  2151. MaxBus = PCI_MAX_BUS;
  2152. Descriptors = NULL;
  2153. //
  2154. // If this root bridge has been already enumerated, then return successfully
  2155. //
  2156. if (GetRootBridgeByHandle (Controller) != NULL) {
  2157. return EFI_SUCCESS;
  2158. }
  2159. //
  2160. // Open pci root bridge io protocol
  2161. //
  2162. Status = gBS->OpenProtocol (
  2163. Controller,
  2164. &gEfiPciRootBridgeIoProtocolGuid,
  2165. (VOID **)&PciRootBridgeIo,
  2166. gPciBusDriverBinding.DriverBindingHandle,
  2167. Controller,
  2168. EFI_OPEN_PROTOCOL_BY_DRIVER
  2169. );
  2170. if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
  2171. return Status;
  2172. }
  2173. Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **)&Descriptors);
  2174. if (EFI_ERROR (Status)) {
  2175. return Status;
  2176. }
  2177. while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
  2178. //
  2179. // Create a device node for root bridge device with a NULL host bridge controller handle
  2180. //
  2181. RootBridgeDev = CreateRootBridge (Controller);
  2182. if (RootBridgeDev == NULL) {
  2183. Descriptors++;
  2184. continue;
  2185. }
  2186. //
  2187. // Record the root bridge-io protocol
  2188. //
  2189. RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
  2190. Status = PciPciDeviceInfoCollector (
  2191. RootBridgeDev,
  2192. (UINT8)MinBus
  2193. );
  2194. if (!EFI_ERROR (Status)) {
  2195. //
  2196. // Remove those PCI devices which are rejected when full enumeration
  2197. //
  2198. RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
  2199. //
  2200. // Process option rom light
  2201. //
  2202. ProcessOptionRomLight (RootBridgeDev);
  2203. //
  2204. // Determine attributes for all devices under this root bridge
  2205. //
  2206. DetermineDeviceAttribute (RootBridgeDev);
  2207. //
  2208. // If successfully, insert the node into device pool
  2209. //
  2210. InsertRootBridge (RootBridgeDev);
  2211. } else {
  2212. //
  2213. // If unsuccessfully, destroy the entire node
  2214. //
  2215. DestroyRootBridge (RootBridgeDev);
  2216. }
  2217. Descriptors++;
  2218. }
  2219. return EFI_SUCCESS;
  2220. }
  2221. /**
  2222. Get bus range from PCI resource descriptor list.
  2223. @param Descriptors A pointer to the address space descriptor.
  2224. @param MinBus The min bus returned.
  2225. @param MaxBus The max bus returned.
  2226. @param BusRange The bus range returned.
  2227. @retval EFI_SUCCESS Successfully got bus range.
  2228. @retval EFI_NOT_FOUND Can not find the specific bus.
  2229. **/
  2230. EFI_STATUS
  2231. PciGetBusRange (
  2232. IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
  2233. OUT UINT16 *MinBus,
  2234. OUT UINT16 *MaxBus,
  2235. OUT UINT16 *BusRange
  2236. )
  2237. {
  2238. while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
  2239. if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
  2240. if (MinBus != NULL) {
  2241. *MinBus = (UINT16)(*Descriptors)->AddrRangeMin;
  2242. }
  2243. if (MaxBus != NULL) {
  2244. *MaxBus = (UINT16)(*Descriptors)->AddrRangeMax;
  2245. }
  2246. if (BusRange != NULL) {
  2247. *BusRange = (UINT16)(*Descriptors)->AddrLen;
  2248. }
  2249. return EFI_SUCCESS;
  2250. }
  2251. (*Descriptors)++;
  2252. }
  2253. return EFI_NOT_FOUND;
  2254. }
  2255. /**
  2256. This routine can be used to start the root bridge.
  2257. @param RootBridgeDev Pci device instance.
  2258. @retval EFI_SUCCESS This device started.
  2259. @retval other Failed to get PCI Root Bridge I/O protocol.
  2260. **/
  2261. EFI_STATUS
  2262. StartManagingRootBridge (
  2263. IN PCI_IO_DEVICE *RootBridgeDev
  2264. )
  2265. {
  2266. EFI_HANDLE RootBridgeHandle;
  2267. EFI_STATUS Status;
  2268. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  2269. //
  2270. // Get the root bridge handle
  2271. //
  2272. RootBridgeHandle = RootBridgeDev->Handle;
  2273. PciRootBridgeIo = NULL;
  2274. //
  2275. // Get the pci root bridge io protocol
  2276. //
  2277. Status = gBS->OpenProtocol (
  2278. RootBridgeHandle,
  2279. &gEfiPciRootBridgeIoProtocolGuid,
  2280. (VOID **)&PciRootBridgeIo,
  2281. gPciBusDriverBinding.DriverBindingHandle,
  2282. RootBridgeHandle,
  2283. EFI_OPEN_PROTOCOL_BY_DRIVER
  2284. );
  2285. if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
  2286. return Status;
  2287. }
  2288. //
  2289. // Store the PciRootBridgeIo protocol into root bridge private data
  2290. //
  2291. RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
  2292. return EFI_SUCCESS;
  2293. }
  2294. /**
  2295. This routine can be used to check whether a PCI device should be rejected when light enumeration.
  2296. @param PciIoDevice Pci device instance.
  2297. @retval TRUE This device should be rejected.
  2298. @retval FALSE This device shouldn't be rejected.
  2299. **/
  2300. BOOLEAN
  2301. IsPciDeviceRejected (
  2302. IN PCI_IO_DEVICE *PciIoDevice
  2303. )
  2304. {
  2305. EFI_STATUS Status;
  2306. UINT32 TestValue;
  2307. UINT32 OldValue;
  2308. UINT32 Mask;
  2309. UINT8 BarOffset;
  2310. //
  2311. // PPB should be skip!
  2312. //
  2313. if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
  2314. return FALSE;
  2315. }
  2316. if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
  2317. //
  2318. // Only test base registers for P2C
  2319. //
  2320. for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
  2321. Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
  2322. Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
  2323. if (EFI_ERROR (Status)) {
  2324. continue;
  2325. }
  2326. TestValue = TestValue & Mask;
  2327. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2328. //
  2329. // The bar isn't programed, so it should be rejected
  2330. //
  2331. return TRUE;
  2332. }
  2333. }
  2334. return FALSE;
  2335. }
  2336. for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
  2337. //
  2338. // Test PCI devices
  2339. //
  2340. Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
  2341. if (EFI_ERROR (Status)) {
  2342. continue;
  2343. }
  2344. if ((TestValue & 0x01) != 0) {
  2345. //
  2346. // IO Bar
  2347. //
  2348. Mask = 0xFFFFFFFC;
  2349. TestValue = TestValue & Mask;
  2350. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2351. return TRUE;
  2352. }
  2353. } else {
  2354. //
  2355. // Mem Bar
  2356. //
  2357. Mask = 0xFFFFFFF0;
  2358. TestValue = TestValue & Mask;
  2359. if ((TestValue & 0x07) == 0x04) {
  2360. //
  2361. // Mem64 or PMem64
  2362. //
  2363. BarOffset += sizeof (UINT32);
  2364. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2365. //
  2366. // Test its high 32-Bit BAR
  2367. //
  2368. Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
  2369. if (TestValue == OldValue) {
  2370. return TRUE;
  2371. }
  2372. }
  2373. } else {
  2374. //
  2375. // Mem32 or PMem32
  2376. //
  2377. if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
  2378. return TRUE;
  2379. }
  2380. }
  2381. }
  2382. }
  2383. return FALSE;
  2384. }
  2385. /**
  2386. Reset all bus number from specific bridge.
  2387. @param Bridge Parent specific bridge.
  2388. @param StartBusNumber Start bus number.
  2389. **/
  2390. VOID
  2391. ResetAllPpbBusNumber (
  2392. IN PCI_IO_DEVICE *Bridge,
  2393. IN UINT8 StartBusNumber
  2394. )
  2395. {
  2396. EFI_STATUS Status;
  2397. PCI_TYPE00 Pci;
  2398. UINT8 Device;
  2399. UINT32 Register;
  2400. UINT8 Func;
  2401. UINT64 Address;
  2402. UINT8 SecondaryBus;
  2403. EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
  2404. PciRootBridgeIo = Bridge->PciRootBridgeIo;
  2405. for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
  2406. for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
  2407. //
  2408. // Check to see whether a pci device is present
  2409. //
  2410. Status = PciDevicePresent (
  2411. PciRootBridgeIo,
  2412. &Pci,
  2413. StartBusNumber,
  2414. Device,
  2415. Func
  2416. );
  2417. if (EFI_ERROR (Status) && (Func == 0)) {
  2418. //
  2419. // go to next device if there is no Function 0
  2420. //
  2421. break;
  2422. }
  2423. if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
  2424. Register = 0;
  2425. Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
  2426. Status = PciRootBridgeIo->Pci.Read (
  2427. PciRootBridgeIo,
  2428. EfiPciWidthUint32,
  2429. Address,
  2430. 1,
  2431. &Register
  2432. );
  2433. SecondaryBus = (UINT8)(Register >> 8);
  2434. if (SecondaryBus != 0) {
  2435. ResetAllPpbBusNumber (Bridge, SecondaryBus);
  2436. }
  2437. //
  2438. // Reset register 18h, 19h, 1Ah on PCI Bridge
  2439. //
  2440. Register &= 0xFF000000;
  2441. Status = PciRootBridgeIo->Pci.Write (
  2442. PciRootBridgeIo,
  2443. EfiPciWidthUint32,
  2444. Address,
  2445. 1,
  2446. &Register
  2447. );
  2448. }
  2449. if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
  2450. //
  2451. // Skip sub functions, this is not a multi function device
  2452. //
  2453. Func = PCI_MAX_FUNC;
  2454. }
  2455. }
  2456. }
  2457. }