TbtSmiHandler.c 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
  1. /**@file
  2. Thunderbolt SMI handler.
  3. Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "TbtSmiHandler.h"
  7. #include <Library/IoLib.h>
  8. #include <Library/BaseLib.h>
  9. #include <Library/DebugLib.h>
  10. #include <Protocol/SmmVariable.h>
  11. #include <Library/BaseMemoryLib.h>
  12. #include <Library/SmmServicesTableLib.h>
  13. #include <Library/PciSegmentLib.h>
  14. #define MEM_PER_SLOT (DEF_RES_MEM_PER_DEV << 4)
  15. #define PMEM_PER_SLOT (DEF_RES_PMEM_PER_DEV << 4)
  16. #define IO_PER_SLOT (DEF_RES_IO_PER_DEV << 2)
  17. GLOBAL_REMOVE_IF_UNREFERENCED UINTN gDeviceBaseAddress;
  18. //
  19. //US(X:0:0), DS(X+1:3:0),DS(X+1:4:0),DS(X+1:5:0),DS(X+1:6:0)
  20. //
  21. GLOBAL_REMOVE_IF_UNREFERENCED BRDG_CONFIG HrConfigs[MAX_CFG_PORTS];
  22. extern UINT8 gCurrentDiscreteTbtRootPort;
  23. extern UINT8 gCurrentDiscreteTbtRootPortType;
  24. BOOLEAN isLegacyDevice = FALSE;
  25. STATIC UINT8 TbtSegment = 0;
  26. STATIC
  27. VOID
  28. PortInfoInit (
  29. IN OUT PORT_INFO *PortInfo
  30. )
  31. {
  32. PortInfo->BusNumLimit = 4;
  33. }
  34. STATIC
  35. VOID
  36. UnsetVesc (
  37. IN UINT8 Bus,
  38. IN UINT8 Dev,
  39. IN UINT8 Fun
  40. )
  41. {
  42. UINT8 Dbus;
  43. UINT32 Data32;
  44. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  45. //
  46. // Check for abcence of DS bridge
  47. //
  48. if(0xFFFF == PciSegmentRead16(gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
  49. return;
  50. }
  51. //
  52. // Unset vesc_reg2[23] bit (to have an option to access below DS)
  53. //
  54. Data32 = PciSegmentRead32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2);
  55. Data32 &= 0xFF7FFFFF;
  56. PciSegmentWrite32(gDeviceBaseAddress + PCI_TBT_VESC_REG2, Data32);
  57. //
  58. // Go to Device behind DS
  59. //
  60. Dbus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  61. DEBUG((DEBUG_INFO, "Dbus = %d\n",Dbus));
  62. //
  63. // Check if there is something behind this Downstream Port (Up or Ep)
  64. // If there nothing behind Downstream Port Set vesc_reg2[23] bit -> this will flush all future MemWr
  65. //
  66. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Dbus, 0x00, 0x00, 0);
  67. if(0xFFFF == PciSegmentRead16(gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET))
  68. {
  69. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  70. Data32 = PciSegmentRead32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2);
  71. Data32 |= 0x00800000;
  72. PciSegmentWrite32 (gDeviceBaseAddress + PCI_TBT_VESC_REG2, Data32);
  73. }
  74. }// Unset_VESC_REG2
  75. STATIC
  76. UINT16
  77. MemPerSlot (
  78. IN UINT16 CurrentUsage
  79. )
  80. {
  81. if (CurrentUsage == 0) {
  82. return 0;
  83. }
  84. if (CurrentUsage <= 16) {
  85. return 16;
  86. }
  87. if (CurrentUsage <= 64) {
  88. return 64;
  89. }
  90. if (CurrentUsage <= 128) {
  91. return 128;
  92. }
  93. if (CurrentUsage <= 256) {
  94. return 256;
  95. }
  96. if (CurrentUsage <= 512) {
  97. return 512;
  98. }
  99. if (CurrentUsage <= 1024) {
  100. return 1024;
  101. }
  102. return CurrentUsage;
  103. } // MemPerSlot
  104. STATIC
  105. UINT64
  106. PMemPerSlot (
  107. IN UINT64 CurrentUsage
  108. )
  109. {
  110. if (CurrentUsage == 0) {
  111. return 0;
  112. }
  113. if (CurrentUsage <= 1024ULL) {
  114. return 1024ULL;
  115. }
  116. if (CurrentUsage <= 4096ULL) {
  117. return 4096ULL;
  118. }
  119. return CurrentUsage;
  120. } // PMemPerSlot
  121. STATIC
  122. VOID
  123. SetPhyPortResources (
  124. IN UINT8 Bus,
  125. IN UINT8 Dev,
  126. IN UINT8 SubBus,
  127. IN INT8 Depth,
  128. IN PORT_INFO *CurrentPi,
  129. IN OUT PORT_INFO *PortInfo
  130. )
  131. {
  132. UINT8 Cmd;
  133. UINT16 DeltaMem;
  134. UINT64 DeltaPMem;
  135. Cmd = CMD_BUS_MASTER;
  136. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, 0x00, 0);
  137. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, SubBus);
  138. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
  139. DeltaMem = PortInfo->MemBase - CurrentPi->MemBase;
  140. if (isLegacyDevice) {
  141. if (Depth >= 0 && (DeltaMem < MEM_PER_SLOT)) {
  142. PortInfo->MemBase += MEM_PER_SLOT - DeltaMem;
  143. }
  144. } else {
  145. if (DeltaMem < MemPerSlot (DeltaMem)) {
  146. PortInfo->MemBase += MemPerSlot (DeltaMem) - DeltaMem;
  147. }
  148. }
  149. if (PortInfo->MemBase > CurrentPi->MemBase && (PortInfo->MemBase - 0x10) <= PortInfo->MemLimit) {
  150. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), CurrentPi->MemBase);
  151. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), PortInfo->MemBase - 0x10);
  152. Cmd |= CMD_BM_MEM;
  153. } else {
  154. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20);
  155. PortInfo->MemBase = CurrentPi->MemBase;
  156. }
  157. DeltaPMem = PortInfo->PMemBase64 - CurrentPi->PMemBase64;
  158. if (isLegacyDevice) {
  159. if ((Depth >= 0) && ((UINTN)DeltaPMem < (UINTN)PMEM_PER_SLOT)) {
  160. PortInfo->PMemBase64 += PMEM_PER_SLOT - DeltaPMem;
  161. }
  162. } else {
  163. if (DeltaPMem < PMemPerSlot (DeltaPMem)) {
  164. PortInfo->PMemBase64 += PMemPerSlot (DeltaPMem) - DeltaPMem;
  165. }
  166. }
  167. if (PortInfo->PMemBase64 > CurrentPi->PMemBase64 && (PortInfo->PMemBase64 - 0x10) <= PortInfo->PMemLimit64) {
  168. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (CurrentPi->PMemBase64 & 0xFFFF));
  169. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) ((PortInfo->PMemBase64 - 0x10) & 0xFFFF));
  170. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (CurrentPi->PMemBase64 >> 16));
  171. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) ((PortInfo->PMemBase64 - 0x10) >> 16));
  172. Cmd |= CMD_BM_MEM;
  173. } else {
  174. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24);
  175. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0);
  176. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), 0);
  177. PortInfo->PMemBase64 = CurrentPi->PMemBase64;
  178. }
  179. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
  180. PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
  181. } // SetPhyPortResources
  182. STATIC
  183. UINT32
  184. SaveSetGetRestoreBar (
  185. IN UINTN Bar
  186. )
  187. {
  188. UINT32 BarReq;
  189. UINT32 OrigBar;
  190. OrigBar = PciSegmentRead32(Bar); // Save BAR
  191. PciSegmentWrite32(Bar, 0xFFFFFFFF); // Set BAR
  192. BarReq = PciSegmentRead32(Bar); // Get BAR
  193. PciSegmentWrite32(Bar, OrigBar); // Restore BAR
  194. return BarReq;
  195. } // SaveSetGetRestoreBar
  196. STATIC
  197. VOID
  198. SetIoBar (
  199. IN UINTN BAR,
  200. IN UINT32 BarReq,
  201. IN OUT UINT8 *Cmd,
  202. IN OUT IO_REGS *IoReg
  203. )
  204. {
  205. UINT16 Alignment;
  206. UINT16 Size;
  207. UINT16 NewBase;
  208. Alignment = ~(BarReq & 0xFFFC);
  209. Size = Alignment + 1;
  210. if (IoReg->Base > IoReg->Limit || !Size) {
  211. return ;
  212. }
  213. NewBase = BAR_ALIGN (IoReg->Base, Alignment);
  214. if (NewBase > IoReg->Limit || NewBase + Size - 1 > IoReg->Limit) {
  215. return ;
  216. }
  217. PciSegmentWrite16(BAR, NewBase);
  218. IoReg->Base = NewBase + Size; // Advance to new position
  219. *Cmd |= CMD_BM_IO; // Set Io Space Enable
  220. } // SetIoBar
  221. STATIC
  222. VOID
  223. SetMemBar (
  224. IN UINTN BAR,
  225. IN UINT32 BarReq,
  226. IN OUT UINT8 *Cmd,
  227. IN OUT MEM_REGS *MemReg
  228. )
  229. {
  230. UINT32 Alignment;
  231. UINT32 Size;
  232. UINT32 NewBase;
  233. Alignment = ~(BarReq & 0xFFFFFFF0);
  234. Size = Alignment + 1;
  235. if (MemReg->Base > MemReg->Limit || !Size) {
  236. return ;
  237. }
  238. NewBase = BAR_ALIGN (MemReg->Base, Alignment);
  239. if (NewBase > MemReg->Limit || NewBase + Size - 1 > MemReg->Limit) {
  240. return ;
  241. }
  242. PciSegmentWrite32(BAR, NewBase);
  243. MemReg->Base = NewBase + Size; // Advance to new position
  244. *Cmd |= CMD_BM_MEM; // Set Memory Space Enable
  245. } // SetMemBar
  246. STATIC
  247. VOID
  248. SetPMem64Bar (
  249. IN UINTN BAR,
  250. IN BOOLEAN IsMaxBar,
  251. IN UINT32 BarReq,
  252. IN OUT UINT8 *Cmd,
  253. IN OUT PMEM_REGS *MemReg
  254. )
  255. {
  256. UINT32 Alignment;
  257. UINT32 Size;
  258. UINT64 NewBase;
  259. Alignment = ~(BarReq & 0xFFFFFFF0);
  260. Size = Alignment + 1;
  261. if (MemReg->Base64 > MemReg->Limit64 || !Size) {
  262. return ;
  263. }
  264. NewBase = BAR_ALIGN (MemReg->Base64, Alignment);
  265. if (NewBase > MemReg->Limit64 || NewBase + Size - 1 > MemReg->Limit64) {
  266. return ;
  267. }
  268. PciSegmentWrite32(BAR, (UINT32)(NewBase & 0xFFFFFFFF));
  269. if (!IsMaxBar) {
  270. BAR++;
  271. PciSegmentWrite32(BAR, (UINT32)(NewBase >> 32));
  272. }
  273. MemReg->Base64 = NewBase + Size; // Advance to new position
  274. *Cmd |= CMD_BM_MEM; // Set Memory Space Enable
  275. } // SetPMem64Bar
  276. STATIC
  277. VOID
  278. SetDevResources (
  279. IN UINT8 Bus,
  280. IN UINT8 Dev,
  281. IN UINT8 MaxFun, // PCI_MAX_FUNC for devices, 1 for bridge
  282. IN UINT8 MaxBar, // PCI_BAR5 for devices, PCI_BAR1 for bridge
  283. IN OUT PORT_INFO *PortInfo
  284. )
  285. {
  286. UINT8 Fun;
  287. UINT8 Reg;
  288. UINT32 BarReq;
  289. IO_REGS Io;
  290. MEM_REGS Mem;
  291. PMEM_REGS PMem;
  292. UINT8 Cmd;
  293. Io.Base = PortInfo->IoBase << 8;
  294. Io.Limit = (PortInfo->IoLimit << 8) | 0xFF;
  295. Mem.Base = PortInfo->MemBase << 16;
  296. Mem.Limit = (PortInfo->MemLimit << 16) | 0xFFFF;
  297. PMem.Base64 = PortInfo->PMemBase64 << 16;
  298. PMem.Limit64 = (PortInfo->PMemLimit64 << 16) | 0xFFFF;
  299. for (Fun = 0; Fun < MaxFun; ++Fun) {
  300. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  301. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BUS_MASTER);
  302. Cmd = PciSegmentRead8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET);
  303. if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
  304. continue;
  305. }
  306. for (Reg = PCI_BASE_ADDRESSREG_OFFSET; Reg <= MaxBar; Reg += 4) {
  307. BarReq = SaveSetGetRestoreBar(gDeviceBaseAddress + Reg); // Perform BAR sizing
  308. if (BarReq & BIT0) {
  309. //
  310. // I/O BAR
  311. //
  312. SetIoBar (
  313. (gDeviceBaseAddress + Reg),
  314. BarReq,
  315. &Cmd,
  316. &Io
  317. );
  318. continue;
  319. }
  320. if (BarReq & BIT3) {
  321. //
  322. // P-Memory BAR
  323. //
  324. SetPMem64Bar ((gDeviceBaseAddress + Reg), MaxBar == Reg, BarReq, &Cmd, &PMem);
  325. } else {
  326. SetMemBar ((gDeviceBaseAddress + Reg), BarReq, &Cmd, &Mem);
  327. }
  328. if (BIT2 == (BarReq & (BIT2 | BIT1))) {
  329. //
  330. // Base address is 64 bits wide
  331. //
  332. Reg += 4;
  333. if (!(BarReq & BIT3)) {
  334. //
  335. // 64-bit memory bar
  336. //
  337. PciSegmentWrite32 (gDeviceBaseAddress + Reg, 0);
  338. }
  339. }
  340. }
  341. if (Cmd & BIT1) {
  342. //
  343. // If device uses I/O and MEM mapping use only MEM mepping
  344. //
  345. Cmd &= ~BIT0;
  346. }
  347. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
  348. PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
  349. }
  350. //
  351. // Update PortInfo if any changes
  352. //
  353. if (Io.Base > ((UINT32) PortInfo->IoBase << 8)) {
  354. PortInfo->IoBase = (UINT8) (BAR_ALIGN (Io.Base, 0xFFF) >> 8);
  355. }
  356. if (Mem.Base > ((UINT32) PortInfo->MemBase << 16)) {
  357. PortInfo->MemBase = (UINT16) (BAR_ALIGN (Mem.Base, 0xFFFFF) >> 16);
  358. }
  359. if (PMem.Base64 > (PortInfo->PMemBase64 << 16)) {
  360. PortInfo->PMemBase64 = (BAR_ALIGN (PMem.Base64, 0xFFFFF) >> 16);
  361. }
  362. } // SetDevResources
  363. STATIC
  364. VOID
  365. InitARHRConfigs(
  366. IN HR_CONFIG *Hr_Config,
  367. IN UINT8 BusNumLimit,
  368. IN OUT BRDG_RES_CONFIG* HrResConf
  369. )
  370. {
  371. UINT8 i,j;
  372. //
  373. // DS port for USB device
  374. //
  375. HrConfigs[AR_DS_PORT2].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
  376. HrConfigs[AR_DS_PORT2].DevId.Dev = 2;
  377. HrConfigs[AR_DS_PORT2].DevId.Fun = 0;
  378. HrConfigs[AR_DS_PORT2].PBus = HrConfigs[AR_DS_PORT2].DevId.Bus;
  379. HrConfigs[AR_DS_PORT2].SBus = HrConfigs[AR_DS_PORT2].PBus + 1;
  380. HrConfigs[AR_DS_PORT2].SubBus = HrConfigs[AR_DS_PORT2].PBus + 1;
  381. //
  382. // CIO port
  383. //
  384. HrConfigs[AR_DS_PORT1].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
  385. HrConfigs[AR_DS_PORT1].DevId.Dev = 1;
  386. HrConfigs[AR_DS_PORT1].DevId.Fun = 0;
  387. HrConfigs[AR_DS_PORT1].PBus = HrConfigs[AR_DS_PORT1].DevId.Bus;
  388. HrConfigs[AR_DS_PORT1].SBus = HrConfigs[HR_DS_PORT0].SubBus + 1;
  389. HrConfigs[AR_DS_PORT1].SubBus = BusNumLimit;
  390. switch(Hr_Config->DeviceId)
  391. {
  392. //
  393. // HR with 1 DS and 1 USB
  394. //
  395. case AR_HR_2C:
  396. case AR_HR_LP:
  397. case AR_HR_C0_2C:
  398. case TR_HR_2C:
  399. Hr_Config->MinDSNumber = HrConfigs[AR_DS_PORT1].DevId.Dev;
  400. Hr_Config->MaxDSNumber = HrConfigs[AR_DS_PORT2].DevId.Dev;
  401. Hr_Config->BridgeLoops = 4;
  402. break;
  403. //
  404. // HR with 2 DS and 1 USB
  405. //
  406. case AR_HR_4C:
  407. case TR_HR_4C:
  408. case AR_HR_C0_4C:
  409. Hr_Config->MinDSNumber = 1;
  410. Hr_Config->MaxDSNumber = 4;
  411. Hr_Config->BridgeLoops = 6;
  412. for(j = 2, i = Hr_Config->MinDSNumber; j < count(HrConfigs) && i <= Hr_Config->MaxDSNumber; ++j, ++i)
  413. {
  414. HrConfigs[j].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
  415. HrConfigs[j].DevId.Dev = i;
  416. HrConfigs[j].DevId.Fun = 0;
  417. HrConfigs[j].PBus = HrConfigs[j].DevId.Bus;
  418. HrConfigs[j].Res.Cls = DEF_CACHE_LINE_SIZE;
  419. }
  420. break;
  421. }
  422. }//InitARHRConfigs
  423. STATIC
  424. VOID
  425. InitCommonHRConfigs (
  426. IN HR_CONFIG *Hr_Config,
  427. IN UINT8 BusNumLimit,
  428. IN OUT BRDG_RES_CONFIG *HrResConf
  429. )
  430. {
  431. UINT8 i;
  432. UINT8 j;
  433. for(i = 0; i < count(HrConfigs); ++i) {
  434. HrConfigs[i].IsDSBridge = TRUE;
  435. }
  436. //
  437. // US(HRBus:0:0)
  438. //
  439. HrConfigs[HR_US_PORT].DevId.Bus = Hr_Config->HRBus;
  440. HrConfigs[HR_US_PORT].DevId.Dev = 0;
  441. HrConfigs[HR_US_PORT].DevId.Fun = 0;
  442. HrConfigs[HR_US_PORT].Res = *HrResConf;
  443. HrConfigs[HR_US_PORT].Res.IoBase = 0xF1;
  444. HrConfigs[HR_US_PORT].Res.IoLimit = 0x01;
  445. HrConfigs[HR_US_PORT].PBus = HrConfigs[HR_US_PORT].DevId.Bus;
  446. HrConfigs[HR_US_PORT].SBus = HrConfigs[HR_US_PORT].PBus + 1;
  447. HrConfigs[HR_US_PORT].SubBus = BusNumLimit;
  448. HrConfigs[HR_US_PORT].IsDSBridge = FALSE;
  449. //
  450. // HIA resides here
  451. //
  452. HrConfigs[HR_DS_PORT0].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
  453. HrConfigs[HR_DS_PORT0].DevId.Dev = 0;
  454. HrConfigs[HR_DS_PORT0].DevId.Fun = 0;
  455. HrConfigs[HR_DS_PORT0].Res = NOT_IN_USE_BRIDGE;
  456. HrConfigs[HR_DS_PORT0].Res.MemBase = HrResConf->MemLimit;
  457. HrConfigs[HR_DS_PORT0].Res.MemLimit = HrResConf->MemLimit;
  458. HrResConf->MemLimit -= 0x10; //This 1 MB chunk will be used by HIA
  459. HrConfigs[HR_DS_PORT0].Res.Cmd = CMD_BM_MEM;
  460. HrConfigs[HR_DS_PORT0].Res.Cls = DEF_CACHE_LINE_SIZE;
  461. HrConfigs[HR_DS_PORT0].PBus = HrConfigs[HR_DS_PORT0].DevId.Bus;
  462. HrConfigs[HR_DS_PORT0].SBus = HrConfigs[HR_DS_PORT0].PBus + 1;
  463. HrConfigs[HR_DS_PORT0].SubBus = HrConfigs[HR_DS_PORT0].PBus + 1;
  464. switch (Hr_Config->DeviceId) {
  465. //
  466. // Alpine Ridge
  467. //
  468. case AR_HR_2C:
  469. case AR_HR_C0_2C:
  470. case AR_HR_LP:
  471. case AR_HR_4C:
  472. case AR_HR_C0_4C:
  473. //
  474. // Titan Ridge
  475. //
  476. case TR_HR_2C:
  477. case TR_HR_4C:
  478. InitARHRConfigs(Hr_Config, BusNumLimit, HrResConf);
  479. break;
  480. default:
  481. //
  482. // DS(HRBus+2:3-6:0)
  483. //
  484. Hr_Config->MinDSNumber = 3;
  485. Hr_Config->MaxDSNumber = 6;
  486. Hr_Config->BridgeLoops = count (HrConfigs);
  487. for (j = 2, i = Hr_Config->MinDSNumber; j < count (HrConfigs) && i <= Hr_Config->MaxDSNumber; ++j, ++i) {
  488. HrConfigs[j].DevId.Bus = HrConfigs[HR_US_PORT].DevId.Bus + 1;
  489. HrConfigs[j].DevId.Dev = i;
  490. HrConfigs[j].DevId.Fun = 0;
  491. HrConfigs[j].PBus = HrConfigs[j].DevId.Bus;
  492. HrConfigs[j].Res.Cls = DEF_CACHE_LINE_SIZE;
  493. }
  494. }
  495. } // InitCommonHRConfigs
  496. STATIC
  497. VOID
  498. InitHRDSPort_Disable (
  499. IN UINT8 id,
  500. IN OUT BRDG_CONFIG *BrdgConf
  501. )
  502. {
  503. HrConfigs[id].Res = NOT_IN_USE_BRIDGE;
  504. HrConfigs[id].SBus = BrdgConf->SBus;
  505. HrConfigs[id].SubBus = BrdgConf->SBus;
  506. BrdgConf->SBus++;
  507. } // InitHRDSPort_Disable
  508. //AR only
  509. STATIC
  510. VOID
  511. InitARDSPort_1Port(
  512. IN OUT BRDG_CONFIG* BrdgConf
  513. )
  514. {
  515. UINT16 MemBase = BrdgConf->Res.MemBase & 0xFFF0;
  516. UINT64 PMemBase64 = BrdgConf->Res.PMemBase64 & ~0xFULL;
  517. UINT8 BusRange = BrdgConf->SubBus - BrdgConf->PBus - 2;
  518. HrConfigs[AR_DS_PORT1].Res = NOT_IN_USE_BRIDGE;
  519. HrConfigs[AR_DS_PORT1].Res.Cls = DEF_CACHE_LINE_SIZE;
  520. HrConfigs[AR_DS_PORT1].Res.Cmd = CMD_BM_MEM;
  521. HrConfigs[AR_DS_PORT1].Res.MemBase = MemBase;
  522. HrConfigs[AR_DS_PORT1].Res.MemLimit = BrdgConf->Res.MemLimit - 1;
  523. HrConfigs[AR_DS_PORT1].Res.PMemBase64 = PMemBase64;
  524. HrConfigs[AR_DS_PORT1].Res.PMemLimit64 = BrdgConf->Res.PMemLimit64;
  525. HrConfigs[AR_DS_PORT1].SBus = BrdgConf->SBus;
  526. HrConfigs[AR_DS_PORT1].SubBus = BrdgConf->SBus + BusRange;
  527. BrdgConf->SBus = HrConfigs[AR_DS_PORT1].SubBus + 1;
  528. HrConfigs[AR_DS_PORT2].Res = NOT_IN_USE_BRIDGE;
  529. HrConfigs[AR_DS_PORT2].Res.Cls = DEF_CACHE_LINE_SIZE;
  530. HrConfigs[AR_DS_PORT2].Res.Cmd = CMD_BM_MEM;
  531. HrConfigs[AR_DS_PORT2].Res.MemBase = BrdgConf->Res.MemLimit;
  532. HrConfigs[AR_DS_PORT2].Res.MemLimit = BrdgConf->Res.MemLimit;
  533. HrConfigs[AR_DS_PORT2].SBus = BrdgConf->SBus;
  534. HrConfigs[AR_DS_PORT2].SubBus = BrdgConf->SBus;
  535. BrdgConf->SBus = HrConfigs[AR_DS_PORT2].SubBus + 1;
  536. }//InitARDSPort_1Port
  537. STATIC
  538. VOID
  539. InitARDSPort_2Port(
  540. IN OUT BRDG_CONFIG* BrdgConf
  541. )
  542. {
  543. UINT16 MemBase = BrdgConf->Res.MemBase & 0xFFF0;
  544. UINT64 PMemBase64 = BrdgConf->Res.PMemBase64 & ~0xFULL;
  545. UINT8 BusRange = BrdgConf->SubBus - BrdgConf->PBus - 3;
  546. // Busses are split between ports 1 and 4
  547. BusRange /= 2;
  548. HrConfigs[AR_DS_PORT1].Res = NOT_IN_USE_BRIDGE;
  549. HrConfigs[AR_DS_PORT1].Res.Cls = DEF_CACHE_LINE_SIZE;
  550. HrConfigs[AR_DS_PORT1].Res.Cmd = CMD_BM_MEM;
  551. HrConfigs[AR_DS_PORT1].Res.MemBase = MemBase;
  552. HrConfigs[AR_DS_PORT1].Res.MemLimit = MemBase + 0x17F0 - 1;
  553. HrConfigs[AR_DS_PORT1].Res.PMemBase64 = PMemBase64;
  554. HrConfigs[AR_DS_PORT1].Res.PMemLimit64 = PMemBase64 + 0x2000 - 1;
  555. HrConfigs[AR_DS_PORT1].SBus = BrdgConf->SBus;
  556. HrConfigs[AR_DS_PORT1].SubBus = BrdgConf->SBus + BusRange;
  557. BrdgConf->SBus = HrConfigs[AR_DS_PORT1].SubBus + 1;
  558. HrConfigs[AR_DS_PORT2].Res = NOT_IN_USE_BRIDGE;
  559. HrConfigs[AR_DS_PORT2].Res.Cls = DEF_CACHE_LINE_SIZE;
  560. HrConfigs[AR_DS_PORT2].Res.Cmd = CMD_BM_MEM;
  561. HrConfigs[AR_DS_PORT2].Res.MemBase = MemBase + 0x17F0;
  562. HrConfigs[AR_DS_PORT2].Res.MemLimit = MemBase + 0x1800 - 1;
  563. HrConfigs[AR_DS_PORT2].SBus = BrdgConf->SBus;
  564. HrConfigs[AR_DS_PORT2].SubBus = BrdgConf->SBus;
  565. BrdgConf->SBus = HrConfigs[AR_DS_PORT2].SubBus + 1;
  566. HrConfigs[AR_DS_PORT4].Res = NOT_IN_USE_BRIDGE;
  567. HrConfigs[AR_DS_PORT4].Res.Cls = DEF_CACHE_LINE_SIZE;
  568. HrConfigs[AR_DS_PORT4].Res.Cmd = CMD_BM_MEM;
  569. HrConfigs[AR_DS_PORT4].Res.MemBase = MemBase + 0x1800;
  570. HrConfigs[AR_DS_PORT4].Res.MemLimit = BrdgConf->Res.MemLimit;
  571. HrConfigs[AR_DS_PORT4].Res.PMemBase64 = PMemBase64 + 0x2000;
  572. HrConfigs[AR_DS_PORT4].Res.PMemLimit64 = BrdgConf->Res.PMemLimit64;
  573. HrConfigs[AR_DS_PORT4].SBus = BrdgConf->SBus;
  574. HrConfigs[AR_DS_PORT4].SubBus = BrdgConf->SubBus;
  575. BrdgConf->SBus = HrConfigs[AR_DS_PORT4].SubBus + 1;
  576. }//InitARDSPort_2Port
  577. STATIC
  578. BOOLEAN
  579. CheckLimits (
  580. IN BOOLEAN Is2PortDev,
  581. IN BRDG_RES_CONFIG *HrResConf,
  582. IN UINT8 BusRange
  583. )
  584. {
  585. UINT16 MemBase;
  586. UINT16 MemLimit;
  587. UINT64 PMemBase64;
  588. UINT64 PMemLimit64;
  589. MemBase = HrResConf->MemBase & 0xFFF0;
  590. MemLimit = HrResConf->MemLimit & 0xFFF0;
  591. PMemBase64 = HrResConf->PMemBase64 & 0xFFF0;
  592. PMemLimit64 = HrResConf->PMemLimit64 & 0xFFF0;
  593. //
  594. // Check memoty alignment
  595. //
  596. if (MemBase & 0x3FF) {
  597. DEBUG((DEBUG_INFO, "M alig\n"));
  598. return FALSE;
  599. }
  600. if (PMemBase64 & 0xFFF) {
  601. DEBUG((DEBUG_INFO, "PM alig\n"));
  602. return FALSE;
  603. }
  604. if (Is2PortDev) {
  605. //
  606. // Check mem size
  607. //
  608. if (MemLimit + 0x10 - MemBase < 0x2E00) {
  609. DEBUG((DEBUG_INFO, "M size\n"));
  610. return FALSE;
  611. }
  612. //
  613. // Check P-mem size
  614. //
  615. if (PMemLimit64 + 0x10 - PMemBase64 < 0x4A00) {
  616. DEBUG((DEBUG_INFO, "PM size\n"));
  617. return FALSE;
  618. }
  619. //
  620. // Check bus range
  621. //
  622. if (BusRange < 106) {
  623. DEBUG((DEBUG_INFO, "Bus range\n"));
  624. return FALSE;
  625. }
  626. } else {
  627. //
  628. // Check mem size
  629. //
  630. if (MemLimit + 0x10 - MemBase < 0x1600) {
  631. DEBUG((DEBUG_INFO, "M size\n"));
  632. return FALSE;
  633. }
  634. //
  635. // Check P-mem size
  636. //
  637. if (PMemLimit64 + 0x10 - PMemBase64 < 0x2200) {
  638. DEBUG((DEBUG_INFO, "PM size\n"));
  639. return FALSE;
  640. }
  641. //
  642. // Check bus range
  643. //
  644. if (BusRange < 56) {
  645. DEBUG((DEBUG_INFO, "Bus range\n"));
  646. return FALSE;
  647. }
  648. }
  649. return TRUE;
  650. } // CheckLimits
  651. STATIC
  652. BOOLEAN
  653. InitHRResConfigs (
  654. IN OUT HR_CONFIG *Hr_Config,
  655. IN UINT8 BusNumLimit,
  656. IN OUT BRDG_RES_CONFIG*HrResConf
  657. )
  658. {
  659. BRDG_CONFIG BrdgConf = { { 0 } };
  660. InitCommonHRConfigs (Hr_Config, BusNumLimit, HrResConf);
  661. BrdgConf.PBus = Hr_Config->HRBus + 2;// Take into account busses
  662. BrdgConf.SBus = Hr_Config->HRBus + 3;// for US and DS of HIA
  663. BrdgConf.SubBus = BusNumLimit;
  664. BrdgConf.Res = *HrResConf;
  665. while (TRUE) {
  666. switch (Hr_Config->DeviceId) {
  667. case AR_HR_4C:
  668. case TR_HR_4C:
  669. case AR_HR_C0_4C:
  670. //
  671. // 2 Port host
  672. //
  673. if (CheckLimits (TRUE, HrResConf, BusNumLimit - Hr_Config->HRBus)) {
  674. InitARDSPort_2Port(&BrdgConf);
  675. DEBUG((DEBUG_INFO, "AR2\n"));
  676. return TRUE;
  677. } else {
  678. return FALSE;
  679. }
  680. // AR only
  681. case AR_HR_2C: // 1 port host
  682. case AR_HR_C0_2C:
  683. case AR_HR_LP:
  684. case TR_HR_2C:
  685. DEBUG((DEBUG_INFO, "AR1\n"));
  686. InitARDSPort_1Port(&BrdgConf);
  687. return TRUE;
  688. default:
  689. InitHRDSPort_Disable (HR_DS_PORT3, &BrdgConf);
  690. InitHRDSPort_Disable (HR_DS_PORT4, &BrdgConf);
  691. InitHRDSPort_Disable (HR_DS_PORT5, &BrdgConf);
  692. InitHRDSPort_Disable (HR_DS_PORT6, &BrdgConf);
  693. return FALSE;
  694. }
  695. }
  696. } // InitHRResConfigs
  697. STATIC
  698. BOOLEAN
  699. InitializeHostRouter (
  700. OUT HR_CONFIG *Hr_Config,
  701. IN UINTN RpSegment,
  702. IN UINTN RpBus,
  703. IN UINTN RpDevice,
  704. IN UINTN RpFunction
  705. )
  706. {
  707. UINT8 BusNumLimit;
  708. BRDG_RES_CONFIG HrResConf = { 0 };
  709. UINT8 i;
  710. BOOLEAN Ret;
  711. Ret = TRUE;
  712. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
  713. Hr_Config->HRBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  714. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, Hr_Config->HRBus, 0x00, 0x00, 0);
  715. Hr_Config->DeviceId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
  716. if (!(IsTbtHostRouter (Hr_Config->DeviceId))) {
  717. return FALSE;
  718. }
  719. TbtSegment = (UINT8)RpSegment;
  720. HrResConf.Cmd = CMD_BM_MEM;
  721. HrResConf.Cls = DEF_CACHE_LINE_SIZE;
  722. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, 0);
  723. HrResConf.IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase));
  724. HrResConf.IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit));
  725. HrResConf.MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase));
  726. HrResConf.MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit));
  727. HrResConf.PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase));
  728. HrResConf.PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit));
  729. HrResConf.PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16;
  730. HrResConf.PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16;
  731. BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
  732. Ret = InitHRResConfigs (Hr_Config, BusNumLimit, &HrResConf);
  733. for (i = 0; i < Hr_Config->BridgeLoops; ++i) {
  734. UINT8 Bus;
  735. UINT8 Dev;
  736. UINT8 Fun;
  737. Bus = HrConfigs[i].DevId.Bus;
  738. Dev = HrConfigs[i].DevId.Dev;
  739. Fun = HrConfigs[i].DevId.Fun;
  740. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
  741. PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, HrConfigs[i].Res.Cls);
  742. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, HrConfigs[i].PBus);
  743. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, HrConfigs[i].SBus);
  744. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, HrConfigs[i].SubBus);
  745. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), HrConfigs[i].Res.MemBase);
  746. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), HrConfigs[i].Res.MemLimit);
  747. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (HrConfigs[i].Res.PMemBase64 & 0xFFFF));
  748. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) (HrConfigs[i].Res.PMemLimit64 & 0xFFFF));
  749. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (HrConfigs[i].Res.PMemBase64 >> 16));
  750. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) (HrConfigs[i].Res.PMemLimit64 >> 16));
  751. PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), HrConfigs[i].Res.IoBase);
  752. PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit), HrConfigs[i].Res.IoLimit);
  753. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16), 0x00000000);
  754. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, HrConfigs[i].Res.Cmd);
  755. }
  756. if (Hr_Config->DeviceId == AR_HR_2C || Hr_Config->DeviceId == AR_HR_4C || Hr_Config->DeviceId == AR_HR_LP) {
  757. for (i = 0; i < Hr_Config->BridgeLoops; ++i) {
  758. if(HrConfigs[i].IsDSBridge) {
  759. UnsetVesc(HrConfigs[i].DevId.Bus, HrConfigs[i].DevId.Dev, HrConfigs[i].DevId.Fun);
  760. }
  761. }
  762. }
  763. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,(Hr_Config->HRBus + 2), 0x00, 0x00, 0);
  764. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX0 * 4), HrConfigs[HR_DS_PORT0].Res.MemLimit << 16);
  765. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), (HrConfigs[HR_DS_PORT0].Res.MemLimit + 0x4) << 16);
  766. PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
  767. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BM_MEM);
  768. return Ret;
  769. } // InitializeHostRouter
  770. STATIC
  771. UINT8
  772. ConfigureSlot (
  773. IN UINT8 Bus,
  774. IN UINT8 MAX_DEVICE,
  775. IN INT8 Depth,
  776. IN BOOLEAN ArPcie,
  777. IN OUT PORT_INFO *PortInfo
  778. )
  779. {
  780. UINT8 Device;
  781. UINT8 SBus;
  782. UINT8 UsedBusNumbers;
  783. UINT8 RetBusNum;
  784. PORT_INFO CurrentSlot;
  785. RetBusNum = 0;
  786. for (Device = 0; Device < MAX_DEVICE; Device++) {
  787. //
  788. // Continue if device is absent
  789. //
  790. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, 0x00, 0);
  791. if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
  792. continue;
  793. }
  794. if (P2P_BRIDGE != PciSegmentRead16 (gDeviceBaseAddress + (PCI_CLASSCODE_OFFSET + 1))) {
  795. SetDevResources (
  796. Bus,
  797. Device,
  798. PCI_MAX_FUNC,
  799. PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX5 * 4),
  800. PortInfo
  801. );
  802. continue;
  803. }
  804. //
  805. // Else Bridge
  806. //
  807. CopyMem (&CurrentSlot, PortInfo, sizeof (PORT_INFO));
  808. ++RetBusNum; // UP Bridge
  809. SBus = Bus + RetBusNum; // DS Bridge
  810. if (SBus + 1 >= PortInfo->BusNumLimit) {
  811. continue;
  812. }
  813. SetDevResources (Bus, Device, 1, PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), PortInfo);
  814. //
  815. // Init UP Bridge to reach DS Bridge
  816. //
  817. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus);
  818. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, SBus);
  819. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit);
  820. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BM_MEM);
  821. if(ArPcie) {
  822. UnsetVesc(Bus, Device, 0x00);
  823. }
  824. UsedBusNumbers = ConfigureSlot(SBus, PCI_MAX_DEVICE + 1, -1, FALSE, PortInfo);
  825. RetBusNum += UsedBusNumbers;
  826. SetPhyPortResources (
  827. Bus,
  828. Device,
  829. SBus + UsedBusNumbers,
  830. Depth,
  831. &CurrentSlot,
  832. PortInfo
  833. );
  834. }
  835. //
  836. // for (Device = 0; Device <= PCI_MAX_DEVICE; Device++)
  837. //
  838. return RetBusNum;
  839. } // ConfigureSlot
  840. STATIC
  841. VOID
  842. SetCioPortResources (
  843. IN UINT8 Bus,
  844. IN UINT8 Dev,
  845. IN UINT8 SBus,
  846. IN UINT8 SubBus,
  847. IN PORT_INFO *portInfoBeforeChange,
  848. IN OUT PORT_INFO *PortInfo
  849. )
  850. {
  851. UINT8 Cmd;
  852. Cmd = CMD_BUS_MASTER;
  853. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, 0x00, 0);
  854. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus);
  855. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, SBus);
  856. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, SubBus);
  857. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
  858. if (PortInfo->IoBase <= PortInfo->IoLimit) {
  859. PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), PortInfo->IoBase);
  860. PciSegmentWrite8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit), PortInfo->IoLimit);
  861. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBaseUpper16), 0x00000000);
  862. Cmd |= CMD_BM_IO;
  863. } else {
  864. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), DISBL_IO_REG1C);
  865. }
  866. if (PortInfo->MemBase <= PortInfo->MemLimit) {
  867. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), PortInfo->MemBase);
  868. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), PortInfo->MemLimit);
  869. Cmd |= CMD_BM_MEM;
  870. } else {
  871. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20);
  872. }
  873. if (PortInfo->PMemBase64 <= PortInfo->PMemLimit64) {
  874. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), (UINT16) (PortInfo->PMemBase64 & 0xFFFF));
  875. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit), (UINT16) (PortInfo->PMemLimit64 & 0xFFFF));
  876. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), (UINT32) (PortInfo->PMemBase64 >> 16));
  877. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), (UINT32) (PortInfo->PMemLimit64 >> 16));
  878. Cmd |= CMD_BM_MEM;
  879. } else {
  880. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24);
  881. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0);
  882. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32), 0);
  883. }
  884. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, Cmd);
  885. PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
  886. } // SetCioPortResources
  887. STATIC
  888. VOID
  889. SetSlotsAsUnused (
  890. IN UINT8 Bus,
  891. IN UINT8 MaxSlotNum,
  892. IN UINT8 CioSlot,
  893. IN OUT PORT_INFO *PortInfo
  894. )
  895. {
  896. UINT8 Slot;
  897. for (Slot = MaxSlotNum; Slot > CioSlot; --Slot) {
  898. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Slot, 0x00, 0);
  899. if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
  900. continue;
  901. }
  902. PciSegmentWrite8 (gDeviceBaseAddress + PCI_CACHELINE_SIZE_OFFSET, DEF_CACHE_LINE_SIZE);
  903. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, Bus);
  904. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit);
  905. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, PortInfo->BusNumLimit);
  906. PciSegmentWrite16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase), DISBL_IO_REG1C);
  907. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), DISBL_MEM32_REG20);
  908. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase), DISBL_PMEM_REG24);
  909. PciSegmentWrite8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, CMD_BUS_MASTER);
  910. PortInfo->BusNumLimit--;
  911. }
  912. } // SetSlotsAsUnused
  913. STATIC
  914. UINT16
  915. FindVendorSpecificHeader(
  916. IN UINT8 Bus
  917. )
  918. {
  919. PCI_EXP_EXT_HDR *ExtHdr;
  920. UINT32 ExtHdrValue;
  921. UINT16 ExtendedRegister;
  922. ExtHdr = (PCI_EXP_EXT_HDR*) &ExtHdrValue;
  923. ExtendedRegister = 0x100;
  924. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0);
  925. while (ExtendedRegister) {
  926. ExtHdrValue = PciSegmentRead32 (gDeviceBaseAddress + ExtendedRegister);
  927. if (ExtHdr->CapabilityId == 0xFFFF) {
  928. return 0x0000; // No Vendor-Specific Extended Capability header
  929. }
  930. if (PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID == ExtHdr->CapabilityId) {
  931. return ExtendedRegister;
  932. }
  933. ExtendedRegister = (UINT16) ExtHdr->NextCapabilityOffset;
  934. }
  935. return 0x0000; // No Vendor-Specific Extended Capability header
  936. }
  937. STATIC
  938. UINT8
  939. FindSsid_SsvidHeader (
  940. IN UINT8 Bus
  941. )
  942. {
  943. UINT8 CapHeaderId;
  944. UINT8 CapHeaderOffset;
  945. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0);
  946. CapHeaderOffset = PciSegmentRead8 (gDeviceBaseAddress + PCI_CAPBILITY_POINTER_OFFSET);
  947. while (CapHeaderOffset != 0) {
  948. CapHeaderId = PciSegmentRead8 (gDeviceBaseAddress + CapHeaderOffset);
  949. if (CapHeaderId == PCIE_CAP_ID_SSID_SSVID) {
  950. return CapHeaderOffset;
  951. }
  952. CapHeaderOffset = PciSegmentRead8 (gDeviceBaseAddress + CapHeaderOffset + 1);
  953. }
  954. DEBUG((DEBUG_INFO, "SID0\n"));
  955. return 0;
  956. } // FindSsid_SsvidHeader
  957. STATIC
  958. BOOLEAN
  959. GetCioSlotByDevId (
  960. IN UINT8 Bus,
  961. OUT UINT8 *CioSlot,
  962. OUT UINT8 *MaxSlotNum,
  963. OUT BOOLEAN *ArPcie
  964. )
  965. {
  966. UINT16 VSECRegister;
  967. BRDG_CIO_MAP_REG BridgMap;
  968. UINT32 BitScanRes;
  969. UINT16 DevId;
  970. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, 0x00, 0x00, 0);
  971. DevId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
  972. //
  973. // Init out params in case device is not recognised
  974. //
  975. *CioSlot = 4;
  976. *MaxSlotNum = 7;
  977. *ArPcie = FALSE;
  978. switch (DevId) {
  979. //
  980. // For known device IDs
  981. //
  982. case 0x1578:
  983. *ArPcie = TRUE;
  984. }
  985. switch (DevId) {
  986. //
  987. // For known device IDs
  988. //
  989. case 0x1513:
  990. case 0x151A:
  991. case 0x151B:
  992. case 0x1547:
  993. case 0x1548:
  994. return TRUE; // Just return
  995. case 0x1549:
  996. return FALSE; // Just return
  997. }
  998. VSECRegister = FindVendorSpecificHeader(Bus);
  999. if (!VSECRegister) {
  1000. return TRUE; // Just return
  1001. }
  1002. //
  1003. // Go to Bridge/CIO map register
  1004. //
  1005. VSECRegister += 0x18;
  1006. BridgMap.AB_REG = PciSegmentRead32(gDeviceBaseAddress + VSECRegister);
  1007. //
  1008. // Check for range
  1009. //
  1010. if (BridgMap.Bits.NumOfDSPorts < 1 || BridgMap.Bits.NumOfDSPorts > 27) {
  1011. return TRUE;
  1012. //
  1013. // Not a valid register
  1014. //
  1015. }
  1016. //
  1017. // Set OUT params
  1018. //
  1019. *MaxSlotNum = (UINT8) BridgMap.Bits.NumOfDSPorts;
  1020. #ifdef _MSC_VER
  1021. if(!_BitScanForward(&BitScanRes, BridgMap.Bits.CioPortMap)) { // No DS bridge which is CIO port
  1022. return FALSE;
  1023. }
  1024. #else
  1025. #ifdef __GNUC__
  1026. if (BridgMap.Bits.CioPortMap == 0) {
  1027. return FALSE;
  1028. }
  1029. BitScanRes = __builtin_ctz (BridgMap.Bits.CioPortMap);
  1030. #else
  1031. #error Unsupported Compiler
  1032. #endif
  1033. #endif
  1034. *CioSlot = (UINT8)BitScanRes;
  1035. return TRUE;
  1036. } // GetCioSlotByDevId
  1037. #define TBT_LEGACY_SUB_SYS_ID 0x11112222
  1038. STATIC
  1039. BOOLEAN
  1040. IsLegacyDevice (
  1041. IN UINT8 Bus
  1042. )
  1043. {
  1044. UINT32 Sid;
  1045. UINT8 SidRegister;
  1046. UINT16 DevId;
  1047. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, 0x00, 0x00, 0);
  1048. DevId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
  1049. switch (DevId) {
  1050. //
  1051. // For known device IDs
  1052. //
  1053. case 0x1513:
  1054. case 0x151A:
  1055. case 0x151B:
  1056. DEBUG((DEBUG_INFO, "Legacy "));
  1057. DEBUG((DEBUG_INFO, "DevId = %d\n",DevId));
  1058. return TRUE;
  1059. //
  1060. // Legacy device by Device Id
  1061. //
  1062. }
  1063. SidRegister = FindSsid_SsvidHeader(Bus);
  1064. if (!SidRegister) {
  1065. return TRUE; // May be absent for legacy devices
  1066. }
  1067. //
  1068. // Go to register
  1069. //
  1070. SidRegister += 0x4;
  1071. Sid = PciSegmentRead32(gDeviceBaseAddress + SidRegister);
  1072. DEBUG((DEBUG_INFO, "SID"));
  1073. DEBUG((DEBUG_INFO, " = %d\n", Sid));
  1074. return TBT_LEGACY_SUB_SYS_ID == Sid || 0 == Sid;
  1075. } // IsLegacyDevice
  1076. STATIC
  1077. VOID
  1078. UnsetVescEp(
  1079. IN UINT8 Bus,
  1080. IN UINT8 MaxSlotNum
  1081. )
  1082. {
  1083. UINT8 i;
  1084. for (i = 0; i <= MaxSlotNum; ++i)
  1085. {
  1086. UnsetVesc(Bus, i, 0);
  1087. }
  1088. }// Unset_VESC_REG2_EP
  1089. STATIC
  1090. BOOLEAN
  1091. ConfigureEP (
  1092. IN INT8 Depth,
  1093. IN OUT UINT8 *Bus,
  1094. IN OUT PORT_INFO *PortInfo
  1095. )
  1096. {
  1097. UINT8 SBus;
  1098. UINT8 CioSlot;
  1099. UINT8 MaxSlotNum;
  1100. BOOLEAN ArPcie;
  1101. UINT8 MaxPHYSlots;
  1102. UINT8 UsedBusNumbers;
  1103. UINT8 cmd;
  1104. BOOLEAN CioSlotPresent;
  1105. BOOLEAN Continue;
  1106. PORT_INFO PortInfoOrg;
  1107. UINT8 CioBus;
  1108. CioSlot = 4;
  1109. MaxSlotNum = 7;
  1110. CopyMem (&PortInfoOrg, PortInfo, sizeof (PORT_INFO));
  1111. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, *Bus, 0x00, 0x00, 0);
  1112. cmd = PciSegmentRead8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET);
  1113. // AR ONLY
  1114. // Endpoint on CIO slot, but not a bridge device
  1115. if (P2P_BRIDGE != PciSegmentRead16 (gDeviceBaseAddress + (PCI_CLASSCODE_OFFSET + 1))) {
  1116. DEBUG((DEBUG_INFO, "UEP\n"));
  1117. // Check whether EP already configured by examining CMD register
  1118. if(cmd & CMD_BUS_MASTER) // Yes, no need to touch this EP
  1119. {
  1120. DEBUG((DEBUG_INFO, "BMF\n"));
  1121. return FALSE;
  1122. }
  1123. // Configure it as regular PCIe device
  1124. ConfigureSlot(*Bus, PCI_MAX_DEVICE + 1, -1, FALSE, PortInfo);
  1125. return FALSE;
  1126. }
  1127. //
  1128. // Based on Device ID assign Cio slot and max number of PHY slots to scan
  1129. //
  1130. CioSlotPresent = GetCioSlotByDevId(*Bus, &CioSlot, &MaxSlotNum, &ArPcie);
  1131. MaxPHYSlots = MaxSlotNum;
  1132. //
  1133. // Check whether EP already configured by examining CMD register
  1134. //
  1135. if (cmd & CMD_BUS_MASTER) {
  1136. //
  1137. // Yes no need to touch this EP, just move to next one in chain
  1138. //
  1139. CioBus = *Bus + 1;
  1140. if(ArPcie){
  1141. UnsetVescEp(CioBus, MaxSlotNum);
  1142. }
  1143. if (!CioSlotPresent) {
  1144. //
  1145. // Cio slot is not present in EP, just return FALSE
  1146. //
  1147. DEBUG((DEBUG_INFO, "BMF\n"));
  1148. return FALSE;
  1149. }
  1150. //
  1151. // Take all resources from Cio slot and return
  1152. //
  1153. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,CioBus, CioSlot, 0x00, 0);
  1154. PortInfo->BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
  1155. PortInfo->IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase));
  1156. PortInfo->IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit));
  1157. PortInfo->MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase));
  1158. PortInfo->MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit));
  1159. PortInfo->PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)) & 0xFFF0;
  1160. PortInfo->PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)) & 0xFFF0;
  1161. PortInfo->PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16;
  1162. PortInfo->PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16;
  1163. PortInfo->PMemLimit64 |= 0xF;
  1164. //
  1165. // Jump to next EP
  1166. //
  1167. *Bus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  1168. //
  1169. // Should we continue?
  1170. //
  1171. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,*Bus, 0x00, 0x00, 0);
  1172. Continue = 0xFFFF != PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
  1173. return Continue;
  1174. }
  1175. //
  1176. // Set is legacy dvice
  1177. //
  1178. isLegacyDevice = IsLegacyDevice (*Bus);
  1179. SetCioPortResources (
  1180. *Bus,
  1181. 0, // Assign all available resources to US port of EP
  1182. *Bus + 1,
  1183. PortInfo->BusNumLimit,
  1184. 0,
  1185. PortInfo
  1186. );
  1187. SBus = *Bus + 1;// Jump to DS port
  1188. if (CioSlotPresent) {
  1189. MaxPHYSlots = CioSlot;
  1190. }
  1191. UsedBusNumbers = ConfigureSlot(SBus, MaxPHYSlots, Depth, ArPcie, PortInfo);
  1192. if (!CioSlotPresent) {
  1193. return FALSE;
  1194. //
  1195. // Stop resource assignment on this chain
  1196. //
  1197. }
  1198. //
  1199. // Set rest of slots us unused
  1200. //
  1201. SetSlotsAsUnused (SBus, MaxSlotNum, CioSlot, PortInfo);
  1202. SetCioPortResources (
  1203. SBus,
  1204. CioSlot,
  1205. SBus + UsedBusNumbers + 1,
  1206. PortInfo->BusNumLimit,
  1207. &PortInfoOrg,
  1208. PortInfo
  1209. );
  1210. *Bus = SBus + UsedBusNumbers + 1;// Go to next EP
  1211. if(ArPcie) {
  1212. UnsetVesc(SBus, CioSlot, 0x00);
  1213. }
  1214. if (*Bus > PortInfo->BusNumLimit - 2) {
  1215. //
  1216. // In case of bus numbers are exhausted stop enumeration
  1217. //
  1218. return FALSE;
  1219. }
  1220. //
  1221. // Check whether we should continue on this chain
  1222. //
  1223. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,*Bus, 0x00, 0x00, 0);
  1224. Continue = 0xFFFF != PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
  1225. return Continue;
  1226. } // ConfigureEP
  1227. STATIC
  1228. VOID
  1229. GetPortResources (
  1230. IN UINT8 Bus,
  1231. IN UINT8 Dev,
  1232. IN UINT8 Fun,
  1233. IN OUT PORT_INFO *PortInfo
  1234. )
  1235. {
  1236. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
  1237. PortInfo->BusNumLimit = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
  1238. PortInfo->IoBase = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoBase)) & 0xF0;
  1239. PortInfo->IoLimit = PciSegmentRead8 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.IoLimit)) & 0xF0;
  1240. PortInfo->MemBase = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase)) & 0xFFF0;
  1241. PortInfo->MemLimit = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit)) & 0xFFF0;
  1242. PortInfo->PMemBase64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryBase)) & 0xFFF0;
  1243. PortInfo->PMemLimit64 = PciSegmentRead16 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableMemoryLimit)) & 0xFFF0;
  1244. PortInfo->PMemBase64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32))) << 16;
  1245. PortInfo->PMemLimit64 |= (UINT64)(PciSegmentRead32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableLimitUpper32))) << 16;
  1246. PortInfo->IoLimit |= 0xF;
  1247. PortInfo->MemLimit |= 0xF;
  1248. PortInfo->PMemLimit64 |= 0xF;
  1249. } // GetPortResources
  1250. STATIC
  1251. VOID
  1252. ConfigurePort (
  1253. IN UINT8 Bus,
  1254. IN UINT8 Dev,
  1255. IN UINT8 Fun,
  1256. IN OUT PORT_INFO *PortInfo
  1257. )
  1258. {
  1259. INT8 i;
  1260. UINT8 USBusNum;
  1261. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
  1262. USBusNum = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  1263. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, USBusNum, 0x00, 0x00, 0);
  1264. if (0xFFFF == PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET)) {
  1265. //
  1266. // Nothing to do if TBT device is not connected
  1267. //
  1268. return ;
  1269. }
  1270. GetPortResources(Bus, Dev, Fun, PortInfo);// Take reserved resources from DS port
  1271. //
  1272. // Assign resources to EPs
  1273. //
  1274. for (i = 0; i < MAX_TBT_DEPTH; ++i) {
  1275. PortInfo->ConfedEP++;
  1276. if (!ConfigureEP (i, &USBusNum, PortInfo)) {
  1277. return ;
  1278. }
  1279. }
  1280. } // ConfigurePort
  1281. VOID
  1282. ThunderboltCallback (
  1283. IN UINT8 Type
  1284. )
  1285. {
  1286. PORT_INFO PortInfoOrg = { 0 };
  1287. HR_CONFIG HrConfig = { 0 };
  1288. UINT8 i;
  1289. UINTN Segment = 0;
  1290. UINTN Bus = 0;
  1291. UINTN Device;
  1292. UINTN Function;
  1293. DEBUG((DEBUG_INFO, "ThunderboltCallback.Entry\n"));
  1294. DEBUG((DEBUG_INFO, "PortInfo Initialization\n"));
  1295. PortInfoInit (&PortInfoOrg);
  1296. if(Type == DTBT_CONTROLLER) {
  1297. if (gCurrentDiscreteTbtRootPort == 0) {
  1298. DEBUG((DEBUG_ERROR, "Invalid RP Input\n"));
  1299. return;
  1300. }
  1301. GetDTbtRpDevFun(gCurrentDiscreteTbtRootPortType, gCurrentDiscreteTbtRootPort - 1, &Device, &Function);
  1302. DEBUG((DEBUG_INFO, "InitializeHostRouter. \n"));
  1303. if (!InitializeHostRouter (&HrConfig, Segment, Bus, Device, Function)) {
  1304. return ;
  1305. }
  1306. //
  1307. // Configure DS ports
  1308. //
  1309. for (i = HrConfig.MinDSNumber; i <= HrConfig.MaxDSNumber; ++i) {
  1310. DEBUG((DEBUG_INFO, "ConfigurePort. \n"));
  1311. ConfigurePort (HrConfig.HRBus + 1, i,0, &PortInfoOrg);
  1312. }
  1313. DEBUG((DEBUG_INFO, "EndOfThunderboltCallback.\n"));
  1314. EndOfThunderboltCallback (Segment, Bus, Device, Function);
  1315. }
  1316. DEBUG((DEBUG_INFO, "ThunderboltCallback.Exit\n"));
  1317. } // ThunderboltCallback
  1318. VOID
  1319. DisablePCIDevicesAndBridges (
  1320. IN UINT8 MinBus,
  1321. IN UINT8 MaxBus
  1322. )
  1323. {
  1324. UINT8 Bus;
  1325. UINT8 Dev;
  1326. UINT8 Fun;
  1327. UINT8 RegVal;
  1328. //
  1329. // Disable PCI device First, and then Disable PCI Bridge
  1330. //
  1331. for (Bus = MaxBus; Bus > MinBus; --Bus) {
  1332. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  1333. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  1334. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
  1335. if (INVALID_PCI_DEVICE == PciSegmentRead32 (gDeviceBaseAddress + PCI_VENDOR_ID_OFFSET)) {
  1336. if (Fun == 0) {
  1337. break;
  1338. }
  1339. continue;
  1340. }
  1341. RegVal = PciSegmentRead8 (gDeviceBaseAddress + PCI_HEADER_TYPE_OFFSET);
  1342. if (HEADER_TYPE_DEVICE == (RegVal & 1)) {
  1343. //
  1344. // ******** Disable PCI Device ********
  1345. // BIT0 I/O Space Enabled BIT1 Memory Space Enabled
  1346. // BIT2 Bus Master Enabled BIT4 Memory Write and Invalidation Enable
  1347. //
  1348. PciSegmentAnd8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, (UINT8)~(BIT0 | BIT1 | BIT2 | BIT4));
  1349. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX0 * 4), 0);
  1350. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX1 * 4), 0);
  1351. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX2 * 4), 0);
  1352. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX3 * 4), 0);
  1353. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX4 * 4), 0);
  1354. PciSegmentWrite32 (gDeviceBaseAddress + PCI_BASE_ADDRESSREG_OFFSET + (PCI_BAR_IDX5 * 4), 0);
  1355. }
  1356. }
  1357. }
  1358. }
  1359. //
  1360. // now no more PCI dev on another side of PCI Bridge can safty disable PCI Bridge
  1361. //
  1362. for (Bus = MaxBus; Bus > MinBus; --Bus) {
  1363. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  1364. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  1365. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment,Bus, Dev, Fun, 0);
  1366. if (INVALID_PCI_DEVICE == PciSegmentRead32 (gDeviceBaseAddress + PCI_VENDOR_ID_OFFSET)) {
  1367. if (Fun == 0) {
  1368. break;
  1369. }
  1370. continue;
  1371. }
  1372. RegVal = PciSegmentRead8 (gDeviceBaseAddress + PCI_HEADER_TYPE_OFFSET);
  1373. if (HEADER_TYPE_PCI_TO_PCI_BRIDGE == (RegVal & BIT0)) {
  1374. PciSegmentAnd8 (gDeviceBaseAddress + PCI_COMMAND_OFFSET, (UINT8)~(BIT0 | BIT1 | BIT2 | BIT4));
  1375. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET, 0);
  1376. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0);
  1377. PciSegmentWrite8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0);
  1378. PciSegmentWrite32 (gDeviceBaseAddress + OFFSET_OF (PCI_TYPE01, Bridge.PrefetchableBaseUpper32), 0);
  1379. }
  1380. } // for ( Fun .. )
  1381. } // for ( Dev ... )
  1382. } // for ( Bus ... )
  1383. } // DisablePCIDevicesAndBridges
  1384. VOID
  1385. TbtDisablePCIDevicesAndBridges (
  1386. IN UINT8 Type
  1387. )
  1388. {
  1389. UINTN Segment = 0;
  1390. UINTN Bus = 0;
  1391. UINTN Device;
  1392. UINTN Function;
  1393. UINT8 MinBus;
  1394. UINT8 MaxBus;
  1395. UINT16 DeviceId;
  1396. MinBus = 1;
  1397. if(Type == DTBT_CONTROLLER) {
  1398. //
  1399. // for(Dev = 0; Dev < 8; ++Dev)
  1400. // {
  1401. // PciOr8(PCI_LIB_ADDRESS(2, Dev, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET), 0x40);
  1402. // gBS->Stall(2000); // 2msec
  1403. // PciAnd8(PCI_LIB_ADDRESS(2, Dev, 0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET), 0xBF);
  1404. // }
  1405. // gBS->Stall(200 * 1000); // 200 msec
  1406. //
  1407. if (gCurrentDiscreteTbtRootPort == 0) {
  1408. DEBUG((DEBUG_ERROR, "Invalid RP Input\n"));
  1409. return;
  1410. }
  1411. GetDTbtRpDevFun(gCurrentDiscreteTbtRootPortType, gCurrentDiscreteTbtRootPort - 1, &Device, &Function);
  1412. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
  1413. MinBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  1414. MaxBus = PciSegmentRead8 (gDeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
  1415. gDeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, MinBus, 0x00, 0x00, 0);
  1416. DeviceId = PciSegmentRead16 (gDeviceBaseAddress + PCI_DEVICE_ID_OFFSET);
  1417. if (!(IsTbtHostRouter (DeviceId))) {
  1418. return;
  1419. }
  1420. TbtSegment = (UINT8)Segment;
  1421. MinBus++;
  1422. //
  1423. // @todo : Move this out when we dont have Loop for ITBT
  1424. //
  1425. DisablePCIDevicesAndBridges(MinBus, MaxBus);
  1426. }
  1427. } // DisablePCIDevicesAndBridges