]> git.proxmox.com Git - mirror_edk2.git/blob - PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.c
Remove svn:executable on *.c, *.h, *.asm, *.S, *.inf and *.asl*
[mirror_edk2.git] / PcAtChipsetPkg / PciHostBridgeDxe / PciHostBridge.c
1 /** @file
2 Pci Host Bridge driver:
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
4
5 Copyright (c) 2008 - 2009, Intel Corporation<BR> All rights
6 reserved. This program and the accompanying materials are
7 licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "PciHostBridge.h"
17
18 //
19 // Support 64 K IO space
20 //
21 #define RES_IO_BASE 0x1000
22 #define RES_IO_LIMIT 0xFFFF
23 //
24 // Support 4G address space
25 //
26 #define RES_MEM_BASE_1 0xF8000000
27 #define RES_MEM_LIMIT_1 (0xFEC00000 - 1)
28
29 //
30 // Hard code: Root Bridge Number within the host bridge
31 // Root Bridge's attribute
32 // Root Bridge's device path
33 // Root Bridge's resource appeture
34 //
35 UINTN RootBridgeNumber[1] = { 1 };
36
37 UINT64 RootBridgeAttribute[1][1] = { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM };
38
39 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
40 {
41 ACPI_DEVICE_PATH,
42 ACPI_DP,
43 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
44 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
45 EISA_PNP_ID(0x0A03),
46 0,
47 END_DEVICE_PATH_TYPE,
48 END_ENTIRE_DEVICE_PATH_SUBTYPE,
49 END_DEVICE_PATH_LENGTH,
50 0
51 }
52 };
53
54 PCI_ROOT_BRIDGE_RESOURCE_APPETURE mResAppeture[1][1] = {
55 {0, 0, 0, 0xffffffff, 0, 1 << 16}
56 };
57
58 EFI_HANDLE mDriverImageHandle;
59
60 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
61 PCI_HOST_BRIDGE_SIGNATURE, // Signature
62 NULL, // HostBridgeHandle
63 0, // RootBridgeNumber
64 {NULL, NULL}, // Head
65 FALSE, // ResourceSubiteed
66 TRUE, // CanRestarted
67 {
68 NotifyPhase,
69 GetNextRootBridge,
70 GetAttributes,
71 StartBusEnumeration,
72 SetBusNumbers,
73 SubmitResources,
74 GetProposedResources,
75 PreprocessController
76 }
77 };
78
79 //
80 // Implementation
81 //
82 EFI_STATUS
83 EFIAPI
84 InitializePciHostBridge (
85 IN EFI_HANDLE ImageHandle,
86 IN EFI_SYSTEM_TABLE *SystemTable
87 )
88 /*++
89
90 Routine Description:
91 Entry point of this driver
92
93 Arguments:
94
95 ImageHandle -
96
97 SystemTable -
98
99 Returns:
100
101 --*/
102 {
103 EFI_STATUS Status;
104 UINTN Loop1;
105 UINTN Loop2;
106 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
107 PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
108 IN EFI_PHYSICAL_ADDRESS BaseAddress;
109 IN UINT64 Length;
110
111 mDriverImageHandle = ImageHandle;
112
113 //
114 // Create Host Bridge Device Handle
115 //
116 for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
117 HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);
118 if (HostBridge == NULL) {
119 return EFI_OUT_OF_RESOURCES;
120 }
121
122 HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
123 InitializeListHead (&HostBridge->Head);
124
125 Status = gBS->InstallMultipleProtocolInterfaces (
126 &HostBridge->HostBridgeHandle,
127 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
128 NULL
129 );
130 if (EFI_ERROR (Status)) {
131 FreePool (HostBridge);
132 return EFI_DEVICE_ERROR;
133 }
134
135 //
136 // Create Root Bridge Device Handle in this Host Bridge
137 //
138
139 for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
140 PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
141 if (PrivateData == NULL) {
142 return EFI_OUT_OF_RESOURCES;
143 }
144
145 PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
146 PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
147
148 RootBridgeConstructor (
149 &PrivateData->Io,
150 HostBridge->HostBridgeHandle,
151 RootBridgeAttribute[Loop1][Loop2],
152 &mResAppeture[Loop1][Loop2]
153 );
154
155 Status = gBS->InstallMultipleProtocolInterfaces(
156 &PrivateData->Handle,
157 &gEfiDevicePathProtocolGuid, PrivateData->DevicePath,
158 &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
159 NULL
160 );
161 if (EFI_ERROR (Status)) {
162 FreePool(PrivateData);
163 return EFI_DEVICE_ERROR;
164 }
165
166 InsertTailList (&HostBridge->Head, &PrivateData->Link);
167 }
168 }
169
170 Status = gDS->AddIoSpace (
171 EfiGcdIoTypeIo,
172 RES_IO_BASE,
173 RES_IO_LIMIT - RES_IO_BASE + 1
174 );
175
176 // PCI memory space from 3.75Gbytes->(4GBytes - BIOSFWH local APIC etc)
177 Status = gDS->AddMemorySpace (
178 EfiGcdMemoryTypeMemoryMappedIo,
179 RES_MEM_BASE_1,
180 (RES_MEM_LIMIT_1 - RES_MEM_BASE_1 + 1),
181 0
182 );
183
184 BaseAddress = 0x80000000;
185 Length = RES_MEM_BASE_1 - BaseAddress;
186 Status = gDS->AddMemorySpace (
187 EfiGcdMemoryTypeMemoryMappedIo,
188 BaseAddress,
189 Length,
190 0
191 );
192
193 return EFI_SUCCESS;
194 }
195
196
197 EFI_STATUS
198 EFIAPI
199 NotifyPhase(
200 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
201 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
202 )
203 /*++
204
205 Routine Description:
206 Enter a certain phase of the PCI enumeration process
207
208 Arguments:
209 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance
210 Phase -- The phase during enumeration
211
212 Returns:
213
214 --*/
215 {
216 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
217 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
218 PCI_RESOURCE_TYPE Index;
219 LIST_ENTRY *List;
220 EFI_PHYSICAL_ADDRESS BaseAddress;
221 UINT64 AddrLen;
222 UINTN BitsOfAlignment;
223 EFI_STATUS Status;
224 EFI_STATUS ReturnStatus;
225
226 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
227
228 switch (Phase) {
229
230 case EfiPciHostBridgeBeginEnumeration:
231 if (HostBridgeInstance->CanRestarted) {
232 //
233 // Reset the Each Root Bridge
234 //
235 List = HostBridgeInstance->Head.ForwardLink;
236
237 while (List != &HostBridgeInstance->Head) {
238 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
239 for (Index = TypeIo; Index < TypeMax; Index++) {
240 RootBridgeInstance->ResAllocNode[Index].Type = Index;
241 RootBridgeInstance->ResAllocNode[Index].Base = 0;
242 RootBridgeInstance->ResAllocNode[Index].Length = 0;
243 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
244 }
245
246 List = List->ForwardLink;
247 }
248
249 HostBridgeInstance->ResourceSubmited = FALSE;
250 HostBridgeInstance->CanRestarted = TRUE;
251 } else {
252 //
253 // Can not restart
254 //
255 return EFI_NOT_READY;
256 }
257 break;
258
259 case EfiPciHostBridgeBeginBusAllocation:
260 //
261 // No specific action is required here, can perform any chipset specific programing
262 //
263 HostBridgeInstance->CanRestarted = FALSE;
264 return EFI_SUCCESS;
265 break;
266
267 case EfiPciHostBridgeEndBusAllocation:
268 //
269 // No specific action is required here, can perform any chipset specific programing
270 //
271 //HostBridgeInstance->CanRestarted = FALSE;
272 return EFI_SUCCESS;
273 break;
274
275 case EfiPciHostBridgeBeginResourceAllocation:
276 //
277 // No specific action is required here, can perform any chipset specific programing
278 //
279 //HostBridgeInstance->CanRestarted = FALSE;
280 return EFI_SUCCESS;
281 break;
282
283 case EfiPciHostBridgeAllocateResources:
284 ReturnStatus = EFI_SUCCESS;
285 if (HostBridgeInstance->ResourceSubmited) {
286 //
287 // Take care of the resource dependencies between the root bridges
288 //
289 List = HostBridgeInstance->Head.ForwardLink;
290
291 while (List != &HostBridgeInstance->Head) {
292 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
293 for (Index = TypeIo; Index < TypeBus; Index++) {
294 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
295
296 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
297
298 //
299 // Get the number of '1' in Alignment.
300 //
301 BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1;
302
303 switch (Index) {
304
305 case TypeIo:
306 //
307 // It is impossible for this chipset to align 0xFFFF for IO16
308 // So clear it
309 //
310 if (BitsOfAlignment >= 16) {
311 BitsOfAlignment = 0;
312 }
313
314 Status = gDS->AllocateIoSpace (
315 EfiGcdAllocateAnySearchBottomUp,
316 EfiGcdIoTypeIo,
317 BitsOfAlignment,
318 AddrLen,
319 &BaseAddress,
320 mDriverImageHandle,
321 NULL
322 );
323
324 if (!EFI_ERROR (Status)) {
325 RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
326 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
327 } else {
328 ReturnStatus = Status;
329 if (Status != EFI_OUT_OF_RESOURCES) {
330 RootBridgeInstance->ResAllocNode[Index].Length = 0;
331 }
332 }
333
334 break;
335
336
337 case TypeMem32:
338 //
339 // It is impossible for this chipset to align 0xFFFFFFFF for Mem32
340 // So clear it
341 //
342
343 if (BitsOfAlignment >= 32) {
344 BitsOfAlignment = 0;
345 }
346
347 Status = gDS->AllocateMemorySpace (
348 EfiGcdAllocateAnySearchBottomUp,
349 EfiGcdMemoryTypeMemoryMappedIo,
350 BitsOfAlignment,
351 AddrLen,
352 &BaseAddress,
353 mDriverImageHandle,
354 NULL
355 );
356
357 if (!EFI_ERROR (Status)) {
358 // We were able to allocate the PCI memory
359 RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
360 RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
361
362 } else {
363 // Not able to allocate enough PCI memory
364 ReturnStatus = Status;
365
366 if (Status != EFI_OUT_OF_RESOURCES) {
367 RootBridgeInstance->ResAllocNode[Index].Length = 0;
368 }
369 ASSERT (FALSE);
370 }
371 break;
372
373 case TypePMem32:
374 case TypeMem64:
375 case TypePMem64:
376 ReturnStatus = EFI_ABORTED;
377 break;
378 default:
379 ASSERT (FALSE);
380 break;
381 }; //end switch
382 }
383 }
384
385 List = List->ForwardLink;
386 }
387
388 return ReturnStatus;
389
390 } else {
391 return EFI_NOT_READY;
392 }
393 break;
394
395 case EfiPciHostBridgeSetResources:
396 break;
397
398 case EfiPciHostBridgeFreeResources:
399 ReturnStatus = EFI_SUCCESS;
400 List = HostBridgeInstance->Head.ForwardLink;
401 while (List != &HostBridgeInstance->Head) {
402 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
403 for (Index = TypeIo; Index < TypeBus; Index++) {
404 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
405 AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
406 BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
407 switch (Index) {
408
409 case TypeIo:
410 Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
411 if (EFI_ERROR (Status)) {
412 ReturnStatus = Status;
413 }
414 break;
415
416 case TypeMem32:
417 Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
418 if (EFI_ERROR (Status)) {
419 ReturnStatus = Status;
420 }
421 break;
422
423 case TypePMem32:
424 break;
425
426 case TypeMem64:
427 break;
428
429 case TypePMem64:
430 break;
431
432 default:
433 ASSERT (FALSE);
434 break;
435
436 }; //end switch
437 RootBridgeInstance->ResAllocNode[Index].Type = Index;
438 RootBridgeInstance->ResAllocNode[Index].Base = 0;
439 RootBridgeInstance->ResAllocNode[Index].Length = 0;
440 RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
441 }
442 }
443
444 List = List->ForwardLink;
445 }
446
447 HostBridgeInstance->ResourceSubmited = FALSE;
448 HostBridgeInstance->CanRestarted = TRUE;
449 return ReturnStatus;
450 break;
451
452 case EfiPciHostBridgeEndResourceAllocation:
453 HostBridgeInstance->CanRestarted = FALSE;
454 break;
455
456 default:
457 return EFI_INVALID_PARAMETER;
458 }; // end switch
459
460 return EFI_SUCCESS;
461 }
462
463 EFI_STATUS
464 EFIAPI
465 GetNextRootBridge(
466 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
467 IN OUT EFI_HANDLE *RootBridgeHandle
468 )
469 /*++
470
471 Routine Description:
472 Return the device handle of the next PCI root bridge that is associated with
473 this Host Bridge
474
475 Arguments:
476 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
477 RootBridgeHandle -- Returns the device handle of the next PCI Root Bridge.
478 On input, it holds the RootBridgeHandle returned by the most
479 recent call to GetNextRootBridge().The handle for the first
480 PCI Root Bridge is returned if RootBridgeHandle is NULL on input
481
482 Returns:
483
484 --*/
485 {
486 BOOLEAN NoRootBridge;
487 LIST_ENTRY *List;
488 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
489 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
490
491 NoRootBridge = TRUE;
492 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
493 List = HostBridgeInstance->Head.ForwardLink;
494
495
496 while (List != &HostBridgeInstance->Head) {
497 NoRootBridge = FALSE;
498 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
499 if (*RootBridgeHandle == NULL) {
500 //
501 // Return the first Root Bridge Handle of the Host Bridge
502 //
503 *RootBridgeHandle = RootBridgeInstance->Handle;
504 return EFI_SUCCESS;
505 } else {
506 if (*RootBridgeHandle == RootBridgeInstance->Handle) {
507 //
508 // Get next if have
509 //
510 List = List->ForwardLink;
511 if (List!=&HostBridgeInstance->Head) {
512 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
513 *RootBridgeHandle = RootBridgeInstance->Handle;
514 return EFI_SUCCESS;
515 } else {
516 return EFI_NOT_FOUND;
517 }
518 }
519 }
520
521 List = List->ForwardLink;
522 } //end while
523
524 if (NoRootBridge) {
525 return EFI_NOT_FOUND;
526 } else {
527 return EFI_INVALID_PARAMETER;
528 }
529 }
530
531 EFI_STATUS
532 EFIAPI
533 GetAttributes(
534 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
535 IN EFI_HANDLE RootBridgeHandle,
536 OUT UINT64 *Attributes
537 )
538 /*++
539
540 Routine Description:
541 Returns the attributes of a PCI Root Bridge.
542
543 Arguments:
544 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
545 RootBridgeHandle -- The device handle of the PCI Root Bridge
546 that the caller is interested in
547 Attribute -- The pointer to attributes of the PCI Root Bridge
548
549 Returns:
550
551 --*/
552 {
553 LIST_ENTRY *List;
554 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
555 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
556
557 if (Attributes == NULL) {
558 return EFI_INVALID_PARAMETER;
559 }
560
561 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
562 List = HostBridgeInstance->Head.ForwardLink;
563
564 while (List != &HostBridgeInstance->Head) {
565 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
566 if (RootBridgeHandle == RootBridgeInstance->Handle) {
567 *Attributes = RootBridgeInstance->RootBridgeAttrib;
568 return EFI_SUCCESS;
569 }
570 List = List->ForwardLink;
571 }
572
573 //
574 // RootBridgeHandle is not an EFI_HANDLE
575 // that was returned on a previous call to GetNextRootBridge()
576 //
577 return EFI_INVALID_PARAMETER;
578 }
579
580 EFI_STATUS
581 EFIAPI
582 StartBusEnumeration(
583 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
584 IN EFI_HANDLE RootBridgeHandle,
585 OUT VOID **Configuration
586 )
587 /*++
588
589 Routine Description:
590 This is the request from the PCI enumerator to set up
591 the specified PCI Root Bridge for bus enumeration process.
592
593 Arguments:
594 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
595 RootBridgeHandle -- The PCI Root Bridge to be set up
596 Configuration -- Pointer to the pointer to the PCI bus resource descriptor
597
598 Returns:
599
600 --*/
601 {
602 LIST_ENTRY *List;
603 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
604 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
605 VOID *Buffer;
606 UINT8 *Temp;
607 UINT64 BusStart;
608 UINT64 BusEnd;
609
610 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
611 List = HostBridgeInstance->Head.ForwardLink;
612
613 while (List != &HostBridgeInstance->Head) {
614 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
615 if (RootBridgeHandle == RootBridgeInstance->Handle) {
616 //
617 // Set up the Root Bridge for Bus Enumeration
618 //
619 BusStart = RootBridgeInstance->BusBase;
620 BusEnd = RootBridgeInstance->BusLimit;
621 //
622 // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
623 //
624
625 Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
626 if (Buffer == NULL) {
627 return EFI_OUT_OF_RESOURCES;
628 }
629
630 Temp = (UINT8 *)Buffer;
631
632 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
633 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
634 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
635 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
636 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
637 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
638 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
639 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
640 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
641 ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;
642
643 Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
644 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
645 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
646
647 *Configuration = Buffer;
648 return EFI_SUCCESS;
649 }
650 List = List->ForwardLink;
651 }
652
653 return EFI_INVALID_PARAMETER;
654 }
655
656 EFI_STATUS
657 EFIAPI
658 SetBusNumbers(
659 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
660 IN EFI_HANDLE RootBridgeHandle,
661 IN VOID *Configuration
662 )
663 /*++
664
665 Routine Description:
666 This function programs the PCI Root Bridge hardware so that
667 it decodes the specified PCI bus range
668
669 Arguments:
670 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
671 RootBridgeHandle -- The PCI Root Bridge whose bus range is to be programmed
672 Configuration -- The pointer to the PCI bus resource descriptor
673
674 Returns:
675
676 --*/
677 {
678 LIST_ENTRY *List;
679 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
680 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
681 UINT8 *Ptr;
682 UINTN BusStart;
683 UINTN BusEnd;
684 UINTN BusLen;
685
686 if (Configuration == NULL) {
687 return EFI_INVALID_PARAMETER;
688 }
689
690 Ptr = Configuration;
691
692 //
693 // Check the Configuration is valid
694 //
695 if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
696 return EFI_INVALID_PARAMETER;
697 }
698
699 if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
700 return EFI_INVALID_PARAMETER;
701 }
702
703 Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
704 if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
705 return EFI_INVALID_PARAMETER;
706 }
707
708 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
709 List = HostBridgeInstance->Head.ForwardLink;
710
711 Ptr = Configuration;
712
713 while (List != &HostBridgeInstance->Head) {
714 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
715 if (RootBridgeHandle == RootBridgeInstance->Handle) {
716 BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
717 BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
718 BusEnd = BusStart + BusLen - 1;
719
720 if (BusStart > BusEnd) {
721 return EFI_INVALID_PARAMETER;
722 }
723
724 if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
725 return EFI_INVALID_PARAMETER;
726 }
727
728 //
729 // Update the Bus Range
730 //
731 RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
732 RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
733 RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
734
735 //
736 // Program the Root Bridge Hardware
737 //
738
739 return EFI_SUCCESS;
740 }
741
742 List = List->ForwardLink;
743 }
744
745 return EFI_INVALID_PARAMETER;
746 }
747
748
749 EFI_STATUS
750 EFIAPI
751 SubmitResources(
752 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
753 IN EFI_HANDLE RootBridgeHandle,
754 IN VOID *Configuration
755 )
756 /*++
757
758 Routine Description:
759 Submits the I/O and memory resource requirements for the specified PCI Root Bridge
760
761 Arguments:
762 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
763 RootBridgeHandle -- The PCI Root Bridge whose I/O and memory resource requirements
764 are being submitted
765 Configuration -- The pointer to the PCI I/O and PCI memory resource descriptor
766 Returns:
767
768 --*/
769 {
770 LIST_ENTRY *List;
771 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
772 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
773 UINT8 *Temp;
774 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
775 UINT64 AddrLen;
776 UINT64 Alignment;
777
778 //
779 // Check the input parameter: Configuration
780 //
781 if (Configuration == NULL) {
782 return EFI_INVALID_PARAMETER;
783 }
784
785 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
786 List = HostBridgeInstance->Head.ForwardLink;
787
788 Temp = (UINT8 *)Configuration;
789 while ( *Temp == 0x8A) {
790 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
791 }
792 if (*Temp != 0x79) {
793 return EFI_INVALID_PARAMETER;
794 }
795
796 Temp = (UINT8 *)Configuration;
797 while (List != &HostBridgeInstance->Head) {
798 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
799 if (RootBridgeHandle == RootBridgeInstance->Handle) {
800 while ( *Temp == 0x8A) {
801 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
802
803 //
804 // Check Address Length
805 //
806 if (ptr->AddrLen > 0xffffffff) {
807 return EFI_INVALID_PARAMETER;
808 }
809
810 //
811 // Check address range alignment
812 //
813 if (ptr->AddrRangeMax >= 0xffffffff || ptr->AddrRangeMax != (GetPowerOfTwo64 (ptr->AddrRangeMax + 1) - 1)) {
814 return EFI_INVALID_PARAMETER;
815 }
816
817 switch (ptr->ResType) {
818
819 case 0:
820
821 //
822 // Check invalid Address Sapce Granularity
823 //
824 if (ptr->AddrSpaceGranularity != 32) {
825 return EFI_INVALID_PARAMETER;
826 }
827
828 //
829 // check the memory resource request is supported by PCI root bridge
830 //
831 if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
832 ptr->SpecificFlag == 0x06) {
833 return EFI_INVALID_PARAMETER;
834 }
835
836 AddrLen = ptr->AddrLen;
837 Alignment = ptr->AddrRangeMax;
838 if (ptr->AddrSpaceGranularity == 32) {
839 if (ptr->SpecificFlag == 0x06) {
840 //
841 // Apply from GCD
842 //
843 RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
844 } else {
845 RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
846 RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
847 RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
848 HostBridgeInstance->ResourceSubmited = TRUE;
849 }
850 }
851
852 if (ptr->AddrSpaceGranularity == 64) {
853 if (ptr->SpecificFlag == 0x06) {
854 RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
855 } else {
856 RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
857 }
858 }
859 break;
860
861 case 1:
862 AddrLen = (UINTN)ptr->AddrLen;
863 Alignment = (UINTN)ptr->AddrRangeMax;
864 RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
865 RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
866 RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
867 HostBridgeInstance->ResourceSubmited = TRUE;
868 break;
869
870 default:
871 break;
872 };
873
874 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
875 }
876
877 return EFI_SUCCESS;
878 }
879
880 List = List->ForwardLink;
881 }
882
883 return EFI_INVALID_PARAMETER;
884 }
885
886 EFI_STATUS
887 EFIAPI
888 GetProposedResources(
889 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
890 IN EFI_HANDLE RootBridgeHandle,
891 OUT VOID **Configuration
892 )
893 /*++
894
895 Routine Description:
896 This function returns the proposed resource settings for the specified
897 PCI Root Bridge
898
899 Arguments:
900 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
901 RootBridgeHandle -- The PCI Root Bridge handle
902 Configuration -- The pointer to the pointer to the PCI I/O
903 and memory resource descriptor
904
905 Returns:
906
907 --*/
908 {
909 LIST_ENTRY *List;
910 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
911 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
912 UINTN Index;
913 UINTN Number;
914 VOID *Buffer;
915 UINT8 *Temp;
916 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
917 UINT64 ResStatus;
918
919 Buffer = NULL;
920 Number = 0;
921 //
922 // Get the Host Bridge Instance from the resource allocation protocol
923 //
924 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
925 List = HostBridgeInstance->Head.ForwardLink;
926
927 //
928 // Enumerate the root bridges in this host bridge
929 //
930 while (List != &HostBridgeInstance->Head) {
931 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
932 if (RootBridgeHandle == RootBridgeInstance->Handle) {
933 for (Index = 0; Index < TypeBus; Index ++) {
934 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
935 Number ++;
936 }
937 }
938
939 if (Number == 0) {
940 return EFI_INVALID_PARAMETER;
941 }
942
943 Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
944 if (Buffer == NULL) {
945 return EFI_OUT_OF_RESOURCES;
946 }
947
948 Temp = Buffer;
949 for (Index = 0; Index < TypeBus; Index ++) {
950 if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
951 ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
952 ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
953
954 switch (Index) {
955
956 case TypeIo:
957 //
958 // Io
959 //
960 ptr->Desc = 0x8A;
961 ptr->Len = 0x2B;
962 ptr->ResType = 1;
963 ptr->GenFlag = 0;
964 ptr->SpecificFlag = 0;
965 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
966 ptr->AddrRangeMax = 0;
967 ptr->AddrTranslationOffset = \
968 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
969 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
970 break;
971
972 case TypeMem32:
973 //
974 // Memory 32
975 //
976 ptr->Desc = 0x8A;
977 ptr->Len = 0x2B;
978 ptr->ResType = 0;
979 ptr->GenFlag = 0;
980 ptr->SpecificFlag = 0;
981 ptr->AddrSpaceGranularity = 32;
982 ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
983 ptr->AddrRangeMax = 0;
984 ptr->AddrTranslationOffset = \
985 (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
986 ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
987 break;
988
989 case TypePMem32:
990 //
991 // Prefetch memory 32
992 //
993 ptr->Desc = 0x8A;
994 ptr->Len = 0x2B;
995 ptr->ResType = 0;
996 ptr->GenFlag = 0;
997 ptr->SpecificFlag = 6;
998 ptr->AddrSpaceGranularity = 32;
999 ptr->AddrRangeMin = 0;
1000 ptr->AddrRangeMax = 0;
1001 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1002 ptr->AddrLen = 0;
1003 break;
1004
1005 case TypeMem64:
1006 //
1007 // Memory 64
1008 //
1009 ptr->Desc = 0x8A;
1010 ptr->Len = 0x2B;
1011 ptr->ResType = 0;
1012 ptr->GenFlag = 0;
1013 ptr->SpecificFlag = 0;
1014 ptr->AddrSpaceGranularity = 64;
1015 ptr->AddrRangeMin = 0;
1016 ptr->AddrRangeMax = 0;
1017 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1018 ptr->AddrLen = 0;
1019 break;
1020
1021 case TypePMem64:
1022 //
1023 // Prefetch memory 64
1024 //
1025 ptr->Desc = 0x8A;
1026 ptr->Len = 0x2B;
1027 ptr->ResType = 0;
1028 ptr->GenFlag = 0;
1029 ptr->SpecificFlag = 6;
1030 ptr->AddrSpaceGranularity = 64;
1031 ptr->AddrRangeMin = 0;
1032 ptr->AddrRangeMax = 0;
1033 ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1034 ptr->AddrLen = 0;
1035 break;
1036 };
1037
1038 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1039 }
1040 }
1041
1042 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
1043 ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
1044
1045 *Configuration = Buffer;
1046
1047 return EFI_SUCCESS;
1048 }
1049
1050 List = List->ForwardLink;
1051 }
1052
1053 return EFI_INVALID_PARAMETER;
1054 }
1055
1056 STATIC
1057 VOID
1058 UpdateRootBridgeAttributes (
1059 IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,
1060 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
1061 )
1062 {
1063 EFI_STATUS Status;
1064 PCI_TYPE01 PciConfigurationHeader;
1065 UINT64 Attributes;
1066
1067 //
1068 // Read the PCI Configuration Header for the device
1069 //
1070 Status = RootBridge->Io.Pci.Read (
1071 &RootBridge->Io,
1072 EfiPciWidthUint16,
1073 EFI_PCI_ADDRESS(
1074 PciAddress.Bus,
1075 PciAddress.Device,
1076 PciAddress.Function,
1077 0
1078 ),
1079 sizeof (PciConfigurationHeader) / sizeof (UINT16),
1080 &PciConfigurationHeader
1081 );
1082 if (EFI_ERROR (Status)) {
1083 return;
1084 }
1085
1086 Attributes = RootBridge->Attributes;
1087
1088 //
1089 // Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
1090 //
1091 if (PciConfigurationHeader.Hdr.Command & 0x20) {
1092 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
1093 }
1094
1095 //
1096 // If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
1097 //
1098 if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
1099 //
1100 // Look at the PPB Configuration for legacy decoding attributes
1101 //
1102 if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
1103 Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
1104 Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
1105 }
1106 if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
1107 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
1108 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
1109 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
1110 }
1111 } else {
1112 //
1113 // See if the PCI device is an IDE controller
1114 //
1115 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
1116 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
1117 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
1118 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
1119 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
1120 }
1121 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
1122 Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
1123 }
1124 if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
1125 Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
1126 }
1127 }
1128
1129 //
1130 // See if the PCI device is a legacy VGA controller
1131 //
1132 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
1133 PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
1134 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
1135 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
1136 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
1137 }
1138
1139 //
1140 // See if the PCI device is a standard VGA controller
1141 //
1142 if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
1143 PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {
1144 Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
1145 Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
1146 Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
1147 }
1148 }
1149
1150 RootBridge->Attributes = Attributes;
1151 RootBridge->Supports = Attributes;
1152 }
1153
1154 EFI_STATUS
1155 EFIAPI
1156 PreprocessController (
1157 IN struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1158 IN EFI_HANDLE RootBridgeHandle,
1159 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1160 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1161 )
1162 /*++
1163
1164 Routine Description:
1165 This function is called for all the PCI controllers that the PCI
1166 bus driver finds. Can be used to Preprogram the controller.
1167
1168 Arguments:
1169 This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
1170 RootBridgeHandle -- The PCI Root Bridge handle
1171 PciBusAddress -- Address of the controller on the PCI bus
1172 Phase -- The Phase during resource allocation
1173
1174 Returns:
1175 EFI_SUCCESS
1176 --*/
1177 {
1178 PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
1179 PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
1180 LIST_ENTRY *List;
1181
1182 HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1183 List = HostBridgeInstance->Head.ForwardLink;
1184
1185 //
1186 // Enumerate the root bridges in this host bridge
1187 //
1188 while (List != &HostBridgeInstance->Head) {
1189 RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1190 if (RootBridgeHandle == RootBridgeInstance->Handle) {
1191 UpdateRootBridgeAttributes (
1192 RootBridgeInstance,
1193 PciAddress
1194 );
1195 return EFI_SUCCESS;
1196 }
1197 List = List->ForwardLink;
1198 }
1199
1200 return EFI_INVALID_PARAMETER;
1201 }