Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1590 lines
39 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. SrbData->IdeCommandLogIndex = ( SrbData->IdeCommandLogIndex + 1) % MAX_COMMAND_LOG_ENTRIES;
  888. return;
  889. }
  890. VOID
  891. IdeLogSaveTaskFile(
  892. PSRB_DATA SrbData,
  893. PIDE_REGISTERS_1 BaseIoAddress
  894. )
  895. {
  896. PCOMMAND_LOG cmdLog = &(SrbData->IdeCommandLog[SrbData->IdeCommandLogIndex]);
  897. if (cmdLog == NULL) {
  898. return;
  899. }
  900. AtapiTaskRegisterSnapshot(BaseIoAddress, &(cmdLog->FinalTaskFile));
  901. return;
  902. }
  903. VOID
  904. IdeLogBmStatus(
  905. PSCSI_REQUEST_BLOCK Srb,
  906. BMSTATUS BmStatus
  907. )
  908. {
  909. PSRB_DATA srbData = IdeGetSrbData(NULL, Srb);
  910. PCOMMAND_LOG cmdLog;
  911. if (srbData == NULL) {
  912. return;
  913. }
  914. cmdLog = &(srbData->IdeCommandLog[srbData->IdeCommandLogIndex]);
  915. if (cmdLog == NULL) {
  916. return;
  917. }
  918. cmdLog->BmStatus = BmStatus;
  919. return;
  920. }
  921. VOID
  922. IdeLogFreeCommandLog(
  923. PSRB_DATA SrbData
  924. )
  925. {
  926. PCOMMAND_LOG cmdLog = SrbData->IdeCommandLog;
  927. if (cmdLog) {
  928. ExFreePool(cmdLog);
  929. }
  930. SrbData->IdeCommandLog = NULL;
  931. SrbData->IdeCommandLogIndex = 0;
  932. }
  933. #endif
  934. #ifdef ENABLE_ATAPI_VERIFIER
  935. PVOID ViIdeExtensionTable[2];
  936. #define VFLAGS_FORCE_TIMEOUT (1<<0)
  937. #define VFLAGS_DMA_TIMEOUT (1<<1)
  938. #define VFLAGS_CFLUSH_TIMEOUT (1<<2)
  939. #define VFLAGS_DEVICE_CHANGE (1<<3)
  940. #define VFLAGS_MISSING_DEVICE (1<<4)
  941. #define VFLAGS_ACTUAL_ERROR (1<<5)
  942. #define VFLAGS_CRC_ERROR (1<<6)
  943. #define VFLAGS_BUSY_ERROR (1<<7)
  944. #define VFLAGS_RW_ERROR (1<<8)
  945. VOID
  946. ViIdeInitVerifierSettings(
  947. IN PFDO_EXTENSION FdoExtension
  948. )
  949. {
  950. }
  951. BOOLEAN
  952. ViIdeGenerateDmaTimeout(
  953. IN PVOID HwDeviceExtension,
  954. IN BOOLEAN DmaInProgress
  955. )
  956. {
  957. PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
  958. PFDO_EXTENSION fdoExtension = ((PFDO_EXTENSION)HwDeviceExtension - 1);
  959. PSCSI_REQUEST_BLOCK srb = hwDeviceExtension->CurrentSrb;
  960. ULONG ideInternalVerifierFlags ;
  961. ASSERT(srb);
  962. ideInternalVerifierFlags = fdoExtension->IdeInternalVerifierFlags[srb->TargetId];
  963. if (ideInternalVerifierFlags & VFLAGS_FORCE_TIMEOUT) {
  964. return TRUE;
  965. }
  966. if (DmaInProgress && (ideInternalVerifierFlags & VFLAGS_DMA_TIMEOUT)) {
  967. return TRUE;
  968. }
  969. if ((srb->Function == SRB_FUNCTION_ATA_PASS_THROUGH) ||
  970. (srb->Function == SRB_FUNCTION_ATA_POWER_PASS_THROUGH)) {
  971. PATA_PASS_THROUGH ataPassThroughData;
  972. PIDEREGS pIdeReg;
  973. ataPassThroughData = srb->DataBuffer;
  974. pIdeReg = &ataPassThroughData->IdeReg;
  975. if ((ideInternalVerifierFlags & VFLAGS_CFLUSH_TIMEOUT) &&
  976. (pIdeReg->bCommandReg == hwDeviceExtension->DeviceParameters[srb->TargetId].IdeFlushCommand )) {
  977. return TRUE;
  978. }
  979. }
  980. return FALSE;
  981. }
  982. ULONG
  983. ViIdeFakeDeviceChange(
  984. IN PFDO_EXTENSION FdoExtension,
  985. ULONG Target
  986. )
  987. {
  988. ULONG ideInternalVerifierFlags = FdoExtension->IdeDebugVerifierFlags[Target];
  989. if (ideInternalVerifierFlags & VFLAGS_DEVICE_CHANGE) {
  990. return 1;
  991. }
  992. return 0;
  993. }
  994. BOOLEAN
  995. ViIdeFakeMissingDevice(
  996. IN PFDO_EXTENSION FdoExtension,
  997. ULONG Target
  998. )
  999. {
  1000. ULONG ideInternalVerifierFlags = FdoExtension->IdeDebugVerifierFlags[Target];
  1001. if (ideInternalVerifierFlags & VFLAGS_MISSING_DEVICE) {
  1002. return TRUE;
  1003. }
  1004. return FALSE;
  1005. }
  1006. VOID
  1007. ViAtapiInterrupt(
  1008. IN PFDO_EXTENSION FdoExtension
  1009. )
  1010. {
  1011. PHW_DEVICE_EXTENSION hwDeviceExtension = FdoExtension->HwDeviceExtension;
  1012. PIDE_REGISTERS_1 baseIoAddress = &(hwDeviceExtension->BaseIoAddress1);
  1013. PSCSI_REQUEST_BLOCK srb = hwDeviceExtension->CurrentSrb;
  1014. ULONG target;
  1015. //DebugPrint((0, "verifier interrupt fdoe = %x, b=%x\n", FdoExtension, baseIoAddress->RegistersBaseAddress));
  1016. if ((ULONG)(baseIoAddress->RegistersBaseAddress) == 0x1f0) {
  1017. ViIdeExtensionTable[0]=FdoExtension;
  1018. } else {
  1019. ViIdeExtensionTable[1]=FdoExtension;
  1020. }
  1021. if (srb == NULL) {
  1022. return ;
  1023. }
  1024. target = srb->TargetId;
  1025. //
  1026. // Generate timeouts
  1027. //
  1028. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_DMA_TIMEOUT) {
  1029. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_DMA_TIMEOUT;
  1030. return;
  1031. }
  1032. //
  1033. // Generate CRC errors
  1034. //
  1035. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_CRC_ERROR) {
  1036. if (FdoExtension->IdeVerifierEventCount[target][CrcEvent] >= FdoExtension->IdeVerifierEventFrequency[target][CrcEvent]) {
  1037. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_CRC_ERROR;
  1038. FdoExtension->IdeVerifierEventCount[target][CrcEvent]=0;
  1039. return;
  1040. } else {
  1041. FdoExtension->IdeVerifierEventCount[target][RwEvent]++;
  1042. }
  1043. }
  1044. //
  1045. // Generate Busy errors
  1046. //
  1047. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_BUSY_ERROR) {
  1048. if (FdoExtension->IdeVerifierEventCount[target][BusyEvent] >= FdoExtension->IdeVerifierEventFrequency[target][BusyEvent]) {
  1049. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_BUSY_ERROR;
  1050. FdoExtension->IdeVerifierEventCount[target][BusyEvent]=0;
  1051. return;
  1052. } else {
  1053. FdoExtension->IdeVerifierEventCount[target][BusyEvent]++;
  1054. }
  1055. }
  1056. //
  1057. // Generate Read write errors
  1058. //
  1059. if (FdoExtension->IdeDebugVerifierFlags[target] & VFLAGS_RW_ERROR) {
  1060. if (FdoExtension->IdeVerifierEventCount[target][RwEvent] >= FdoExtension->IdeVerifierEventFrequency[target][RwEvent]) {
  1061. FdoExtension->IdeInternalVerifierFlags[target] |= VFLAGS_RW_ERROR;
  1062. FdoExtension->IdeVerifierEventCount[target][RwEvent]=0;
  1063. return;
  1064. } else {
  1065. FdoExtension->IdeVerifierEventCount[target][RwEvent]++;
  1066. }
  1067. }
  1068. // ViIdeGenerateReadWriteErrors(FdoExtension);
  1069. // ViIdeGenerateDmaErrors(FdoExtension);
  1070. // ViIdeFakeHungController(FdoExtension);
  1071. return ;
  1072. }
  1073. UCHAR
  1074. ViIdeGetBaseStatus(
  1075. PIDE_REGISTERS_1 BaseIoAddress
  1076. )
  1077. {
  1078. UCHAR status = IdePortInPortByte((BaseIoAddress)->Command);
  1079. /*
  1080. UCHAR deviceSelect = IdePortInPortByte(BaseIoAddress->DriveSelect);
  1081. UCHAR channel = ((ULONG)(BaseIoAddress->RegistersBaseAddress) == 0x1f0) ? 0: 1;
  1082. PFDO_EXTENSION fdoExtension = ViIdeExtensionTable[channel];
  1083. ULONG target = (deviceSelect == 0xA0)? 0: 1;
  1084. ULONG ideInternalVerifierFlags;
  1085. ULONG dFlags;
  1086. if (fdoExtension == NULL) {
  1087. return status;
  1088. }
  1089. ideInternalVerifierFlags = fdoExtension->IdeInternalVerifierFlags[target];
  1090. dFlags = fdoExtension->HwDeviceExtension->DeviceFlags[target];
  1091. if (status & IDE_STATUS_ERROR) {
  1092. SETMASK(fdoExtension->IdeInternalVerifierFlags[target], VFLAGS_ACTUAL_ERROR);
  1093. return status;
  1094. }
  1095. if (ideInternalVerifierFlags & VFLAGS_CRC_ERROR) {
  1096. return IDE_STATUS_ERROR;
  1097. }
  1098. if (ideInternalVerifierFlags & VFLAGS_BUSY_ERROR) {
  1099. return IDE_STATUS_BUSY;
  1100. }
  1101. if (ideInternalVerifierFlags & VFLAGS_RW_ERROR) {
  1102. return IDE_STATUS_ERROR;
  1103. }
  1104. */
  1105. return status;
  1106. }
  1107. UCHAR
  1108. ViIdeGetErrorByte(
  1109. PIDE_REGISTERS_1 BaseIoAddress
  1110. )
  1111. /**++
  1112. Description:
  1113. Depending on the internalVerifier flag (set by the other verifier routines),
  1114. this function will return the appropriate error value. However, if the device
  1115. reports an actual error (as indicated by the internalverifier flag),
  1116. it is returned unchanged.
  1117. Arguments:
  1118. BaseIoAddress : Task file registers
  1119. Return Value:
  1120. The error byte.
  1121. --**/
  1122. {
  1123. UCHAR error = IdePortInPortByte(BaseIoAddress->Error);
  1124. /*
  1125. UCHAR deviceSelect = IdePortInPortByte(BaseIoAddress->DriveSelect);
  1126. UCHAR channel = ((ULONG)(BaseIoAddress->RegistersBaseAddress) == 0x1f0) ? 0: 1;
  1127. PFDO_EXTENSION fdoExtension = ViIdeExtensionTable[channel];
  1128. ULONG target = (deviceSelect == 0xA0)? 0: 1;
  1129. ULONG ideInternalVerifierFlags;
  1130. ULONG dFlags;
  1131. if (fdoExtension == NULL ) {
  1132. return error;
  1133. }
  1134. ideInternalVerifierFlags = fdoExtension->IdeInternalVerifierFlags[target];
  1135. dFlags = fdoExtension->HwDeviceExtension->DeviceFlags[target];
  1136. //
  1137. // return error if an actual error was reproted
  1138. //
  1139. if (ideInternalVerifierFlags & VFLAGS_ACTUAL_ERROR) {
  1140. CLRMASK(fdoExtension->IdeInternalVerifierFlags[target], VFLAGS_ACTUAL_ERROR);
  1141. return error;
  1142. }
  1143. if (ideInternalVerifierFlags & VFLAGS_CRC_ERROR) {
  1144. if (dFlags & DFLAGS_ATAPI_DEVICE) {
  1145. error = SCSI_SENSE_HARDWARE_ERROR << 4;
  1146. } else {
  1147. error = IDE_ERROR_CRC_ERROR | IDE_ERROR_COMMAND_ABORTED;
  1148. }
  1149. return error;
  1150. }
  1151. */
  1152. return error;
  1153. }
  1154. #endif
  1155. #ifdef IDE_MEASURE_BUSSCAN_SPEED
  1156. VOID
  1157. LogBusScanStartTimer(
  1158. PLARGE_INTEGER TickCount
  1159. )
  1160. {
  1161. KeQueryTickCount(TickCount);
  1162. return;
  1163. }
  1164. ULONG
  1165. LogBusScanStopTimer(
  1166. PLARGE_INTEGER TickCount
  1167. )
  1168. {
  1169. LARGE_INTEGER tickCount2;
  1170. LARGE_INTEGER numMs;
  1171. KeQueryTickCount(&tickCount2);
  1172. numMs.QuadPart = ((tickCount2.QuadPart - TickCount->QuadPart) * KeQueryTimeIncrement()) / (10 * 1000);
  1173. return(numMs.u.LowPart);
  1174. }
  1175. #endif
  1176. VOID
  1177. FASTCALL
  1178. IdePortLogNoMemoryErrorFn(
  1179. IN PVOID DeviceExtension,
  1180. IN ULONG TargetId,
  1181. IN POOL_TYPE PoolType,
  1182. IN SIZE_T Size,
  1183. IN ULONG FailureLocationId,
  1184. IN ULONG Tag
  1185. )
  1186. /*++
  1187. Routine Description:
  1188. This routine writes a message to the event log indicating that an
  1189. allocation failure has occurred.
  1190. Arguments:
  1191. DeviceExtension - Fdo Extension
  1192. TargetId - The target Id of the device that the request was to be sent to
  1193. PoolType - identifies the pool the failed allocation attempt was from.
  1194. Size - indicates the number of bytes that the failed allocation
  1195. attempt tried to obtain.
  1196. Tag - identifies the pool tag associated with the failed
  1197. allocation.
  1198. LocationId - identifies the location in the source code where it failed
  1199. Return Value:
  1200. VOID
  1201. --*/
  1202. {
  1203. NTSTATUS status;
  1204. PFDO_EXTENSION deviceExtension = (PFDO_EXTENSION) (DeviceExtension);
  1205. PIO_ERROR_LOG_PACKET errorLogEntry;
  1206. PIO_ERROR_LOG_PACKET currentValue;
  1207. InterlockedIncrement(&deviceExtension->NumMemoryFailure);
  1208. //
  1209. // Try to allocate a new error log event.
  1210. //
  1211. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  1212. deviceExtension->DeviceObject,
  1213. ALLOC_FAILURE_LOGSIZE
  1214. );
  1215. //
  1216. // If we could not allocate a log event, we check the device extension to
  1217. // see if it has a reserve event we can use. If we cannot get the device
  1218. // extension or if it does not contain a reserve event, we return
  1219. // without logging the allocation failure.
  1220. //
  1221. if (errorLogEntry == NULL) {
  1222. //
  1223. // Get the reserve event in the device extension. The reserve event
  1224. // may have already been used, so it's possible that it is NULL. If
  1225. // this is the case, we give up and return.
  1226. //
  1227. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  1228. deviceExtension->ReserveAllocFailureLogEntry[TargetId];
  1229. if (errorLogEntry == NULL) {
  1230. DebugPrint((1, "IdePortLogAllocationFailureFn: no reserve packet\n"));
  1231. return;
  1232. }
  1233. //
  1234. // We have to ensure that we are the only instance to use this
  1235. // event. To do so, we attempt to NULL the event in the driver
  1236. // extension. If somebody else beats us to it, they own the
  1237. // event and we have to give up.
  1238. //
  1239. currentValue = InterlockedCompareExchangePointer(
  1240. &(deviceExtension->ReserveAllocFailureLogEntry[TargetId]),
  1241. NULL,
  1242. errorLogEntry
  1243. );
  1244. if (errorLogEntry != currentValue) {
  1245. DebugPrint((1, "IdePortLogAllocationFailureFn: someone already owns packet\n"));
  1246. return;
  1247. }
  1248. }
  1249. //
  1250. // Log the error
  1251. //
  1252. errorLogEntry->ErrorCode = IO_WARNING_ALLOCATION_FAILED;
  1253. errorLogEntry->SequenceNumber = 0;
  1254. errorLogEntry->MajorFunctionCode = 0;
  1255. errorLogEntry->RetryCount = 0;
  1256. errorLogEntry->UniqueErrorValue = 0x10;
  1257. errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  1258. errorLogEntry->DumpDataSize = 4 * sizeof(ULONG);
  1259. errorLogEntry->DumpData[0] = TargetId;
  1260. errorLogEntry->DumpData[1] = FailureLocationId;
  1261. errorLogEntry->DumpData[2] = PtrToUlong((PVOID)Size);
  1262. errorLogEntry->DumpData[3] = Tag;
  1263. IoWriteErrorLogEntry(errorLogEntry);
  1264. }