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