Exemple #1
0
//
// update interrupt line [checked]
//
VOID PciUpdateInterruptLine(__in PDEVICE_OBJECT Pdo,__in UCHAR LineRegister)
{
	PAGED_CODE();

	PPCI_LEGACY_DEVICE_INFO Info						= CONTAINING_RECORD(PciLegacyDeviceHead.Next,PCI_LEGACY_DEVICE_INFO,ListEntry);
	PPCI_PDO_EXTENSION PdoExt							= static_cast<PPCI_PDO_EXTENSION>(Pdo->DeviceExtension);

	while(Info)
	{
		if(Info->OwnerDevice == Pdo)
		{
			PdoExt										= Info->PdoExt;
			break;
		}
		Info											= CONTAINING_RECORD(Info->ListEntry.Next,PCI_LEGACY_DEVICE_INFO,ListEntry);
	}

	ASSERT(PdoExt->Common.ExtensionType == PciPdoExtensionType);

	//
	// set raw/adjusted interrupt line
	//
	PdoExt->AdjustedInterruptLine						= LineRegister;
	PdoExt->RawInterruptLine							= LineRegister;

	//
	// and program hardware
	//
	PciWriteDeviceConfig(PdoExt,&LineRegister,FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.InterruptLine),sizeof(LineRegister));

	//
	// update registry data
	//
	PCI_COMMON_HEADER BiosConfig;
	NTSTATUS Status										= PciGetBiosConfig(PdoExt,&BiosConfig);
	ASSERT(NT_SUCCESS(Status));

	if(BiosConfig.u.type0.InterruptLine != LineRegister)
	{
		Status											= PciSaveBiosConfig(PdoExt,&BiosConfig);
		ASSERT(NT_SUCCESS(Status));
	}
}
Exemple #2
0
VOID
NTAPI
PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
    NTSTATUS Status;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
    PIO_RESOURCE_DESCRIPTOR IoDescriptor;
    PPCI_FUNCTION_RESOURCES Resources;
    PCI_COMMON_HEADER BiosData;
    PPCI_COMMON_HEADER Current;
    PPCI_COMMON_CONFIG SavedConfig;
    ULONG i, Bar, BarMask;
    PULONG BarArray;
    PHYSICAL_ADDRESS Limit, Base, Length;
    BOOLEAN HaveIoLimit, CheckAlignment;
    PPCI_PDO_EXTENSION PdoExtension;

    /* Get the pointers from the extension */
    PdoExtension = Context->PdoExtension;
    Resources = PdoExtension->Resources;
    Current = Context->Current;

    /* Check if decodes are disabled */
    if (!(Context->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)))
    {
        /* Well, we're going to need them from somewhere, use the registry data */
        Status = PciGetBiosConfig(PdoExtension, &BiosData);
        if (NT_SUCCESS(Status)) Current = &BiosData;
    }

    /* Scan all current and limit descriptors for each BAR needed */
    BarArray = Current->u.type1.BaseAddresses;
    for (i = 0; i < 6; i++)
    {
        /* Get the current resource descriptor, and the limit requirement */
        CmDescriptor = &Resources->Current[i];
        IoDescriptor = &Resources->Limit[i];

        /* Copy descriptor data, skipping null descriptors */
        CmDescriptor->Type = IoDescriptor->Type;
        if (CmDescriptor->Type == CmResourceTypeNull) continue;
        CmDescriptor->Flags = IoDescriptor->Flags;
        CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;

        /* Initialize the high-parts to zero, since most stuff is 32-bit only */
        Base.QuadPart = Limit.QuadPart = Length.QuadPart = 0;

        /* Check if we're handling PCI BARs, or the ROM BAR */
        if ((i < PCI_TYPE1_ADDRESSES) || (i == 5))
        {
            /* Is this the ROM BAR? */
            if (i == 5)
            {
                /* Read the correct bar, with the appropriate mask */
                Bar = Current->u.type1.ROMBaseAddress;
                BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK;

                /* Decode the base address, and write down the length */
                Base.LowPart = Bar & BarMask;
                DPRINT1("ROM BAR Base: %lx\n", Base.LowPart);
                CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
            }
            else
            {
                /* Otherwise, get the BAR from the array */
                Bar = BarArray[i];

                /* Is this an I/O BAR? */
                if (Bar & PCI_ADDRESS_IO_SPACE)
                {
                    /* Set the correct mask */
                    ASSERT(CmDescriptor->Type == CmResourceTypePort);
                    BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
                }
                else
                {
                    /* This is a memory BAR, set the correct base */
                    ASSERT(CmDescriptor->Type == CmResourceTypeMemory);
                    BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;

                    /* IS this a 64-bit BAR? */
                    if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
                    {
                        /* Read the next 32-bits as well, ie, the next BAR */
                        Base.HighPart = BarArray[i + 1];
                    }
                }

                /* Decode the base address, and write down the length */
                Base.LowPart = Bar & BarMask;
                DPRINT1("BAR Base: %lx\n", Base.LowPart);
                CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
            }
        }
        else
        {
            /* Reset loop conditions */
            HaveIoLimit = FALSE;
            CheckAlignment = FALSE;

            /* Check which descriptor is being parsed */
            if (i == 2)
            {
                /* I/O Port Requirements */
                Base.LowPart = PciBridgeIoBase(Current);
                Limit.LowPart = PciBridgeIoLimit(Current);
                DPRINT1("Bridge I/O Base and Limit: %lx %lx\n",
                         Base.LowPart, Limit.LowPart);

                /* Do we have any I/O Port data? */
                if (!(Base.LowPart) && (Current->u.type1.IOLimit))
                {
                    /* There's a limit */
                    HaveIoLimit = TRUE;
                }
            }
            else if (i == 3)
            {
                /* Memory requirements */
                Base.LowPart = PciBridgeMemoryBase(Current);
                Limit.LowPart = PciBridgeMemoryLimit(Current);

                /* These should always be there, so check their alignment */
                DPRINT1("Bridge MEM Base and Limit: %lx %lx\n",
                         Base.LowPart, Limit.LowPart);
                CheckAlignment = TRUE;
            }
            else if (i == 4)
            {
                /* This should only be present for prefetch memory */
                ASSERT(CmDescriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE);
                Base = PciBridgePrefetchMemoryBase(Current);
                Limit = PciBridgePrefetchMemoryLimit(Current);

                /* If it's there, check the alignment */
                DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n", Base, Limit);
                CheckAlignment = TRUE;
            }

            /* Check for invalid base address */
            if (Base.QuadPart >= Limit.QuadPart)
            {
                /* Assume the descriptor is bogus */
                CmDescriptor->Type = CmResourceTypeNull;
                IoDescriptor->Type = CmResourceTypeNull;
                continue;
            }

            /* Check if there's no memory, and no I/O port either */
            if (!(Base.LowPart) && !(HaveIoLimit))
            {
                /* This seems like a bogus requirement, ignore it */
                CmDescriptor->Type = CmResourceTypeNull;
                continue;
            }

            /* Set the length to be the limit - the base; should always be 32-bit */
            Length.QuadPart = Limit.LowPart - Base.LowPart + 1;
            ASSERT(Length.HighPart == 0);
            CmDescriptor->u.Generic.Length = Length.LowPart;

            /* Check if alignment should be set */
            if (CheckAlignment)
            {
                /* Compute the required alignment for this length */
                ASSERT(CmDescriptor->u.Memory.Length > 0);
                IoDescriptor->u.Memory.Alignment =
                    PciBridgeMemoryWorstCaseAlignment(CmDescriptor->u.Memory.Length);
            }
        }

        /* Now set the base address */
        CmDescriptor->u.Generic.Start.LowPart = Base.LowPart;
    }

    /* Save PCI settings into the PDO extension for easy access later */
    PdoExtension->Dependent.type1.PrimaryBus = Current->u.type1.PrimaryBus;
    PdoExtension->Dependent.type1.SecondaryBus = Current->u.type1.SecondaryBus;
    PdoExtension->Dependent.type1.SubordinateBus = Current->u.type1.SubordinateBus;

    /* Check for subtractive decode bridges */
    if (PdoExtension->Dependent.type1.SubtractiveDecode)
    {
        /* Check if legacy VGA decodes are enabled */
        DPRINT1("Subtractive decode bridge\n");
        if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
        {
            /* Save this setting for later */
            DPRINT1("VGA Bridge\n");
            PdoExtension->Dependent.type1.VgaBitSet = TRUE;
        }

        /* Legacy ISA decoding is not compatible with subtractive decode */
        ASSERT(PdoExtension->Dependent.type1.IsaBitSet == FALSE);
    }
    else
    {
        /* Check if legacy VGA decodes are enabled */
        if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
        {
            /* Save this setting for later */
            DPRINT1("VGA Bridge\n");
            PdoExtension->Dependent.type1.VgaBitSet = TRUE;

            /* And on positive decode, we'll also need extra resources locked */
            PdoExtension->AdditionalResourceCount = 4;
        }

        /* Check if legacy ISA decoding is enabled */
        if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA)
        {
            /* Save this setting for later */
            DPRINT1("ISA Bridge\n");
            PdoExtension->Dependent.type1.IsaBitSet = TRUE;
        }
    }

    /*
     * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
     * i820, i840, i845 Chipsets) that have subtractive decode broken.
     */
    if (((PdoExtension->VendorId == 0x8086) &&
         ((PdoExtension->DeviceId == 0x2418) ||
          (PdoExtension->DeviceId == 0x2428) ||
          (PdoExtension->DeviceId == 0x244E) ||
          (PdoExtension->DeviceId == 0x2448))) ||
        (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
    {
        /* Check if subtractive decode is actually enabled */
        if (PdoExtension->Dependent.type1.SubtractiveDecode)
        {
            /* We're going to need a copy of the configuration for later use */
            DPRINT1("apply config save hack to ICH subtractive decode\n");
            SavedConfig = ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH, 'PciP');
            PdoExtension->ParentFdoExtension->PreservedConfig = SavedConfig;
            if (SavedConfig) RtlCopyMemory(SavedConfig, Current, PCI_COMMON_HDR_LENGTH);
        }
    }
}