Sync with trunk r58740.
[reactos.git] / drivers / bus / pcix / pdo.c
index b54dda4..9d06b6f 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
+LONG PciPdoSequenceNumber;
+
+C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION, DeviceState) == FIELD_OFFSET(PCI_PDO_EXTENSION, DeviceState));
+C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION, TentativeNextState) == FIELD_OFFSET(PCI_PDO_EXTENSION, TentativeNextState));
+C_ASSERT(FIELD_OFFSET(PCI_FDO_EXTENSION, List) == FIELD_OFFSET(PCI_PDO_EXTENSION, Next));
+
+PCI_MN_DISPATCH_TABLE PciPdoDispatchPowerTable[] =
+{
+    {IRP_DISPATCH, (PCI_DISPATCH_FUNCTION)PciPdoWaitWake},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoSetPowerState},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryPower},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
+};
+
+PCI_MN_DISPATCH_TABLE PciPdoDispatchPnpTable[] =
+{
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpStartDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryRemoveDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpRemoveDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpCancelRemoveDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpStopDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryStopDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpCancelStopDevice},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryDeviceRelations},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryInterface},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryCapabilities},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryResources},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryResourceRequirements},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryDeviceText},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpReadConfig},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpWriteConfig},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryId},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryDeviceState},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryBusInformation},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpDeviceUsageNotification},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpSurpriseRemoval},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciPdoIrpQueryLegacyBusInformation},
+    {IRP_COMPLETE, (PCI_DISPATCH_FUNCTION)PciIrpNotSupported}
+};
+
+PCI_MJ_DISPATCH_TABLE PciPdoDispatchTable =
+{
+    IRP_MN_QUERY_LEGACY_BUS_INFORMATION,
+    PciPdoDispatchPnpTable,
+    IRP_MN_QUERY_POWER,
+    PciPdoDispatchPowerTable,
+    IRP_COMPLETE,
+    (PCI_DISPATCH_FUNCTION)PciIrpNotSupported,
+    IRP_COMPLETE,
+    (PCI_DISPATCH_FUNCTION)PciIrpInvalidDeviceRequest
+};
+
 /* FUNCTIONS ******************************************************************/
 
