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