Esempio n. 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));
	}
}
Esempio n. 2
0
//
// update subordinate bus [checked]
//
VOID PciUpdateAncestorSubordinateBuses(__in PPCI_FDO_EXTENSION FdoExt,__in UCHAR MaxBus)
{
	PAGED_CODE();

	while(FdoExt->ParentFdoExtension)
	{
		PPCI_PDO_EXTENSION PdoExt						= static_cast<PPCI_PDO_EXTENSION>(FdoExt->PhysicalDeviceObject->DeviceExtension);
		ASSERT(!PdoExt->NotPresent);

		if(PdoExt->Dependent.type1.SubordinateBus < MaxBus)
		{
			PdoExt->Dependent.type1.SubordinateBus		= MaxBus;
			PciWriteDeviceConfig(PdoExt,&MaxBus,FIELD_OFFSET(PCI_COMMON_HEADER,u.type1.SubordinateBus),sizeof(MaxBus));
		}

		FdoExt											= FdoExt->ParentFdoExtension;
	}

	ASSERT(FdoExt == FdoExt->BusRootFdoExtension);
	ASSERT(MaxBus <= FdoExt->MaxSubordinateBus);
}
Esempio n. 3
0
//
// set bus number [checked]
//
NTSTATUS PciSetBusNumbers(__in PPCI_PDO_EXTENSION PdoExt,__in UCHAR Primary,__in UCHAR Secondary,__in UCHAR Subordinate)
{
	PAGED_CODE();

	ASSERT(Primary < Secondary || (Primary == 0 && Secondary == 0));
	ASSERT(Secondary <= Subordinate);

	UCHAR Buffer[3]										= {Primary,Secondary,Subordinate};

	KeEnterCriticalRegion();
	KeWaitForSingleObject(&PciBusLock,Executive,KernelMode,FALSE,0);

	PdoExt->Dependent.type1.PrimaryBus					= Primary;
	PdoExt->Dependent.type1.SecondaryBus				= Secondary;
	PdoExt->Dependent.type1.SubordinateBus				= Subordinate;
	PdoExt->Dependent.type1.WeChangedBusNumbers			= TRUE;

	PciWriteDeviceConfig(PdoExt,Buffer,FIELD_OFFSET(PCI_COMMON_HEADER,u.type1.PrimaryBus),sizeof(Buffer));

	KeSetEvent(&PciBusLock,IO_NO_INCREMENT,FALSE);
	KeLeaveCriticalRegion();

	return STATUS_SUCCESS;
}
Esempio n. 4
0
NTSTATUS
NTAPI
PciSetPowerManagedDevicePowerState(IN PPCI_PDO_EXTENSION DeviceExtension,
                                   IN DEVICE_POWER_STATE DeviceState,
                                   IN BOOLEAN IrpSet)
{
    NTSTATUS Status;
    PCI_PM_CAPABILITY PmCaps;
    ULONG CapsOffset;

    /* Assume success */
    Status = STATUS_SUCCESS;

    /* Check if this device can support low power states */
    if (!(PciCanDisableDecodes(DeviceExtension, NULL, 0, TRUE)) &&
         (DeviceState != PowerDeviceD0))
    {
        /* Simply return success, ignoring this request */
        DPRINT1("Cannot disable decodes on this device, ignoring PM request...\n");
        return Status;
    }

    /* Does the device support power management at all? */
    if (!(DeviceExtension->HackFlags & PCI_HACK_NO_PM_CAPS))
    {
        /* Get the PM capabailities register */
        CapsOffset = PciReadDeviceCapability(DeviceExtension,
                                             DeviceExtension->CapabilitiesPtr,
                                             PCI_CAPABILITY_ID_POWER_MANAGEMENT,
                                             &PmCaps.Header,
                                             sizeof(PCI_PM_CAPABILITY));
        ASSERT(CapsOffset);
        ASSERT(DeviceState != PowerDeviceUnspecified);

        /* Check if the device is being powered up */
        if (DeviceState == PowerDeviceD0)
        {
            /* Set full power state */
            PmCaps.PMCSR.ControlStatus.PowerState = 0;

            /* Check if the device supports Cold-D3 poweroff */
            if (PmCaps.PMC.Capabilities.Support.PMED3Cold)
            {
                /* If there was a pending PME, clear it */
                PmCaps.PMCSR.ControlStatus.PMEStatus = 1;
            }
        }
        else
        {
            /* Otherwise, just set the new power state, converting from NT */
            PmCaps.PMCSR.ControlStatus.PowerState = DeviceState - 1;
        }

        /* Write the new power state in the PMCSR */
        PciWriteDeviceConfig(DeviceExtension,
                             &PmCaps.PMCSR,
                             CapsOffset + FIELD_OFFSET(PCI_PM_CAPABILITY, PMCSR),
                             sizeof(PCI_PMCSR));

        /* Now wait for the change to "stick" based on the spec-mandated time */
        Status = PciStallForPowerChange(DeviceExtension, DeviceState, CapsOffset);
        if (!NT_SUCCESS(Status)) return Status;
    }
    else
    {
        /* Nothing to do! */
        DPRINT1("No PM on this device, ignoring request\n");
    }

    /* Check if new resources have to be assigned */
    if (IrpSet)
    {
        /* Check if the new device state is lower (higher power) than now */
        if (DeviceState < DeviceExtension->PowerState.CurrentDeviceState)
        {
            /* We would normally re-assign resources after powerup */
            UNIMPLEMENTED_DBGBREAK();
            Status = STATUS_NOT_IMPLEMENTED;
        }
    }

    /* Return the power state change status */
    return Status;
}