3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>
6 This program and the accompanying materials
7 are 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
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.
16 #include "PciEmulation.h"
18 #define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
21 ACPI_HID_DEVICE_PATH AcpiDevicePath
;
22 PCI_DEVICE_PATH PciDevicePath
;
23 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
24 } EFI_PCI_IO_DEVICE_PATH
;
28 EFI_PCI_IO_DEVICE_PATH DevicePath
;
29 EFI_PCI_IO_PROTOCOL PciIoProtocol
;
30 PCI_TYPE00
*ConfigSpace
;
31 PCI_ROOT_BRIDGE RootBridge
;
33 } EFI_PCI_IO_PRIVATE_DATA
;
35 #define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
36 #define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
38 EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate
=
41 { ACPI_DEVICE_PATH
, ACPI_DP
, { sizeof (ACPI_HID_DEVICE_PATH
), 0 } },
42 EISA_PNP_ID(0x0A03), // HID
46 { HARDWARE_DEVICE_PATH
, HW_PCI_DP
, { sizeof (PCI_DEVICE_PATH
), 0 } },
50 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, { sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0} }
64 IN EFI_PCI_IO_PROTOCOL
*This
,
65 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
75 return EFI_UNSUPPORTED
;
80 IN EFI_PCI_IO_PROTOCOL
*This
,
81 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
91 return EFI_UNSUPPORTED
;
96 IN EFI_PCI_IO_PROTOCOL
*This
,
97 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
104 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
106 return PciRootBridgeIoMemRead (&Private
->RootBridge
.Io
,
107 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
108 Private
->ConfigSpace
->Device
.Bar
[BarIndex
] + Offset
, //Fix me ConfigSpace
116 IN EFI_PCI_IO_PROTOCOL
*This
,
117 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
124 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
126 return PciRootBridgeIoMemWrite (&Private
->RootBridge
.Io
,
127 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
128 Private
->ConfigSpace
->Device
.Bar
[BarIndex
] + Offset
, //Fix me ConfigSpace
136 IN EFI_PCI_IO_PROTOCOL
*This
,
137 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
145 return EFI_UNSUPPORTED
;
150 IN EFI_PCI_IO_PROTOCOL
*This
,
151 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
159 return EFI_UNSUPPORTED
;
164 IN EFI_PCI_IO_PROTOCOL
*This
,
165 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
171 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
174 Status
= PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)Width
,
179 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
) //Fix me ConfigSpace
186 IN EFI_PCI_IO_PROTOCOL
*This
,
187 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
193 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
195 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
198 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
), //Fix me ConfigSpace
206 IN EFI_PCI_IO_PROTOCOL
*This
,
207 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
208 IN UINT8 DestBarIndex
,
209 IN UINT64 DestOffset
,
210 IN UINT8 SrcBarIndex
,
216 return EFI_UNSUPPORTED
;
221 IN EFI_PCI_IO_PROTOCOL
*This
,
222 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
223 IN VOID
*HostAddress
,
224 IN OUT UINTN
*NumberOfBytes
,
225 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
229 DMA_MAP_OPERATION DmaOperation
;
231 if (Operation
== EfiPciIoOperationBusMasterRead
) {
232 DmaOperation
= MapOperationBusMasterRead
;
233 } else if (Operation
== EfiPciIoOperationBusMasterWrite
) {
234 DmaOperation
= MapOperationBusMasterWrite
;
235 } else if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
236 DmaOperation
= MapOperationBusMasterCommonBuffer
;
238 return EFI_INVALID_PARAMETER
;
240 return DmaMap (DmaOperation
, HostAddress
, NumberOfBytes
, DeviceAddress
, Mapping
);
245 IN EFI_PCI_IO_PROTOCOL
*This
,
249 return DmaUnmap (Mapping
);
253 PciIoAllocateBuffer (
254 IN EFI_PCI_IO_PROTOCOL
*This
,
255 IN EFI_ALLOCATE_TYPE Type
,
256 IN EFI_MEMORY_TYPE MemoryType
,
258 OUT VOID
**HostAddress
,
262 if (Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) {
264 return EFI_UNSUPPORTED
;
267 return DmaAllocateBuffer (MemoryType
, Pages
, HostAddress
);
273 IN EFI_PCI_IO_PROTOCOL
*This
,
278 return DmaFreeBuffer (Pages
, HostAddress
);
284 IN EFI_PCI_IO_PROTOCOL
*This
292 IN EFI_PCI_IO_PROTOCOL
*This
,
293 OUT UINTN
*SegmentNumber
,
294 OUT UINTN
*BusNumber
,
295 OUT UINTN
*DeviceNumber
,
296 OUT UINTN
*FunctionNumber
299 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
301 if (SegmentNumber
!= NULL
) {
302 *SegmentNumber
= Private
->Segment
;
305 if (BusNumber
!= NULL
) {
309 if (DeviceNumber
!= NULL
) {
313 if (FunctionNumber
!= NULL
) {
322 IN EFI_PCI_IO_PROTOCOL
*This
,
323 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
324 IN UINT64 Attributes
,
325 OUT UINT64
*Result OPTIONAL
329 case EfiPciIoAttributeOperationGet
:
330 case EfiPciIoAttributeOperationSupported
:
331 if (Result
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
334 // We are not a real PCI device so just say things we kind of do
335 *Result
= EFI_PCI_IO_ATTRIBUTE_MEMORY
| EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
| EFI_PCI_DEVICE_ENABLE
;
338 case EfiPciIoAttributeOperationSet
:
339 case EfiPciIoAttributeOperationEnable
:
340 case EfiPciIoAttributeOperationDisable
:
341 // Since we are not a real PCI device no enable/set or disable operations exist.
346 return EFI_INVALID_PARAMETER
;
352 PciIoGetBarAttributes (
353 IN EFI_PCI_IO_PROTOCOL
*This
,
355 OUT UINT64
*Supports
, OPTIONAL
356 OUT VOID
**Resources OPTIONAL
360 return EFI_UNSUPPORTED
;
364 PciIoSetBarAttributes (
365 IN EFI_PCI_IO_PROTOCOL
*This
,
366 IN UINT64 Attributes
,
368 IN OUT UINT64
*Offset
,
369 IN OUT UINT64
*Length
373 return EFI_UNSUPPORTED
;
376 EFI_PCI_IO_PROTOCOL PciIoTemplate
=
380 { PciIoMemRead
, PciIoMemWrite
},
381 { PciIoIoRead
, PciIoIoWrite
},
382 { PciIoPciRead
, PciIoPciWrite
},
391 PciIoGetBarAttributes
,
392 PciIoSetBarAttributes
,
400 IN PHYSICAL_ADDRESS MemoryStart
,
401 IN UINT64 MemorySize
,
409 EFI_PCI_IO_PRIVATE_DATA
*Private
;
411 // Configure USB host
414 // Create a private structure
415 Private
= AllocatePool (sizeof (EFI_PCI_IO_PRIVATE_DATA
));
416 if (Private
== NULL
) {
417 Status
= EFI_OUT_OF_RESOURCES
;
421 Private
->Signature
= EFI_PCI_IO_PRIVATE_DATA_SIGNATURE
; // Fill in signature
422 Private
->RootBridge
.Signature
= PCI_ROOT_BRIDGE_SIGNATURE
; // Fake Root Bridge structure needs a signature too
423 Private
->RootBridge
.MemoryStart
= MemoryStart
; // Get the USB capability register base
424 Private
->Segment
= 0; // Default to segment zero
426 // Calculate the total size of the USB controller (OHCI + EHCI).
427 Private
->RootBridge
.MemorySize
= MemorySize
; //CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));
429 // Create fake PCI config space: OHCI + EHCI
430 Private
->ConfigSpace
= AllocateZeroPool (sizeof (PCI_TYPE00
));
431 if (Private
->ConfigSpace
== NULL
) {
432 Status
= EFI_OUT_OF_RESOURCES
;
438 // Configure PCI config space: OHCI + EHCI
440 Private
->ConfigSpace
->Hdr
.VendorId
= 0x3530; //TODO: Define one
441 Private
->ConfigSpace
->Hdr
.DeviceId
= 0x3530; //TODO: Define one
442 Private
->ConfigSpace
->Hdr
.ClassCode
[0] = ClassCode1
;
443 Private
->ConfigSpace
->Hdr
.ClassCode
[1] = ClassCode2
;
444 Private
->ConfigSpace
->Hdr
.ClassCode
[2] = ClassCode3
;
445 Private
->ConfigSpace
->Device
.Bar
[0] = MemoryStart
;
449 // Unique device path.
450 CopyMem (&Private
->DevicePath
, &PciIoDevicePathTemplate
, sizeof (PciIoDevicePathTemplate
));
451 Private
->DevicePath
.AcpiDevicePath
.UID
= 0;
452 Private
->DevicePath
.PciDevicePath
.Device
= DeviceId
;
454 // Copy protocol structure
455 CopyMem (&Private
->PciIoProtocol
, &PciIoTemplate
, sizeof (PciIoTemplate
));
457 Status
= gBS
->InstallMultipleProtocolInterfaces (&Handle
,
458 &gEfiPciIoProtocolGuid
, &Private
->PciIoProtocol
,
459 &gEfiDevicePathProtocolGuid
, &Private
->DevicePath
,
461 if (EFI_ERROR (Status
)) {
462 DEBUG ((EFI_D_ERROR
, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces () failed.\n"));
469 PciEmulationEntryPoint (
475 Status
= PciInstallDevice (0, FixedPcdGet32 (PcdSynopsysUsbOhciBaseAddress
), SIZE_64KB
, PCI_IF_OHCI
, PCI_CLASS_SERIAL_USB
, PCI_CLASS_SERIAL
);
476 if (EFI_ERROR (Status
)) {
477 DEBUG ((EFI_D_ERROR
, "PciEmulation: failed to install OHCI device.\n"));
480 Status
= PciInstallDevice (1, FixedPcdGet32 (PcdSynopsysUsbEhciBaseAddress
), SIZE_64KB
, PCI_IF_EHCI
, PCI_CLASS_SERIAL_USB
, PCI_CLASS_SERIAL
);
481 if (EFI_ERROR (Status
)) {
482 DEBUG ((EFI_D_ERROR
, "PciEmulation: failed to install EHCI device.\n"));