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