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.

1592 lines
40 KiB

  1. /*++
  2. Copyright (C) 1997-99 Microsoft Corporation
  3. Module Name:
  4. hack.c
  5. Abstract:
  6. --*/
  7. #include "ideport.h"
  8. #include "hack.h"
  9. #ifdef ALLOC_PRAGMA
  10. #pragma alloc_text(PAGE, IdePortSlaveIsGhost)
  11. #pragma alloc_text(PAGE, IdePortGetFlushCommand)
  12. #pragma alloc_text(PAGE, IdePortMustBePio)
  13. #pragma alloc_text(PAGE, IdePortPioByDefaultDevice)
  14. #pragma alloc_text(PAGE, IdePortDeviceHasNonRemovableMedia)
  15. #pragma alloc_text(PAGE, IdePortDeviceIsLs120)
  16. #pragma alloc_text(PAGE, IdePortNoPowerDown)
  17. #pragma alloc_text(PAGE, IdePortVerifyDma)
  18. #pragma alloc_text(NONPAGE, IdePortFudgeAtaIdentifyData)
  19. #pragma alloc_text(PAGE, IdePortIsThisAPanasonicPCMCIACard)
  20. #pragma alloc_text(PAGE, IdeFindSpecialDevice)
  21. /*
  22. #pragma alloc_text(PAGE, IdePortIsThisASonyMemorystickPCMCIACard)
  23. #pragma alloc_text(PAGE, IdePortSonyMemoryStick)
  24. #pragma alloc_text(PAGE, IdePortReuseIdent)
  25. #pragma alloc_text(PAGE, IdePortBadCdrom)
  26. */
  27. #endif // ALLOC_PRAGMA
  28. #if defined (FAKE_BMSETUP_FAILURE)
  29. ULONG FailBmSetupCount = 0;
  30. #endif // FAKE_BMSETUP_FAILURE
  31. #if DBG
  32. ULONG IdeDebugRescanBusFreq = 0;
  33. ULONG IdeDebugRescanBusCounter = 0;
  34. ULONG IdeDebugHungControllerFreq = 0;
  35. ULONG IdeDebugHungControllerCounter = 0;
  36. ULONG IdeDebugTimeoutAllCacheFlush = 0;
  37. ULONG IdeDebugForceSmallCrashDumpBlockSize = 0;
  38. PDEVICE_OBJECT IdeDebugDevObjTimeoutAllDmaSrb = 0;
  39. ULONG IdeDebug = 0;
  40. ULONG IdeDebugPrintControl = DBG_ALWAYS;
  41. UCHAR IdeBuffer[0x1000];
  42. VOID
  43. IdeDebugPrint(
  44. ULONG DebugPrintLevel,
  45. PCCHAR DebugMessage,
  46. ...
  47. )
  48. /*++
  49. Routine Description:
  50. Debug print for all SCSI drivers
  51. Arguments:
  52. Debug print level between 0 and 3, with 3 being the most verbose.
  53. Return Value:
  54. None
  55. --*/
  56. {
  57. BOOLEAN print = FALSE;
  58. va_list ap;
  59. va_start(ap, DebugMessage);
  60. if (DebugPrintLevel & DBG_BIT_CONTROL) {
  61. if (DebugPrintLevel == DBG_ALWAYS) {
  62. print = TRUE;
  63. } else if ((DebugPrintLevel & ~DBG_BIT_CONTROL) & IdeDebugPrintControl) {
  64. print = TRUE;
  65. }
  66. } else {
  67. if (DebugPrintLevel <= IdeDebug) {
  68. print = TRUE;
  69. }
  70. }
  71. if (print) {
  72. vsprintf(IdeBuffer, DebugMessage, ap);
  73. #ifdef ENABLE_DBG_PRINT
  74. DbgPrint(IdeBuffer);
  75. #else
  76. DbgPrintEx(DPFLTR_IDEP_ID,
  77. DPFLTR_INFO_LEVEL,
  78. IdeBuffer
  79. );
  80. #endif
  81. }
  82. va_end(ap);
  83. } // end IdeDebugPrint()
  84. #endif
  85. //
  86. // if we see one of these slave device that looks like
  87. // the master device, we will ignore the slave device
  88. //
  89. BOOLEAN
  90. IdePortSlaveIsGhost (
  91. IN OUT PFDO_EXTENSION FdoExtension,
  92. IN PIDENTIFY_DATA MasterIdentifyData,
  93. IN PIDENTIFY_DATA SlaveIdentifyData
  94. )
  95. {
  96. ULONG length;
  97. ULONG i;
  98. PAGED_CODE();
  99. length = sizeof (MasterIdentifyData->ModelNumber);
  100. if (length == RtlCompareMemory (
  101. MasterIdentifyData->ModelNumber,
  102. SlaveIdentifyData->ModelNumber,
  103. length)) {
  104. if (IdePortSearchDeviceInRegMultiSzList (
  105. FdoExtension,
  106. MasterIdentifyData,
  107. GHOST_SLAVE_DEVICE)) {
  108. DebugPrint ((DBG_WARNING, "ATAPI: Found a ghost slave\n"));
  109. return TRUE;
  110. }
  111. }
  112. return FALSE;
  113. }
  114. UCHAR
  115. IdePortGetFlushCommand (
  116. IN OUT PFDO_EXTENSION FdoExtension,
  117. IN OUT PPDO_EXTENSION PdoExtension,
  118. IN PIDENTIFY_DATA IdentifyData
  119. )
  120. {
  121. ULONG i;
  122. UCHAR flushCommand;
  123. BOOLEAN done;
  124. PAGED_CODE();
  125. ASSERT (FdoExtension);
  126. ASSERT (PdoExtension);
  127. ASSERT (IdentifyData);
  128. done = FALSE;
  129. //
  130. // in hall of shame list?
  131. //
  132. if (IdePortSearchDeviceInRegMultiSzList (
  133. FdoExtension,
  134. IdentifyData,
  135. NO_FLUSH_DEVICE)) {
  136. DebugPrint ((DBG_WARNING, "ATAPI: found a device that couldn't handle any flush command\n"));
  137. flushCommand = IDE_COMMAND_NO_FLUSH;
  138. done = TRUE;
  139. } else if (IdePortSearchDeviceInRegMultiSzList (
  140. FdoExtension,
  141. IdentifyData,
  142. CHECK_POWER_FLUSH_DEVICE)) {
  143. DebugPrint ((DBG_WARNING, "ATAPI: found a device that has to use check power mode command to flush\n"));
  144. flushCommand = IDE_COMMAND_CHECK_POWER;
  145. done = TRUE;
  146. }
  147. if (!done) {
  148. //
  149. // real ATA-4 drive?
  150. //
  151. if ((IdentifyData->MajorRevision != 0x0000) &&
  152. (IdentifyData->MajorRevision != 0xffff)) {
  153. USHORT version;
  154. version = IdentifyData->MajorRevision & ATA_VERSION_MASK;
  155. if (version & ~(ATA1_COMPLIANCE | ATA2_COMPLIANCE | ATA3_COMPLIANCE)) {
  156. //
  157. // ATA-4 Flush Command
  158. //
  159. flushCommand = IDE_COMMAND_FLUSH_CACHE;
  160. done = TRUE;
  161. }
  162. }
  163. }
  164. if (!done) {
  165. ATA_PASS_THROUGH ataPassThroughData;
  166. NTSTATUS status;
  167. //
  168. // try the ATA-4 flush command. maybe it will work.
  169. //
  170. RtlZeroMemory (&ataPassThroughData, sizeof (ataPassThroughData));
  171. ataPassThroughData.IdeReg.bCommandReg = IDE_COMMAND_FLUSH_CACHE;
  172. ataPassThroughData.IdeReg.bReserved = ATA_PTFLAGS_STATUS_DRDY_REQUIRED | ATA_PTFLAGS_ENUM_PROBING;
  173. status = IssueSyncAtaPassThroughSafe (
  174. FdoExtension,
  175. PdoExtension,
  176. &ataPassThroughData,
  177. FALSE,
  178. FALSE,
  179. 15,
  180. FALSE
  181. );
  182. if (NT_SUCCESS(status)) {
  183. if (!(ataPassThroughData.IdeReg.bCommandReg & IDE_STATUS_ERROR)) {
  184. flushCommand = IDE_COMMAND_FLUSH_CACHE;
  185. done = TRUE;
  186. }
  187. }
  188. }
  189. if (!done) {
  190. // out of idea!
  191. // choose the default
  192. flushCommand = IDE_COMMAND_CHECK_POWER;
  193. }
  194. return flushCommand;
  195. }
  196. #if 0
  197. BOOLEAN
  198. IdePortReuseIdent(
  199. IN PFDO_EXTENSION FdoExtension,
  200. IN PIDENTIFY_DATA IdentifyData
  201. )
  202. {
  203. PAGED_CODE();
  204. //
  205. // Determine if we can re-use the identify data
  206. //
  207. if (IdePortSearchDeviceInRegMultiSzList (
  208. FdoExtension,
  209. IdentifyData,
  210. NEED_IDENT_DEVICE)) {
  211. return TRUE;
  212. }
  213. return FALSE;
  214. }
  215. #endif
  216. BOOLEAN
  217. IdePortMustBePio (
  218. IN PFDO_EXTENSION FdoExtension,
  219. IN PIDENTIFY_DATA IdentifyData
  220. )
  221. {
  222. PAGED_CODE();
  223. //
  224. // query pio only device from the registry
  225. //
  226. if (IdePortSearchDeviceInRegMultiSzList (
  227. FdoExtension,
  228. IdentifyData,
  229. PIO_ONLY_DEVICE)) {
  230. return TRUE;
  231. }
  232. return FALSE;
  233. } // IdePortMustBePio
  234. BOOLEAN
  235. IdePortPioByDefaultDevice (
  236. IN PFDO_EXTENSION FdoExtension,
  237. IN PIDENTIFY_DATA IdentifyData
  238. )
  239. {
  240. PAGED_CODE();
  241. //
  242. // query pio only device from the registry
  243. //
  244. if (IdePortSearchDeviceInRegMultiSzList (
  245. FdoExtension,
  246. IdentifyData,
  247. DEFAULT_PIO_DEVICE)) {
  248. return TRUE;
  249. }
  250. return FALSE;
  251. } // IdePortMustBePio
  252. BOOLEAN
  253. IdePortDeviceHasNonRemovableMedia (
  254. IN OUT PFDO_EXTENSION FdoExtension,
  255. IN PIDENTIFY_DATA IdentifyData
  256. )
  257. {
  258. BOOLEAN removableMediaOverride;
  259. PAGED_CODE();
  260. if (IsNEC_98) {
  261. return ((IdentifyData->GeneralConfiguration & (1 << 7))? TRUE :
  262. (!Is98LegacyIde(&FdoExtension->HwDeviceExtension->BaseIoAddress1)? TRUE : FALSE));
  263. }
  264. return (IdentifyData->GeneralConfiguration & (1 << 7)) ? TRUE : FALSE;
  265. /*
  266. removableMediaOverride = FALSE;
  267. if (IdePortSearchDeviceInRegMultiSzList (
  268. FdoExtension,
  269. IdentifyData,
  270. NONREMOVABLE_MEDIA_OVERRIDE)) {
  271. removableMediaOverride = TRUE;
  272. }
  273. if (removableMediaOverride) {
  274. return FALSE;
  275. } else {
  276. return (IdentifyData->GeneralConfiguration & (1 << 7)) ? TRUE : FALSE;
  277. }
  278. */
  279. }
  280. BOOLEAN
  281. IdePortDeviceIsLs120 (
  282. IN PFDO_EXTENSION FdoExtension,
  283. IN PIDENTIFY_DATA IdentifyData
  284. )
  285. {
  286. UCHAR modelNumber[41];
  287. ULONG i;
  288. UCHAR ls120NameString[] = "LS-120";
  289. PAGED_CODE();
  290. //
  291. // byte swap model number
  292. //
  293. for (i=0; i<40; i+=2) {
  294. modelNumber[i + 0] = IdentifyData->ModelNumber[i + 1];
  295. modelNumber[i + 1] = IdentifyData->ModelNumber[i + 0];
  296. }
  297. modelNumber[i] = 0;
  298. return strstr(_strupr(modelNumber), ls120NameString) ? TRUE : FALSE;
  299. } // IdePortDeviceIsLs120
  300. BOOLEAN
  301. IdePortNoPowerDown (
  302. IN PFDO_EXTENSION FdoExtension,
  303. IN PIDENTIFY_DATA IdentifyData
  304. )
  305. {
  306. PAGED_CODE();
  307. //
  308. // query no power down device from the registry
  309. //
  310. if (IdePortSearchDeviceInRegMultiSzList (
  311. FdoExtension,
  312. IdentifyData,
  313. NO_POWER_DOWN_DEVICE)) {
  314. return TRUE;
  315. }
  316. return FALSE;
  317. } // IdePortNoPowerDown
  318. BOOLEAN
  319. IdePortVerifyDma (
  320. IN PPDO_EXTENSION pdoExtension,
  321. IN IDE_DEVICETYPE ideDeviceType
  322. )
  323. {
  324. NTSTATUS status;
  325. ULONG oldDmaTransferTimeoutCount;
  326. BOOLEAN dmaOk;
  327. dmaOk = TRUE;
  328. if (pdoExtension->DmaTransferTimeoutCount >= PDO_DMA_TIMEOUT_LIMIT) {
  329. dmaOk = FALSE;
  330. } else if (ideDeviceType == DeviceIsAtapi) {
  331. INQUIRYDATA DmaInquiryData;
  332. INQUIRYDATA PioInquiryData;
  333. status = IssueInquirySafe(
  334. pdoExtension->ParentDeviceExtension,
  335. pdoExtension,
  336. &DmaInquiryData,
  337. FALSE);
  338. if (NT_SUCCESS(status)) {
  339. //
  340. // force a pio transfer
  341. //
  342. oldDmaTransferTimeoutCount = InterlockedExchange(
  343. &pdoExtension->DmaTransferTimeoutCount,
  344. PDO_DMA_TIMEOUT_LIMIT
  345. );
  346. status = IssueInquirySafe(
  347. pdoExtension->ParentDeviceExtension,
  348. pdoExtension,
  349. &PioInquiryData,
  350. FALSE);
  351. if (NT_SUCCESS(status) &&
  352. (RtlCompareMemory (&DmaInquiryData, &PioInquiryData,
  353. sizeof(DmaInquiryData)) != sizeof(DmaInquiryData))) {
  354. dmaOk = FALSE;
  355. //
  356. // dma is not ok, leave the dma error count as PDO_DMA_TIMEOUT_LIMIT
  357. // so that we are not going to use dma with this device
  358. //
  359. } else {
  360. InterlockedExchange(
  361. &pdoExtension->DmaTransferTimeoutCount,
  362. oldDmaTransferTimeoutCount
  363. );
  364. }
  365. }
  366. } else if (ideDeviceType == DeviceIsAta) {
  367. PUCHAR dmaDataBuffer;
  368. PUCHAR pioDataBuffer;
  369. CDB cdb;
  370. //
  371. // the only non-desctrutive way to test dma on a
  372. // ata device is to perform a pio read and a dma read and
  373. // compare the data.
  374. //
  375. // this technique does not work if the device has a removable
  376. // media and it is removed.
  377. //
  378. dmaDataBuffer = ExAllocatePool (
  379. NonPagedPool,
  380. 512 * 2
  381. );
  382. if (dmaDataBuffer) {
  383. pioDataBuffer = dmaDataBuffer + 512;
  384. //
  385. // setup dma pass through
  386. //
  387. RtlZeroMemory(&cdb, sizeof(CDB));
  388. cdb.CDB10.OperationCode = SCSIOP_READ;
  389. cdb.CDB10.TransferBlocksLsb = 1;
  390. status = IssueSyncAtapiCommandSafe (
  391. pdoExtension->ParentDeviceExtension,
  392. pdoExtension,
  393. &cdb,
  394. dmaDataBuffer,
  395. 512,
  396. TRUE,
  397. 2,
  398. FALSE
  399. );
  400. if (NT_SUCCESS(status)) {
  401. //
  402. // setup pio pass through
  403. //
  404. RtlZeroMemory(&cdb, sizeof(CDB));
  405. cdb.CDB10.OperationCode = SCSIOP_READ;
  406. cdb.CDB10.TransferBlocksLsb = 1;
  407. //
  408. // force a pio transfer
  409. //
  410. oldDmaTransferTimeoutCount = InterlockedExchange(
  411. &pdoExtension->DmaTransferTimeoutCount,
  412. PDO_DMA_TIMEOUT_LIMIT
  413. );
  414. status = IssueSyncAtapiCommand (
  415. pdoExtension->ParentDeviceExtension,
  416. pdoExtension,
  417. &cdb,
  418. pioDataBuffer,
  419. 512,
  420. TRUE,
  421. 2,
  422. FALSE
  423. );
  424. if (NT_SUCCESS(status) &&
  425. (RtlCompareMemory (
  426. dmaDataBuffer,
  427. pioDataBuffer,
  428. 512) != 512)) {
  429. dmaOk = FALSE;
  430. //
  431. // dma is not ok, leave the dma error count as PDO_DMA_TIMEOUT_LIMIT
  432. // so that we are not going to use dma with this device
  433. //
  434. } else {
  435. InterlockedExchange(
  436. &pdoExtension->DmaTransferTimeoutCount,
  437. oldDmaTransferTimeoutCount
  438. );
  439. }
  440. }
  441. }
  442. if (dmaDataBuffer) {
  443. ExFreePool (dmaDataBuffer);
  444. }
  445. }
  446. #if DBG
  447. #if defined (FAKE_BROKEN_DMA_DEVICE)
  448. InterlockedExchange(
  449. &pdoExtension->DmaTransferTimeoutCount,
  450. PDO_DMA_TIMEOUT_LIMIT
  451. );
  452. dmaOk = FALSE;
  453. #endif // FAKE_BROKEN_DMA_DEVICE
  454. #endif // DBG
  455. if (!dmaOk) {
  456. ERROR_LOG_ENTRY errorLogEntry;
  457. errorLogEntry.ErrorCode = SP_BAD_FW_ERROR;
  458. errorLogEntry.MajorFunctionCode = IRP_MJ_SCSI;
  459. errorLogEntry.PathId = pdoExtension->PathId;
  460. errorLogEntry.TargetId = pdoExtension->TargetId;
  461. errorLogEntry.Lun = pdoExtension->Lun;
  462. errorLogEntry.UniqueId = ERRLOGID_LYING_DMA_SYSTEM;
  463. errorLogEntry.ErrorLogRetryCount = 0;
  464. errorLogEntry.SequenceNumber = 0;
  465. LogErrorEntry(
  466. pdoExtension->ParentDeviceExtension,
  467. &errorLogEntry
  468. );
  469. DebugPrint ((
  470. DBG_ALWAYS,
  471. "ATAPI: system and/or device lies about its dma capability. pdoe = 0x%x\n",
  472. pdoExtension
  473. ));
  474. }
  475. return dmaOk;
  476. }
  477. VOID
  478. IdePortFudgeAtaIdentifyData(
  479. IN OUT PIDENTIFY_DATA IdentifyData
  480. )
  481. {
  482. if (IdentifyData->GeneralConfiguration == 0xffff) {
  483. //
  484. // guessing we have a really old ATA drive
  485. // fake the GeneralConfiguration value
  486. //
  487. CLRMASK (
  488. IdentifyData->GeneralConfiguration,
  489. (IDE_IDDATA_REMOVABLE | (1 << 15))
  490. );
  491. }
  492. }
  493. #define PANASONIC_PCMCIA_IDE_DEVICE L"PCMCIA\\KME-KXLC005-A99E"
  494. BOOLEAN
  495. IdePortIsThisAPanasonicPCMCIACard(
  496. IN PFDO_EXTENSION FdoExtension
  497. )
  498. {
  499. IO_STATUS_BLOCK ioStatus;
  500. KEVENT pnpEvent;
  501. NTSTATUS status;
  502. PDEVICE_OBJECT targetObject;
  503. PIO_STACK_LOCATION irpStack;
  504. PIRP pnpIrp;
  505. BOOLEAN result = FALSE;
  506. PAGED_CODE();
  507. targetObject = FdoExtension->AttacheeDeviceObject;
  508. //
  509. // Initialize the event
  510. //
  511. KeInitializeEvent( &pnpEvent, SynchronizationEvent, FALSE );
  512. //
  513. // Build an Irp
  514. //
  515. pnpIrp = IoBuildSynchronousFsdRequest(
  516. IRP_MJ_PNP,
  517. FdoExtension->AttacheeDeviceObject,
  518. NULL,
  519. 0,
  520. NULL,
  521. &pnpEvent,
  522. &ioStatus
  523. );
  524. if (pnpIrp == NULL) {
  525. return FALSE;
  526. }
  527. //
  528. // Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
  529. //
  530. pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  531. pnpIrp->IoStatus.Information = 0;
  532. //
  533. // Set the top of stack
  534. //
  535. irpStack = IoGetNextIrpStackLocation( pnpIrp );
  536. RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
  537. irpStack->MajorFunction = IRP_MJ_PNP;
  538. irpStack->MinorFunction = IRP_MN_QUERY_ID;
  539. irpStack->Parameters.QueryId.IdType = BusQueryDeviceID;
  540. //
  541. // Make sure that there are no completion routines set
  542. //
  543. IoSetCompletionRoutine(
  544. pnpIrp,
  545. NULL,
  546. NULL,
  547. FALSE,
  548. FALSE,
  549. FALSE
  550. );
  551. //
  552. // Call the driver
  553. //
  554. status = IoCallDriver( targetObject, pnpIrp );
  555. if (status == STATUS_PENDING) {
  556. //
  557. // Block until the irp comes back
  558. //
  559. KeWaitForSingleObject(
  560. &pnpEvent,
  561. Executive,
  562. KernelMode,
  563. FALSE,
  564. NULL
  565. );
  566. status = ioStatus.Status;
  567. }
  568. if (NT_SUCCESS(status)) {
  569. UNICODE_STRING panasonicDeviceId;
  570. UNICODE_STRING deviceId;
  571. RtlInitUnicodeString (&panasonicDeviceId, PANASONIC_PCMCIA_IDE_DEVICE);
  572. RtlInitUnicodeString (&deviceId, (PWCHAR) ioStatus.Information);
  573. if (!RtlCompareUnicodeString(
  574. &deviceId,
  575. &panasonicDeviceId,
  576. TRUE)) {
  577. result = TRUE;
  578. }
  579. ExFreePool ((PVOID) ioStatus.Information);
  580. }
  581. return result;
  582. }
  583. //
  584. // Timing Code
  585. //
  586. #if defined (ENABLE_TIME_LOG)
  587. TIME_LOG TimeLog[TimeMax] = {0};
  588. VOID
  589. LogStartTime(
  590. TIME_ID id,
  591. PLARGE_INTEGER timer
  592. )
  593. {
  594. *timer = KeQueryPerformanceCounter(NULL);
  595. }
  596. VOID
  597. LogStopTime(
  598. TIME_ID id,
  599. PLARGE_INTEGER timer,
  600. ULONG waterMark
  601. )
  602. {
  603. LARGE_INTEGER freq;
  604. LARGE_INTEGER stopTime;
  605. LARGE_INTEGER diffTime;
  606. LARGE_INTEGER diffTimeInMicroSec;
  607. stopTime = KeQueryPerformanceCounter(&freq);
  608. diffTime.QuadPart = stopTime.QuadPart - timer->QuadPart;
  609. diffTimeInMicroSec.QuadPart = (diffTime.QuadPart * 1000000) / freq.QuadPart;
  610. // need a spinlock
  611. if (TimeLog[id].min.QuadPart == 0) {
  612. TimeLog[id].min.QuadPart = 0x7fffffffffffffffL;
  613. }
  614. if (diffTime.QuadPart < TimeLog[id].min.QuadPart) {
  615. TimeLog[id].min = diffTime;
  616. }
  617. if (diffTime.QuadPart > TimeLog[id].max.QuadPart) {
  618. TimeLog[id].max = diffTime;
  619. }
  620. TimeLog[id].totalTimeInMicroSec.QuadPart += diffTimeInMicroSec.QuadPart;
  621. TimeLog[id].numLog.QuadPart++;
  622. if (waterMark) {
  623. if (diffTimeInMicroSec.LowPart > waterMark) {
  624. DebugPrint ((DBG_ALWAYS, "IdePort: timerID 0x%d took %d us\n", id, (ULONG) diffTimeInMicroSec.LowPart));
  625. }
  626. }
  627. }
  628. #endif // ENABLE_TIME_LOG
  629. #if defined (IDE_BUS_TRACE)
  630. ULONG IdePortBusTraceTableMaxEntries = 0x20000;
  631. BUS_TRACE_LOG IdePortBusTaceLog = {0, 0, 0, FALSE};
  632. VOID InitBusTraceLogTable (
  633. VOID
  634. )
  635. {
  636. ASSERT (IdePortBusTaceLog.LogTable == NULL);
  637. //
  638. // make sure MAX_ULONG + 1 is a multiple of total log entries
  639. // so that when the index wraps, we don't skin any log entry
  640. //
  641. ASSERT(!((((ULONGLONG) 0xffffffff) + 1) % IdePortBusTraceTableMaxEntries));
  642. IdePortBusTaceLog.LogTable =
  643. ExAllocatePool (NonPagedPool, IdePortBusTraceTableMaxEntries * sizeof(BUS_TRACE_RECORD));
  644. if (IdePortBusTaceLog.LogTable) {
  645. IdePortBusTaceLog.NumLogTableEntries = IdePortBusTraceTableMaxEntries;
  646. IdePortBusTaceLog.LastLogTableEntry = -1;
  647. IdePortBusTaceLog.TableWrapped = FALSE;
  648. KeInitializeSpinLock(&IdePortBusTaceLog.SpinLock);
  649. }
  650. }
  651. VOID FreeBusTraceLogTable (
  652. VOID
  653. )
  654. {
  655. if (IdePortBusTaceLog.LogTable) {
  656. ExFreePool (IdePortBusTaceLog.LogTable);
  657. RtlZeroMemory(&IdePortBusTaceLog, sizeof(IdePortBusTaceLog));
  658. }
  659. }
  660. VOID
  661. IdepUpdateTraceLog (
  662. IO_TYPE IoType,
  663. PVOID PortAddress,
  664. ULONG Data
  665. )
  666. {
  667. KIRQL currentIrql;
  668. ULONG lastEntry;
  669. if (IdePortBusTaceLog.LogTable) {
  670. lastEntry = InterlockedIncrement(&IdePortBusTaceLog.LastLogTableEntry);
  671. lastEntry--;
  672. lastEntry %= IdePortBusTaceLog.NumLogTableEntries;
  673. IdePortBusTaceLog.LogTable[lastEntry].IoType = IoType;
  674. IdePortBusTaceLog.LogTable[lastEntry].Address = PortAddress;
  675. IdePortBusTaceLog.LogTable[lastEntry].Data = Data;
  676. IdePortBusTaceLog.LogTable[lastEntry].Count = 1;
  677. }
  678. }
  679. UCHAR
  680. IdepPortInPortByte (
  681. PUCHAR PortAddress
  682. )
  683. {
  684. KIRQL currentIrql;
  685. UCHAR data;
  686. data = READ_PORT_UCHAR(PortAddress);
  687. IdepUpdateTraceLog (InPortByte, PortAddress, (ULONG) data);
  688. return data;
  689. }
  690. VOID
  691. IdepPortOutPortByte (
  692. PUCHAR PortAddress,
  693. UCHAR Data
  694. )
  695. {
  696. WRITE_PORT_UCHAR(PortAddress, Data);
  697. IdepUpdateTraceLog (OutPortByte, PortAddress, (ULONG) Data);
  698. return;
  699. }
  700. USHORT
  701. IdepPortInPortWord (
  702. PUSHORT PortAddress
  703. )
  704. {
  705. KIRQL currentIrql;
  706. USHORT data;
  707. data = READ_PORT_USHORT(PortAddress);
  708. IdepUpdateTraceLog (InPortWord, PortAddress, (ULONG) data);
  709. return data;
  710. }
  711. VOID
  712. IdepPortOutPortWord (
  713. PUSHORT PortAddress,
  714. USHORT Data
  715. )
  716. {
  717. WRITE_PORT_USHORT(PortAddress, Data);
  718. IdepUpdateTraceLog (OutPortWord, PortAddress, (ULONG) Data);
  719. return;
  720. }
  721. VOID
  722. IdepPortInPortWordBuffer (
  723. PUSHORT PortAddress,
  724. PUSHORT Buffer,
  725. ULONG Count
  726. )
  727. {
  728. ULONG i;
  729. for (i=0; i<Count; i++) {
  730. Buffer[i] = IdepPortInPortWord (PortAddress);
  731. }
  732. return;
  733. }
  734. VOID
  735. IdepPortOutPortWordBuffer (
  736. PUSHORT PortAddress,
  737. PUSHORT Buffer,
  738. ULONG Count
  739. )
  740. {
  741. ULONG i;
  742. for (i=0; i<Count; i++) {
  743. IdepPortOutPortWord (PortAddress, Buffer[i]);
  744. }
  745. return;
  746. }
  747. #endif // IDE_BUS_TRACE
  748. SPECIAL_ACTION_FLAG
  749. IdeFindSpecialDevice(
  750. IN PUCHAR VendorProductId,
  751. IN PUCHAR ProductRevisionId
  752. )
  753. /*++
  754. Routine Description:
  755. This routine will search the IDE special device table to determine whether
  756. any special behavior should be enabled for this device. The match is made upto
  757. the strlen of VendorProductId in the table.
  758. Arguments:
  759. VendorProductId - the full vendor & product ID of the device in question.
  760. ProductRevisionId - the full product revision ID of the device in question.
  761. ReturnValue:
  762. an ulong which describes the limitations of the device
  763. in question.
  764. --*/
  765. {
  766. IDE_SPECIAL_DEVICE IdeSpecialDeviceTable[] = {
  767. {"TOSHIBA CD-ROM XM-1702B", NULL, disableSerialNumber},
  768. {"TOSHIBA CD-ROM XM-6202B", NULL, disableSerialNumber},
  769. {"COMPAQ DVD-ROM DRD-U424", NULL, disableSerialNumber},
  770. {" " , NULL, disableSerialNumber},
  771. {"KENWOOD CD-ROM", NULL, skipModeSense},
  772. {"MEMORYSTICK", NULL, setFlagSonyMemoryStick},
  773. {NULL, NULL, noSpecialAction}
  774. };
  775. ULONG i;
  776. ULONG length;
  777. PAGED_CODE();
  778. //
  779. // if both the arguments are null, then just return no special action
  780. //
  781. if (VendorProductId == NULL &&
  782. ProductRevisionId == NULL) {
  783. return noSpecialAction;
  784. }
  785. for(i = 0; IdeSpecialDeviceTable[i].VendorProductId != NULL; i++) {
  786. //
  787. // Match only upto the strlen of the productID in the table
  788. // This will allow special action for all the models from a particular vendor.
  789. //
  790. length=strlen(IdeSpecialDeviceTable[i].VendorProductId);
  791. if (length != RtlCompareMemory(IdeSpecialDeviceTable[i].VendorProductId,
  792. VendorProductId, length)) {
  793. continue;
  794. }
  795. //
  796. // Partial matches are not acceptable for revision Ids.
  797. //
  798. if((IdeSpecialDeviceTable[i].Revision != NULL) &&
  799. (strcmp(IdeSpecialDeviceTable[i].Revision,
  800. ProductRevisionId) != 0)) {
  801. continue;
  802. }
  803. //
  804. // We've got a match. Break out.
  805. //
  806. break;
  807. }
  808. //
  809. // Return whatever entry we're pointing at. If we matched based on the
  810. // id's then this will be the matching entry. If we broke out of the
  811. // loop then this will be the last entry in the list which is the
  812. // benign, "nothing special about this device" entry that we return
  813. // for a failed match.
  814. //
  815. return (IdeSpecialDeviceTable[i].RequiredAction);
  816. }
  817. #ifdef ENABLE_COMMAND_LOG
  818. VOID
  819. IdeLogOpenCommandLog(
  820. PSRB_DATA SrbData
  821. )
  822. {
  823. if (SrbData->IdeCommandLog == NULL) {
  824. SrbData->IdeCommandLog = ExAllocatePool(
  825. NonPagedPool,
  826. MAX_COMMAND_LOG_ENTRIES*sizeof(COMMAND_LOG)
  827. );
  828. if (SrbData->IdeCommandLog != NULL) {
  829. RtlZeroMemory(SrbData->IdeCommandLog, MAX_COMMAND_LOG_ENTRIES*sizeof(COMMAND_LOG));
  830. }
  831. SrbData->IdeCommandLogIndex = 0;
  832. }
  833. return;
  834. }
  835. VOID
  836. IdeLogStartCommandLog(
  837. PSRB_DATA SrbData
  838. )
  839. {
  840. PCOMMAND_LOG cmdLog = &(SrbData->IdeCommandLog[SrbData->IdeCommandLogIndex]);
  841. PSCSI_REQUEST_BLOCK srb = SrbData->CurrentSrb;
  842. ASSERT(srb);
  843. if (cmdLog == NULL) {
  844. return;
  845. }
  846. UpdateStartTimeStamp(cmdLog);
  847. if (srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH ||
  848. srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH) {
  849. PATA_PASS_THROUGH ataPassThroughData = srb->DataBuffer;
  850. cmdLog->Cdb[0]= srb->Function;
  851. RtlCopyMemory(&(cmdLog->Cdb[1]), &(ataPassThroughData->IdeReg), sizeof(IDEREGS));
  852. } else {
  853. RtlCopyMemory(&(cmdLog->Cdb), &(srb->Cdb), sizeof(CDB));
  854. }
  855. return;
  856. }
  857. VOID
  858. IdeLogStopCommandLog(
  859. PSRB_DATA SrbData
  860. )
  861. {
  862. PCOMMAND_LOG cmdLog = &(SrbData->IdeCommandLog[SrbData->IdeCommandLogIndex]);
  863. PSCSI_REQUEST_BLOCK srb = SrbData->CurrentSrb;
  864. PSENSE_DATA senseBuffer = NULL;
  865. ULONG senseInfoBufferLength;
  866. ASSERT(srb);
  867. if (cmdLog == NULL) {
  868. return;
  869. }
  870. UpdateStopTimeStamp(cmdLog);
  871. if (srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
  872. senseBuffer = srb->DataBuffer;
  873. senseInfoBufferLength = srb->DataTransferLength;
  874. } else if (srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) {
  875. senseBuffer = srb->SenseInfoBuffer;
  876. senseInfoBufferLength = (ULONG) srb->SenseInfoBufferLength;
  877. }
  878. if (senseBuffer && (senseInfoBufferLength > FIELD_OFFSET(SENSE_DATA, AdditionalSenseCodeQualifier))) {
  879. cmdLog->SenseData[0] = senseBuffer->SenseKey;
  880. cmdLog->SenseData[1] = senseBuffer->AdditionalSenseCode;
  881. cmdLog->SenseData[2] = senseBuffer->AdditionalSenseCodeQualifier;
  882. }else {
  883. cmdLog->SenseData[0] = 0;
  884. cmdLog->SenseData[1] = 0;
  885. cmdLog->SenseData[2] = 0;
  886. }
  887. cmdLog->SrbStatus = srb->SrbStatus;
  888. SrbData->IdeCommandLogIndex = ( SrbData->IdeCommandLogIndex + 1) % MAX_COMMAND_LOG_ENTRIES;
  889. return;
  890. }
  891. VOID
  892. IdeLogSaveTaskFile(
  893. PSRB_DATA SrbData,
  894. PIDE_REGISTERS_1 BaseIoAddress
  895. )
  896. {
  897. PCOMMAND_LOG cmdLog = &(SrbData->IdeCommandLog[SrbData->IdeCommandLogIndex]);
  898. if (cmdLog == NULL) {
  899. return;
  900. }
  901. AtapiTaskRegisterSnapshot(BaseIoAddress, &(cmdLog->FinalTaskFile));
  902. return;
  903. }
  904. VOID
  905. IdeLogBmStatus(
  906. PSCSI_REQUEST_BLOCK Srb,
  907. BMSTATUS BmStatus
  908. )
  909. {
  910. PSRB_DATA srbData = IdeGetSrbData(NULL, Srb);
  911. PCOMMAND_LOG cmdLog;
  912. if (srbData == NULL) {
  913. return;
  914. }
  915. cmdLog = &(srbData->IdeCommandLog[srbData->IdeCommandLogIndex]);
  916. if (cmdLog == NULL) {
  917. return;
  918. }
  919. cmdLog->BmStatus = BmStatus;
  920. return;
  921. }
  922. VOID
  923. IdeLogFreeCommandLog(
  924. PSRB_DATA SrbData
  925. )
  926. {
  927. PCOMMAND_LOG cmdLog = SrbData->IdeCommandLog;
  928. if (cmdLog) {
  929. ExFreePool(cmdLog);
  930. }
  931. SrbData->IdeCommandLog = NULL;
  932. SrbData->IdeCommandLogIndex = 0;
  933. }
  934. #endif
  935. #ifdef ENABLE_ATAPI_VERIFIER
  936. PVOID ViIdeExtensionTable[2];
  937. #define VFLAGS_FORCE_TIMEOUT (1<<0)
  938. #define VFLAGS_DMA_TIMEOUT (1<<1)
  939. #define VFLAGS_CFLUSH_TIMEOUT (1<<2)
  940. #define VFLAGS_DEVICE_CHANGE (1<<3)
  941. #define VFLAGS_MISSING_DEVICE (1<<4)
  942. #define VFLAGS_ACTUAL_ERROR (1<<5)
  943. #define VFLAGS_CRC_ERROR (1<<6)
  944. #define VFLAGS_BUSY_ERROR (1<<7)
  945. #define VFLAGS_RW_ERROR (1<<8)
  946. VOID
  947. ViIdeInitVerifierSettings(
  948. IN PFDO_EXTENSION FdoExtension
  949. )
  950. {
  951. }
  952. BOOLEAN
  953. ViIdeGenerateDmaTimeout(
  954. IN PVOID HwDeviceExtension,
  955. IN BOOLEAN DmaInProgress
  956. )
  957. {
  958. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  959. PFDO_EXTENSION fdoExtension = ((PFDO_EXTENSION)HwDeviceExtension - 1);
  960. PSCSI_REQUEST_BLOCK srb = hwDeviceExtension->CurrentSrb;
  961. ULONG ideInternalVerifierFlags ;
  962. ASSERT(srb);
  963. ideInternalVerifierFlags = fdoExtension->IdeInternalVerifierFlags[srb->TargetId];
  964. if (ideInternalVerifierFlags & VFLAGS_FORCE_TIMEOUT) {
  965. return TRUE;
  966. }
  967. if (DmaInProgress && (ideInternalVerifierFlags & VFLAGS_DMA_TIMEOUT)) {
  968. return TRUE;
  969. }
  970. if ((srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH) ||
  971. (srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH)) {
  972. PATA_PASS_THROUGH ataPassThroughData;
  973. PIDEREGS pIdeReg;
  974. ataPassThroughData = srb->DataBuffer;
  975. pIdeReg = &ataPassThroughData->IdeReg;
  976. if ((ideInternalVerifierFlags & VFLAGS_CFLUSH_TIMEOUT) &&
  977. (pIdeReg->bCommandReg == hwDeviceExtension->DeviceParameters[srb->TargetId].IdeFlushCommand )) {
  978. return TRUE;
  979. }
  980. }
  981. return FALSE;
  982. }
  983. ULONG
  984. ViIdeFakeDeviceChange(
  985. IN PFDO_EXTENSION FdoExtension,
  986. ULONG Target
  987. )
  988. {
  989. ULONG ideInternalVerifierFlags = FdoExtension->IdeDebugVerifierFlags[Target];
  990. if (ideInternalVerifierFlags & VFLAGS_DEVICE_CHANGE) {
  991. return 1;
  992. }
  993. return 0;
  994. }
  995. BOOLEAN
  996. ViIdeFakeMissingDevice(
  997. IN PFDO_EXTENSION FdoExtension,
  998. ULONG Target
  999. )
  1000. {
  1001. ULONG ideInternalVerifierFlags = FdoExtension->IdeDebugVerifierFlags[Target];
  1002. if (ideInternalVerifierFlags & VFLAGS_MISSING_DEVICE) {
  1003. return TRUE;
  1004. }
  1005. return FALSE;
  1006. }
  1007. VOID
  1008. ViAtapiInterrupt(
  1009. IN PFDO_EXTENSION FdoExtension
  1010. )
  1011. {
  1012. PHW_DEVICE_EXTENSION hwDeviceExtension = FdoExtension->HwDeviceExtension;
  1013. PIDE_REGISTERS_1 baseIoAddress = &(hwDeviceExtension->BaseIoAddress1);
  1014. PSCSI_REQUEST_BLOCK srb = hwDeviceExtension->CurrentSrb;
  1015. ULONG target;
  1016. //DebugPrint((0, "verifier interrupt fdoe = %x, b=%x\n", FdoExtension, baseIoAddress->RegistersBaseAddress));
  1017. if ((ULONG)(baseIoAddress->RegistersBaseAddress) == 0x1f0) {
  1018. ViIdeExtensionTable[0]=FdoExtension;
  1019. } else {
  1020. ViIdeExtensionTable[1]=FdoExtension;
  1021. }
  1022. if (srb == NULL) {
  1023. return ;
  1024. }
  1025. target = srb->TargetId;
  1026. //
  1027. // Generate timeouts
  1028. //
  1029. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_DMA_TIMEOUT) {
  1030. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_DMA_TIMEOUT;
  1031. return;
  1032. }
  1033. //
  1034. // Generate CRC errors
  1035. //
  1036. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_CRC_ERROR) {
  1037. if (FdoExtension->IdeVerifierEventCount[target][CrcEvent] >= FdoExtension->IdeVerifierEventFrequency[target][CrcEvent]) {
  1038. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_CRC_ERROR;
  1039. FdoExtension->IdeVerifierEventCount[target][CrcEvent]=0;
  1040. return;
  1041. } else {
  1042. FdoExtension->IdeVerifierEventCount[target][RwEvent]++;
  1043. }
  1044. }
  1045. //
  1046. // Generate Busy errors
  1047. //
  1048. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_BUSY_ERROR) {
  1049. if (FdoExtension->IdeVerifierEventCount[target][BusyEvent] >= FdoExtension->IdeVerifierEventFrequency[target][BusyEvent]) {
  1050. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_BUSY_ERROR;
  1051. FdoExtension->IdeVerifierEventCount[target][BusyEvent]=0;
  1052. return;
  1053. } else {
  1054. FdoExtension->IdeVerifierEventCount[target][BusyEvent]++;
  1055. }
  1056. }
  1057. //
  1058. // Generate Read write errors
  1059. //
  1060. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_RW_ERROR) {
  1061. if (FdoExtension->IdeVerifierEventCount[target][RwEvent] >= FdoExtension->IdeVerifierEventFrequency[target][RwEvent]) {
  1062. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_RW_ERROR;
  1063. FdoExtension->IdeVerifierEventCount[target][RwEvent]=0;
  1064. return;
  1065. } else {
  1066. FdoExtension->IdeVerifierEventCount[target][RwEvent]++;
  1067. }
  1068. }
  1069. // ViIdeGenerateReadWriteErrors(FdoExtension);
  1070. // ViIdeGenerateDmaErrors(FdoExtension);
  1071. // ViIdeFakeHungController(FdoExtension);
  1072. return ;
  1073. }
  1074. UCHAR
  1075. ViIdeGetBaseStatus(
  1076. PIDE_REGISTERS_1 BaseIoAddress
  1077. )
  1078. {
  1079. UCHAR status = IdePortInPortByte((BaseIoAddress)->Command);
  1080. /*
  1081. UCHAR deviceSelect = IdePortInPortByte(BaseIoAddress->DriveSelect);
  1082. UCHAR channel = ((ULONG)(BaseIoAddress->RegistersBaseAddress) == 0x1f0) ? 0: 1;
  1083. PFDO_EXTENSION fdoExtension = ViIdeExtensionTable[channel];
  1084. ULONG target = (deviceSelect == 0xA0)? 0: 1;
  1085. ULONG ideInternalVerifierFlags;
  1086. ULONG dFlags;
  1087. if (fdoExtension == NULL) {
  1088. return status;
  1089. }
  1090. ideInternalVerifierFlags = fdoExtension->IdeInternalVerifierFlags[target];
  1091. dFlags = fdoExtension->HwDeviceExtension->DeviceFlags[target];
  1092. if (status & IDE_STATUS_ERROR) {
  1093. SETMASK(fdoExtension->IdeInternalVerifierFlags[target], VFLAGS_ACTUAL_ERROR);
  1094. return status;
  1095. }
  1096. if (ideInternalVerifierFlags & VFLAGS_CRC_ERROR) {
  1097. return IDE_STATUS_ERROR;
  1098. }
  1099. if (ideInternalVerifierFlags & VFLAGS_BUSY_ERROR) {
  1100. return IDE_STATUS_BUSY;
  1101. }
  1102. if (ideInternalVerifierFlags & VFLAGS_RW_ERROR) {
  1103. return IDE_STATUS_ERROR;
  1104. }
  1105. */
  1106. return status;
  1107. }
  1108. UCHAR
  1109. ViIdeGetErrorByte(
  1110. PIDE_REGISTERS_1 BaseIoAddress
  1111. )
  1112. /**++
  1113. Description:
  1114. Depending on the internalVerifier flag (set by the other verifier routines),
  1115. this function will return the appropriate error value. However, if the device
  1116. reports an actual error (as indicated by the internalverifier flag),
  1117. it is returned unchanged.
  1118. Arguments:
  1119. BaseIoAddress : Task file registers
  1120. Return Value:
  1121. The error byte.
  1122. --**/
  1123. {
  1124. UCHAR error = IdePortInPortByte(BaseIoAddress->Error);
  1125. /*
  1126. UCHAR deviceSelect = IdePortInPortByte(BaseIoAddress->DriveSelect);
  1127. UCHAR channel = ((ULONG)(BaseIoAddress->RegistersBaseAddress) == 0x1f0) ? 0: 1;
  1128. PFDO_EXTENSION fdoExtension = ViIdeExtensionTable[channel];
  1129. ULONG target = (deviceSelect == 0xA0)? 0: 1;
  1130. ULONG ideInternalVerifierFlags;
  1131. ULONG dFlags;
  1132. if (fdoExtension == NULL ) {
  1133. return error;
  1134. }
  1135. ideInternalVerifierFlags = fdoExtension->IdeInternalVerifierFlags[target];
  1136. dFlags = fdoExtension->HwDeviceExtension->DeviceFlags[target];
  1137. //
  1138. // return error if an actual error was reproted
  1139. //
  1140. if (ideInternalVerifierFlags & VFLAGS_ACTUAL_ERROR) {
  1141. CLRMASK(fdoExtension->IdeInternalVerifierFlags[target], VFLAGS_ACTUAL_ERROR);
  1142. return error;
  1143. }
  1144. if (ideInternalVerifierFlags & VFLAGS_CRC_ERROR) {
  1145. if (dFlags & DFLAGS_ATAPI_DEVICE) {
  1146. error = SCSI_SENSE_HARDWARE_ERROR << 4;
  1147. } else {
  1148. error = IDE_ERROR_CRC_ERROR | IDE_ERROR_COMMAND_ABORTED;
  1149. }
  1150. return error;
  1151. }
  1152. */
  1153. return error;
  1154. }
  1155. #endif
  1156. #ifdef IDE_MEASURE_BUSSCAN_SPEED
  1157. VOID
  1158. LogBusScanStartTimer(
  1159. PLARGE_INTEGER TickCount
  1160. )
  1161. {
  1162. KeQueryTickCount(TickCount);
  1163. return;
  1164. }
  1165. ULONG
  1166. LogBusScanStopTimer(
  1167. PLARGE_INTEGER TickCount
  1168. )
  1169. {
  1170. LARGE_INTEGER tickCount2;
  1171. LARGE_INTEGER numMs;
  1172. KeQueryTickCount(&tickCount2);
  1173. numMs.QuadPart = ((tickCount2.QuadPart - TickCount->QuadPart) * KeQueryTimeIncrement()) / (10 * 1000);
  1174. return(numMs.u.LowPart);
  1175. }
  1176. #endif
  1177. VOID
  1178. FASTCALL
  1179. IdePortLogNoMemoryErrorFn(
  1180. IN PVOID DeviceExtension,
  1181. IN ULONG TargetId,
  1182. IN POOL_TYPE PoolType,
  1183. IN SIZE_T Size,
  1184. IN ULONG FailureLocationId,
  1185. IN ULONG Tag
  1186. )
  1187. /*++
  1188. Routine Description:
  1189. This routine writes a message to the event log indicating that an
  1190. allocation failure has occurred.
  1191. Arguments:
  1192. DeviceExtension - Fdo Extension
  1193. TargetId - The target Id of the device that the request was to be sent to
  1194. PoolType - identifies the pool the failed allocation attempt was from.
  1195. Size - indicates the number of bytes that the failed allocation
  1196. attempt tried to obtain.
  1197. Tag - identifies the pool tag associated with the failed
  1198. allocation.
  1199. LocationId - identifies the location in the source code where it failed
  1200. Return Value:
  1201. VOID
  1202. --*/
  1203. {
  1204. NTSTATUS status;
  1205. PFDO_EXTENSION deviceExtension = (PFDO_EXTENSION) (DeviceExtension);
  1206. PIO_ERROR_LOG_PACKET errorLogEntry;
  1207. PIO_ERROR_LOG_PACKET currentValue;
  1208. InterlockedIncrement(&deviceExtension->NumMemoryFailure);
  1209. //
  1210. // Try to allocate a new error log event.
  1211. //
  1212. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1213. deviceExtension->DeviceObject,
  1214. ALLOC_FAILURE_LOGSIZE
  1215. );
  1216. //
  1217. // If we could not allocate a log event, we check the device extension to
  1218. // see if it has a reserve event we can use. If we cannot get the device
  1219. // extension or if it does not contain a reserve event, we return
  1220. // without logging the allocation failure.
  1221. //
  1222. if (errorLogEntry == NULL) {
  1223. //
  1224. // Get the reserve event in the device extension. The reserve event
  1225. // may have already been used, so it's possible that it is NULL. If
  1226. // this is the case, we give up and return.
  1227. //
  1228. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  1229. deviceExtension->ReserveAllocFailureLogEntry[TargetId];
  1230. if (errorLogEntry == NULL) {
  1231. DebugPrint((1, "IdePortLogAllocationFailureFn: no reserve packet\n"));
  1232. return;
  1233. }
  1234. //
  1235. // We have to ensure that we are the only instance to use this
  1236. // event. To do so, we attempt to NULL the event in the driver
  1237. // extension. If somebody else beats us to it, they own the
  1238. // event and we have to give up.
  1239. //
  1240. currentValue = InterlockedCompareExchangePointer(
  1241. &(deviceExtension->ReserveAllocFailureLogEntry[TargetId]),
  1242. NULL,
  1243. errorLogEntry
  1244. );
  1245. if (errorLogEntry != currentValue) {
  1246. DebugPrint((1, "IdePortLogAllocationFailureFn: someone already owns packet\n"));
  1247. return;
  1248. }
  1249. }
  1250. //
  1251. // Log the error
  1252. //
  1253. errorLogEntry->ErrorCode = IO_WARNING_ALLOCATION_FAILED;
  1254. errorLogEntry->SequenceNumber = 0;
  1255. errorLogEntry->MajorFunctionCode = 0;
  1256. errorLogEntry->RetryCount = 0;
  1257. errorLogEntry->UniqueErrorValue = 0x10;
  1258. errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  1259. errorLogEntry->DumpDataSize = 4 * sizeof(ULONG);
  1260. errorLogEntry->DumpData[0] = TargetId;
  1261. errorLogEntry->DumpData[1] = FailureLocationId;
  1262. errorLogEntry->DumpData[2] = PtrToUlong((PVOID)Size);
  1263. errorLogEntry->DumpData[3] = Tag;
  1264. IoWriteErrorLogEntry(errorLogEntry);
  1265. }