]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/PciRootBridgeNoEnumerationDxe/PcatPciRootBridge.c
Porting Duet module from EDKI to EDKII
[mirror_edk2.git] / DuetPkg / PciRootBridgeNoEnumerationDxe / PcatPciRootBridge.c
CommitLineData
c69dd9df 1/*++\r
2\r
3Copyright (c) 2005 - 2006, Intel Corporation \r
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
65 Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &gCpuIo);\r
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
82 &PrivateData\r
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
107 PrivateData->Mem32Base = 0xffffffffffffffff;\r
108 PrivateData->Pmem32Base = 0xffffffffffffffff;\r
109 PrivateData->Mem64Base = 0xffffffffffffffff;\r
110 PrivateData->Pmem64Base = 0xffffffffffffffff;\r
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
154 Status = PcatRootBridgeDevicePathConstructor (&PrivateData->DevicePath, PciRootBridgeIndex, (PrivateData->PciExpressBaseAddress != 0) ? TRUE : FALSE);\r
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
220 //\r
221 // Increment the number of PCI device found on the primary bus of the PCI root bridge\r
222 //\r
223 NumberOfPciDevices++;\r
224\r
225 //\r
226 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header\r
227 //\r
228 if (PciConfigurationHeader.Hdr.Command & 0x20) {\r
229 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
230 }\r
231\r
232 //\r
233 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number\r
234 //\r
235 if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {\r
236 //\r
237 // Get the Bus range that the PPB is decoding\r
238 //\r
239 if (PciConfigurationHeader.Bridge.SubordinateBus > PrivateData->SubordinateBus) {\r
240 //\r
241 // If the suborinate bus number of the PCI-PCI bridge is greater than the PCI root bridge's\r
242 // current subordinate bus number, then update the PCI root bridge's subordinate bus number \r
243 //\r
244 PrivateData->SubordinateBus = PciConfigurationHeader.Bridge.SubordinateBus;\r
245 }\r
246\r
247 //\r
248 // Get the I/O range that the PPB is decoding\r
249 //\r
250 Value = PciConfigurationHeader.Bridge.IoBase & 0x0f;\r
251 Base = ((UINT32)PciConfigurationHeader.Bridge.IoBase & 0xf0) << 8;\r
252 Limit = (((UINT32)PciConfigurationHeader.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;\r
253 if (Value == 0x01) {\r
254 Base |= ((UINT32)PciConfigurationHeader.Bridge.IoBaseUpper16 << 16);\r
255 Limit |= ((UINT32)PciConfigurationHeader.Bridge.IoLimitUpper16 << 16);\r
256 }\r
257 if (Base < Limit) {\r
258 if (PrivateData->IoBase > Base) {\r
259 PrivateData->IoBase = Base;\r
260 }\r
261 if (PrivateData->IoLimit < Limit) {\r
262 PrivateData->IoLimit = Limit;\r
263 }\r
264 }\r
265\r
266 //\r
267 // Get the Memory range that the PPB is decoding\r
268 //\r
269 Base = ((UINT32)PciConfigurationHeader.Bridge.MemoryBase & 0xfff0) << 16;\r
270 Limit = (((UINT32)PciConfigurationHeader.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;\r
271 if (Base < Limit) {\r
272 if (PrivateData->MemBase > Base) {\r
273 PrivateData->MemBase = Base;\r
274 }\r
275 if (PrivateData->MemLimit < Limit) {\r
276 PrivateData->MemLimit = Limit;\r
277 }\r
278 if (PrivateData->Mem32Base > Base) {\r
279 PrivateData->Mem32Base = Base;\r
280 }\r
281 if (PrivateData->Mem32Limit < Limit) {\r
282 PrivateData->Mem32Limit = Limit;\r
283 }\r
284 }\r
285\r
286 //\r
287 // Get the Prefetchable Memory range that the PPB is decoding\r
288 //\r
289 Value = PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0x0f;\r
290 Base = ((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;\r
291 Limit = (((UINT32)PciConfigurationHeader.Bridge.PrefetchableMemoryLimit & 0xfff0) << 16) | 0xffffff;\r
292 if (Value == 0x01) {\r
293 Base |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableBaseUpper32,32);\r
294 Limit |= LShiftU64((UINT64)PciConfigurationHeader.Bridge.PrefetchableLimitUpper32,32);\r
295 }\r
296 if (Base < Limit) {\r
297 if (PrivateData->MemBase > Base) {\r
298 PrivateData->MemBase = Base;\r
299 }\r
300 if (PrivateData->MemLimit < Limit) {\r
301 PrivateData->MemLimit = Limit;\r
302 }\r
303 if (Value == 0x00) {\r
304 if (PrivateData->Pmem32Base > Base) {\r
305 PrivateData->Pmem32Base = Base;\r
306 }\r
307 if (PrivateData->Pmem32Limit < Limit) {\r
308 PrivateData->Pmem32Limit = Limit;\r
309 }\r
310 }\r
311 if (Value == 0x01) {\r
312 if (PrivateData->Pmem64Base > Base) {\r
313 PrivateData->Pmem64Base = Base;\r
314 }\r
315 if (PrivateData->Pmem64Limit < Limit) {\r
316 PrivateData->Pmem64Limit = Limit;\r
317 }\r
318 }\r
319 }\r
320\r
321 //\r
322 // Look at the PPB Configuration for legacy decoding attributes\r
323 //\r
324 if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {\r
325 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
326 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
327 }\r
328 if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {\r
329 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
330 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
331 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
332 }\r
333\r
334 } else {\r
335 //\r
336 // Parse the BARs of the PCI device to determine what I/O Ranges,\r
337 // Memory Ranges, and Prefetchable Memory Ranges the device is decoding\r
338 //\r
339 if ((PciConfigurationHeader.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {\r
340 Status = PcatPciRootBridgeParseBars (\r
341 PrivateData, \r
342 PciConfigurationHeader.Hdr.Command,\r
343 PrimaryBusIndex, \r
344 Device, \r
345 Function\r
346 );\r
347 }\r
348\r
349 //\r
350 // See if the PCI device is an IDE controller\r
351 //\r
352 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&\r
353 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {\r
354 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {\r
355 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
356 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
357 }\r
358 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {\r
359 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;\r
360 }\r
361 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {\r
362 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;\r
363 }\r
364 }\r
365\r
366 //\r
367 // See if the PCI device is a legacy VGA controller\r
368 //\r
369 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&\r
370 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {\r
371 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
372 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
373 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
374 }\r
375\r
376 //\r
377 // See if the PCI device is a standard VGA controller\r
378 //\r
379 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&\r
380 PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {\r
381 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;\r
382 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;\r
383 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;\r
384 }\r
385\r
386 //\r
387 // See if the PCI Device is a PCI - ISA or PCI - EISA \r
388 // or ISA_POSITIVIE_DECODE Bridge device\r
389 //\r
390 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x06) {\r
391 if (PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ||\r
392 PciConfigurationHeader.Hdr.ClassCode[1] == 0x02 || \r
393 PciConfigurationHeader.Hdr.ClassCode[1] == 0x80 ) {\r
394 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;\r
395 PrivateData->Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
396\r
397 if (PrivateData->MemBase > 0xa0000) {\r
398 PrivateData->MemBase = 0xa0000;\r
399 }\r
400 if (PrivateData->MemLimit < 0xbffff) {\r
401 PrivateData->MemLimit = 0xbffff;\r
402 }\r
403 }\r
404 }\r
405 }\r
406\r
407 //\r
408 // If this device is not a multi function device, then skip the rest of this PCI device\r
409 //\r
410 if (Function == 0 && !(PciConfigurationHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION)) {\r
411 break;\r
412 }\r
413 }\r
414 }\r
415\r
416 //\r
417 // After scanning all the PCI devices on the PCI root bridge's primary bus, update the \r
418 // Primary Bus Number for the next PCI root bridge to be this PCI root bridge's subordinate\r
419 // bus number + 1.\r
420 //\r
421 PrimaryBusIndex = PrivateData->SubordinateBus + 1;\r
422\r
423 //\r
424 // If at least one PCI device was found on the primary bus of this PCI root bridge, then the PCI root bridge\r
425 // exists.\r
426 //\r
427 if (NumberOfPciDevices > 0) {\r
428\r
429 //\r
430 // Adjust the I/O range used for bounds checking for the legacy decoding attributed\r
431 //\r
432 if (PrivateData->Attributes & 0x7f) {\r
433 PrivateData->IoBase = 0;\r
434 if (PrivateData->IoLimit < 0xffff) {\r
435 PrivateData->IoLimit = 0xffff;\r
436 }\r
437 }\r
438\r
439 //\r
440 // Adjust the Memory range used for bounds checking for the legacy decoding attributed\r
441 //\r
442 if (PrivateData->Attributes & EFI_PCI_ATTRIBUTE_VGA_MEMORY) {\r
443 if (PrivateData->MemBase > 0xa0000) {\r
444 PrivateData->MemBase = 0xa0000;\r
445 }\r
446 if (PrivateData->MemLimit < 0xbffff) {\r
447 PrivateData->MemLimit = 0xbffff;\r
448 }\r
449 }\r
450\r
451 //\r
452 // Build ACPI descriptors for the resources on the PCI Root Bridge\r
453 //\r
454 Status = ConstructConfiguration(PrivateData);\r
455 ASSERT_EFI_ERROR (Status);\r
456\r
457 //\r
458 // Create the handle for this PCI Root Bridge \r
459 //\r
460 Status = gBS->InstallMultipleProtocolInterfaces (\r
461 &PrivateData->Handle, \r
462 &gEfiDevicePathProtocolGuid,\r
463 PrivateData->DevicePath,\r
464 &gEfiPciRootBridgeIoProtocolGuid,\r
465 &PrivateData->Io,\r
466 NULL\r
467 );\r
468 ASSERT_EFI_ERROR (Status);\r
469\r
470 //\r
471 // Contruct DeviceIoProtocol\r
472 //\r
473 Status = DeviceIoConstructor (\r
474 PrivateData->Handle,\r
475 &PrivateData->Io,\r
476 PrivateData->DevicePath,\r
477 (UINT16)PrivateData->PrimaryBus,\r
478 (UINT16)PrivateData->SubordinateBus\r
479 );\r
480 ASSERT_EFI_ERROR (Status);\r
481\r
482 //\r
483 // Scan this PCI Root Bridge for PCI Option ROMs and add them to the PCI Option ROM Table\r
484 //\r
485 Status = ScanPciRootBridgeForRoms(&PrivateData->Io);\r
486\r
487 //\r
488 // Increment the index for the next PCI Root Bridge\r
489 //\r
490 PciRootBridgeIndex++;\r
491\r
492 } else {\r
493\r
494 //\r
495 // If no PCI Root Bridges were found on the current PCI segment, then exit\r
496 //\r
497 if (NumberOfPciRootBridges == 0) {\r
498 Status = EFI_SUCCESS;\r
499 goto Done;\r
500 }\r
501\r
502 }\r
503\r
504 //\r
505 // If the PrimaryBusIndex is greater than the maximum allowable PCI bus number, then\r
506 // the PCI Segment Number is incremented, and the next segment is searched starting at Bus #0\r
507 // Otherwise, the search is continued on the next PCI Root Bridge\r
508 //\r
509 if (PrimaryBusIndex > PCI_MAX_BUS) {\r
510 PciSegmentIndex++;\r
511 NumberOfPciRootBridges = 0;\r
512 PrimaryBusIndex = 0;\r
513 } else {\r
514 NumberOfPciRootBridges++;\r
515 }\r
516\r
517 }\r
518\r
519 return EFI_SUCCESS;\r
520\r
521Done:\r
522 //\r
523 // Clean up memory allocated for the PCI Root Bridge that was searched but not created.\r
524 //\r
525 if (PrivateData) {\r
526 if (PrivateData->DevicePath) {\r
527 gBS->FreePool(PrivateData->DevicePath);\r
528 }\r
529 gBS->FreePool (PrivateData);\r
530 }\r
531\r
532 //\r
533 // If no PCI Root Bridges were discovered, then return the error condition from scanning the\r
534 // first PCI Root Bridge\r
535 //\r
536 if (PciRootBridgeIndex == 0) {\r
537 return Status;\r
538 }\r
539\r
540 return EFI_SUCCESS;\r
541}\r
542\r
543EFI_STATUS \r
544ConstructConfiguration(\r
545 IN OUT PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData\r
546 )\r
547/*++\r
548\r
549Routine Description:\r
550\r
551Arguments:\r
552\r
553Returns:\r
554\r
555 None\r
556\r
557--*/\r
558 \r
559{\r
560 EFI_STATUS Status;\r
561 UINT8 NumConfig;\r
562 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;\r
563 EFI_ACPI_END_TAG_DESCRIPTOR *ConfigurationEnd;\r
564\r
565 NumConfig = 0;\r
566 PrivateData->Configuration = NULL;\r
567\r
568 if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {\r
569 NumConfig++;\r
570 }\r
571 if (PrivateData->IoLimit >= PrivateData->IoBase) {\r
572 NumConfig++;\r
573 }\r
574 if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {\r
575 NumConfig++;\r
576 }\r
577 if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {\r
578 NumConfig++;\r
579 }\r
580 if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {\r
581 NumConfig++;\r
582 }\r
583 if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {\r
584 NumConfig++;\r
585 }\r
586\r
587 if ( NumConfig == 0 ) {\r
588\r
589 //\r
590 // If there is no resource request\r
591 //\r
592 Status = gBS->AllocatePool (\r
593 EfiBootServicesData, \r
594 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
595 &PrivateData->Configuration\r
596 );\r
597 if (EFI_ERROR (Status )) {\r
598 return Status;\r
599 }\r
600\r
601 Configuration = PrivateData->Configuration;\r
602 \r
603 ZeroMem (\r
604 Configuration, \r
605 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) \r
606 );\r
607 \r
608 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
609 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
610 Configuration++;\r
611\r
612 ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);\r
613 ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
614 ConfigurationEnd->Checksum = 0;\r
615 }\r
616\r
617 //\r
618 // If there is at least one type of resource request,\r
619 // allocate a acpi resource node \r
620 //\r
621 Status = gBS->AllocatePool (\r
622 EfiBootServicesData, \r
623 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),\r
624 &PrivateData->Configuration\r
625 );\r
626 if (EFI_ERROR (Status )) {\r
627 return Status;\r
628 }\r
629 \r
630 Configuration = PrivateData->Configuration;\r
631\r
632 ZeroMem (\r
633 Configuration, \r
634 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
635 );\r
636\r
637 if (PrivateData->SubordinateBus >= PrivateData->PrimaryBus) {\r
638 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
639 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
640 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;\r
641 Configuration->SpecificFlag = 0; \r
642 Configuration->AddrRangeMin = PrivateData->PrimaryBus;\r
643 Configuration->AddrRangeMax = PrivateData->SubordinateBus;\r
644 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
645 Configuration++;\r
646 }\r
647 //\r
648 // Deal with io aperture\r
649 //\r
650 if (PrivateData->IoLimit >= PrivateData->IoBase) {\r
651 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
652 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
653 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
654 Configuration->SpecificFlag = 1; //non ISA range\r
655 Configuration->AddrRangeMin = PrivateData->IoBase;\r
656 Configuration->AddrRangeMax = PrivateData->IoLimit;\r
657 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
658 Configuration++;\r
659 }\r
660\r
661 //\r
662 // Deal with mem32 aperture\r
663 //\r
664 if (PrivateData->Mem32Limit >= PrivateData->Mem32Base) {\r
665 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
666 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
667 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
668 Configuration->SpecificFlag = 0; //Nonprefechable\r
669 Configuration->AddrSpaceGranularity = 32; //32 bit\r
670 Configuration->AddrRangeMin = PrivateData->Mem32Base;\r
671 Configuration->AddrRangeMax = PrivateData->Mem32Limit;\r
672 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
673 Configuration++;\r
674 } \r
675\r
676 //\r
677 // Deal with Pmem32 aperture\r
678 //\r
679 if (PrivateData->Pmem32Limit >= PrivateData->Pmem32Base) {\r
680 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
681 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
682 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
683 Configuration->SpecificFlag = 0x6; //prefechable\r
684 Configuration->AddrSpaceGranularity = 32; //32 bit\r
685 Configuration->AddrRangeMin = PrivateData->Pmem32Base;\r
686 Configuration->AddrRangeMax = PrivateData->Pmem32Limit;\r
687 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
688 Configuration++;\r
689 }\r
690\r
691 //\r
692 // Deal with mem64 aperture\r
693 //\r
694 if (PrivateData->Mem64Limit >= PrivateData->Mem64Base) {\r
695 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
696 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
697 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
698 Configuration->SpecificFlag = 0; //nonprefechable\r
699 Configuration->AddrSpaceGranularity = 64; //32 bit\r
700 Configuration->AddrRangeMin = PrivateData->Mem64Base;\r
701 Configuration->AddrRangeMax = PrivateData->Mem64Limit;\r
702 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
703 Configuration++;\r
704 }\r
705\r
706 //\r
707 // Deal with Pmem64 aperture\r
708 //\r
709 if (PrivateData->Pmem64Limit >= PrivateData->Pmem64Base) {\r
710 Configuration->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
711 Configuration->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);\r
712 Configuration->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
713 Configuration->SpecificFlag = 0x06; //prefechable\r
714 Configuration->AddrSpaceGranularity = 64; //32 bit\r
715 Configuration->AddrRangeMin = PrivateData->Pmem64Base;\r
716 Configuration->AddrRangeMax = PrivateData->Pmem64Limit;\r
717 Configuration->AddrLen = Configuration->AddrRangeMax - Configuration->AddrRangeMin + 1;\r
718 Configuration++;\r
719 }\r
720\r
721 //\r
722 // put the checksum\r
723 //\r
724 ConfigurationEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);\r
725 ConfigurationEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
726 ConfigurationEnd->Checksum = 0;\r
727\r
728 return EFI_SUCCESS;\r
729}\r
730\r
731EFI_STATUS \r
732PcatPciRootBridgeBarExisted (\r
733 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
734 IN UINT64 Address,\r
735 OUT UINT32 *OriginalValue,\r
736 OUT UINT32 *Value\r
737 ) \r
738/*++\r
739\r
740Routine Description:\r
741\r
742Arguments:\r
743\r
744Returns:\r
745\r
746 None\r
747\r
748--*/\r
749{\r
750 EFI_STATUS Status;\r
751 UINT32 AllOnes;\r
752 EFI_TPL OldTpl;\r
753\r
754 //\r
755 // Preserve the original value\r
756 //\r
757 Status = PrivateData->Io.Pci.Read (\r
758 &PrivateData->Io, \r
759 EfiPciWidthUint32, \r
760 Address, \r
761 1, \r
762 OriginalValue\r
763 );\r
764\r
765 //\r
766 // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
767 //\r
768 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
769\r
770 AllOnes = 0xffffffff;\r
771\r
772 Status = PrivateData->Io.Pci.Write (\r
773 &PrivateData->Io, \r
774 EfiPciWidthUint32, \r
775 Address, \r
776 1, \r
777 &AllOnes\r
778 );\r
779 Status = PrivateData->Io.Pci.Read (\r
780 &PrivateData->Io, \r
781 EfiPciWidthUint32, \r
782 Address, \r
783 1, \r
784 Value\r
785 );\r
786\r
787 //\r
788 //Write back the original value\r
789 //\r
790 Status = PrivateData->Io.Pci.Write (\r
791 &PrivateData->Io, \r
792 EfiPciWidthUint32, \r
793 Address, \r
794 1, \r
795 OriginalValue\r
796 );\r
797\r
798 //\r
799 // Restore TPL to its original level\r
800 //\r
801 gBS->RestoreTPL (OldTpl);\r
802\r
803 if ( *Value == 0 ) {\r
804 return EFI_DEVICE_ERROR;\r
805 }\r
806 return EFI_SUCCESS;\r
807}\r
808\r
809EFI_STATUS\r
810PcatPciRootBridgeParseBars (\r
811 IN PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData,\r
812 IN UINT16 Command,\r
813 IN UINTN Bus,\r
814 IN UINTN Device,\r
815 IN UINTN Function\r
816 )\r
817/*++\r
818\r
819Routine Description:\r
820\r
821Arguments:\r
822\r
823Returns:\r
824\r
825 None\r
826\r
827--*/\r
828{\r
829 EFI_STATUS Status;\r
830 UINT64 Address;\r
831 UINT32 OriginalValue;\r
832 UINT32 Value;\r
833 UINT32 OriginalUpperValue;\r
834 UINT32 UpperValue;\r
835 UINT64 Mask;\r
836 UINTN Offset;\r
837 UINT64 Base;\r
838 UINT64 Length;\r
839 UINT64 Limit;\r
840\r
841 for (Offset = 0x10; Offset < 0x28; Offset += 4) {\r
842 Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);\r
843 Status = PcatPciRootBridgeBarExisted (\r
844 PrivateData,\r
845 Address,\r
846 &OriginalValue,\r
847 &Value\r
848 );\r
849\r
850 if (!EFI_ERROR (Status )) {\r
851 if ( Value & 0x01 ) { \r
852 if (Command & 0x0001) {\r
853 //\r
854 //Device I/Os\r
855 //\r
856 Mask = 0xfffffffc;\r
857 Base = OriginalValue & Mask;\r
858 Length = ((~(Value & Mask)) & Mask) + 0x04;\r
859 if (!(Value & 0xFFFF0000)){\r
860 Length &= 0x0000FFFF;\r
861 }\r
862 Limit = Base + Length - 1;\r
863\r
864 if (Base < Limit) {\r
865 if (PrivateData->IoBase > Base) {\r
866 PrivateData->IoBase = (UINT32)Base;\r
867 }\r
868 if (PrivateData->IoLimit < Limit) {\r
869 PrivateData->IoLimit = (UINT32)Limit;\r
870 }\r
871 }\r
872 }\r
873 \r
874 } else {\r
875\r
876 if (Command & 0x0002) {\r
877\r
878 Mask = 0xfffffff0;\r
879 Base = OriginalValue & Mask;\r
880 Length = Value & Mask;\r
881 \r
882 if ((Value & 0x07) != 0x04) {\r
883 Length = ((~Length) + 1) & 0xffffffff;\r
884 } else {\r
885 Offset += 4; \r
886 Address = EFI_PCI_ADDRESS (Bus, Device, Function, Offset);\r
887\r
888 Status = PcatPciRootBridgeBarExisted (\r
889 PrivateData,\r
890 Address,\r
891 &OriginalUpperValue,\r
892 &UpperValue\r
893 );\r
894\r
895 Base = Base | LShiftU64((UINT64)OriginalUpperValue,32);\r
896 Length = Length | LShiftU64((UINT64)UpperValue,32);\r
897 Length = (~Length) + 1;\r
898 }\r
899\r
900 Limit = Base + Length - 1;\r
901\r
902 if (Base < Limit) {\r
903 if (PrivateData->MemBase > Base) {\r
904 PrivateData->MemBase = Base;\r
905 }\r
906 if (PrivateData->MemLimit < Limit) {\r
907 PrivateData->MemLimit = Limit;\r
908 }\r
909\r
910 switch (Value &0x07) {\r
911 case 0x00: ////memory space; anywhere in 32 bit address space\r
912 if (Value & 0x08) {\r
913 if (PrivateData->Pmem32Base > Base) {\r
914 PrivateData->Pmem32Base = Base;\r
915 }\r
916 if (PrivateData->Pmem32Limit < Limit) {\r
917 PrivateData->Pmem32Limit = Limit;\r
918 }\r
919 } else {\r
920 if (PrivateData->Mem32Base > Base) {\r
921 PrivateData->Mem32Base = Base;\r
922 }\r
923 if (PrivateData->Mem32Limit < Limit) {\r
924 PrivateData->Mem32Limit = Limit;\r
925 }\r
926 }\r
927 break;\r
928 case 0x04: //memory space; anywhere in 64 bit address space\r
929 if (Value & 0x08) {\r
930 if (PrivateData->Pmem64Base > Base) {\r
931 PrivateData->Pmem64Base = Base;\r
932 }\r
933 if (PrivateData->Pmem64Limit < Limit) {\r
934 PrivateData->Pmem64Limit = Limit;\r
935 }\r
936 } else {\r
937 if (PrivateData->Mem64Base > Base) {\r
938 PrivateData->Mem64Base = Base;\r
939 }\r
940 if (PrivateData->Mem64Limit < Limit) {\r
941 PrivateData->Mem64Limit = Limit;\r
942 }\r
943 }\r
944 break;\r
945 }\r
946 }\r
947 }\r
948 }\r
949 }\r
950 }\r
951 return EFI_SUCCESS;\r
952}\r
953\r
954UINT64\r
955GetPciExpressBaseAddressForRootBridge (\r
956 IN UINTN HostBridgeNumber,\r
957 IN UINTN RootBridgeNumber\r
958 )\r
959/*++\r
960\r
961Routine Description:\r
962 This routine is to get PciExpress Base Address for this RootBridge\r
963\r
964Arguments:\r
965 HostBridgeNumber - The number of HostBridge\r
966 RootBridgeNumber - The number of RootBridge\r
967 \r
968Returns:\r
969 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge\r
970\r
971--*/\r
972{\r
973 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;\r
974 UINTN BufferSize;\r
975 UINT32 Index;\r
976 UINT32 Number;\r
977 VOID *HobList;\r
978 EFI_STATUS Status;\r
979 EFI_PEI_HOB_POINTERS GuidHob;\r
980\r
981 //\r
982 // Get Hob List from configuration table\r
983 //\r
984 Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);\r
985 if (EFI_ERROR (Status)) {\r
986 return 0;\r
987 }\r
988\r
989 //\r
990 // Get PciExpressAddressInfo Hob\r
991 //\r
992 PciExpressBaseAddressInfo = NULL;\r
993 BufferSize = 0;\r
994 GuidHob.Raw = GetNextGuidHob (&gEfiPciExpressBaseAddressGuid, &HobList);\r
995 if (GuidHob.Raw != NULL) {\r
996 PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);\r
997 BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);\r
998 } else {\r
999 return 0;\r
1000 }\r
1001\r
1002 //\r
1003 // Search the PciExpress Base Address in the Hob for current RootBridge\r
1004 //\r
1005 Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));\r
1006 for (Index = 0; Index < Number; Index++) {\r
1007 if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&\r
1008 (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {\r
1009 return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;\r
1010 }\r
1011 }\r
1012\r
1013 //\r
1014 // Do not find the PciExpress Base Address in the Hob\r
1015 //\r
1016 return 0;\r
1017}\r
1018\r