VOID PortBusChangeProcess ( _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension ) { AHCI_SERIAL_ATA_CONTROL sctl; STOR_LOCK_HANDLE lockhandle = {0}; //1 if link speed was limited, restore the supported value. sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong); if ( (sctl.SPD != 0) && (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS) ) { sctl.SPD = 0; //AHCI 3.3.11 --- 0h No speed negotiation restrictions StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong, sctl.AsUlong); } //2 Kicks off the Start Channel state machine StorPortAcquireSpinLock(ChannelExtension->AdapterExtension, InterruptLock, NULL, &lockhandle); AhciPortReset(ChannelExtension, TRUE); // all requests should be completed StorPortReleaseSpinLock(ChannelExtension->AdapterExtension, &lockhandle); //3 Requests rescan on this port, ignore the return status of this API. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport. StorPortStateChangeDetected(ChannelExtension->AdapterExtension, STATE_CHANGE_TARGET, (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress, 0, AhciBusChangeCallback, NULL); PortReleaseActiveReference(ChannelExtension, NULL); }
VOID PortBusChangeProcess ( _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension ) { AHCI_SERIAL_ATA_CONTROL sctl; STOR_LOCK_HANDLE lockhandle = {0}; ULONG status = STOR_STATUS_UNSUCCESSFUL; //1 if link speed was limited, restore the supported value. sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong); if ( (sctl.SPD != 0) && (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS) ) { sctl.SPD = 0; //AHCI 3.3.11 --- 0h No speed negotiation restrictions StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong, sctl.AsUlong); } //2 Kicks off the Start Channel state machine AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle); AhciPortReset(ChannelExtension, TRUE); // all requests should be completed AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle); //3 Requests rescan on this port. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport. status = StorPortStateChangeDetected(ChannelExtension->AdapterExtension, STATE_CHANGE_TARGET, (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress, 0, AhciBusChangeCallback, NULL); // if the state change notification fails, set a timer to retry the notification after a delay if (status == STOR_STATUS_UNSUCCESSFUL) { if (ChannelExtension->BusChangeTimer == NULL) { StorPortInitializeTimer(ChannelExtension->AdapterExtension, &ChannelExtension->BusChangeTimer); } status = StorPortRequestTimer(ChannelExtension->AdapterExtension, ChannelExtension->BusChangeTimer, AhciBusChangeTimerCallback, ChannelExtension, 100000, // 100 milliseconds 0); if ( status != STOR_STATUS_SUCCESS ) { PortReleaseActiveReference(ChannelExtension, NULL); } } else { if (ChannelExtension->BusChangeTimer != NULL) { StorPortFreeTimer(ChannelExtension->AdapterExtension, ChannelExtension->BusChangeTimer); ChannelExtension->BusChangeTimer = NULL; } PortReleaseActiveReference(ChannelExtension, NULL); } }