Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

926 lines
22 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. pdo.c
  5. Abstract:
  6. This module contains the dispatch routines for scsiport's physical device
  7. objects
  8. Authors:
  9. Peter Wieland
  10. Environment:
  11. Kernel mode only
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "port.h"
  16. #if DBG
  17. static const char *__file__ = __FILE__;
  18. #endif
  19. VOID
  20. SpAdapterCleanup(
  21. IN PADAPTER_EXTENSION DeviceExtension
  22. );
  23. VOID
  24. SpReapChildren(
  25. IN PADAPTER_EXTENSION Adapter
  26. );
  27. BOOLEAN
  28. SpTerminateAdapterSynchronized (
  29. IN PADAPTER_EXTENSION Adapter
  30. );
  31. BOOLEAN
  32. SpRemoveAdapterSynchronized(
  33. IN PADAPTER_EXTENSION Adapter
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE, SpDeleteLogicalUnit)
  37. #pragma alloc_text(PAGE, SpRemoveLogicalUnit)
  38. #pragma alloc_text(PAGE, SpWaitForRemoveLock)
  39. #pragma alloc_text(PAGE, SpAdapterCleanup)
  40. #pragma alloc_text(PAGE, SpReapChildren)
  41. #pragma alloc_text(PAGELOCK, ScsiPortRemoveAdapter)
  42. #endif
  43. BOOLEAN
  44. SpRemoveLogicalUnit(
  45. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  46. IN UCHAR RemoveType
  47. )
  48. {
  49. PADAPTER_EXTENSION adapterExtension = LogicalUnit->AdapterExtension;
  50. ULONG isRemoved;
  51. ULONG oldDebugLevel;
  52. PAGED_CODE();
  53. if(LogicalUnit->CommonExtension.IsRemoved != REMOVE_COMPLETE) {
  54. if(RemoveType == IRP_MN_REMOVE_DEVICE) {
  55. SpWaitForRemoveLock(LogicalUnit->DeviceObject, SP_BASE_REMOVE_LOCK );
  56. //
  57. // If the device was claimed we should release it now.
  58. //
  59. if(LogicalUnit->IsClaimed) {
  60. LogicalUnit->IsClaimed = FALSE;
  61. LogicalUnit->IsLegacyClaim = FALSE;
  62. }
  63. }
  64. DebugPrint((1, "SpRemoveLogicalUnit - %sremoving device %#p\n",
  65. (RemoveType == IRP_MN_SURPRISE_REMOVAL) ? "surprise " : "",
  66. LogicalUnit));
  67. //
  68. // If the lun isn't marked as missing yet or is marked as missing but
  69. // PNP hasn't been informed yet then we cannot delete it. Set it back
  70. // to the NO_REMOVE state so that we'll be able to attempt a rescan.
  71. //
  72. // Likewise if the lun is invisible then just swallow the remove
  73. // operation now that we've cleared any existing claims.
  74. //
  75. if(RemoveType == IRP_MN_REMOVE_DEVICE) {
  76. //
  77. // If the device is not missing or is missing but is still
  78. // enumerated then don't finish destroying it.
  79. //
  80. if((LogicalUnit->IsMissing == TRUE) &&
  81. (LogicalUnit->IsEnumerated == FALSE)) {
  82. // do nothing here - fall through and destroy the device.
  83. } else {
  84. DebugPrint((1, "SpRemoveLogicalUnit - device is not missing "
  85. "and will not be destroyed\n"));
  86. SpAcquireRemoveLock(LogicalUnit->DeviceObject, SP_BASE_REMOVE_LOCK);
  87. LogicalUnit->CommonExtension.IsRemoved = NO_REMOVE;
  88. return FALSE;
  89. }
  90. } else if((LogicalUnit->IsVisible == FALSE) &&
  91. (LogicalUnit->IsMissing == FALSE)) {
  92. //
  93. // The surprise remove came because the device is no longer
  94. // visible. We don't want to destroy it.
  95. //
  96. return FALSE;
  97. }
  98. //
  99. // Mark the device as uninitialized so that we'll go back and
  100. // recreate all the necessary stuff if it gets restarted.
  101. //
  102. LogicalUnit->CommonExtension.IsInitialized = FALSE;
  103. //
  104. // Delete the device map entry for this one (if any).
  105. //
  106. SpDeleteDeviceMapEntry(&(LogicalUnit->CommonExtension));
  107. if(RemoveType == IRP_MN_REMOVE_DEVICE) {
  108. ASSERT(LogicalUnit->RequestTimeoutCounter == -1);
  109. ASSERT(LogicalUnit->ReadyLogicalUnit == NULL);
  110. ASSERT(LogicalUnit->PendingRequest == NULL);
  111. ASSERT(LogicalUnit->BusyRequest == NULL);
  112. ASSERT(LogicalUnit->QueueCount == 0);
  113. LogicalUnit->CommonExtension.IsRemoved = REMOVE_COMPLETE;
  114. //
  115. // Yank this out of the logical unit list.
  116. //
  117. SpRemoveLogicalUnitFromBin(LogicalUnit->AdapterExtension,
  118. LogicalUnit);
  119. LogicalUnit->PathId = 0xff;
  120. LogicalUnit->TargetId = 0xff;
  121. LogicalUnit->Lun = 0xff;
  122. //
  123. // If this device wasn't temporary then delete it.
  124. //
  125. if(LogicalUnit->IsTemporary == FALSE) {
  126. SpDeleteLogicalUnit(LogicalUnit);
  127. }
  128. }
  129. }
  130. return TRUE;
  131. }
  132. VOID
  133. SpDeleteLogicalUnit(
  134. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  135. )
  136. /*++
  137. Routine Description:
  138. This routine will release any resources held for the logical unit, mark the
  139. device extension as deleted, and call the io system to actually delete
  140. the object. The device object will be deleted once it's reference count
  141. drops to zero.
  142. Arguments:
  143. LogicalUnit - the device object for the logical unit to be deleted.
  144. Return Value:
  145. none
  146. --*/
  147. {
  148. PAGED_CODE();
  149. ASSERT(LogicalUnit->ReadyLogicalUnit == NULL);
  150. ASSERT(LogicalUnit->PendingRequest == NULL);
  151. ASSERT(LogicalUnit->BusyRequest == NULL);
  152. ASSERT(LogicalUnit->QueueCount == 0);
  153. ASSERT(LogicalUnit->PathId == 0xff);
  154. ASSERT(LogicalUnit->TargetId == 0xff);
  155. ASSERT(LogicalUnit->Lun == 0xff);
  156. //
  157. // Unregister with WMI.
  158. //
  159. if(LogicalUnit->CommonExtension.WmiInitialized == TRUE) {
  160. //
  161. // Destroy all our WMI resources and unregister with WMI.
  162. //
  163. IoWMIRegistrationControl(LogicalUnit->DeviceObject,
  164. WMIREG_ACTION_DEREGISTER);
  165. //
  166. // We should be asking the WmiFreeRequestList of remove some
  167. // free cells.
  168. LogicalUnit->CommonExtension.WmiInitialized = FALSE;
  169. SpWmiDestroySpRegInfo(LogicalUnit->DeviceObject);
  170. }
  171. #if DBG
  172. // ASSERT(LogicalUnit->CommonExtension.RemoveTrackingList == NULL);
  173. ExDeleteNPagedLookasideList(
  174. &(LogicalUnit->CommonExtension.RemoveTrackingLookasideList));
  175. #endif
  176. //
  177. // If the request sense irp still exists, delete it.
  178. //
  179. if(LogicalUnit->RequestSenseIrp != NULL) {
  180. IoFreeIrp(LogicalUnit->RequestSenseIrp);
  181. LogicalUnit->RequestSenseIrp = NULL;
  182. }
  183. if(LogicalUnit->HwLogicalUnitExtension != NULL) {
  184. ExFreePool(LogicalUnit->HwLogicalUnitExtension);
  185. LogicalUnit->HwLogicalUnitExtension = NULL;
  186. }
  187. if(LogicalUnit->SerialNumber.Buffer != NULL) {
  188. ExFreePool(LogicalUnit->SerialNumber.Buffer);
  189. RtlInitAnsiString(&(LogicalUnit->SerialNumber), NULL);
  190. }
  191. if(LogicalUnit->DeviceIdentifierPage != NULL) {
  192. ExFreePool(LogicalUnit->DeviceIdentifierPage);
  193. LogicalUnit->DeviceIdentifierPage = NULL;
  194. }
  195. //
  196. // If this lun is temporary then clear the RescanLun field in the adapter.
  197. //
  198. if(LogicalUnit->IsTemporary) {
  199. ASSERT(LogicalUnit->AdapterExtension->RescanLun = LogicalUnit);
  200. LogicalUnit->AdapterExtension->RescanLun = NULL;
  201. } else {
  202. ASSERT(LogicalUnit->AdapterExtension->RescanLun != LogicalUnit);
  203. }
  204. IoDeleteDevice(LogicalUnit->DeviceObject);
  205. return;
  206. }
  207. VOID
  208. ScsiPortRemoveAdapter(
  209. IN PDEVICE_OBJECT AdapterObject,
  210. IN BOOLEAN Surprise
  211. )
  212. {
  213. PADAPTER_EXTENSION adapter = AdapterObject->DeviceExtension;
  214. PCOMMON_EXTENSION commonExtension = AdapterObject->DeviceExtension;
  215. NTSTATUS status = STATUS_SUCCESS;
  216. PAGED_CODE();
  217. ASSERT_FDO(AdapterObject);
  218. ASSERT(adapter->IsPnp);
  219. //
  220. // Set the flag PD_ADAPTER_REMOVED to keep scsiport from calling into the
  221. // miniport after we've started this teardown.
  222. //
  223. if(Surprise == FALSE) {
  224. PVOID sectionHandle;
  225. KIRQL oldIrql;
  226. //
  227. // Wait until all outstanding requests have been completed. If the
  228. // adapter was surprise removed, we don't need to wait on the remove
  229. // lock again, since we already waited for it in the surprise remove
  230. // path.
  231. //
  232. if (commonExtension->CurrentPnpState != IRP_MN_SURPRISE_REMOVAL) {
  233. SpWaitForRemoveLock(AdapterObject, AdapterObject);
  234. }
  235. //
  236. // If the device is started we should uninitialize the miniport and
  237. // release it's resources. Fortunately this is exactly what stop does.
  238. //
  239. if((commonExtension->CurrentPnpState != IRP_MN_SURPRISE_REMOVAL) &&
  240. ((commonExtension->CurrentPnpState == IRP_MN_START_DEVICE) ||
  241. (commonExtension->PreviousPnpState == IRP_MN_START_DEVICE))) {
  242. //
  243. // Okay. If this adapter can't support remove then we're dead
  244. //
  245. ASSERT(SpIsAdapterControlTypeSupported(adapter, ScsiStopAdapter) == TRUE);
  246. //
  247. // Stop the miniport now that it's safe.
  248. //
  249. SpEnableDisableAdapter(adapter, FALSE);
  250. //
  251. // Mark the adapter as removed.
  252. //
  253. #ifdef ALLOC_PRAGMA
  254. sectionHandle = MmLockPagableCodeSection(ScsiPortRemoveAdapter);
  255. InterlockedIncrement(&SpPAGELOCKLockCount);
  256. #endif
  257. KeAcquireSpinLock(&(adapter->SpinLock), &oldIrql);
  258. adapter->SynchronizeExecution(adapter->InterruptObject,
  259. SpRemoveAdapterSynchronized,
  260. adapter);
  261. KeReleaseSpinLock(&(adapter->SpinLock), oldIrql);
  262. #ifdef ALLOC_PRAGMA
  263. InterlockedDecrement(&SpPAGELOCKLockCount);
  264. MmUnlockPagableImageSection(sectionHandle);
  265. #endif
  266. }
  267. SpReapChildren(adapter);
  268. }
  269. if(commonExtension->WmiInitialized == TRUE) {
  270. //
  271. // Destroy all our WMI resources and unregister with WMI.
  272. //
  273. IoWMIRegistrationControl(AdapterObject, WMIREG_ACTION_DEREGISTER);
  274. SpWmiRemoveFreeMiniPortRequestItems(adapter);
  275. commonExtension->WmiInitialized = FALSE;
  276. commonExtension->WmiMiniPortInitialized = FALSE;
  277. }
  278. //
  279. // If we were surprise removed then this has already been done once.
  280. // In that case don't try to run the cleanup code a second time even though
  281. // it's safe to do so.
  282. //
  283. SpDeleteDeviceMapEntry(commonExtension);
  284. SpDestroyAdapter(adapter, Surprise);
  285. return;
  286. }
  287. VOID
  288. SpWaitForRemoveLock(
  289. IN PDEVICE_OBJECT DeviceObject,
  290. IN PVOID LockTag
  291. )
  292. {
  293. PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  294. PAGED_CODE();
  295. //
  296. // Mark the thing as removing
  297. //
  298. commonExtension->IsRemoved = REMOVE_PENDING;
  299. //
  300. // Release our outstanding lock.
  301. //
  302. SpReleaseRemoveLock(DeviceObject, LockTag);
  303. DebugPrint((4, "SpWaitForRemoveLock - Reference count is now %d\n",
  304. commonExtension->RemoveLock));
  305. KeWaitForSingleObject(&(commonExtension->RemoveEvent),
  306. Executive,
  307. KernelMode,
  308. FALSE,
  309. NULL);
  310. DebugPrint((4, "SpWaitForRemoveLock - removing device %#p\n",
  311. DeviceObject));
  312. return;
  313. }
  314. VOID
  315. SpDestroyAdapter(
  316. IN PADAPTER_EXTENSION Adapter,
  317. IN BOOLEAN Surprise
  318. )
  319. {
  320. SpReleaseAdapterResources(Adapter, Surprise);
  321. SpAdapterCleanup(Adapter);
  322. return;
  323. }
  324. VOID
  325. SpAdapterCleanup(
  326. IN PADAPTER_EXTENSION Adapter
  327. )
  328. /*++
  329. Routine Description:
  330. This routine cleans up the names associated with the specified adapter
  331. and the i/o system counts.
  332. Arguments:
  333. Adapter - Supplies a pointer to the device extension to be deleted.
  334. Return Value:
  335. None.
  336. --*/
  337. {
  338. PCOMMON_EXTENSION commonExtension = &(Adapter->CommonExtension);
  339. PAGED_CODE();
  340. //
  341. // If we assigned a port number to this adapter then attempt to delete the
  342. // symbolic links we created to it.
  343. //
  344. if(Adapter->PortNumber != -1) {
  345. PWCHAR wideNameStrings[] = {L"\\Device\\ScsiPort%d",
  346. L"\\DosDevices\\Scsi%d:"};
  347. ULONG i;
  348. for(i = 0; i < (sizeof(wideNameStrings) / sizeof(PWCHAR)); i++) {
  349. WCHAR wideLinkName[64];
  350. UNICODE_STRING unicodeLinkName;
  351. swprintf(wideLinkName, wideNameStrings[i], Adapter->PortNumber);
  352. RtlInitUnicodeString(&unicodeLinkName, wideLinkName);
  353. IoDeleteSymbolicLink(&unicodeLinkName);
  354. }
  355. Adapter->PortNumber = -1;
  356. //
  357. // Decrement the scsiport count.
  358. //
  359. IoGetConfigurationInformation()->ScsiPortCount--;
  360. }
  361. return;
  362. }
  363. VOID
  364. SpReleaseAdapterResources(
  365. IN PADAPTER_EXTENSION Adapter,
  366. IN BOOLEAN Surprise
  367. )
  368. /*++
  369. Routine Description:
  370. This function deletes all of the storage associated with a device
  371. extension, disconnects from the timers and interrupts and then deletes the
  372. object. This function can be called at any time during the initialization.
  373. Arguments:
  374. Adapter - Supplies a pointer to the device extesnion to be deleted.
  375. Return Value:
  376. None.
  377. --*/
  378. {
  379. PCOMMON_EXTENSION commonExtension = &(Adapter->CommonExtension);
  380. ULONG j;
  381. PVOID tempPointer;
  382. PAGED_CODE();
  383. #if DBG
  384. if(!Surprise) {
  385. //
  386. // Free the Remove tracking lookaside list.
  387. //
  388. ExDeleteNPagedLookasideList(&(commonExtension->RemoveTrackingLookasideList));
  389. }
  390. #endif
  391. //
  392. // Stop the time and disconnect the interrupt if they have been
  393. // initialized. The interrupt object is connected after
  394. // timer has been initialized, and the interrupt object is connected, but
  395. // before the timer is started.
  396. //
  397. if(Adapter->DeviceObject->Timer != NULL) {
  398. IoStopTimer(Adapter->DeviceObject);
  399. KeCancelTimer(&(Adapter->MiniPortTimer));
  400. }
  401. if(Adapter->SynchronizeExecution != SpSynchronizeExecution) {
  402. if (Adapter->InterruptObject) {
  403. IoDisconnectInterrupt(Adapter->InterruptObject);
  404. }
  405. if (Adapter->InterruptObject2) {
  406. IoDisconnectInterrupt(Adapter->InterruptObject2);
  407. Adapter->InterruptObject2 = NULL;
  408. }
  409. //
  410. // SpSynchronizeExecution expects to get a pointer to the
  411. // adapter extension as the "interrupt" parameter.
  412. //
  413. Adapter->InterruptObject = (PVOID) Adapter;
  414. Adapter->SynchronizeExecution = SpSynchronizeExecution;
  415. }
  416. //
  417. // Delete the miniport's device extension
  418. //
  419. if (Adapter->HwDeviceExtension != NULL) {
  420. PHW_DEVICE_EXTENSION devExt =
  421. CONTAINING_RECORD(Adapter->HwDeviceExtension,
  422. HW_DEVICE_EXTENSION,
  423. HwDeviceExtension);
  424. ExFreePool(devExt);
  425. Adapter->HwDeviceExtension = NULL;
  426. }
  427. //
  428. // Free the configuration information structure.
  429. //
  430. if (Adapter->PortConfig) {
  431. ExFreePool(Adapter->PortConfig);
  432. Adapter->PortConfig = NULL;
  433. }
  434. //
  435. // Deallocate SCSIPORT WMI REGINFO information, if any.
  436. //
  437. SpWmiDestroySpRegInfo(Adapter->DeviceObject);
  438. //
  439. // Free the common buffer.
  440. //
  441. if (SpVerifyingCommonBuffer(Adapter)) {
  442. SpFreeCommonBufferVrfy(Adapter);
  443. } else {
  444. if (Adapter->SrbExtensionBuffer != NULL &&
  445. Adapter->CommonBufferSize != 0) {
  446. if (Adapter->DmaAdapterObject == NULL) {
  447. //
  448. // Since there is no adapter just free the non-paged pool.
  449. //
  450. ExFreePool(Adapter->SrbExtensionBuffer);
  451. } else {
  452. if(Adapter->UncachedExtensionIsCommonBuffer == FALSE) {
  453. MmFreeContiguousMemorySpecifyCache(Adapter->SrbExtensionBuffer,
  454. Adapter->CommonBufferSize,
  455. MmCached);
  456. } else {
  457. FreeCommonBuffer(
  458. Adapter->DmaAdapterObject,
  459. Adapter->CommonBufferSize,
  460. Adapter->PhysicalCommonBuffer,
  461. Adapter->SrbExtensionBuffer,
  462. FALSE);
  463. }
  464. }
  465. Adapter->SrbExtensionBuffer = NULL;
  466. }
  467. }
  468. //
  469. // Get rid of our dma adapter.
  470. //
  471. if(Adapter->DmaAdapterObject != NULL) {
  472. PutDmaAdapter(Adapter->DmaAdapterObject);
  473. Adapter->DmaAdapterObject = NULL;
  474. }
  475. //
  476. // Free the SRB data array.
  477. //
  478. if (Adapter->SrbDataListInitialized) {
  479. if(Adapter->EmergencySrbData != NULL) {
  480. ExFreeToNPagedLookasideList(
  481. &Adapter->SrbDataLookasideList,
  482. Adapter->EmergencySrbData);
  483. Adapter->EmergencySrbData = NULL;
  484. }
  485. ExDeleteNPagedLookasideList(&Adapter->SrbDataLookasideList);
  486. Adapter->SrbDataListInitialized = FALSE;
  487. }
  488. if (Adapter->InquiryBuffer != NULL) {
  489. ExFreePool(Adapter->InquiryBuffer);
  490. Adapter->InquiryBuffer = NULL;
  491. }
  492. if (Adapter->InquirySenseBuffer != NULL) {
  493. ExFreePool(Adapter->InquirySenseBuffer);
  494. Adapter->InquirySenseBuffer = NULL;
  495. }
  496. if (Adapter->InquiryIrp != NULL) {
  497. IoFreeIrp(Adapter->InquiryIrp);
  498. Adapter->InquiryIrp = NULL;
  499. }
  500. if (Adapter->InquiryMdl != NULL) {
  501. IoFreeMdl(Adapter->InquiryMdl);
  502. Adapter->InquiryMdl = NULL;
  503. }
  504. #ifndef USE_DMA_MACROS
  505. //
  506. // Free the Scatter Gather lookaside list.
  507. //
  508. if (Adapter->MediumScatterGatherListInitialized) {
  509. ExDeleteNPagedLookasideList(
  510. &Adapter->MediumScatterGatherLookasideList);
  511. Adapter->MediumScatterGatherListInitialized = FALSE;
  512. }
  513. #endif
  514. //
  515. // Unmap any mapped areas.
  516. //
  517. SpReleaseMappedAddresses(Adapter);
  518. //
  519. // If we've got any resource lists allocated still we should free them
  520. // now.
  521. //
  522. if(Adapter->AllocatedResources != NULL) {
  523. ExFreePool(Adapter->AllocatedResources);
  524. Adapter->AllocatedResources = NULL;
  525. }
  526. if(Adapter->TranslatedResources != NULL) {
  527. ExFreePool(Adapter->TranslatedResources);
  528. Adapter->TranslatedResources = NULL;
  529. }
  530. //
  531. // Cleanup verifier resources.
  532. //
  533. if (SpVerifierActive(Adapter)) {
  534. SpDoVerifierCleanup(Adapter);
  535. }
  536. #if defined(FORWARD_PROGRESS)
  537. //
  538. // Cleanup the adapter's reserved pages.
  539. //
  540. if (Adapter->ReservedPages != NULL) {
  541. MmFreeMappingAddress(Adapter->ReservedPages,
  542. SCSIPORT_TAG_MAPPING_LIST);
  543. Adapter->ReservedPages = NULL;
  544. }
  545. if (Adapter->ReservedMdl != NULL) {
  546. IoFreeMdl(Adapter->ReservedMdl);
  547. Adapter->ReservedMdl = NULL;
  548. }
  549. #endif
  550. Adapter->CommonExtension.IsInitialized = FALSE;
  551. return;
  552. }
  553. VOID
  554. SpReapChildren(
  555. IN PADAPTER_EXTENSION Adapter
  556. )
  557. {
  558. ULONG j;
  559. PAGED_CODE();
  560. //
  561. // Run through the logical unit bins and remove any child devices which
  562. // remain.
  563. //
  564. for(j = 0; j < NUMBER_LOGICAL_UNIT_BINS; j++) {
  565. while(Adapter->LogicalUnitList[j].List != NULL) {
  566. PLOGICAL_UNIT_EXTENSION lun =
  567. Adapter->LogicalUnitList[j].List;
  568. lun->IsMissing = TRUE;
  569. lun->IsEnumerated = FALSE;
  570. SpRemoveLogicalUnit(lun, IRP_MN_REMOVE_DEVICE);
  571. }
  572. }
  573. return;
  574. }
  575. VOID
  576. SpTerminateAdapter(
  577. IN PADAPTER_EXTENSION Adapter
  578. )
  579. /*++
  580. Routine Description:
  581. This routine will terminate the miniport's control of the adapter. It
  582. does not cleanly shutdown the miniport and should only be called when
  583. scsiport is notified that the adapter has been surprise removed.
  584. This works by synchronizing with the miniport and setting flags to
  585. disable any new calls into the miniport. Once this has been done it can
  586. run through and complete any i/o requests which may still be inside
  587. the miniport.
  588. Arguments:
  589. Adapter - the adapter to terminate.
  590. Return Value:
  591. none
  592. --*/
  593. {
  594. KIRQL oldIrql;
  595. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  596. KeAcquireSpinLockAtDpcLevel(&(Adapter->SpinLock));
  597. if(Adapter->CommonExtension.PreviousPnpState == IRP_MN_START_DEVICE) {
  598. //
  599. // TA synchronized will stop all calls into the miniport and complete
  600. // all active requests.
  601. //
  602. Adapter->SynchronizeExecution(Adapter->InterruptObject,
  603. SpTerminateAdapterSynchronized,
  604. Adapter);
  605. Adapter->CommonExtension.PreviousPnpState = 0xff;
  606. KeReleaseSpinLockFromDpcLevel(&(Adapter->SpinLock));
  607. //
  608. // Stop the miniport timer
  609. //
  610. KeCancelTimer(&(Adapter->MiniPortTimer));
  611. //
  612. // We keep the device object timer running so that any held, busy or
  613. // otherwise deferred requests will have a chance to get flushed out.
  614. // We can give the whole process a boost by setting the adapter timeout
  615. // counter to 1 (it will go to zero in the tick handler) and running
  616. // the tick handler by hand here.
  617. //
  618. // IoStopTimer(Adapter->DeviceObject);
  619. Adapter->PortTimeoutCounter = 1;
  620. ScsiPortTickHandler(Adapter->DeviceObject, NULL);
  621. } else {
  622. KeReleaseSpinLockFromDpcLevel(&(Adapter->SpinLock));
  623. }
  624. KeLowerIrql(oldIrql);
  625. return;
  626. }
  627. BOOLEAN
  628. SpTerminateAdapterSynchronized(
  629. IN PADAPTER_EXTENSION Adapter
  630. )
  631. {
  632. //
  633. // Disable the interrupt from coming in.
  634. //
  635. SET_FLAG(Adapter->InterruptData.InterruptFlags, PD_ADAPTER_REMOVED);
  636. CLEAR_FLAG(Adapter->InterruptData.InterruptFlags, PD_RESET_HOLD);
  637. ScsiPortCompleteRequest(Adapter->HwDeviceExtension,
  638. 0xff,
  639. 0xff,
  640. 0xff,
  641. SRB_STATUS_NO_HBA);
  642. //
  643. // Run the completion DPC.
  644. //
  645. if(TEST_FLAG(Adapter->InterruptData.InterruptFlags,
  646. PD_NOTIFICATION_REQUIRED)) {
  647. SpRequestCompletionDpc(Adapter->DeviceObject);
  648. }
  649. return TRUE;
  650. }
  651. BOOLEAN
  652. SpRemoveAdapterSynchronized(
  653. PADAPTER_EXTENSION Adapter
  654. )
  655. {
  656. //
  657. // Disable the interrupt from coming in.
  658. //
  659. SET_FLAG(Adapter->InterruptData.InterruptFlags, PD_ADAPTER_REMOVED);
  660. CLEAR_FLAG(Adapter->InterruptData.InterruptFlags, PD_RESET_HOLD);
  661. return TRUE;
  662. }