]> git.proxmox.com Git - mirror_edk2.git/blob - Omap35xxPkg/PciEmulation/PciEmulation.c
91761c451d94e69fb80761b14b49cfcb54fd53d2
[mirror_edk2.git] / Omap35xxPkg / PciEmulation / PciEmulation.c
1 /** @file
2
3 Copyright (c) 2008-2009, Apple Inc. All rights reserved.
4
5 All rights reserved. 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 #include <Omap3530/Omap3530.h>
17
18 EFI_CPU_ARCH_PROTOCOL *gCpu;
19 EMBEDDED_EXTERNAL_DEVICE *gTPS65950;
20
21 #define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
22
23 typedef struct {
24 ACPI_HID_DEVICE_PATH AcpiDevicePath;
25 PCI_DEVICE_PATH PciDevicePath;
26 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
27 } EFI_PCI_IO_DEVICE_PATH;
28
29 typedef struct {
30 UINT32 Signature;
31 EFI_PCI_IO_DEVICE_PATH DevicePath;
32 EFI_PCI_IO_PROTOCOL PciIoProtocol;
33 PCI_TYPE00 *ConfigSpace;
34 PCI_ROOT_BRIDGE RootBridge;
35 UINTN Segment;
36 } EFI_PCI_IO_PRIVATE_DATA;
37
38 #define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
39 #define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
40
41 EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =
42 {
43 {
44 { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0},
45 EISA_PNP_ID(0x0A03), // HID
46 0 // UID
47 },
48 {
49 { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0},
50 0,
51 0
52 },
53 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
54 };
55
56 STATIC
57 VOID
58 ConfigureUSBHost (
59 VOID
60 )
61 {
62 EFI_STATUS Status;
63 UINT8 Data = 0;
64
65 #if 0
66 // Take USB host out of force-standby mode
67 MmioWrite32 (UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY
68 | UHH_SYSCONFIG_CLOCKACTIVITY_ON
69 | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY
70 | UHH_SYSCONFIG_ENAWAKEUP_ENABLE
71 | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN);
72 MmioWrite32 (UHH_HOSTCONFIG, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT
73 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT
74 | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT
75 | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE
76 | UHH_HOSTCONFIG_ENA_INCR16_ENABLE
77 | UHH_HOSTCONFIG_ENA_INCR8_ENABLE
78 | UHH_HOSTCONFIG_ENA_INCR4_ENABLE
79 | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON
80 | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE);
81
82 // USB reset (GPIO 147 - Port 5 pin 19) output high
83 MmioAnd32(GPIO5_BASE + GPIO_OE, ~BIT19);
84 MmioWrite32 (GPIO5_BASE + GPIO_SETDATAOUT, BIT19);
85
86 // Get the Power IC protocol.
87 Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
88 ASSERT_EFI_ERROR(Status);
89
90 //Enable power to the USB host.
91 Status = gTPS65950->Read(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
92 ASSERT_EFI_ERROR(Status);
93
94 //LEDAON & LEDAPWM control the power to the USB host so enable those bits.
95 Data |= (LEDAON | LEDAPWM);
96
97 Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
98 ASSERT_EFI_ERROR(Status);
99 #else
100 // Get the Power IC protocol.
101 Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950);
102 ASSERT_EFI_ERROR(Status);
103
104 //Enable power to the USB host.
105 Status = gTPS65950->Read(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
106 ASSERT_EFI_ERROR(Status);
107
108 //LEDAON & LEDAPWM control the power to the USB host so enable those bits.
109 Data |= (LEDAON | LEDAPWM);
110
111 Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data);
112 ASSERT_EFI_ERROR(Status);
113
114 // USB reset (GPIO 147 - Port 5 pin 19) output low
115 MmioAnd32 (GPIO5_BASE + GPIO_OE, ~BIT19);
116 MmioWrite32 (GPIO5_BASE + GPIO_CLEARDATAOUT, BIT19);
117
118 // Turn on functional & interface clocks to the USBHOST power domain
119 MmioOr32 (CM_FCLKEN_USBHOST, CM_FCLKEN_USBHOST_EN_USBHOST2_ENABLE | CM_FCLKEN_USBHOST_EN_USBHOST1_ENABLE);
120 MmioOr32 (CM_ICLKEN_USBHOST, CM_ICLKEN_USBHOST_EN_USBHOST_ENABLE);
121 // Wait for clock to become active
122 while (0 == (MmioRead32 (CM_CLKSTST_USBHOST) & 1));
123
124
125
126 // Take USB host out of force-standby mode
127 MmioWrite32 (UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY
128 | UHH_SYSCONFIG_CLOCKACTIVITY_ON
129 | UHH_SYSCONFIG_ENAWAKEUP_ENABLE
130 | UHH_SYSCONFIG_SOFTRESET
131 );
132 while ((MmioRead32 (UHH_SYSSTATUS) & UHH_SYSSTATUS_RESETDONE) != UHH_SYSSTATUS_RESETDONE);
133
134 MmioWrite32 (UHH_SYSCONFIG, UHH_SYSCONFIG_CLOCKACTIVITY_ON
135 | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY
136 | UHH_SYSCONFIG_ENAWAKEUP_ENABLE
137 );
138
139
140 MmioWrite32 (UHH_HOSTCONFIG, UHH_HOSTCONFIG_ENA_INCR16_ENABLE
141 | UHH_HOSTCONFIG_ENA_INCR8_ENABLE
142 | UHH_HOSTCONFIG_ENA_INCR4_ENABLE
143 );
144
145 // USB reset output high
146 MmioWrite32 (GPIO5_BASE + GPIO_SETDATAOUT, BIT19);
147
148 #endif
149 }
150
151 EFI_STATUS
152 PciIoPollMem (
153 IN EFI_PCI_IO_PROTOCOL *This,
154 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
155 IN UINT8 BarIndex,
156 IN UINT64 Offset,
157 IN UINT64 Mask,
158 IN UINT64 Value,
159 IN UINT64 Delay,
160 OUT UINT64 *Result
161 )
162 {
163 ASSERT (FALSE);
164 return EFI_UNSUPPORTED;
165 }
166
167 EFI_STATUS
168 PciIoPollIo (
169 IN EFI_PCI_IO_PROTOCOL *This,
170 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
171 IN UINT8 BarIndex,
172 IN UINT64 Offset,
173 IN UINT64 Mask,
174 IN UINT64 Value,
175 IN UINT64 Delay,
176 OUT UINT64 *Result
177 )
178 {
179 ASSERT (FALSE);
180 return EFI_UNSUPPORTED;
181 }
182
183 EFI_STATUS
184 PciIoMemRead (
185 IN EFI_PCI_IO_PROTOCOL *This,
186 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
187 IN UINT8 BarIndex,
188 IN UINT64 Offset,
189 IN UINTN Count,
190 IN OUT VOID *Buffer
191 )
192 {
193 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
194
195 return PciRootBridgeIoMemRead (&Private->RootBridge.Io,
196 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
197 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
198 Count,
199 Buffer
200 );
201 }
202
203 EFI_STATUS
204 PciIoMemWrite (
205 IN EFI_PCI_IO_PROTOCOL *This,
206 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
207 IN UINT8 BarIndex,
208 IN UINT64 Offset,
209 IN UINTN Count,
210 IN OUT VOID *Buffer
211 )
212 {
213 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
214
215 return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,
216 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
217 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,
218 Count,
219 Buffer
220 );
221 }
222
223 EFI_STATUS
224 PciIoIoRead (
225 IN EFI_PCI_IO_PROTOCOL *This,
226 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
227 IN UINT8 BarIndex,
228 IN UINT64 Offset,
229 IN UINTN Count,
230 IN OUT VOID *Buffer
231 )
232 {
233 ASSERT (FALSE);
234 return EFI_UNSUPPORTED;
235 }
236
237 EFI_STATUS
238 PciIoIoWrite (
239 IN EFI_PCI_IO_PROTOCOL *This,
240 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
241 IN UINT8 BarIndex,
242 IN UINT64 Offset,
243 IN UINTN Count,
244 IN OUT VOID *Buffer
245 )
246 {
247 ASSERT (FALSE);
248 return EFI_UNSUPPORTED;
249 }
250
251 EFI_STATUS
252 PciIoPciRead (
253 IN EFI_PCI_IO_PROTOCOL *This,
254 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
255 IN UINT32 Offset,
256 IN UINTN Count,
257 IN OUT VOID *Buffer
258 )
259 {
260 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
261
262 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,
263 Count,
264 TRUE,
265 (PTR)(UINTN)Buffer,
266 TRUE,
267 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset)
268 );
269 }
270
271 EFI_STATUS
272 PciIoPciWrite (
273 IN EFI_PCI_IO_PROTOCOL *This,
274 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
275 IN UINT32 Offset,
276 IN UINTN Count,
277 IN OUT VOID *Buffer
278 )
279 {
280 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
281
282 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
283 Count,
284 TRUE,
285 (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),
286 TRUE,
287 (PTR)(UINTN)Buffer
288 );
289 }
290
291 EFI_STATUS
292 PciIoCopyMem (
293 IN EFI_PCI_IO_PROTOCOL *This,
294 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
295 IN UINT8 DestBarIndex,
296 IN UINT64 DestOffset,
297 IN UINT8 SrcBarIndex,
298 IN UINT64 SrcOffset,
299 IN UINTN Count
300 )
301 {
302 ASSERT (FALSE);
303 return EFI_UNSUPPORTED;
304 }
305
306 EFI_STATUS
307 PciIoMap (
308 IN EFI_PCI_IO_PROTOCOL *This,
309 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
310 IN VOID *HostAddress,
311 IN OUT UINTN *NumberOfBytes,
312 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
313 OUT VOID **Mapping
314 )
315 {
316 MAP_INFO_INSTANCE *Map;
317 EFI_STATUS Status;
318
319 if ( HostAddress == NULL || NumberOfBytes == NULL ||
320 DeviceAddress == NULL || Mapping == NULL ) {
321
322 return EFI_INVALID_PARAMETER;
323 }
324
325
326 if (Operation >= EfiPciOperationMaximum) {
327 return EFI_INVALID_PARAMETER;
328 }
329
330 *DeviceAddress = ConvertToPhysicalAddress (HostAddress);
331
332 // Data cache flush (HostAddress, NumberOfBytes);
333
334 // Remember range so we can flush on the other side
335 Status = gBS->AllocatePool (EfiBootServicesData, sizeof (PCI_DMA_MAP), (VOID **) &Map);
336 if (EFI_ERROR(Status)) {
337 return EFI_OUT_OF_RESOURCES;
338 }
339
340 *Mapping = Map;
341
342 Map->HostAddress = (UINTN)HostAddress;
343 Map->DeviceAddress = *DeviceAddress;
344 Map->NumberOfBytes = *NumberOfBytes;
345 Map->Operation = Operation;
346
347 // EfiCpuFlushTypeWriteBack, EfiCpuFlushTypeInvalidate
348 gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate);
349
350 return EFI_SUCCESS;
351 }
352
353 EFI_STATUS
354 PciIoUnmap (
355 IN EFI_PCI_IO_PROTOCOL *This,
356 IN VOID *Mapping
357 )
358 {
359 PCI_DMA_MAP *Map;
360
361 if (Mapping == NULL) {
362 ASSERT (FALSE);
363 return EFI_INVALID_PARAMETER;
364 }
365
366 Map = (PCI_DMA_MAP *)Mapping;
367 if (Map->Operation == EfiPciOperationBusMasterWrite) {
368 //
369 // Make sure we read buffer from uncached memory and not the cache
370 //
371 gCpu->FlushDataCache (gCpu, Map->HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate);
372 }
373
374 FreePool (Map);
375
376 return EFI_SUCCESS;
377 }
378
379 EFI_STATUS
380 PciIoAllocateBuffer (
381 IN EFI_PCI_IO_PROTOCOL *This,
382 IN EFI_ALLOCATE_TYPE Type,
383 IN EFI_MEMORY_TYPE MemoryType,
384 IN UINTN Pages,
385 OUT VOID **HostAddress,
386 IN UINT64 Attributes
387 )
388 {
389 if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {
390 return EFI_UNSUPPORTED;
391 }
392
393 if (HostAddress == NULL) {
394 return EFI_INVALID_PARAMETER;
395 }
396
397 //
398 // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
399 //
400 // We used uncached memory to keep coherency
401 //
402 if (MemoryType == EfiBootServicesData) {
403 *HostAddress = UncachedAllocatePages (Pages);
404 } else if (MemoryType != EfiRuntimeServicesData) {
405 *HostAddress = UncachedAllocateRuntimePages (Pages);
406 } else {
407 return EFI_INVALID_PARAMETER;
408 }
409
410 return EFI_SUCCESS;
411 }
412
413 EFI_STATUS
414 PciIoFreeBuffer (
415 IN EFI_PCI_IO_PROTOCOL *This,
416 IN UINTN Pages,
417 IN VOID *HostAddress
418 )
419 {
420 if (HostAddress == NULL) {
421 return EFI_INVALID_PARAMETER;
422 }
423
424 UncachedFreePages (HostAddress, Pages);
425 return EFI_SUCCESS;
426 }
427
428
429 EFI_STATUS
430 PciIoFlush (
431 IN EFI_PCI_IO_PROTOCOL *This
432 )
433 {
434 return EFI_SUCCESS;
435 }
436
437 EFI_STATUS
438 PciIoGetLocation (
439 IN EFI_PCI_IO_PROTOCOL *This,
440 OUT UINTN *SegmentNumber,
441 OUT UINTN *BusNumber,
442 OUT UINTN *DeviceNumber,
443 OUT UINTN *FunctionNumber
444 )
445 {
446 EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
447
448 if (SegmentNumber != NULL) {
449 *SegmentNumber = Private->Segment;
450 }
451
452 if (BusNumber != NULL) {
453 *BusNumber = 0xff;
454 }
455
456 if (DeviceNumber != NULL) {
457 *DeviceNumber = 0;
458 }
459
460 if (FunctionNumber != NULL) {
461 *FunctionNumber = 0;
462 }
463
464 return EFI_SUCCESS;
465 }
466
467 EFI_STATUS
468 PciIoAttributes (
469 IN EFI_PCI_IO_PROTOCOL *This,
470 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
471 IN UINT64 Attributes,
472 OUT UINT64 *Result OPTIONAL
473 )
474 {
475 switch (Operation) {
476 case EfiPciIoAttributeOperationGet:
477 case EfiPciIoAttributeOperationSupported:
478 if (Result == NULL) {
479 return EFI_INVALID_PARAMETER;
480 }
481 // We are not a real PCI device so just say things we kind of do
482 *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE;
483 break;
484
485 case EfiPciIoAttributeOperationSet:
486 case EfiPciIoAttributeOperationEnable:
487 case EfiPciIoAttributeOperationDisable:
488 // Since we are not a real PCI device no enable/set or disable operations exist.
489 return EFI_SUCCESS;
490
491 default:
492 ASSERT (FALSE);
493 return EFI_INVALID_PARAMETER;
494 };
495 return EFI_SUCCESS;
496 }
497
498 EFI_STATUS
499 PciIoGetBarAttributes (
500 IN EFI_PCI_IO_PROTOCOL *This,
501 IN UINT8 BarIndex,
502 OUT UINT64 *Supports, OPTIONAL
503 OUT VOID **Resources OPTIONAL
504 )
505 {
506 ASSERT (FALSE);
507 return EFI_UNSUPPORTED;
508 }
509
510 EFI_STATUS
511 PciIoSetBarAttributes (
512 IN EFI_PCI_IO_PROTOCOL *This,
513 IN UINT64 Attributes,
514 IN UINT8 BarIndex,
515 IN OUT UINT64 *Offset,
516 IN OUT UINT64 *Length
517 )
518 {
519 ASSERT (FALSE);
520 return EFI_UNSUPPORTED;
521 }
522
523 EFI_PCI_IO_PROTOCOL PciIoTemplate =
524 {
525 PciIoPollMem,
526 PciIoPollIo,
527 PciIoMemRead,
528 PciIoMemWrite,
529 PciIoIoRead,
530 PciIoIoWrite,
531 PciIoPciRead,
532 PciIoPciWrite,
533 PciIoCopyMem,
534 PciIoMap,
535 PciIoUnmap,
536 PciIoAllocateBuffer,
537 PciIoFreeBuffer,
538 PciIoFlush,
539 PciIoGetLocation,
540 PciIoAttributes,
541 PciIoGetBarAttributes,
542 PciIoSetBarAttributes,
543 0,
544 0
545 };
546
547 EFI_STATUS
548 EFIAPI
549 PciEmulationEntryPoint (
550 IN EFI_HANDLE ImageHandle,
551 IN EFI_SYSTEM_TABLE *SystemTable
552 )
553 {
554 EFI_STATUS Status;
555 EFI_HANDLE Handle;
556 EFI_PCI_IO_PRIVATE_DATA *Private;
557 UINT8 CapabilityLength;
558 UINT8 PhysicalPorts;
559 UINTN Count;
560
561 // Get the Cpu protocol for later use
562 Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu);
563 ASSERT_EFI_ERROR(Status);
564
565 //Configure USB host for OMAP3530.
566 ConfigureUSBHost();
567
568 // Create a private structure
569 Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA));
570 if (Private == NULL) {
571 Status = EFI_OUT_OF_RESOURCES;
572 return Status;
573 }
574
575 Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature
576 Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too
577 Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base
578 Private->Segment = 0; // Default to segment zero
579
580 // Find out the capability register length and number of physical ports.
581 CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart);
582 PhysicalPorts = (MmioRead32 (Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F;
583
584 // Calculate the total size of the USB registers.
585 Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
586
587 // Enable Port Power bit in Port status and control registers in EHCI register space.
588 // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
589 // host controller implementation includes port power control.
590 for (Count = 0; Count < PhysicalPorts; Count++) {
591 MmioOr32 ((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000);
592 }
593
594 // Create fake PCI config space.
595 Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00));
596 if (Private->ConfigSpace == NULL) {
597 Status = EFI_OUT_OF_RESOURCES;
598 FreePool(Private);
599 return Status;
600 }
601
602 // Configure PCI config space
603 Private->ConfigSpace->Hdr.VendorId = 0x3530;
604 Private->ConfigSpace->Hdr.DeviceId = 0x3530;
605 Private->ConfigSpace->Hdr.ClassCode[0] = 0x20;
606 Private->ConfigSpace->Hdr.ClassCode[1] = 0x03;
607 Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C;
608 Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart;
609
610 Handle = NULL;
611
612 // Unique device path.
613 CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate));
614 Private->DevicePath.AcpiDevicePath.UID = 0;
615
616 // Copy protocol structure
617 CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate));
618
619 Status = gBS->InstallMultipleProtocolInterfaces(&Handle,
620 &gEfiPciIoProtocolGuid, &Private->PciIoProtocol,
621 &gEfiDevicePathProtocolGuid, &Private->DevicePath,
622 NULL);
623 if (EFI_ERROR(Status)) {
624 DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));
625 }
626
627 return Status;
628 }
629