]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/PciRootBridgeNoEnumerationDxe/X64/PcatIo.c
DuetPkg: Fix EFIAPI usage inconsistencies
[mirror_edk2.git] / DuetPkg / PciRootBridgeNoEnumerationDxe / X64 / PcatIo.c
CommitLineData
c69dd9df 1/*++\r
2\r
b1f700a8
HT
3Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
c69dd9df 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 PcatPciRootBridgeIo.c\r
14 \r
15Abstract:\r
16\r
17 EFI PC AT PCI Root Bridge Io Protocol\r
18\r
19Revision History\r
20\r
21--*/\r
22\r
23#include "PcatPciRootBridge.h"\r
24\r
e56dd2ce 25BOOLEAN mPciOptionRomTableInstalled = FALSE;\r
26EFI_PCI_OPTION_ROM_TABLE mPciOptionRomTable = {0, NULL};\r
c69dd9df 27\r
28EFI_STATUS\r
0492698a 29EFIAPI\r
c69dd9df 30PcatRootBridgeIoIoRead (\r
31 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
32 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
33 IN UINT64 UserAddress,\r
34 IN UINTN Count,\r
35 IN OUT VOID *UserBuffer\r
36 )\r
37{\r
38 return gCpuIo->Io.Read (\r
39 gCpuIo,\r
40 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
41 UserAddress,\r
42 Count,\r
43 UserBuffer\r
44 );\r
45}\r
46\r
47EFI_STATUS\r
0492698a 48EFIAPI\r
c69dd9df 49PcatRootBridgeIoIoWrite (\r
50 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
51 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
52 IN UINT64 UserAddress,\r
53 IN UINTN Count,\r
54 IN OUT VOID *UserBuffer\r
55 )\r
56{\r
57 return gCpuIo->Io.Write (\r
58 gCpuIo,\r
59 (EFI_CPU_IO_PROTOCOL_WIDTH) Width,\r
60 UserAddress,\r
61 Count,\r
62 UserBuffer\r
63 );\r
64\r
65}\r
66\r
67EFI_STATUS\r
68PcatRootBridgeIoGetIoPortMapping (\r
69 OUT EFI_PHYSICAL_ADDRESS *IoPortMapping,\r
70 OUT EFI_PHYSICAL_ADDRESS *MemoryPortMapping\r
71 )\r
72/*++\r
73\r
74 Get the IO Port Mapping. For IA-32 it is always 0.\r
75 \r
76--*/\r
77{\r
78 *IoPortMapping = 0;\r
79 *MemoryPortMapping = 0;\r
80\r
81 return EFI_SUCCESS;\r
82}\r
83\r
84EFI_STATUS\r
85PcatRootBridgeIoPciRW (\r
86 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,\r
87 IN BOOLEAN Write,\r
88 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,\r
89 IN UINT64 UserAddress,\r
90 IN UINTN Count,\r
91 IN OUT VOID *UserBuffer\r
92 )\r
93{\r
94 PCI_CONFIG_ACCESS_CF8 Pci;\r
95 PCI_CONFIG_ACCESS_CF8 PciAligned;\r
96 UINT32 InStride;\r
97 UINT32 OutStride;\r
98 UINTN PciData;\r
99 UINTN PciDataStride;\r
100 PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData;\r
101 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;\r
102 UINT64 PciExpressRegAddr;\r
103 BOOLEAN UsePciExpressAccess;\r
104\r
105 if (Width < 0 || Width >= EfiPciWidthMaximum) {\r
106 return EFI_INVALID_PARAMETER;\r
107 }\r
108 \r
109 if ((Width & 0x03) >= EfiPciWidthUint64) {\r
110 return EFI_INVALID_PARAMETER;\r
111 }\r
112 \r
113 PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);\r
114\r
115 InStride = 1 << (Width & 0x03);\r
116 OutStride = InStride;\r
815119f3 117 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
c69dd9df 118 InStride = 0;\r
119 }\r
120\r
815119f3 121 if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) {\r
c69dd9df 122 OutStride = 0;\r
123 }\r
124\r
125 UsePciExpressAccess = FALSE;\r
126\r
394bbc59 127 CopyMem (&PciAddress, &UserAddress, sizeof(UINT64));\r
c69dd9df 128\r
129 if (PciAddress.ExtendedRegister > 0xFF) {\r
130 //\r
131 // Check PciExpressBaseAddress\r
132 //\r
133 if ((PrivateData->PciExpressBaseAddress == 0) ||\r
eea53ce1 134 (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) {\r
c69dd9df 135 return EFI_UNSUPPORTED;\r
136 } else {\r
137 UsePciExpressAccess = TRUE;\r
138 }\r
139 } else {\r
140 if (PciAddress.ExtendedRegister != 0) {\r
394bbc59 141 Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF;\r
c69dd9df 142 } else {\r
394bbc59 143 Pci.Bits.Reg = PciAddress.Register;\r
c69dd9df 144 }\r
145 //\r
146 // Note: We can also use PciExpress access here, if wanted.\r
147 //\r
148 }\r
149\r
150 if (!UsePciExpressAccess) {\r
394bbc59 151 Pci.Bits.Func = PciAddress.Function;\r
152 Pci.Bits.Dev = PciAddress.Device;\r
153 Pci.Bits.Bus = PciAddress.Bus;\r
154 Pci.Bits.Reserved = 0;\r
155 Pci.Bits.Enable = 1;\r
c69dd9df 156\r
157 //\r
158 // PCI Config access are all 32-bit alligned, but by accessing the\r
159 // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types\r
160 // are possible on PCI.\r
161 //\r
162 // To read a byte of PCI config space you load 0xcf8 and \r
163 // read 0xcfc, 0xcfd, 0xcfe, 0xcff\r
164 //\r
394bbc59 165 PciDataStride = Pci.Bits.Reg & 0x03;\r
c69dd9df 166\r
167 while (Count) {\r
168 PciAligned = Pci;\r
394bbc59 169 PciAligned.Bits.Reg &= 0xfc;\r
c69dd9df 170 PciData = (UINTN)PrivateData->PciData + PciDataStride;\r
171 EfiAcquireLock(&PrivateData->PciLock);\r
172 This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned);\r
173 if (Write) {\r
174 This->Io.Write (This, Width, PciData, 1, UserBuffer);\r
175 } else {\r
176 This->Io.Read (This, Width, PciData, 1, UserBuffer);\r
177 }\r
178 EfiReleaseLock(&PrivateData->PciLock);\r
179 UserBuffer = ((UINT8 *)UserBuffer) + OutStride;\r
180 PciDataStride = (PciDataStride + InStride) % 4;\r
394bbc59 181 Pci.Bits.Reg += InStride;\r
c69dd9df 182 Count -= 1;\r
183 }\r
184 } else {\r
185 //\r
186 // Access PCI-Express space by using memory mapped method.\r
187 //\r
188 PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) |\r
189 (PciAddress.Bus << 20) |\r
190 (PciAddress.Device << 15) |\r
191 (PciAddress.Function << 12);\r
192 if (PciAddress.ExtendedRegister != 0) {\r
193 PciExpressRegAddr += PciAddress.ExtendedRegister;\r
194 } else {\r
195 PciExpressRegAddr += PciAddress.Register;\r
196 }\r
197 while (Count) {\r
198 if (Write) {\r
199 This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
200 } else {\r
201 This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer);\r
202 }\r
203\r
204 UserBuffer = ((UINT8 *) UserBuffer) + OutStride;\r
205 PciExpressRegAddr += InStride;\r
206 Count -= 1;\r
207 }\r
208 }\r
209 \r
210 return EFI_SUCCESS;\r
211}\r
212\r
c69dd9df 213VOID\r
214ScanPciBus(\r
215 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
216 UINT16 MinBus,\r
217 UINT16 MaxBus,\r
218 UINT16 MinDevice,\r
219 UINT16 MaxDevice,\r
220 UINT16 MinFunc,\r
221 UINT16 MaxFunc,\r
222 EFI_PCI_BUS_SCAN_CALLBACK Callback,\r
223 VOID *Context\r
224 )\r
225 \r
226{\r
227 UINT16 Bus;\r
228 UINT16 Device;\r
229 UINT16 Func;\r
230 UINT64 Address;\r
231 PCI_TYPE00 PciHeader;\r
232\r
233 //\r
234 // Loop through all busses\r
235 //\r
236 for (Bus = MinBus; Bus <= MaxBus; Bus++) {\r
237 // \r
238 // Loop 32 devices per bus\r
239 //\r
240 for (Device = MinDevice; Device <= MaxDevice; Device++) {\r
241 //\r
242 // Loop through 8 functions per device\r
243 //\r
244 for (Func = MinFunc; Func <= MaxFunc; Func++) {\r
245\r
246 //\r
247 // Compute the EFI Address required to access the PCI Configuration Header of this PCI Device\r
248 //\r
249 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
250\r
251 //\r
252 // Read the VendorID from this PCI Device's Confioguration Header\r
253 //\r
254 IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &PciHeader.Hdr.VendorId);\r
255 \r
256 //\r
257 // If VendorId = 0xffff, there does not exist a device at this \r
258 // location. For each device, if there is any function on it, \r
259 // there must be 1 function at Function 0. So if Func = 0, there\r
260 // will be no more functions in the same device, so we can break\r
261 // loop to deal with the next device.\r
262 // \r
263 if (PciHeader.Hdr.VendorId == 0xffff && Func == 0) {\r
264 break;\r
265 }\r
266 \r
267 if (PciHeader.Hdr.VendorId != 0xffff) {\r
268\r
269 //\r
270 // Read the HeaderType to determine if this is a multi-function device\r
271 //\r
272 IoDev->Pci.Read (IoDev, EfiPciWidthUint8, Address + 0x0e, 1, &PciHeader.Hdr.HeaderType);\r
273\r
274 //\r
275 // Call the callback function for the device that was found\r
276 //\r
277 Callback(\r
278 IoDev, \r
279 MinBus, MaxBus,\r
280 MinDevice, MaxDevice,\r
281 MinFunc, MaxFunc,\r
282 Bus,\r
283 Device,\r
284 Func,\r
285 Context\r
286 );\r
287\r
288 //\r
289 // If this is not a multi-function device, we can leave the loop \r
290 // to deal with the next device.\r
291 //\r
292 if ((PciHeader.Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00 && Func == 0) {\r
293 break;\r
294 }\r
295 } \r
296 }\r
297 }\r
298 }\r
299}\r
300\r
c69dd9df 301VOID\r
302CheckForRom (\r
303 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
304 UINT16 MinBus,\r
305 UINT16 MaxBus,\r
306 UINT16 MinDevice,\r
307 UINT16 MaxDevice,\r
308 UINT16 MinFunc,\r
309 UINT16 MaxFunc,\r
310 UINT16 Bus,\r
311 UINT16 Device,\r
312 UINT16 Func,\r
313 IN VOID *VoidContext\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
317 PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
318 UINT64 Address;\r
319 PCI_TYPE00 PciHeader;\r
320 PCI_TYPE01 *PciBridgeHeader;\r
321 UINT32 Register;\r
322 UINT32 RomBar;\r
323 UINT32 RomBarSize;\r
324 EFI_PHYSICAL_ADDRESS RomBuffer;\r
325 UINT32 MaxRomSize;\r
326 EFI_PCI_EXPANSION_ROM_HEADER EfiRomHeader;\r
327 PCI_DATA_STRUCTURE Pcir;\r
328 EFI_PCI_OPTION_ROM_DESCRIPTOR *TempPciOptionRomDescriptors;\r
329 BOOLEAN LastImage;\r
330\r
331 Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
332\r
333 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
334\r
335 //\r
336 // Save the contents of the PCI Configuration Header\r
337 //\r
338 IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
339\r
340 if (IS_PCI_BRIDGE(&PciHeader)) {\r
341\r
342 PciBridgeHeader = (PCI_TYPE01 *)(&PciHeader);\r
343\r
344 //\r
345 // See if the PCI-PCI Bridge has its secondary interface enabled.\r
346 //\r
347 if (PciBridgeHeader->Bridge.SubordinateBus >= PciBridgeHeader->Bridge.SecondaryBus) {\r
348\r
349 //\r
350 // Disable the Prefetchable Memory Window\r
351 //\r
352 Register = 0x00000000;\r
353 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x26, 1, &Register);\r
354 IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x2c, 1, &Register);\r
355 Register = 0xffffffff;\r
356 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x24, 1, &Register);\r
357 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x28, 1, &Register);\r
358\r
359 //\r
360 // Program Memory Window to the PCI Root Bridge Memory Window\r
361 //\r
362 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 0x20, 4, &Context->PpbMemoryWindow);\r
363\r
364 //\r
365 // Enable the Memory decode for the PCI-PCI Bridge\r
366 //\r
367 IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
368 Register |= 0x02;\r
369 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
370\r
371 //\r
372 // Recurse on the Secondary Bus Number\r
373 //\r
374 ScanPciBus(\r
375 IoDev,\r
376 PciBridgeHeader->Bridge.SecondaryBus, PciBridgeHeader->Bridge.SecondaryBus, \r
377 0, PCI_MAX_DEVICE, \r
378 0, PCI_MAX_FUNC, \r
379 CheckForRom, Context\r
380 );\r
381 }\r
382 } else {\r
383\r
384 //\r
385 // Check if an Option ROM Register is present and save the Option ROM Window Register\r
386 //\r
387 RomBar = 0xffffffff;\r
388 IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
389 IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
390\r
391 RomBarSize = (~(RomBar & 0xfffff800)) + 1;\r
392\r
393 //\r
394 // Make sure the size of the ROM is between 0 and 16 MB\r
395 //\r
396 if (RomBarSize > 0 && RomBarSize <= 0x01000000) {\r
397\r
398 //\r
399 // Program Option ROM Window Register to the PCI Root Bridge Window and Enable the Option ROM Window\r
400 //\r
401 RomBar = (Context->PpbMemoryWindow & 0xffff) << 16;\r
402 RomBar = ((RomBar - 1) & (~(RomBarSize - 1))) + RomBarSize;\r
403 if (RomBar < (Context->PpbMemoryWindow & 0xffff0000)) {\r
404 MaxRomSize = (Context->PpbMemoryWindow & 0xffff0000) - RomBar;\r
405 RomBar = RomBar + 1;\r
406 IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
407 IoDev->Pci.Read (IoDev, EfiPciWidthUint32, Address + 0x30, 1, &RomBar);\r
408 RomBar = RomBar - 1;\r
409\r
410 //\r
411 // Enable the Memory decode for the PCI Device\r
412 //\r
413 IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
414 Register |= 0x02;\r
415 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
416\r
417 //\r
418 // Follow the chain of images to determine the size of the Option ROM present\r
419 // Keep going until the last image is found by looking at the Indicator field\r
420 // or the size of an image is 0, or the size of all the images is bigger than the\r
421 // size of the window programmed into the PPB.\r
422 //\r
423 RomBarSize = 0;\r
424 do {\r
425\r
426 LastImage = TRUE;\r
427\r
394bbc59 428 ZeroMem (&EfiRomHeader, sizeof(EfiRomHeader));\r
c69dd9df 429 IoDev->Mem.Read (\r
430 IoDev, \r
431 EfiPciWidthUint8, \r
432 RomBar + RomBarSize, \r
433 sizeof(EfiRomHeader),\r
434 &EfiRomHeader\r
435 );\r
436\r
437 Pcir.ImageLength = 0;\r
438\r
439 if (EfiRomHeader.Signature == 0xaa55) {\r
440\r
394bbc59 441 ZeroMem (&Pcir, sizeof(Pcir));\r
c69dd9df 442 IoDev->Mem.Read (\r
443 IoDev, \r
444 EfiPciWidthUint8, \r
445 RomBar + RomBarSize + EfiRomHeader.PcirOffset, \r
446 sizeof(Pcir),\r
447 &Pcir\r
448 );\r
449\r
450 if ((Pcir.Indicator & 0x80) == 0x00) {\r
451 LastImage = FALSE;\r
452 }\r
453\r
454 RomBarSize += Pcir.ImageLength * 512;\r
455 }\r
456 } while (!LastImage && RomBarSize < MaxRomSize && Pcir.ImageLength !=0);\r
457\r
458 if (RomBarSize > 0) {\r
459\r
460 //\r
461 // Allocate a memory buffer for the Option ROM contents.\r
462 //\r
463 Status = gBS->AllocatePages(\r
464 AllocateAnyPages,\r
465 EfiBootServicesData,\r
466 EFI_SIZE_TO_PAGES(RomBarSize),\r
467 &RomBuffer\r
468 );\r
469\r
470 if (!EFI_ERROR (Status)) {\r
471\r
472 //\r
473 // Copy the contents of the Option ROM to the memory buffer\r
474 //\r
475 IoDev->Mem.Read (IoDev, EfiPciWidthUint32, RomBar, RomBarSize / sizeof(UINT32), (VOID *)(UINTN)RomBuffer);\r
476\r
477 Status = gBS->AllocatePool(\r
478 EfiBootServicesData,\r
479 ((UINT32)mPciOptionRomTable.PciOptionRomCount + 1) * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR),\r
3a0a1473 480 (VOID **) &TempPciOptionRomDescriptors\r
c69dd9df 481 );\r
482 if (mPciOptionRomTable.PciOptionRomCount > 0) {\r
394bbc59 483 CopyMem(\r
c69dd9df 484 TempPciOptionRomDescriptors, \r
485 mPciOptionRomTable.PciOptionRomDescriptors, \r
486 (UINT32)mPciOptionRomTable.PciOptionRomCount * sizeof(EFI_PCI_OPTION_ROM_DESCRIPTOR)\r
487 );\r
488\r
489 gBS->FreePool(mPciOptionRomTable.PciOptionRomDescriptors);\r
490 }\r
491\r
492 mPciOptionRomTable.PciOptionRomDescriptors = TempPciOptionRomDescriptors; \r
493\r
494 TempPciOptionRomDescriptors = &(mPciOptionRomTable.PciOptionRomDescriptors[(UINT32)mPciOptionRomTable.PciOptionRomCount]);\r
495\r
496 TempPciOptionRomDescriptors->RomAddress = RomBuffer;\r
497 TempPciOptionRomDescriptors->MemoryType = EfiBootServicesData;\r
498 TempPciOptionRomDescriptors->RomLength = RomBarSize;\r
499 TempPciOptionRomDescriptors->Seg = (UINT32)IoDev->SegmentNumber;\r
500 TempPciOptionRomDescriptors->Bus = (UINT8)Bus;\r
501 TempPciOptionRomDescriptors->Dev = (UINT8)Device;\r
502 TempPciOptionRomDescriptors->Func = (UINT8)Func;\r
503 TempPciOptionRomDescriptors->ExecutedLegacyBiosImage = TRUE;\r
504 TempPciOptionRomDescriptors->DontLoadEfiRom = FALSE;\r
505\r
506 mPciOptionRomTable.PciOptionRomCount++;\r
507 }\r
508 }\r
509\r
510 //\r
511 // Disable the Memory decode for the PCI-PCI Bridge\r
512 //\r
513 IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
514 Register &= (~0x02);\r
515 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address + 4, 1, &Register);\r
516 }\r
517 }\r
518 }\r
519\r
520 //\r
521 // Restore the PCI Configuration Header \r
522 //\r
523 IoDev->Pci.Write (IoDev, EfiPciWidthUint32, Address, sizeof(PciHeader)/sizeof(UINT32), &PciHeader);\r
524}\r
525\r
c69dd9df 526VOID\r
527SaveCommandRegister (\r
528 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
529 UINT16 MinBus,\r
530 UINT16 MaxBus,\r
531 UINT16 MinDevice,\r
532 UINT16 MaxDevice,\r
533 UINT16 MinFunc,\r
534 UINT16 MaxFunc,\r
535 UINT16 Bus,\r
536 UINT16 Device,\r
537 UINT16 Func,\r
538 IN VOID *VoidContext\r
539 )\r
540\r
541{\r
542 PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
543 UINT64 Address;\r
544 UINTN Index;\r
545 UINT16 Command;\r
546\r
547 Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
548\r
549 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
550\r
551 Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
552\r
553 IoDev->Pci.Read (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
554\r
555 //\r
556 // Clear the memory enable bit\r
557 //\r
3a0a1473 558 Command = (UINT16) (Context->CommandRegisterBuffer[Index] & (~0x02));\r
c69dd9df 559\r
560 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Command);\r
561}\r
562\r
c69dd9df 563VOID\r
564RestoreCommandRegister (\r
565 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,\r
566 UINT16 MinBus,\r
567 UINT16 MaxBus,\r
568 UINT16 MinDevice,\r
569 UINT16 MaxDevice,\r
570 UINT16 MinFunc,\r
571 UINT16 MaxFunc,\r
572 UINT16 Bus,\r
573 UINT16 Device,\r
574 UINT16 Func,\r
575 IN VOID *VoidContext\r
576 )\r
577\r
578{\r
579 PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *Context;\r
580 UINT64 Address;\r
581 UINTN Index;\r
582\r
583 Context = (PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT *)VoidContext;\r
584\r
585 Address = EFI_PCI_ADDRESS (Bus, Device, Func, 4);\r
586\r
587 Index = (Bus - MinBus) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1) + Device * (PCI_MAX_FUNC+1) + Func;\r
588\r
589 IoDev->Pci.Write (IoDev, EfiPciWidthUint16, Address, 1, &Context->CommandRegisterBuffer[Index]);\r
590}\r
591\r
592EFI_STATUS\r
593ScanPciRootBridgeForRoms(\r
594 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev\r
595 )\r
596 \r
597{\r
598 EFI_STATUS Status;\r
599 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; \r
600 UINT16 MinBus;\r
601 UINT16 MaxBus;\r
602 UINT64 RootWindowBase;\r
603 UINT64 RootWindowLimit;\r
604 PCAT_PCI_ROOT_BRIDGE_SCAN_FOR_ROM_CONTEXT Context;\r
605\r
606 if (mPciOptionRomTableInstalled == FALSE) {\r
607 gBS->InstallConfigurationTable(&gEfiPciOptionRomTableGuid, &mPciOptionRomTable);\r
608 mPciOptionRomTableInstalled = TRUE;\r
609 }\r
610\r
3a0a1473 611 Status = IoDev->Configuration(IoDev, (VOID **) &Descriptors);\r
c69dd9df 612 if (EFI_ERROR (Status) || Descriptors == NULL) {\r
613 return EFI_NOT_FOUND;\r
614 }\r
615\r
616 MinBus = 0xffff;\r
617 MaxBus = 0xffff;\r
618 RootWindowBase = 0;\r
619 RootWindowLimit = 0;\r
620 while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
621 //\r
622 // Find bus range\r
623 //\r
624 if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
625 MinBus = (UINT16)Descriptors->AddrRangeMin;\r
626 MaxBus = (UINT16)Descriptors->AddrRangeMax;\r
627 }\r
628 //\r
629 // Find memory descriptors that are not prefetchable\r
630 //\r
631 if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM && Descriptors->SpecificFlag == 0) {\r
632 //\r
633 // Find Memory Descriptors that are less than 4GB, so the PPB Memory Window can be used for downstream devices\r
634 //\r
99032c45 635 if (Descriptors->AddrRangeMax < 0x100000000ULL) {\r
c69dd9df 636 //\r
637 // Find the largest Non-Prefetchable Memory Descriptor that is less than 4GB\r
638 //\r
639 if ((Descriptors->AddrRangeMax - Descriptors->AddrRangeMin) > (RootWindowLimit - RootWindowBase)) {\r
640 RootWindowBase = Descriptors->AddrRangeMin;\r
641 RootWindowLimit = Descriptors->AddrRangeMax;\r
642 }\r
643 }\r
644 }\r
645 Descriptors ++;\r
646 }\r
647\r
648 //\r
649 // Make sure a bus range was found\r
650 //\r
651 if (MinBus == 0xffff || MaxBus == 0xffff) {\r
652 return EFI_NOT_FOUND;\r
653 }\r
654\r
655 //\r
656 // Make sure a non-prefetchable memory region was found\r
657 //\r
658 if (RootWindowBase == 0 && RootWindowLimit == 0) {\r
659 return EFI_NOT_FOUND;\r
660 }\r
661\r
662 //\r
663 // Round the Base and Limit values to 1 MB boudaries\r
664 //\r
665 RootWindowBase = ((RootWindowBase - 1) & 0xfff00000) + 0x00100000;\r
666 RootWindowLimit = ((RootWindowLimit + 1) & 0xfff00000) - 1;\r
667\r
668 //\r
669 // Make sure that the size of the rounded window is greater than zero\r
670 //\r
671 if (RootWindowLimit <= RootWindowBase) {\r
672 return EFI_NOT_FOUND;\r
673 }\r
674\r
675 //\r
676 // Allocate buffer to save the Command register from all the PCI devices\r
677 //\r
678 Context.CommandRegisterBuffer = NULL;\r
679 Status = gBS->AllocatePool(\r
680 EfiBootServicesData,\r
681 sizeof(UINT16) * (MaxBus - MinBus + 1) * (PCI_MAX_DEVICE+1) * (PCI_MAX_FUNC+1),\r
3a0a1473 682 (VOID **) &Context.CommandRegisterBuffer\r
c69dd9df 683 );\r
684\r
685 if (EFI_ERROR (Status)) {\r
686 return Status;\r
687 }\r
688\r
689 Context.PpbMemoryWindow = (((UINT32)RootWindowBase) >> 16) | ((UINT32)RootWindowLimit & 0xffff0000);\r
690\r
691 //\r
692 // Save the Command register from all the PCI devices, and disable the I/O, Mem, and BusMaster bits\r
693 //\r
694 ScanPciBus(\r
695 IoDev,\r
696 MinBus, MaxBus, \r
697 0, PCI_MAX_DEVICE, \r
698 0, PCI_MAX_FUNC, \r
699 SaveCommandRegister, &Context\r
700 );\r
701\r
702 //\r
703 // Recursively scan all the busses for PCI Option ROMs\r
704 //\r
705 ScanPciBus(\r
706 IoDev,\r
707 MinBus, MinBus, \r
708 0, PCI_MAX_DEVICE, \r
709 0, PCI_MAX_FUNC, \r
710 CheckForRom, &Context\r
711 );\r
712\r
713 //\r
714 // Restore the Command register in all the PCI devices\r
715 //\r
716 ScanPciBus(\r
717 IoDev,\r
718 MinBus, MaxBus, \r
719 0, PCI_MAX_DEVICE, \r
720 0, PCI_MAX_FUNC, \r
721 RestoreCommandRegister, &Context\r
722 );\r
723\r
724 //\r
725 // Free the buffer used to save all the Command register values\r
726 //\r
727 gBS->FreePool(Context.CommandRegisterBuffer);\r
728\r
729 return EFI_SUCCESS;\r
730}\r