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.

5637 lines
120 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. diskdump.c
  5. Abstract:
  6. This is a special SCSI driver that serves as a combined SCSI disk
  7. class driver and SCSI manager for SCSI miniport drivers. It's sole
  8. responsibility is to provide disk services to copy physical memory
  9. into a portion of the disk as a record of a system crash.
  10. Author:
  11. Mike Glass
  12. Notes:
  13. Ported from osloader SCSI modules which were originally developed by
  14. Jeff Havens and Mike Glass.
  15. Revision History:
  16. --*/
  17. #include "ntosp.h"
  18. #include "stdarg.h"
  19. #include "stdio.h"
  20. #include "storport.h"
  21. #include "ntdddisk.h"
  22. #include "diskdump.h"
  23. //
  24. // Need a couple of aliases since we build w/ storport.h vs srb.h.
  25. //
  26. enum {
  27. CallDisableInterrupts = _obsolete1,
  28. CallEnableInterrupts = _obsolete2
  29. };
  30. typedef PHYSICAL_ADDRESS SCSI_PHYSICAL_ADDRESS, *PSCSI_PHYSICAL_ADDRESS;
  31. #undef ScsiPortConvertPhysicalAddressToUlong
  32. #if DBG
  33. #undef DebugPrint
  34. #define DebugPrint(x) ScsiDebugPrint x
  35. #endif
  36. extern PBOOLEAN Mm64BitPhysicalAddress;
  37. //
  38. // The scsi dump driver needs to allocate memory out of it's own, private
  39. // allocation pool. This necessary to prevent pool corruption from
  40. // preventing a successful crashdump.
  41. //
  42. #ifdef ExAllocatePool
  43. #undef ExAllocatePool
  44. #endif
  45. #ifdef ExFreePool
  46. #undef ExFreePool
  47. #endif
  48. #define ExAllocatePool C_ASSERT (FALSE)
  49. #define ExFreePool C_ASSERT (FALSE)
  50. PDEVICE_EXTENSION DeviceExtension;
  51. #define SECONDS (1000 * 1000)
  52. #define RESET_DELAY (4 * SECONDS)
  53. typedef
  54. BOOLEAN
  55. (*PSTOR_SYNCHRONIZED_ACCESS)(
  56. IN PVOID HwDeviceExtension,
  57. IN PVOID Context
  58. );
  59. VOID
  60. ExecuteSrb(
  61. IN PSCSI_REQUEST_BLOCK Srb
  62. );
  63. BOOLEAN
  64. ResetBus(
  65. IN PDEVICE_EXTENSION pDevExt,
  66. IN ULONG PathId
  67. );
  68. VOID
  69. FreeScatterGatherList(
  70. IN PDEVICE_EXTENSION DeviceExtension,
  71. IN PSCSI_REQUEST_BLOCK Srb
  72. );
  73. ULONG
  74. ScsiPortConvertPhysicalAddressToUlong(
  75. PHYSICAL_ADDRESS Address
  76. );
  77. VOID
  78. ScsiDebugPrint(
  79. ULONG DebugPrintLevel,
  80. PCCHAR DebugMessage,
  81. ...
  82. );
  83. //
  84. // Routines start
  85. //
  86. VOID
  87. FreePool(
  88. IN PVOID Ptr
  89. )
  90. /*++
  91. Routine Description:
  92. free block of memory.
  93. Arguments:
  94. ptr - The memory to free.
  95. Return Value:
  96. None.
  97. --*/
  98. {
  99. PMEMORY_HEADER freedBlock;
  100. //
  101. // Don't try to coalesce. They will probably just ask for something
  102. // of just this size again.
  103. //
  104. freedBlock = (PMEMORY_HEADER)Ptr - 1;
  105. freedBlock->Next = DeviceExtension->FreeMemory;
  106. DeviceExtension->FreeMemory = freedBlock;
  107. }
  108. PVOID
  109. AllocatePool(
  110. IN ULONG Size
  111. )
  112. /*++
  113. Routine Description:
  114. Allocate block of memory. Uses first fit algorithm.
  115. The free memory pointer always points to the beginning of the zone.
  116. Arguments:
  117. Size - size of memory to be allocated.
  118. Return Value:
  119. Address of memory block.
  120. --*/
  121. {
  122. PMEMORY_HEADER descriptor = DeviceExtension->FreeMemory;
  123. PMEMORY_HEADER previous = NULL;
  124. ULONG length;
  125. //
  126. // Adjust size for memory header and round up memory to 16 bytes.
  127. //
  128. length = (Size + sizeof(MEMORY_HEADER) + 15) & ~15;
  129. //
  130. // Walk free list looking for first block of memory equal to
  131. // or greater than (adjusted) size requested.
  132. //
  133. while (descriptor) {
  134. if (descriptor->Length >= length) {
  135. //
  136. // Update free list eliminating as much of this block as necessary.
  137. //
  138. // Make sure if we don't have enough of the block left for a
  139. // memory header we just point to the next block (and adjust
  140. // length accordingly).
  141. //
  142. if (!previous) {
  143. if (descriptor->Length < (length+sizeof(MEMORY_HEADER))) {
  144. DeviceExtension->FreeMemory = DeviceExtension->FreeMemory->Next;
  145. } else {
  146. DeviceExtension->FreeMemory =
  147. (PMEMORY_HEADER)((PUCHAR)descriptor + length);
  148. previous = DeviceExtension->FreeMemory;
  149. previous->Length = descriptor->Length - length;
  150. previous->Next = descriptor->Next;
  151. descriptor->Length = length;
  152. }
  153. } else {
  154. if (descriptor->Length < (length+sizeof(MEMORY_HEADER))) {
  155. previous->Next = descriptor->Next;
  156. } else {
  157. previous->Next =
  158. (PMEMORY_HEADER)((PUCHAR)descriptor + length);
  159. previous->Next->Length = descriptor->Length - length;
  160. previous->Next->Next = descriptor->Next;
  161. descriptor->Length = length;
  162. }
  163. }
  164. //
  165. // Update memory header for allocated block.
  166. //
  167. descriptor->Next = NULL;
  168. //
  169. // Adjust address past header.
  170. //
  171. (PUCHAR)descriptor += sizeof(MEMORY_HEADER);
  172. break;
  173. }
  174. previous = descriptor;
  175. descriptor = descriptor->Next;
  176. }
  177. return descriptor;
  178. }
  179. BOOLEAN
  180. DiskDumpOpen(
  181. IN LARGE_INTEGER PartitionOffset
  182. )
  183. /*++
  184. Routine Description:
  185. This is the entry point for open requests to the diskdump driver.
  186. Arguments:
  187. PartitionOffset - Byte offset of partition on disk.
  188. Return Value:
  189. TRUE
  190. --*/
  191. {
  192. //
  193. // Update partition object in device extension for this partition.
  194. //
  195. DeviceExtension->PartitionOffset = PartitionOffset;
  196. return TRUE;
  197. }
  198. VOID
  199. WorkHorseDpc(
  200. )
  201. /*++
  202. Routine Description:
  203. Handle miniport notification.
  204. Arguments:
  205. None.
  206. Return Value:
  207. None.
  208. --*/
  209. {
  210. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  211. //
  212. // Check for a flush DMA adapter object request. Note that
  213. // on the finish up code this will have been already cleared.
  214. //
  215. if (DeviceExtension->InterruptFlags & PD_FLUSH_ADAPTER_BUFFERS) {
  216. //
  217. // Call IoFlushAdapterBuffers using the parameters saved from the last
  218. // IoMapTransfer call.
  219. //
  220. IoFlushAdapterBuffers(
  221. DeviceExtension->DmaAdapterObject,
  222. DeviceExtension->Mdl,
  223. DeviceExtension->MapRegisterBase[1],
  224. DeviceExtension->FlushAdapterParameters.LogicalAddress,
  225. DeviceExtension->FlushAdapterParameters.Length,
  226. (BOOLEAN)(DeviceExtension->FlushAdapterParameters.Srb->SrbFlags
  227. & SRB_FLAGS_DATA_OUT ? TRUE : FALSE));
  228. DeviceExtension->InterruptFlags &= ~PD_FLUSH_ADAPTER_BUFFERS;
  229. }
  230. //
  231. // Check for an IoMapTransfer DMA request. Note that on the finish
  232. // up code, this will have been cleared.
  233. //
  234. if (DeviceExtension->InterruptFlags & PD_MAP_TRANSFER) {
  235. //
  236. // Call IoMapTransfer using the parameters saved from the
  237. // interrupt level.
  238. //
  239. IoMapTransfer(
  240. DeviceExtension->DmaAdapterObject,
  241. DeviceExtension->Mdl,
  242. DeviceExtension->MapRegisterBase[1],
  243. DeviceExtension->MapTransferParameters.LogicalAddress,
  244. &DeviceExtension->MapTransferParameters.Length,
  245. (BOOLEAN)(DeviceExtension->MapTransferParameters.Srb->SrbFlags
  246. & SRB_FLAGS_DATA_OUT ? TRUE : FALSE));
  247. //
  248. // Save the paramters for IoFlushAdapterBuffers.
  249. //
  250. DeviceExtension->FlushAdapterParameters =
  251. DeviceExtension->MapTransferParameters;
  252. DeviceExtension->InterruptFlags &= ~PD_MAP_TRANSFER;
  253. DeviceExtension->Flags |= PD_CALL_DMA_STARTED;
  254. }
  255. //
  256. // Process any completed requests.
  257. //
  258. if (DeviceExtension->RequestComplete) {
  259. //
  260. // Reset request timeout counter.
  261. //
  262. DeviceExtension->RequestTimeoutCounter = -1;
  263. DeviceExtension->RequestComplete = FALSE;
  264. DeviceExtension->RequestPending = FALSE;
  265. //
  266. // Flush the adapter buffers if necessary.
  267. //
  268. if (DeviceExtension->MasterWithAdapter) {
  269. FreeScatterGatherList (DeviceExtension, srb);
  270. }
  271. if (srb->SrbStatus != SRB_STATUS_SUCCESS) {
  272. if ( ((srb->ScsiStatus == SCSISTAT_BUSY) ||
  273. (srb->SrbStatus == SRB_STATUS_BUSY) )&&
  274. (DeviceExtension->RetryCount++ < 20)) {
  275. //
  276. // If busy status is returned, then indicate that the logical
  277. // unit is busy. The timeout code will restart the request
  278. // when it fires. Reset the status to pending.
  279. //
  280. srb->SrbStatus = SRB_STATUS_PENDING;
  281. DeviceExtension->Flags |= PD_LOGICAL_UNIT_IS_BUSY;
  282. //
  283. // Restore the data transfer length.
  284. //
  285. srb->DataTransferLength = DeviceExtension->ByteCount;
  286. DeviceExtension->RequestPending = TRUE;
  287. }
  288. }
  289. //
  290. // Make MDL pointer NULL to show there is no outstanding request.
  291. //
  292. DeviceExtension->Mdl = NULL;
  293. }
  294. }
  295. VOID
  296. RequestSenseCompletion(
  297. )
  298. /*++
  299. Routine Description:
  300. Arguments:
  301. None.
  302. Return Value:
  303. None.
  304. --*/
  305. {
  306. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->RequestSenseSrb;
  307. PSCSI_REQUEST_BLOCK failingSrb = &DeviceExtension->Srb;
  308. PSENSE_DATA senseBuffer = DeviceExtension->RequestSenseBuffer;
  309. //
  310. // Request sense completed. If successful or data over/underrun
  311. // get the failing SRB and indicate that the sense information
  312. // is valid. The class driver will check for underrun and determine
  313. // if there is enough sense information to be useful.
  314. //
  315. if ((SRB_STATUS(srb->SrbStatus) == SRB_STATUS_SUCCESS) ||
  316. (SRB_STATUS(srb->SrbStatus) == SRB_STATUS_DATA_OVERRUN)) {
  317. //
  318. // Check that request sense buffer is valid.
  319. //
  320. if (srb->DataTransferLength >= FIELD_OFFSET(SENSE_DATA, CommandSpecificInformation)) {
  321. DebugPrint((1,"RequestSenseCompletion: Error code is %x\n",
  322. senseBuffer->ErrorCode));
  323. DebugPrint((1,"RequestSenseCompletion: Sense key is %x\n",
  324. senseBuffer->SenseKey));
  325. DebugPrint((1, "RequestSenseCompletion: Additional sense code is %x\n",
  326. senseBuffer->AdditionalSenseCode));
  327. DebugPrint((1, "RequestSenseCompletion: Additional sense code qualifier is %x\n",
  328. senseBuffer->AdditionalSenseCodeQualifier));
  329. }
  330. }
  331. //
  332. // Complete original request.
  333. //
  334. DeviceExtension->RequestComplete = TRUE;
  335. WorkHorseDpc();
  336. }
  337. VOID
  338. IssueRequestSense(
  339. )
  340. /*++
  341. Routine Description:
  342. This routine creates a REQUEST SENSE request and sends it to the miniport
  343. driver.
  344. The completion routine cleans up the data structures
  345. and processes the logical unit queue according to the flags.
  346. A pointer to failing SRB is stored at the end of the request sense
  347. Srb, so that the completion routine can find it.
  348. Arguments:
  349. None.
  350. Return Value:
  351. None.
  352. --*/
  353. {
  354. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->RequestSenseSrb;
  355. PCDB cdb = (PCDB)srb->Cdb;
  356. PPFN_NUMBER page;
  357. PFN_NUMBER localMdl[ (sizeof(MDL)/sizeof(PFN_NUMBER)) + (MAXIMUM_TRANSFER_SIZE / PAGE_SIZE) + 2];
  358. //
  359. // Zero SRB.
  360. //
  361. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  362. //
  363. // Build REQUEST SENSE SRB.
  364. //
  365. srb->TargetId = DeviceExtension->Srb.TargetId;
  366. srb->Lun = DeviceExtension->Srb.Lun;
  367. srb->PathId = DeviceExtension->Srb.PathId;
  368. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  369. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  370. srb->DataBuffer = DeviceExtension->RequestSenseBuffer;
  371. srb->DataTransferLength = sizeof(SENSE_DATA);
  372. srb->ScsiStatus = srb->SrbStatus = 0;
  373. srb->NextSrb = 0;
  374. srb->CdbLength = 6;
  375. srb->TimeOutValue = 5;
  376. //
  377. // Build MDL and map it so that it can be used.
  378. //
  379. DeviceExtension->Mdl = (PMDL) &localMdl[0];
  380. MmInitializeMdl(DeviceExtension->Mdl,
  381. srb->DataBuffer,
  382. srb->DataTransferLength);
  383. page = MmGetMdlPfnArray ( DeviceExtension->Mdl );
  384. *page = (PFN_NUMBER)(DeviceExtension->PhysicalAddress[1].QuadPart >> PAGE_SHIFT);
  385. MmMapMemoryDumpMdl(DeviceExtension->Mdl);
  386. //
  387. // Disable auto request sense.
  388. //
  389. srb->SenseInfoBufferLength = 0;
  390. srb->SenseInfoBuffer = NULL;
  391. //
  392. // Set read and bypass frozen queue bits in flags.
  393. //
  394. srb->SrbFlags = SRB_FLAGS_DATA_IN |
  395. SRB_FLAGS_BYPASS_FROZEN_QUEUE |
  396. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  397. SRB_FLAGS_DISABLE_AUTOSENSE |
  398. SRB_FLAGS_DISABLE_DISCONNECT;
  399. //
  400. // REQUEST SENSE cdb looks like INQUIRY cdb.
  401. //
  402. cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
  403. cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
  404. //
  405. // Send SRB to miniport driver.
  406. //
  407. ExecuteSrb(srb);
  408. }
  409. ULONG
  410. StartDevice(
  411. IN UCHAR TargetId,
  412. IN UCHAR Lun
  413. )
  414. /*++
  415. Routine Description:
  416. Starts up the target device.
  417. Arguments:
  418. TargetId - the id of the device
  419. Lun - The logical unit number
  420. Return Value:
  421. SRB status
  422. --*/
  423. {
  424. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->RequestSenseSrb;
  425. PCDB cdb = (PCDB)srb->Cdb;
  426. ULONG retry;
  427. retry = 0;
  428. DebugPrint((1,"StartDevice: Attempt to start device\n"));
  429. retry_start:
  430. //
  431. // Zero SRB.
  432. //
  433. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  434. RtlZeroMemory(cdb, sizeof(CDB));
  435. srb->TargetId = TargetId;
  436. srb->Lun = Lun;
  437. srb->PathId = DeviceExtension->Srb.PathId;
  438. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  439. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  440. srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
  441. SRB_FLAGS_DISABLE_AUTOSENSE |
  442. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  443. SRB_FLAGS_BYPASS_LOCKED_QUEUE;
  444. srb->CdbLength = 6;
  445. srb->SrbStatus = 0;
  446. srb->ScsiStatus = 0;
  447. srb->NextSrb = 0;
  448. srb->TimeOutValue = 30;
  449. cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
  450. cdb->START_STOP.Start = 1;
  451. //
  452. // Send SRB to miniport driver.
  453. //
  454. ExecuteSrb(srb);
  455. if (srb->SrbStatus != SRB_STATUS_SUCCESS) {
  456. if (retry++ < 4) {
  457. DebugPrint((1,"StartDevice: Failed SRB STATUS: %x Retry #: %x\n",
  458. srb->SrbStatus,retry));
  459. goto retry_start;
  460. }
  461. }
  462. return srb->SrbStatus;
  463. }
  464. VOID
  465. AllocateScatterGatherList(
  466. IN PDEVICE_EXTENSION DeviceExtension,
  467. IN PSCSI_REQUEST_BLOCK Srb
  468. )
  469. /*++
  470. Routine Description:
  471. Create a scatter/gather list for the specified IO.
  472. Arguments:
  473. DeviceExtension - Device extension.
  474. Srb - Scsi Request block to create the scatter/gather list for.
  475. Return Value:
  476. None.
  477. --*/
  478. {
  479. BOOLEAN succ;
  480. BOOLEAN writeToDevice;
  481. ULONG totalLength;
  482. PSCATTER_GATHER_ELEMENT scatterList;
  483. //
  484. // Calculate the number of map registers needed for this transfer.
  485. //
  486. DeviceExtension->NumberOfMapRegisters =
  487. ADDRESS_AND_SIZE_TO_SPAN_PAGES(Srb->DataBuffer,
  488. Srb->DataTransferLength);
  489. //
  490. // Build the scatter/gather list.
  491. //
  492. scatterList = DeviceExtension->ScatterGatherList.Elements;
  493. totalLength = 0;
  494. DeviceExtension->ScatterGatherList.NumberOfElements = 0;
  495. //
  496. // Build the scatter/gather list by looping through the transfer
  497. // calling I/O map transfer.
  498. //
  499. writeToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE;
  500. while (totalLength < Srb->DataTransferLength) {
  501. //
  502. // Request that the rest of the transfer be mapped.
  503. //
  504. scatterList->Length = Srb->DataTransferLength - totalLength;
  505. //
  506. // Io is always done through the second map register.
  507. //
  508. scatterList->Address =
  509. IoMapTransfer (
  510. DeviceExtension->DmaAdapterObject,
  511. DeviceExtension->Mdl,
  512. DeviceExtension->MapRegisterBase[1],
  513. (PCCHAR) Srb->DataBuffer + totalLength,
  514. &scatterList->Length,
  515. writeToDevice);
  516. totalLength += scatterList->Length;
  517. scatterList++;
  518. DeviceExtension->ScatterGatherList.NumberOfElements++;
  519. }
  520. }
  521. VOID
  522. FreeScatterGatherList(
  523. IN PDEVICE_EXTENSION DeviceExtension,
  524. IN PSCSI_REQUEST_BLOCK Srb
  525. )
  526. /*++
  527. Routine Description:
  528. Free a scatter/gather list, freeing all resources associated with it.
  529. Arguments:
  530. DeviceExtension - Device extension.
  531. Srb - Scsi Request block to free the scatter/gather list for.
  532. Return Value:
  533. None.
  534. --*/
  535. {
  536. BOOLEAN succ;
  537. BOOLEAN writeToDevice;
  538. ULONG totalLength;
  539. PSCATTER_GATHER_ELEMENT scatterList;
  540. if (DeviceExtension->Mdl == NULL) {
  541. return;
  542. }
  543. scatterList = DeviceExtension->ScatterGatherList.Elements;
  544. totalLength = 0;
  545. //
  546. // Loop through the list, call IoFlushAdapterBuffers for each entry in
  547. // the list.
  548. //
  549. writeToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE;
  550. while (totalLength < Srb->DataTransferLength) {
  551. //
  552. // Io is always done through the second map register.
  553. //
  554. succ = IoFlushAdapterBuffers(
  555. DeviceExtension->DmaAdapterObject,
  556. DeviceExtension->Mdl,
  557. DeviceExtension->MapRegisterBase[1],
  558. (PCCHAR)Srb->DataBuffer + totalLength,
  559. scatterList->Length,
  560. writeToDevice);
  561. ASSERT (succ == TRUE);
  562. totalLength += scatterList->Length;
  563. scatterList++;
  564. }
  565. }
  566. VOID
  567. StartIo(
  568. IN PSCSI_REQUEST_BLOCK Srb
  569. )
  570. /*++
  571. Routine Description:
  572. Arguments:
  573. Srb - Request to start.
  574. Return Value:
  575. Nothing.
  576. --*/
  577. {
  578. ULONG totalLength;
  579. BOOLEAN writeToDevice;
  580. //
  581. // Set up SRB extension.
  582. //
  583. Srb->SrbExtension = DeviceExtension->SrbExtension;
  584. //
  585. // Flush the data buffer if necessary.
  586. //
  587. if (Srb->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT)) {
  588. if (Srb->DataTransferLength > DeviceExtension->Capabilities.MaximumTransferLength) {
  589. DebugPrint((1,
  590. "StartIo: StartIo Length Exceeds limit (%x > %x)\n",
  591. Srb->DataTransferLength,
  592. DeviceExtension->Capabilities.MaximumTransferLength));
  593. }
  594. HalFlushIoBuffers(
  595. DeviceExtension->Mdl,
  596. (BOOLEAN) (Srb->SrbFlags & SRB_FLAGS_DATA_IN ? TRUE : FALSE),
  597. TRUE);
  598. //
  599. // Determine if this adapter needs map registers.
  600. //
  601. if (DeviceExtension->MasterWithAdapter) {
  602. AllocateScatterGatherList (DeviceExtension, Srb);
  603. }
  604. }
  605. //
  606. // Set request timeout value from Srb SCSI.
  607. //
  608. DeviceExtension->RequestTimeoutCounter = Srb->TimeOutValue;
  609. //
  610. // Send SRB to miniport driver. Miniport driver will notify when
  611. // it completes.
  612. //
  613. if (DeviceExtension->PortType == StorPort &&
  614. DeviceExtension->HwBuildIo != NULL) {
  615. DeviceExtension->HwBuildIo (DeviceExtension->HwDeviceExtension, Srb);
  616. }
  617. DeviceExtension->HwStartIo(DeviceExtension->HwDeviceExtension, Srb);
  618. }
  619. VOID
  620. TickHandler(
  621. IN PSCSI_REQUEST_BLOCK Srb
  622. )
  623. /*++
  624. Routine Description:
  625. This routine simulates a 1-second tickhandler and is used to time
  626. requests.
  627. Arguments:
  628. Srb - request being timed.
  629. Return Value:
  630. None.
  631. --*/
  632. {
  633. if (DeviceExtension->RequestPending) {
  634. //
  635. // Check for busy requests.
  636. //
  637. if (DeviceExtension->Flags & PD_LOGICAL_UNIT_IS_BUSY) {
  638. DebugPrint((1,"TickHandler: Retrying busy status request\n"));
  639. //
  640. // Clear the busy flag and retry the request.
  641. //
  642. DeviceExtension->Flags &= ~PD_LOGICAL_UNIT_IS_BUSY;
  643. StartIo(Srb);
  644. } else if (DeviceExtension->RequestTimeoutCounter == 0) {
  645. ULONG i;
  646. //
  647. // Request timed out.
  648. //
  649. DebugPrint((1, "TickHandler: Request timed out\n"));
  650. DebugPrint((1,
  651. "TickHandler: CDB operation code %x\n",
  652. DeviceExtension->Srb.Cdb[0]));
  653. DebugPrint((1,
  654. "TickHandler: Retry count %x\n",
  655. DeviceExtension->RetryCount));
  656. //
  657. // Reset request timeout counter to unused state.
  658. //
  659. DeviceExtension->RequestTimeoutCounter = -1;
  660. if (!ResetBus(DeviceExtension, 0)) {
  661. DebugPrint((1,"Reset SCSI bus failed\n"));
  662. }
  663. //
  664. // Call the interupt handler for a few microseconds to clear any reset
  665. // interrupts.
  666. //
  667. for (i = 0; i < 1000 * 100; i++) {
  668. DeviceExtension->StallRoutine(10);
  669. if (DeviceExtension->HwInterrupt != NULL) {
  670. DeviceExtension->HwInterrupt(DeviceExtension->HwDeviceExtension);
  671. }
  672. }
  673. //
  674. // Wait 2 seconds for the devices to recover after the reset.
  675. //
  676. DeviceExtension->StallRoutine(2 * SECONDS);
  677. } else if (DeviceExtension->RequestTimeoutCounter != -1) {
  678. DeviceExtension->RequestTimeoutCounter--;
  679. }
  680. }
  681. }
  682. VOID
  683. ExecuteSrb(
  684. IN PSCSI_REQUEST_BLOCK Srb
  685. )
  686. /*++
  687. Routine Description:
  688. This routine calls the start I/O routine an waits for the request to
  689. complete. During the wait for complete the interrupt routine is called,
  690. also the timer routines are called at the appropriate times. After the
  691. request completes a check is made to determine if an request sense needs
  692. to be issued.
  693. Arguments:
  694. Srb - Request to execute.
  695. Return Value:
  696. Nothing.
  697. --*/
  698. {
  699. ULONG milliSecondTime;
  700. ULONG secondTime;
  701. ULONG completionDelay;
  702. //
  703. // Show request is pending.
  704. //
  705. DeviceExtension->RequestPending = TRUE;
  706. //
  707. // Start the request.
  708. //
  709. StartIo(Srb);
  710. //
  711. // The completion delay controls how long interrupts are serviced after
  712. // a request has been completed. This allows interrupts which occur after
  713. // a completion to be serviced.
  714. //
  715. completionDelay = COMPLETION_DELAY;
  716. //
  717. // Wait for the SRB to complete.
  718. //
  719. while (DeviceExtension->RequestPending) {
  720. //
  721. // Wait 1 second then call the scsi port timer routine.
  722. //
  723. for (secondTime = 0; secondTime < 1000/ 250; secondTime++) {
  724. for (milliSecondTime = 0; milliSecondTime < (250 * 1000 / PD_INTERLOOP_STALL); milliSecondTime++) {
  725. if (!(DeviceExtension->Flags & PD_DISABLE_INTERRUPTS)) {
  726. //
  727. // Call miniport driver's interrupt routine.
  728. //
  729. if (DeviceExtension->HwInterrupt != NULL) {
  730. DeviceExtension->HwInterrupt(DeviceExtension->HwDeviceExtension);
  731. }
  732. }
  733. //
  734. // If the request is complete, call the interrupt routine
  735. // a few more times to clean up any extra interrupts.
  736. //
  737. if (!DeviceExtension->RequestPending) {
  738. if (completionDelay-- == 0) {
  739. goto done;
  740. }
  741. }
  742. if (DeviceExtension->Flags & PD_ENABLE_CALL_REQUEST) {
  743. //
  744. // Call the miniport requested routine.
  745. //
  746. DeviceExtension->Flags &= ~PD_ENABLE_CALL_REQUEST;
  747. DeviceExtension->HwRequestInterrupt(DeviceExtension->HwDeviceExtension);
  748. if (DeviceExtension->Flags & PD_DISABLE_CALL_REQUEST) {
  749. DeviceExtension->Flags &= ~(PD_DISABLE_INTERRUPTS | PD_DISABLE_CALL_REQUEST);
  750. DeviceExtension->HwRequestInterrupt(DeviceExtension->HwDeviceExtension);
  751. }
  752. }
  753. if (DeviceExtension->Flags & PD_CALL_DMA_STARTED) {
  754. DeviceExtension->Flags &= ~PD_CALL_DMA_STARTED;
  755. //
  756. // Notify the miniport driver that the DMA has been
  757. // started.
  758. //
  759. if (DeviceExtension->HwDmaStarted) {
  760. DeviceExtension->HwDmaStarted(
  761. DeviceExtension->HwDeviceExtension
  762. );
  763. }
  764. }
  765. //
  766. // This enforces the delay between calls to the interrupt routine.
  767. //
  768. DeviceExtension->StallRoutine(PD_INTERLOOP_STALL);
  769. //
  770. // Check the miniport timer.
  771. //
  772. if (DeviceExtension->TimerValue != 0) {
  773. DeviceExtension->TimerValue--;
  774. if (DeviceExtension->TimerValue == 0) {
  775. //
  776. // The timer timed out so called requested timer routine.
  777. //
  778. DeviceExtension->HwTimerRequest(DeviceExtension->HwDeviceExtension);
  779. }
  780. }
  781. }
  782. }
  783. TickHandler(Srb);
  784. DebugPrint((1,"ExecuteSrb: Waiting for SRB request to complete (~3 sec)\n"));
  785. }
  786. done:
  787. if (Srb == &DeviceExtension->Srb &&
  788. Srb->SrbStatus != SRB_STATUS_SUCCESS) {
  789. //
  790. // Determine if a REQUEST SENSE command needs to be done.
  791. //
  792. if ((Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION) &&
  793. !DeviceExtension->FinishingUp) {
  794. //
  795. // Call IssueRequestSense and it will complete the request after
  796. // the REQUEST SENSE completes.
  797. //
  798. DebugPrint((1,
  799. "ExecuteSrb: Issue request sense\n"));
  800. IssueRequestSense();
  801. }
  802. }
  803. }
  804. NTSTATUS
  805. DiskDumpWrite(
  806. IN PLARGE_INTEGER DiskByteOffset,
  807. IN PMDL Mdl
  808. )
  809. /*++
  810. Routine Description:
  811. This is the entry point for write requests to the diskdump driver.
  812. Arguments:
  813. DiskByteOffset - Byte offset relative to beginning of partition.
  814. Mdl - Memory descriptor list that defines this request.
  815. Return Value:
  816. Status of write operation.
  817. --*/
  818. {
  819. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  820. PCDB cdb = (PCDB)&srb->Cdb;
  821. ULONG blockOffset;
  822. ULONG blockCount;
  823. ULONG retryCount = 0;
  824. //
  825. // ISSUE - 2000/02/29 - math:
  826. //
  827. // This is here until the StartVa is page aligned in the dump code
  828. // (MmMapPhysicalMdl).
  829. //
  830. Mdl->StartVa = PAGE_ALIGN( Mdl->StartVa );
  831. DebugPrint((2,
  832. "Write memory at %x for %x bytes\n",
  833. Mdl->StartVa,
  834. Mdl->ByteCount));
  835. writeRetry:
  836. if (retryCount) {
  837. //
  838. // Remap the Mdl for dump data if IssueRequestSense() is called
  839. // in ExecuteSrb() due to a write error.
  840. //
  841. MmMapMemoryDumpMdl(Mdl);
  842. }
  843. //
  844. // Zero SRB.
  845. //
  846. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  847. //
  848. // Save MDL in device extension.
  849. //
  850. DeviceExtension->Mdl = Mdl;
  851. //
  852. // Initialize SRB.
  853. //
  854. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  855. srb->PathId = DeviceExtension->PathId;
  856. srb->TargetId = DeviceExtension->TargetId;
  857. srb->Lun = DeviceExtension->Lun;
  858. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  859. srb->SrbFlags = SRB_FLAGS_DATA_OUT |
  860. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  861. SRB_FLAGS_DISABLE_DISCONNECT |
  862. SRB_FLAGS_DISABLE_AUTOSENSE;
  863. srb->SrbStatus = srb->ScsiStatus = 0;
  864. srb->NextSrb = 0;
  865. srb->TimeOutValue = 10;
  866. srb->CdbLength = 10;
  867. srb->DataTransferLength = Mdl->ByteCount;
  868. //
  869. // See if adapter needs the memory mapped.
  870. //
  871. if (DeviceExtension->MapBuffers) {
  872. srb->DataBuffer = Mdl->MappedSystemVa;
  873. //
  874. // ISSUE - 2000/02/29 - math: Work-around bad callers.
  875. //
  876. // MapBuffers indicates the adapter expects srb->DataBuffer to be a valid VA reference
  877. // MmMapDumpMdl initializes MappedSystemVa to point to a pre-defined VA region
  878. // Make sure StartVa points to the same page, some callers do not initialize all mdl fields
  879. //
  880. Mdl->StartVa = PAGE_ALIGN( Mdl->MappedSystemVa );
  881. } else {
  882. srb->DataBuffer = (PVOID)((PCHAR)Mdl->StartVa + Mdl->ByteOffset);
  883. }
  884. //
  885. // Initialize CDB for write command.
  886. //
  887. cdb->CDB10.OperationCode = SCSIOP_WRITE;
  888. //
  889. // Convert disk byte offset to block offset.
  890. //
  891. blockOffset = (ULONG)((DeviceExtension->PartitionOffset.QuadPart +
  892. (*DiskByteOffset).QuadPart) /
  893. DeviceExtension->BytesPerSector);
  894. //
  895. // Fill in CDB block address.
  896. //
  897. cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&blockOffset)->Byte3;
  898. cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&blockOffset)->Byte2;
  899. cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&blockOffset)->Byte1;
  900. cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&blockOffset)->Byte0;
  901. blockCount = Mdl->ByteCount >> DeviceExtension->SectorShift;
  902. cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&blockCount)->Byte1;
  903. cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&blockCount)->Byte0;
  904. //
  905. // Send SRB to miniport driver.
  906. //
  907. ExecuteSrb(srb);
  908. //
  909. // Retry SRBs returned with failing status.
  910. //
  911. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
  912. DebugPrint((0,
  913. "Write request failed with SRB status %x\n",
  914. srb->SrbStatus));
  915. //
  916. // If retries not exhausted then retry request.
  917. //
  918. if (retryCount < 2) {
  919. retryCount++;
  920. goto writeRetry;
  921. }
  922. return STATUS_UNSUCCESSFUL;
  923. } else {
  924. return STATUS_SUCCESS;
  925. }
  926. }
  927. VOID
  928. DiskDumpFinish(
  929. VOID
  930. )
  931. /*++
  932. Routine Description:
  933. This routine sends ops that finish up the write
  934. Arguments:
  935. None.
  936. Return Value:
  937. Status of write operation.
  938. --*/
  939. {
  940. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  941. PCDB cdb = (PCDB)&srb->Cdb;
  942. ULONG retryCount = 0;
  943. //
  944. // No data will be transfered with these two requests. So set up
  945. // our extension so that we don't try to flush any buffers.
  946. //
  947. DeviceExtension->InterruptFlags &= ~PD_FLUSH_ADAPTER_BUFFERS;
  948. DeviceExtension->InterruptFlags &= ~PD_MAP_TRANSFER;
  949. DeviceExtension->MapRegisterBase[1] = 0;
  950. DeviceExtension->FinishingUp = TRUE;
  951. //
  952. // Zero SRB.
  953. //
  954. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  955. //
  956. // Initialize SRB.
  957. //
  958. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  959. srb->PathId = DeviceExtension->PathId;
  960. srb->TargetId = DeviceExtension->TargetId;
  961. srb->Lun = DeviceExtension->Lun;
  962. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  963. srb->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  964. SRB_FLAGS_DISABLE_DISCONNECT |
  965. SRB_FLAGS_DISABLE_AUTOSENSE;
  966. srb->SrbStatus = srb->ScsiStatus = 0;
  967. srb->NextSrb = 0;
  968. srb->TimeOutValue = 10;
  969. srb->CdbLength = 10;
  970. //
  971. // Initialize CDB for write command.
  972. //
  973. cdb->CDB10.OperationCode = SCSIOP_SYNCHRONIZE_CACHE;
  974. //
  975. // Send SRB to miniport driver.
  976. //
  977. ExecuteSrb(srb);
  978. srb->CdbLength = 0;
  979. srb->Function = SRB_FUNCTION_SHUTDOWN;
  980. srb->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  981. SRB_FLAGS_DISABLE_DISCONNECT |
  982. SRB_FLAGS_DISABLE_AUTOSENSE;
  983. srb->SrbStatus = srb->ScsiStatus = 0;
  984. srb->NextSrb = 0;
  985. srb->TimeOutValue = 0;
  986. ExecuteSrb(srb);
  987. }
  988. ULONG
  989. GetDeviceTransferSize(
  990. PVOID PortConfig
  991. )
  992. {
  993. ULONG TransferLength;
  994. //
  995. // For all other bus types ISA, EISA, MicroChannel set to the minimum
  996. // known supported size (ex., 32kb)
  997. //
  998. TransferLength = MINIMUM_TRANSFER_SIZE;
  999. //
  1000. // Return the maximum transfer size for the adapter.
  1001. //
  1002. if ( PortConfig ) {
  1003. PPORT_CONFIGURATION_INFORMATION ConfigInfo = PortConfig;
  1004. //
  1005. // Init the transfer length if it exists in port config
  1006. //
  1007. if ( ConfigInfo->MaximumTransferLength ) {
  1008. TransferLength = ConfigInfo->MaximumTransferLength;
  1009. }
  1010. //
  1011. // If the bus is PCI then increase the maximum transfer size
  1012. //
  1013. if ( ConfigInfo->AdapterInterfaceType == PCIBus) {
  1014. if ( TransferLength > MAXIMUM_TRANSFER_SIZE) {
  1015. TransferLength = MAXIMUM_TRANSFER_SIZE;
  1016. }
  1017. } else {
  1018. if (TransferLength > MINIMUM_TRANSFER_SIZE) {
  1019. TransferLength = MINIMUM_TRANSFER_SIZE;
  1020. }
  1021. }
  1022. }
  1023. return TransferLength;
  1024. }
  1025. NTSTATUS
  1026. DriverEntry(
  1027. IN PDRIVER_OBJECT DriverObject,
  1028. IN PUNICODE_STRING RegistryPath
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This is the system's entry point into the diskdump driver.
  1033. Arguments:
  1034. DriverObject - Not used.
  1035. RegistryPath - Using this field to pass initialization parameters.
  1036. Return Value:
  1037. STATUS_SUCCESS
  1038. --*/
  1039. {
  1040. PDUMP_INITIALIZATION_CONTEXT context = (PDUMP_INITIALIZATION_CONTEXT)RegistryPath;
  1041. PMEMORY_HEADER memoryHeader;
  1042. ULONG i;
  1043. PSCSI_ADDRESS TargetAddress;
  1044. //
  1045. // Zero the entire device extension and memory blocks.
  1046. //
  1047. RtlZeroMemory( context->MemoryBlock, 8*PAGE_SIZE );
  1048. RtlZeroMemory( context->CommonBuffer[0], context->CommonBufferSize );
  1049. RtlZeroMemory( context->CommonBuffer[1], context->CommonBufferSize );
  1050. //
  1051. // Allocate device extension from free memory block.
  1052. //
  1053. memoryHeader = (PMEMORY_HEADER)context->MemoryBlock;
  1054. DeviceExtension =
  1055. (PDEVICE_EXTENSION)((PUCHAR)memoryHeader + sizeof(MEMORY_HEADER));
  1056. //
  1057. // Initialize memory descriptor.
  1058. //
  1059. memoryHeader->Length = sizeof(DEVICE_EXTENSION) + sizeof(MEMORY_HEADER);
  1060. memoryHeader->Next = NULL;
  1061. //
  1062. // Fill in first free memory header.
  1063. //
  1064. DeviceExtension->FreeMemory =
  1065. (PMEMORY_HEADER)((PUCHAR)memoryHeader + memoryHeader->Length);
  1066. DeviceExtension->FreeMemory->Length =
  1067. (8*PAGE_SIZE) - memoryHeader->Length;
  1068. DeviceExtension->FreeMemory->Next = NULL;
  1069. //
  1070. // Store away init parameters.
  1071. //
  1072. DeviceExtension->StallRoutine = context->StallRoutine;
  1073. DeviceExtension->CommonBufferSize = context->CommonBufferSize;
  1074. TargetAddress = context->TargetAddress;
  1075. //
  1076. // Make sure that the common buffer size is backed by enough crash dump ptes
  1077. // The size is defined by MAXIMUM_TRANSFER_SIZE
  1078. //
  1079. if (DeviceExtension->CommonBufferSize > MAXIMUM_TRANSFER_SIZE) {
  1080. DeviceExtension->CommonBufferSize = MAXIMUM_TRANSFER_SIZE;
  1081. }
  1082. //
  1083. // Formerly, we allowed NULL TargetAddresses. No more. We must have
  1084. // a valid SCSI TargetAddress to create the dump. If not, just fail
  1085. // here.
  1086. //
  1087. if ( TargetAddress == NULL ) {
  1088. return STATUS_INVALID_PARAMETER;
  1089. }
  1090. DeviceExtension->PathId = TargetAddress->PathId;
  1091. DeviceExtension->TargetId = TargetAddress->TargetId;
  1092. DeviceExtension->Lun = TargetAddress->Lun;
  1093. DebugPrint((1,"DiskDump[DriverEntry] ScsiAddress.Length = %x\n",TargetAddress->Length));
  1094. DebugPrint((1,"DiskDump[DriverEntry] ScsiAddress.PortNumber = %x\n",TargetAddress->PortNumber));
  1095. DebugPrint((1,"DiskDump[DriverEntry] ScisAddress.PathId = %x\n",TargetAddress->PathId));
  1096. DebugPrint((1,"DiskDump[DriverEntry] ScisAddress.TargetId = %x\n",TargetAddress->TargetId));
  1097. DebugPrint((1,"DiskDump[DriverEntry] ScisAddress.Lun = %x\n",TargetAddress->Lun));
  1098. //
  1099. // Save off common buffer's virtual and physical addresses.
  1100. //
  1101. for (i = 0; i < 2; i++) {
  1102. DeviceExtension->CommonBuffer[i] = context->CommonBuffer[i];
  1103. //
  1104. // Convert the va of the buffer to obtain the PhysicalAddress
  1105. //
  1106. DeviceExtension->PhysicalAddress[i] =
  1107. MmGetPhysicalAddress(context->CommonBuffer[i]);
  1108. }
  1109. //
  1110. // Save driver parameters.
  1111. //
  1112. DeviceExtension->DmaAdapterObject = (PADAPTER_OBJECT)context->AdapterObject;
  1113. DeviceExtension->ConfigurationInformation =
  1114. context->PortConfiguration;
  1115. //
  1116. // We need to fixup this field of the port configuration information.
  1117. //
  1118. if (*Mm64BitPhysicalAddress) {
  1119. DeviceExtension->ConfigurationInformation->Dma64BitAddresses = SCSI_DMA64_SYSTEM_SUPPORTED;
  1120. }
  1121. DeviceExtension->MappedAddressList = NULL;
  1122. if (context->MappedRegisterBase) {
  1123. DeviceExtension->MappedAddressList =
  1124. *(PMAPPED_ADDRESS *) context->MappedRegisterBase;
  1125. }
  1126. //
  1127. // Initialize request tracking booleans.
  1128. //
  1129. DeviceExtension->RequestPending = FALSE;
  1130. DeviceExtension->RequestComplete = FALSE;
  1131. //
  1132. // Return major entry points.
  1133. //
  1134. context->OpenRoutine = DiskDumpOpen;
  1135. context->WriteRoutine = DiskDumpWrite;
  1136. context->FinishRoutine = DiskDumpFinish;
  1137. context->MaximumTransferSize = GetDeviceTransferSize(context->PortConfiguration);
  1138. return STATUS_SUCCESS;
  1139. }
  1140. NTSTATUS
  1141. InitializeConfiguration(
  1142. IN PHW_INITIALIZATION_DATA HwInitData,
  1143. OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  1144. IN BOOLEAN InitialCall
  1145. )
  1146. /*++
  1147. Routine Description:
  1148. This routine initializes the port configuration information structure.
  1149. Any necessary information is extracted from the registery.
  1150. Arguments:
  1151. DeviceExtension - Supplies the device extension.
  1152. HwInitializationData - Supplies the initial miniport data.
  1153. ConfigInfo - Supplies the configuration information to be
  1154. initialized.
  1155. InitialCall - Indicates that this is first call to this function.
  1156. If InitialCall is FALSE, then the perivous configuration information
  1157. is used to determine the new information.
  1158. Return Value:
  1159. Returns a status indicating the success or fail of the initializaiton.
  1160. --*/
  1161. {
  1162. ULONG i;
  1163. //
  1164. // If this is the initial call then zero the information and set
  1165. // the structure to the uninitialized values.
  1166. //
  1167. if (InitialCall) {
  1168. RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION));
  1169. ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
  1170. ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType;
  1171. ConfigInfo->InterruptMode = Latched;
  1172. ConfigInfo->MaximumTransferLength = 0xffffffff;
  1173. ConfigInfo->NumberOfPhysicalBreaks = 0xffffffff;
  1174. ConfigInfo->DmaChannel = 0xffffffff;
  1175. ConfigInfo->NumberOfAccessRanges = HwInitData->NumberOfAccessRanges;
  1176. ConfigInfo->MaximumNumberOfTargets = 8;
  1177. for (i = 0; i < 8; i++) {
  1178. ConfigInfo->InitiatorBusId[i] = ~0;
  1179. }
  1180. }
  1181. return STATUS_SUCCESS;
  1182. }
  1183. PINQUIRYDATA
  1184. IssueInquiry(
  1185. )
  1186. /*++
  1187. Routine Description:
  1188. This routine prepares an INQUIRY command that is sent to the miniport driver.
  1189. Arguments:
  1190. None.
  1191. Return Value:
  1192. Address of INQUIRY data.
  1193. --*/
  1194. {
  1195. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  1196. PCDB cdb = (PCDB)&srb->Cdb;
  1197. ULONG retryCount = 0;
  1198. PINQUIRYDATA inquiryData = DeviceExtension->CommonBuffer[1];
  1199. PPFN_NUMBER page;
  1200. PFN_NUMBER localMdl[(sizeof( MDL )/sizeof(PFN_NUMBER)) + (MAXIMUM_TRANSFER_SIZE / PAGE_SIZE) + 2];
  1201. inquiryRetry:
  1202. //
  1203. // Zero SRB.
  1204. //
  1205. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  1206. //
  1207. // Initialize SRB.
  1208. //
  1209. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  1210. srb->PathId = DeviceExtension->PathId;
  1211. srb->TargetId = DeviceExtension->TargetId;
  1212. srb->Lun = DeviceExtension->Lun;
  1213. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  1214. srb->SrbFlags = SRB_FLAGS_DATA_IN |
  1215. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  1216. SRB_FLAGS_DISABLE_DISCONNECT |
  1217. SRB_FLAGS_DISABLE_AUTOSENSE;
  1218. srb->SrbStatus = srb->ScsiStatus = 0;
  1219. srb->NextSrb = 0;
  1220. srb->TimeOutValue = 5;
  1221. srb->CdbLength = 6;
  1222. srb->DataBuffer = inquiryData;
  1223. srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
  1224. //
  1225. // Build MDL and map it so that it can be used.
  1226. //
  1227. DeviceExtension->Mdl = (PMDL)&localMdl[0];
  1228. MmInitializeMdl(DeviceExtension->Mdl,
  1229. srb->DataBuffer,
  1230. srb->DataTransferLength);
  1231. page = MmGetMdlPfnArray ( DeviceExtension->Mdl );
  1232. *page = (PFN_NUMBER)(DeviceExtension->PhysicalAddress[1].QuadPart >> PAGE_SHIFT);
  1233. MmMapMemoryDumpMdl(DeviceExtension->Mdl);
  1234. //
  1235. // Initialize CDB for INQUIRY command.
  1236. //
  1237. cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
  1238. cdb->CDB6INQUIRY.LogicalUnitNumber = 0;
  1239. cdb->CDB6INQUIRY.Reserved1 = 0;
  1240. cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
  1241. cdb->CDB6INQUIRY.PageCode = 0;
  1242. cdb->CDB6INQUIRY.IReserved = 0;
  1243. cdb->CDB6INQUIRY.Control = 0;
  1244. //
  1245. // Send SRB to miniport driver.
  1246. //
  1247. ExecuteSrb(srb);
  1248. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS &&
  1249. SRB_STATUS(srb->SrbStatus) != SRB_STATUS_DATA_OVERRUN) {
  1250. DebugPrint((2,
  1251. "IssueInquiry: Inquiry failed SRB status %x\n",
  1252. srb->SrbStatus));
  1253. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT &&
  1254. retryCount < 2) {
  1255. //
  1256. // If the selection did not time out then retry the request.
  1257. //
  1258. retryCount++;
  1259. goto inquiryRetry;
  1260. } else {
  1261. return NULL;
  1262. }
  1263. }
  1264. return inquiryData;
  1265. }
  1266. VOID
  1267. IssueReadCapacity(
  1268. )
  1269. /*++
  1270. Routine Description:
  1271. This routine prepares a READ CAPACITY command that is sent to the
  1272. miniport driver.
  1273. Arguments:
  1274. None.
  1275. Return Value:
  1276. None.
  1277. --*/
  1278. {
  1279. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  1280. PCDB cdb = (PCDB)&srb->Cdb;
  1281. PREAD_CAPACITY_DATA readCapacityData = DeviceExtension->CommonBuffer[1];
  1282. ULONG retryCount = 0;
  1283. PPFN_NUMBER page;
  1284. PFN_NUMBER localMdl[(sizeof( MDL )/sizeof(PFN_NUMBER)) + (MAXIMUM_TRANSFER_SIZE / PAGE_SIZE) + 2];
  1285. //
  1286. // Zero SRB.
  1287. //
  1288. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  1289. readCapacityRetry:
  1290. //
  1291. // Initialize SRB.
  1292. //
  1293. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  1294. srb->PathId = DeviceExtension->PathId;
  1295. srb->TargetId = DeviceExtension->TargetId;
  1296. srb->Lun = DeviceExtension->Lun;
  1297. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  1298. srb->SrbFlags = SRB_FLAGS_DATA_IN |
  1299. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  1300. SRB_FLAGS_DISABLE_AUTOSENSE |
  1301. SRB_FLAGS_DISABLE_DISCONNECT;
  1302. srb->SrbStatus = srb->ScsiStatus = 0;
  1303. srb->NextSrb = 0;
  1304. srb->TimeOutValue = 5;
  1305. srb->CdbLength = 10;
  1306. srb->DataBuffer = readCapacityData;
  1307. srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
  1308. //
  1309. // Build MDL and map it so that it can be used.
  1310. //
  1311. DeviceExtension->Mdl = (PMDL) &localMdl[0];
  1312. MmInitializeMdl(DeviceExtension->Mdl,
  1313. srb->DataBuffer,
  1314. srb->DataTransferLength);
  1315. page = MmGetMdlPfnArray (DeviceExtension->Mdl);
  1316. *page = (PFN_NUMBER)(DeviceExtension->PhysicalAddress[1].QuadPart >> PAGE_SHIFT);
  1317. MmMapMemoryDumpMdl(DeviceExtension->Mdl);
  1318. //
  1319. // Initialize CDB.
  1320. //
  1321. cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_CAPACITY;
  1322. //
  1323. // Send SRB to miniport driver.
  1324. //
  1325. ExecuteSrb(srb);
  1326. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS &&
  1327. (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_DATA_OVERRUN || srb->Cdb[0] == SCSIOP_READ_CAPACITY)) {
  1328. DebugPrint((1,
  1329. "ReadCapacity failed SRB status %x\n",
  1330. srb->SrbStatus));
  1331. if (retryCount < 2) {
  1332. //
  1333. // If the selection did not time out then retry the request.
  1334. //
  1335. retryCount++;
  1336. goto readCapacityRetry;
  1337. } else {
  1338. //
  1339. // Guess and hope that the block size is 512.
  1340. //
  1341. DeviceExtension->BytesPerSector = 512;
  1342. DeviceExtension->SectorShift = 9;
  1343. }
  1344. } else {
  1345. //
  1346. // Assuming that the 2 lsb is the only non-zero byte, this puts it in
  1347. // the right place.
  1348. //
  1349. DeviceExtension->BytesPerSector = readCapacityData->BytesPerBlock >> 8;
  1350. WHICH_BIT(DeviceExtension->BytesPerSector, DeviceExtension->SectorShift);
  1351. //
  1352. // Check for return size of zero. Set to default size and pass the problem downstream
  1353. //
  1354. if (!DeviceExtension->BytesPerSector) {
  1355. DeviceExtension->BytesPerSector = 512;
  1356. DeviceExtension->SectorShift = 9;
  1357. }
  1358. }
  1359. }
  1360. ULONG
  1361. ScsiPortInitialize(
  1362. IN PVOID Argument1,
  1363. IN PVOID Argument2,
  1364. IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
  1365. IN PVOID HwContext
  1366. )
  1367. /*++
  1368. Routine Description:
  1369. This routine is called by miniport driver to complete initialization.
  1370. Port configuration structure contains data from the miniport's previous
  1371. initialization and all system resources should be assigned and valid.
  1372. Arguments:
  1373. Argument1 - Not used.
  1374. Argument2 - Not used.
  1375. HwInitializationData - Miniport initialization structure
  1376. HwContext - Value passed to miniport driver's config routine
  1377. Return Value:
  1378. NT Status - STATUS_SUCCESS if boot device found.
  1379. --*/
  1380. {
  1381. BOOLEAN succ;
  1382. ULONG status;
  1383. ULONG srbStatus;
  1384. PPORT_CONFIGURATION_INFORMATION configInfo;
  1385. PIO_SCSI_CAPABILITIES capabilities;
  1386. ULONG length;
  1387. BOOLEAN callAgain;
  1388. UCHAR dumpString[] = "dump=1;";
  1389. UCHAR crashDump[32];
  1390. PINQUIRYDATA inquiryData;
  1391. BOOLEAN allocatedConfigInfo;
  1392. ASSERT ( DeviceExtension != NULL );
  1393. //
  1394. // Check if boot device has already been found.
  1395. //
  1396. if (DeviceExtension->FoundBootDevice) {
  1397. return (ULONG)STATUS_UNSUCCESSFUL;
  1398. }
  1399. //
  1400. // Initialization
  1401. //
  1402. DeviceExtension->HwDeviceExtension = NULL;
  1403. DeviceExtension->SpecificLuExtension = NULL;
  1404. configInfo = NULL;
  1405. capabilities = NULL;
  1406. inquiryData = NULL;
  1407. allocatedConfigInfo = FALSE;
  1408. RtlCopyMemory(crashDump,
  1409. dumpString,
  1410. strlen(dumpString) + 1);
  1411. //
  1412. // Check size of init data structure.
  1413. //
  1414. if (HwInitializationData->HwInitializationDataSize > sizeof(HW_INITIALIZATION_DATA)) {
  1415. return (ULONG) STATUS_REVISION_MISMATCH;
  1416. } else if (HwInitializationData->HwInitializationDataSize ==
  1417. FIELD_OFFSET (HW_INITIALIZATION_DATA, HwBuildIo)) {
  1418. DeviceExtension->PortType = ScsiPort;
  1419. } else {
  1420. DeviceExtension->PortType = StorPort;
  1421. }
  1422. //
  1423. // Check that each required entry is not NULL.
  1424. //
  1425. if ((!HwInitializationData->HwInitialize) ||
  1426. (!HwInitializationData->HwFindAdapter) ||
  1427. (!HwInitializationData->HwResetBus)) {
  1428. DebugPrint((0,
  1429. "ScsiPortInitialize: Miniport driver missing required entry\n"));
  1430. return (ULONG)STATUS_UNSUCCESSFUL;
  1431. }
  1432. //
  1433. // Set timer to -1 to indicate no outstanding request.
  1434. //
  1435. DeviceExtension->RequestTimeoutCounter = -1;
  1436. //
  1437. // Allocate memory for the miniport driver's device extension.
  1438. //
  1439. DeviceExtension->HwDeviceExtension =
  1440. AllocatePool(HwInitializationData->DeviceExtensionSize);
  1441. if (!DeviceExtension->HwDeviceExtension) {
  1442. status = STATUS_INSUFFICIENT_RESOURCES;
  1443. goto done;
  1444. }
  1445. //
  1446. // Allocate memory for the hardware logical unit extension and
  1447. // zero it out.
  1448. //
  1449. if (HwInitializationData->SpecificLuExtensionSize) {
  1450. DeviceExtension->HwLogicalUnitExtensionSize =
  1451. HwInitializationData->SpecificLuExtensionSize;
  1452. DeviceExtension->SpecificLuExtension =
  1453. AllocatePool (HwInitializationData->SpecificLuExtensionSize);
  1454. if ( !DeviceExtension->SpecificLuExtension ) {
  1455. status = STATUS_INSUFFICIENT_RESOURCES;
  1456. goto done;
  1457. }
  1458. RtlZeroMemory (
  1459. DeviceExtension->SpecificLuExtension,
  1460. DeviceExtension->HwLogicalUnitExtensionSize);
  1461. }
  1462. //
  1463. // Save the dependent driver routines in the device extension.
  1464. //
  1465. DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
  1466. DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
  1467. DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
  1468. DeviceExtension->HwReset = HwInitializationData->HwResetBus;
  1469. DeviceExtension->HwDmaStarted = HwInitializationData->HwDmaStarted;
  1470. DeviceExtension->HwLogicalUnitExtensionSize =
  1471. HwInitializationData->SpecificLuExtensionSize;
  1472. //
  1473. // If STORPORT grab the HwBuildIo routine.
  1474. //
  1475. if (DeviceExtension->PortType == StorPort) {
  1476. DeviceExtension->HwBuildIo = HwInitializationData->HwBuildIo;
  1477. } else {
  1478. DeviceExtension->HwBuildIo = NULL;
  1479. }
  1480. //
  1481. // Get pointer to capabilities structure.
  1482. //
  1483. capabilities = &DeviceExtension->Capabilities;
  1484. capabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
  1485. //
  1486. // Check if port configuration information structure passed in from
  1487. // the system is valid.
  1488. //
  1489. if (configInfo = DeviceExtension->ConfigurationInformation) {
  1490. //
  1491. // Check to see if this structure applies to this miniport
  1492. // initialization. As long as they ask for more access ranges
  1493. // here than are required when they initialized with scsiport,
  1494. // we should be fine.
  1495. //
  1496. if((configInfo->AdapterInterfaceType != HwInitializationData->AdapterInterfaceType) ||
  1497. (HwInitializationData->NumberOfAccessRanges < configInfo->NumberOfAccessRanges)) {
  1498. //
  1499. // Don't initialize this time.
  1500. //
  1501. status = STATUS_NO_SUCH_DEVICE;
  1502. goto done;
  1503. }
  1504. } else {
  1505. //
  1506. // Allocate a new configuration information structure.
  1507. //
  1508. configInfo = AllocatePool(sizeof(PORT_CONFIGURATION_INFORMATION));
  1509. allocatedConfigInfo = TRUE;
  1510. if ( !configInfo ) {
  1511. status = STATUS_INSUFFICIENT_RESOURCES;
  1512. goto done;
  1513. }
  1514. configInfo->AccessRanges = NULL;
  1515. //
  1516. // Set up configuration information structure.
  1517. //
  1518. status = InitializeConfiguration(
  1519. HwInitializationData,
  1520. configInfo,
  1521. TRUE);
  1522. if (!NT_SUCCESS (status)) {
  1523. status = STATUS_NO_SUCH_DEVICE;
  1524. goto done;
  1525. }
  1526. //
  1527. // Allocate memory for access ranges.
  1528. //
  1529. configInfo->NumberOfAccessRanges =
  1530. HwInitializationData->NumberOfAccessRanges;
  1531. configInfo->AccessRanges =
  1532. AllocatePool(sizeof(ACCESS_RANGE) * HwInitializationData->NumberOfAccessRanges);
  1533. if (configInfo->AccessRanges == NULL) {
  1534. status = STATUS_INSUFFICIENT_RESOURCES;
  1535. goto done;
  1536. }
  1537. //
  1538. // Zero out access ranges.
  1539. //
  1540. RtlZeroMemory(configInfo->AccessRanges,
  1541. HwInitializationData->NumberOfAccessRanges
  1542. * sizeof(ACCESS_RANGE));
  1543. }
  1544. //
  1545. // Determine the maximum transfer size for this adapter
  1546. //
  1547. capabilities->MaximumTransferLength = GetDeviceTransferSize(configInfo);
  1548. DebugPrint ((1,
  1549. "DiskDump: Port Capabilities MaxiumTransferLength = 0x%08x\n",
  1550. capabilities->MaximumTransferLength));
  1551. //
  1552. // Get address of SRB extension.
  1553. //
  1554. DeviceExtension->SrbExtension = DeviceExtension->CommonBuffer[0];
  1555. DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
  1556. length = HwInitializationData->SrbExtensionSize;
  1557. length = (length + 7) & ~7;
  1558. //
  1559. // Get address of request sense buffer.
  1560. //
  1561. DeviceExtension->RequestSenseBuffer = (PSENSE_DATA)
  1562. ((PUCHAR)DeviceExtension->CommonBuffer[0] + length);
  1563. length += sizeof(SENSE_DATA);
  1564. length = (length + 7) & ~7;
  1565. //
  1566. // Use the rest of the buffer for the noncached extension.
  1567. //
  1568. DeviceExtension->NonCachedExtension =
  1569. (PUCHAR)DeviceExtension->CommonBuffer[0] + length;
  1570. //
  1571. // Save the maximum size noncached extension can be.
  1572. //
  1573. DeviceExtension->NonCachedExtensionSize = DeviceExtension->CommonBufferSize - length;
  1574. //
  1575. // If a map registers are required, then allocate them permanently
  1576. // here using the adapter object passed in by the system.
  1577. //
  1578. if (DeviceExtension->DmaAdapterObject != NULL ) {
  1579. LARGE_INTEGER pfn;
  1580. PPFN_NUMBER page;
  1581. PMDL mdl;
  1582. ULONG numberOfPages;
  1583. ULONG i;
  1584. PFN_NUMBER localMdl[(sizeof( MDL )/sizeof (PFN_NUMBER)) + (MAXIMUM_TRANSFER_SIZE / PAGE_SIZE) + 2];
  1585. //
  1586. // Determine how many map registers are needed by considering
  1587. // the maximum transfer size and the size of the two common buffers.
  1588. //
  1589. numberOfPages = capabilities->MaximumTransferLength / PAGE_SIZE;
  1590. DeviceExtension->MapRegisterBase[0] =
  1591. HalAllocateCrashDumpRegisters(DeviceExtension->DmaAdapterObject,
  1592. &numberOfPages);
  1593. numberOfPages = capabilities->MaximumTransferLength / PAGE_SIZE;
  1594. DeviceExtension->MapRegisterBase[1] =
  1595. HalAllocateCrashDumpRegisters(DeviceExtension->DmaAdapterObject,
  1596. &numberOfPages);
  1597. //
  1598. // ISSUE - 2000/02/29 - math: Review.
  1599. //
  1600. // We assume this always succeeds for MAX TRANSFER SIZE as long
  1601. // as max transfer size is less than 64k
  1602. //
  1603. //
  1604. // Determine if adapter is a busmaster or uses slave DMA.
  1605. //
  1606. if (HwInitializationData->NeedPhysicalAddresses &&
  1607. configInfo->Master) {
  1608. DeviceExtension->MasterWithAdapter = TRUE;
  1609. } else {
  1610. DeviceExtension->MasterWithAdapter = FALSE;
  1611. }
  1612. //
  1613. // Build MDL to describe the first common buffer.
  1614. //
  1615. mdl = (PMDL)&localMdl[0];
  1616. MmInitializeMdl(mdl,
  1617. DeviceExtension->CommonBuffer[0],
  1618. DeviceExtension->CommonBufferSize);
  1619. //
  1620. // Get base of page index array at end of MDL.
  1621. //
  1622. page = MmGetMdlPfnArray (mdl);
  1623. //
  1624. // Calculate number of pages per memory block.
  1625. //
  1626. numberOfPages = DeviceExtension->CommonBufferSize / PAGE_SIZE;
  1627. //
  1628. // Fill in MDL description of first memory block.
  1629. //
  1630. for (i = 0; i < numberOfPages; i++) {
  1631. //
  1632. // Calculate first page.
  1633. //
  1634. *page = (PFN_NUMBER)((DeviceExtension->PhysicalAddress[0].QuadPart +
  1635. (PAGE_SIZE * i)) >> PAGE_SHIFT);
  1636. page++;
  1637. }
  1638. mdl->MdlFlags = MDL_PAGES_LOCKED;
  1639. //
  1640. // We need to Map the entire buffer.
  1641. //
  1642. length = DeviceExtension->CommonBufferSize;
  1643. //
  1644. // Convert physical buffer addresses to logical.
  1645. //
  1646. DeviceExtension->LogicalAddress[0] =
  1647. IoMapTransfer(
  1648. DeviceExtension->DmaAdapterObject,
  1649. mdl,
  1650. DeviceExtension->MapRegisterBase[0],
  1651. DeviceExtension->CommonBuffer[0],
  1652. &length,
  1653. FALSE);
  1654. //
  1655. // Build MDL to describe the second common buffer.
  1656. //
  1657. mdl = (PMDL)&localMdl[0];
  1658. MmInitializeMdl(mdl,
  1659. DeviceExtension->CommonBuffer[1],
  1660. DeviceExtension->CommonBufferSize);
  1661. //
  1662. // Get base of page index array at end of MDL.
  1663. //
  1664. page = MmGetMdlPfnArray ( mdl );
  1665. //
  1666. // Calculate number of pages per memory block.
  1667. //
  1668. numberOfPages = DeviceExtension->CommonBufferSize / PAGE_SIZE;
  1669. //
  1670. // Fill in MDL description of first memory block.
  1671. //
  1672. for (i = 0; i < numberOfPages; i++) {
  1673. //
  1674. // Calculate first page.
  1675. //
  1676. *page = (PFN_NUMBER)((DeviceExtension->PhysicalAddress[1].QuadPart +
  1677. (PAGE_SIZE * i)) >> PAGE_SHIFT);
  1678. page++;
  1679. }
  1680. //
  1681. // We need to map the entire buffer.
  1682. //
  1683. length = DeviceExtension->CommonBufferSize;
  1684. //
  1685. // Convert physical buffer addresses to logical.
  1686. //
  1687. DeviceExtension->LogicalAddress[1] =
  1688. IoMapTransfer(
  1689. DeviceExtension->DmaAdapterObject,
  1690. mdl,
  1691. DeviceExtension->MapRegisterBase[1],
  1692. DeviceExtension->CommonBuffer[1],
  1693. &length,
  1694. FALSE);
  1695. } else {
  1696. DeviceExtension->MasterWithAdapter = FALSE;
  1697. DeviceExtension->LogicalAddress[0] =
  1698. DeviceExtension->PhysicalAddress[0];
  1699. DeviceExtension->LogicalAddress[1] =
  1700. DeviceExtension->PhysicalAddress[1];
  1701. }
  1702. //
  1703. // Call miniport driver's find adapter routine.
  1704. //
  1705. if (HwInitializationData->HwFindAdapter(DeviceExtension->HwDeviceExtension,
  1706. HwContext,
  1707. NULL,
  1708. (PCHAR) crashDump,
  1709. configInfo,
  1710. &callAgain) != SP_RETURN_FOUND) {
  1711. status = STATUS_NO_SUCH_DEVICE;
  1712. goto done;
  1713. }
  1714. DebugPrint((1,
  1715. "SCSI adapter IRQ is %d\n",
  1716. configInfo->BusInterruptLevel));
  1717. DebugPrint((1,
  1718. "SCSI adapter ID is %d\n",
  1719. configInfo->InitiatorBusId[0]));
  1720. if (configInfo->NumberOfAccessRanges) {
  1721. DebugPrint((1,
  1722. "SCSI IO address is %x\n",
  1723. ((*(configInfo->AccessRanges))[0]).RangeStart.LowPart));
  1724. }
  1725. //
  1726. // Set indicater as to whether adapter needs mapped buffers.
  1727. //
  1728. DeviceExtension->MapBuffers = configInfo->MapBuffers;
  1729. //
  1730. // Set maximum number of page breaks.
  1731. //
  1732. capabilities->MaximumPhysicalPages = configInfo->NumberOfPhysicalBreaks;
  1733. if (HwInitializationData->ReceiveEvent) {
  1734. capabilities->SupportedAsynchronousEvents |=
  1735. SRBEV_SCSI_ASYNC_NOTIFICATION;
  1736. }
  1737. capabilities->TaggedQueuing = HwInitializationData->TaggedQueuing;
  1738. capabilities->AdapterScansDown = configInfo->AdapterScansDown;
  1739. capabilities->AlignmentMask = configInfo->AlignmentMask;
  1740. //
  1741. // Make sure maximum nuber of pages is set to a reasonable value.
  1742. // This occurs for miniports with no Dma adapter.
  1743. //
  1744. if (capabilities->MaximumPhysicalPages == 0) {
  1745. capabilities->MaximumPhysicalPages =
  1746. (ULONG)ROUND_TO_PAGES(capabilities->MaximumTransferLength) + 1;
  1747. //
  1748. // Honor any limit requested by the miniport.
  1749. //
  1750. if (configInfo->NumberOfPhysicalBreaks < capabilities->MaximumPhysicalPages) {
  1751. capabilities->MaximumPhysicalPages =
  1752. configInfo->NumberOfPhysicalBreaks;
  1753. }
  1754. }
  1755. //
  1756. // Get maximum target IDs.
  1757. //
  1758. if (configInfo->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS) {
  1759. DeviceExtension->MaximumTargetIds = SCSI_MAXIMUM_TARGETS_PER_BUS;
  1760. } else {
  1761. DeviceExtension->MaximumTargetIds =
  1762. configInfo->MaximumNumberOfTargets;
  1763. }
  1764. //
  1765. // Get number of SCSI buses.
  1766. //
  1767. DeviceExtension->NumberOfBuses = configInfo->NumberOfBuses;
  1768. //
  1769. // Call the miniport driver to do its initialization.
  1770. //
  1771. if (!DeviceExtension->HwInitialize(DeviceExtension->HwDeviceExtension)) {
  1772. status = STATUS_INVALID_PARAMETER;
  1773. goto done;
  1774. }
  1775. //
  1776. // Issue the inquiry command.
  1777. //
  1778. inquiryData = IssueInquiry ();
  1779. if (inquiryData == NULL) {
  1780. status = STATUS_UNSUCCESSFUL;
  1781. goto done;
  1782. }
  1783. KdPrintEx ((
  1784. DPFLTR_CRASHDUMP_ID,
  1785. DPFLTR_TRACE_LEVEL,
  1786. "DISKDUMP: Inquiry: Type %d Qual %d Mod %d %s\n",
  1787. (LONG) inquiryData->DeviceType,
  1788. (LONG) inquiryData->DeviceTypeQualifier,
  1789. (LONG) inquiryData->DeviceTypeModifier,
  1790. inquiryData->RemovableMedia ? "Removable" : "Non-Removable"));
  1791. //
  1792. // Reset the bus.
  1793. //
  1794. succ = ResetBus (DeviceExtension, DeviceExtension->PathId);
  1795. if ( !succ ) {
  1796. status = STATUS_UNSUCCESSFUL;
  1797. goto done;
  1798. }
  1799. //
  1800. // Start the device.
  1801. //
  1802. srbStatus = StartDevice (
  1803. DeviceExtension->TargetId,
  1804. DeviceExtension->Lun);
  1805. if (srbStatus != SRB_STATUS_SUCCESS) {
  1806. //
  1807. // SCSIOP_START_STOP_DEVICE is allowed to fail. Some adapters (AMI MegaRAID)
  1808. // fail this request.
  1809. //
  1810. DebugPrint ((0, "DISKDUMP: PathId=%x TargetId=%x Lun=%x failed to start srbStatus = %d\n",
  1811. DeviceExtension->PathId, DeviceExtension->TargetId,
  1812. DeviceExtension->Lun, (LONG) srbStatus));
  1813. }
  1814. //
  1815. // Initialize the driver's capacity data (BytesPerSector, etc.)
  1816. //
  1817. IssueReadCapacity ();
  1818. //
  1819. // NOTE: We may want to go a sanity check that we have actually found
  1820. // the correct drive. On MBR disks this can be accomplished by looking
  1821. // at the NTFT disk signature. On GPT disks we can look at the DiskId.
  1822. // This only makes a difference if the crashdump code gave us the
  1823. // wrong TargetId, Lun, which it should never do.
  1824. //
  1825. DeviceExtension->FoundBootDevice = TRUE;
  1826. status = STATUS_SUCCESS;
  1827. done:
  1828. //
  1829. // On failure, free all resources.
  1830. //
  1831. if ( !NT_SUCCESS (status) ) {
  1832. //
  1833. // The config info can either come from space we allocated or from
  1834. // the DUMP_INITIALIZATION_CONTEXT. If it was allocated and we failed
  1835. // we need to free it.
  1836. //
  1837. if (allocatedConfigInfo && configInfo != NULL) {
  1838. if (configInfo->AccessRanges != NULL) {
  1839. FreePool (configInfo->AccessRanges);
  1840. configInfo->AccessRanges = NULL;
  1841. }
  1842. FreePool (configInfo);
  1843. configInfo = NULL;
  1844. }
  1845. if (DeviceExtension->HwDeviceExtension) {
  1846. FreePool (DeviceExtension->HwDeviceExtension);
  1847. DeviceExtension->HwDeviceExtension = NULL;
  1848. }
  1849. if (DeviceExtension->SpecificLuExtension) {
  1850. FreePool (DeviceExtension->SpecificLuExtension);
  1851. DeviceExtension->SpecificLuExtension = NULL;
  1852. }
  1853. }
  1854. return (ULONG) status;
  1855. }
  1856. //
  1857. // Routines providing service to hardware dependent driver.
  1858. //
  1859. SCSI_PHYSICAL_ADDRESS
  1860. ScsiPortGetPhysicalAddress(
  1861. IN PVOID HwDeviceExtension,
  1862. IN PSCSI_REQUEST_BLOCK Srb,
  1863. IN PVOID VirtualAddress,
  1864. OUT ULONG *Length
  1865. )
  1866. /*++
  1867. Routine Description:
  1868. This routine returns a 32-bit physical address to which a virtual address
  1869. is mapped. There are 2 types addresses that can be translated via this call:
  1870. - An address of memory from the two common buffers that the system provides
  1871. for the crashdump disk drivers.
  1872. - A data buffer address described in an MDL that the system provided with
  1873. an IO request.
  1874. Arguments:
  1875. Return Value:
  1876. --*/
  1877. {
  1878. PSCATTER_GATHER_ELEMENT scatterList;
  1879. PMDL mdl;
  1880. ULONG byteOffset;
  1881. ULONG whichPage;
  1882. PPFN_NUMBER pages;
  1883. PHYSICAL_ADDRESS address;
  1884. //
  1885. // There are two distinct types of memory addresses for which a
  1886. // physical address must be calculated.
  1887. //
  1888. // The first is the data buffer passed in an SRB.
  1889. //
  1890. // The second is an address within the common buffer which is
  1891. // the noncached extension or SRB extensions.
  1892. //
  1893. if (Srb) {
  1894. //
  1895. // There are two distinct types of adapters that require physical
  1896. // addresses.
  1897. //
  1898. // The first is busmaster devices for which scatter/gather lists
  1899. // have already been built.
  1900. //
  1901. // The second is slave or system DMA devices. As the diskdump driver
  1902. // will program the system DMA hardware, the miniport driver will never
  1903. // need to see the physical addresses, so I don't think it will ever
  1904. // make this call.
  1905. //
  1906. if (DeviceExtension->MasterWithAdapter) {
  1907. //
  1908. // A scatter/gather list has already been allocated. Use it to determine
  1909. // the physical address and length. Get the scatter/gather list.
  1910. //
  1911. scatterList = DeviceExtension->ScatterGatherList.Elements;
  1912. //
  1913. // Calculate byte offset into the data buffer.
  1914. //
  1915. byteOffset = (ULONG)((PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer);
  1916. //
  1917. // Find the appropriate entry in the scatter/gatter list.
  1918. //
  1919. while (byteOffset >= scatterList->Length) {
  1920. byteOffset -= scatterList->Length;
  1921. scatterList++;
  1922. }
  1923. //
  1924. // Calculate the physical address and length to be returned.
  1925. //
  1926. *Length = scatterList->Length - byteOffset;
  1927. address.QuadPart = scatterList->Address.QuadPart + byteOffset;
  1928. } else {
  1929. DebugPrint((0,
  1930. "DISKDUMP: Jeff led me to believe this code may never get executed.\n"));
  1931. //
  1932. // Get MDL.
  1933. //
  1934. mdl = DeviceExtension->Mdl;
  1935. //
  1936. // Calculate byte offset from
  1937. // beginning of first physical page.
  1938. //
  1939. if (DeviceExtension->MapBuffers) {
  1940. byteOffset = (ULONG)((PCHAR)VirtualAddress - (PCHAR)mdl->MappedSystemVa);
  1941. } else {
  1942. byteOffset = (ULONG)((PCHAR)VirtualAddress - (PCHAR)mdl->StartVa);
  1943. }
  1944. //
  1945. // Calculate which physical page.
  1946. //
  1947. whichPage = byteOffset >> PAGE_SHIFT;
  1948. //
  1949. // Calculate beginning of physical page array.
  1950. //
  1951. pages = MmGetMdlPfnArray ( mdl );
  1952. //
  1953. // Calculate physical address.
  1954. //
  1955. address.QuadPart = (pages[whichPage] << PAGE_SHIFT) +
  1956. BYTE_OFFSET(VirtualAddress);
  1957. }
  1958. } else {
  1959. //
  1960. // Miniport SRB extensions and noncached extensions come from
  1961. // common buffer 0.
  1962. //
  1963. if (VirtualAddress >= DeviceExtension->CommonBuffer[0] &&
  1964. VirtualAddress <
  1965. (PVOID)((PUCHAR)DeviceExtension->CommonBuffer[0] + DeviceExtension->CommonBufferSize)) {
  1966. address.QuadPart =
  1967. (ULONG_PTR)((PUCHAR)VirtualAddress -
  1968. (PUCHAR)DeviceExtension->CommonBuffer[0]) +
  1969. DeviceExtension->LogicalAddress[0].QuadPart;
  1970. *Length = (ULONG)(DeviceExtension->CommonBufferSize -
  1971. ((PUCHAR)VirtualAddress -
  1972. (PUCHAR)DeviceExtension->CommonBuffer[0]));
  1973. } else if (VirtualAddress >= DeviceExtension->CommonBuffer[1] &&
  1974. VirtualAddress <
  1975. (PVOID)((PUCHAR)DeviceExtension->CommonBuffer[1] + DeviceExtension->CommonBufferSize)) {
  1976. address.QuadPart =
  1977. (ULONG_PTR)((PUCHAR)VirtualAddress -
  1978. (PUCHAR)DeviceExtension->CommonBuffer[1]) +
  1979. DeviceExtension->LogicalAddress[1].QuadPart;
  1980. *Length = (ULONG)(DeviceExtension->CommonBufferSize -
  1981. ((PUCHAR)VirtualAddress -
  1982. (PUCHAR)DeviceExtension->CommonBuffer[1]));
  1983. } else {
  1984. DbgPrint("Crashdump: miniport attempted to get physical address "
  1985. "for invalid VA %#p\n", VirtualAddress);
  1986. DbgPrint("Crashdump: Valid range 1: %p through %p\n",
  1987. (PUCHAR) DeviceExtension->CommonBuffer[0],
  1988. ((PUCHAR) DeviceExtension->CommonBuffer[0]) + DeviceExtension->CommonBufferSize);
  1989. DbgPrint("Crashdump: Valid ranges 2: %p through %p\n",
  1990. (PUCHAR) DeviceExtension->CommonBuffer[1],
  1991. ((PUCHAR) DeviceExtension->CommonBuffer[1]) + DeviceExtension->CommonBufferSize);
  1992. KeBugCheckEx(PORT_DRIVER_INTERNAL,
  1993. 0x80000001,
  1994. (ULONG_PTR) DeviceExtension,
  1995. (ULONG_PTR) VirtualAddress,
  1996. (ULONG_PTR) NULL);
  1997. address.QuadPart = 0;
  1998. *Length = 0;
  1999. }
  2000. }
  2001. return address;
  2002. }
  2003. #define CHECK_POINTER_RANGE(LowerBound,Address,Size)\
  2004. ((PUCHAR)(LowerBound) <= (PUCHAR)(Address) && \
  2005. (PUCHAR)Address < ((PUCHAR)(LowerBound) + Size))
  2006. SCSI_PHYSICAL_ADDRESS
  2007. StorPortGetPhysicalAddress(
  2008. IN PVOID HwDeviceExtension,
  2009. IN PSCSI_REQUEST_BLOCK Srb,
  2010. IN PVOID VirtualAddress,
  2011. OUT ULONG *Length
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. This routine returns a 32-bit physical address to which a virtual address
  2016. is mapped. There are 2 types addresses that can be translated via this call:
  2017. - An address of memory from the two common buffers that the system provides
  2018. for the crashdump disk drivers.
  2019. - A data buffer address described in an MDL that the system provided with
  2020. an IO request.
  2021. Arguments:
  2022. Return Value:
  2023. --*/
  2024. {
  2025. //
  2026. // Unlike SCSIPORT, STORPORT requires a SRB for the SRB's DataBuffer,
  2027. // SenseInfoBuffer and SrbExtension. If this is one of these cases,
  2028. // translate it back to the SCSIPORT usage.
  2029. //
  2030. if (Srb &&
  2031. CHECK_POINTER_RANGE (Srb->SrbExtension, VirtualAddress,
  2032. DeviceExtension->SrbExtensionSize)) {
  2033. Srb = NULL;
  2034. }
  2035. return ScsiPortGetPhysicalAddress (HwDeviceExtension,
  2036. Srb,
  2037. VirtualAddress,
  2038. Length);
  2039. }
  2040. PVOID
  2041. ScsiPortGetVirtualAddress(
  2042. IN PVOID HwDeviceExtension,
  2043. IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
  2044. )
  2045. /*++
  2046. Routine Description:
  2047. This routine is returns a virtual address associated with a
  2048. physical address, if the physical address was obtained by a
  2049. call to ScsiPortGetPhysicalAddress.
  2050. Arguments:
  2051. PhysicalAddress
  2052. Return Value:
  2053. Virtual address if physical page hashed.
  2054. NULL if physical page not found in hash.
  2055. --*/
  2056. {
  2057. ULONG address = ScsiPortConvertPhysicalAddressToUlong(PhysicalAddress);
  2058. ULONG offset;
  2059. //
  2060. // Check if address is in the range of the first common buffer.
  2061. //
  2062. if (address >= DeviceExtension->PhysicalAddress[0].LowPart &&
  2063. address < (DeviceExtension->PhysicalAddress[0].LowPart +
  2064. DeviceExtension->CommonBufferSize)) {
  2065. offset = address - DeviceExtension->PhysicalAddress[0].LowPart;
  2066. return ((PUCHAR)DeviceExtension->CommonBuffer[0] + offset);
  2067. }
  2068. //
  2069. // Check if the address is in the range of the second common buffer.
  2070. //
  2071. if (address >= DeviceExtension->PhysicalAddress[1].LowPart &&
  2072. address < (DeviceExtension->PhysicalAddress[1].LowPart +
  2073. DeviceExtension->CommonBufferSize)) {
  2074. offset = address - DeviceExtension->PhysicalAddress[1].LowPart;
  2075. return ((PUCHAR)DeviceExtension->CommonBuffer[1] + offset);
  2076. }
  2077. return NULL;
  2078. }
  2079. PVOID
  2080. ScsiPortGetLogicalUnit(
  2081. IN PVOID HwDeviceExtension,
  2082. IN UCHAR PathId,
  2083. IN UCHAR TargetId,
  2084. IN UCHAR Lun
  2085. )
  2086. /*++
  2087. Routine Description:
  2088. Return miniport driver's logical unit extension.
  2089. Arguments:
  2090. HwDeviceExtension - The port driver's device extension follows
  2091. the miniport's device extension and contains a pointer to
  2092. the logical device extension list.
  2093. PathId, TargetId and Lun - identify which logical unit on the
  2094. SCSI buses.
  2095. Return Value:
  2096. Miniport driver's logical unit extension
  2097. --*/
  2098. {
  2099. return DeviceExtension->SpecificLuExtension;
  2100. }
  2101. VOID
  2102. ScsiPortNotification(
  2103. IN SCSI_NOTIFICATION_TYPE NotificationType,
  2104. IN PVOID HwDeviceExtension,
  2105. ...
  2106. )
  2107. {
  2108. PSCSI_REQUEST_BLOCK srb = NULL;
  2109. va_list(ap);
  2110. va_start(ap, HwDeviceExtension);
  2111. switch (NotificationType) {
  2112. case NextLuRequest:
  2113. case NextRequest:
  2114. //
  2115. // Start next packet on adapter's queue.
  2116. //
  2117. DeviceExtension->InterruptFlags |= PD_READY_FOR_NEXT_REQUEST;
  2118. break;
  2119. case RequestComplete:
  2120. //
  2121. // Record completed request.
  2122. //
  2123. srb = va_arg(ap, PSCSI_REQUEST_BLOCK);
  2124. //
  2125. // Check which SRB is completing.
  2126. //
  2127. if (srb == &DeviceExtension->Srb) {
  2128. //
  2129. // Complete this request.
  2130. //
  2131. DeviceExtension->RequestComplete = TRUE;
  2132. } else if (srb == &DeviceExtension->RequestSenseSrb) {
  2133. //
  2134. // Process request sense.
  2135. //
  2136. RequestSenseCompletion();
  2137. }
  2138. break;
  2139. case ResetDetected:
  2140. //
  2141. // Delay for 4 seconds.
  2142. //
  2143. DeviceExtension->StallRoutine ( RESET_DELAY );
  2144. break;
  2145. case CallDisableInterrupts:
  2146. ASSERT(DeviceExtension->Flags & PD_DISABLE_INTERRUPTS);
  2147. //
  2148. // The miniport wants us to call the specified routine
  2149. // with interrupts disabled. This is done after the current
  2150. // HwRequestInterrutp routine completes. Indicate the call is
  2151. // needed and save the routine to be called.
  2152. //
  2153. DeviceExtension->Flags |= PD_DISABLE_CALL_REQUEST;
  2154. DeviceExtension->HwRequestInterrupt = va_arg(ap, PHW_INTERRUPT);
  2155. break;
  2156. case CallEnableInterrupts:
  2157. ASSERT(!(DeviceExtension->Flags & PD_DISABLE_INTERRUPTS));
  2158. //
  2159. // The miniport wants us to call the specified routine
  2160. // with interrupts enabled this is done from the DPC.
  2161. // Disable calls to the interrupt routine, indicate the call is
  2162. // needed and save the routine to be called.
  2163. //
  2164. DeviceExtension->Flags |= PD_DISABLE_INTERRUPTS | PD_ENABLE_CALL_REQUEST;
  2165. DeviceExtension->HwRequestInterrupt = va_arg(ap, PHW_INTERRUPT);
  2166. break;
  2167. case RequestTimerCall:
  2168. DeviceExtension->HwTimerRequest = va_arg(ap, PHW_INTERRUPT);
  2169. DeviceExtension->TimerValue = va_arg(ap, ULONG);
  2170. if (DeviceExtension->TimerValue) {
  2171. //
  2172. // Round up the timer value to the stall time.
  2173. //
  2174. DeviceExtension->TimerValue = (DeviceExtension->TimerValue
  2175. + PD_INTERLOOP_STALL - 1)/ PD_INTERLOOP_STALL;
  2176. }
  2177. break;
  2178. }
  2179. va_end(ap);
  2180. //
  2181. // Check to see if the last DPC has been processed yet. If so
  2182. // queue another DPC.
  2183. //
  2184. WorkHorseDpc();
  2185. }
  2186. VOID
  2187. ScsiPortFlushDma(
  2188. IN PVOID HwDeviceExtension
  2189. )
  2190. /*++
  2191. Routine Description:
  2192. This routine checks to see if the previous IoMapTransfer has been done
  2193. started. If it has not, then the PD_MAP_TRANSER flag is cleared, and the
  2194. routine returns; otherwise, this routine schedules a DPC which will call
  2195. IoFlushAdapter buffers.
  2196. Arguments:
  2197. HwDeviceExtension - Supplies a the hardware device extension for the
  2198. host bus adapter which will be doing the data transfer.
  2199. Return Value:
  2200. None.
  2201. --*/
  2202. {
  2203. if (DeviceExtension->InterruptFlags & PD_MAP_TRANSFER) {
  2204. //
  2205. // The transfer has not been started so just clear the map transfer
  2206. // flag and return.
  2207. //
  2208. DeviceExtension->InterruptFlags &= ~PD_MAP_TRANSFER;
  2209. return;
  2210. }
  2211. DeviceExtension->InterruptFlags |= PD_FLUSH_ADAPTER_BUFFERS;
  2212. //
  2213. // Check to see if the last DPC has been processed yet. If so
  2214. // queue another DPC.
  2215. //
  2216. WorkHorseDpc();
  2217. return;
  2218. }
  2219. VOID
  2220. ScsiPortIoMapTransfer(
  2221. IN PVOID HwDeviceExtension,
  2222. IN PSCSI_REQUEST_BLOCK Srb,
  2223. IN PVOID LogicalAddress,
  2224. IN ULONG Length
  2225. )
  2226. /*++
  2227. Routine Description:
  2228. Saves the parameters for the call to IoMapTransfer and schedules the DPC
  2229. if necessary.
  2230. Arguments:
  2231. HwDeviceExtension - Supplies a the hardware device extension for the
  2232. host bus adapter which will be doing the data transfer.
  2233. Srb - Supplies the particular request that data transfer is for.
  2234. LogicalAddress - Supplies the logical address where the transfer should
  2235. begin.
  2236. Length - Supplies the maximum length in bytes of the transfer.
  2237. Return Value:
  2238. None.
  2239. --*/
  2240. {
  2241. //
  2242. // Make sure this host bus adapter has an Dma adapter object.
  2243. //
  2244. if (DeviceExtension->DmaAdapterObject == NULL) {
  2245. //
  2246. // No DMA adapter, no work.
  2247. //
  2248. return;
  2249. }
  2250. DeviceExtension->MapTransferParameters.Srb = Srb;
  2251. DeviceExtension->MapTransferParameters.LogicalAddress = LogicalAddress;
  2252. DeviceExtension->MapTransferParameters.Length = Length;
  2253. DeviceExtension->InterruptFlags |= PD_MAP_TRANSFER;
  2254. //
  2255. // Check to see if the last DPC has been processed yet. If so
  2256. // queue another DPC.
  2257. //
  2258. WorkHorseDpc();
  2259. }
  2260. VOID
  2261. ScsiPortLogError(
  2262. IN PVOID HwDeviceExtension,
  2263. IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
  2264. IN UCHAR PathId,
  2265. IN UCHAR TargetId,
  2266. IN UCHAR Lun,
  2267. IN ULONG ErrorCode,
  2268. IN ULONG UniqueId
  2269. )
  2270. /*++
  2271. Routine Description:
  2272. This routine does no more than put up a debug print message in a debug
  2273. build.
  2274. Arguments:
  2275. DeviceExtenson - Supplies the HBA miniport driver's adapter data storage.
  2276. TargetId, Lun and PathId - specify device address on a SCSI bus.
  2277. ErrorCode - Supplies an error code indicating the type of error.
  2278. UniqueId - Supplies a unique identifier for the error.
  2279. Return Value:
  2280. None.
  2281. --*/
  2282. {
  2283. DebugPrint((0,"\n\nLogErrorEntry: Logging SCSI error packet. ErrorCode = %d.\n",
  2284. ErrorCode));
  2285. DebugPrint((0,
  2286. "PathId = %2x, TargetId = %2x, Lun = %2x, UniqueId = %x.\n\n",
  2287. PathId,
  2288. TargetId,
  2289. Lun,
  2290. UniqueId));
  2291. return;
  2292. }
  2293. VOID
  2294. ScsiPortCompleteRequest(
  2295. IN PVOID HwDeviceExtension,
  2296. IN UCHAR PathId,
  2297. IN UCHAR TargetId,
  2298. IN UCHAR Lun,
  2299. IN UCHAR SrbStatus
  2300. )
  2301. /*++
  2302. Routine Description:
  2303. Complete all active requests for the specified logical unit.
  2304. Arguments:
  2305. DeviceExtenson - Supplies the HBA miniport driver's adapter data storage.
  2306. TargetId, Lun and PathId - specify device address on a SCSI bus.
  2307. SrbStatus - Status to be returned in each completed SRB.
  2308. Return Value:
  2309. None.
  2310. --*/
  2311. {
  2312. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  2313. PSCSI_REQUEST_BLOCK failingSrb;
  2314. //
  2315. // Check if a request is outstanding.
  2316. //
  2317. if (!DeviceExtension->Mdl) {
  2318. return;
  2319. }
  2320. //
  2321. // Just in case this is an abort request,
  2322. // get pointer to failingSrb.
  2323. //
  2324. failingSrb = srb->NextSrb;
  2325. //
  2326. // Update SRB status and show no bytes transferred.
  2327. //
  2328. srb->SrbStatus = SrbStatus;
  2329. srb->DataTransferLength = 0;
  2330. //
  2331. // Call notification routine.
  2332. //
  2333. ScsiPortNotification(RequestComplete,
  2334. HwDeviceExtension,
  2335. srb);
  2336. //
  2337. // Check if this was an ABORT SRB
  2338. //
  2339. if (failingSrb) {
  2340. //
  2341. // This was an abort request. The failing
  2342. // SRB must also be completed.
  2343. //
  2344. failingSrb->SrbStatus = SrbStatus;
  2345. failingSrb->DataTransferLength = 0;
  2346. //
  2347. // Call notification routine.
  2348. //
  2349. ScsiPortNotification(RequestComplete,
  2350. HwDeviceExtension,
  2351. failingSrb);
  2352. }
  2353. return;
  2354. }
  2355. VOID
  2356. ScsiPortMoveMemory(
  2357. IN PVOID WriteBuffer,
  2358. IN PVOID ReadBuffer,
  2359. IN ULONG Length
  2360. )
  2361. /*++
  2362. Routine Description:
  2363. Copy from one buffer into another.
  2364. Arguments:
  2365. ReadBuffer - source
  2366. WriteBuffer - destination
  2367. Length - number of bytes to copy
  2368. Return Value:
  2369. None.
  2370. --*/
  2371. {
  2372. RtlMoveMemory(WriteBuffer, ReadBuffer, Length);
  2373. }
  2374. VOID
  2375. ScsiPortStallExecution(
  2376. ULONG Delay
  2377. )
  2378. /*++
  2379. Routine Description:
  2380. Wait number of microseconds in tight processor loop.
  2381. Arguments:
  2382. Delay - number of microseconds to wait.
  2383. Return Value:
  2384. None.
  2385. --*/
  2386. {
  2387. DeviceExtension->StallRoutine(Delay);
  2388. }
  2389. VOID
  2390. ScsiDebugPrint(
  2391. ULONG DebugPrintLevel,
  2392. PCCHAR DebugMessage,
  2393. ...
  2394. )
  2395. /*++
  2396. Routine Description:
  2397. Debug print for all SCSI drivers
  2398. Arguments:
  2399. Debug print level between 0 and 3, with 3 being the most verbose.
  2400. Return Value:
  2401. None
  2402. --*/
  2403. {
  2404. #if DBG
  2405. va_list ap;
  2406. ULONG DebugLevel;
  2407. va_start( ap, DebugMessage );
  2408. switch (DebugPrintLevel) {
  2409. case 0:
  2410. DebugLevel = DPFLTR_WARNING_LEVEL;
  2411. break;
  2412. case 1:
  2413. case 2:
  2414. DebugLevel = DPFLTR_TRACE_LEVEL;
  2415. break;
  2416. case 3:
  2417. DebugLevel = DPFLTR_INFO_LEVEL;
  2418. break;
  2419. default:
  2420. DebugLevel = DebugPrintLevel;
  2421. break;
  2422. }
  2423. vDbgPrintExWithPrefix ("DISKDUMP: ",
  2424. DPFLTR_CRASHDUMP_ID,
  2425. DebugLevel,
  2426. DebugMessage,
  2427. ap);
  2428. va_end(ap);
  2429. #endif
  2430. }
  2431. UCHAR
  2432. ScsiPortReadPortUchar(
  2433. IN PUCHAR Port
  2434. )
  2435. /*++
  2436. Routine Description:
  2437. Read from the specificed port address.
  2438. Arguments:
  2439. Port - Supplies a pointer to the port address.
  2440. Return Value:
  2441. Returns the value read from the specified port address.
  2442. --*/
  2443. {
  2444. return(READ_PORT_UCHAR(Port));
  2445. }
  2446. USHORT
  2447. ScsiPortReadPortUshort(
  2448. IN PUSHORT Port
  2449. )
  2450. /*++
  2451. Routine Description:
  2452. Read from the specificed port address.
  2453. Arguments:
  2454. Port - Supplies a pointer to the port address.
  2455. Return Value:
  2456. Returns the value read from the specified port address.
  2457. --*/
  2458. {
  2459. return(READ_PORT_USHORT(Port));
  2460. }
  2461. ULONG
  2462. ScsiPortReadPortUlong(
  2463. IN PULONG Port
  2464. )
  2465. /*++
  2466. Routine Description:
  2467. Read from the specificed port address.
  2468. Arguments:
  2469. Port - Supplies a pointer to the port address.
  2470. Return Value:
  2471. Returns the value read from the specified port address.
  2472. --*/
  2473. {
  2474. return(READ_PORT_ULONG(Port));
  2475. }
  2476. UCHAR
  2477. ScsiPortReadRegisterUchar(
  2478. IN PUCHAR Register
  2479. )
  2480. /*++
  2481. Routine Description:
  2482. Read from the specificed register address.
  2483. Arguments:
  2484. Register - Supplies a pointer to the register address.
  2485. Return Value:
  2486. Returns the value read from the specified register address.
  2487. --*/
  2488. {
  2489. return(READ_REGISTER_UCHAR(Register));
  2490. }
  2491. USHORT
  2492. ScsiPortReadRegisterUshort(
  2493. IN PUSHORT Register
  2494. )
  2495. /*++
  2496. Routine Description:
  2497. Read from the specificed register address.
  2498. Arguments:
  2499. Register - Supplies a pointer to the register address.
  2500. Return Value:
  2501. Returns the value read from the specified register address.
  2502. --*/
  2503. {
  2504. return(READ_REGISTER_USHORT(Register));
  2505. }
  2506. ULONG
  2507. ScsiPortReadRegisterUlong(
  2508. IN PULONG Register
  2509. )
  2510. /*++
  2511. Routine Description:
  2512. Read from the specificed register address.
  2513. Arguments:
  2514. Register - Supplies a pointer to the register address.
  2515. Return Value:
  2516. Returns the value read from the specified register address.
  2517. --*/
  2518. {
  2519. return(READ_REGISTER_ULONG(Register));
  2520. }
  2521. VOID
  2522. ScsiPortReadRegisterBufferUchar(
  2523. IN PUCHAR Register,
  2524. IN PUCHAR Buffer,
  2525. IN ULONG Count
  2526. )
  2527. /*++
  2528. Routine Description:
  2529. Read a buffer of unsigned bytes from the specified register address.
  2530. Arguments:
  2531. Register - Supplies a pointer to the port address.
  2532. Buffer - Supplies a pointer to the data buffer area.
  2533. Count - The count of items to move.
  2534. Return Value:
  2535. None
  2536. --*/
  2537. {
  2538. READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
  2539. }
  2540. VOID
  2541. ScsiPortReadRegisterBufferUshort(
  2542. IN PUSHORT Register,
  2543. IN PUSHORT Buffer,
  2544. IN ULONG Count
  2545. )
  2546. /*++
  2547. Routine Description:
  2548. Read a buffer of unsigned shorts from the specified register address.
  2549. Arguments:
  2550. Register - Supplies a pointer to the port address.
  2551. Buffer - Supplies a pointer to the data buffer area.
  2552. Count - The count of items to move.
  2553. Return Value:
  2554. None
  2555. --*/
  2556. {
  2557. READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
  2558. }
  2559. VOID
  2560. ScsiPortReadRegisterBufferUlong(
  2561. IN PULONG Register,
  2562. IN PULONG Buffer,
  2563. IN ULONG Count
  2564. )
  2565. /*++
  2566. Routine Description:
  2567. Read a buffer of unsigned longs from the specified register address.
  2568. Arguments:
  2569. Register - Supplies a pointer to the port address.
  2570. Buffer - Supplies a pointer to the data buffer area.
  2571. Count - The count of items to move.
  2572. Return Value:
  2573. None
  2574. --*/
  2575. {
  2576. READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
  2577. }
  2578. VOID
  2579. ScsiPortWritePortUchar(
  2580. IN PUCHAR Port,
  2581. IN UCHAR Value
  2582. )
  2583. /*++
  2584. Routine Description:
  2585. Write to the specificed port address.
  2586. Arguments:
  2587. Port - Supplies a pointer to the port address.
  2588. Value - Supplies the value to be written.
  2589. Return Value:
  2590. None
  2591. --*/
  2592. {
  2593. WRITE_PORT_UCHAR(Port, Value);
  2594. }
  2595. VOID
  2596. ScsiPortWritePortUshort(
  2597. IN PUSHORT Port,
  2598. IN USHORT Value
  2599. )
  2600. /*++
  2601. Routine Description:
  2602. Write to the specificed port address.
  2603. Arguments:
  2604. Port - Supplies a pointer to the port address.
  2605. Value - Supplies the value to be written.
  2606. Return Value:
  2607. None
  2608. --*/
  2609. {
  2610. WRITE_PORT_USHORT(Port, Value);
  2611. }
  2612. VOID
  2613. ScsiPortWritePortUlong(
  2614. IN PULONG Port,
  2615. IN ULONG Value
  2616. )
  2617. /*++
  2618. Routine Description:
  2619. Write to the specificed port address.
  2620. Arguments:
  2621. Port - Supplies a pointer to the port address.
  2622. Value - Supplies the value to be written.
  2623. Return Value:
  2624. None
  2625. --*/
  2626. {
  2627. WRITE_PORT_ULONG(Port, Value);
  2628. }
  2629. VOID
  2630. ScsiPortWriteRegisterUchar(
  2631. IN PUCHAR Register,
  2632. IN UCHAR Value
  2633. )
  2634. /*++
  2635. Routine Description:
  2636. Write to the specificed register address.
  2637. Arguments:
  2638. Register - Supplies a pointer to the register address.
  2639. Value - Supplies the value to be written.
  2640. Return Value:
  2641. None
  2642. --*/
  2643. {
  2644. WRITE_REGISTER_UCHAR(Register, Value);
  2645. }
  2646. VOID
  2647. ScsiPortWriteRegisterUshort(
  2648. IN PUSHORT Register,
  2649. IN USHORT Value
  2650. )
  2651. /*++
  2652. Routine Description:
  2653. Write to the specificed register address.
  2654. Arguments:
  2655. Register - Supplies a pointer to the register address.
  2656. Value - Supplies the value to be written.
  2657. Return Value:
  2658. None
  2659. --*/
  2660. {
  2661. WRITE_REGISTER_USHORT(Register, Value);
  2662. }
  2663. VOID
  2664. ScsiPortWriteRegisterUlong(
  2665. IN PULONG Register,
  2666. IN ULONG Value
  2667. )
  2668. /*++
  2669. Routine Description:
  2670. Write to the specificed register address.
  2671. Arguments:
  2672. Register - Supplies a pointer to the register address.
  2673. Value - Supplies the value to be written.
  2674. Return Value:
  2675. None
  2676. --*/
  2677. {
  2678. WRITE_REGISTER_ULONG(Register, Value);
  2679. }
  2680. VOID
  2681. ScsiPortWriteRegisterBufferUchar(
  2682. IN PUCHAR Register,
  2683. IN PUCHAR Buffer,
  2684. IN ULONG Count
  2685. )
  2686. /*++
  2687. Routine Description:
  2688. Write a buffer of unsigned bytes from the specified register address.
  2689. Arguments:
  2690. Register - Supplies a pointer to the port address.
  2691. Buffer - Supplies a pointer to the data buffer area.
  2692. Count - The count of items to move.
  2693. Return Value:
  2694. None
  2695. --*/
  2696. {
  2697. WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
  2698. }
  2699. VOID
  2700. ScsiPortWriteRegisterBufferUshort(
  2701. IN PUSHORT Register,
  2702. IN PUSHORT Buffer,
  2703. IN ULONG Count
  2704. )
  2705. /*++
  2706. Routine Description:
  2707. Write a buffer of unsigned shorts from the specified register address.
  2708. Arguments:
  2709. Register - Supplies a pointer to the port address.
  2710. Buffer - Supplies a pointer to the data buffer area.
  2711. Count - The count of items to move.
  2712. Return Value:
  2713. None
  2714. --*/
  2715. {
  2716. WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
  2717. }
  2718. VOID
  2719. ScsiPortWriteRegisterBufferUlong(
  2720. IN PULONG Register,
  2721. IN PULONG Buffer,
  2722. IN ULONG Count
  2723. )
  2724. /*++
  2725. Routine Description:
  2726. Write a buffer of unsigned longs from the specified register address.
  2727. Arguments:
  2728. Register - Supplies a pointer to the port address.
  2729. Buffer - Supplies a pointer to the data buffer area.
  2730. Count - The count of items to move.
  2731. Return Value:
  2732. None
  2733. --*/
  2734. {
  2735. WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
  2736. }
  2737. SCSI_PHYSICAL_ADDRESS
  2738. ScsiPortConvertUlongToPhysicalAddress(
  2739. ULONG_PTR UlongAddress
  2740. )
  2741. {
  2742. SCSI_PHYSICAL_ADDRESS physicalAddress;
  2743. physicalAddress.QuadPart = UlongAddress;
  2744. return(physicalAddress);
  2745. }
  2746. ULONG
  2747. ScsiPortConvertPhysicalAddressToUlong(
  2748. PHYSICAL_ADDRESS Address
  2749. )
  2750. {
  2751. return(Address.LowPart);
  2752. }
  2753. PVOID
  2754. ScsiPortGetDeviceBase(
  2755. IN PVOID HwDeviceExtension,
  2756. IN INTERFACE_TYPE BusType,
  2757. IN ULONG SystemIoBusNumber,
  2758. SCSI_PHYSICAL_ADDRESS IoAddress,
  2759. ULONG NumberOfBytes,
  2760. BOOLEAN InIoSpace
  2761. )
  2762. /*++
  2763. Routine Description:
  2764. This routine maps an IO address to system address space.
  2765. This was done during system initialization for the crash dump driver.
  2766. Arguments:
  2767. HwDeviceExtension - used to find port device extension.
  2768. BusType - what type of bus - eisa, mca, isa
  2769. SystemIoBusNumber - which IO bus (for machines with multiple buses).
  2770. IoAddress - base device address to be mapped.
  2771. NumberOfBytes - number of bytes for which address is valid.
  2772. InIoSpace - indicates an IO address.
  2773. Return Value:
  2774. Mapped address
  2775. --*/
  2776. {
  2777. PMAPPED_ADDRESS Addresses = DeviceExtension->MappedAddressList;
  2778. PHYSICAL_ADDRESS CardAddress;
  2779. ULONG AddressSpace = InIoSpace;
  2780. PVOID MappedAddress = NULL;
  2781. BOOLEAN b;
  2782. b = HalTranslateBusAddress(
  2783. BusType, // AdapterInterfaceType
  2784. SystemIoBusNumber, // SystemIoBusNumber
  2785. IoAddress, // Bus Address
  2786. &AddressSpace, // AddressSpace
  2787. &CardAddress
  2788. );
  2789. if ( !b ) {
  2790. return NULL;
  2791. }
  2792. //
  2793. // If the address space is not in I/O space, then it was mapped during
  2794. // the original system initialization of the driver. Therefore, it must
  2795. // be in the list of mapped address ranges. Look it up and return it.
  2796. //
  2797. if (!AddressSpace) {
  2798. while (Addresses) {
  2799. if (SystemIoBusNumber == Addresses->BusNumber &&
  2800. NumberOfBytes == Addresses->NumberOfBytes &&
  2801. IoAddress.QuadPart == Addresses->IoAddress.QuadPart) {
  2802. MappedAddress = Addresses->MappedAddress;
  2803. break;
  2804. }
  2805. Addresses = Addresses->NextMappedAddress;
  2806. }
  2807. } else {
  2808. MappedAddress = (PVOID)(ULONG_PTR)CardAddress.QuadPart;
  2809. }
  2810. return MappedAddress;
  2811. }
  2812. VOID
  2813. ScsiPortFreeDeviceBase(
  2814. IN PVOID HwDeviceExtension,
  2815. IN PVOID MappedAddress
  2816. )
  2817. /*++
  2818. Routine Description:
  2819. This routine unmaps an IO address that has been previously mapped
  2820. to system address space using ScsiPortGetDeviceBase().
  2821. Arguments:
  2822. HwDeviceExtension - used to find port device extension.
  2823. MappedAddress - address to unmap.
  2824. NumberOfBytes - number of bytes mapped.
  2825. InIoSpace - addresses in IO space don't get mapped.
  2826. Return Value:
  2827. None
  2828. --*/
  2829. {
  2830. UNREFERENCED_PARAMETER(HwDeviceExtension);
  2831. UNREFERENCED_PARAMETER(MappedAddress);
  2832. return;
  2833. }
  2834. PVOID
  2835. ScsiPortGetUncachedExtension(
  2836. IN PVOID HwDeviceExtension,
  2837. IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
  2838. IN ULONG NumberOfBytes
  2839. )
  2840. /*++
  2841. Routine Description:
  2842. This function returns the address of the noncached extension for the
  2843. miniport driver.
  2844. Arguments:
  2845. DeviceExtension - Supplies a pointer to the miniports device extension.
  2846. ConfigInfo - Supplies a pointer to the partially initialized configuraiton
  2847. information. This is used to get an DMA adapter object.
  2848. NumberOfBytes - Supplies the size of the extension which needs to be
  2849. allocated
  2850. Return Value:
  2851. A pointer to the noncached device extension or
  2852. NULL if the requested extension size is larger than the extension
  2853. that was previously allocated.
  2854. --*/
  2855. {
  2856. if (DeviceExtension->NonCachedExtensionSize >= NumberOfBytes) {
  2857. return DeviceExtension->NonCachedExtension;
  2858. } else {
  2859. DebugPrint((0,
  2860. "ScsiPortGetUncachedExtension: Request %x but only %x available\n",
  2861. NumberOfBytes,
  2862. DeviceExtension->NonCachedExtensionSize));
  2863. return NULL;
  2864. }
  2865. }
  2866. ULONG
  2867. ScsiPortGetBusData(
  2868. IN PVOID DeviceExtension,
  2869. IN ULONG BusDataType,
  2870. IN ULONG SystemIoBusNumber,
  2871. IN ULONG SlotNumber,
  2872. IN PVOID Buffer,
  2873. IN ULONG Length
  2874. )
  2875. /*++
  2876. Routine Description:
  2877. The function returns the bus data for an adapter slot or CMOS address.
  2878. Arguments:
  2879. BusDataType - Supplies the type of bus.
  2880. BusNumber - Indicates which bus.
  2881. Buffer - Supplies the space to store the data.
  2882. Length - Supplies a count in bytes of the maximum amount to return.
  2883. Return Value:
  2884. Returns the amount of data stored into the buffer.
  2885. --*/
  2886. {
  2887. ULONG ret;
  2888. //
  2889. // If the length is non-zero, the the requested data.
  2890. //
  2891. if (BusDataType == PCIConfiguration) {
  2892. ret = HalGetBusDataByOffset(
  2893. BusDataType,
  2894. SystemIoBusNumber,
  2895. SlotNumber,
  2896. Buffer,
  2897. 0,
  2898. Length);
  2899. } else {
  2900. ret = 0;
  2901. }
  2902. return ret;
  2903. }
  2904. PSCSI_REQUEST_BLOCK
  2905. ScsiPortGetSrb(
  2906. IN PVOID HwDeviceExtension,
  2907. IN UCHAR PathId,
  2908. IN UCHAR TargetId,
  2909. IN UCHAR Lun,
  2910. IN LONG QueueTag
  2911. )
  2912. /*++
  2913. Routine Description:
  2914. This routine retrieves an active SRB for a particuliar logical unit.
  2915. Arguments:
  2916. HwDeviceExtension -
  2917. PathId -
  2918. TargetId -
  2919. Lun - identify logical unit on SCSI bus.
  2920. QueueTag - -1 indicates request is not tagged.
  2921. Return Value:
  2922. SRB if outstanding request, otherwise NULL.
  2923. --*/
  2924. {
  2925. PSCSI_REQUEST_BLOCK srb;
  2926. if (DeviceExtension->RequestPending) {
  2927. srb = &DeviceExtension->Srb;
  2928. } else {
  2929. srb = NULL;
  2930. }
  2931. return srb;
  2932. }
  2933. BOOLEAN
  2934. ScsiPortValidateRange(
  2935. IN PVOID HwDeviceExtension,
  2936. IN INTERFACE_TYPE BusType,
  2937. IN ULONG SystemIoBusNumber,
  2938. IN SCSI_PHYSICAL_ADDRESS IoAddress,
  2939. IN ULONG NumberOfBytes,
  2940. IN BOOLEAN InIoSpace
  2941. )
  2942. /*++
  2943. Routine Description:
  2944. This routine should take an IO range and make sure that it is not already
  2945. in use by another adapter. This allows miniport drivers to probe IO where
  2946. an adapter could be, without worrying about messing up another card.
  2947. Arguments:
  2948. HwDeviceExtension - Used to find scsi managers internal structures
  2949. BusType - EISA, PCI, PC/MCIA, MCA, ISA, what?
  2950. SystemIoBusNumber - Which system bus?
  2951. IoAddress - Start of range
  2952. NumberOfBytes - Length of range
  2953. InIoSpace - Is range in IO space?
  2954. Return Value:
  2955. TRUE if range not claimed by another driver.
  2956. --*/
  2957. {
  2958. //
  2959. // This is not implemented in NT.
  2960. //
  2961. return TRUE;
  2962. }
  2963. VOID
  2964. ScsiPortReadPortBufferUchar(
  2965. IN PUCHAR Port,
  2966. IN PUCHAR Buffer,
  2967. IN ULONG Count
  2968. )
  2969. /*++
  2970. Routine Description:
  2971. Read a buffer of unsigned bytes from the specified port address.
  2972. Arguments:
  2973. Port - Supplies a pointer to the port address.
  2974. Buffer - Supplies a pointer to the data buffer area.
  2975. Count - The count of items to move.
  2976. Return Value:
  2977. None
  2978. --*/
  2979. {
  2980. READ_PORT_BUFFER_UCHAR(Port, Buffer, Count);
  2981. }
  2982. VOID
  2983. ScsiPortReadPortBufferUshort(
  2984. IN PUSHORT Port,
  2985. IN PUSHORT Buffer,
  2986. IN ULONG Count
  2987. )
  2988. /*++
  2989. Routine Description:
  2990. Read a buffer of unsigned shorts from the specified port address.
  2991. Arguments:
  2992. Port - Supplies a pointer to the port address.
  2993. Buffer - Supplies a pointer to the data buffer area.
  2994. Count - The count of items to move.
  2995. Return Value:
  2996. None
  2997. --*/
  2998. {
  2999. READ_PORT_BUFFER_USHORT(Port, Buffer, Count);
  3000. }
  3001. VOID
  3002. ScsiPortReadPortBufferUlong(
  3003. IN PULONG Port,
  3004. IN PULONG Buffer,
  3005. IN ULONG Count
  3006. )
  3007. /*++
  3008. Routine Description:
  3009. Read a buffer of unsigned longs from the specified port address.
  3010. Arguments:
  3011. Port - Supplies a pointer to the port address.
  3012. Buffer - Supplies a pointer to the data buffer area.
  3013. Count - The count of items to move.
  3014. Return Value:
  3015. None
  3016. --*/
  3017. {
  3018. READ_PORT_BUFFER_ULONG(Port, Buffer, Count);
  3019. }
  3020. VOID
  3021. ScsiPortWritePortBufferUchar(
  3022. IN PUCHAR Port,
  3023. IN PUCHAR Buffer,
  3024. IN ULONG Count
  3025. )
  3026. /*++
  3027. Routine Description:
  3028. Write a buffer of unsigned bytes from the specified port address.
  3029. Arguments:
  3030. Port - Supplies a pointer to the port address.
  3031. Buffer - Supplies a pointer to the data buffer area.
  3032. Count - The count of items to move.
  3033. Return Value:
  3034. None
  3035. --*/
  3036. {
  3037. WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count);
  3038. }
  3039. VOID
  3040. ScsiPortWritePortBufferUshort(
  3041. IN PUSHORT Port,
  3042. IN PUSHORT Buffer,
  3043. IN ULONG Count
  3044. )
  3045. /*++
  3046. Routine Description:
  3047. Write a buffer of unsigned shorts from the specified port address.
  3048. Arguments:
  3049. Port - Supplies a pointer to the port address.
  3050. Buffer - Supplies a pointer to the data buffer area.
  3051. Count - The count of items to move.
  3052. Return Value:
  3053. None
  3054. --*/
  3055. {
  3056. WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count);
  3057. }
  3058. VOID
  3059. ScsiPortWritePortBufferUlong(
  3060. IN PULONG Port,
  3061. IN PULONG Buffer,
  3062. IN ULONG Count
  3063. )
  3064. /*++
  3065. Routine Description:
  3066. Write a buffer of unsigned longs from the specified port address.
  3067. Arguments:
  3068. Port - Supplies a pointer to the port address.
  3069. Buffer - Supplies a pointer to the data buffer area.
  3070. Count - The count of items to move.
  3071. Return Value:
  3072. None
  3073. --*/
  3074. {
  3075. WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count);
  3076. }
  3077. ULONG
  3078. ScsiPortSetBusDataByOffset(
  3079. IN PVOID DeviceExtension,
  3080. IN ULONG BusDataType,
  3081. IN ULONG SystemIoBusNumber,
  3082. IN ULONG SlotNumber,
  3083. IN PVOID Buffer,
  3084. IN ULONG Offset,
  3085. IN ULONG Length
  3086. )
  3087. /*++
  3088. Routine Description:
  3089. The function returns writes bus data to a specific offset within a slot.
  3090. Arguments:
  3091. DeviceExtension - State information for a particular adapter.
  3092. BusDataType - Supplies the type of bus.
  3093. SystemIoBusNumber - Indicates which system IO bus.
  3094. SlotNumber - Indicates which slot.
  3095. Buffer - Supplies the data to write.
  3096. Offset - Byte offset to begin the write.
  3097. Length - Supplies a count in bytes of the maximum amount to return.
  3098. Return Value:
  3099. Number of bytes written.
  3100. --*/
  3101. {
  3102. return 0;
  3103. return(HalSetBusDataByOffset(BusDataType,
  3104. SystemIoBusNumber,
  3105. SlotNumber,
  3106. Buffer,
  3107. Offset,
  3108. Length));
  3109. }
  3110. BOOLEAN
  3111. ResetBus(
  3112. IN PDEVICE_EXTENSION DeviceExtension,
  3113. IN ULONG PathId
  3114. )
  3115. /*++
  3116. Routine Description:
  3117. This function will call the miniport's reset routine, and stall for 4 seconds
  3118. before continuing
  3119. Arguments:
  3120. DeviceExtension - State information for a particular adapter.
  3121. Pathid - Identifies the SCSI bus to reset
  3122. --*/
  3123. {
  3124. BOOLEAN result;
  3125. ASSERT ( DeviceExtension != NULL );
  3126. ASSERT ( DeviceExtension->HwReset != NULL );
  3127. result = DeviceExtension->HwReset ( DeviceExtension->HwDeviceExtension, PathId );
  3128. //
  3129. // Wait for 4 seconds
  3130. //
  3131. DeviceExtension->StallRoutine( RESET_DELAY );
  3132. //
  3133. // Poll the interrupt handler to clear any reset interrupts.
  3134. //
  3135. if (DeviceExtension->HwInterrupt != NULL) {
  3136. DeviceExtension->HwInterrupt(DeviceExtension->HwDeviceExtension);
  3137. }
  3138. return result;
  3139. }
  3140. VOID
  3141. ScsiPortQuerySystemTime(
  3142. OUT PLARGE_INTEGER Time
  3143. )
  3144. {
  3145. Time->QuadPart = 0;
  3146. }
  3147. BOOLEAN
  3148. StorPortDeviceBusy(
  3149. IN PVOID HwDeviceExtension,
  3150. IN UCHAR PathId,
  3151. IN UCHAR TargetId,
  3152. IN UCHAR Lun,
  3153. IN ULONG RequestsToComplete
  3154. )
  3155. {
  3156. return TRUE;
  3157. }
  3158. BOOLEAN
  3159. StorPortDeviceReady(
  3160. IN PVOID HwDeviceExtension,
  3161. IN UCHAR PathId,
  3162. IN UCHAR TargetId,
  3163. IN UCHAR Lun
  3164. )
  3165. {
  3166. return TRUE;
  3167. }
  3168. PSTOR_SCATTER_GATHER_LIST
  3169. StorPortGetScatterGatherList(
  3170. IN PVOID HwDeviceExtension,
  3171. IN PSCSI_REQUEST_BLOCK Srb
  3172. )
  3173. {
  3174. // NB: Check that SG list count is correct
  3175. return (PSTOR_SCATTER_GATHER_LIST)&DeviceExtension->ScatterGatherList;
  3176. }
  3177. BOOLEAN
  3178. StorPortResumeDevice(
  3179. IN PVOID HwDeviceExtension,
  3180. IN UCHAR PathId,
  3181. IN UCHAR TargetId,
  3182. IN UCHAR Lun
  3183. )
  3184. {
  3185. return TRUE;
  3186. }
  3187. BOOLEAN
  3188. StorPortBusy(
  3189. IN PVOID HwDeviceExtension,
  3190. IN ULONG RequestsToComplete
  3191. )
  3192. {
  3193. return TRUE;
  3194. }
  3195. BOOLEAN
  3196. StorPortReady(
  3197. IN PVOID HwDeviceExtension
  3198. )
  3199. {
  3200. return TRUE;
  3201. }
  3202. BOOLEAN
  3203. StorPortPause(
  3204. IN PVOID HwDeviceExtension,
  3205. IN ULONG Timeout
  3206. )
  3207. {
  3208. ScsiPortStallExecution (Timeout * SECONDS);
  3209. return TRUE;
  3210. }
  3211. BOOLEAN
  3212. StorPortPauseDevice(
  3213. IN PVOID HwDeviceExtension,
  3214. IN UCHAR PathId,
  3215. IN UCHAR TargetId,
  3216. IN UCHAR Lun,
  3217. IN ULONG Timeout
  3218. )
  3219. {
  3220. ScsiPortStallExecution (Timeout * SECONDS);
  3221. return TRUE;
  3222. }
  3223. BOOLEAN
  3224. StorPortResume(
  3225. IN PVOID HwDeviceExtension
  3226. )
  3227. {
  3228. return TRUE;
  3229. }
  3230. BOOLEAN
  3231. StorPortSynchronizeAccess(
  3232. IN PVOID HwDeviceExtension,
  3233. IN PSTOR_SYNCHRONIZED_ACCESS SynchronizedAccessRoutine,
  3234. IN PVOID Context
  3235. )
  3236. {
  3237. ASSERT (SynchronizedAccessRoutine != NULL);
  3238. return SynchronizedAccessRoutine (HwDeviceExtension, Context);
  3239. }
  3240. //
  3241. // DEAD CODE: The remainder of this file is no longer used.
  3242. //
  3243. #if 0
  3244. //
  3245. // The functions ReadSector() and IssueReadCapacity() are
  3246. // no longer necessary. They are left here for reference purposes
  3247. // only
  3248. //
  3249. VOID
  3250. ReadSector(
  3251. PLARGE_INTEGER ByteOffset
  3252. )
  3253. /*++
  3254. Routine Description:
  3255. Read 1 sector into common buffer.
  3256. Arguments:
  3257. None.
  3258. Return Value:
  3259. None.
  3260. --*/
  3261. {
  3262. PSCSI_REQUEST_BLOCK srb = &DeviceExtension->Srb;
  3263. PCDB cdb = (PCDB)&srb->Cdb;
  3264. ULONG startingSector;
  3265. ULONG retryCount = 0;
  3266. PPFN_NUMBER page;
  3267. PFN_NUMBER localMdl[(sizeof( MDL )/sizeof(PFN_NUMBER)) + (MAXIMUM_TRANSFER_SIZE / PAGE_SIZE) + 2];
  3268. //
  3269. // Zero SRB.
  3270. //
  3271. RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
  3272. readSectorRetry:
  3273. //
  3274. // Initialize SRB.
  3275. //
  3276. srb->Length = sizeof(SCSI_REQUEST_BLOCK);
  3277. srb->PathId = DeviceExtension->PathId;
  3278. srb->TargetId = DeviceExtension->TargetId;
  3279. srb->Lun = DeviceExtension->Lun;
  3280. srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
  3281. srb->SrbFlags = SRB_FLAGS_DATA_IN |
  3282. SRB_FLAGS_DISABLE_SYNCH_TRANSFER |
  3283. SRB_FLAGS_DISABLE_DISCONNECT |
  3284. SRB_FLAGS_DISABLE_AUTOSENSE;
  3285. srb->SrbStatus = srb->ScsiStatus = 0;
  3286. srb->NextSrb = 0;
  3287. srb->TimeOutValue = 5;
  3288. srb->CdbLength = 10;
  3289. srb->DataBuffer = DeviceExtension->CommonBuffer[1];
  3290. srb->DataTransferLength = DeviceExtension->BytesPerSector;
  3291. //
  3292. // Build MDL and map it so that it can be used.
  3293. //
  3294. DeviceExtension->Mdl = (PMDL)&localMdl[0];
  3295. MmInitializeMdl(DeviceExtension->Mdl,
  3296. srb->DataBuffer,
  3297. srb->DataTransferLength);
  3298. page = MdlGetMdlPfnArray ( DeviceExtension->Mdl );
  3299. *page = (PFN_NUMBER)(DeviceExtension->PhysicalAddress[1].QuadPart >> PAGE_SHIFT);
  3300. MmMapMemoryDumpMdl(DeviceExtension->Mdl);
  3301. //
  3302. // Initialize CDB for READ command.
  3303. //
  3304. cdb->CDB10.OperationCode = SCSIOP_READ;
  3305. //
  3306. // Calculate starting sector.
  3307. //
  3308. startingSector = (ULONG)((*ByteOffset).QuadPart /
  3309. DeviceExtension->BytesPerSector);
  3310. //
  3311. // SCSI CDBs use big endian.
  3312. //
  3313. cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&startingSector)->Byte3;
  3314. cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&startingSector)->Byte2;
  3315. cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&startingSector)->Byte1;
  3316. cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&startingSector)->Byte0;
  3317. cdb->CDB10.TransferBlocksMsb = 0;
  3318. cdb->CDB10.TransferBlocksLsb = 1;
  3319. //
  3320. // Send SRB to miniport driver.
  3321. //
  3322. ExecuteSrb(srb);
  3323. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS &&
  3324. SRB_STATUS(srb->SrbStatus) != SRB_STATUS_DATA_OVERRUN) {
  3325. DebugPrint((1,
  3326. "ReadSector: Read sector failed SRB status %x\n",
  3327. srb->SrbStatus));
  3328. if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT &&
  3329. retryCount < 2) {
  3330. //
  3331. // If the selection did not time out then retry the request.
  3332. //
  3333. retryCount++;
  3334. goto readSectorRetry;
  3335. }
  3336. }
  3337. }
  3338. #endif
  3339. UCHAR
  3340. StorPortReadPortUchar(
  3341. IN PVOID HwDeviceExtension,
  3342. IN PUCHAR Port
  3343. )
  3344. /*++
  3345. Routine Description:
  3346. Read from the specified port address.
  3347. Arguments:
  3348. Port - Supplies a pointer to the port address.
  3349. Return Value:
  3350. Returns the value read from the specified port address.
  3351. --*/
  3352. {
  3353. return(READ_PORT_UCHAR(Port));
  3354. }
  3355. USHORT
  3356. StorPortReadPortUshort(
  3357. IN PVOID HwDeviceExtension,
  3358. IN PUSHORT Port
  3359. )
  3360. /*++
  3361. Routine Description:
  3362. Read from the specified port address.
  3363. Arguments:
  3364. Port - Supplies a pointer to the port address.
  3365. Return Value:
  3366. Returns the value read from the specified port address.
  3367. --*/
  3368. {
  3369. return(READ_PORT_USHORT(Port));
  3370. }
  3371. ULONG
  3372. StorPortReadPortUlong(
  3373. IN PVOID HwDeviceExtension,
  3374. IN PULONG Port
  3375. )
  3376. /*++
  3377. Routine Description:
  3378. Read from the specified port address.
  3379. Arguments:
  3380. Port - Supplies a pointer to the port address.
  3381. Return Value:
  3382. Returns the value read from the specified port address.
  3383. --*/
  3384. {
  3385. return(READ_PORT_ULONG(Port));
  3386. }
  3387. VOID
  3388. StorPortReadPortBufferUchar(
  3389. IN PVOID HwDeviceExtension,
  3390. IN PUCHAR Port,
  3391. IN PUCHAR Buffer,
  3392. IN ULONG Count
  3393. )
  3394. /*++
  3395. Routine Description:
  3396. Read a buffer of unsigned bytes from the specified port address.
  3397. Arguments:
  3398. Port - Supplies a pointer to the port address.
  3399. Buffer - Supplies a pointer to the data buffer area.
  3400. Count - The count of items to move.
  3401. Return Value:
  3402. None
  3403. --*/
  3404. {
  3405. READ_PORT_BUFFER_UCHAR(Port, Buffer, Count);
  3406. }
  3407. VOID
  3408. StorPortReadPortBufferUshort(
  3409. IN PVOID HwDeviceExtension,
  3410. IN PUSHORT Port,
  3411. IN PUSHORT Buffer,
  3412. IN ULONG Count
  3413. )
  3414. /*++
  3415. Routine Description:
  3416. Read a buffer of unsigned shorts from the specified port address.
  3417. Arguments:
  3418. Port - Supplies a pointer to the port address.
  3419. Buffer - Supplies a pointer to the data buffer area.
  3420. Count - The count of items to move.
  3421. Return Value:
  3422. None
  3423. --*/
  3424. {
  3425. READ_PORT_BUFFER_USHORT(Port, Buffer, Count);
  3426. }
  3427. VOID
  3428. StorPortReadPortBufferUlong(
  3429. IN PVOID HwDeviceExtension,
  3430. IN PULONG Port,
  3431. IN PULONG Buffer,
  3432. IN ULONG Count
  3433. )
  3434. /*++
  3435. Routine Description:
  3436. Read a buffer of unsigned longs from the specified port address.
  3437. Arguments:
  3438. Port - Supplies a pointer to the port address.
  3439. Buffer - Supplies a pointer to the data buffer area.
  3440. Count - The count of items to move.
  3441. Return Value:
  3442. None
  3443. --*/
  3444. {
  3445. READ_PORT_BUFFER_ULONG(Port, Buffer, Count);
  3446. }
  3447. UCHAR
  3448. StorPortReadRegisterUchar(
  3449. IN PVOID HwDeviceExtension,
  3450. IN PUCHAR Register
  3451. )
  3452. /*++
  3453. Routine Description:
  3454. Read from the specificed register address.
  3455. Arguments:
  3456. Register - Supplies a pointer to the register address.
  3457. Return Value:
  3458. Returns the value read from the specified register address.
  3459. --*/
  3460. {
  3461. return(READ_REGISTER_UCHAR(Register));
  3462. }
  3463. USHORT
  3464. StorPortReadRegisterUshort(
  3465. IN PVOID HwDeviceExtension,
  3466. IN PUSHORT Register
  3467. )
  3468. /*++
  3469. Routine Description:
  3470. Read from the specified register address.
  3471. Arguments:
  3472. Register - Supplies a pointer to the register address.
  3473. Return Value:
  3474. Returns the value read from the specified register address.
  3475. --*/
  3476. {
  3477. return(READ_REGISTER_USHORT(Register));
  3478. }
  3479. ULONG
  3480. StorPortReadRegisterUlong(
  3481. IN PVOID HwDeviceExtension,
  3482. IN PULONG Register
  3483. )
  3484. /*++
  3485. Routine Description:
  3486. Read from the specified register address.
  3487. Arguments:
  3488. Register - Supplies a pointer to the register address.
  3489. Return Value:
  3490. Returns the value read from the specified register address.
  3491. --*/
  3492. {
  3493. return(READ_REGISTER_ULONG(Register));
  3494. }
  3495. VOID
  3496. StorPortReadRegisterBufferUchar(
  3497. IN PVOID HwDeviceExtension,
  3498. IN PUCHAR Register,
  3499. IN PUCHAR Buffer,
  3500. IN ULONG Count
  3501. )
  3502. /*++
  3503. Routine Description:
  3504. Read a buffer of unsigned bytes from the specified register address.
  3505. Arguments:
  3506. Register - Supplies a pointer to the port address.
  3507. Buffer - Supplies a pointer to the data buffer area.
  3508. Count - The count of items to move.
  3509. Return Value:
  3510. None
  3511. --*/
  3512. {
  3513. READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
  3514. }
  3515. VOID
  3516. StorPortReadRegisterBufferUshort(
  3517. IN PVOID HwDeviceExtension,
  3518. IN PUSHORT Register,
  3519. IN PUSHORT Buffer,
  3520. IN ULONG Count
  3521. )
  3522. /*++
  3523. Routine Description:
  3524. Read a buffer of unsigned shorts from the specified register address.
  3525. Arguments:
  3526. Register - Supplies a pointer to the port address.
  3527. Buffer - Supplies a pointer to the data buffer area.
  3528. Count - The count of items to move.
  3529. Return Value:
  3530. None
  3531. --*/
  3532. {
  3533. READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
  3534. }
  3535. VOID
  3536. StorPortReadRegisterBufferUlong(
  3537. IN PVOID HwDeviceExtension,
  3538. IN PULONG Register,
  3539. IN PULONG Buffer,
  3540. IN ULONG Count
  3541. )
  3542. /*++
  3543. Routine Description:
  3544. Read a buffer of unsigned longs from the specified register address.
  3545. Arguments:
  3546. Register - Supplies a pointer to the port address.
  3547. Buffer - Supplies a pointer to the data buffer area.
  3548. Count - The count of items to move.
  3549. Return Value:
  3550. None
  3551. --*/
  3552. {
  3553. READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
  3554. }
  3555. VOID
  3556. StorPortWritePortUchar(
  3557. IN PVOID HwDeviceExtension,
  3558. IN PUCHAR Port,
  3559. IN UCHAR Value
  3560. )
  3561. /*++
  3562. Routine Description:
  3563. Write to the specificed port address.
  3564. Arguments:
  3565. Port - Supplies a pointer to the port address.
  3566. Value - Supplies the value to be written.
  3567. Return Value:
  3568. None
  3569. --*/
  3570. {
  3571. WRITE_PORT_UCHAR(Port, Value);
  3572. }
  3573. VOID
  3574. StorPortWritePortUshort(
  3575. IN PVOID HwDeviceExtension,
  3576. IN PUSHORT Port,
  3577. IN USHORT Value
  3578. )
  3579. /*++
  3580. Routine Description:
  3581. Write to the specificed port address.
  3582. Arguments:
  3583. Port - Supplies a pointer to the port address.
  3584. Value - Supplies the value to be written.
  3585. Return Value:
  3586. None
  3587. --*/
  3588. {
  3589. WRITE_PORT_USHORT(Port, Value);
  3590. }
  3591. VOID
  3592. StorPortWritePortUlong(
  3593. IN PVOID HwDeviceExtension,
  3594. IN PULONG Port,
  3595. IN ULONG Value
  3596. )
  3597. /*++
  3598. Routine Description:
  3599. Write to the specificed port address.
  3600. Arguments:
  3601. Port - Supplies a pointer to the port address.
  3602. Value - Supplies the value to be written.
  3603. Return Value:
  3604. None
  3605. --*/
  3606. {
  3607. WRITE_PORT_ULONG(Port, Value);
  3608. }
  3609. VOID
  3610. StorPortWritePortBufferUchar(
  3611. IN PVOID HwDeviceExtension,
  3612. IN PUCHAR Port,
  3613. IN PUCHAR Buffer,
  3614. IN ULONG Count
  3615. )
  3616. /*++
  3617. Routine Description:
  3618. Write a buffer of unsigned bytes from the specified port address.
  3619. Arguments:
  3620. Port - Supplies a pointer to the port address.
  3621. Buffer - Supplies a pointer to the data buffer area.
  3622. Count - The count of items to move.
  3623. Return Value:
  3624. None
  3625. --*/
  3626. {
  3627. WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count);
  3628. }
  3629. VOID
  3630. StorPortWritePortBufferUshort(
  3631. IN PVOID HwDeviceExtension,
  3632. IN PUSHORT Port,
  3633. IN PUSHORT Buffer,
  3634. IN ULONG Count
  3635. )
  3636. /*++
  3637. Routine Description:
  3638. Write a buffer of unsigned shorts from the specified port address.
  3639. Arguments:
  3640. Port - Supplies a pointer to the port address.
  3641. Buffer - Supplies a pointer to the data buffer area.
  3642. Count - The count of items to move.
  3643. Return Value:
  3644. None
  3645. --*/
  3646. {
  3647. WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count);
  3648. }
  3649. VOID
  3650. StorPortWritePortBufferUlong(
  3651. IN PVOID HwDeviceExtension,
  3652. IN PULONG Port,
  3653. IN PULONG Buffer,
  3654. IN ULONG Count
  3655. )
  3656. /*++
  3657. Routine Description:
  3658. Write a buffer of unsigned longs from the specified port address.
  3659. Arguments:
  3660. Port - Supplies a pointer to the port address.
  3661. Buffer - Supplies a pointer to the data buffer area.
  3662. Count - The count of items to move.
  3663. Return Value:
  3664. None
  3665. --*/
  3666. {
  3667. WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count);
  3668. }
  3669. VOID
  3670. StorPortWriteRegisterUchar(
  3671. IN PVOID HwDeviceExtension,
  3672. IN PUCHAR Register,
  3673. IN UCHAR Value
  3674. )
  3675. /*++
  3676. Routine Description:
  3677. Write to the specificed register address.
  3678. Arguments:
  3679. Register - Supplies a pointer to the register address.
  3680. Value - Supplies the value to be written.
  3681. Return Value:
  3682. None
  3683. --*/
  3684. {
  3685. WRITE_REGISTER_UCHAR(Register, Value);
  3686. }
  3687. VOID
  3688. StorPortWriteRegisterUshort(
  3689. IN PVOID HwDeviceExtension,
  3690. IN PUSHORT Register,
  3691. IN USHORT Value
  3692. )
  3693. /*++
  3694. Routine Description:
  3695. Write to the specificed register address.
  3696. Arguments:
  3697. Register - Supplies a pointer to the register address.
  3698. Value - Supplies the value to be written.
  3699. Return Value:
  3700. None
  3701. --*/
  3702. {
  3703. WRITE_REGISTER_USHORT(Register, Value);
  3704. }
  3705. VOID
  3706. StorPortWriteRegisterBufferUchar(
  3707. IN PVOID HwDeviceExtension,
  3708. IN PUCHAR Register,
  3709. IN PUCHAR Buffer,
  3710. IN ULONG Count
  3711. )
  3712. /*++
  3713. Routine Description:
  3714. Write a buffer of unsigned bytes from the specified register address.
  3715. Arguments:
  3716. Register - Supplies a pointer to the port address.
  3717. Buffer - Supplies a pointer to the data buffer area.
  3718. Count - The count of items to move.
  3719. Return Value:
  3720. None
  3721. --*/
  3722. {
  3723. WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count);
  3724. }
  3725. VOID
  3726. StorPortWriteRegisterBufferUshort(
  3727. IN PVOID HwDeviceExtension,
  3728. IN PUSHORT Register,
  3729. IN PUSHORT Buffer,
  3730. IN ULONG Count
  3731. )
  3732. /*++
  3733. Routine Description:
  3734. Write a buffer of unsigned shorts from the specified register address.
  3735. Arguments:
  3736. Register - Supplies a pointer to the port address.
  3737. Buffer - Supplies a pointer to the data buffer area.
  3738. Count - The count of items to move.
  3739. Return Value:
  3740. None
  3741. --*/
  3742. {
  3743. WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count);
  3744. }
  3745. VOID
  3746. StorPortWriteRegisterBufferUlong(
  3747. IN PVOID HwDeviceExtension,
  3748. IN PULONG Register,
  3749. IN PULONG Buffer,
  3750. IN ULONG Count
  3751. )
  3752. /*++
  3753. Routine Description:
  3754. Write a buffer of unsigned longs from the specified register address.
  3755. Arguments:
  3756. Register - Supplies a pointer to the port address.
  3757. Buffer - Supplies a pointer to the data buffer area.
  3758. Count - The count of items to move.
  3759. Return Value:
  3760. None
  3761. --*/
  3762. {
  3763. WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count);
  3764. }
  3765. VOID
  3766. StorPortWriteRegisterUlong(
  3767. IN PVOID HwDeviceExtension,
  3768. IN PULONG Register,
  3769. IN ULONG Value
  3770. )
  3771. /*++
  3772. Routine Description:
  3773. Write to the specificed register address.
  3774. Arguments:
  3775. Register - Supplies a pointer to the register address.
  3776. Value - Supplies the value to be written.
  3777. Return Value:
  3778. None
  3779. --*/
  3780. {
  3781. WRITE_REGISTER_ULONG(Register, Value);
  3782. }
  3783. PUCHAR
  3784. StorPortAllocateRegistryBuffer(
  3785. IN PVOID HwDeviceExtension,
  3786. IN PULONG Length
  3787. )
  3788. {
  3789. return NULL;
  3790. }
  3791. VOID
  3792. StorPortFreeRegistryBuffer(
  3793. IN PVOID HwDeviceExtension,
  3794. IN PUCHAR Buffer
  3795. )
  3796. {
  3797. }
  3798. BOOLEAN
  3799. StorPortRegistryRead(
  3800. IN PVOID HwDeviceExtension,
  3801. IN PUCHAR ValueName,
  3802. IN ULONG Global,
  3803. IN ULONG Type,
  3804. IN PUCHAR Buffer,
  3805. IN PULONG BufferLength
  3806. )
  3807. {
  3808. return FALSE;
  3809. }
  3810. BOOLEAN
  3811. StorPortRegistryWrite(
  3812. IN PVOID HwDeviceExtension,
  3813. IN PUCHAR ValueName,
  3814. IN ULONG Global,
  3815. IN ULONG Type,
  3816. IN PUCHAR Buffer,
  3817. IN ULONG BufferLength
  3818. )
  3819. {
  3820. return FALSE;
  3821. }
  3822. BOOLEAN
  3823. StorPortSetDeviceQueueDepth(
  3824. IN PVOID HwDeviceExtension,
  3825. IN UCHAR PathId,
  3826. IN UCHAR TargetId,
  3827. IN UCHAR Lun,
  3828. IN ULONG Depth
  3829. )
  3830. {
  3831. return TRUE;
  3832. }