+NTSTATUS
+NTAPI
+PciPdoWaitWake(IN PIRP Irp,
+               IN PIO_STACK_LOCATION IoStackLocation,
+               IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoSetPowerState(IN PIRP Irp,
+                    IN PIO_STACK_LOCATION IoStackLocation,
+                    IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryPower(IN PIRP Irp,
+                    IN PIO_STACK_LOCATION IoStackLocation,
+                    IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpStartDevice(IN PIRP Irp,
+                     IN PIO_STACK_LOCATION IoStackLocation,
+                     IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    NTSTATUS Status;
+    BOOLEAN Changed, DoReset;
+    POWER_STATE PowerState;
+    PAGED_CODE();
+
+    DoReset = FALSE;
+
+    /* Begin entering the start phase */
+    Status = PciBeginStateTransition((PVOID)DeviceExtension, PciStarted);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Check if this is a VGA device */
+    if (((DeviceExtension->BaseClass == PCI_CLASS_PRE_20) &&
+         (DeviceExtension->SubClass == PCI_SUBCLASS_PRE_20_VGA)) ||
+        ((DeviceExtension->BaseClass == PCI_CLASS_DISPLAY_CTLR) &&
+         (DeviceExtension->SubClass == PCI_SUBCLASS_VID_VGA_CTLR)))
+    {
+        /* Always force it on */
+        DeviceExtension->CommandEnables |= (PCI_ENABLE_IO_SPACE |
+                                            PCI_ENABLE_MEMORY_SPACE);
+    }
+
+    /* Check if native IDE is enabled and it owns the I/O ports */
+    if (DeviceExtension->IoSpaceUnderNativeIdeControl)
+    {
+        /* Then don't allow I/O access */
+        DeviceExtension->CommandEnables &= ~PCI_ENABLE_IO_SPACE;
+    }
+
+    /* Always enable bus mastering */
+    DeviceExtension->CommandEnables |= PCI_ENABLE_BUS_MASTER;
+
+    /* Check if the OS assigned resources differ from the PCI configuration */
+    Changed = PciComputeNewCurrentSettings(DeviceExtension,
+                                           IoStackLocation->Parameters.
+                                           StartDevice.AllocatedResources);
+    if (Changed)
+    {
+        /* Remember this for later */
+        DeviceExtension->MovedDevice = TRUE;
+    }
+    else
+    {
+        /* All good */
+        DPRINT1("PCI - START not changing resource settings.\n");
+    }
+
+    /* Check if the device was sleeping */
+    if (DeviceExtension->PowerState.CurrentDeviceState != PowerDeviceD0)
+    {
+        /* Power it up */
+        Status = PciSetPowerManagedDevicePowerState(DeviceExtension,
+                                                    PowerDeviceD0,
+                                                    FALSE);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Powerup fail, fail the request */
+            PciCancelStateTransition((PVOID)DeviceExtension, PciStarted);
+            return STATUS_DEVICE_POWER_FAILURE;
+        }
+
+        /* Tell the power manager that the device is powered up */
+        PowerState.DeviceState = PowerDeviceD0;
+        PoSetPowerState(DeviceExtension->PhysicalDeviceObject,
+                        DevicePowerState,
+                        PowerState);
+
+        /* Update internal state */
+        DeviceExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
+
+        /* This device's resources and decodes will need to be reset */
+        DoReset = TRUE;
+    }
+
+    /* Update resource information now that the device is powered up and active */
+    Status = PciSetResources(DeviceExtension, DoReset, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* That failed, so cancel the transition */
+        PciCancelStateTransition((PVOID)DeviceExtension, PciStarted);
+    }
+    else
+    {
+        /* Fully commit, as the device is now started up and ready to go */
+        PciCommitStateTransition((PVOID)DeviceExtension, PciStarted);
+    }
+
+    /* Return the result of the start request */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryRemoveDevice(IN PIRP Irp,
+                           IN PIO_STACK_LOCATION IoStackLocation,
+                           IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpRemoveDevice(IN PIRP Irp,
+                      IN PIO_STACK_LOCATION IoStackLocation,
+                      IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpCancelRemoveDevice(IN PIRP Irp,
+                            IN PIO_STACK_LOCATION IoStackLocation,
+                            IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpStopDevice(IN PIRP Irp,
+                    IN PIO_STACK_LOCATION IoStackLocation,
+                    IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryStopDevice(IN PIRP Irp,
+                         IN PIO_STACK_LOCATION IoStackLocation,
+                         IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpCancelStopDevice(IN PIRP Irp,
+                          IN PIO_STACK_LOCATION IoStackLocation,
+                          IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryInterface(IN PIRP Irp,
+                        IN PIO_STACK_LOCATION IoStackLocation,
+                        IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryDeviceRelations(IN PIRP Irp,
+                              IN PIO_STACK_LOCATION IoStackLocation,
+                              IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    /* Are ejection relations being queried? */
+    if (IoStackLocation->Parameters.QueryDeviceRelations.Type == EjectionRelations)
+    {
+        /* Call the worker function */
+        Status = PciQueryEjectionRelations(DeviceExtension,
+                                           (PDEVICE_RELATIONS*)&Irp->
+                                           IoStatus.Information);
+    }
+    else if (IoStackLocation->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation)
+    {
+        /* The only other relation supported is the target device relation */
+        Status = PciQueryTargetDeviceRelations(DeviceExtension,
+                                               (PDEVICE_RELATIONS*)&Irp->
+                                               IoStatus.Information);
+    }
+    else
+    {
+        /* All other relations are unsupported */
+        Status = STATUS_NOT_SUPPORTED;
+    }
+
+    /* Return either the result of the worker function, or unsupported status */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryCapabilities(IN PIRP Irp,
+                           IN PIO_STACK_LOCATION IoStackLocation,
+                           IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+
+    /* Call the worker function */
+    return PciQueryCapabilities(DeviceExtension,
+                                IoStackLocation->
+                                Parameters.DeviceCapabilities.Capabilities);
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryResources(IN PIRP Irp,
+                        IN PIO_STACK_LOCATION IoStackLocation,
+                        IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+
+    /* Call the worker function */
+    return PciQueryResources(DeviceExtension,
+                            (PCM_RESOURCE_LIST*)&Irp->IoStatus.Information);
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryResourceRequirements(IN PIRP Irp,
+                                   IN PIO_STACK_LOCATION IoStackLocation,
+                                   IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+
+    /* Call the worker function */
+    return PciQueryRequirements(DeviceExtension,
+                                (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->
+                                IoStatus.Information);
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryDeviceText(IN PIRP Irp,
+                         IN PIO_STACK_LOCATION IoStackLocation,
+                         IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+
+    /* Call the worker function */
+    return PciQueryDeviceText(DeviceExtension,
+                              IoStackLocation->
+                              Parameters.QueryDeviceText.DeviceTextType,
+                              IoStackLocation->
+                              Parameters.QueryDeviceText.LocaleId,
+                              (PWCHAR*)&Irp->IoStatus.Information);
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryId(IN PIRP Irp,
+                 IN PIO_STACK_LOCATION IoStackLocation,
+                 IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+
+    /* Call the worker function */
+    return PciQueryId(DeviceExtension,
+                      IoStackLocation->Parameters.QueryId.IdType,
+                      (PWCHAR*)&Irp->IoStatus.Information);
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryBusInformation(IN PIRP Irp,
+                             IN PIO_STACK_LOCATION IoStackLocation,
+                             IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    PAGED_CODE();
+
+    /* Call the worker function */
+    return PciQueryBusInformation(DeviceExtension,
+                                  (PPNP_BUS_INFORMATION*)&Irp->
+                                  IoStatus.Information);
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpReadConfig(IN PIRP Irp,
+                    IN PIO_STACK_LOCATION IoStackLocation,
+                    IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpWriteConfig(IN PIRP Irp,
+                     IN PIO_STACK_LOCATION IoStackLocation,
+                     IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryDeviceState(IN PIRP Irp,
+                          IN PIO_STACK_LOCATION IoStackLocation,
+                          IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpDeviceUsageNotification(IN PIRP Irp,
+                                 IN PIO_STACK_LOCATION IoStackLocation,
+                                 IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpSurpriseRemoval(IN PIRP Irp,
+                         IN PIO_STACK_LOCATION IoStackLocation,
+                         IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoIrpQueryLegacyBusInformation(IN PIRP Irp,
+                                   IN PIO_STACK_LOCATION IoStackLocation,
+                                   IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+    UNIMPLEMENTED_DBGBREAK();
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+NTAPI
+PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension,
+             IN PCI_SLOT_NUMBER Slot,
+             OUT PDEVICE_OBJECT *PdoDeviceObject)
+{
+    WCHAR DeviceName[32];
+    UNICODE_STRING DeviceString;
+    NTSTATUS Status;
+    PDEVICE_OBJECT DeviceObject;
+    PPCI_PDO_EXTENSION PdoExtension;
+    ULONG SequenceNumber;
+    PAGED_CODE();
+
+    /* Pick an atomically unique sequence number for this device */
+    SequenceNumber = InterlockedIncrement(&PciPdoSequenceNumber);
+
+    /* Create the standard PCI device name for a PDO */
+    swprintf(DeviceName, L"\\Device\\NTPNP_PCI%04d", SequenceNumber);
+    RtlInitUnicodeString(&DeviceString, DeviceName);
+
+    /* Create the actual device now */
+    Status = IoCreateDevice(DeviceExtension->FunctionalDeviceObject->DriverObject,
+                            sizeof(PCI_PDO_EXTENSION),
+                            &DeviceString,
+                            FILE_DEVICE_BUS_EXTENDER,
+                            0,
+                            0,
+                            &DeviceObject);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Get the extension for it */
+    PdoExtension = (PPCI_PDO_EXTENSION)DeviceObject->DeviceExtension;
+    DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
+            DeviceExtension->BaseBus,
+            Slot.u.bits.DeviceNumber,
+            Slot.u.bits.FunctionNumber,
+            DeviceObject,
+            DeviceObject->DeviceExtension);
+
+    /* Configure the extension */
+    PdoExtension->ExtensionType = PciPdoExtensionType;
+    PdoExtension->IrpDispatchTable = &PciPdoDispatchTable;
+    PdoExtension->PhysicalDeviceObject = DeviceObject;
+    PdoExtension->Slot = Slot;
+    PdoExtension->PowerState.CurrentSystemState = PowerDeviceD0;
+    PdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
+    PdoExtension->ParentFdoExtension = DeviceExtension;
+
+    /* Initialize the lock for arbiters and other interfaces */
+    KeInitializeEvent(&PdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE);
+
+    /* Initialize the state machine */
+    PciInitializeState((PPCI_FDO_EXTENSION)PdoExtension);
+
+    /* Add the PDO to the parent's list */
+    PdoExtension->Next = NULL;
+    PciInsertEntryAtTail((PSINGLE_LIST_ENTRY)&DeviceExtension->ChildPdoList,
+                         (PPCI_FDO_EXTENSION)PdoExtension,
+                         &DeviceExtension->ChildListLock);
+
+    /* And finally return it to the caller */
+    *PdoDeviceObject = DeviceObject;
+    return STATUS_SUCCESS;
+}
+
 /* EOF */