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 */