]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
Update the PCD comments for PcdFrameworkHiiCompatibilitySupport.
[mirror_edk2.git] / DuetPkg / PciRootBridgeNoEnumerationDxe / PcatPciRootBridge.c
CommitLineData
c69dd9df 1/*++\r
2\r
8e53d246 3Copyright (c) 2005 - 2008, Intel Corporation \r
c69dd9df 4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 PcatPciRootBridge.c\r
14 \r
15Abstract:\r
16\r
17 EFI PC-AT PCI Root Bridge Controller\r
18\r
19--*/\r
20\r
21#include "PcatPciRootBridge.h"\r
22#include "DeviceIo.h"\r
23\r
24EFI_CPU_IO_PROTOCOL *gCpuIo;\r
25\r
26EFI_STATUS\r
27EFIAPI\r
28InitializePcatPciRootBridge (\r
29 IN EFI_HANDLE ImageHandle,\r
30 IN EFI_SYSTEM_TABLE *SystemTable\r
31 )\r
32/*++\r
33\r
34Routine Description:\r
35 Initializes the PCI Root Bridge Controller\r
36\r
37Arguments:\r
38 ImageHandle -\r
39 SystemTable -\r
40 \r
41Returns:\r
42 None\r
43\r
44--*/\r
45{\r
46 EFI_STATUS Status;\r
47 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
48 UINTN PciSegmentIndex;\r
49 UINTN PciRootBridgeIndex;\r
50 UINTN PrimaryBusIndex;\r
51 UINTN NumberOfPciRootBridges;\r
52 UINTN NumberOfPciDevices;\r
53 UINTN Device;\r
54 UINTN Function;\r
55 UINT16 VendorId;\r
56 PCI_TYPE01 PciConfigurationHeader;\r
57 UINT64 Address;\r
58 UINT64 Value;\r
59 UINT64 Base;\r
60 UINT64 Limit;\r
61\r
62 //\r
63 // Initialize gCpuIo now since the chipset init code requires it.\r
64 //\r
8e53d246 65 Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, (VOID **)&gCpuIo);\r
c69dd9df 66 ASSERT_EFI_ERROR (Status);\r
67\r
68 //\r
69 // Initialize variables required to search all PCI segments for PCI devices\r
70 //\r
71 PciSegmentIndex = 0;\r
72 PciRootBridgeIndex = 0;\r
73 NumberOfPciRootBridges = 0;\r
74 PrimaryBusIndex = 0;\r
75\r
76 while (PciSegmentIndex <= PCI_MAX_SEGMENT) {\r
77\r
78 PrivateData = NULL;\r
79 Status = gBS->AllocatePool(\r
80 EfiBootServicesData,\r
81 sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE),\r
8e53d246 82 (VOID **)&PrivateData\r
c69dd9df 83 );\r
84 if (EFI_ERROR (Status)) {\r
85 goto Done;\r
86 }\r
87\r
88 ZeroMem (PrivateData, sizeof (PCAT_PCI_ROOT_BRIDGE_INSTANCE));\r
89\r
90 //\r
91 // Initialize the signature of the private data structure\r
92 //\r
93 PrivateData->Signature = PCAT_PCI_ROOT_BRIDGE_SIGNATURE;\r
94 PrivateData->Handle = NULL;\r
95 PrivateData->DevicePath = NULL;\r
96 InitializeListHead (&PrivateData->MapInfo);\r
97\r
98 //\r
99 // Initialize the PCI root bridge number and the bus range for that root bridge\r
100 //\r
101 PrivateData->RootBridgeNumber = (UINT32)PciRootBridgeIndex;\r
102 PrivateData->PrimaryBus = (UINT32)PrimaryBusIndex;\r
103 PrivateData->SubordinateBus = (UINT32)PrimaryBusIndex;\r
104\r
105 PrivateData->IoBase = 0xffffffff;\r
106 PrivateData->MemBase = 0xffffffff;\r
8e53d246 107 PrivateData->Mem32Base = 0xffffffffffffffffULL;\r
108 PrivateData->Pmem32Base = 0xffffffffffffffffULL;\r
109 PrivateData->Mem64Base = 0xffffffffffffffffULL;\r
110 PrivateData->Pmem64Base = 0xffffffffffffffffULL;\r
c69dd9df 111\r
112 //\r
113 // The default mechanism for performing PCI Configuration cycles is to \r
114 // use the I/O ports at 0xCF8 and 0xCFC. This is only used for IA-32.\r
115 // IPF uses SAL calls to perform PCI COnfiguration cycles\r
116 //\r
117 PrivateData->PciAddress = 0xCF8;\r
118 PrivateData->PciData = 0xCFC;\r
119\r
120 //\r
121 // Get the physical I/O base for performing PCI I/O cycles\r
122 // For IA-32, this is always 0, because IA-32 has IN and OUT instructions\r
123 // For IPF, a SAL call is made to retrieve the base address for PCI I/O cycles\r
124 //\r
125 Status = PcatRootBridgeIoGetIoPortMapping (\r
126 &PrivateData->PhysicalIoBase, \r
127 &PrivateData->PhysicalMemoryBase\r
128 );\r
129 if (EFI_ERROR (Status)) {\r
130 goto Done;\r
131 }\r
132\r
133 //\r
134 // Get PCI Express Base Address\r
135 //\r
136 PrivateData->PciExpressBaseAddress = GetPciExpressBaseAddressForRootBridge (PciSegmentIndex, PciRootBridgeIndex);\r
137 if (PrivateData->PciExpressBaseAddress != 0) {\r
138 DEBUG ((EFI_D_ERROR, "PCIE Base - 0x%lx\n", PrivateData->PciExpressBaseAddress));\r
139 }\r
140\r
141 //\r
142 // Create a lock for performing PCI Configuration cycles\r
143 //\r
144 EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL);\r
145\r
146 //\r
147 // Initialize the attributes for this PCI root bridge\r
148 //\r
149 PrivateData->Attributes = 0;\r
150\r
151 //\r
152 // Build the EFI Device Path Protocol instance for this PCI Root Bridge\r
153 //\r
2b7d16cf 154 Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (BOOLEAN)((PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE));\r
c69dd9df 155 if (EFI_ERROR (Status)) {\r
156 goto Done;\r
157 }\r
158\r
159 //\r
160 // Build the PCI Root Bridge I/O Protocol instance for this PCI Root Bridge\r
161 //\r
162 Status = PcatRootBridgeIoConstructor (&PrivateData->Io, PciSegmentIndex);\r
163 if (EFI_ERROR (Status)) {\r
164 goto Done;\r
165 }\r
166 \r
167 //\r
168 // Scan all the PCI devices on the primary bus of the PCI root bridge\r
169 //\r
170 for (Device = 0, NumberOfPciDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
171 \r
172 for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {\r
173\r
174 //\r
175 // Compute the PCI configuration address of the PCI device to probe\r
176 //\r
177 Address = EFI_PCI_ADDRESS (PrimaryBusIndex, Device, Function, 0);\r
178\r
179 //\r
180 // Read the Vendor ID from the PCI Configuration Header\r
181 //\r
182 Status = PrivateData->Io.Pci.Read (\r
183 &PrivateData->Io, \r
184 EfiPciWidthUint16, \r
185 Address, \r
186 sizeof (VendorId), \r
187 &VendorId\r
188 );\r
189 if ((EFI_ERROR (Status)) || ((VendorId == 0xffff) && (Function == 0))) {\r
190 //\r
191 // If the PCI Configuration Read fails, or a PCI device does not exist, then \r
192 // skip this entire PCI device\r
193 //\r
194 break;\r
195 }\r
196 if (VendorId == 0xffff) {\r
197 //\r
198 // If PCI function != 0, VendorId == 0xFFFF, we continue to search PCI function.\r
199 //\r
200 continue;\r
201 }\r
202\r
203 //\r
204 // Read the entire PCI Configuration Header\r
205 //\r
206 Status = PrivateData->Io.Pci.Read (\r
207 &PrivateData->Io, \r
208 EfiPciWidthUint32, \r
209 Address, \r
210 sizeof (PciConfigurationHeader) / sizeof (UINT32), \r
211 &PciConfigurationHeader\r
212 );\r
213 if (EFI_ERROR (Status)) {\r
214 //\r
215 // If the entire PCI Configuration Header can not be read, then skip this entire PCI device\r
216 //\r
217 break;\r
218 }\r
219\r
8e53d246 220\r
c69dd9df 221 //\r
222 // Increment the number of PCI device found on the primary bus of the PCI root bridge\r
223 //\r
224 NumberOfPciDevices++;\r
225\r
226 //\r
227 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header\r
228 //\r
229 if (PciConfigurationHeader.Hdr.Command & 0x20) {\r
230 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
231 }\r
232\r
233 //\r
234 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number\r
235 //\r
236 if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {\r
237 //\r
238 // Get the Bus range that the PPB is decoding\r
239 //\r
240 if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {\r
241 //\r
242 // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's\r
243 // current subordinate bus number, then update the PCI root bridge's subordinate bus number \r
244 //\r
245 PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;\r
246 }\r
247\r
248 //\r
249 // Get the I/O range that the PPB is decoding\r
250 //\r
251 Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;\r
252 Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;\r
253 Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;\r
254 if (Value == 0x01) {\r
255 Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);\r
256 Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);\r
257 }\r
258 if (Base < Limit) {\r
259 if (PrivateData->IoBase > Base) {\r
260 PrivateData->IoBase = Base;\r
261 }\r
262 if (PrivateData->IoLimit < Limit) {\r
263 PrivateData->IoLimit = Limit;\r
264 }\r
265 }\r
266\r
267 //\r
268 // Get the Memory range that the PPB is decoding\r
269 //\r
270 Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;\r
271 Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;\r
272 if (Base < Limit) {\r
273 if (PrivateData->MemBase > Base) {\r
274 PrivateData->MemBase = Base;\r
275 }\r
276 if (PrivateData->MemLimit < Limit) {\r
277 PrivateData->MemLimit = Limit;\r
278 }\r
279 if (PrivateData->Mem32Base > Base) {\r
280 PrivateData->Mem32Base = Base;\r
281 }\r
282 if (PrivateData->Mem32Limit < Limit) {\r
283 PrivateData->Mem32Limit = Limit;\r
284 }\r
285 }\r
286\r
287 //\r
288 // Get the Prefetchable Memory range that the PPB is decoding\r
289 //\r
290 Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;\r
291 Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;\r
292 Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;\r
293 if (Value == 0x01) {\r
294 Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);\r
295 Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);\r
296 }\r
297 if (Base < Limit) {\r
298 if (PrivateData->MemBase > Base) {\r
299 PrivateData->MemBase = Base;\r
300 }\r
301 if (PrivateData->MemLimit < Limit) {\r
302 PrivateData->MemLimit = Limit;\r
303 }\r
304 if (Value == 0x00) {\r
305 if (PrivateData->Pmem32Base > Base) {\r
306 PrivateData->Pmem32Base = Base;\r
307 }\r
308 if (PrivateData->Pmem32Limit < Limit) {\r
309 PrivateData->Pmem32Limit = Limit;\r
310 }\r
311 }\r
312 if (Value == 0x01) {\r
313 if (PrivateData->Pmem64Base > Base) {\r
314 PrivateData->Pmem64Base = Base;\r
315 }\r
316 if (PrivateData->Pmem64Limit < Limit) {\r
317 PrivateData->Pmem64Limit = Limit;\r
318 }\r
319 }\r
320 }\r
321\r
322 //\r
323 // Look at the PPB Configuration for legacy decoding attributes\r
324 //\r
325 if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {\r
326 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
327 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
328 }\r
329 if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {\r
330 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
331 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
332 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
333 }\r
334\r
335 } else {\r
336 //\r
337 // Parse the BARs of the PCI device to determine what I/O Ranges,\r
338 // Memory Ranges, and Prefetchable Memory Ranges the device is decoding\r
339 //\r
340 if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {\r
341 Status = PcatPciRootBridgeParseBars (\r
342 PrivateData, \r
343 PciConfigurationHeader.Hdr.Command,\r
344 PrimaryBusIndex, \r
345 Device, \r
346 Function\r
347 );\r
348 }\r
349\r
350 //\r
351 // See if the PCI device is an IDE controller\r
352 //\r
353 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&\r
354 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {\r
355 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {\r
356 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
357 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
358 }\r
359 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {\r
360 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
361 }\r
362 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {\r
363 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
364 }\r
365 }\r
366\r
367 //\r
368 // See if the PCI device is a legacy VGA controller\r
369 //\r
370 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&\r
371 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {\r
372 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
373 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
374 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
375 }\r
376\r
377 //\r
378 // See if the PCI device is a standard VGA controller\r
379 //\r
380 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&\r
381 PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {\r
382 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
383 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
384 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
385 }\r
386\r
387 //\r
388 // See if the PCI Device is a PCI - ISA or PCI - EISA \r
389 // or ISA_POSITIVIE_DECODE Bridge device\r
390 //\r
391 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {\r
392 if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||\r
393 PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || \r
394 PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {\r
395 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
396 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
397\r
398 if (PrivateData->MemBase > 0xa0000) {\r
399 PrivateData->MemBase = 0xa0000;\r
400 }\r
401 if (PrivateData->MemLimit < 0xbffff) {\r
402 PrivateData->MemLimit = 0xbffff;\r
403 }\r
404 }\r
405 }\r
406 }\r
407\r
408 //\r
409 // If this device is not a multi function device, then skip the rest of this PCI device\r
410 //\r
411 if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {\r
412 break;\r
413 }\r
414 }\r
415 }\r
416\r
417 //\r
418 // After scanning all the PCI devices on the PCI root bridge's primary bus, update the \r
419 // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate\r
420 // bus number + 1.\r
421 //\r
422 PrimaryBusIndex = PrivateData->SubordinateBus + 1;\r
423\r
424 //\r
425 // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge\r
426 // exists.\r
427 //\r
428 if (NumberOfPciDevices > 0) {\r
429\r
430 //\r
431 // Adjust the I/O range used for bounds checking for the legacy decoding attributed\r
432 //\r
433 if (PrivateData->Attributes & 0x7f) {\r
434 PrivateData->IoBase = 0;\r
435 if (PrivateData->IoLimit < 0xffff) {\r
436 PrivateData->IoLimit = 0xffff;\r
437 }\r
438 }\r
439\r
440 //\r
441 // Adjust the Memory range used for bounds checking for the legacy decoding attributed\r
442 //\r
443 if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {\r
444 if (PrivateData->MemBase > 0xa0000) {\r
445 PrivateData->MemBase = 0xa0000;\r
446 }\r
447 if (PrivateData->MemLimit < 0xbffff) {\r
448 PrivateData->MemLimit = 0xbffff;\r
449 }\r
450 }\r
451\r
452 //\r
453 // Build ACPI descriptors for the resources on the PCI Root Bridge\r
454 //\r
455 Status = ConstructConfiguration(PrivateData);\r
456 ASSERT_EFI_ERROR (Status);\r
457\r
458 //\r
459 // Create the handle for this PCI Root Bridge \r
460 //\r
461 Status = gBS->InstallMultipleProtocolInterfaces (\r
462 &PrivateData->Handle, \r
463 &gEfiDevicePathProtocolGuid,\r
464 PrivateData->DevicePath,\r
465 &gEfiPciRootBridgeIoProtocolGuid,\r
466 &PrivateData->Io,\r
467 NULL\r
468 );\r
469 ASSERT_EFI_ERROR (Status);\r
470\r
471 //\r
472 // Contruct DeviceIoProtocol\r
473 //\r
474 Status = DeviceIoConstructor (\r
475 PrivateData->Handle,\r
476 &PrivateData->Io,\r
477 PrivateData->DevicePath,\r
478 (UINT16)PrivateData->PrimaryBus,\r
479 (UINT16)PrivateData->SubordinateBus\r
480 );\r
481 ASSERT_EFI_ERROR (Status);\r
482\r
483 //\r
484 // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table\r
485 //\r
486 Status = ScanPciRootBridgeForRoms(&PrivateData->Io);\r
487\r
488 //\r
489 // Increment the index for the next PCI Root Bridge\r
490 //\r
491 PciRootBridgeIndex++;\r
492\r
493 } else {\r
494\r
495 //\r
496 // If no PCI Root Bridges were found on the current PCI segment, then exit\r
497 //\r
498 if (NumberOfPciRootBridges == 0) {\r
499 Status = EFI_SUCCESS;\r
500 goto Done;\r
501 }\r
502\r
503 }\r
504\r
505 //\r
506 // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then\r
507 // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0\r
508 // Otherwise, the search is continued on the next PCI Root Bridge\r
509 //\r
510 if (PrimaryBusIndex > PCI_MAX_BUS) {\r
511 PciSegmentIndex++;\r
512 NumberOfPciRootBridges = 0;\r
513 PrimaryBusIndex = 0;\r
514 } else {\r
515 NumberOfPciRootBridges++;\r
516 }\r
517\r
518 }\r
519\r
520 return EFI_SUCCESS;\r
521\r
522Done:\r
523 //\r
524 // Clean up memory allocated for the PCI Root Bridge that was searched but not created.\r
525 //\r
526 if (PrivateData) {\r
527 if (PrivateData->DevicePath) {\r
528 gBS->FreePool(PrivateData->DevicePath);\r
529 }\r
530 gBS->FreePool (PrivateData);\r
531 }\r
532\r
533 //\r
534 // If no PCI Root Bridges were discovered, then return the error condition from scanning the\r
535 // first PCI Root Bridge\r
536 //\r
537 if (PciRootBridgeIndex == 0) {\r
538 return Status;\r
539 }\r
540\r
541 return EFI_SUCCESS;\r
542}\r
543\r
544EFI_STATUS \r
545ConstructConfiguration(\r
546 IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData\r
547 )\r
548/*++\r
549\r
550Routine Description:\r
551\r
552Arguments:\r
553\r
554Returns:\r
555\r
556 None\r
557\r
558--*/\r
559 \r
560{\r
561 EFI_STATUS Status;\r
562 UINT8 NumConfig;\r
563 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
564 EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;\r
565\r
566 NumConfig = 0;\r
567 PrivateData->Configuration = NULL;\r
568\r
569 if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {\r
570 NumConfig++;\r
571 }\r
572 if (PrivateData->IoLimit >= PrivateData->IoBase) {\r
573 NumConfig++;\r
574 }\r
575 if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {\r
576 NumConfig++;\r
577 }\r
578 if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {\r
579 NumConfig++;\r
580 }\r
581 if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {\r
582 NumConfig++;\r
583 }\r
584 if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {\r
585 NumConfig++;\r
586 }\r
587\r
588 if ( NumConfig == 0 ) {\r
589\r
590 //\r
591 // If there is no resource request\r
592 //\r
593 Status = gBS->AllocatePool (\r
594 EfiBootServicesData, \r
595 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
8e53d246 596 (VOID **)&PrivateData->Configuration\r
c69dd9df 597 );\r
598 if (EFI_ERROR (Status )) {\r
599 return Status;\r
600 }\r
601\r
602 Configuration = PrivateData->Configuration;\r
603 \r
604 ZeroMem (\r
605 Configuration, \r
606 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) \r
607 );\r
608 \r
609 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
610 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
611 Configuration++;\r
612\r
613 ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);\r
614 ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
615 ConfigurationEnd->Checksum = 0;\r
616 }\r
617\r
618 //\r
619 // If there is at least one type of resource request,\r
620 // allocate a acpi resource node \r
621 //\r
622 Status = gBS->AllocatePool (\r
623 EfiBootServicesData, \r
624 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
8e53d246 625 (VOID **)&PrivateData->Configuration\r
c69dd9df 626 );\r
627 if (EFI_ERROR (Status )) {\r
628 return Status;\r
629 }\r
630 \r
631 Configuration = PrivateData->Configuration;\r
632\r
633 ZeroMem (\r
634 Configuration, \r
635 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
636 );\r
637\r
638 if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {\r
639 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
640 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
641 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
642 Configuration->SpecificFlag = 0; \r
643 Configuration->AddrRangeMin = PrivateData->PrimaryBus;\r
644 Configuration->AddrRangeMax = PrivateData->SubordinateBus;\r
645 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
646 Configuration++;\r
647 }\r
648 //\r
649 // Deal with io aperture\r
650 //\r
651 if (PrivateData->IoLimit >= PrivateData->IoBase) {\r
652 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
653 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
654 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
655 Configuration->SpecificFlag = 1; //non ISA range\r
656 Configuration->AddrRangeMin = PrivateData->IoBase;\r
657 Configuration->AddrRangeMax = PrivateData->IoLimit;\r
658 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
659 Configuration++;\r
660 }\r
661\r
662 //\r
663 // Deal with mem32 aperture\r
664 //\r
665 if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {\r
666 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
667 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
668 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
669 Configuration->SpecificFlag = 0; //Nonprefechable\r
670 Configuration->AddrSpaceGranularity = 32; //32 bit\r
671 Configuration->AddrRangeMin = PrivateData->Mem32Base;\r
672 Configuration->AddrRangeMax = PrivateData->Mem32Limit;\r
673 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
674 Configuration++;\r
675 } \r
676\r
677 //\r
678 // Deal with Pmem32 aperture\r
679 //\r
680 if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {\r
681 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
682 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
683 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
684 Configuration->SpecificFlag = 0x6; //prefechable\r
685 Configuration->AddrSpaceGranularity = 32; //32 bit\r
686 Configuration->AddrRangeMin = PrivateData->Pmem32Base;\r
687 Configuration->AddrRangeMax = PrivateData->Pmem32Limit;\r
688 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
689 Configuration++;\r
690 }\r
691\r
692 //\r
693 // Deal with mem64 aperture\r
694 //\r
695 if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {\r
696 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
697 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
698 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
699 Configuration->SpecificFlag = 0; //nonprefechable\r
700 Configuration->AddrSpaceGranularity = 64; //32 bit\r
701 Configuration->AddrRangeMin = PrivateData->Mem64Base;\r
702 Configuration->AddrRangeMax = PrivateData->Mem64Limit;\r
703 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
704 Configuration++;\r
705 }\r
706\r
707 //\r
708 // Deal with Pmem64 aperture\r
709 //\r
710 if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {\r
711 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
712 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
713 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
714 Configuration->SpecificFlag = 0x06; //prefechable\r
715 Configuration->AddrSpaceGranularity = 64; //32 bit\r
716 Configuration->AddrRangeMin = PrivateData->Pmem64Base;\r
717 Configuration->AddrRangeMax = PrivateData->Pmem64Limit;\r
718 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
719 Configuration++;\r
720 }\r
721\r
722 //\r
723 // put the checksum\r
724 //\r
725 ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);\r
726 ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
727 ConfigurationEnd->Checksum = 0;\r
728\r
729 return EFI_SUCCESS;\r
730}\r
731\r
732EFI_STATUS \r
733PcatPciRootBridgeBarExisted (\r
734 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
735 IN UINT64 Address,\r
736 OUT UINT32 *OriginalValue,\r
737 OUT UINT32 *Value\r
738 ) \r
739/*++\r
740\r
741Routine Description:\r
742\r
743Arguments:\r
744\r
745Returns:\r
746\r
747 None\r
748\r
749--*/\r
750{\r
751 EFI_STATUS Status;\r
752 UINT32 AllOnes;\r
753 EFI_TPL OldTpl;\r
754\r
755 //\r
756 // Preserve the original value\r
757 //\r
758 Status = PrivateData->Io.Pci.Read (\r
759 &PrivateData->Io, \r
760 EfiPciWidthUint32, \r
761 Address, \r
762 1, \r
763 OriginalValue\r
764 );\r
765\r
766 //\r
767 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
768 //\r
769 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
770\r
771 AllOnes = 0xffffffff;\r
772\r
773 Status = PrivateData->Io.Pci.Write (\r
774 &PrivateData->Io, \r
775 EfiPciWidthUint32, \r
776 Address, \r
777 1, \r
778 &AllOnes\r
779 );\r
780 Status = PrivateData->Io.Pci.Read (\r
781 &PrivateData->Io, \r
782 EfiPciWidthUint32, \r
783 Address, \r
784 1, \r
785 Value\r
786 );\r
787\r
788 //\r
789 //Write back the original value\r
790 //\r
791 Status = PrivateData->Io.Pci.Write (\r
792 &PrivateData->Io, \r
793 EfiPciWidthUint32, \r
794 Address, \r
795 1, \r
796 OriginalValue\r
797 );\r
798\r
799 //\r
800 // Restore TPL to its original level\r
801 //\r
802 gBS->RestoreTPL (OldTpl);\r
803\r
804 if ( *Value == 0 ) {\r
805 return EFI_DEVICE_ERROR;\r
806 }\r
2b7d16cf 807 return Status;\r
c69dd9df 808}\r
809\r
810EFI_STATUS\r
811PcatPciRootBridgeParseBars (\r
812 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
813 IN UINT16 Command,\r
814 IN UINTN Bus,\r
815 IN UINTN Device,\r
816 IN UINTN Function\r
817 )\r
818/*++\r
819\r
820Routine Description:\r
821\r
822Arguments:\r
823\r
824Returns:\r
825\r
826 None\r
827\r
828--*/\r
829{\r
830 EFI_STATUS Status;\r
831 UINT64 Address;\r
832 UINT32 OriginalValue;\r
833 UINT32 Value;\r
834 UINT32 OriginalUpperValue;\r
835 UINT32 UpperValue;\r
836 UINT64 Mask;\r
837 UINTN Offset;\r
838 UINT64 Base;\r
839 UINT64 Length;\r
840 UINT64 Limit;\r
841\r
842 for (Offset = 0x10; Offset < 0x28; Offset += 4) {\r
843 Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);\r
844 Status = PcatPciRootBridgeBarExisted (\r
845 PrivateData,\r
846 Address,\r
847 &OriginalValue,\r
848 &Value\r
849 );\r
850\r
851 if (!EFI_ERROR (Status )) {\r
852 if ( Value & 0x01 ) { \r
853 if (Command & 0x0001) {\r
854 //\r
855 //Device I/Os\r
856 //\r
857 Mask = 0xfffffffc;\r
858 Base = OriginalValue & Mask;\r
859 Length = ((~(Value & Mask)) & Mask) + 0x04;\r
860 if (!(Value & 0xFFFF0000)){\r
861 Length &= 0x0000FFFF;\r
862 }\r
863 Limit = Base + Length - 1;\r
864\r
865 if (Base < Limit) {\r
866 if (PrivateData->IoBase > Base) {\r
867 PrivateData->IoBase = (UINT32)Base;\r
868 }\r
869 if (PrivateData->IoLimit < Limit) {\r
870 PrivateData->IoLimit = (UINT32)Limit;\r
871 }\r
872 }\r
873 }\r
874 \r
875 } else {\r
876\r
877 if (Command & 0x0002) {\r
878\r
879 Mask = 0xfffffff0;\r
880 Base = OriginalValue & Mask;\r
881 Length = Value & Mask;\r
882 \r
883 if ((Value & 0x07) != 0x04) {\r
884 Length = ((~Length) + 1) & 0xffffffff;\r
885 } else {\r
886 Offset += 4; \r
887 Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);\r
888\r
889 Status = PcatPciRootBridgeBarExisted (\r
890 PrivateData,\r
891 Address,\r
892 &OriginalUpperValue,\r
893 &UpperValue\r
894 );\r
895\r
896 Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);\r
897 Length = Length | LShiftU64((UINT64)UpperValue,32);\r
898 Length = (~Length) + 1;\r
899 }\r
900\r
901 Limit = Base + Length - 1;\r
902\r
903 if (Base < Limit) {\r
904 if (PrivateData->MemBase > Base) {\r
905 PrivateData->MemBase = Base;\r
906 }\r
907 if (PrivateData->MemLimit < Limit) {\r
908 PrivateData->MemLimit = Limit;\r
909 }\r
910\r
911 switch (Value &0x07) {\r
912 case 0x00: ////memory space; anywhere in 32 bit address space\r
913 if (Value & 0x08) {\r
914 if (PrivateData->Pmem32Base > Base) {\r
915 PrivateData->Pmem32Base = Base;\r
916 }\r
917 if (PrivateData->Pmem32Limit < Limit) {\r
918 PrivateData->Pmem32Limit = Limit;\r
919 }\r
920 } else {\r
921 if (PrivateData->Mem32Base > Base) {\r
922 PrivateData->Mem32Base = Base;\r
923 }\r
924 if (PrivateData->Mem32Limit < Limit) {\r
925 PrivateData->Mem32Limit = Limit;\r
926 }\r
927 }\r
928 break;\r
929 case 0x04: //memory space; anywhere in 64 bit address space\r
930 if (Value & 0x08) {\r
931 if (PrivateData->Pmem64Base > Base) {\r
932 PrivateData->Pmem64Base = Base;\r
933 }\r
934 if (PrivateData->Pmem64Limit < Limit) {\r
935 PrivateData->Pmem64Limit = Limit;\r
936 }\r
937 } else {\r
938 if (PrivateData->Mem64Base > Base) {\r
939 PrivateData->Mem64Base = Base;\r
940 }\r
941 if (PrivateData->Mem64Limit < Limit) {\r
942 PrivateData->Mem64Limit = Limit;\r
943 }\r
944 }\r
945 break;\r
946 }\r
947 }\r
948 }\r
949 }\r
950 }\r
951 }\r
952 return EFI_SUCCESS;\r
953}\r
954\r
955UINT64\r
956GetPciExpressBaseAddressForRootBridge (\r
957 IN UINTN HostBridgeNumber,\r
958 IN UINTN RootBridgeNumber\r
959 )\r
960/*++\r
961\r
962Routine Description:\r
963 This routine is to get PciExpress Base Address for this RootBridge\r
964\r
965Arguments:\r
966 HostBridgeNumber - The number of HostBridge\r
967 RootBridgeNumber - The number of RootBridge\r
968 \r
969Returns:\r
970 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge\r
971\r
972--*/\r
973{\r
974 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;\r
975 UINTN BufferSize;\r
976 UINT32 Index;\r
977 UINT32 Number;\r
c69dd9df 978 EFI_PEI_HOB_POINTERS GuidHob;\r
979\r
c69dd9df 980 //\r
981 // Get PciExpressAddressInfo Hob\r
982 //\r
983 PciExpressBaseAddressInfo = NULL;\r
984 BufferSize = 0;\r
8e53d246 985 GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);\r
c69dd9df 986 if (GuidHob.Raw != NULL) {\r
987 PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);\r
988 BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);\r
989 } else {\r
990 return 0;\r
991 }\r
992\r
993 //\r
994 // Search the PciExpress Base Address in the Hob for current RootBridge\r
995 //\r
996 Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));\r
997 for (Index = 0; Index < Number; Index++) {\r
998 if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&\r
999 (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {\r
1000 return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;\r
1001 }\r
1002 }\r
1003\r
1004 //\r
1005 // Do not find the PciExpress Base Address in the Hob\r
1006 //\r
1007 return 0;\r
1008}\r
1009\r