TbtSmiHandler.c 51 KB

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