Leaked source code of windows server 2003
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.

1620 lines
44 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. #define KEEP_COMPLETE_REQUEST
  16. #include "port.h"
  17. #define __FILE_ID__ 'pdo '
  18. #if DBG
  19. static const char *__file__ = __FILE__;
  20. #endif
  21. LONG SpPowerIdleTimeout = -1; // use system default
  22. NTSTATUS
  23. SpPdoHandleIoctlStorageQueryProperty(
  24. IN PDEVICE_OBJECT Pdo,
  25. IN PIRP Irp
  26. );
  27. NTSTATUS
  28. SpPdoHandleIoctlScsiGetAddress(
  29. IN PDEVICE_OBJECT Pdo,
  30. IN PIRP Irp
  31. );
  32. NTSTATUS
  33. SpPdoHandleIoctlScsiPassthrough(
  34. IN PDEVICE_OBJECT Pdo,
  35. IN PIRP Irp
  36. );
  37. NTSTATUS
  38. SpPdoHandleIoctlScsiPassthroughDirect(
  39. IN PDEVICE_OBJECT Pdo,
  40. IN PIRP Irp
  41. );
  42. NTSTATUS
  43. SpPagingPathNotificationCompletion(
  44. IN PDEVICE_OBJECT DeviceObject,
  45. IN PIRP LowerIrp,
  46. IN PDEVICE_OBJECT Fdo
  47. );
  48. #ifdef ALLOC_PRAGMA
  49. #pragma alloc_text(PAGE, ScsiPortPdoPnp)
  50. #pragma alloc_text(PAGE, ScsiPortPdoCreateClose)
  51. #pragma alloc_text(PAGE, ScsiPortStartLogicalUnit)
  52. #pragma alloc_text(PAGE, ScsiPortInitPdoWmi)
  53. #pragma alloc_text(PAGE, SpPdoHandleIoctlStorageQueryProperty)
  54. #pragma alloc_text(PAGE, SpPdoHandleIoctlScsiGetAddress)
  55. #pragma alloc_text(PAGE, SpPdoHandleIoctlScsiPassthrough)
  56. #pragma alloc_text(PAGE, SpPdoHandleIoctlScsiPassthroughDirect)
  57. #endif
  58. NTSTATUS
  59. SpPdoHandleIoctlStorageQueryProperty(
  60. IN PDEVICE_OBJECT Pdo,
  61. IN PIRP Irp
  62. )
  63. /*++
  64. Routine Description:
  65. This routine handles the IOCTL_STORAGE_QUERY_PROPERTY request for a PDO.
  66. It validates the input buffer and passes calls a helper routine to do the
  67. work. The helper routine handles completing or forwarding the request and
  68. releasing the remove lock.
  69. Arguments:
  70. Pdo - Supplies a pointer to the physical device object
  71. Irp - Supplies a pointer to the io request packet
  72. Return Value:
  73. NTSTATUS
  74. --*/
  75. {
  76. NTSTATUS status;
  77. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  78. PAGED_CODE();
  79. if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
  80. sizeof(STORAGE_PROPERTY_QUERY)) {
  81. //
  82. // The input buffer is not big enough to hold a STORAGE_PROPERTY_QUERY
  83. // structure. Fail the request.
  84. //
  85. status = STATUS_INVALID_PARAMETER;
  86. Irp->IoStatus.Status = status;
  87. SpReleaseRemoveLock(Pdo, Irp);
  88. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  89. } else {
  90. //
  91. // Call helper routine to do the bulk of the work. The helper completes
  92. // or forwards the request down the stack and releases the remove lock.
  93. //
  94. status = ScsiPortQueryPropertyPdo(Pdo, Irp);
  95. }
  96. return status;
  97. }
  98. NTSTATUS
  99. SpPdoHandleIoctlScsiGetAddress(
  100. IN PDEVICE_OBJECT Pdo,
  101. IN PIRP Irp
  102. )
  103. /*++
  104. Routine Description:
  105. This routine handles the IOCTL_SCSI_GET_ADDRESS. It validates the input
  106. that the output buffer is big enough to hold a SCSI_ADDRESS structure. If
  107. the buffer is big enough, it copies the address information into the buffer.
  108. Arguments:
  109. Pdo - Supplies a pointer to the physical device object
  110. Irp - Supplies a pointer to the io request packet
  111. Return Value:
  112. STATUS_SUCCESS if the supplied buffer is big enough to hold the address.
  113. STATUS_BUFFER_TOO_SMALL if the supplied buffer is too small.
  114. --*/
  115. {
  116. NTSTATUS status;
  117. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  118. PLOGICAL_UNIT_EXTENSION luExtension = Pdo->DeviceExtension;
  119. PSCSI_ADDRESS scsiAddress = Irp->AssociatedIrp.SystemBuffer;
  120. PAGED_CODE();
  121. if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
  122. sizeof(SCSI_ADDRESS)) {
  123. //
  124. // The output buffer is too small to hold a SCSI_ADDRESS structure,
  125. // so we fail the request.
  126. //
  127. status = STATUS_BUFFER_TOO_SMALL;
  128. } else {
  129. //
  130. // Fill in the address information and set the IoStatus.Information
  131. // to the sizeof the SCSI_ADDRESS structure.
  132. //
  133. scsiAddress->Length = sizeof(SCSI_ADDRESS);
  134. scsiAddress->PortNumber = (UCHAR) luExtension->PortNumber;
  135. scsiAddress->PathId = luExtension->PathId;
  136. scsiAddress->TargetId = luExtension->TargetId;
  137. scsiAddress->Lun = luExtension->Lun;
  138. status = STATUS_SUCCESS;
  139. Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
  140. }
  141. //
  142. // Complete the request and release the remove lock.
  143. //
  144. Irp->IoStatus.Status = status;
  145. SpReleaseRemoveLock(Pdo, Irp);
  146. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  147. return status;
  148. }
  149. NTSTATUS
  150. SpPdoHandleIoctlScsiPassthrough(
  151. IN PDEVICE_OBJECT Pdo,
  152. IN PIRP Irp
  153. )
  154. /*++
  155. Routine Description:
  156. This routine handles IOCTL_SCSI_PASS_THROUGH. It checks that the input
  157. buffer is big enough to hold a SCSI_PASS_THROUGH structure, fills in the
  158. address information for this LU and passes the request down to the FDO
  159. handler to do the real work.
  160. Arguments:
  161. Pdo - Supplies a pointer to the physical device object
  162. Irp - Supplies a pointer to the io request packet
  163. Return Value:
  164. NTSTATUS
  165. --*/
  166. {
  167. PLOGICAL_UNIT_EXTENSION luExtension = Pdo->DeviceExtension;
  168. NTSTATUS status;
  169. PAGED_CODE();
  170. //
  171. // Initialize the address of the SCSI_PASS_THROUGH structure embedded
  172. // in the supplied IRP. This routine verifies that the size of the
  173. // SystemBuffer is big enough to hold a SCSI_PASS_THROUGH structure
  174. // before it touches it.
  175. //
  176. status = PortSetPassThroughAddress(
  177. Irp,
  178. luExtension->PathId,
  179. luExtension->TargetId,
  180. luExtension->Lun
  181. );
  182. if (status != STATUS_SUCCESS) {
  183. Irp->IoStatus.Status = status;
  184. SpReleaseRemoveLock(Pdo, Irp);
  185. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  186. } else {
  187. //
  188. // Forward the request down to the FDO handler.
  189. //
  190. PCOMMON_EXTENSION commonExtension = Pdo->DeviceExtension;
  191. IoSkipCurrentIrpStackLocation(Irp);
  192. SpReleaseRemoveLock(Pdo, Irp);
  193. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  194. }
  195. return status;
  196. }
  197. NTSTATUS
  198. SpPdoHandleIoctlScsiPassthroughDirect(
  199. IN PDEVICE_OBJECT Pdo,
  200. IN PIRP Irp
  201. )
  202. /*++
  203. Routine Description:
  204. This routine handles IOCTL_SCSI_PASS_THROUGH_DIRECT. It simply delegates
  205. to the handler for IOCTL_SCSI_PASS_THROUGH since they both do exactly the
  206. same thing.
  207. Arguments:
  208. Pdo - Supplies a pointer to the physical device object
  209. Irp - Supplies a pointer to the io request packet
  210. Return Value:
  211. NTSTATUS
  212. --*/
  213. {
  214. PAGED_CODE();
  215. return SpPdoHandleIoctlScsiPassthrough(Pdo, Irp);
  216. }
  217. NTSTATUS
  218. ScsiPortPdoDeviceControl(
  219. IN PDEVICE_OBJECT Pdo,
  220. IN PIRP Irp
  221. )
  222. /*++
  223. Routine Description:
  224. This routine handles device control requests for scsi target devices
  225. Arguments:
  226. Pdo - a pointer to the physical device object
  227. Irp - a pointer to the io request packet
  228. Return Value:
  229. status
  230. --*/
  231. {
  232. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  233. ULONG ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
  234. PCOMMON_EXTENSION commonExtension = Pdo->DeviceExtension;
  235. NTSTATUS status;
  236. ULONG isRemoved;
  237. //
  238. // If the device has been removed or is in the process of being removed,
  239. // we must fail this request.
  240. //
  241. isRemoved = SpAcquireRemoveLock(Pdo, Irp);
  242. if (isRemoved) {
  243. SpReleaseRemoveLock(Pdo, Irp);
  244. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  245. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  246. return STATUS_DEVICE_DOES_NOT_EXIST;
  247. }
  248. ASSERT(commonExtension->IsPdo);
  249. //
  250. // Initialize the status.
  251. //
  252. Irp->IoStatus.Status = 0;
  253. Irp->IoStatus.Information = 0;
  254. switch (ioControlCode) {
  255. case IOCTL_STORAGE_QUERY_PROPERTY:
  256. status = SpPdoHandleIoctlStorageQueryProperty(Pdo, Irp);
  257. break;
  258. case IOCTL_SCSI_GET_ADDRESS:
  259. status = SpPdoHandleIoctlScsiGetAddress(Pdo, Irp);
  260. break;
  261. case IOCTL_SCSI_PASS_THROUGH:
  262. status = SpPdoHandleIoctlScsiPassthrough(Pdo, Irp);
  263. break;
  264. case IOCTL_SCSI_PASS_THROUGH_DIRECT:
  265. status = SpPdoHandleIoctlScsiPassthroughDirect(Pdo, Irp);
  266. break;
  267. case IOCTL_SCSI_GET_DUMP_POINTERS:
  268. IoSkipCurrentIrpStackLocation(Irp);
  269. SpReleaseRemoveLock(Pdo, Irp);
  270. status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
  271. break;
  272. default: {
  273. DebugPrint((1, "ScsiPortPdoDeviceControl: unsupported IOCTL %08x\n",
  274. ioControlCode));
  275. SpReleaseRemoveLock(Pdo, Irp);
  276. status = STATUS_INVALID_DEVICE_REQUEST;
  277. Irp->IoStatus.Status = status;
  278. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  279. break;
  280. }
  281. }
  282. return status;
  283. }
  284. NTSTATUS
  285. ScsiPortPdoPnp(
  286. IN PDEVICE_OBJECT LogicalUnit,
  287. IN PIRP Irp
  288. )
  289. /*++
  290. Routine Description:
  291. This routine handles pnp-power requests. Currently it will just be
  292. successful
  293. Arguments:
  294. LogicalUnit - pointer to the physical device object
  295. Irp - pointer to the io request packet
  296. Return Value:
  297. status
  298. --*/
  299. {
  300. PLOGICAL_UNIT_EXTENSION logicalUnitExtension = LogicalUnit->DeviceExtension;
  301. PCOMMON_EXTENSION commonExtension = LogicalUnit->DeviceExtension;
  302. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  303. static ULONG i = 0;
  304. NTSTATUS status = STATUS_SUCCESS;
  305. ULONG isRemoved;
  306. PAGED_CODE();
  307. isRemoved = SpAcquireRemoveLock(LogicalUnit, Irp);
  308. #if 0
  309. if(isRemoved != ) {
  310. ASSERT(isRemoved != REMOVE_PENDING);
  311. status = STATUS_DEVICE_DOES_NOT_EXIST;
  312. Irp->IoStatus.Status = status;
  313. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  314. return status;
  315. }
  316. #else
  317. ASSERT(isRemoved != REMOVE_COMPLETE);
  318. #endif
  319. switch(irpStack->MinorFunction) {
  320. case IRP_MN_QUERY_PNP_DEVICE_STATE: {
  321. //
  322. // If the device is in the paging path then mark it as
  323. // not-disableable.
  324. //
  325. PPNP_DEVICE_STATE deviceState =
  326. (PPNP_DEVICE_STATE) &(Irp->IoStatus.Information);
  327. DebugPrint((1, "ScsiPortPdoPnp: QUERY_DEVICE_STATE for PDO %#x\n", LogicalUnit));
  328. if(commonExtension->PagingPathCount != 0) {
  329. SET_FLAG((*deviceState), PNP_DEVICE_NOT_DISABLEABLE);
  330. DebugPrint((1, "ScsiPortPdoPnp: QUERY_DEVICE_STATE: %#x - not disableable\n",
  331. LogicalUnit));
  332. }
  333. Irp->IoStatus.Status = STATUS_SUCCESS;
  334. SpReleaseRemoveLock(LogicalUnit, Irp);
  335. SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
  336. return STATUS_SUCCESS;
  337. }
  338. case IRP_MN_START_DEVICE: {
  339. if(commonExtension->CurrentPnpState == IRP_MN_START_DEVICE) {
  340. Irp->IoStatus.Status = STATUS_SUCCESS;
  341. break;
  342. }
  343. if(commonExtension->IsInitialized == FALSE) {
  344. status = ScsiPortInitLogicalUnit(logicalUnitExtension);
  345. }
  346. if(NT_SUCCESS(status)) {
  347. commonExtension->IsInitialized = TRUE;
  348. status = ScsiPortStartLogicalUnit(logicalUnitExtension);
  349. }
  350. if(NT_SUCCESS(status)) {
  351. commonExtension->CurrentPnpState = IRP_MN_START_DEVICE;
  352. commonExtension->PreviousPnpState = 0xff;
  353. }
  354. Irp->IoStatus.Status = status;
  355. break;
  356. }
  357. case IRP_MN_QUERY_ID: {
  358. UCHAR rawIdString[64] = "UNKNOWN ID TYPE";
  359. ANSI_STRING ansiIdString;
  360. UNICODE_STRING unicodeIdString;
  361. BOOLEAN multiStrings;
  362. PINQUIRYDATA inquiryData = &(logicalUnitExtension->InquiryData);
  363. //
  364. // We've been asked for the id of one of the physical device objects
  365. //
  366. DebugPrint((2, "ScsiPortPnp: got IRP_MN_QUERY_ID\n"));
  367. RtlInitUnicodeString(&unicodeIdString, NULL);
  368. RtlInitAnsiString(&ansiIdString, NULL);
  369. switch(irpStack->Parameters.QueryId.IdType) {
  370. case BusQueryDeviceID: {
  371. status = ScsiPortGetDeviceId(LogicalUnit, &unicodeIdString);
  372. multiStrings = FALSE;
  373. break;
  374. }
  375. case BusQueryInstanceID: {
  376. status = ScsiPortGetInstanceId(LogicalUnit, &unicodeIdString);
  377. multiStrings = FALSE;
  378. break;
  379. }
  380. case BusQueryHardwareIDs: {
  381. status = ScsiPortGetHardwareIds(
  382. LogicalUnit->DriverObject,
  383. &(logicalUnitExtension->InquiryData),
  384. &unicodeIdString);
  385. multiStrings = TRUE;
  386. break;
  387. }
  388. case BusQueryCompatibleIDs: {
  389. status = ScsiPortGetCompatibleIds(
  390. LogicalUnit->DriverObject,
  391. &(logicalUnitExtension->InquiryData),
  392. &unicodeIdString);
  393. multiStrings = TRUE;
  394. break;
  395. }
  396. default: {
  397. status = Irp->IoStatus.Status;
  398. Irp->IoStatus.Information = 0;
  399. multiStrings = FALSE;
  400. break;
  401. }
  402. }
  403. Irp->IoStatus.Status = status;
  404. if(NT_SUCCESS(status)) {
  405. PWCHAR idString;
  406. //
  407. // fix up all invalid characters
  408. //
  409. idString = unicodeIdString.Buffer;
  410. while (*idString) {
  411. if ((*idString <= L' ') ||
  412. (*idString > (WCHAR)0x7F) ||
  413. (*idString == L',')) {
  414. *idString = L'_';
  415. }
  416. idString++;
  417. if ((*idString == L'\0') && multiStrings) {
  418. idString++;
  419. }
  420. }
  421. Irp->IoStatus.Information = (ULONG_PTR) unicodeIdString.Buffer;
  422. } else {
  423. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  424. }
  425. SpReleaseRemoveLock(LogicalUnit, Irp);
  426. SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
  427. return status;
  428. break;
  429. }
  430. case IRP_MN_QUERY_RESOURCES:
  431. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: {
  432. Irp->IoStatus.Status = STATUS_SUCCESS;
  433. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  434. SpReleaseRemoveLock(LogicalUnit, Irp);
  435. SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
  436. return STATUS_SUCCESS;
  437. }
  438. case IRP_MN_SURPRISE_REMOVAL:
  439. case IRP_MN_REMOVE_DEVICE: {
  440. BOOLEAN destroyed;
  441. //
  442. // Release the lock for this IRP before going in.
  443. //
  444. if(commonExtension->IsRemoved == NO_REMOVE) {
  445. commonExtension->IsRemoved = REMOVE_PENDING;
  446. }
  447. SpReleaseRemoveLock(LogicalUnit, Irp);
  448. destroyed = SpRemoveLogicalUnit(logicalUnitExtension,
  449. irpStack->MinorFunction);
  450. if(destroyed) {
  451. commonExtension->PreviousPnpState =
  452. commonExtension->CurrentPnpState;
  453. commonExtension->CurrentPnpState = irpStack->MinorFunction;
  454. } else {
  455. commonExtension->CurrentPnpState = 0xff;
  456. commonExtension->PreviousPnpState = irpStack->MinorFunction;
  457. }
  458. status = STATUS_SUCCESS;
  459. Irp->IoStatus.Status = status;
  460. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  461. return status;
  462. }
  463. case IRP_MN_QUERY_DEVICE_TEXT: {
  464. Irp->IoStatus.Status =
  465. SpQueryDeviceText(
  466. LogicalUnit,
  467. irpStack->Parameters.QueryDeviceText.DeviceTextType,
  468. irpStack->Parameters.QueryDeviceText.LocaleId,
  469. (PWSTR *) &Irp->IoStatus.Information
  470. );
  471. break;
  472. }
  473. case IRP_MN_QUERY_CAPABILITIES: {
  474. PDEVICE_CAPABILITIES capabilities =
  475. irpStack->Parameters.DeviceCapabilities.Capabilities;
  476. PSCSIPORT_DEVICE_TYPE deviceType = NULL;
  477. capabilities->RawDeviceOK = 1;
  478. deviceType = SpGetDeviceTypeInfo(
  479. logicalUnitExtension->InquiryData.DeviceType
  480. );
  481. if((deviceType != NULL) && (deviceType->IsStorage)) {
  482. capabilities->SilentInstall = 1;
  483. }
  484. capabilities->Address = logicalUnitExtension->TargetId;
  485. Irp->IoStatus.Status = STATUS_SUCCESS;
  486. break;
  487. }
  488. case IRP_MN_QUERY_STOP_DEVICE:
  489. case IRP_MN_QUERY_REMOVE_DEVICE: {
  490. if ((commonExtension->PagingPathCount != 0) ||
  491. (logicalUnitExtension->IsLegacyClaim == TRUE)) {
  492. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  493. } else {
  494. Irp->IoStatus.Status = STATUS_SUCCESS;
  495. commonExtension->PreviousPnpState =
  496. commonExtension->CurrentPnpState;
  497. commonExtension->CurrentPnpState = irpStack->MinorFunction;
  498. }
  499. break;
  500. }
  501. case IRP_MN_CANCEL_STOP_DEVICE: {
  502. if(commonExtension->CurrentPnpState == IRP_MN_QUERY_STOP_DEVICE) {
  503. commonExtension->CurrentPnpState =
  504. commonExtension->PreviousPnpState;
  505. commonExtension->PreviousPnpState = 0xff;
  506. }
  507. Irp->IoStatus.Status = STATUS_SUCCESS;
  508. break;
  509. }
  510. case IRP_MN_CANCEL_REMOVE_DEVICE: {
  511. if(commonExtension->CurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE) {
  512. commonExtension->CurrentPnpState =
  513. commonExtension->PreviousPnpState;
  514. commonExtension->PreviousPnpState = 0xff;
  515. }
  516. Irp->IoStatus.Status = STATUS_SUCCESS;
  517. break;
  518. }
  519. case IRP_MN_STOP_DEVICE: {
  520. ASSERT(commonExtension->CurrentPnpState == IRP_MN_QUERY_STOP_DEVICE);
  521. status = ScsiPortStopLogicalUnit(logicalUnitExtension);
  522. ASSERT(NT_SUCCESS(status));
  523. Irp->IoStatus.Status = status;
  524. Irp->IoStatus.Information = (ULONG_PTR) NULL;
  525. if(NT_SUCCESS(status)) {
  526. commonExtension->CurrentPnpState = IRP_MN_STOP_DEVICE;
  527. commonExtension->PreviousPnpState = 0xff;
  528. }
  529. SpReleaseRemoveLock(LogicalUnit, Irp);
  530. SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
  531. return status;
  532. }
  533. case IRP_MN_QUERY_DEVICE_RELATIONS: {
  534. PDEVICE_RELATIONS deviceRelations;
  535. if(irpStack->Parameters.QueryDeviceRelations.Type !=
  536. TargetDeviceRelation) {
  537. break;
  538. }
  539. //
  540. // DEVICE_RELATIONS definition contains one object pointer.
  541. //
  542. deviceRelations = SpAllocatePool(PagedPool,
  543. sizeof(DEVICE_RELATIONS),
  544. SCSIPORT_TAG_DEVICE_RELATIONS,
  545. LogicalUnit->DriverObject);
  546. if(deviceRelations == NULL) {
  547. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  548. break;
  549. }
  550. RtlZeroMemory(deviceRelations, sizeof(DEVICE_RELATIONS));
  551. deviceRelations->Count = 1;
  552. deviceRelations->Objects[0] = LogicalUnit;
  553. ObReferenceObject(deviceRelations->Objects[0]);
  554. Irp->IoStatus.Status = STATUS_SUCCESS;
  555. Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
  556. break;
  557. }
  558. case IRP_MN_DEVICE_USAGE_NOTIFICATION: {
  559. PIRP newIrp;
  560. PIO_STACK_LOCATION nextStack;
  561. DebugPrint((1, "Pdo - IRP_MN_DEVICE_USAGE_NOTIFICATION %#p received for "
  562. "logical unit %#p\n",
  563. Irp,
  564. LogicalUnit));
  565. newIrp = SpAllocateIrp(
  566. commonExtension->LowerDeviceObject->StackSize,
  567. FALSE,
  568. LogicalUnit->DriverObject);
  569. if(newIrp == NULL) {
  570. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  571. break;
  572. }
  573. newIrp->AssociatedIrp.MasterIrp = Irp;
  574. newIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  575. nextStack = IoGetNextIrpStackLocation(newIrp);
  576. *nextStack = *IoGetCurrentIrpStackLocation(Irp);
  577. IoSetCompletionRoutine(newIrp,
  578. SpPagingPathNotificationCompletion,
  579. commonExtension->LowerDeviceObject,
  580. TRUE,
  581. TRUE,
  582. TRUE);
  583. status = IoCallDriver(commonExtension->LowerDeviceObject,
  584. newIrp);
  585. return status;
  586. break;
  587. }
  588. }
  589. SpReleaseRemoveLock(LogicalUnit, Irp);
  590. status = Irp->IoStatus.Status;
  591. SpCompleteRequest(LogicalUnit, Irp, NULL, IO_NO_INCREMENT);
  592. return status;
  593. }
  594. NTSTATUS
  595. SpPagingPathNotificationCompletion(
  596. IN PDEVICE_OBJECT DeviceObject,
  597. IN PIRP LowerIrp,
  598. IN PDEVICE_OBJECT Fdo
  599. )
  600. {
  601. PIRP upperIrp = LowerIrp->AssociatedIrp.MasterIrp;
  602. PIO_STACK_LOCATION lowerStack = IoGetCurrentIrpStackLocation(LowerIrp);
  603. PIO_STACK_LOCATION upperStack = IoGetCurrentIrpStackLocation(upperIrp);
  604. PDEVICE_OBJECT pdo = upperStack->DeviceObject;
  605. PADAPTER_EXTENSION lowerExtension;
  606. PLOGICAL_UNIT_EXTENSION upperExtension;
  607. ASSERT(Fdo != NULL);
  608. ASSERT(pdo != NULL);
  609. DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: Completion of "
  610. "paging notification irp %#p sent due to irp %#p\n",
  611. LowerIrp, upperIrp));
  612. lowerExtension = (PADAPTER_EXTENSION) Fdo->DeviceExtension;
  613. upperExtension = (PLOGICAL_UNIT_EXTENSION) pdo->DeviceExtension;
  614. ASSERT_FDO(lowerExtension->DeviceObject);
  615. ASSERT_PDO(upperExtension->DeviceObject);
  616. DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: irp status %#08lx\n",
  617. LowerIrp->IoStatus.Status));
  618. if(NT_SUCCESS(LowerIrp->IoStatus.Status)) {
  619. PUCHAR typeName = "INSERT TYPE HERE";
  620. PULONG lowerCount;
  621. PULONG upperCount;
  622. //
  623. // The parameters have already been erased from the lower irp stack
  624. // location - use the parameters from the upper once since they're
  625. // just a copy.
  626. //
  627. switch(upperStack->Parameters.UsageNotification.Type) {
  628. case DeviceUsageTypePaging: {
  629. lowerCount = &(lowerExtension->CommonExtension.PagingPathCount);
  630. upperCount = &(upperExtension->CommonExtension.PagingPathCount);
  631. typeName = "PagingPathCount";
  632. break;
  633. }
  634. case DeviceUsageTypeHibernation: {
  635. lowerCount = &(lowerExtension->CommonExtension.HibernatePathCount);
  636. upperCount = &(upperExtension->CommonExtension.HibernatePathCount);
  637. typeName = "HibernatePathCount";
  638. break;
  639. }
  640. case DeviceUsageTypeDumpFile: {
  641. lowerCount = &(lowerExtension->CommonExtension.DumpPathCount);
  642. upperCount = &(upperExtension->CommonExtension.DumpPathCount);
  643. typeName = "DumpPathCount";
  644. break;
  645. }
  646. default: {
  647. typeName = "unknown type";
  648. lowerCount = upperCount = NULL;
  649. break;
  650. }
  651. }
  652. if(lowerCount != NULL) {
  653. IoAdjustPagingPathCount(
  654. lowerCount,
  655. upperStack->Parameters.UsageNotification.InPath
  656. );
  657. DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: "
  658. "Fdo %s count - %d\n",
  659. typeName, *lowerCount));
  660. IoInvalidateDeviceState(lowerExtension->LowerPdo);
  661. }
  662. if(upperCount != NULL) {
  663. IoAdjustPagingPathCount(
  664. upperCount,
  665. upperStack->Parameters.UsageNotification.InPath
  666. );
  667. DebugPrint((1, "Completion - IRP_MN_DEVICE_USAGE_NOTIFICATION: "
  668. "Pdo %s count - %d\n",
  669. typeName, *upperCount));
  670. IoInvalidateDeviceState(upperExtension->DeviceObject);
  671. }
  672. }
  673. upperIrp->IoStatus = LowerIrp->IoStatus;
  674. SpReleaseRemoveLock(upperExtension->CommonExtension.DeviceObject, upperIrp);
  675. SpCompleteRequest(upperExtension->CommonExtension.DeviceObject,
  676. upperIrp,
  677. NULL,
  678. IO_NO_INCREMENT);
  679. IoFreeIrp(LowerIrp);
  680. return STATUS_MORE_PROCESSING_REQUIRED;
  681. }
  682. NTSTATUS
  683. ScsiPortPdoCreateClose(
  684. IN PDEVICE_OBJECT Pdo,
  685. IN PIRP Irp
  686. )
  687. /*++
  688. Routine Description:
  689. This routine handles creates and closes for bus device pdo's
  690. Arguments:
  691. Pdo - a pointer to the physical device object
  692. Irp - a pointer to the io request packet
  693. Return Value:
  694. status
  695. --*/
  696. {
  697. PLOGICAL_UNIT_EXTENSION logicalUnit = Pdo->DeviceExtension;
  698. ULONG isRemoved;
  699. NTSTATUS status = STATUS_SUCCESS;
  700. PAGED_CODE();
  701. ASSERT_PDO(Pdo);
  702. isRemoved = SpAcquireRemoveLock(Pdo, Irp);
  703. if(IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_CREATE) {
  704. if(isRemoved) {
  705. status = STATUS_DEVICE_DOES_NOT_EXIST;
  706. } else if(logicalUnit->IsTemporary == TRUE) {
  707. status = STATUS_DEVICE_NOT_READY;
  708. }
  709. }
  710. Irp->IoStatus.Status = status;
  711. SpReleaseRemoveLock(Pdo, Irp);
  712. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  713. return status;
  714. }
  715. NTSTATUS
  716. ScsiPortScsi1PdoScsi(
  717. IN PDEVICE_OBJECT Pdo,
  718. IN PIRP Irp
  719. )
  720. /*++
  721. Routine Description:
  722. This routine is a wrapper around ScsiPortPdoScsi. It inserts the LUN number
  723. into the CDB before calling the generic version. this is for use with
  724. older target controllers which don't pay attention to the identify message
  725. sent before the command phase.
  726. Arguments:
  727. Pdo - a pointer to the physical device object
  728. Irp - a pointer to the io request packet
  729. Return Value:
  730. status
  731. --*/
  732. {
  733. PLOGICAL_UNIT_EXTENSION lun = Pdo->DeviceExtension;
  734. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  735. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  736. //
  737. // NOTICE: The SCSI-II specification indicates that this field should be
  738. // zero; however, some target controllers ignore the logical unit number
  739. // in the INDENTIFY message and only look at the logical unit number field
  740. // in the CDB.
  741. //
  742. srb->Cdb[1] |= lun->Lun << 5;
  743. return ScsiPortPdoScsi(Pdo, Irp);
  744. }
  745. NTSTATUS
  746. ScsiPortPdoScsi(
  747. IN PDEVICE_OBJECT Pdo,
  748. IN PIRP Irp
  749. )
  750. /*++
  751. Routine Description:
  752. This routine dispatches SRB's for a particular target device. It will fill
  753. in the Port, Path, Target and Lun values and then forward the request
  754. through to the FDO for the bus
  755. Arguments:
  756. Pdo - a pointer to the physical device object
  757. Irp - a pointer to the io request packet
  758. Return Value:
  759. status
  760. --*/
  761. {
  762. PLOGICAL_UNIT_EXTENSION lun = Pdo->DeviceExtension;
  763. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  764. #if DBG
  765. PDRIVER_OBJECT lowerDriverObject =
  766. lun->CommonExtension.LowerDeviceObject->DriverObject;
  767. #endif
  768. PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;
  769. ULONG isRemoved;
  770. PSRB_DATA srbData;
  771. BOOLEAN isLock = FALSE;
  772. NTSTATUS status;
  773. isRemoved = SpAcquireRemoveLock(Pdo, Irp);
  774. if(isRemoved &&
  775. !IS_CLEANUP_REQUEST(irpStack) &&
  776. (srb->Function != SRB_FUNCTION_CLAIM_DEVICE)) {
  777. Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
  778. SpReleaseRemoveLock(Pdo, Irp);
  779. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  780. return STATUS_DEVICE_DOES_NOT_EXIST;
  781. }
  782. srb->PathId = lun->PathId;
  783. srb->TargetId = lun->TargetId;
  784. srb->Lun = lun->Lun;
  785. //
  786. // Queue tags should be assigned only by the StartIo routine. Set it to
  787. // a benign value here so we can tell later on that we don't have to
  788. // clear the tag value in the bitmap.
  789. //
  790. srb->QueueTag = SP_UNTAGGED;
  791. #if DBG
  792. ASSERT(lowerDriverObject->MajorFunction[IRP_MJ_SCSI] != NULL);
  793. ASSERT(lowerDriverObject->MajorFunction[IRP_MJ_SCSI] == ScsiPortGlobalDispatch);
  794. #endif
  795. switch(srb->Function) {
  796. case SRB_FUNCTION_ABORT_COMMAND: {
  797. status = STATUS_NOT_SUPPORTED;
  798. break;
  799. }
  800. case SRB_FUNCTION_CLAIM_DEVICE:
  801. case SRB_FUNCTION_RELEASE_DEVICE:
  802. case SRB_FUNCTION_REMOVE_DEVICE: {
  803. status = SpClaimLogicalUnit(
  804. lun->CommonExtension.LowerDeviceObject->DeviceExtension,
  805. lun,
  806. Irp,
  807. FALSE);
  808. break;
  809. }
  810. case SRB_FUNCTION_UNLOCK_QUEUE:
  811. case SRB_FUNCTION_LOCK_QUEUE: {
  812. SpStartLockRequest(lun, Irp);
  813. return STATUS_PENDING;
  814. }
  815. case SRB_FUNCTION_RELEASE_QUEUE:
  816. case SRB_FUNCTION_FLUSH_QUEUE: {
  817. srbData = SpAllocateBypassSrbData(lun);
  818. ASSERT(srbData != NULL);
  819. goto RunSrb;
  820. }
  821. default: {
  822. if(TEST_FLAG(srb->SrbFlags, (SRB_FLAGS_BYPASS_LOCKED_QUEUE |
  823. SRB_FLAGS_BYPASS_FROZEN_QUEUE))) {
  824. srbData = SpAllocateBypassSrbData(lun);
  825. ASSERT(srbData != NULL);
  826. } else {
  827. srbData = SpAllocateSrbData( lun->AdapterExtension, Irp, lun);
  828. if(srbData == NULL) {
  829. //
  830. // There wasn't an SRB_DATA block available for this
  831. // request so it's been queued waiting for resources -
  832. // leave the logical unit remove-locked and return pending.
  833. //
  834. DebugPrint((1, "ScsiPortPdoScsi: Insufficient resources "
  835. "to allocate SRB_DATA structure\n"));
  836. return STATUS_PENDING;
  837. }
  838. }
  839. RunSrb:
  840. srbData->CurrentIrp = Irp;
  841. srbData->CurrentSrb = srb;
  842. srbData->LogicalUnit = lun;
  843. srb->OriginalRequest = srbData;
  844. return SpDispatchRequest(lun, Irp);
  845. }
  846. }
  847. Irp->IoStatus.Status = status;
  848. SpReleaseRemoveLock(Pdo, Irp);
  849. SpCompleteRequest(Pdo, Irp, NULL, IO_NO_INCREMENT);
  850. return status;
  851. }
  852. NTSTATUS
  853. ScsiPortStartLogicalUnit(
  854. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  855. )
  856. /*++
  857. Routine Description:
  858. This routine will attempt to start the specified device object.
  859. Currently this involves clearing the INITIALIZING flag if it was set,
  860. and running through to the device node and marking itself as started. This
  861. last is a kludge
  862. Arguments:
  863. LogicalUnit - a pointer to the PDO being started
  864. Return Value:
  865. status
  866. --*/
  867. {
  868. PADAPTER_EXTENSION adapterExtension = LogicalUnit->AdapterExtension;
  869. HANDLE instanceHandle;
  870. NTSTATUS status;
  871. PAGED_CODE();
  872. //
  873. // Open the devnode for this PDO and see if anyone's given us some
  874. // default SRB flags.
  875. //
  876. status = IoOpenDeviceRegistryKey(LogicalUnit->DeviceObject,
  877. PLUGPLAY_REGKEY_DEVICE,
  878. KEY_READ,
  879. &instanceHandle);
  880. if(NT_SUCCESS(status)) {
  881. RTL_QUERY_REGISTRY_TABLE queryTable[2];
  882. ULONG zero = 0;
  883. RtlZeroMemory(queryTable, sizeof(queryTable));
  884. queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  885. queryTable[0].Name = L"DefaultRequestFlags";
  886. queryTable[0].EntryContext = &(LogicalUnit->CommonExtension.SrbFlags);
  887. queryTable[0].DefaultType = REG_DWORD;
  888. queryTable[0].DefaultData = &zero;
  889. queryTable[0].DefaultLength = sizeof(ULONG);
  890. status = RtlQueryRegistryValues(
  891. RTL_REGISTRY_HANDLE | RTL_REGISTRY_OPTIONAL,
  892. (PWSTR) instanceHandle,
  893. queryTable,
  894. NULL,
  895. NULL);
  896. //
  897. // CODEWORK: need a way to turn off tagged queuing and caching. Ie.
  898. // keep track of negative flags as well.
  899. //
  900. LogicalUnit->CommonExtension.SrbFlags &=
  901. ( SRB_FLAGS_DISABLE_DISCONNECT |
  902. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  903. SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
  904. DebugPrint((1, "SpStartDevice: Default SRB flags for (%d,%d,%d) are "
  905. "%#08lx\n",
  906. LogicalUnit->PathId,
  907. LogicalUnit->TargetId,
  908. LogicalUnit->Lun,
  909. LogicalUnit->CommonExtension.SrbFlags));
  910. ZwClose(instanceHandle);
  911. } else {
  912. DebugPrint((1, "SpStartDevice: Error opening instance key for pdo "
  913. "[%#08lx]\n",
  914. status));
  915. }
  916. //
  917. // If the queue is locked then unlock it to start i/o processing.
  918. //
  919. if(LogicalUnit->QueueLockCount > 0) {
  920. status = SpLockUnlockQueue(LogicalUnit->DeviceObject,
  921. FALSE,
  922. TRUE);
  923. }
  924. return status;
  925. }
  926. VOID
  927. ScsiPortInitPdoWmi(
  928. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  929. )
  930. /*++
  931. Routine Description:
  932. This routine will attempt WMI initialization for the PDO.
  933. Arguments:
  934. DeviceObject - a pointer to the PDO being started
  935. Return Value:
  936. status
  937. --*/
  938. {
  939. PCOMMON_EXTENSION commonExtension = &(LogicalUnit->CommonExtension);
  940. PADAPTER_EXTENSION adapterExtension = LogicalUnit->AdapterExtension;
  941. PAGED_CODE();
  942. //
  943. // Now that we have a LUN, we can initialize WMI support for the adapter if
  944. // the miniport supports WMI. This may be a re-register if we've already
  945. // registered on behalf of scsiport itself. We have to wait until we have
  946. // a LUN when the miniport supports WMI because we send it an SRB to do
  947. // its own initialization. We can't send it an SRB until we have a logical
  948. // unit.
  949. //
  950. if (adapterExtension->CommonExtension.WmiMiniPortInitialized == FALSE &&
  951. adapterExtension->CommonExtension.WmiMiniPortSupport == TRUE) {
  952. ULONG action;
  953. //
  954. // Decide whether we are registering or reregistering WMI for the FDO.
  955. //
  956. action = (adapterExtension->CommonExtension.WmiInitialized == FALSE) ?
  957. WMIREG_ACTION_REGISTER : WMIREG_ACTION_REREGISTER;
  958. //
  959. // Register/reregister. We can get WMI irps as soon as we do this.
  960. //
  961. IoWMIRegistrationControl(adapterExtension->DeviceObject, action);
  962. adapterExtension->CommonExtension.WmiMiniPortInitialized = TRUE;
  963. adapterExtension->CommonExtension.WmiInitialized = TRUE;
  964. }
  965. //
  966. // Initialize WMI support.
  967. //
  968. if (commonExtension->WmiInitialized == FALSE) {
  969. //
  970. // Build the SCSIPORT WMI registration information buffer for this PDO.
  971. //
  972. SpWmiInitializeSpRegInfo(LogicalUnit->DeviceObject);
  973. //
  974. // Register this device object only if the miniport supports WMI and/or
  975. // SCSIPORT will support certain WMI GUIDs on behalf of the miniport.
  976. //
  977. if (commonExtension->WmiMiniPortSupport ||
  978. commonExtension->WmiScsiPortRegInfoBuf) {
  979. //
  980. // Register this physical device object as a WMI data provider,
  981. // instructing WMI that it is ready to receive WMI IRPs.
  982. //
  983. IoWMIRegistrationControl(LogicalUnit->DeviceObject,
  984. WMIREG_ACTION_REGISTER);
  985. commonExtension->WmiInitialized = TRUE;
  986. }
  987. //
  988. // Allocate several WMI_MINIPORT_REQUEST_ITEM blocks to satisfy a
  989. // potential onslaught of WMIEvent notifications by the miniport.
  990. //
  991. if (commonExtension->WmiMiniPortSupport) {
  992. //
  993. // Currently we only allocate two per new SCSI target (PDO).
  994. //
  995. SpWmiInitializeFreeRequestList(LogicalUnit->DeviceObject, 2);
  996. }
  997. }
  998. return;
  999. }
  1000. NTSTATUS
  1001. ScsiPortInitLogicalUnit(
  1002. IN PLOGICAL_UNIT_EXTENSION LogicalUnit
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. This routine will attempt to start the specified device object.
  1007. Arguments:
  1008. DeviceObject - a pointer to the PDO being started
  1009. Return Value:
  1010. status
  1011. --*/
  1012. {
  1013. PCOMMON_EXTENSION commonExtension = &(LogicalUnit->CommonExtension);
  1014. PADAPTER_EXTENSION adapterExtension = LogicalUnit->AdapterExtension;
  1015. HANDLE instanceHandle;
  1016. NTSTATUS status = STATUS_SUCCESS;
  1017. PAGED_CODE();
  1018. //
  1019. // Initialize the idle detection timer. Tell the system to put us into a
  1020. // D3 state when we're not being used.
  1021. //
  1022. LogicalUnit->CommonExtension.IdleTimer =
  1023. PoRegisterDeviceForIdleDetection(LogicalUnit->DeviceObject,
  1024. SpPowerIdleTimeout,
  1025. SpPowerIdleTimeout,
  1026. PowerDeviceD3);
  1027. ScsiPortInitPdoWmi(LogicalUnit);
  1028. //
  1029. // Build a device map entry for this logical unit.
  1030. //
  1031. SpBuildDeviceMapEntry(commonExtension);
  1032. return status;
  1033. }
  1034. VOID
  1035. SpStartLockRequest(
  1036. IN PLOGICAL_UNIT_EXTENSION LogicalUnit,
  1037. IN PIRP Irp OPTIONAL
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This routine is responsible for queueing, starting or restarting a lock
  1042. request.
  1043. If Irp is provided then it will dispatched iff no existing lock or unlock
  1044. request is already running. If one is already running this request will
  1045. be queued.
  1046. If Irp is not provided then the next request on the LockRequestQueue will
  1047. be removed and dispatched.
  1048. This routine relies on the device queue to provide synchronization. Since
  1049. we can only have one request get past the device queue at any given time we
  1050. should only have one call at any given time with Irp set to NULL.
  1051. Arguments:
  1052. LogicalUnit - the logical unit to which this lock request was sent.
  1053. Irp - the irp for the lock request.
  1054. Return Value:
  1055. none
  1056. --*/
  1057. {
  1058. KIRQL oldIrql;
  1059. PIO_STACK_LOCATION irpStack;
  1060. PSCSI_REQUEST_BLOCK srb;
  1061. PSRB_DATA srbData;
  1062. BOOLEAN lock;
  1063. oldIrql = KeRaiseIrqlToDpcLevel();
  1064. //
  1065. // If no IRP was provided then get one out of the device queue.
  1066. // Otherwise make sure the device queue is not busy.
  1067. //
  1068. if(Irp == NULL) {
  1069. PKDEVICE_QUEUE_ENTRY entry;
  1070. ASSERT(LogicalUnit->CurrentLockRequest != NULL);
  1071. LogicalUnit->CurrentLockRequest = NULL;
  1072. entry = KeRemoveDeviceQueue(&(LogicalUnit->LockRequestQueue));
  1073. if(entry == NULL) {
  1074. //
  1075. // No more requests have come in while processing this one -
  1076. // we can just return.
  1077. //
  1078. KeLowerIrql(oldIrql);
  1079. return;
  1080. } else {
  1081. Irp = CONTAINING_RECORD(entry,
  1082. IRP,
  1083. Tail.Overlay.DeviceQueueEntry);
  1084. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1085. srb = irpStack->Parameters.Scsi.Srb;
  1086. lock = (srb->Function == SRB_FUNCTION_LOCK_QUEUE);
  1087. }
  1088. } else {
  1089. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1090. srb = irpStack->Parameters.Scsi.Srb;
  1091. lock = (srb->Function == SRB_FUNCTION_LOCK_QUEUE);
  1092. DebugPrint((2, "SpStartLockRequest: called to %s queue %#p\n",
  1093. lock ? "lock" : "unlock",
  1094. LogicalUnit));
  1095. //
  1096. // See if we can let this request keep processing or if we'll
  1097. // have to queue it.
  1098. //
  1099. IoMarkIrpPending(Irp);
  1100. if(KeInsertDeviceQueue(&(LogicalUnit->LockRequestQueue),
  1101. &(Irp->Tail.Overlay.DeviceQueueEntry))) {
  1102. KeLowerIrql(oldIrql);
  1103. return;
  1104. }
  1105. }
  1106. ASSERT(Irp != NULL);
  1107. ASSERT(LogicalUnit->CurrentLockRequest == NULL);
  1108. //
  1109. // This srb function is only valid as part of a power up request
  1110. // and will be ignored if the power state is D0.
  1111. //
  1112. CLEAR_FLAG(srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
  1113. SET_FLAG(srb->SrbFlags, SRB_FLAGS_BYPASS_LOCKED_QUEUE);
  1114. //
  1115. // Throw this request down so it gets processed as a real
  1116. // request. We need to get the completion dpc to start
  1117. // things running again. there are too many flags to set
  1118. // to do it from here.
  1119. //
  1120. DebugPrint((2, "SpStartLockRequest: %s %#p into "
  1121. "queue %#p ... issuing request\n",
  1122. lock ? "lock" : "unlock", srb, LogicalUnit));
  1123. //
  1124. // There are four bypass srb data blocks available - we should have at most
  1125. // one lock request awaiting completion and the one we're about to start
  1126. // so this call should never, ever fail.
  1127. //
  1128. srbData = SpAllocateBypassSrbData(LogicalUnit);
  1129. ASSERT(srbData != NULL);
  1130. //
  1131. // Set the current lock request. As long as this is cleared
  1132. // before the next item is removed from the queue everything
  1133. // will be happy.
  1134. //
  1135. ASSERT(LogicalUnit->CurrentLockRequest == NULL);
  1136. LogicalUnit->CurrentLockRequest = srbData;
  1137. srbData->CurrentIrp = Irp;
  1138. srbData->CurrentSrb = srb;
  1139. srbData->LogicalUnit = LogicalUnit;
  1140. srb->OriginalRequest = srbData;
  1141. SpDispatchRequest(LogicalUnit, Irp);
  1142. KeLowerIrql(oldIrql);
  1143. return;
  1144. }