blob: 17ea03ccf486eed9ab575625d69b0605f486a52f [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/** @file
2
3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "PciEmulation.h"
16
17EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
18
19#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
20
21typedef struct {
22 ACPI_HID_DEVICE_PATH AcpiDevicePath;
23 PCI_DEVICE_PATH PciDevicePath;
24 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
25} EFI_PCI_IO_DEVICE_PATH;
26
27typedef struct {
28 UINT32 Signature;
29 EFI_PCI_IO_DEVICE_PATH DevicePath;
30 EFI_PCI_IO_PROTOCOL PciIoProtocol;
31 PCI_TYPE00 *ConfigSpace;
32 PCI_ROOT_BRIDGE RootBridge;
33 UINTN Segment;
34} EFI_PCI_IO_PRIVATE_DATA;
35
36#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
37#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
38
39EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
40{
41 {
42 { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },
43 EISA_PNP_ID(0x0A03), // HID
44 0 // UID
45 },
46 {
47 { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },
48 0,
49 0
50 },
51 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
52};
53
54STATIC
55VOID
56ConfigureUSBHost (
57 VOID
58 )
59{
60 EFI_STATUS Status;
61 UINT8 Data = 0;
62
63 // Take USB host out of force-standby mode
64 MmioWrite32 (UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY
65 | UHH_SYSCONFIG_CLOCKACTIVITY_ON
66 | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY
67 | UHH_SYSCONFIG_ENAWAKEUP_ENABLE
68 | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN);
69 MmioWrite32 (UHH_HOSTCONFIG, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT
70 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT
71 | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT
72 | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE
73 | UHH_HOSTCONFIG_ENA_INCR16_ENABLE
74 | UHH_HOSTCONFIG_ENA_INCR8_ENABLE
75 | UHH_HOSTCONFIG_ENA_INCR4_ENABLE
76 | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON
77 | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE);
78
79 // USB reset (GPIO 147 - Port 5 pin 19) output high
80 MmioAnd32 (GPIO5_BASE + GPIO_OE, ~BIT19);
81 MmioWrite32 (GPIO5_BASE + GPIO_SETDATAOUT, BIT19);
82
83 // Get the Power IC protocol
84 Status = gBS->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
85 ASSERT_EFI_ERROR (Status);
86
87 // Power the USB PHY
88 Data = VAUX_DEV_GRP_P1;
89 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VAUX2_DEV_GRP), 1, &Data);
90 ASSERT_EFI_ERROR(Status);
91
92 Data = VAUX_DEDICATED_18V;
93 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VAUX2_DEDICATED), 1, &Data);
94 ASSERT_EFI_ERROR (Status);
95
96 // Enable power to the USB hub
97 Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
98 ASSERT_EFI_ERROR (Status);
99
100 // LEDAON controls the power to the USB host, PWM is disabled
101 Data &= ~LEDAPWM;
102 Data |= LEDAON;
103
104 Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
105 ASSERT_EFI_ERROR (Status);
106}
107
108
109EFI_STATUS
110PciIoPollMem (
111 IN EFI_PCI_IO_PROTOCOL *This,
112 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
113 IN UINT8 BarIndex,
114 IN UINT64 Offset,
115 IN UINT64 Mask,
116 IN UINT64 Value,
117 IN UINT64 Delay,
118 OUT UINT64 *Result
119 )
120{
121 ASSERT (FALSE);
122 return EFI_UNSUPPORTED;
123}
124
125EFI_STATUS
126PciIoPollIo (
127 IN EFI_PCI_IO_PROTOCOL *This,
128 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
129 IN UINT8 BarIndex,
130 IN UINT64 Offset,
131 IN UINT64 Mask,
132 IN UINT64 Value,
133 IN UINT64 Delay,
134 OUT UINT64 *Result
135 )
136{
137 ASSERT (FALSE);
138 return EFI_UNSUPPORTED;
139}
140
141EFI_STATUS
142PciIoMemRead (
143 IN EFI_PCI_IO_PROTOCOL *This,
144 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
145 IN UINT8 BarIndex,
146 IN UINT64 Offset,
147 IN UINTN Count,
148 IN OUT VOID *Buffer
149 )
150{
151 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
152
153 return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
154 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
155 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
156 Count,
157 Buffer
158 );
159}
160
161EFI_STATUS
162PciIoMemWrite (
163 IN EFI_PCI_IO_PROTOCOL *This,
164 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
165 IN UINT8 BarIndex,
166 IN UINT64 Offset,
167 IN UINTN Count,
168 IN OUT VOID *Buffer
169 )
170{
171 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
172
173 return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
174 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
175 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
176 Count,
177 Buffer
178 );
179}
180
181EFI_STATUS
182PciIoIoRead (
183 IN EFI_PCI_IO_PROTOCOL *This,
184 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
185 IN UINT8 BarIndex,
186 IN UINT64 Offset,
187 IN UINTN Count,
188 IN OUT VOID *Buffer
189 )
190{
191 ASSERT (FALSE);
192 return EFI_UNSUPPORTED;
193}
194
195EFI_STATUS
196PciIoIoWrite (
197 IN EFI_PCI_IO_PROTOCOL *This,
198 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
199 IN UINT8 BarIndex,
200 IN UINT64 Offset,
201 IN UINTN Count,
202 IN OUT VOID *Buffer
203 )
204{
205 ASSERT (FALSE);
206 return EFI_UNSUPPORTED;
207}
208
209/**
210 Enable a PCI driver to read PCI controller registers in PCI configuration space.
211
212 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
213 @param[in] Width Signifies the width of the memory operations.
214 @param[in] Offset The offset within the PCI configuration space for
215 the PCI controller.
216 @param[in] Count The number of PCI configuration operations to
217 perform. Bytes moved is Width size * Count,
218 starting at Offset.
219
220 @param[in out] Buffer The destination buffer to store the results.
221
222 @retval EFI_SUCCESS The data was read from the PCI controller.
223 @retval EFI_INVALID_PARAMETER "Width" is invalid.
224 @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
225
226**/
227EFI_STATUS
228PciIoPciRead (
229 IN EFI_PCI_IO_PROTOCOL *This,
230 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
231 IN UINT32 Offset,
232 IN UINTN Count,
233 IN OUT VOID *Buffer
234 )
235{
236 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
237 EFI_STATUS Status;
238
239 if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
240 return EFI_INVALID_PARAMETER;
241 }
242
243 Status = PciRootBridgeIoMemRW (
244 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
245 Count,
246 TRUE,
247 (PTR)(UINTN)Buffer,
248 TRUE,
249 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace
250 );
251
252 return Status;
253}
254
255/**
256 Enable a PCI driver to write PCI controller registers in PCI configuration space.
257
258 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
259 @param[in] Width Signifies the width of the memory operations.
260 @param[in] Offset The offset within the PCI configuration space for
261 the PCI controller.
262 @param[in] Count The number of PCI configuration operations to
263 perform. Bytes moved is Width size * Count,
264 starting at Offset.
265
266 @param[in out] Buffer The source buffer to write data from.
267
268 @retval EFI_SUCCESS The data was read from the PCI controller.
269 @retval EFI_INVALID_PARAMETER "Width" is invalid.
270 @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
271
272**/
273EFI_STATUS
274PciIoPciWrite (
275 IN EFI_PCI_IO_PROTOCOL *This,
276 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
277 IN UINT32 Offset,
278 IN UINTN Count,
279 IN OUT VOID *Buffer
280 )
281{
282 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
283
284 if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) {
285 return EFI_INVALID_PARAMETER;
286 }
287
288 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
289 Count,
290 TRUE,
291 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
292 TRUE,
293 (PTR)(UINTN)Buffer
294 );
295}
296
297EFI_STATUS
298PciIoCopyMem (
299 IN EFI_PCI_IO_PROTOCOL *This,
300 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
301 IN UINT8 DestBarIndex,
302 IN UINT64 DestOffset,
303 IN UINT8 SrcBarIndex,
304 IN UINT64 SrcOffset,
305 IN UINTN Count
306 )
307{
308 ASSERT (FALSE);
309 return EFI_UNSUPPORTED;
310}
311
312EFI_STATUS
313PciIoMap (
314 IN EFI_PCI_IO_PROTOCOL *This,
315 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
316 IN VOID *HostAddress,
317 IN OUT UINTN *NumberOfBytes,
318 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
319 OUT VOID **Mapping
320 )
321{
322 DMA_MAP_OPERATION DmaOperation;
323
324 if (Operation == EfiPciIoOperationBusMasterRead) {
325 DmaOperation = MapOperationBusMasterRead;
326 } else if (Operation == EfiPciIoOperationBusMasterWrite) {
327 DmaOperation = MapOperationBusMasterWrite;
328 } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {
329 DmaOperation = MapOperationBusMasterCommonBuffer;
330 } else {
331 return EFI_INVALID_PARAMETER;
332 }
333 return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
334}
335
336EFI_STATUS
337PciIoUnmap (
338 IN EFI_PCI_IO_PROTOCOL *This,
339 IN VOID *Mapping
340 )
341{
342 return DmaUnmap (Mapping);
343}
344
345/**
346 Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
347 mapping.
348
349 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
350 @param[in] Type This parameter is not used and must be ignored.
351 @param[in] MemoryType The type of memory to allocate, EfiBootServicesData or
352 EfiRuntimeServicesData.
353 @param[in] Pages The number of pages to allocate.
354 @param[out] HostAddress A pointer to store the base system memory address of
355 the allocated range.
356 @param[in] Attributes The requested bit mask of attributes for the allocated
357 range. Only the attributes,
358 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and
359 EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this
360 function. If any other bits are set, then EFI_UNSUPPORTED
361 is returned. This function ignores this bit mask.
362
363 @retval EFI_SUCCESS The requested memory pages were allocated.
364 @retval EFI_INVALID_PARAMETER HostAddress is NULL.
365 @retval EFI_INVALID_PARAMETER MemoryType is invalid.
366 @retval EFI_UNSUPPORTED Attributes is unsupported.
367 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
368
369**/
370EFI_STATUS
371PciIoAllocateBuffer (
372 IN EFI_PCI_IO_PROTOCOL *This,
373 IN EFI_ALLOCATE_TYPE Type,
374 IN EFI_MEMORY_TYPE MemoryType,
375 IN UINTN Pages,
376 OUT VOID **HostAddress,
377 IN UINT64 Attributes
378 )
379{
380 if (Attributes &
381 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE |
382 EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) {
383 return EFI_UNSUPPORTED;
384 }
385
386 return DmaAllocateBuffer (MemoryType, Pages, HostAddress);
387}
388
389
390EFI_STATUS
391PciIoFreeBuffer (
392 IN EFI_PCI_IO_PROTOCOL *This,
393 IN UINTN Pages,
394 IN VOID *HostAddress
395 )
396{
397 return DmaFreeBuffer (Pages, HostAddress);
398}
399
400
401EFI_STATUS
402PciIoFlush (
403 IN EFI_PCI_IO_PROTOCOL *This
404 )
405{
406 return EFI_SUCCESS;
407}
408
409/**
410 Retrieves this PCI controller's current PCI bus number, device number, and function number.
411
412 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
413 @param[out] SegmentNumber The PCI controller's current PCI segment number.
414 @param[out] BusNumber The PCI controller's current PCI bus number.
415 @param[out] DeviceNumber The PCI controller's current PCI device number.
416 @param[out] FunctionNumber The PCI controller’s current PCI function number.
417
418 @retval EFI_SUCCESS The PCI controller location was returned.
419 @retval EFI_INVALID_PARAMETER At least one out of the four output parameters is
420 a NULL pointer.
421**/
422EFI_STATUS
423PciIoGetLocation (
424 IN EFI_PCI_IO_PROTOCOL *This,
425 OUT UINTN *SegmentNumber,
426 OUT UINTN *BusNumber,
427 OUT UINTN *DeviceNumber,
428 OUT UINTN *FunctionNumber
429 )
430{
431 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);
432
433 if ((SegmentNumber == NULL) || (BusNumber == NULL) ||
434 (DeviceNumber == NULL) || (FunctionNumber == NULL) ) {
435 return EFI_INVALID_PARAMETER;
436 }
437
438 *SegmentNumber = Private->Segment;
439 *BusNumber = 0xff;
440 *DeviceNumber = 0;
441 *FunctionNumber = 0;
442
443 return EFI_SUCCESS;
444}
445
446/**
447 Performs an operation on the attributes that this PCI controller supports.
448
449 The operations include getting the set of supported attributes, retrieving
450 the current attributes, setting the current attributes, enabling attributes,
451 and disabling attributes.
452
453 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
454 @param[in] Operation The operation to perform on the attributes for this
455 PCI controller.
456 @param[in] Attributes The mask of attributes that are used for Set,
457 Enable and Disable operations.
458 @param[out] Result A pointer to the result mask of attributes that are
459 returned for the Get and Supported operations. This
460 is an optional parameter that may be NULL for the
461 Set, Enable, and Disable operations.
462
463 @retval EFI_SUCCESS The operation on the PCI controller's
464 attributes was completed. If the operation
465 was Get or Supported, then the attribute mask
466 is returned in Result.
467 @retval EFI_INVALID_PARAMETER Operation is greater than or equal to
468 EfiPciIoAttributeOperationMaximum.
469 @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL.
470 @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL.
471
472**/
473EFI_STATUS
474PciIoAttributes (
475 IN EFI_PCI_IO_PROTOCOL *This,
476 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
477 IN UINT64 Attributes,
478 OUT UINT64 *Result OPTIONAL
479 )
480{
481 switch (Operation) {
482 case EfiPciIoAttributeOperationGet:
483 case EfiPciIoAttributeOperationSupported:
484 if (Result == NULL) {
485 return EFI_INVALID_PARAMETER;
486 }
487 //
488 // We are not a real PCI device so just say things we kind of do
489 //
490 *Result = EFI_PCI_DEVICE_ENABLE;
491 break;
492
493 case EfiPciIoAttributeOperationSet:
494 case EfiPciIoAttributeOperationEnable:
495 case EfiPciIoAttributeOperationDisable:
496 if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) {
497 return EFI_UNSUPPORTED;
498 }
499 // Since we are not a real PCI device no enable/set or disable operations exist.
500 return EFI_SUCCESS;
501
502 default:
503 return EFI_INVALID_PARAMETER;
504 };
505 return EFI_SUCCESS;
506}
507
508EFI_STATUS
509PciIoGetBarAttributes (
510 IN EFI_PCI_IO_PROTOCOL *This,
511 IN UINT8 BarIndex,
512 OUT UINT64 *Supports, OPTIONAL
513 OUT VOID **Resources OPTIONAL
514 )
515{
516 ASSERT (FALSE);
517 return EFI_UNSUPPORTED;
518}
519
520EFI_STATUS
521PciIoSetBarAttributes (
522 IN EFI_PCI_IO_PROTOCOL *This,
523 IN UINT64 Attributes,
524 IN UINT8 BarIndex,
525 IN OUT UINT64 *Offset,
526 IN OUT UINT64 *Length
527 )
528{
529 ASSERT (FALSE);
530 return EFI_UNSUPPORTED;
531}
532
533EFI_PCI_IO_PROTOCOL PciIoTemplate =
534{
535 PciIoPollMem,
536 PciIoPollIo,
537 { PciIoMemRead, PciIoMemWrite },
538 { PciIoIoRead, PciIoIoWrite },
539 { PciIoPciRead, PciIoPciWrite },
540 PciIoCopyMem,
541 PciIoMap,
542 PciIoUnmap,
543 PciIoAllocateBuffer,
544 PciIoFreeBuffer,
545 PciIoFlush,
546 PciIoGetLocation,
547 PciIoAttributes,
548 PciIoGetBarAttributes,
549 PciIoSetBarAttributes,
550 0,
551 0
552};
553
554EFI_STATUS
555EFIAPI
556PciEmulationEntryPoint (
557 IN EFI_HANDLE ImageHandle,
558 IN EFI_SYSTEM_TABLE *SystemTable
559 )
560{
561 EFI_STATUS Status;
562 EFI_HANDLE Handle;
563 EFI_PCI_IO_PRIVATE_DATA *Private;
564 UINT8 CapabilityLength;
565 UINT8 PhysicalPorts;
566 UINTN Count;
567
568
569 //Configure USB host for OMAP3530.
570 ConfigureUSBHost();
571
572 // Create a private structure
573 Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
574 if (Private == NULL) {
575 Status = EFI_OUT_OF_RESOURCES;
576 return Status;
577 }
578
579 Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
580 Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
581 Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base
582 Private->Segment = 0; // Default to segment zero
583
584 // Find out the capability register length and number of physical ports.
585 CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart);
586 PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
587
588 // Calculate the total size of the USB registers.
589 Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
590
591 // Enable Port Power bit in Port status and control registers in EHCI register space.
592 // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
593 // host controller implementation includes port power control.
594 for (Count = 0; Count < PhysicalPorts; Count++) {
595 MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
596 }
597
598 // Create fake PCI config space.
599 Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
600 if (Private->ConfigSpace == NULL) {
601 Status = EFI_OUT_OF_RESOURCES;
602 FreePool(Private);
603 return Status;
604 }
605
606 // Configure PCI config space
607 Private->ConfigSpace->Hdr.VendorId = 0xFFFF; // Invalid vendor Id as it is not an actual device.
608 Private->ConfigSpace->Hdr.DeviceId = 0x0000; // Not relevant as the vendor id is not valid.
609 Private->ConfigSpace->Hdr.ClassCode[0] = 0x20;
610 Private->ConfigSpace->Hdr.ClassCode[1] = 0x03;
611 Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
612 Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
613
614 Handle = NULL;
615
616 // Unique device path.
617 CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
618 Private->DevicePath.AcpiDevicePath.UID = 0;
619
620 // Copy protocol structure
621 CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
622
623 Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
624 &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
625 &gEfiDevicePathProtocolGuid, &Private->DevicePath,
626 NULL);
627 if (EFI_ERROR(Status)) {
628 DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
629 }
630
631 return Status;
632}
633