From 2261af52659b0b0bb5dc733fe67fadbeb9302845 Mon Sep 17 00:00:00 2001 From: evb Date: Fri, 16 Jul 2010 01:14:52 +0000 Subject: [PATCH 1/1] IRP_MN_START_DEVICE implement for ROOT FDO (PciFdoStartDevice) PciInitializeArbiterRanges implement to scan arbiter not yet construct since Arb library missing Add PCI state machine (PciBeginStateTransition, PciCancelStateTransition, PciCommitStateTransition) andtransition array (PnpStateTransitionArray) to check if valid Now IRP_MN_QUERY_DEVICE_RELATIONS sent to ROOT FDO means time to enumerate bus! svn path=/trunk/; revision=48075 --- reactos/drivers/bus/pcix/arb/arb_comn.c | 79 +++++++++++ reactos/drivers/bus/pcix/fdo.c | 46 ++++++- reactos/drivers/bus/pcix/pci.h | 37 +++++- reactos/drivers/bus/pcix/pci/state.c | 166 ++++++++++++++++++++++++ reactos/drivers/bus/pcix/utils.c | 20 +++ 5 files changed, 344 insertions(+), 4 deletions(-) diff --git a/reactos/drivers/bus/pcix/arb/arb_comn.c b/reactos/drivers/bus/pcix/arb/arb_comn.c index b66fb549705..52e0fa43e7e 100644 --- a/reactos/drivers/bus/pcix/arb/arb_comn.c +++ b/reactos/drivers/bus/pcix/arb/arb_comn.c @@ -121,4 +121,83 @@ PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) /* Return to caller */ return Status; } + +NTSTATUS +NTAPI +PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCM_RESOURCE_LIST Resources) +{ + //PPCI_PDO_EXTENSION PdoExtension; + CM_RESOURCE_TYPE DesiredType; + PVOID Instance; + PCI_SIGNATURE ArbiterType; + + /* Arbiters should not already be initialized */ + if (DeviceExtension->ArbitersInitialized) + { + /* Duplicated start request, fail initialization */ + DPRINT1("PCI Warning hot start FDOx %08x, resource ranges not checked.\n", DeviceExtension); + return STATUS_INVALID_DEVICE_REQUEST; + } + + /* Check for non-root FDO */ + if (!PCI_IS_ROOT_FDO(DeviceExtension)) + { + /* Grab the PDO */ +#if 0 // when pdo support + PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension; + ASSERT(PdoExtension->ExtensionType == PciPdoExtensionType); +#endif + /* Multiple FDOs are not yet supported */ + UNIMPLEMENTED; + while (TRUE); + return STATUS_SUCCESS; + } + + /* Loop all arbiters */ + for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++) + { + /* Pick correct resource type for each arbiter */ + if (ArbiterType == PciArb_Io) + { + /* I/O Port */ + DesiredType = CmResourceTypePort; + } + else if (ArbiterType == PciArb_Memory) + { + /* Device RAM */ + DesiredType = CmResourceTypeMemory; + } + else + { + /* Ignore anything else */ + continue; + } + + /* Find an arbiter of this type */ + Instance = PciFindNextSecondaryExtension(&DeviceExtension->SecondaryExtension, + ArbiterType); + if (Instance) + { + /* + * Now we should initialize it, not yet implemented because Arb + * library isn't yet implemented, not even the headers. + */ + UNIMPLEMENTED; + //while (TRUE); + } + else + { + /* The arbiter was not found, this is an error! */ + DPRINT1("PCI - FDO ext 0x%08x %s arbiter (REQUIRED) is missing.\n", + DeviceExtension, + PciArbiterNames[ArbiterType - PciArb_Io]); + } + } + + /* Arbiters are now initialized */ + DeviceExtension->ArbitersInitialized = TRUE; + return STATUS_SUCCESS; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/fdo.c b/reactos/drivers/bus/pcix/fdo.c index 08d61ade478..b00b67e55ad 100644 --- a/reactos/drivers/bus/pcix/fdo.c +++ b/reactos/drivers/bus/pcix/fdo.c @@ -76,9 +76,49 @@ PciFdoIrpStartDevice(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension) { - UNIMPLEMENTED; - while (TRUE); - return STATUS_NOT_SUPPORTED; + NTSTATUS Status; + PCM_RESOURCE_LIST Resources; + PAGED_CODE(); + + /* The device stack must be starting the FDO in a success path */ + if (!NT_SUCCESS(Irp->IoStatus.Status)) return STATUS_NOT_SUPPORTED; + + /* Attempt to switch the state machine to the started state */ + Status = PciBeginStateTransition(DeviceExtension, PciStarted); + if (!NT_SUCCESS(Status)) return Status; + + /* Check for any boot-provided resources */ + Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources; + DPRINT1("Resources: %p\n", Resources); + if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) + { + /* These resources would only be for non-root FDOs, unhandled for now */ + ASSERT(Resources->Count == 1); + UNIMPLEMENTED; + while (TRUE); + } + + /* Initialize the arbiter for this FDO */ + Status = PciInitializeArbiterRanges(DeviceExtension, Resources); + if (!NT_SUCCESS(Status)) + { + /* Cancel the transition if this failed */ + PciCancelStateTransition(DeviceExtension, PciStarted); + return Status; + } + + /* Again, check for boot-provided resources for non-root FDO */ + if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) + { + /* Unhandled for now */ + ASSERT(Resources->Count == 1); + UNIMPLEMENTED; + while (TRUE); + } + + /* Commit the transition to the started state */ + PciCommitStateTransition(DeviceExtension, PciStarted); + return STATUS_SUCCESS; } NTSTATUS diff --git a/reactos/drivers/bus/pcix/pci.h b/reactos/drivers/bus/pcix/pci.h index 3ceaadb1da2..3c48449c6d9 100644 --- a/reactos/drivers/bus/pcix/pci.h +++ b/reactos/drivers/bus/pcix/pci.h @@ -309,7 +309,6 @@ PciCallDownIrpStack( IN PIRP Irp ); - // // Power Routines // @@ -564,6 +563,13 @@ PcipLinkSecondaryExtension( IN PVOID Destructor ); +PPCI_SECONDARY_EXTENSION +NTAPI +PciFindNextSecondaryExtension( + IN PSINGLE_LIST_ENTRY ListHead, + IN PCI_SIGNATURE ExtensionType +); + // // Configuration Routines // @@ -582,6 +588,28 @@ PciInitializeState( IN PPCI_FDO_EXTENSION DeviceExtension ); +NTSTATUS +NTAPI +PciBeginStateTransition( + IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCI_STATE NewState +); + +NTSTATUS +NTAPI +PciCancelStateTransition( + IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCI_STATE NewState +); + +VOID +NTAPI +PciCommitStateTransition( + IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCI_STATE NewState +); + + // // Arbiter Support // @@ -591,6 +619,13 @@ PciInitializeArbiters( IN PPCI_FDO_EXTENSION FdoExtension ); +NTSTATUS +NTAPI +PciInitializeArbiterRanges( + IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCM_RESOURCE_LIST Resources +); + // // Debug Helpers // diff --git a/reactos/drivers/bus/pcix/pci/state.c b/reactos/drivers/bus/pcix/pci/state.c index 994000f2043..62191647452 100644 --- a/reactos/drivers/bus/pcix/pci/state.c +++ b/reactos/drivers/bus/pcix/pci/state.c @@ -14,6 +14,72 @@ /* GLOBALS ********************************************************************/ +PCHAR PciTransitionText[PciMaxObjectState + 1] = +{ + "PciNotStarted", + "PciStarted", + "PciDeleted", + "PciStopped", + "PciSurpriseRemoved", + "PciSynchronizedOperation", + "PciMaxObjectState" +}; + +NTSTATUS PnpStateCancelArray[PciMaxObjectState] = +{ + STATUS_INVALID_DEVICE_REQUEST, + STATUS_FAIL_CHECK, + STATUS_INVALID_DEVICE_STATE, + STATUS_INVALID_DEVICE_STATE, + STATUS_FAIL_CHECK, + STATUS_FAIL_CHECK +}; + +NTSTATUS PnpStateTransitionArray[PciMaxObjectState * PciMaxObjectState] = +{ + STATUS_SUCCESS, // Not Started -> Not Started + STATUS_SUCCESS, // Started -> Not Started + STATUS_FAIL_CHECK, // Deleted -> Not Started + STATUS_SUCCESS, // Stopped -> Not Started + STATUS_FAIL_CHECK, // Surprise Removed -> Not Started + STATUS_FAIL_CHECK, // Synchronized Operation -> Not Started + + STATUS_SUCCESS, // Not Started -> Started + STATUS_FAIL_CHECK, // Started -> Started + STATUS_FAIL_CHECK, // Deleted -> Started + STATUS_SUCCESS, // Stopped -> Started + STATUS_FAIL_CHECK, // Surprise Removed -> Started + STATUS_FAIL_CHECK, // Synchronized Operation -> Started + + STATUS_SUCCESS, // Not Started -> Deleted + STATUS_SUCCESS, // Started -> Deleted + STATUS_FAIL_CHECK, // Deleted -> Deleted + STATUS_FAIL_CHECK, // Stopped -> Deleted + STATUS_SUCCESS, // Surprise Removed -> Deleted + STATUS_FAIL_CHECK, // Synchronized Operation -> Deleted + + STATUS_INVALID_DEVICE_REQUEST, // Not Started -> Stopped + STATUS_SUCCESS, // Started -> Stopped + STATUS_FAIL_CHECK, // Deleted -> Stopped + STATUS_FAIL_CHECK, // Stopped -> Stopped + STATUS_FAIL_CHECK, // Surprise Removed -> Stopped + STATUS_FAIL_CHECK, // Synchronized Operation -> Stopped + + STATUS_SUCCESS, // Not Started -> Surprise Removed + STATUS_SUCCESS, // Started -> Surprise Removed + STATUS_FAIL_CHECK, // Deleted -> Surprise Removed + STATUS_SUCCESS, // Stopped -> Surprise Removed + STATUS_FAIL_CHECK, // Surprise Removed -> Surprise Removed + STATUS_FAIL_CHECK, // Synchronized Operation -> Surprise Removed + + STATUS_SUCCESS, // Not Started -> Synchronized Operation + STATUS_SUCCESS, // Started -> Synchronized Operation + STATUS_INVALID_DEVICE_STATE, // Deleted -> Synchronized Operation + STATUS_SUCCESS, // Stopped -> Synchronized Operation + STATUS_INVALID_DEVICE_STATE, // Surprise Removed -> Synchronized Operation + STATUS_FAIL_CHECK // Synchronized Operation -> Synchronized Operation +}; + /* FUNCTIONS ******************************************************************/ VOID @@ -25,4 +91,104 @@ PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension) DeviceExtension->TentativeNextState = PciNotStarted; } +NTSTATUS +NTAPI +PciBeginStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCI_STATE NewState) +{ + PCI_STATE CurrentState; + NTSTATUS Status; + DPRINT1("PCI Request to begin transition of Extension %p to %s ->", + DeviceExtension, + PciTransitionText[NewState]); + + /* Assert the device isn't already in a pending transition */ + ASSERT(DeviceExtension->TentativeNextState == DeviceExtension->DeviceState); + + /* Assert this is a valid state */ + CurrentState = DeviceExtension->DeviceState; + ASSERT(CurrentState < PciMaxObjectState); + ASSERT(NewState < PciMaxObjectState); + + /* Lookup if this state transition is valid */ + Status = PnpStateTransitionArray[CurrentState + 6 * NewState]; + if (Status == STATUS_FAIL_CHECK) + { + /* Invalid transition (logical fault) */ + DPRINT1("ERROR\nPCI: Error trying to enter state \"%s\" " + "from state \"%s\"\n", + PciTransitionText[NewState], + PciTransitionText[CurrentState]); + DbgBreakPoint(); + } + else if (Status == STATUS_INVALID_DEVICE_REQUEST) + { + /* Invalid transition (illegal request) */ + DPRINT1("ERROR\nPCI: Illegal request to try to enter state \"%s\" " + "from state \"%s\", rejecting", + PciTransitionText[NewState], + PciTransitionText[CurrentState]); + } + + /* New state must be different from current, unless request is at fault */ + ASSERT((NewState != DeviceExtension->DeviceState) || (!NT_SUCCESS(Status))); + + /* Enter the new state if successful, and return state status */ + if (NT_SUCCESS(Status)) DeviceExtension->TentativeNextState = NewState; + DbgPrint("%x\n", Status); + return Status; +} + +NTSTATUS +NTAPI +PciCancelStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCI_STATE StateNotEntered) +{ + NTSTATUS Status; + DPRINT1("PCI Request to cancel transition of Extension %p to %s ->", + DeviceExtension, + PciTransitionText[StateNotEntered]); + + /* The next state can't be the state the device is already in */ + if (DeviceExtension->TentativeNextState == DeviceExtension->DeviceState) + { + /* It's too late since the state was already committed */ + ASSERT(StateNotEntered < PciMaxObjectState); + ASSERT(PnpStateCancelArray[StateNotEntered] != STATUS_FAIL_CHECK); + + /* Return failure */ + Status = STATUS_INVALID_DEVICE_STATE; + DbgPrint("%x\n", Status); + } + else + { + /* The device hasn't yet entered the state, so it's still possible to cancel */ + ASSERT(DeviceExtension->TentativeNextState == StateNotEntered); + DeviceExtension->TentativeNextState = DeviceExtension->DeviceState; + + /* Return success */ + Status = STATUS_SUCCESS; + DbgPrint("%x\n", Status); + } + + /* Return the cancel state */ + return Status; +} + +VOID +NTAPI +PciCommitStateTransition(IN PPCI_FDO_EXTENSION DeviceExtension, + IN PCI_STATE NewState) +{ + DPRINT1("PCI Commit transition of Extension %p to %s\n", + DeviceExtension, PciTransitionText[NewState]); + + /* Make sure this is a valid commit */ + ASSERT(NewState != PciSynchronizedOperation); + ASSERT(DeviceExtension->TentativeNextState == NewState); + + /* Enter the new state */ + DeviceExtension->DeviceState = NewState; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/utils.c b/reactos/drivers/bus/pcix/utils.c index 91cd9521015..0684b17ebd4 100644 --- a/reactos/drivers/bus/pcix/utils.c +++ b/reactos/drivers/bus/pcix/utils.c @@ -555,4 +555,24 @@ PciSendIoctl(IN PDEVICE_OBJECT DeviceObject, return Status; } +PPCI_SECONDARY_EXTENSION +NTAPI +PciFindNextSecondaryExtension(IN PSINGLE_LIST_ENTRY ListHead, + IN PCI_SIGNATURE ExtensionType) +{ + PSINGLE_LIST_ENTRY NextEntry; + PPCI_SECONDARY_EXTENSION Extension; + + /* Scan the list */ + for (NextEntry = ListHead; NextEntry; NextEntry = NextEntry->Next) + { + /* Grab each extension and check if it's the one requested */ + Extension = CONTAINING_RECORD(NextEntry, PCI_SECONDARY_EXTENSION, List); + if (Extension->ExtensionType == ExtensionType) return Extension; + } + + /* Nothing was found */ + return NULL; +} + /* EOF */ -- 2.17.1