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.

1059 lines
27 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. obsolete.c
  5. Abstract:
  6. THESE ARE EXPORTED CLASSPNP FUNCTIONS (and their subroutines)
  7. WHICH ARE NOW OBSOLETE.
  8. BUT WE NEED TO KEEP THEM AROUND FOR LEGACY REASONS.
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "classp.h"
  15. #include "debug.h"
  16. PIRP ClassRemoveCScanList(IN PCSCAN_LIST List);
  17. VOID ClasspInitializeCScanList(IN PCSCAN_LIST List);
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, ClassDeleteSrbLookasideList)
  20. #pragma alloc_text(PAGE, ClassInitializeSrbLookasideList)
  21. #endif
  22. typedef struct _CSCAN_LIST_ENTRY {
  23. LIST_ENTRY Entry;
  24. ULONGLONG BlockNumber;
  25. } CSCAN_LIST_ENTRY, *PCSCAN_LIST_ENTRY;
  26. /*
  27. * ClassSplitRequest
  28. *
  29. * This is a legacy exported function.
  30. * It is called by storage miniport driver that have their own
  31. * StartIo routine when the transfer size is too large for the hardware.
  32. * We map it to our new read/write handler.
  33. */
  34. VOID ClassSplitRequest(IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN ULONG MaximumBytes)
  35. {
  36. PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
  37. PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
  38. if (MaximumBytes > fdoData->HwMaxXferLen) {
  39. DBGERR(("ClassSplitRequest - driver requesting split to size that "
  40. "hardware is unable to handle!\n"));
  41. }
  42. if (MaximumBytes < fdoData->HwMaxXferLen){
  43. DBGWARN(("ClassSplitRequest - driver requesting smaller HwMaxXferLen "
  44. "than required"));
  45. fdoData->HwMaxXferLen = MAX(MaximumBytes, PAGE_SIZE);
  46. }
  47. ServiceTransferRequest(Fdo, Irp);
  48. }
  49. /*++////////////////////////////////////////////////////////////////////////////
  50. ClassIoCompleteAssociated()
  51. Routine Description:
  52. This routine executes when the port driver has completed a request.
  53. It looks at the SRB status in the completing SRB and if not success
  54. it checks for valid request sense buffer information. If valid, the
  55. info is used to update status with more precise message of type of
  56. error. This routine deallocates the SRB. This routine is used for
  57. requests which were build by split request. After it has processed
  58. the request it decrements the Irp count in the master Irp. If the
  59. count goes to zero then the master Irp is completed.
  60. Arguments:
  61. Fdo - Supplies the functional device object which represents the target.
  62. Irp - Supplies the Irp which has completed.
  63. Context - Supplies a pointer to the SRB.
  64. Return Value:
  65. NT status
  66. --*/
  67. NTSTATUS
  68. ClassIoCompleteAssociated(
  69. IN PDEVICE_OBJECT Fdo,
  70. IN PIRP Irp,
  71. IN PVOID Context
  72. )
  73. {
  74. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
  75. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  76. PSCSI_REQUEST_BLOCK srb = Context;
  77. PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
  78. LONG irpCount;
  79. NTSTATUS status;
  80. BOOLEAN retry;
  81. DBGWARN(("ClassIoCompleteAssociated is OBSOLETE !"));
  82. //
  83. // Check SRB status for success of completing request.
  84. //
  85. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
  86. ULONG retryInterval;
  87. DebugPrint((2,"ClassIoCompleteAssociated: IRP %p, SRB %p", Irp, srb));
  88. //
  89. // Release the queue if it is frozen.
  90. //
  91. if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
  92. ClassReleaseQueue(Fdo);
  93. }
  94. retry = ClassInterpretSenseInfo(
  95. Fdo,
  96. srb,
  97. irpStack->MajorFunction,
  98. irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ?
  99. irpStack->Parameters.DeviceIoControl.IoControlCode :
  100. 0,
  101. MAXIMUM_RETRIES -
  102. ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4),
  103. &status,
  104. &retryInterval);
  105. //
  106. // If the status is verified required and the this request
  107. // should bypass verify required then retry the request.
  108. //
  109. if (irpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME &&
  110. status == STATUS_VERIFY_REQUIRED) {
  111. status = STATUS_IO_DEVICE_ERROR;
  112. retry = TRUE;
  113. }
  114. if (retry && ((ULONG)(ULONG_PTR)irpStack->Parameters.Others.Argument4)--) {
  115. //
  116. // Retry request. If the class driver has supplied a StartIo,
  117. // call it directly for retries.
  118. //
  119. DebugPrint((1, "Retry request %p\n", Irp));
  120. if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
  121. FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
  122. }
  123. RetryRequest(Fdo, Irp, srb, TRUE, retryInterval);
  124. return STATUS_MORE_PROCESSING_REQUIRED;
  125. }
  126. } else {
  127. //
  128. // Set status for successful request.
  129. //
  130. status = STATUS_SUCCESS;
  131. } // end if (SRB_STATUS(srb->SrbStatus) ...
  132. //
  133. // Return SRB to list.
  134. //
  135. if (PORT_ALLOCATED_SENSE(fdoExtension, srb)) {
  136. FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExtension, srb);
  137. }
  138. ClassFreeOrReuseSrb(fdoExtension, srb);
  139. //
  140. // Set status in completing IRP.
  141. //
  142. Irp->IoStatus.Status = status;
  143. DebugPrint((2, "ClassIoCompleteAssociated: Partial xfer IRP %p\n", Irp));
  144. //
  145. // Get next stack location. This original request is unused
  146. // except to keep track of the completing partial IRPs so the
  147. // stack location is valid.
  148. //
  149. irpStack = IoGetNextIrpStackLocation(originalIrp);
  150. //
  151. // Update status only if error so that if any partial transfer
  152. // completes with error, then the original IRP will return with
  153. // error. If any of the asynchronous partial transfer IRPs fail,
  154. // with an error then the original IRP will return 0 bytes transfered.
  155. // This is an optimization for successful transfers.
  156. //
  157. if (!NT_SUCCESS(status)) {
  158. originalIrp->IoStatus.Status = status;
  159. originalIrp->IoStatus.Information = 0;
  160. //
  161. // Set the hard error if necessary.
  162. //
  163. if (IoIsErrorUserInduced(status)) {
  164. //
  165. // Store DeviceObject for filesystem.
  166. //
  167. IoSetHardErrorOrVerifyDevice(originalIrp, Fdo);
  168. }
  169. }
  170. //
  171. // Decrement and get the count of remaining IRPs.
  172. //
  173. irpCount = InterlockedDecrement(
  174. (PLONG)&irpStack->Parameters.Others.Argument1);
  175. DebugPrint((2, "ClassIoCompleteAssociated: Partial IRPs left %d\n",
  176. irpCount));
  177. //
  178. // Ensure that the irpCount doesn't go negative. This was happening once
  179. // because classpnp would get confused if it ran out of resources when
  180. // splitting the request.
  181. //
  182. ASSERT(irpCount >= 0);
  183. if (irpCount == 0) {
  184. //
  185. // All partial IRPs have completed.
  186. //
  187. DebugPrint((2,
  188. "ClassIoCompleteAssociated: All partial IRPs complete %p\n",
  189. originalIrp));
  190. if (fdoExtension->CommonExtension.DriverExtension->InitData.ClassStartIo) {
  191. //
  192. // Acquire a separate copy of the remove lock so the debugging code
  193. // works okay and we don't have to hold up the completion of this
  194. // irp until after we start the next packet(s).
  195. //
  196. KIRQL oldIrql;
  197. UCHAR uniqueAddress;
  198. ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddress);
  199. ClassReleaseRemoveLock(Fdo, originalIrp);
  200. ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
  201. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  202. IoStartNextPacket(Fdo, FALSE);
  203. KeLowerIrql(oldIrql);
  204. ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddress);
  205. } else {
  206. //
  207. // just complete this request
  208. //
  209. ClassReleaseRemoveLock(Fdo, originalIrp);
  210. ClassCompleteRequest(Fdo, originalIrp, IO_DISK_INCREMENT);
  211. }
  212. }
  213. //
  214. // Deallocate IRP and indicate the I/O system should not attempt any more
  215. // processing.
  216. //
  217. IoFreeIrp(Irp);
  218. return STATUS_MORE_PROCESSING_REQUIRED;
  219. } // end ClassIoCompleteAssociated()
  220. /*++////////////////////////////////////////////////////////////////////////////
  221. RetryRequest()
  222. Routine Description:
  223. This is a wrapper around the delayed retry DPC routine, RetryRequestDPC.
  224. This reinitalizes the necessary fields, queues the request, and sets
  225. a timer to call the DPC if someone hasn't already done so.
  226. Arguments:
  227. DeviceObject - Supplies the device object associated with this request.
  228. Irp - Supplies the request to be retried.
  229. Srb - Supplies a Pointer to the SCSI request block to be retied.
  230. Assocaiated - Indicates this is an assocatied Irp created by split request.
  231. RetryInterval - How long, in seconds, before retrying the request.
  232. Return Value:
  233. None
  234. --*/
  235. VOID
  236. RetryRequest(
  237. PDEVICE_OBJECT DeviceObject,
  238. PIRP Irp,
  239. PSCSI_REQUEST_BLOCK Srb,
  240. BOOLEAN Associated,
  241. ULONG RetryInterval
  242. )
  243. {
  244. PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
  245. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  246. PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
  247. ULONG transferByteCount;
  248. // This function is obsolete but is still used by some of our class drivers.
  249. // DBGWARN(("RetryRequest is OBSOLETE !"));
  250. //
  251. // Determine the transfer count of the request. If this is a read or a
  252. // write then the transfer count is in the Irp stack. Otherwise assume
  253. // the MDL contains the correct length. If there is no MDL then the
  254. // transfer length must be zero.
  255. //
  256. if (currentIrpStack->MajorFunction == IRP_MJ_READ ||
  257. currentIrpStack->MajorFunction == IRP_MJ_WRITE) {
  258. transferByteCount = currentIrpStack->Parameters.Read.Length;
  259. } else if (Irp->MdlAddress != NULL) {
  260. //
  261. // Note this assumes that only read and write requests are spilt and
  262. // other request do not need to be. If the data buffer address in
  263. // the MDL and the SRB don't match then transfer length is most
  264. // likely incorrect.
  265. //
  266. ASSERT(Srb->DataBuffer == MmGetMdlVirtualAddress(Irp->MdlAddress));
  267. transferByteCount = Irp->MdlAddress->ByteCount;
  268. } else {
  269. transferByteCount = 0;
  270. }
  271. //
  272. // this is a safety net. this should not normally be hit, since we are
  273. // not guaranteed to be an fdoExtension
  274. //
  275. ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
  276. //
  277. // Reset byte count of transfer in SRB Extension.
  278. //
  279. Srb->DataTransferLength = transferByteCount;
  280. //
  281. // Zero SRB statuses.
  282. //
  283. Srb->SrbStatus = Srb->ScsiStatus = 0;
  284. //
  285. // Set the no disconnect flag, disable synchronous data transfers and
  286. // disable tagged queuing. This fixes some errors.
  287. // NOTE: Cannot clear these flags, just add to them
  288. //
  289. SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
  290. SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
  291. CLEAR_FLAG(Srb->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
  292. Srb->QueueTag = SP_UNTAGGED;
  293. //
  294. // Set up major SCSI function.
  295. //
  296. nextIrpStack->MajorFunction = IRP_MJ_SCSI;
  297. //
  298. // Save SRB address in next stack for port driver.
  299. //
  300. nextIrpStack->Parameters.Scsi.Srb = Srb;
  301. IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);
  302. {
  303. LARGE_INTEGER retry100ns;
  304. retry100ns.QuadPart = RetryInterval; // seconds
  305. retry100ns.QuadPart *= (LONGLONG)1000 * 1000 * 10;
  306. ClassRetryRequest(DeviceObject, Irp, retry100ns);
  307. }
  308. return;
  309. } // end RetryRequest()
  310. /*++
  311. ClassBuildRequest()
  312. Routine Description:
  313. This routine allocates an SRB for the specified request then calls
  314. ClasspBuildRequestEx to create a SCSI operation to read or write the device.
  315. If no SRB is available then the request will be queued to be issued later
  316. when requests are available. Drivers which do not want the queueing
  317. behavior should allocate the SRB themselves and call ClasspBuildRequestEx
  318. to issue it.
  319. Arguments:
  320. Fdo - Supplies the functional device object associated with this request.
  321. Irp - Supplies the request to be retried.
  322. Note:
  323. If the IRP is for a disk transfer, the byteoffset field
  324. will already have been adjusted to make it relative to
  325. the beginning of the disk.
  326. Return Value:
  327. NT Status
  328. --*/
  329. NTSTATUS
  330. ClassBuildRequest(
  331. PDEVICE_OBJECT Fdo,
  332. PIRP Irp
  333. )
  334. {
  335. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
  336. PSCSI_REQUEST_BLOCK srb;
  337. // This function is obsolete, but still called by CDROM.SYS .
  338. // DBGWARN(("ClassBuildRequest is OBSOLETE !"));
  339. //
  340. // Allocate an Srb.
  341. //
  342. srb = ClasspAllocateSrb(fdoExtension);
  343. if(srb == NULL) {
  344. return STATUS_INSUFFICIENT_RESOURCES;
  345. }
  346. ClasspBuildRequestEx(fdoExtension, Irp, srb);
  347. return STATUS_SUCCESS;
  348. } // end ClassBuildRequest()
  349. VOID
  350. ClasspBuildRequestEx(
  351. IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
  352. IN PIRP Irp,
  353. IN PSCSI_REQUEST_BLOCK Srb
  354. )
  355. /*++
  356. ClasspBuildRequestEx()
  357. Routine Description:
  358. This routine allocates and builds an Srb for a read or write request.
  359. The block address and length are supplied by the Irp. The retry count
  360. is stored in the current stack for use by ClassIoComplete which
  361. processes these requests when they complete. The Irp is ready to be
  362. passed to the port driver when this routine returns.
  363. Arguments:
  364. FdoExtension - Supplies the device extension associated with this request.
  365. Irp - Supplies the request to be issued.
  366. Srb - Supplies an SRB to be used for the request.
  367. Note:
  368. If the IRP is for a disk transfer, the byteoffset field
  369. will already have been adjusted to make it relative to
  370. the beginning of the disk.
  371. Return Value:
  372. NT Status
  373. --*/
  374. {
  375. PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
  376. PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
  377. LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
  378. PCDB cdb;
  379. ULONG logicalBlockAddress;
  380. USHORT transferBlocks;
  381. // This function is obsolete, but still called by CDROM.SYS .
  382. // DBGWARN(("ClasspBuildRequestEx is OBSOLETE !"));
  383. //
  384. // Prepare the SRB.
  385. //
  386. RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
  387. //
  388. // Calculate relative sector address.
  389. //
  390. logicalBlockAddress =
  391. (ULONG)(Int64ShrlMod32(startingOffset.QuadPart,
  392. FdoExtension->SectorShift));
  393. //
  394. // Write length to SRB.
  395. //
  396. Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  397. //
  398. // Set up IRP Address.
  399. //
  400. Srb->OriginalRequest = Irp;
  401. //
  402. // Set up target ID and logical unit number.
  403. //
  404. Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  405. Srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
  406. //
  407. // Save byte count of transfer in SRB Extension.
  408. //
  409. Srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
  410. //
  411. // Initialize the queue actions field.
  412. //
  413. Srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
  414. //
  415. // Queue sort key is Relative Block Address.
  416. //
  417. Srb->QueueSortKey = logicalBlockAddress;
  418. //
  419. // Indicate auto request sense by specifying buffer and size.
  420. //
  421. Srb->SenseInfoBuffer = FdoExtension->SenseData;
  422. Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
  423. //
  424. // Set timeout value of one unit per 64k bytes of data.
  425. //
  426. Srb->TimeOutValue = ((Srb->DataTransferLength + 0xFFFF) >> 16) *
  427. FdoExtension->TimeOutValue;
  428. //
  429. // Zero statuses.
  430. //
  431. Srb->SrbStatus = Srb->ScsiStatus = 0;
  432. Srb->NextSrb = 0;
  433. //
  434. // Indicate that 10-byte CDB's will be used.
  435. //
  436. Srb->CdbLength = 10;
  437. //
  438. // Fill in CDB fields.
  439. //
  440. cdb = (PCDB)Srb->Cdb;
  441. transferBlocks = (USHORT)(currentIrpStack->Parameters.Read.Length >>
  442. FdoExtension->SectorShift);
  443. //
  444. // Move little endian values into CDB in big endian format.
  445. //
  446. cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte3;
  447. cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte2;
  448. cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte1;
  449. cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddress)->Byte0;
  450. cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&transferBlocks)->Byte1;
  451. cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&transferBlocks)->Byte0;
  452. //
  453. // Set transfer direction flag and Cdb command.
  454. //
  455. if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
  456. DebugPrint((3, "ClassBuildRequest: Read Command\n"));
  457. SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_IN);
  458. cdb->CDB10.OperationCode = SCSIOP_READ;
  459. } else {
  460. DebugPrint((3, "ClassBuildRequest: Write Command\n"));
  461. SET_FLAG(Srb->SrbFlags, SRB_FLAGS_DATA_OUT);
  462. cdb->CDB10.OperationCode = SCSIOP_WRITE;
  463. }
  464. //
  465. // If this is not a write-through request, then allow caching.
  466. //
  467. if (!(currentIrpStack->Flags & SL_WRITE_THROUGH)) {
  468. SET_FLAG(Srb->SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE);
  469. } else {
  470. //
  471. // If write caching is enable then force media access in the
  472. // cdb.
  473. //
  474. if (FdoExtension->DeviceFlags & DEV_WRITE_CACHE) {
  475. cdb->CDB10.ForceUnitAccess = TRUE;
  476. }
  477. }
  478. if(TEST_FLAG(Irp->Flags, (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))) {
  479. SET_FLAG(Srb->SrbFlags, SRB_CLASS_FLAGS_PAGING);
  480. }
  481. //
  482. // OR in the default flags from the device object.
  483. //
  484. SET_FLAG(Srb->SrbFlags, FdoExtension->SrbFlags);
  485. //
  486. // Set up major SCSI function.
  487. //
  488. nextIrpStack->MajorFunction = IRP_MJ_SCSI;
  489. //
  490. // Save SRB address in next stack for port driver.
  491. //
  492. nextIrpStack->Parameters.Scsi.Srb = Srb;
  493. //
  494. // Save retry count in current IRP stack.
  495. //
  496. currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
  497. //
  498. // Set up IoCompletion routine address.
  499. //
  500. IoSetCompletionRoutine(Irp, ClassIoComplete, Srb, TRUE, TRUE, TRUE);
  501. }
  502. VOID ClasspInsertCScanList(IN PLIST_ENTRY ListHead, IN PCSCAN_LIST_ENTRY Entry)
  503. {
  504. PCSCAN_LIST_ENTRY t;
  505. DBGWARN(("ClasspInsertCScanList is OBSOLETE !"));
  506. //
  507. // Iterate through the list. Insert this entry in the sorted list in
  508. // order (after other requests for the same block). At each stop if
  509. // blockNumber(Entry) >= blockNumber(t) then move on.
  510. //
  511. for(t = (PCSCAN_LIST_ENTRY) ListHead->Flink;
  512. t != (PCSCAN_LIST_ENTRY) ListHead;
  513. t = (PCSCAN_LIST_ENTRY) t->Entry.Flink) {
  514. if(Entry->BlockNumber < t->BlockNumber) {
  515. //
  516. // Set the pointers in entry to the right location.
  517. //
  518. Entry->Entry.Flink = &(t->Entry);
  519. Entry->Entry.Blink = t->Entry.Blink;
  520. //
  521. // Set the pointers in the surrounding elements to refer to us.
  522. //
  523. t->Entry.Blink->Flink = &(Entry->Entry);
  524. t->Entry.Blink = &(Entry->Entry);
  525. return;
  526. }
  527. }
  528. //
  529. // Insert this entry at the tail of the list. If the list was empty this
  530. // will also be the head of the list.
  531. //
  532. InsertTailList(ListHead, &(Entry->Entry));
  533. }
  534. VOID ClassInsertCScanList(IN PCSCAN_LIST List, IN PIRP Irp, IN ULONGLONG BlockNumber, IN BOOLEAN LowPriority)
  535. /*++
  536. Routine Description:
  537. This routine inserts an entry into the CScan list based on it's block number
  538. and priority. It is assumed that the caller is providing synchronization
  539. to the access of the list.
  540. Low priority requests are always scheduled to run on the next sweep across
  541. the disk. Normal priority requests will be inserted into the current or
  542. next sweep based on the standard C-SCAN algorithm.
  543. Arguments:
  544. List - the list to insert into
  545. Irp - the irp to be inserted.
  546. BlockNumber - the block number for this request.
  547. LowPriority - indicates that the request is lower priority and should be
  548. done on the next sweep across the disk.
  549. Return Value:
  550. none
  551. --*/
  552. {
  553. PCSCAN_LIST_ENTRY entry = (PCSCAN_LIST_ENTRY)Irp->Tail.Overlay.DriverContext;
  554. DBGWARN(("ClassInsertCScanList is OBSOLETE !"));
  555. //
  556. // Set the block number in the entry. We need this to keep the list sorted.
  557. //
  558. entry->BlockNumber = BlockNumber;
  559. //
  560. // If it's a normal priority request and further down the disk than our
  561. // current position then insert this entry into the current sweep.
  562. //
  563. if((LowPriority != TRUE) && (BlockNumber > List->BlockNumber)) {
  564. ClasspInsertCScanList(&(List->CurrentSweep), entry);
  565. } else {
  566. ClasspInsertCScanList(&(List->NextSweep), entry);
  567. }
  568. return;
  569. }
  570. VOID ClassFreeOrReuseSrb( IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
  571. IN PSCSI_REQUEST_BLOCK Srb)
  572. /*++
  573. Routine Description:
  574. This routine will attempt to reuse the provided SRB to start a blocked
  575. read/write request.
  576. If there is no need to reuse the request it will be returned
  577. to the SRB lookaside list.
  578. Arguments:
  579. Fdo - the device extension
  580. Srb - the SRB which is to be reused or freed.
  581. Return Value:
  582. none.
  583. --*/
  584. {
  585. PCLASS_PRIVATE_FDO_DATA privateData = FdoExtension->PrivateFdoData;
  586. PCOMMON_DEVICE_EXTENSION commonExt = &FdoExtension->CommonExtension;
  587. KIRQL oldIrql;
  588. PIRP blockedIrp;
  589. // This function is obsolete, but still called by DISK.SYS .
  590. // DBGWARN(("ClassFreeOrReuseSrb is OBSOLETE !"));
  591. //
  592. // safety net. this should never occur. if it does, it's a potential
  593. // memory leak.
  594. //
  595. ASSERT(!TEST_FLAG(Srb->SrbFlags, SRB_FLAGS_FREE_SENSE_BUFFER));
  596. if (commonExt->IsSrbLookasideListInitialized){
  597. /*
  598. * Put the SRB back in our lookaside list.
  599. *
  600. * BUGBUG - Some class drivers use ClassIoComplete
  601. * to complete SRBs that they themselves allocated.
  602. * So we may be putting a "foreign" SRB
  603. * (e.g. with a different pool tag) into our lookaside list.
  604. */
  605. ClasspFreeSrb(FdoExtension, Srb);
  606. }
  607. else {
  608. DBGERR(("ClassFreeOrReuseSrb: someone is trying to use an uninitialized SrbLookasideList !!!"));;
  609. ExFreePool(Srb);
  610. }
  611. }
  612. /*++////////////////////////////////////////////////////////////////////////////
  613. ClassDeleteSrbLookasideList()
  614. Routine Description:
  615. This routine deletes a lookaside listhead for srbs, and should be called
  616. only during the final removal.
  617. If called at other times, the caller is responsible for
  618. synchronization and removal issues.
  619. Arguments:
  620. CommonExtension - Pointer to the CommonExtension containing the listhead.
  621. Return Value:
  622. None
  623. --*/
  624. VOID ClassDeleteSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension)
  625. {
  626. PAGED_CODE();
  627. // This function is obsolete, but is still called by some of our code.
  628. // DBGWARN(("ClassDeleteSrbLookasideList is OBSOLETE !"));
  629. if (CommonExtension->IsSrbLookasideListInitialized){
  630. CommonExtension->IsSrbLookasideListInitialized = FALSE;
  631. ExDeleteNPagedLookasideList(&CommonExtension->SrbLookasideList);
  632. }
  633. else {
  634. DBGWARN(("ClassDeleteSrbLookasideList: attempt to delete uninitialized or freed srblookasidelist"));
  635. }
  636. }
  637. /*++////////////////////////////////////////////////////////////////////////////
  638. ClassInitializeSrbLookasideList()
  639. Routine Description:
  640. This routine sets up a lookaside listhead for srbs, and should be called
  641. only from the ClassInitDevice() routine to prevent race conditions.
  642. If called from other locations, the caller is responsible for
  643. synchronization and removal issues.
  644. Arguments:
  645. CommonExtension - Pointer to the CommonExtension containing the listhead.
  646. NumberElements - Supplies the maximum depth of the lookaside list.
  647. Note:
  648. The Windows 2000 version of classpnp did not return any status value from
  649. this call.
  650. --*/
  651. VOID ClassInitializeSrbLookasideList( IN PCOMMON_DEVICE_EXTENSION CommonExtension,
  652. IN ULONG NumberElements)
  653. {
  654. PAGED_CODE();
  655. // This function is obsolete, but still called by DISK.SYS .
  656. // DBGWARN(("ClassInitializeSrbLookasideList is OBSOLETE !"));
  657. ASSERT(!CommonExtension->IsSrbLookasideListInitialized);
  658. if (!CommonExtension->IsSrbLookasideListInitialized){
  659. ExInitializeNPagedLookasideList(&CommonExtension->SrbLookasideList,
  660. NULL,
  661. NULL,
  662. NonPagedPool,
  663. sizeof(SCSI_REQUEST_BLOCK),
  664. '$scS',
  665. (USHORT)NumberElements);
  666. CommonExtension->IsSrbLookasideListInitialized = TRUE;
  667. }
  668. }
  669. VOID ClasspInitializeCScanList(IN PCSCAN_LIST List)
  670. {
  671. PAGED_CODE();
  672. RtlZeroMemory(List, sizeof(CSCAN_LIST));
  673. InitializeListHead(&(List->CurrentSweep));
  674. InitializeListHead(&(List->NextSweep));
  675. }
  676. VOID ClasspStartNextSweep(PCSCAN_LIST List)
  677. {
  678. ASSERT(IsListEmpty(&(List->CurrentSweep)) == TRUE);
  679. //
  680. // If the next sweep is empty then there's nothing to do.
  681. //
  682. if(IsListEmpty(&(List->NextSweep))) {
  683. return;
  684. }
  685. //
  686. // Copy the next sweep list head into the current sweep list head.
  687. //
  688. List->CurrentSweep = List->NextSweep;
  689. //
  690. // Unlink the next sweep list from the list head now that we have a copy
  691. // of it.
  692. //
  693. InitializeListHead(&(List->NextSweep));
  694. //
  695. // Update the next sweep list to point back to the current sweep list head.
  696. //
  697. List->CurrentSweep.Flink->Blink = &(List->CurrentSweep);
  698. List->CurrentSweep.Blink->Flink = &(List->CurrentSweep);
  699. return;
  700. }
  701. PIRP ClassRemoveCScanList(IN PCSCAN_LIST List)
  702. {
  703. PCSCAN_LIST_ENTRY entry;
  704. //
  705. // If the current sweep is empty then promote the next sweep.
  706. //
  707. if(IsListEmpty(&(List->CurrentSweep))) {
  708. ClasspStartNextSweep(List);
  709. }
  710. //
  711. // If the current sweep is still empty then we're done.
  712. //
  713. if(IsListEmpty(&(List->CurrentSweep))) {
  714. return NULL;
  715. }
  716. //
  717. // Remove the head entry from the current sweep. Record it's block number
  718. // so that nothing before it on the disk gets into the current sweep.
  719. //
  720. entry = (PCSCAN_LIST_ENTRY) RemoveHeadList(&(List->CurrentSweep));
  721. List->BlockNumber = entry->BlockNumber;
  722. return CONTAINING_RECORD(entry, IRP, Tail.Overlay.DriverContext);
  723. }