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.

1517 lines
40 KiB

  1. #include "pch.h"
  2. #include "precomp.h"
  3. typedef ULONG64 POINTER;
  4. //
  5. // Port processing irp means the port driver is currently executing
  6. // instructions to complete the irp. The irp is NOT waiting for
  7. // resources on any queue.
  8. //
  9. #define RaidPortProcessingIrp (0xA8)
  10. //
  11. // Pending resources is when the irp is in an IO queue awaiting
  12. // resources.
  13. //
  14. #define RaidPendingResourcesIrp (0xA9)
  15. //
  16. // The irp takes on state Miniport Processing while the miniport has
  17. // control over the irp. That is, between the time we call HwStartIo
  18. // and when the miniport calls ScsiPortNotification with a completion
  19. // status for the irp.
  20. //
  21. #define RaidMiniportProcessingIrp (0xAA)
  22. //
  23. // The irp takes on the Pending Completion state when it is moved to
  24. // the completed list.
  25. //
  26. #define RaidPendingCompletionIrp (0xAB)
  27. //
  28. // We set the irp state to Completed just before we call IoCompleteRequest
  29. // for the irp.
  30. //
  31. #define RaidCompletedIrp (0xAC)
  32. //#define XRB_SIGNATURE (0x1F2E3D4CUL)
  33. #define ARRAY_COUNT(Array) (sizeof(Array)/sizeof(Array[0]))
  34. ULONG Verbose = 0;
  35. PCHAR DeviceStateTable [] = {
  36. "Not Present", // not present
  37. "Working", // working
  38. "Stopped", // stopped
  39. "P-Stop", // pending stop
  40. "P-Remove", // pending remove
  41. "Surprise", // surprise remove
  42. "Removed", // removed
  43. "Invalid" // invalid state
  44. };
  45. PCHAR SystemPowerTable [] = {
  46. "Unspecified",
  47. "Working",
  48. "Sleeping1",
  49. "Sleeping2",
  50. "Sleeping3",
  51. "Hibernate",
  52. "Shutdown",
  53. "Maximum",
  54. "Invalid"
  55. };
  56. PCHAR DevicePowerTable [] = {
  57. "Unspecified",
  58. "D0",
  59. "D1",
  60. "D2",
  61. "D3",
  62. "Maximum",
  63. "Invalid"
  64. };
  65. char *SCSI6byteOpCode[] = { /* 0x00 - 0x1E */
  66. "SCSI/TEST UNT RDY",
  67. "SCSI/REZERO UNIT ",
  68. "SCSI/REQ BLK ADDR",
  69. "SCSI/REQ SENSE ",
  70. "SCSI/FORMAT UNIT ",
  71. "SCSI/RD BLK LMTS ",
  72. "SCSI/NO OPCODE ",
  73. "SCSI/REASSGN BLKS",
  74. "SCSI/READ (06) ",
  75. "SCSI/INVALID ",
  76. "SCSI/WRITE (06) ",
  77. "SCSI/SEEK (06) ",
  78. "SCSI/SEEK BLOCK ",
  79. "SCSI/PARTITION ",
  80. "SCSI/NO OPCODE ",
  81. "SCSI/READ REVERSE",
  82. "SCSI/WRTE FILEMKS",
  83. "SCSI/SPACE ",
  84. "SCSI/INQUIRY ",
  85. "SCSI/VERIFY (06) ",
  86. "SCSI/RECVR BUFFRD",
  87. "SCSI/MODE SEL(06)",
  88. "SCSI/RESERVE UNIT",
  89. "SCSI/RELEASE UNIT",
  90. "SCSI/COPY ",
  91. "SCSI/ERASE ",
  92. "SCSI/MOD SNSE(06)",
  93. "SCSI/STRT/STP UNT",
  94. "SCSI/RECV DIAGNOS",
  95. "SCSI/SEND DIAGNOS",
  96. "SCSI/MEDIUM REMVL"
  97. };
  98. char *SCSI10byteOpCode[] = { /* 0x23 - 0x5F */
  99. "SCSI/RD FRMTD CAP",
  100. "SCSI/NOP ",
  101. "SCSI/READ CAP ",
  102. "SCSI/NOP ",
  103. "SCSI/NOP ",
  104. "SCSI/READ (10) ",
  105. "SCSI/NO OPCODE ",
  106. "SCSI/WRITE (10) ",
  107. "SCSI/SEEK (10) ",
  108. "SCSI/NOP ",
  109. "SCSI/NOP ",
  110. "SCSI/WRT&VRF (10)",
  111. "SCSI/VERIFY (10) ",
  112. "SCSI/SC DT H (10)",
  113. "SCSI/SC DT E (10)",
  114. "SCSI/SC DT L (10)",
  115. "SCSI/ST LMTS (10)",
  116. "SCSI/PRE-FETCH ",
  117. "SCSI/SYNC CACHE",
  118. "SCSI/LCK/UN CACHE",
  119. "SCSI/RD DF D (10)",
  120. "SCSI/NO OPCODE ",
  121. "SCSI/COMPARE ",
  122. "SCSI/CPY & VERIFY",
  123. "SCSI/WRT DAT BUFF",
  124. "SCSI/RD DAT BUFF ",
  125. "SCSI/NO OPCODE ",
  126. "SCSI/READ LONG ",
  127. "SCSI/WRITE LONG ",
  128. "SCSI/CHGE DEF ",
  129. "SCSI/RD SUB-CHNL ",
  130. "SCSI/READ TOC ",
  131. "SCSI/READ HEADER ",
  132. "SCSI/PLY AUD (10)",
  133. "SCSI/GET CONFIG ",
  134. "SCSI/PLY AUD MSF ",
  135. "SCSI/PLY TRK INDX",
  136. "SCSI/PLY TRK REL ",
  137. "SCSI/GET EVT STAT",
  138. "SCSI/PAUSE/RESUME",
  139. "SCSI/LOG SELECT ",
  140. "SCSI/LOG SENSE ",
  141. "SCSI/STP/PLY SCAN",
  142. "SCSI/NO OPCODE ",
  143. "SCSI/NO OPCODE ",
  144. "SCSI/RD DSK INFO ",
  145. "SCSI/RD TRK INFO ",
  146. "SCSI/RSRV TRCK RZ",
  147. "SCSI/SND OPC INFO",
  148. "SCSI/MOD SEL (10)",
  149. "SCSI/NO OPCODE ",
  150. "SCSI/NO OPCODE ",
  151. "SCSI/NO OPCODE ",
  152. "SCSI/NO OPCODE ",
  153. "SCSI/MOD SNS (10)",
  154. "SCSI/CLS TRCK SES",
  155. "SCSI/RD BUFF CAP ",
  156. "SCSI/SND CUE SHT ",
  157. "SCSI/PRS RSRV IN ",
  158. "SCSI/PRS RSRV OUT"
  159. };
  160. char *SCSI12byteOpCode[] = { /* 0xA0 - 0xBF, 0xE7 */
  161. "SCSI/REPORT LUNS ",
  162. "SCSI/BLANK ",
  163. "SCSI/NO OPCODE ",
  164. "SCSI/SEND KEY ",
  165. "SCSI/REPORT KEY ",
  166. "SCSI/MOVE MEDIUM ",
  167. "SCSI/LD/UNLD SLOT",
  168. "SCSI/SET RD AHEAD",
  169. "SCSI/NO OPCODE ",
  170. "SCSI/NO OPCODE ",
  171. "SCSI/NO OPCODE ",
  172. "SCSI/NO OPCODE ",
  173. "SCSI/NO OPCODE ",
  174. "SCSI/RD DVD STRUC",
  175. "SCSI/NO OPCODE ",
  176. "SCSI/NO OPCODE ",
  177. "SCSI/NO OPCODE ",
  178. "SCSI/NO OPCODE ",
  179. "SCSI/NO OPCODE ",
  180. "SCSI/NO OPCODE ",
  181. "SCSI/NO OPCODE ",
  182. "SCSI/REQ VOL ELMT",
  183. "SCSI/SEND VOL TAG",
  184. "SCSI/NO OPCODE ",
  185. "SCSI/RD ELMT STAT",
  186. "SCSI/READ CD MSF ",
  187. "SCSI/SCAN CD ",
  188. "SCSI/SET CD SPEED",
  189. "SCSI/PLAY CD ",
  190. "SCSI/MECHNSM STAT",
  191. "SCSI/READ CD ",
  192. "SCSI/SND DVD STRC",
  193. "SCSI/INIT ELM RNG", /* 0xE7 */
  194. };
  195. PCHAR SrbFunctions [] = {
  196. "EXECUTE SCSI ", // 0x00
  197. "CLAIM DEVICE ", // 0x01
  198. "IO CONTROL ", // 0x02
  199. "RECEIVE EVENT ", // 0x03
  200. "RELEASE QUEUE ", // 0x04
  201. "ATTACH DEVICE ", // 0x05
  202. "RELEASE DEVICE ", // 0x06
  203. "SHUTDOWN ", // 0x07
  204. "FLUSH ", // 0x08
  205. "NOP ", // 0x09
  206. "NOP ", // 0x0A
  207. "NOP ", // 0x0B
  208. "NOP ", // 0x0C
  209. "NOP ", // 0x0D
  210. "NOP ", // 0x0E
  211. "NOP ", // 0x0F
  212. "ABORT COMMAND ", // 0x10
  213. "RELEASE RECOVERY ", // 0x11
  214. "RESET BUS ", // 0x12
  215. "RESET DEVICE ", // 0x13
  216. "TERMINATE IO ", // 0x14
  217. "FLUSH QUEUE ", // 0x15
  218. "REMOVE DEVICE ", // 0x16
  219. "WMI ", // 0x17
  220. "LOCK QUEUE ", // 0x18
  221. "UNLOCK QUEUE ", // 0x19
  222. "NOP ", // 0x1A
  223. "NOP ", // 0x1B
  224. "NOP ", // 0x1C
  225. "NOP ", // 0x1D
  226. "NOP ", // 0x1E
  227. "NOP ", // 0x1F
  228. "RESET LUN " // 0x20
  229. };
  230. VOID
  231. FixString (
  232. PSZ Id
  233. )
  234. {
  235. ULONG Pos;
  236. Pos = strlen(Id);
  237. if (Pos > 0) {
  238. Pos--;
  239. }
  240. while ( (Pos > 0) && (Id[Pos] == ' ') ) {
  241. Id[Pos]='\0';
  242. Pos--;
  243. }
  244. }
  245. UCHAR
  246. GetIoState(
  247. IN POINTER Xrb
  248. )
  249. {
  250. POINTER Irp;
  251. ULONG Offset;
  252. UCHAR State;
  253. POINTER ExEntry;
  254. GetFieldValue (Xrb,
  255. "storport!EXTENDED_REQUEST_BLOCK",
  256. "Irp",
  257. Irp);
  258. GetFieldOffset ("storport!IRP",
  259. "Tail.Overlay.DeviceQueueEntry",
  260. &Offset);
  261. ExEntry = Irp + Offset;
  262. GetFieldValue (ExEntry,
  263. "storport!EX_DEVICE_QUEUE_ENTRY",
  264. "State",
  265. State);
  266. return State;
  267. }
  268. BOOLEAN
  269. GetScsiCommand(
  270. IN POINTER Srb,
  271. OUT PUCHAR Command
  272. )
  273. {
  274. ULONG Offset;
  275. *Command = 0xFF;
  276. GetFieldOffset("storport!SCSI_REQUEST_BLOCK", "Cdb", &Offset);
  277. ReadMemory(Srb + Offset, Command, sizeof (Command), NULL);
  278. return TRUE;
  279. }
  280. BOOLEAN
  281. VerifyXrb(
  282. IN POINTER Xrb
  283. )
  284. {
  285. ULONG Signature;
  286. GetFieldValue (Xrb,
  287. "storport!EXTENDED_REQUEST_BLOCK",
  288. "Signature",
  289. Signature);
  290. return (Signature == XRB_SIGNATURE);
  291. }
  292. VOID
  293. GetUnitProductInfo (
  294. IN ULONG64 UnitExtension,
  295. PSZ VendorId,
  296. PSZ ProductId
  297. )
  298. {
  299. ULONG64 UnitInfoPtr;
  300. ULONG64 UnitInfo;
  301. ULONG offset;
  302. ZeroMemory(VendorId, 9);
  303. ZeroMemory(ProductId, 17);
  304. if (!GetFieldOffset("storport!RAID_UNIT_EXTENSION", "Identity", &offset)) {
  305. UnitInfoPtr = UnitExtension + offset;
  306. if (!GetFieldOffset("storport!STOR_SCSI_IDENTITY", "InquiryData", &offset)) {
  307. UnitInfoPtr = UnitInfoPtr + offset;
  308. ReadPointer(UnitInfoPtr, &UnitInfo);
  309. if (GetFieldData(UnitInfo, "storport!INQUIRYDATA", "VendorId", 8, VendorId)) {
  310. //dprintf("ERROR: Unable to retrieve VendorId field\n");
  311. }
  312. if (GetFieldData(UnitInfo, "storport!INQUIRYDATA", "ProductId", 16, ProductId)) {
  313. //dprintf("ERROR: Unable to retrieve ProductId field\n");
  314. }
  315. FixString(VendorId);
  316. FixString(ProductId);
  317. }
  318. else {
  319. dprintf("ERROR: Unable to retrieve InquiryData offset\n");
  320. }
  321. }
  322. else {
  323. dprintf("ERROR: Unable to retrieve Identity offset\n");
  324. }
  325. }
  326. VOID
  327. PrintAddressList (
  328. IN ULONG64 Address
  329. )
  330. {
  331. if (IsPtr64()) {
  332. dprintf("%16.16x ", Address);
  333. }
  334. else {
  335. dprintf("%8.8x ", Address);
  336. }
  337. }
  338. VOID
  339. GetScsiCommandString(
  340. IN UCHAR Command,
  341. IN PCHAR Buffer
  342. )
  343. {
  344. UCHAR Index;
  345. if ((Command >= 0x00) && (Command <= 0x1E)) {
  346. Index = Command;
  347. sprintf(Buffer, "%s", SCSI6byteOpCode[Index]);
  348. return;
  349. }
  350. if ((Command >= 0x23) && (Command <= 0x5F)) {
  351. Index = Command - 0x23;
  352. sprintf(Buffer, "%s", SCSI10byteOpCode[Index]);
  353. return;
  354. }
  355. if ((Command >= 0xA0) && (Command <= 0xBF)) {
  356. Index = Command - 0xA0;
  357. sprintf(Buffer, "%s", SCSI12byteOpCode[Index]);
  358. return;
  359. }
  360. if (Command == 0xE7) {
  361. sprintf(Buffer, "%s", SCSI12byteOpCode[32]);
  362. return;
  363. }
  364. sprintf(Buffer, "NO OPCODE ");
  365. }
  366. VOID
  367. PrintAddress (
  368. IN PSZ Name,
  369. IN ULONG64 Address
  370. )
  371. {
  372. if (IsPtr64()) {
  373. dprintf("%s %16.16x ", Name, Address);
  374. }
  375. else {
  376. dprintf("%s %8.8x ", Name, Address);
  377. }
  378. }
  379. ULONG64
  380. ContainingRecord (
  381. IN ULONG64 Object,
  382. IN PSZ Type,
  383. IN PSZ Field
  384. )
  385. {
  386. ULONG offset;
  387. if (GetFieldOffset(Type, Field, &offset)) {
  388. return 0;
  389. }
  390. else {
  391. return (Object - offset);
  392. }
  393. }
  394. BOOLEAN
  395. CheckRaidObject (
  396. IN ULONG64 Object,
  397. IN RAID_OBJECT_TYPE Type
  398. )
  399. {
  400. RAID_OBJECT_TYPE RetType;
  401. if (GetFieldValue(Object, "storport!RAID_COMMON_EXTENSION", "ObjectType", RetType )) {
  402. return FALSE;
  403. }
  404. else if (Type != RetType) {
  405. return FALSE;
  406. }
  407. return TRUE;
  408. }
  409. BOOLEAN
  410. IsDeviceObject (
  411. IN ULONG64 address
  412. )
  413. {
  414. CSHORT Type;
  415. if (GetFieldValue(address, "storport!DEVICE_OBJECT", "Type", Type)) {
  416. return FALSE;
  417. }
  418. else {
  419. return (Type == IO_TYPE_DEVICE);
  420. }
  421. }
  422. ULONG64
  423. GetExtension (
  424. IN ULONG64 address,
  425. IN RAID_OBJECT_TYPE Object
  426. )
  427. {
  428. ULONG64 Extension;
  429. ULONG64 DeviceObject;
  430. ULONG64 temp;
  431. ULONG offset;
  432. if (CheckRaidObject(address, Object)) {
  433. Extension = address;
  434. if (Object == RaidAdapterObject) {
  435. InitTypeRead(Extension, storport!RAID_ADAPTER_EXTENSION);
  436. }
  437. else if (Object == RaidUnitObject) {
  438. InitTypeRead(Extension, storport!RAID_UNIT_EXTENSION);
  439. }
  440. DeviceObject = ReadField(DeviceObject);
  441. if (IsDeviceObject(DeviceObject)) {
  442. if (GetFieldOffset("storport!DEVICE_OBJECT", "DeviceExtension", &offset)) {
  443. dprintf("ERROR: Unable to retrieve Device Extension offset\n");
  444. temp = 0;
  445. }
  446. else {
  447. ReadPointer(DeviceObject + offset, &temp);
  448. }
  449. if (temp == Extension) {
  450. return Extension;
  451. }
  452. }
  453. }
  454. DeviceObject = address;
  455. if (IsDeviceObject(DeviceObject)) {
  456. if (GetFieldOffset("storport!DEVICE_OBJECT", "DeviceExtension", &offset)) {
  457. dprintf("ERROR: Unable to retrieve Device Extension offset\n");
  458. Extension = 0;
  459. }
  460. else {
  461. ReadPointer(DeviceObject + offset, &Extension);
  462. }
  463. if (CheckRaidObject(Extension, Object)) {
  464. if (Object == RaidAdapterObject) {
  465. InitTypeRead(Extension, storport!RAID_ADAPTER_EXTENSION);
  466. }
  467. else if (Object == RaidUnitObject) {
  468. InitTypeRead(Extension, storport!RAID_UNIT_EXTENSION);
  469. }
  470. DeviceObject = ReadField(DeviceObject);
  471. if (DeviceObject == address) {
  472. return Extension;
  473. }
  474. }
  475. }
  476. else {
  477. dprintf("ERROR: Invalid Device Object\n");
  478. }
  479. return 0;
  480. }
  481. PCHAR
  482. DeviceStateToString (
  483. IN ULONG State
  484. )
  485. {
  486. if (State > 6) {
  487. return DeviceStateTable[7];
  488. }
  489. return DeviceStateTable[State];
  490. }
  491. PCHAR
  492. SystemPower (
  493. IN ULONG State
  494. )
  495. {
  496. if (State > 7) {
  497. return SystemPowerTable[8];
  498. }
  499. return SystemPowerTable[State];
  500. }
  501. PCHAR
  502. DevicePower (
  503. IN ULONG State
  504. )
  505. {
  506. if (State > 5) {
  507. return DevicePowerTable[6];
  508. }
  509. return DevicePowerTable[State];
  510. }
  511. PCHAR
  512. GetSrbFunction(
  513. IN UCHAR SrbFunctionCode
  514. )
  515. {
  516. if (SrbFunctionCode >= ARRAY_COUNT (SrbFunctions)) {
  517. return "Invalid SRB Function";
  518. }
  519. return SrbFunctions [SrbFunctionCode];
  520. }
  521. ULONG
  522. GetRemLockCount (
  523. IN ULONG64 Object,
  524. IN PSZ Type,
  525. IN PSZ Field
  526. )
  527. {
  528. ULONG64 address;
  529. ULONG offset;
  530. ULONG IOCount;
  531. IOCount = -1;
  532. if (!GetFieldOffset(Type, Field, &offset)) {
  533. address = Object + offset;
  534. if (!GetFieldOffset("storport!IO_REMOVE_LOCK", "Common", &offset)) {
  535. address = address + offset;
  536. GetFieldValue(address,"storport!IO_REMOVE_LOCK_COMMON_BLOCK", "IoCount", IOCount);
  537. }
  538. }
  539. return IOCount;
  540. }
  541. VOID
  542. dindentf(
  543. IN ULONG Depth
  544. )
  545. {
  546. ULONG i;
  547. for (i = 1; i <= Depth; i++) {
  548. dprintf(" ");
  549. }
  550. }
  551. VOID
  552. DumpQueuedRequests(
  553. IN POINTER DeviceQueue
  554. )
  555. {
  556. ULONG64 ListHead;
  557. ULONG64 NextRequest;
  558. ULONG64 Irp;
  559. ULONG64 StackLocation;
  560. ULONG64 Srb;
  561. ULONG offset;
  562. ULONG CommandLength;
  563. ULONG TimeOut;
  564. UCHAR ScsiCommand;
  565. UCHAR SrbFunction;
  566. CHAR ScsiCommandString[100];
  567. if (GetFieldOffset("storport!EXTENDED_DEVICE_QUEUE", "DeviceListHead", &offset)) {
  568. dprintf("ERROR: Unable to retrieve PendingQueue offset\n");
  569. return;
  570. }
  571. ListHead = DeviceQueue + offset;
  572. for (GetFieldValue(ListHead, "storport!LIST_ENTRY", "Flink", NextRequest); NextRequest != 0 && NextRequest != ListHead; GetFieldValue(NextRequest, "storport!LIST_ENTRY", "Flink", NextRequest)) {
  573. Irp = ContainingRecord(NextRequest, "storport!IRP", "Tail.Overlay.DeviceQueueEntry.DeviceListEntry");
  574. PrintAddressList(Irp);
  575. if (GetFieldOffset("storport!IRP", "Tail.Overlay.CurrentStackLocation", &offset)) {
  576. dprintf("ERROR: Unable to retrieve Current Stack Location offset\n");
  577. return;
  578. }
  579. StackLocation = Irp + offset;
  580. ReadPtr(StackLocation, &StackLocation);
  581. if (GetFieldOffset("storport!IO_STACK_LOCATION",
  582. "Parameters.Scsi.Srb", &offset)) {
  583. dprintf("ERROR: Unable to retrieve Srb offset\n");
  584. return;
  585. }
  586. Srb = StackLocation + offset;
  587. ReadPtr (Srb, &Srb);
  588. PrintAddressList(Srb);
  589. dprintf(" n/a ");
  590. GetFieldValue (Srb,
  591. "storport!SCSI_REQUEST_BLOCK",
  592. "Function",
  593. SrbFunction);
  594. if (SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) {
  595. GetScsiCommand (Srb, &ScsiCommand),
  596. GetScsiCommandString (ScsiCommand, ScsiCommandString);
  597. } else {
  598. sprintf (ScsiCommandString,
  599. "%s ",
  600. GetSrbFunction (SrbFunction));
  601. }
  602. dprintf ("%s ", ScsiCommandString);
  603. InitTypeRead(Irp, storport!IRP);
  604. PrintAddressList(ReadField(MdlAddress));
  605. dprintf(" n/a ");
  606. GetFieldValue(Srb,
  607. "storport!SCSI_REQUEST_BLOCK",
  608. "TimeOutValue",
  609. TimeOut);
  610. dprintf("%d\n", TimeOut);
  611. }
  612. }
  613. #if 0
  614. VOID
  615. ReadFlink(
  616. IN ULONG64 ListEntry,
  617. OUT PULONG64 NextListEntry
  618. )
  619. {
  620. GetFieldValue (ListEntry, "nt!LIST_ENTRY", "Flink", *NextListEntry);
  621. }
  622. VOID
  623. IteratePendingRequests(
  624. IN ULONG64 DeviceQueue,
  625. IN ULONG Flags,
  626. IN PFN Callback
  627. )
  628. {
  629. ULONG64 ListHead;
  630. ULONG64 NextRequest;
  631. ULONG64 Irp;
  632. ULONG64 StackLocation;
  633. ULONG64 Srb;
  634. ULONG offset;
  635. ULONG CommandLength;
  636. ULONG TimeOut;
  637. UCHAR Command;
  638. UCHAR SrbFunction;
  639. if (GetFieldOffset("storport!EXTENDED_DEVICE_QUEUE", "DeviceListHead", &offset)) {
  640. dprintf("ERROR: Unable to retrieve PendingQueue offset\n");
  641. return;
  642. }
  643. ListHead = DeviceQueue + offset;
  644. for (ReadFlink (ListHead, NextRequest);
  645. NextRequest != 0 && NextRequest != ListHead;
  646. ReadFlink (NextRequest, NextRequest)) {
  647. Irp = ContainingRecord (
  648. NextRequest,
  649. "storport!IRP",
  650. "Tail.Overlay.DeviceQueueEntry.DeviceListEntry");
  651. Callback (Irp);
  652. }
  653. }
  654. #endif
  655. ULONG
  656. DumpRequests (
  657. IN POINTER UnitExtension,
  658. IN UCHAR RequestedState
  659. )
  660. /*++
  661. Routine Description:
  662. Print out list of outstanding or pending requests depending on value
  663. of RequestedState parameter.
  664. Arguments:
  665. UnitExtension - Debuggee-Pointer to unit extension.
  666. RequestedState - Supplies the requested state to dump, must be either:
  667. RaidMiniportProcessingIrp for Outstanding requests.
  668. RaidPendingCompletionIrp for Completing requests.
  669. Return Value:
  670. Number of requests dumped.
  671. --*/
  672. {
  673. POINTER address;
  674. POINTER NextRequest;
  675. POINTER Xrb;
  676. POINTER Srb;
  677. ULONG offset;
  678. ULONG TimeOut;
  679. UCHAR SrbFunction;
  680. UCHAR ScsiCommand;
  681. CHAR ScsiCommandString[100];
  682. UCHAR IoState;
  683. ULONG Count;
  684. Count = 0;
  685. if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "PendingQueue", &offset)) {
  686. dprintf("ERROR: Unable to retrieve PendingQueue offset\n");
  687. return 0;
  688. }
  689. address = UnitExtension + offset;
  690. if (GetFieldOffset("storport!STOR_EVENT_QUEUE", "List", &offset)) {
  691. dprintf("ERROR: Unable to retrieve PendingQueue offset\n");
  692. return 0;
  693. }
  694. address += offset;
  695. for (GetFieldValue(address, "storport!LIST_ENTRY", "Flink", NextRequest);
  696. NextRequest != 0 && NextRequest != address;
  697. GetFieldValue(NextRequest, "storport!LIST_ENTRY", "Flink", NextRequest)) {
  698. Xrb = ContainingRecord (NextRequest,
  699. "storport!EXTENDED_REQUEST_BLOCK",
  700. "PendingLink.NextLink");
  701. if (Verbose) {
  702. dprintf ("VERBOSE: Xrb %p\n", Xrb);
  703. }
  704. InitTypeRead(Xrb, storport!EXTENDED_REQUEST_BLOCK);
  705. if (!VerifyXrb (Xrb)) {
  706. dprintf ("ERROR: Request %p does not have an XRB signature!\n",
  707. Xrb);
  708. continue;
  709. }
  710. IoState = GetIoState (Xrb);
  711. if (Verbose) {
  712. dprintf ("VERBOSE: Irp state is %x\n", (ULONG)IoState);
  713. }
  714. if (IoState != RequestedState) {
  715. continue;
  716. }
  717. Count++;
  718. GetFieldValue (Xrb,
  719. "storport!EXTENDED_REQUEST_BLOCK",
  720. "Srb",
  721. Srb);
  722. PrintAddressList(ReadField(Irp));
  723. PrintAddressList(Srb);
  724. PrintAddressList(Xrb);
  725. GetFieldValue (Srb,
  726. "storport!SCSI_REQUEST_BLOCK",
  727. "Function",
  728. SrbFunction);
  729. if (SrbFunction == SRB_FUNCTION_EXECUTE_SCSI) {
  730. GetScsiCommand (Srb, &ScsiCommand);
  731. GetScsiCommandString (ScsiCommand, ScsiCommandString);
  732. } else {
  733. sprintf (ScsiCommandString,
  734. "%s ",
  735. GetSrbFunction (SrbFunction));
  736. }
  737. dprintf ("%s ", ScsiCommandString);
  738. InitTypeRead(Xrb, storport!EXTENDED_REQUEST_BLOCK);
  739. PrintAddressList (ReadField(Mdl));
  740. PrintAddressList (ReadField(SgList));
  741. GetFieldValue(Srb,
  742. "Storport!SCSI_REQUEST_BLOCK",
  743. "TimeOutValue",
  744. TimeOut);
  745. dprintf("%d\n", TimeOut);
  746. }
  747. return Count;
  748. }
  749. ULONG
  750. DumpOutstandingRequests(
  751. IN POINTER UnitExtension
  752. )
  753. {
  754. return DumpRequests (UnitExtension, RaidMiniportProcessingIrp);
  755. }
  756. ULONG
  757. DumpCompletedRequests(
  758. IN POINTER UnitExtension
  759. )
  760. {
  761. return DumpRequests (UnitExtension, RaidPendingCompletionIrp);
  762. }
  763. VOID
  764. PrintRequestListHeader(
  765. IN PCHAR Title
  766. )
  767. {
  768. dprintf ("\n\n[%s]\n\n", Title);
  769. dprintf("IRP SRB XRB Command MDL "
  770. "SGList Timeout\n");
  771. dprintf("----------------------------------------------------------"
  772. "-----------------\n");
  773. }
  774. VOID
  775. DumpUnit (
  776. IN ULONG64 address,
  777. IN ULONG Level,
  778. IN ULONG Depth
  779. )
  780. {
  781. ULONG64 UnitExtension;
  782. ULONG64 VirtualBase;
  783. ULONG64 QueueTagList;
  784. ULONG64 IoQueue;
  785. ULONG64 DeviceQueue;
  786. ULONG64 IoGateway;
  787. ULONG64 EventQ;
  788. ULONG offset;
  789. ULONG RemLock_IOCount;
  790. UCHAR VendorId[9] = {0};
  791. UCHAR ProductId[17] = {0};
  792. PSZ SlowLock;
  793. UnitExtension = GetExtension(address, RaidUnitObject);
  794. if (UnitExtension == 0) {
  795. dprintf("ERROR: Unable to retrieve Unit Extension address\n");
  796. return;
  797. }
  798. InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION);
  799. if (Level == 0) {
  800. GetUnitProductInfo(UnitExtension, VendorId, ProductId);
  801. dindentf(Depth);
  802. if (!GetFieldOffset("storport!RAID_UNIT_EXTENSION", "Address", &offset)) {
  803. InitTypeRead(UnitExtension + offset, storport!STOR_SCSI_ADDRESS);
  804. }
  805. else {
  806. dprintf("ERROR: Unable to retrieve STOR_SCSI_ADDRESS structure offset\n");
  807. }
  808. dprintf("%-10.10s %-10.10s %2d %2d %2d ",
  809. VendorId,
  810. ProductId,
  811. (ULONG)ReadField(PathId),
  812. (ULONG)ReadField(TargetId),
  813. (ULONG)ReadField(Lun));
  814. InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION);
  815. PrintAddressList(ReadField(DeviceObject));
  816. PrintAddressList(UnitExtension);
  817. if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "IoQueue", &offset)) {
  818. dprintf("ERROR: Unable to retrieve IoQueue offset\n");
  819. return;
  820. }
  821. IoQueue = UnitExtension + offset;
  822. if (GetFieldOffset("storport!IO_QUEUE", "DeviceQueue", &offset)) {
  823. dprintf("ERROR: Unable to retreive DeviceQueue offset\n");
  824. return;
  825. }
  826. DeviceQueue = IoQueue + offset;
  827. InitTypeRead(DeviceQueue, storport!EXTENDED_DEVICE_QUEUE);
  828. dprintf("%3d %3d %2d ",
  829. (ULONG)ReadField(DeviceRequests),
  830. (ULONG)ReadField(OutstandingRequests),
  831. (ULONG)ReadField(ByPassRequests));
  832. InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION);
  833. dprintf("%s\n", DeviceStateToString((ULONG)ReadField(DeviceState)));
  834. } else {
  835. ULONG OutstandingCount;
  836. ULONG Count;
  837. dprintf("UNIT\n");
  838. Depth++;
  839. dindentf(Depth);
  840. PrintAddress("DO", ReadField(DeviceObject));
  841. PrintAddress("Ext", UnitExtension);
  842. PrintAddress("Adapter", ReadField(Adapter));
  843. dprintf("%s\n", DeviceStateToString((ULONG)ReadField(DeviceState)));
  844. GetUnitProductInfo(UnitExtension, VendorId, ProductId);
  845. dindentf(Depth);
  846. if (!GetFieldOffset("storport!RAID_UNIT_EXTENSION", "Address", &offset)) {
  847. InitTypeRead(UnitExtension + offset, storport!STOR_SCSI_ADDRESS);
  848. } else {
  849. dprintf("ERROR: Unable to retrieve STOR_SCSI_ADDRESS structure offset\n");
  850. }
  851. dprintf("Vendor: %s Product: %s SCSI ID: (%d, %d, %d) \n", VendorId, ProductId, (ULONG)ReadField(PathId), (ULONG)ReadField(TargetId), (ULONG)ReadField(Lun));
  852. InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION);
  853. dindentf(Depth);
  854. dprintf("%s %s %s %s \n", (ReadField(Flags.DeviceClaimed) ? "Claimed" : ""), (ReadField(Flags.QueueFrozen) ? "Frozen" : ""), (ReadField(Flags.QueueLocked) ? "Locked" : ""), (ReadField(Flags.Enumerated) ? "Enumerated" : ""));
  855. InitTypeRead(UnitExtension, storport!RAID_UNIT_EXTENSION);
  856. SlowLock = ReadField(SlowLock) ? "Held" : "Free";
  857. RemLock_IOCount = GetRemLockCount(UnitExtension, "storport!RAID_UNIT_EXTENSION", "RemoveLock");
  858. dindentf(Depth);
  859. dprintf("SlowLock %s RemLock %d PageCount %d\n", SlowLock, RemLock_IOCount, (ULONG)ReadField(PagingPathCount));
  860. VirtualBase = ReadField(SrbExtensionRegion.VirtualBase);
  861. dindentf(Depth);
  862. PrintAddress("SrbExtensionRegion (Virtual Base)", VirtualBase);
  863. dprintf("(%d bytes)\n", (ULONG)ReadField(SrbExtensionRegion.Length));
  864. if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "TagList", &offset)) {
  865. dprintf("ERROR: Unable to retrieve TagList offset\n");
  866. return;
  867. }
  868. QueueTagList = UnitExtension + offset;
  869. dindentf(Depth);
  870. PrintAddress("QueueTagList:", QueueTagList);
  871. dprintf("(%d of %d used)\n", (ULONG)ReadField(TagList.OutstandingTags), (ULONG)ReadField(TagList.Count));
  872. if (GetFieldOffset("storport!RAID_UNIT_EXTENSION", "IoQueue", &offset)) {
  873. dprintf("ERROR: Unable to retrieve IoQueue offset\n");
  874. }
  875. IoQueue = UnitExtension + offset;
  876. if (GetFieldOffset("storport!IO_QUEUE", "DeviceQueue", &offset)) {
  877. dprintf("ERROR: Unable to retreive DeviceQueue offset\n");
  878. }
  879. DeviceQueue = IoQueue + offset;
  880. if (GetFieldOffset ("storport!RAID_UNIT_EXTENSION", "PendingQueue", &offset)) {
  881. dprintf ("ERROR: Unable to retrieve PendingQueue offset\n");
  882. }
  883. EventQ = UnitExtension + offset;
  884. InitTypeRead (EventQ, storport!STOR_EVENT_QUEUE);
  885. dindentf(Depth);
  886. dprintf("Outstanding: Head %p Tail %p Timeout %d\n",
  887. ReadField (List.Flink),
  888. ReadField (List.Blink),
  889. ReadField (Timeout));
  890. InitTypeRead(DeviceQueue, storport!EXTENDED_DEVICE_QUEUE);
  891. dindentf(Depth);
  892. PrintAddress("DeviceQueue", DeviceQueue);
  893. dprintf("Depth: %d ", (ULONG)ReadField(Depth));
  894. dprintf("Status: %s \n",
  895. (ReadField(Frozen) ? "Frozen" : "Not Frozen"));
  896. IoGateway = ReadField(Gateway);
  897. InitTypeRead(IoGateway, storport!STOR_IO_GATEWAY);
  898. dindentf(Depth);
  899. dprintf("IO Gateway: Busy Count %d Pause Count %d\n",
  900. (ULONG)ReadField(BusyCount),
  901. (ULONG)ReadField(PauseCount));
  902. InitTypeRead(DeviceQueue, storport!EXTENDED_DEVICE_QUEUE);
  903. dindentf(Depth);
  904. OutstandingCount = (ULONG)ReadField (OutstandingRequests);
  905. dprintf("Requests: Outstanding %d Device %d ByPass %d\n",
  906. OutstandingCount,
  907. (ULONG)ReadField(DeviceRequests),
  908. (ULONG)ReadField(ByPassRequests));
  909. PrintRequestListHeader ("Queued Requests");
  910. DumpQueuedRequests (DeviceQueue);
  911. PrintRequestListHeader ("Outstanding Requests");
  912. Count = DumpOutstandingRequests (UnitExtension);
  913. PrintRequestListHeader ("Completed Requests");
  914. Count += DumpCompletedRequests (UnitExtension);
  915. if (Count < OutstandingCount) {
  916. dprintf ("\n\nNOTE: %d request(s) not found on the completed or outstanding list. The\n"
  917. " requests are probably being transferred from one list to another. On an\n"
  918. " MP machine this could be happening on a separate processor.\n",
  919. OutstandingCount - Count);
  920. } else if (Count > OutstandingCount) {
  921. dprintf ("ERROR: %d counted requests > %d outstanding requests\n\n",
  922. Count, OutstandingCount);
  923. }
  924. dprintf ("\n");
  925. }
  926. }
  927. VOID
  928. ListAdapterUnits(
  929. IN ULONG64 AdapterExtension,
  930. IN ULONG Level,
  931. IN ULONG Depth
  932. )
  933. {
  934. ULONG64 Units;
  935. ULONG64 NextUnit;
  936. ULONG64 UnitExtension;
  937. ULONG offset;
  938. if (!GetFieldOffset("storport!RAID_ADAPTER_EXTENSION", "UnitList.List", &offset)) {
  939. Units = AdapterExtension + offset;
  940. }
  941. else {
  942. dprintf("ERROR: Unable to retrieve Unit List offset\n");
  943. return;
  944. }
  945. for (GetFieldValue(Units, "storport!LIST_ENTRY", "Flink", NextUnit); NextUnit != 0 && NextUnit != Units; GetFieldValue(NextUnit, "storport!LIST_ENTRY", "Flink", NextUnit)) {
  946. UnitExtension = ContainingRecord(NextUnit, "storport!RAID_UNIT_EXTENSION", "NextUnit");
  947. if (!CheckRaidObject(UnitExtension, RaidUnitObject)) {
  948. dprintf("ERROR: Invalid RAID unit object\n");
  949. return;
  950. }
  951. DumpUnit(UnitExtension, 0, Depth);
  952. }
  953. }
  954. VOID
  955. DumpAdapter (
  956. IN ULONG64 address,
  957. IN ULONG Level,
  958. IN ULONG Depth
  959. )
  960. {
  961. ULONG64 AdapterExtension;
  962. ULONG64 DriverNameBuffer;
  963. ULONG64 DriverNameLength;
  964. ULONG64 DriverObject;
  965. ULONG64 MiniportObject;
  966. ULONG64 HwInitData;
  967. ULONG64 HwDeviceExt;
  968. CHAR NameBuffer[512] = {0};
  969. PSZ SlowLock;
  970. ULONG RemLock;
  971. ULONG offset;
  972. ULONG debugtemp;
  973. ULONG debugoffset;
  974. AdapterExtension = GetExtension(address, RaidAdapterObject);
  975. if (AdapterExtension == 0) {
  976. dprintf("ERROR: Unable to retrieve Adapter Extension address\n");
  977. return;
  978. }
  979. InitTypeRead (AdapterExtension, storport!RAID_ADAPTER_EXTENSION);
  980. if (Level == 0) {
  981. if (GetFieldValue(ReadField(Driver), "storport!RAID_DRIVER_EXTENSION", "DriverObject", DriverObject)) {
  982. dprintf("ERROR: Unable to retrieve Driver Extension address\n");
  983. return;
  984. }
  985. GetFieldValue(DriverObject, "storport!DRIVER_OBJECT", "DriverName.Buffer", DriverNameBuffer);
  986. GetFieldValue(DriverObject, "storport!DRIVER_OBJECT", "DriverName.Length", DriverNameLength);
  987. DriverNameLength = min(DriverNameLength, sizeof(NameBuffer)/sizeof(WCHAR)-1);
  988. ReadMemory(DriverNameBuffer, (PVOID)NameBuffer, (ULONG)DriverNameLength*sizeof(WCHAR), NULL);
  989. dprintf("%-20.20S ", NameBuffer);
  990. PrintAddressList(ReadField(DeviceObject));
  991. PrintAddressList(AdapterExtension);
  992. dprintf(" %s\n", DeviceStateToString((ULONG)ReadField(DeviceState)));
  993. } else {
  994. dprintf("ADAPTER\n");
  995. Depth++;
  996. dindentf(Depth);
  997. PrintAddress("DO", ReadField(DeviceObject));
  998. PrintAddress("Ext", AdapterExtension);
  999. PrintAddress("Driver", ReadField(Driver));
  1000. dprintf("%s\n", DeviceStateToString((ULONG)ReadField(DeviceState)));
  1001. dindentf(Depth);
  1002. PrintAddress("LDO", ReadField(LowerDeviceObject));
  1003. PrintAddress("PDO", ReadField(PhysicalDeviceObject));
  1004. dprintf("\n");
  1005. SlowLock = ReadField(SlowLock) ? "Held" : "Free";
  1006. RemLock = GetRemLockCount(AdapterExtension, "storport!RAID_ADAPTER_EXTENSION", "RemoveLock");
  1007. dindentf(Depth);
  1008. dprintf("SlowLock %s RemLock %d \n", SlowLock, RemLock);
  1009. dindentf(Depth);
  1010. dprintf("Power: %s %s %s\n",
  1011. SystemPower((ULONG)ReadField(Power.SystemState)),
  1012. DevicePower((ULONG)ReadField(Power.DeviceState)),
  1013. (ReadField(IoModel) == StorSynchronizeFullDuplex ? "Full Duplex" : "Half Duplex"));
  1014. dindentf(Depth);
  1015. dprintf("Bus %d Slot %d ", (ULONG)ReadField(BusNumber), (ULONG)ReadField(SlotNumber));
  1016. PrintAddress("DMA", ReadField(Dma.DmaAdapter));
  1017. PrintAddress("Interrupt", ReadField(Interrupt));
  1018. dprintf("\n");
  1019. dindentf(Depth);
  1020. PrintAddress("ResourceList: Allocated", ReadField(ResourceList.AllocatedResources));
  1021. PrintAddress("Translated", ReadField(ResourceList.TranslatedResources));
  1022. dprintf("\n");
  1023. dindentf(Depth);
  1024. dprintf("Gateway: Outstanding %d Lower %d High %d\n",
  1025. (ULONG)ReadField(Gateway.Outstanding),
  1026. (ULONG)ReadField(Gateway.LowWaterMark),
  1027. (ULONG)ReadField(Gateway.HighWaterMark));
  1028. GetFieldOffset("storport!RAID_ADAPTER_EXTENSION", "Miniport", &offset);
  1029. MiniportObject = AdapterExtension + offset;
  1030. InitTypeRead(MiniportObject, storport!RAID_MINIPORT);
  1031. HwInitData = ReadField(HwInitializationData);
  1032. GetFieldOffset("storport!RAID_MINIPORT", "PortConfiguration", &offset);
  1033. dindentf(Depth);
  1034. PrintAddress("PortConfigInfo", (MiniportObject + offset));
  1035. dprintf("\n");
  1036. dindentf(Depth);
  1037. PrintAddress("HwInit", HwInitData);
  1038. HwDeviceExt = ReadField(PrivateDeviceExt);
  1039. if (!GetFieldOffset("storport!RAID_HW_DEVICE_EXT", "HwDeviceExtension", &offset)) {
  1040. HwDeviceExt = HwDeviceExt + offset;
  1041. }
  1042. else {
  1043. HwDeviceExt = 0;
  1044. }
  1045. PrintAddress("HwDeviceExt", HwDeviceExt);
  1046. InitTypeRead(HwInitData, storport!HW_INITIALIZATION_DATA);
  1047. dprintf("(%d bytes)\n", (ULONG)ReadField(DeviceExtensionSize));
  1048. dindentf(Depth);
  1049. dprintf("SrbExt %d bytes LUExt %d bytes\n",
  1050. (ULONG)ReadField(SrbExtensionSize),
  1051. (ULONG)ReadField(SpecificLuExtensionSize));
  1052. dindentf(Depth);
  1053. dprintf("Logical Units: \n");
  1054. dprintf("\n");
  1055. dindentf(Depth);
  1056. dprintf("Product SCSI ID Object Extension Pnd Out Ct State\n");
  1057. dindentf(Depth);
  1058. dprintf("----------------------------------------------------------------------------\n");
  1059. ListAdapterUnits(AdapterExtension, Level, Depth);
  1060. }
  1061. }
  1062. VOID
  1063. ListGeneral (
  1064. IN ULONG Level,
  1065. IN ULONG Depth,
  1066. IN CHAR Type
  1067. )
  1068. {
  1069. ULONG64 address;
  1070. ULONG64 Drivers;
  1071. ULONG64 Adapters;
  1072. ULONG64 PortData;
  1073. ULONG64 NextDriver;
  1074. ULONG64 NextAdapter;
  1075. ULONG64 DriverExtension;
  1076. ULONG64 AdapterExtension;
  1077. ULONG offset;
  1078. address = GetExpression("storport!RaidpPortData");
  1079. if ((address != 0)) {
  1080. ReadPointer(address, &PortData);
  1081. if (!GetFieldOffset("storport!RAID_PORT_DATA", "DriverList.List", &offset)) {
  1082. Drivers = PortData + offset;
  1083. }
  1084. else {
  1085. dprintf("ERROR: Unable to retrieve Driver List offset\n");
  1086. return;
  1087. }
  1088. }
  1089. else {
  1090. dprintf("ERROR: Unable to lookup RAID_PORT_DATA structure\n");
  1091. return;
  1092. }
  1093. for (GetFieldValue(Drivers, "storport!LIST_ENTRY", "Flink", NextDriver); NextDriver != 0 && NextDriver != Drivers; GetFieldValue(NextDriver, "storport!LIST_ENTRY", "Flink", NextDriver)) {
  1094. DriverExtension = ContainingRecord(NextDriver, "storport!RAID_DRIVER_EXTENSION", "DriverLink");
  1095. if (!CheckRaidObject(DriverExtension, RaidDriverObject)) {
  1096. dprintf("ERROR: Not a valid RAID Driver Object\n");
  1097. return;
  1098. }
  1099. if (!GetFieldOffset("storport!RAID_DRIVER_EXTENSION", "AdapterList.List", &offset)) {
  1100. Adapters = DriverExtension + offset;
  1101. }
  1102. else {
  1103. dprintf("ERROR: Unable to retrieve Adapter List offset\n");
  1104. return;
  1105. }
  1106. if (Type == 'A') {
  1107. dprintf("Driver Object Extension State\n");
  1108. dprintf("----------------------------------------------------\n");
  1109. }
  1110. else if (Type == 'U') {
  1111. dprintf("Product SCSI ID Object Extension Pnd Out Ct State\n");
  1112. dprintf("----------------------------------------------------------------------------\n");
  1113. }
  1114. GetFieldValue(Adapters,
  1115. "storport!LIST_ENTRY",
  1116. "Flink",
  1117. NextAdapter);
  1118. //ASSERT(NextAdapter != 0);
  1119. while (NextAdapter != 0 && NextAdapter != Adapters) {
  1120. AdapterExtension = ContainingRecord(
  1121. NextAdapter,
  1122. "storport!RAID_ADAPTER_EXTENSION",
  1123. "NextAdapter");
  1124. if (!CheckRaidObject(AdapterExtension, RaidAdapterObject)) {
  1125. dprintf("ERROR: Not a valid RAID Adapter Object\n");
  1126. return;
  1127. }
  1128. if (Type == 'A') {
  1129. DumpAdapter(AdapterExtension, Level, Depth);
  1130. }
  1131. else if (Type == 'U') {
  1132. ListAdapterUnits(AdapterExtension, Level, Depth);
  1133. }
  1134. else {
  1135. dprintf("ERROR: Wrong Type\n");
  1136. return;
  1137. }
  1138. GetFieldValue(NextAdapter,
  1139. "storport!LIST_ENTRY",
  1140. "Flink",
  1141. NextAdapter);
  1142. }
  1143. }
  1144. }
  1145. __inline BOOL
  1146. GetHelpExpressionEx(
  1147. PCSTR Expression,
  1148. PCSTR* Command
  1149. )
  1150. {
  1151. if (Expression[0] != '\0' ) {
  1152. *Command = Expression;
  1153. return TRUE;
  1154. }
  1155. return FALSE;
  1156. }
  1157. DECLARE_API (help)
  1158. {
  1159. PCSTR command;
  1160. if(GetHelpExpressionEx(args, &command)) {
  1161. if ((strcmp(command, "adapter") == 0) || (strcmp(command, "Adapter") == 0)) {
  1162. dprintf("\nNAME: \n");
  1163. dprintf("\t!storkd.adapter\n");
  1164. dprintf("\nUSAGE: \n");
  1165. dprintf("\t!adapter [ADAPTER-OBJECT]\n");
  1166. dprintf("\nARGUMENTS: \n");
  1167. dprintf("\tADAPTER-OBJECT - pointer to a device object or an adapter extension\n");
  1168. dprintf("\tfor a given unit. If no ADAPTER-OBJECT is specified, all STOR adapters\n");
  1169. dprintf("\tused in the system are listed.\n");
  1170. return S_OK;
  1171. }
  1172. else if ((strcmp(command, "unit") == 0) || (strcmp(command, "UNIT") == 0) || (strcmp(command, "Unit") == 0)) {
  1173. dprintf("\nNAME: \n");
  1174. dprintf("\t!storkd.unit\n");
  1175. dprintf("\nUSAGE: \n");
  1176. dprintf("\t!lun [UNIT-OBJECT]\n");
  1177. dprintf("\nARGUMENTS: \n");
  1178. dprintf("\tUNIT-OBJECT - pointer to a device object or an unit extension for a\n");
  1179. dprintf("\tgiven logical unit. If no UNIT-OBJECT is specified, all STOR logical\n");
  1180. dprintf("\tunits used in the system is listed.\n");
  1181. return S_OK;
  1182. }
  1183. else if ((strcmp(command, "help") == 0) || (strcmp(command, "HELP") == 0) || (strcmp(command, "Help") == 0)) {
  1184. dprintf("\nNAME: \n");
  1185. dprintf("\t!storkd.help\n");
  1186. dprintf("\nUSAGE: \n");
  1187. dprintf("\t!help [COMMAND]\n");
  1188. dprintf("\nARGUMENTS: \n");
  1189. dprintf("\tCOMMAND - command name.\n");
  1190. return S_OK;
  1191. }
  1192. else {
  1193. dprintf ("\nERROR: INVALID COMMAND\n");
  1194. return S_OK;
  1195. }
  1196. }
  1197. else {
  1198. dprintf("\n!adapter - list all adapters with summary information\n");
  1199. dprintf("!adapter <address> - provide detailed information about the adapter\n");
  1200. dprintf(" identified by its device object or device extension\n");
  1201. dprintf(" address\n");
  1202. dprintf("!unit - list all logical units with summary information\n");
  1203. dprintf("!unit <address> - provide detailed information about the logical unit\n");
  1204. dprintf(" identified by its device object or device extension\n");
  1205. dprintf(" address\n");
  1206. dprintf("!help - list commands with description\n");
  1207. dprintf("\n");
  1208. return S_OK;
  1209. }
  1210. }
  1211. DECLARE_API (adapter)
  1212. {
  1213. ULONG64 address;
  1214. if (GetExpressionEx(args, &address, &args)) {
  1215. DumpAdapter(address, 1, 0);
  1216. }
  1217. else {
  1218. ListGeneral(0, 0, 'A');
  1219. }
  1220. return S_OK;
  1221. }
  1222. DECLARE_API (unit)
  1223. {
  1224. ULONG64 address;
  1225. if (GetExpressionEx(args, &address, &args)) {
  1226. DumpUnit(address, 1, 0);
  1227. }
  1228. else {
  1229. ListGeneral(0, 0, 'U');
  1230. }
  1231. return S_OK;
  1232. }