EFI_STATUS EFIAPI PcatRootBridgeIoSetAttributes ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN UINT64 Attributes, IN OUT UINT64 *ResourceBase, IN OUT UINT64 *ResourceLength ) { PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); // // This is a generic driver for a PC-AT class system. It does not have any // chipset specific knowlegde, so none of the attributes can be set or // cleared. Any attempt to set attribute that are already set will succeed, // and any attempt to set an attribute that is not supported will fail. // if (Attributes & (~PrivateData->Attributes)) { return EFI_UNSUPPORTED; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoConfiguration ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, OUT VOID **Resources ) /*++ Routine Description: Arguments: Returns: --*/ { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; UINTN Index; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); for (Index = 0; Index < TypeMax; Index++) { if (PrivateData->ResAllocNode[Index].Status == ResAllocated) { Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base; Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1; Configuration.SpaceDesp[Index].AddrLen = PrivateData->ResAllocNode[Index].Length; } } *Resources = &Configuration; return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoMemRead ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) /*++ Routine Description: Memory read Arguments: Returns: --*/ { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth; UINTN OldCount; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); // // Check memory access limit // if (Address < PrivateData->MemBase) { return EFI_INVALID_PARAMETER; } OldWidth = Width; OldCount = Count; if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { Count = 1; } Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03); if (Address + (((UINTN)1 << Width) * Count) - 1 > PrivateData->MemLimit) { return EFI_INVALID_PARAMETER; } return mCpuIo->Mem.Read (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, Address, OldCount, Buffer); }
EFI_STATUS EFIAPI RootBridgeIoGetAttributes ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, OUT UINT64 *Supported, OUT UINT64 *Attributes ) /*++ Routine Description: Get the attributes that a PCI root bridge supports and the attributes the PCI root bridge is currently using. Arguments: This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. Supports - A pointer to the mask of attributes that this PCI root bridge supports. Attributes - A pointer to the mask of attributes that this PCI root bridge is currently using. Returns: EFI_SUCCESS - Success. EFI_INVALID_PARAMETER - Invalid parameter found. --*/ // GC_TODO: Supported - add argument and description to function comment // // GC_TODO: Supported - add argument and description to function comment // // GC_TODO: Supported - add argument and description to function comment // { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); if (Attributes == NULL && Supported == NULL) { return EFI_INVALID_PARAMETER; } // // Set the return value for Supported and Attributes // if (Supported) { *Supported = PrivateData->Supports; } if (Attributes) { *Attributes = PrivateData->Attributes; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoSetAttributes ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN UINT64 Attributes, IN OUT UINT64 *ResourceBase, IN OUT UINT64 *ResourceLength ) /*++ Routine Description: Sets the attributes for a resource range on a PCI root bridge. Arguments: This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. Attributes - The mask of attributes to set. ResourceBase - Pointer to the base address of the resource range to be modified by the attributes specified by Attributes. ResourceLength - Pointer to the length of the resource range to be modified. Returns: EFI_SUCCESS - Success. EFI_INVALID_PARAMETER - Invalid parameter found. EFI_OUT_OF_RESOURCES - Not enough resources to set the attributes upon. --*/ // // GC_TODO: EFI_UNSUPPORTED - add return value to function comment // { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); if (Attributes != 0) { Attributes &= (PrivateData->Supports); if (Attributes == 0) { return EFI_UNSUPPORTED; } } if (Attributes == PrivateData->Attributes) { return EFI_SUCCESS; } // // It is just a trick for some attribute can only be enabled or disabled // otherwise it can impact on other devices // PrivateData->Attributes = Attributes; return EFI_SUCCESS; }
EFI_STATUS EFIAPI PcatRootBridgeIoConfiguration ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, OUT VOID **Resources ) { PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); *Resources = PrivateData->Configuration; return EFI_SUCCESS; }
EFI_STATUS EFIAPI PcatRootBridgeIoMemWrite ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) { PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; UINTN AlignMask; PTR In; PTR Out; if ( Buffer == NULL ) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); if (!PcatRootBridgeMemAddressValid (PrivateData, Address)) { return EFI_INVALID_PARAMETER; } AlignMask = (1 << (Width & 0x03)) - 1; if (Address & AlignMask) { return EFI_INVALID_PARAMETER; } Address += PrivateData->PhysicalMemoryBase; In.buf = (VOID *)(UINTN) Address; Out.buf = Buffer; if ((UINT32)Width <= EfiPciWidthUint64) { return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out); } if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { return PcatRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out); } if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { return PcatRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out); } return EFI_INVALID_PARAMETER; }
EFI_STATUS EFIAPI PcatRootBridgeIoGetAttributes ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, OUT UINT64 *Supported, OPTIONAL OUT UINT64 *Attributes ) { PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); if (Attributes == NULL && Supported == NULL) { return EFI_INVALID_PARAMETER; } // // Supported is an OPTIONAL parameter. See if it is NULL // if (Supported) { // // This is a generic driver for a PC-AT class system. It does not have any // chipset specific knowlegde, so none of the attributes can be set or // cleared. Any attempt to set attribute that are already set will succeed, // and any attempt to set an attribute that is not supported will fail. // *Supported = PrivateData->Attributes; } // // Set Attrbutes to the attributes detected when the PCI Root Bridge was initialized // if (Attributes) { *Attributes = PrivateData->Attributes; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoGetAttributes ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, OUT UINT64 *Supported, OUT UINT64 *Attributes ) /*++ Routine Description: Arguments: Returns: --*/ { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); if (Attributes == NULL && Supported == NULL) { return EFI_INVALID_PARAMETER; } // // Set the return value for Supported and Attributes // if (Supported) { *Supported = PrivateData->Supports; } if (Attributes) { *Attributes = PrivateData->Attributes; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoIoWrite ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) /*++ Routine Description: Enable a PCI driver to write to PCI controller registers in the PCI root bridge I/O space. Arguments: This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Width - Signifies the width of the memory operation. Address - The base address of the I/O operation. Count - The number of I/O operations to perform. Buffer - The source buffer to write data from. Returns: EFI_SUCCESS - The data was written to the PCI root bridge. EFI_INVALID_PARAMETER - Invalid parameters found. EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. --*/ { UINTN AlignMask; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } if (Width < 0 || Width == EfiPciWidthUint64 || Width == EfiPciWidthFifoUint64 || Width == EfiPciWidthFillUint64 || Width >= EfiPciWidthMaximum ) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); // // AlignMask = (1 << Width) - 1; // AlignMask = (1 << (Width & 0x03)) - 1; // // Check Io access limit // if (Address > PrivateData->Aperture.IoLimit) { return EFI_INVALID_PARAMETER; } if (Address & AlignMask) { return EFI_INVALID_PARAMETER; } return mCpuIo->Io.Write ( mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer ); }
EFI_STATUS SimpleIioRootBridgeConstructor ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, IN EFI_HANDLE HostBridgeHandle, IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE *ResAperture, UINT64 AllocAttributes ) /*++ Routine Description: Construct the Pci Root Bridge Io protocol. Arguments: Protocol - Protocol to initialize. HostBridgeHandle - Handle to the HostBridge. ResAperture - Resource apperture of the root bridge. AllocAttributes - Attribute of resouce allocated. Returns: EFI_SUCCESS - Success. Others - Fail. --*/ { EFI_STATUS Status; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PCI_RESOURCE_TYPE Index; UINT32 HecBase; UINT32 HecSize; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol); // // Initialize the apertures with default values // CopyMem ( &PrivateData->Aperture, ResAperture, sizeof (PCI_ROOT_BRIDGE_RESOURCE_APERTURE) ); for (Index = TypeIo; Index < TypeMax; Index++) { PrivateData->ResAllocNode[Index].Type = Index; PrivateData->ResAllocNode[Index].Base = 0; PrivateData->ResAllocNode[Index].Length = 0; PrivateData->ResAllocNode[Index].Status = ResNone; } EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL); PrivateData->PciAddress = 0xCF8; PrivateData->PciData = 0xCFC; PrivateData->RootBridgeAllocAttrib = AllocAttributes; PrivateData->Attributes = 0; PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_ATTRIBUTE_VGA_MEMORY | EFI_PCI_ATTRIBUTE_VGA_IO_16; // // Don't support BASE above 4GB currently // Position to bit 39:28 // HecBase = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressBase; HecSize = (UINT32) mIioUds->IioUdsPtr->PlatformData.PciExpressSize; ASSERT ((HecBase & (HecSize - 1)) == 0); ASSERT (HecBase != 0); PrivateData->HecBase = HecBase; PrivateData->HecLen = HecSize; PrivateData->BusNumberAssigned = FALSE; PrivateData->BusScanCount = 0; Protocol->ParentHandle = HostBridgeHandle; Protocol->PollMem = RootBridgeIoPollMem; Protocol->PollIo = RootBridgeIoPollIo; Protocol->Mem.Read = RootBridgeIoMemRead; Protocol->Mem.Write = RootBridgeIoMemWrite; Protocol->Io.Read = RootBridgeIoIoRead; Protocol->Io.Write = RootBridgeIoIoWrite; Protocol->CopyMem = RootBridgeIoCopyMem; Protocol->Pci.Read = RootBridgeIoPciRead; Protocol->Pci.Write = RootBridgeIoPciWrite; Protocol->Map = RootBridgeIoMap; Protocol->Unmap = RootBridgeIoUnmap; Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer; Protocol->FreeBuffer = RootBridgeIoFreeBuffer; Protocol->Flush = RootBridgeIoFlush; Protocol->GetAttributes = RootBridgeIoGetAttributes; Protocol->SetAttributes = RootBridgeIoSetAttributes; Protocol->Configuration = RootBridgeIoConfiguration; Protocol->SegmentNumber = 0; Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, &mMetronome); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol ( &gEfiCpuIoProtocolGuid, NULL, &mCpuIo ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoMemWrite ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) /*++ Routine Description: Allow write to memory mapped I/O space. Arguments: This - Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. Width - The width of memory operation. Address - Base address of the memory operation. Count - Number of memory opeartion to perform. Buffer - The source buffer to write data from. Returns: EFI_SUCCESS - Success. EFI_INVALID_PARAMETER - Invalid parameter found. EFI_OUT_OF_RESOURCES - Fail due to lack of resources. --*/ { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } if (Width < 0 || Width == EfiPciWidthUint64 || Width == EfiPciWidthFifoUint64 || Width == EfiPciWidthFillUint64 || Width >= EfiPciWidthMaximum ) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); // // Check memory access limit // if (PrivateData->Aperture.Mem64Limit > PrivateData->Aperture.Mem64Base) { if (Address > PrivateData->Aperture.Mem64Limit) { return EFI_INVALID_PARAMETER; } } else { if (Address > PrivateData->Aperture.Mem32Limit) { return EFI_INVALID_PARAMETER; } } return mCpuIo->Mem.Write ( mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, Address, Count, Buffer ); }
EFI_STATUS EFIAPI RootBridgeIoConfiguration ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, OUT VOID **Resources ) /*++ Routine Description: Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0 resource descriptor. Arguments: This - Pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance. Resources - Pointer to the ACPI 2.0 resource descriptor that describe the current configuration of this PCI root bridge. Returns: EFI_SUCCESS - Success. EFI_UNSUPPORTED - Current configuration of the PCI root bridge could not be retrieved. --*/ // // GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment // { EFI_STATUS Status; UINTN Idx; PCI_ROOT_BRIDGE_INSTANCE *RbPrivateData; PCI_RES_NODE *ResAllocNode; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Config; // // Get this instance of the Root Bridge. // RbPrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); // // If the pointer is not NULL, it points to a buffer already allocated. // if (RbPrivateData->ConfigBuffer == NULL) { Status = gBS->AllocatePool ( EfiBootServicesData, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), &RbPrivateData->ConfigBuffer ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } } Config = RbPrivateData->ConfigBuffer; ZeroMem (Config, TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); for (Idx = 0; Idx < TypeMax; Idx++) { ResAllocNode = &RbPrivateData->ResAllocNode[Idx]; if (ResAllocNode->Status != ResAllocated) { continue; } switch (ResAllocNode->Type) { case TypeIo: Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; Config->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; Config->AddrRangeMin = ResAllocNode->Base; Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1; Config->AddrLen = ResAllocNode->Length; break; case TypeMem32: Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; Config->AddrSpaceGranularity = 32; Config->AddrRangeMin = ResAllocNode->Base; Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1; Config->AddrLen = ResAllocNode->Length; break; case TypePMem32: Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; Config->SpecificFlag = 6; Config->AddrSpaceGranularity = 32; Config->AddrRangeMin = ResAllocNode->Base; Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1; Config->AddrLen = ResAllocNode->Length; break; case TypeMem64: Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; Config->SpecificFlag = 6; Config->AddrSpaceGranularity = 64; Config->AddrRangeMin = ResAllocNode->Base; Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1; Config->AddrLen = ResAllocNode->Length; break; case TypePMem64: Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; Config->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; Config->SpecificFlag = 6; Config->AddrSpaceGranularity = 64; Config->AddrRangeMin = ResAllocNode->Base; Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1; Config->AddrLen = ResAllocNode->Length; break; case TypeBus: Config->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; Config->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; Config->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; Config->AddrRangeMin = ResAllocNode->Base; Config->AddrRangeMax = ResAllocNode->Base + ResAllocNode->Length - 1; Config->AddrLen = ResAllocNode->Length; break; default: break; } Config++; } // // Terminate the entries. // ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Desc = ACPI_END_TAG_DESCRIPTOR; ((EFI_ACPI_END_TAG_DESCRIPTOR *) Config)->Checksum = 0x0; *Resources = RbPrivateData->ConfigBuffer; return EFI_SUCCESS; }
EFI_STATUS EFIAPI PcatRootBridgeIoUnmap ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN VOID *Mapping ) { MAP_INFO *MapInfo; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; LIST_ENTRY *Link; // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); // // See if the Map() operation associated with this Unmap() required a mapping buffer. // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS. // if (Mapping != NULL) { // // Get the MAP_INFO structure from Mapping // MapInfo = (MAP_INFO *)Mapping; for (Link = PrivateData->MapInfo.ForwardLink; Link != &PrivateData->MapInfo; Link = Link->ForwardLink) { if (((MAP_INFO_INSTANCE*)Link)->Map == MapInfo) break; } if (Link == &PrivateData->MapInfo) { return EFI_INVALID_PARAMETER; } RemoveEntryList(Link); ((MAP_INFO_INSTANCE*)Link)->Map = NULL; gBS->FreePool((MAP_INFO_INSTANCE*)Link); // // If this is a write operation from the Bus Master's point of view, // then copy the contents of the mapped buffer into the real buffer // so the processor can read the contents of the real buffer. // if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) { CopyMem ( (VOID *)(UINTN)MapInfo->HostAddress, (VOID *)(UINTN)MapInfo->MappedHostAddress, MapInfo->NumberOfBytes ); } // // Free the mapped buffer and the MAP_INFO structure. // gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages); gBS->FreePool (Mapping); } // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); return EFI_SUCCESS; }
EFI_STATUS PcatRootBridgeIoIoRead ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) { PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; UINTN InStride; UINTN OutStride; UINTN AlignMask; UINTN Address; PTR Buffer; UINT16 Data16; UINT32 Data32; if ( UserBuffer == NULL ) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); Address = (UINTN) UserAddress; Buffer.buf = (UINT8 *)UserBuffer; if ( Address < PrivateData->IoBase || Address > PrivateData->IoLimit ) { return EFI_INVALID_PARAMETER; } if ((UINT32)Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } if ((Width & 0x03) == EfiPciWidthUint64) { return EFI_INVALID_PARAMETER; } AlignMask = (1 << (Width & 0x03)) - 1; if ( Address & AlignMask ) { return EFI_INVALID_PARAMETER; } InStride = 1 << (Width & 0x03); OutStride = InStride; if (Width >=EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { InStride = 0; } if (Width >=EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { OutStride = 0; } Width = Width & 0x03; Address += PrivateData->PhysicalIoBase; // // Loop for each iteration and move the data // switch (Width) { case EfiPciWidthUint8: for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) { MEMORY_FENCE(); *Buffer.ui8 = PORT_TO_MEM8(Address); MEMORY_FENCE(); } break; case EfiPciWidthUint16: for (; Count > 0; Count--, Buffer.buf += OutStride, Address += InStride) { MEMORY_FENCE(); if (Buffer.ui & 0x1) { Data16 = PORT_TO_MEM16(Address); *Buffer.ui8 = (UINT8)(Data16 & 0xff); *(Buffer.ui8+1) = (UINT8)((Data16 >> 8) & 0xff); } else { *Buffer.ui16 = PORT_TO_MEM16(Address); } MEMORY_FENCE(); }
EFI_STATUS PcatRootBridgeIoPciRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN BOOLEAN Write, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) { PCI_CONFIG_ACCESS_CF8 Pci; PCI_CONFIG_ACCESS_CF8 PciAligned; UINT32 InStride; UINT32 OutStride; UINTN PciData; UINTN PciDataStride; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; UINT64 PciExpressRegAddr; BOOLEAN UsePciExpressAccess; if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } if ((Width & 0x03) >= EfiPciWidthUint64) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); InStride = 1 << (Width & 0x03); OutStride = InStride; if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { InStride = 0; } if (Width >= EfiPciWidthFillUint8 && Width <= EfiPciWidthFillUint64) { OutStride = 0; } UsePciExpressAccess = FALSE; CopyMem (&PciAddress, &UserAddress, sizeof(UINT64)); if (PciAddress.ExtendedRegister > 0xFF) { // // Check PciExpressBaseAddress // if ((PrivateData->PciExpressBaseAddress == 0) || (PrivateData->PciExpressBaseAddress >= MAX_ADDRESS)) { return EFI_UNSUPPORTED; } else { UsePciExpressAccess = TRUE; } } else { if (PciAddress.ExtendedRegister != 0) { Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF; } else { Pci.Bits.Reg = PciAddress.Register; } // // Note: We can also use PciExpress access here, if wanted. // } if (!UsePciExpressAccess) { Pci.Bits.Func = PciAddress.Function; Pci.Bits.Dev = PciAddress.Device; Pci.Bits.Bus = PciAddress.Bus; Pci.Bits.Reserved = 0; Pci.Bits.Enable = 1; // // PCI Config access are all 32-bit alligned, but by accessing the // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types // are possible on PCI. // // To read a byte of PCI config space you load 0xcf8 and // read 0xcfc, 0xcfd, 0xcfe, 0xcff // PciDataStride = Pci.Bits.Reg & 0x03; while (Count) { PciAligned = Pci; PciAligned.Bits.Reg &= 0xfc; PciData = (UINTN)PrivateData->PciData + PciDataStride; EfiAcquireLock(&PrivateData->PciLock); This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned); if (Write) { This->Io.Write (This, Width, PciData, 1, UserBuffer); } else { This->Io.Read (This, Width, PciData, 1, UserBuffer); } EfiReleaseLock(&PrivateData->PciLock); UserBuffer = ((UINT8 *)UserBuffer) + OutStride; PciDataStride = (PciDataStride + InStride) % 4; Pci.Bits.Reg += InStride; Count -= 1; } } else { // // Access PCI-Express space by using memory mapped method. // PciExpressRegAddr = (PrivateData->PciExpressBaseAddress) | (PciAddress.Bus << 20) | (PciAddress.Device << 15) | (PciAddress.Function << 12); if (PciAddress.ExtendedRegister != 0) { PciExpressRegAddr += PciAddress.ExtendedRegister; } else { PciExpressRegAddr += PciAddress.Register; } while (Count) { if (Write) { This->Mem.Write (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer); } else { This->Mem.Read (This, Width, (UINTN) PciExpressRegAddr, 1, UserBuffer); } UserBuffer = ((UINT8 *) UserBuffer) + OutStride; PciExpressRegAddr += InStride; Count -= 1; } } return EFI_SUCCESS; }
EFI_STATUS EFIAPI PcatRootBridgeIoMap ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, IN VOID *HostAddress, IN OUT UINTN *NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping ) { EFI_STATUS Status; EFI_PHYSICAL_ADDRESS PhysicalAddress; MAP_INFO *MapInfo; MAP_INFO_INSTANCE *MapInstance; PCAT_PCI_ROOT_BRIDGE_INSTANCE *PrivateData; if ( HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL ) { return EFI_INVALID_PARAMETER; } // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); // // Initialize the return values to their defaults // *Mapping = NULL; // // Make sure that Operation is valid // if ((UINT32)Operation >= EfiPciOperationMaximum) { return EFI_INVALID_PARAMETER; } // // Most PCAT like chipsets can not handle performing DMA above 4GB. // If any part of the DMA transfer being mapped is above 4GB, then // map the DMA transfer to a buffer below 4GB. // PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) { // // Common Buffer operations can not be remapped. If the common buffer // if above 4GB, then it is not possible to generate a mapping, so return // an error. // if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) { return EFI_UNSUPPORTED; } // // Allocate a MAP_INFO structure to remember the mapping when Unmap() is // called later. // Status = gBS->AllocatePool ( EfiBootServicesData, sizeof(MAP_INFO), (VOID **)&MapInfo ); if (EFI_ERROR (Status)) { *NumberOfBytes = 0; return Status; } // // Return a pointer to the MAP_INFO structure in Mapping // *Mapping = MapInfo; // // Initialize the MAP_INFO structure // MapInfo->Operation = Operation; MapInfo->NumberOfBytes = *NumberOfBytes; MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES(*NumberOfBytes); MapInfo->HostAddress = PhysicalAddress; MapInfo->MappedHostAddress = 0x00000000ffffffff; // // Allocate a buffer below 4GB to map the transfer to. // Status = gBS->AllocatePages ( AllocateMaxAddress, EfiBootServicesData, MapInfo->NumberOfPages, &MapInfo->MappedHostAddress ); if (EFI_ERROR(Status)) { gBS->FreePool (MapInfo); *NumberOfBytes = 0; return Status; } // // If this is a read operation from the Bus Master's point of view, // then copy the contents of the real buffer into the mapped buffer // so the Bus Master can read the contents of the real buffer. // if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) { CopyMem ( (VOID *)(UINTN)MapInfo->MappedHostAddress, (VOID *)(UINTN)MapInfo->HostAddress, MapInfo->NumberOfBytes ); } Status =gBS->AllocatePool ( EfiBootServicesData, sizeof(MAP_INFO_INSTANCE), (VOID **)&MapInstance ); if (EFI_ERROR(Status)) { gBS->FreePages (MapInfo->MappedHostAddress,MapInfo->NumberOfPages); gBS->FreePool (MapInfo); *NumberOfBytes = 0; return Status; } MapInstance->Map=MapInfo; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); InsertTailList(&PrivateData->MapInfo,&MapInstance->Link); // // The DeviceAddress is the address of the maped buffer below 4GB // *DeviceAddress = MapInfo->MappedHostAddress; } else { // // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress // *DeviceAddress = PhysicalAddress; } // // Perform a fence operation to make sure all memory operations are flushed // MemoryFence(); return EFI_SUCCESS; }
STATIC EFI_STATUS RootBridgeIoPciRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN BOOLEAN Write, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) /*++ Routine Description: Arguments: Returns: --*/ { PCI_CONFIG_ACCESS_CF8 Pci; PCI_CONFIG_ACCESS_CF8 PciAligned; UINT32 Stride; UINTN PciData; UINTN PciDataStride; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; if (Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); ASSERT (((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*)&UserAddress)->ExtendedRegister == 0x00); Stride = 1 << Width; Pci.Bits.Reg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register; Pci.Bits.Func = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Function; Pci.Bits.Dev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Device; Pci.Bits.Bus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Bus; Pci.Bits.Reserved = 0; Pci.Bits.Enable = 1; // // PCI Configure access are all 32-bit aligned, but by accessing the // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types // are possible on PCI. // // To read a byte of PCI configuration space you load 0xcf8 and // read 0xcfc, 0xcfd, 0xcfe, 0xcff // PciDataStride = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &UserAddress)->Register & 0x03; while (Count) { PciAligned = Pci; PciAligned.Bits.Reg &= 0xfc; PciData = PrivateData->PciData + PciDataStride; EfiAcquireLock(&PrivateData->PciLock); This->Io.Write (This, EfiPciWidthUint32, \ PrivateData->PciAddress, 1, &PciAligned); if (Write) { This->Io.Write (This, Width, PciData, 1, UserBuffer); } else { This->Io.Read (This, Width, PciData, 1, UserBuffer); } EfiReleaseLock(&PrivateData->PciLock); UserBuffer = ((UINT8 *)UserBuffer) + Stride; PciDataStride = (PciDataStride + Stride) % 4; Count -= 1; // // Only increment the PCI address if Width is not a FIFO. // if (Width >= EfiPciWidthUint8 && Width <= EfiPciWidthUint64) { Pci.Bits.Reg += Stride; } } return EFI_SUCCESS; }
EFI_STATUS RootBridgeConstructor ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol, IN EFI_HANDLE HostBridgeHandle, IN UINT64 Attri, IN PCI_ROOT_BRIDGE_RESOURCE_APPETURE *ResAppeture ) /*++ Routine Description: Construct the Pci Root Bridge Io protocol Arguments: Protocol - protocol to initialize Returns: None --*/ { EFI_STATUS Status; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; PCI_RESOURCE_TYPE Index; PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol); // // The host to pci bridge, the host memory and io addresses are // direct mapped to pci addresses, so no need translate, set bases to 0. // PrivateData->MemBase = ResAppeture->MemBase; PrivateData->IoBase = ResAppeture->IoBase; // // The host bridge only supports 32bit addressing for memory // and standard IA32 16bit io // PrivateData->MemLimit = ResAppeture->MemLimit; PrivateData->IoLimit = ResAppeture->IoLimit; // // Bus Appeture for this Root Bridge (Possible Range) // PrivateData->BusBase = ResAppeture->BusBase; PrivateData->BusLimit = ResAppeture->BusLimit; // // Specific for this chipset // for (Index = TypeIo; Index < TypeMax; Index++) { PrivateData->ResAllocNode[Index].Type = Index; PrivateData->ResAllocNode[Index].Base = 0; PrivateData->ResAllocNode[Index].Length = 0; PrivateData->ResAllocNode[Index].Status = ResNone; } EfiInitializeLock (&PrivateData->PciLock, TPL_HIGH_LEVEL); PrivateData->PciAddress = 0xCF8; PrivateData->PciData = 0xCFC; PrivateData->RootBridgeAttrib = Attri; PrivateData->Attributes = 0; PrivateData->Supports = 0; Protocol->ParentHandle = HostBridgeHandle; Protocol->PollMem = RootBridgeIoPollMem; Protocol->PollIo = RootBridgeIoPollIo; Protocol->Mem.Read = RootBridgeIoMemRead; Protocol->Mem.Write = RootBridgeIoMemWrite; Protocol->Io.Read = RootBridgeIoIoRead; Protocol->Io.Write = RootBridgeIoIoWrite; Protocol->CopyMem = RootBridgeIoCopyMem; Protocol->Pci.Read = RootBridgeIoPciRead; Protocol->Pci.Write = RootBridgeIoPciWrite; Protocol->Map = RootBridgeIoMap; Protocol->Unmap = RootBridgeIoUnmap; Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer; Protocol->FreeBuffer = RootBridgeIoFreeBuffer; Protocol->Flush = RootBridgeIoFlush; Protocol->GetAttributes = RootBridgeIoGetAttributes; Protocol->SetAttributes = RootBridgeIoSetAttributes; Protocol->Configuration = RootBridgeIoConfiguration; Protocol->SegmentNumber = 0; Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }
// // Internal function // EFI_STATUS RootBridgeIoPciRW ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN BOOLEAN Write, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 UserAddress, IN UINTN Count, IN OUT VOID *UserBuffer ) { PCI_CONFIG_ACCESS_CF8 Pci; PCI_CONFIG_ACCESS_CF8 PciAligned; UINT32 InStride; UINT32 OutStride; UINTN PciData; UINTN PciDataStride; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } if ((Width & 0x03) >= EfiPciWidthUint64) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); InStride = 1 << (Width & 0x03); OutStride = InStride; if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { InStride = 0; } if (Width >= EfiCpuIoWidthFillUint8 && Width <= EfiCpuIoWidthFillUint64) { OutStride = 0; } CopyMem (&PciAddress, &UserAddress, sizeof(UINT64)); if (PciAddress.ExtendedRegister > 0xFF) { return EFI_UNSUPPORTED; } if (PciAddress.ExtendedRegister != 0) { Pci.Bits.Reg = PciAddress.ExtendedRegister & 0xFF; } else { Pci.Bits.Reg = PciAddress.Register; } Pci.Bits.Func = PciAddress.Function; Pci.Bits.Dev = PciAddress.Device; Pci.Bits.Bus = PciAddress.Bus; Pci.Bits.Reserved = 0; Pci.Bits.Enable = 1; // // PCI Config access are all 32-bit alligned, but by accessing the // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types // are possible on PCI. // // To read a byte of PCI config space you load 0xcf8 and // read 0xcfc, 0xcfd, 0xcfe, 0xcff // PciDataStride = Pci.Bits.Reg & 0x03; while (Count) { CopyMem (&PciAligned, &Pci, sizeof (PciAligned)); PciAligned.Bits.Reg &= 0xfc; PciData = (UINTN)PrivateData->PciData + PciDataStride; EfiAcquireLock(&PrivateData->PciLock); This->Io.Write (This, EfiPciWidthUint32, PrivateData->PciAddress, 1, &PciAligned); if (Write) { This->Io.Write (This, Width, PciData, 1, UserBuffer); } else { This->Io.Read (This, Width, PciData, 1, UserBuffer); } EfiReleaseLock(&PrivateData->PciLock); UserBuffer = ((UINT8 *)UserBuffer) + OutStride; PciDataStride = (PciDataStride + InStride) % 4; Pci.Bits.Reg += InStride; Count -= 1; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI RootBridgeIoPciWrite ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) /*++ Routine Description: Allows write to PCI configuration space. Arguments: This - A pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Width - Signifies the width of the memory operation. Address - The address within the PCI configuration space for the PCI controller. Count - The number of PCI configuration operations to perform. Buffer - The source buffer to get the results. Returns: EFI_SUCCESS - The data was written to the PCI root bridge. EFI_INVALID_PARAMETER - Invalid parameters found. EFI_OUT_OF_RESOURCES - The request could not be completed due to a lack of resources. --*/ { PCI_ROOT_BRIDGE_INSTANCE *PrivateData; UINT32 PciBus; UINT32 PciDev; UINT32 PciFn; UINT32 PciExtReg; UINT64 ExtConfigAdd; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } // // Write Pci configuration space // PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This); if (PrivateData->HecBase == 0) { return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer); } if (!((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister) { PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Register; } else { PciExtReg = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->ExtendedRegister & 0x0FFF; } PciBus = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Bus; PciDev = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Device; PciFn = ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *) &Address)->Function; ExtConfigAdd = (UINT64) PrivateData->HecBase + PCIE_OFF (PciBus, PciDev, PciFn, PciExtReg); return mCpuIo->Mem.Write ( mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) Width, ExtConfigAdd, Count, Buffer ); }
EFI_STATUS EFIAPI RootBridgeIoIoWrite ( IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN OUT VOID *Buffer ) /*++ Routine Description: Io write Arguments: Returns: --*/ { UINTN AlignMask; PCI_ROOT_BRIDGE_INSTANCE *PrivateData; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH OldWidth; UINTN OldCount; if (Buffer == NULL) { return EFI_INVALID_PARAMETER; } if (Width < 0 || Width >= EfiPciWidthMaximum) { return EFI_INVALID_PARAMETER; } PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This); //AlignMask = (1 << Width) - 1; AlignMask = (1 << (Width & 0x03)) - 1; // // Check Io access limit // if (Address < PrivateData->IoBase) { return EFI_INVALID_PARAMETER; } OldWidth = Width; OldCount = Count; if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { Count = 1; } Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)(Width & 0x03); if (Address + (((UINTN)1 << Width) * Count) - 1 >= PrivateData->IoLimit) { return EFI_INVALID_PARAMETER; } if (Address & AlignMask) { return EFI_INVALID_PARAMETER; } return mCpuIo->Io.Write (mCpuIo, (EFI_CPU_IO_PROTOCOL_WIDTH) OldWidth, Address, OldCount, Buffer); }