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.

6023 lines
162 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. vfhal.c
  5. Abstract:
  6. This module contains the routines to verify hal usage & apis.
  7. Author:
  8. Jordan Tigani (jtigani) 12-Nov-1999
  9. Revision History:
  10. --*/
  11. // needed for data pointer to function pointer conversions
  12. #pragma warning(disable:4054) // type cast from function pointer to PVOID (data pointer)
  13. #pragma warning(disable:4055) // type cast from PVOID (data pointer) to function pointer
  14. #include "vfdef.h"
  15. #include "vihal.h"
  16. #define THUNKED_API
  17. //
  18. // We are keying on the IO verifier level.
  19. //
  20. extern BOOLEAN IopVerifierOn;
  21. extern ULONG IovpVerifierLevel;
  22. //
  23. // Use this to not generate false errors when we enter the debugger
  24. //
  25. extern LARGE_INTEGER KdTimerStart;
  26. // ===================================
  27. // Flags that can be set on the fly...
  28. // ===================================
  29. //
  30. //
  31. // Hal verifier has two parts (at this point) -- the timer verifier and the
  32. // dma verifier. The timer verifier only runs when the hal is being verified.
  33. //
  34. // DMA verifier runs when ioverifier is >= level 3 *or*
  35. // when HKLM\System\CCS\Control\Session Manager\I/O System\VerifyDma is
  36. // nonzero.
  37. //
  38. ULONG ViVerifyDma = FALSE;
  39. LOGICAL ViVerifyPerformanceCounter = FALSE;
  40. //
  41. // Specify whether we want to double buffer all dma transfers for hooked
  42. // drivers. This is an easy way to tell whether the driver will work on a
  43. // PAE system without having to do extensive testing on a pae system.
  44. // It also adds a physical guard page to each side of each double buffered
  45. // page. Benefits of this is that it can catch hardware that over (or under)
  46. // writes its allocation.
  47. //
  48. LOGICAL ViDoubleBufferDma = TRUE;
  49. //
  50. // Specifies whether we want to use a physical guard page on either side
  51. // of common buffer allocations.
  52. //
  53. LOGICAL ViProtectBuffers = TRUE;
  54. //
  55. // Whether or not we can inject failures into DMA api calls.
  56. //
  57. LOGICAL ViInjectDmaFailures = FALSE;
  58. //
  59. // Internal debug flag ... useful to turn on certain debug features
  60. // at runtime.
  61. //
  62. LOGICAL ViSuperDebug = FALSE;
  63. // ======================================
  64. // Internal globals are set automatically
  65. // ======================================
  66. LOGICAL ViSufficientlyBootedForPcControl = FALSE;
  67. LOGICAL ViSufficientlyBootedForDmaFailure = FALSE;
  68. ULONG ViMaxMapRegistersPerAdapter = 0x20;
  69. ULONG ViAllocationsFailedDeliberately = 0;
  70. //
  71. // Wait 30 seconds after boot before we start imposing
  72. // consistency on the performance counter.
  73. // Once the performance counter bugs are fixed, this can be
  74. // lowered.
  75. // This one number is used for both Performance counter control
  76. // and dma failure injection.
  77. //
  78. LARGE_INTEGER ViRequiredTimeSinceBoot = {(LONG) 30 * 1000 * 1000, 0};
  79. //
  80. // When doing double buffering, we write this guy at the beginning and end
  81. // of every buffer to make sure that nobody overwrites their allocation
  82. //
  83. CHAR ViDmaVerifierTag[] = {'D','m','a','V','r','f','y','0'};
  84. BOOLEAN ViPenalties[] =
  85. {
  86. HVC_ASSERT, // HV_MISCELLANEOUS_ERROR
  87. HVC_ASSERT, // HV_PERFORMANCE_COUNTER_DECREASED
  88. HVC_WARN, // HV_PERFORMANCE_COUNTER_SKIPPED
  89. HVC_BUGCHECK, // HV_FREED_TOO_MANY_COMMON_BUFFERS
  90. HVC_BUGCHECK, // HV_FREED_TOO_MANY_ADAPTER_CHANNELS
  91. HVC_BUGCHECK, // HV_FREED_TOO_MANY_MAP_REGISTERS
  92. HVC_BUGCHECK, // HV_FREED_TOO_MANY_SCATTER_GATHER_LISTS
  93. HVC_ASSERT, // HV_LEFTOVER_COMMON_BUFFERS
  94. HVC_ASSERT, // HV_LEFTOVER_ADAPTER_CHANNELS
  95. HVC_ASSERT, // HV_LEFTOVER_MAP_REGISTERS
  96. HVC_ASSERT, // HV_LEFTOVER_SCATTER_GATHER_LISTS
  97. HVC_ASSERT, // HV_TOO_MANY_ADAPTER_CHANNELS
  98. HVC_ASSERT, // HV_TOO_MANY_MAP_REGISTERS
  99. HVC_ASSERT, // HV_DID_NOT_FLUSH_ADAPTER_BUFFERS
  100. HVC_BUGCHECK, // HV_DMA_BUFFER_NOT_LOCKED
  101. HVC_BUGCHECK, // HV_BOUNDARY_OVERRUN
  102. HVC_ASSERT, // HV_CANNOT_FREE_MAP_REGISTERS
  103. HVC_ASSERT, // HV_DID_NOT_PUT_ADAPTER
  104. HVC_WARN | HVC_ONCE, // HV_MDL_FLAGS_NOT_SET
  105. HVC_ASSERT, // HV_BAD_IRQL
  106. //
  107. // This is a hack that is in because almost nobody calls
  108. // PutDmaAdapter at the right Irql... so until it gets fixed, just
  109. // print out a warning so we don't have to assert on known situations.
  110. //
  111. HVC_ASSERT, // HV_BAD_IRQL_JUST_WARN
  112. HVC_WARN | HVC_ONCE, // HV_OUT_OF_MAP_REGISTERS
  113. HVC_ASSERT | HVC_ONCE, // HV_FLUSH_EMPTY_BUFFERS
  114. HVC_ASSERT, // HV_MISMATCHED_MAP_FLUSH
  115. HVC_BUGCHECK, // HV_ADAPTER_ALREADY_RELEASED
  116. HVC_BUGCHECK, // HV_NULL_DMA_ADAPTER
  117. HVC_IGNORE, // HV_MAP_FLUSH_NO_TRANSFER
  118. HVC_BUGCHECK, // HV_ADDRESS_NOT_IN_MDL
  119. HVC_BUGCHECK, // HV_DATA_LOSS
  120. HVC_BUGCHECK, // HV_DOUBLE_MAP_REGISTER
  121. HVC_ASSERT, // HV_OBSOLETE_API
  122. HVC_ASSERT, // HV_BAD_MDL
  123. HVC_ASSERT, // HV_FLUSH_NOT_MAPPED
  124. HVC_ASSERT | HVC_ONCE // HV_MAP_ZERO_LENGTH_BUFFER
  125. };
  126. HAL_VERIFIER_LOCKED_LIST ViAdapterList = {NULL,NULL,0};
  127. PVF_TIMER_INFORMATION ViTimerInformation;
  128. DMA_OPERATIONS ViDmaOperations =
  129. {
  130. sizeof(DMA_OPERATIONS),
  131. (PPUT_DMA_ADAPTER) VfPutDmaAdapter,
  132. (PALLOCATE_COMMON_BUFFER) VfAllocateCommonBuffer,
  133. (PFREE_COMMON_BUFFER) VfFreeCommonBuffer,
  134. (PALLOCATE_ADAPTER_CHANNEL) VfAllocateAdapterChannel,
  135. (PFLUSH_ADAPTER_BUFFERS) VfFlushAdapterBuffers,
  136. (PFREE_ADAPTER_CHANNEL) VfFreeAdapterChannel,
  137. (PFREE_MAP_REGISTERS) VfFreeMapRegisters,
  138. (PMAP_TRANSFER) VfMapTransfer,
  139. (PGET_DMA_ALIGNMENT) VfGetDmaAlignment,
  140. (PREAD_DMA_COUNTER) VfReadDmaCounter,
  141. (PGET_SCATTER_GATHER_LIST) VfGetScatterGatherList,
  142. (PPUT_SCATTER_GATHER_LIST) VfPutScatterGatherList,
  143. //
  144. // New DMA APIs
  145. //
  146. (PCALCULATE_SCATTER_GATHER_LIST_SIZE) VfCalculateScatterGatherListSize,
  147. (PBUILD_SCATTER_GATHER_LIST) VfBuildScatterGatherList,
  148. (PBUILD_MDL_FROM_SCATTER_GATHER_LIST) VfBuildMdlFromScatterGatherList
  149. };
  150. #if !defined (NO_LEGACY_DRIVERS)
  151. DMA_OPERATIONS ViLegacyDmaOperations =
  152. {
  153. sizeof(DMA_OPERATIONS),
  154. //
  155. // PutDmaAdapter cannot be called by name
  156. //
  157. (PPUT_DMA_ADAPTER) NULL,
  158. (PALLOCATE_COMMON_BUFFER) HalAllocateCommonBuffer,
  159. (PFREE_COMMON_BUFFER) HalFreeCommonBuffer,
  160. (PALLOCATE_ADAPTER_CHANNEL) IoAllocateAdapterChannel,
  161. (PFLUSH_ADAPTER_BUFFERS) IoFlushAdapterBuffers,
  162. (PFREE_ADAPTER_CHANNEL) IoFreeAdapterChannel,
  163. (PFREE_MAP_REGISTERS) IoFreeMapRegisters,
  164. (PMAP_TRANSFER) IoMapTransfer,
  165. //
  166. // HalGetDmaAlignmentRequirement isn't exported by legacy hals
  167. //
  168. (PGET_DMA_ALIGNMENT) NULL,
  169. (PREAD_DMA_COUNTER) HalReadDmaCounter,
  170. //
  171. // Scatter gather functions can never get called by name
  172. //
  173. NULL,
  174. NULL
  175. };
  176. #endif
  177. #ifdef ALLOC_PRAGMA
  178. #pragma alloc_text(INIT, VfHalVerifierInitialize)
  179. #pragma alloc_text(PAGEVRFY, VfGetDmaAdapter)
  180. #if !defined (NO_LEGACY_DRIVERS)
  181. #pragma alloc_text(PAGEVRFY, VfLegacyGetAdapter)
  182. #endif
  183. #pragma alloc_text(PAGEVRFY, VfPutDmaAdapter)
  184. #pragma alloc_text(PAGEVRFY, VfHalDeleteDevice)
  185. #pragma alloc_text(PAGEVRFY, VfAllocateCommonBuffer)
  186. #pragma alloc_text(PAGEVRFY, VfFreeCommonBuffer)
  187. #pragma alloc_text(PAGEVRFY, VfAllocateAdapterChannel)
  188. #pragma alloc_text(PAGEVRFY, VfAdapterCallback)
  189. #pragma alloc_text(PAGEVRFY, VfFreeAdapterChannel)
  190. #pragma alloc_text(PAGEVRFY, VfFreeMapRegisters)
  191. #pragma alloc_text(PAGEVRFY, VfMapTransfer)
  192. #pragma alloc_text(PAGEVRFY, VfFlushAdapterBuffers)
  193. #pragma alloc_text(PAGEVRFY, VfGetDmaAlignment)
  194. #pragma alloc_text(PAGEVRFY, VfReadDmaCounter)
  195. #pragma alloc_text(PAGEVRFY, VfGetScatterGatherList)
  196. #pragma alloc_text(PAGEVRFY, VfPutScatterGatherList)
  197. #pragma alloc_text(PAGEVRFY, VfQueryPerformanceCounter)
  198. #pragma alloc_text(PAGEVRFY, VfInitializeTimerInformation)
  199. #pragma alloc_text(PAGEVRFY, ViRefreshCallback)
  200. #pragma alloc_text(PAGEVRFY, VfInjectDmaFailure)
  201. #pragma alloc_text(PAGEVRFY, ViHookDmaAdapter)
  202. #pragma alloc_text(PAGEVRFY, ViGetAdapterInformation)
  203. #pragma alloc_text(PAGEVRFY, ViGetRealDmaOperation)
  204. #pragma alloc_text(PAGEVRFY, ViSpecialAllocateCommonBuffer)
  205. #pragma alloc_text(PAGEVRFY, ViSpecialFreeCommonBuffer)
  206. #pragma alloc_text(PAGEVRFY, ViAllocateMapRegisterFile)
  207. #pragma alloc_text(PAGEVRFY, ViFreeMapRegisterFile)
  208. #pragma alloc_text(PAGEVRFY, ViMapDoubleBuffer)
  209. #pragma alloc_text(PAGEVRFY, ViFlushDoubleBuffer)
  210. #pragma alloc_text(PAGEVRFY, ViFreeMapRegistersToFile)
  211. #pragma alloc_text(PAGEVRFY, ViFindMappedRegisterInFile)
  212. #pragma alloc_text(PAGEVRFY, ViCheckAdapterBuffers)
  213. #pragma alloc_text(PAGEVRFY, ViTagBuffer)
  214. #pragma alloc_text(PAGEVRFY, ViCheckTag)
  215. #pragma alloc_text(PAGEVRFY, ViInitializePadding)
  216. #pragma alloc_text(PAGEVRFY, ViCheckPadding)
  217. #pragma alloc_text(PAGEVRFY, ViHasBufferBeenTouched)
  218. #pragma alloc_text(PAGEVRFY, VfAssert)
  219. #pragma alloc_text(PAGEVRFY, VfBuildScatterGatherList)
  220. #pragma alloc_text(PAGEVRFY, VfAllocateCrashDumpRegisters)
  221. #pragma alloc_text(PAGEVRFY, VfScatterGatherCallback)
  222. #pragma alloc_text(PAGEVRFY, ViAllocateContiguousMemory)
  223. #if defined (_X86_)
  224. #pragma alloc_text(PAGEVRFY, ViRdtscX86)
  225. #elif defined(_IA64_)
  226. #pragma alloc_text(PAGEVRFY, ViRdtscIA64)
  227. #else
  228. #pragma alloc_text(PAGEVRFY, ViRdtscNull)
  229. #endif
  230. #endif
  231. typedef
  232. LARGE_INTEGER
  233. (*PKE_QUERY_PERFORMANCE_COUNTER) (
  234. IN PLARGE_INTEGER PerformanceFrequency OPTIONAL
  235. );
  236. VOID
  237. ViRefreshCallback(
  238. IN PKDPC Dpc,
  239. IN PVOID DeferredContext,
  240. IN PVOID SystemArgument1,
  241. IN PVOID SystemArgument2
  242. )
  243. {
  244. UNREFERENCED_PARAMETER(Dpc);
  245. UNREFERENCED_PARAMETER(DeferredContext);
  246. UNREFERENCED_PARAMETER(SystemArgument1);
  247. UNREFERENCED_PARAMETER(SystemArgument2);
  248. VfQueryPerformanceCounter(NULL);
  249. } // ViRefreshCallback //
  250. VOID
  251. VfInitializeTimerInformation()
  252. /*++
  253. Routine Description:
  254. Sets up all the performance counter refresh timer.
  255. Arguments:
  256. Not used.
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. ULONG timerPeriod;
  262. LARGE_INTEGER performanceCounter;
  263. PAGED_CODE();
  264. ViTimerInformation = ExAllocatePoolWithTag(NonPagedPool, sizeof(VF_TIMER_INFORMATION), HAL_VERIFIER_POOL_TAG);
  265. if (! ViTimerInformation )
  266. return;
  267. RtlZeroMemory(ViTimerInformation, sizeof(VF_TIMER_INFORMATION));
  268. KeInitializeTimer(&ViTimerInformation->RefreshTimer);
  269. KeInitializeDpc(&ViTimerInformation->RefreshDpc,
  270. ViRefreshCallback,
  271. NULL
  272. );
  273. //
  274. // Find out the performance counter frequency
  275. //
  276. performanceCounter = KeQueryPerformanceCounter(
  277. (PLARGE_INTEGER) &ViTimerInformation->PerformanceFrequency);
  278. SAFE_WRITE_TIMER64(ViTimerInformation->UpperBound,
  279. RtlConvertLongToLargeInteger(-1));
  280. SAFE_WRITE_TIMER64(ViTimerInformation->LastKdStartTime, KdTimerStart);
  281. //
  282. // We are going to be setting a timer to go off every millisecond, so
  283. // we need the timer tick interval to be as low as possible.
  284. //
  285. // N.B The system can't change this value after we have set it to a
  286. // minimum so we don't have to worry about the TimeIncrement value
  287. // changing.
  288. //
  289. ExSetTimerResolution(0, TRUE);
  290. //
  291. // Calculate how far the performance counter goes in one clock tick
  292. //
  293. // Counts Counts Seconds
  294. // ------ = ------ * -------
  295. // Tick Second Tick
  296. //
  297. // Second Counts 100 nanoSeconds
  298. // = -------------------- * ------ * ---------------
  299. // 10^7 100 nanoSeconds Second Tick
  300. ViTimerInformation->CountsPerTick = (ULONG)
  301. (ViTimerInformation->PerformanceFrequency.QuadPart *
  302. KeQueryTimeIncrement() / ( 10 * 1000 * 1000));
  303. //
  304. // Set our refresh timer to wake up every timer tick to keep the
  305. // upper bound calculation in the right ballpark.
  306. // Round the system increment time to nearest millisecond * convert
  307. // 100 nanosecond units to milliseconds
  308. //
  309. timerPeriod = (KeQueryTimeIncrement() + 400 * 10) / (1000 * 10);
  310. KeSetTimerEx(
  311. &ViTimerInformation->RefreshTimer,
  312. RtlConvertLongToLargeInteger(-1 * 1000 * 1000), // start in a second
  313. timerPeriod,
  314. &ViTimerInformation->RefreshDpc
  315. );
  316. } // ViInitializeTimerInformation //
  317. VOID
  318. VfHalVerifierInitialize(
  319. VOID
  320. )
  321. /*++
  322. Routine Description:
  323. Sets up all data structures etc. needed to run hal verifier.
  324. Arguments:
  325. Return Value:
  326. None.
  327. --*/
  328. {
  329. VF_INITIALIZE_LOCKED_LIST(&ViAdapterList);
  330. if ( VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_VERIFY_DMA)) {
  331. ViVerifyDma = TRUE;
  332. }
  333. if ( VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_DOUBLE_BUFFER_DMA)) {
  334. ViDoubleBufferDma = TRUE;
  335. }
  336. if ( VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_VERIFY_PERFORMANCE_COUNTER)) {
  337. ViVerifyPerformanceCounter = TRUE;
  338. }
  339. } // VfHalVerifierInitialize //
  340. THUNKED_API
  341. LARGE_INTEGER
  342. VfQueryPerformanceCounter (
  343. IN PLARGE_INTEGER PerformanceFrequency OPTIONAL
  344. )
  345. /*++
  346. Routine Description:
  347. Make sure that the performance counter is correct. For now, just ensure
  348. that the pc is strictly increasing, but eventually we are going to keep
  349. track of processor cycle counts (on X86 of course). This is complicated
  350. by the fact that we want to run on any arbitrary hal -- and the time
  351. stamp counter will get reset when we hibernate or otherwise restart a
  352. processor (as in a failover restart on a Fault tolerant system).
  353. N.B. This function can be called from any IRQL and on any processor --
  354. we should try to protect ourselves accordingly
  355. Arguments:
  356. PerformanceFrequency -- lets us query the performance frequency.
  357. Return Value:
  358. Current 64-bit performance counter value.
  359. --*/
  360. {
  361. LARGE_INTEGER performanceCounter;
  362. LARGE_INTEGER lastPerformanceCounter;
  363. PTIMER_TICK currentTickInformation;
  364. LARGE_INTEGER upperBound;
  365. LARGE_INTEGER tickCount;
  366. LARGE_INTEGER lastTickCount;
  367. LARGE_INTEGER nextUpperBound;
  368. ULONG currentCounter;
  369. if (! ViVerifyPerformanceCounter)
  370. {
  371. return KeQueryPerformanceCounter(PerformanceFrequency);
  372. }
  373. if (! ViSufficientlyBootedForPcControl)
  374. //
  375. // If we're not worrying about performance counters yet
  376. // call the real function
  377. //
  378. {
  379. LARGE_INTEGER currentTime;
  380. KIRQL currentIrql;
  381. performanceCounter = KeQueryPerformanceCounter(PerformanceFrequency);
  382. currentIrql = KeGetCurrentIrql();
  383. KeQuerySystemTime(&currentTime);
  384. //
  385. // We can't call VfInitializeTimerInformation unless we're at
  386. // less than dispatch level
  387. //
  388. if (currentIrql < DISPATCH_LEVEL &&
  389. currentTime.QuadPart > KeBootTime.QuadPart +
  390. ViRequiredTimeSinceBoot.QuadPart )
  391. {
  392. ViSufficientlyBootedForPcControl = TRUE;
  393. VfInitializeTimerInformation();
  394. if (! ViTimerInformation )
  395. {
  396. //
  397. // If we failed initialization, we're out of luck.
  398. //
  399. ViVerifyPerformanceCounter = FALSE;
  400. return performanceCounter;
  401. }
  402. }
  403. else
  404. //
  405. // If we haven't booted enough yet, just return the current
  406. // performance counter
  407. //
  408. {
  409. return performanceCounter;
  410. }
  411. } // ! ViSufficientlyBooted //
  412. ASSERT(ViTimerInformation);
  413. //
  414. // Find out what the last performance counter value was
  415. // (bottom 32 bits may rollover while we are in the middle of reading so
  416. // we have to do a bit of extra work).
  417. //
  418. SAFE_READ_TIMER64( lastPerformanceCounter,
  419. ViTimerInformation->LastPerformanceCounter );
  420. performanceCounter = KeQueryPerformanceCounter(PerformanceFrequency);
  421. //
  422. // Make sure that PC hasn't gone backwards
  423. //
  424. VF_ASSERT(
  425. performanceCounter.QuadPart >= lastPerformanceCounter.QuadPart,
  426. HV_PERFORMANCE_COUNTER_DECREASED,
  427. ( "Performance counter has decreased-- PC1: %I64x, PC0: %I64x",
  428. performanceCounter.QuadPart,
  429. lastPerformanceCounter.QuadPart )
  430. );
  431. //
  432. // We're not only checking that the performance counter increased,
  433. // we're making sure that it didn't increase too much
  434. //
  435. SAFE_READ_TIMER64( lastTickCount,
  436. ViTimerInformation->LastTickCount );
  437. //
  438. // The hal takes care of synchronization for this.
  439. // N.B.If an interrupt comes in between the performance counter &
  440. // tick count the tick count could increase in the meantime --
  441. // this isn't a problem because it will just make our upper
  442. // bound a bit higher.
  443. //
  444. KeQueryTickCount(&tickCount);
  445. //
  446. // Save this Perf count & tick count values so we can dump the most
  447. // recent ones from the debugger (find the index into our saved
  448. // counter list)
  449. //
  450. currentCounter = InterlockedIncrement(
  451. (PLONG)(&ViTimerInformation->CurrentCounter) ) % MAX_COUNTERS;
  452. currentTickInformation =
  453. &ViTimerInformation->SavedTicks[currentCounter];
  454. currentTickInformation->PerformanceCounter = performanceCounter;
  455. currentTickInformation->TimerTick = tickCount;
  456. currentTickInformation->TimeStampCounter = ViRdtsc();
  457. currentTickInformation->Processor = KeGetCurrentProcessorNumber();
  458. //
  459. // Tentatively set the next upper bound too... set a whole second
  460. // ahead.
  461. //
  462. nextUpperBound.QuadPart = performanceCounter.QuadPart +
  463. ViTimerInformation->PerformanceFrequency.QuadPart;
  464. //
  465. // If it has been too long since we last called
  466. // KeQueryPerformanceCounter, don't check the upper bound.
  467. //
  468. if (tickCount.QuadPart - lastTickCount.QuadPart < 4)
  469. {
  470. //
  471. // Figure out the upper bound on the performance counter
  472. //
  473. SAFE_READ_TIMER64(upperBound, ViTimerInformation->UpperBound);
  474. //
  475. // Make sure the PC hasn't gone too far forwards.
  476. //
  477. if ((ULONGLONG) performanceCounter.QuadPart >
  478. (ULONGLONG) upperBound.QuadPart )
  479. {
  480. LARGE_INTEGER lastKdStartTime;
  481. //
  482. // Microseconds = 10^6 * ticks / ticks per second
  483. //
  484. ULONG miliseconds = (ULONG) ( 1000 *
  485. ( performanceCounter.QuadPart -
  486. lastPerformanceCounter.QuadPart ) /
  487. ViTimerInformation->PerformanceFrequency.QuadPart );
  488. //
  489. // Check if the skip was caused by entering the debugger
  490. //
  491. SAFE_READ_TIMER64(lastKdStartTime, ViTimerInformation->LastKdStartTime);
  492. if (KdTimerStart.QuadPart <= lastKdStartTime.QuadPart)
  493. {
  494. //
  495. // skip was not caused by entering the debugger
  496. //
  497. VF_ASSERT(
  498. (ULONGLONG) performanceCounter.QuadPart <=
  499. (ULONGLONG) upperBound.QuadPart,
  500. HV_PERFORMANCE_COUNTER_SKIPPED,
  501. ( "Performance counter skipped too far -- %I64x (%d milliseconds)",
  502. performanceCounter.QuadPart,
  503. miliseconds )
  504. );
  505. }
  506. else
  507. {
  508. //
  509. // Entering debugger caused us to skip too far
  510. //
  511. SAFE_WRITE_TIMER64(ViTimerInformation->LastKdStartTime, KdTimerStart);
  512. //
  513. // N.B. when we assert, we sit and wait while the
  514. // performance counter goes up. We may not get
  515. // a clock tick interrupt in this time, so set
  516. // the next maximum to the highest possible large
  517. // integer.
  518. //
  519. nextUpperBound = RtlConvertLongToLargeInteger(-1);
  520. }
  521. } // if we skipped too far //
  522. } // If it hasn't been too many clock ticks since the last //
  523. // performance counter call //
  524. //
  525. // Save the upper bound calculation and the current tick count
  526. //
  527. SAFE_WRITE_TIMER64(ViTimerInformation->LastTickCount, tickCount);
  528. SAFE_WRITE_TIMER64(ViTimerInformation->UpperBound, nextUpperBound);
  529. //
  530. // Save this performance counter to serve as a minimum for the next guy.
  531. // (must do so in a safe way).
  532. //
  533. SAFE_WRITE_TIMER64( ViTimerInformation->LastPerformanceCounter,
  534. performanceCounter );
  535. return performanceCounter;
  536. } // VfQueryPerformanceCounter //
  537. #if defined (_X86_)
  538. //
  539. // For some annoying reason, a naked function call will cause
  540. // a warning since we don't have a "return" statement
  541. //
  542. #pragma warning(disable: 4035)
  543. //
  544. // RDTSC is a non-standard instruction -- so build it from
  545. // the opcode (0x0F31)
  546. //
  547. #ifndef RDTSC
  548. #define RDTSC __asm _emit 0x0F __asm _emit 0x31
  549. #endif
  550. _declspec(naked)
  551. LARGE_INTEGER
  552. ViRdtscX86()
  553. {
  554. __asm{
  555. RDTSC
  556. ret
  557. }
  558. } // ViRdtscX86 //
  559. #elif defined(_IA64_)
  560. LARGE_INTEGER
  561. ViRdtscIA64()
  562. {
  563. LARGE_INTEGER itc;
  564. itc.QuadPart = __getReg(CV_IA64_ApITC);
  565. return itc;
  566. } // ViRdtscIA64 //
  567. #else // !X86 && !_IA64_ //
  568. LARGE_INTEGER
  569. ViRdtscNull()
  570. {
  571. //
  572. // Return 0
  573. //
  574. return RtlConvertLongToLargeInteger(0);
  575. } // ViRdtscNull //
  576. #endif
  577. PADAPTER_INFORMATION
  578. ViHookDmaAdapter(
  579. IN PDMA_ADAPTER DmaAdapter,
  580. IN PDEVICE_DESCRIPTION DeviceDescription,
  581. IN ULONG NumberOfMapRegisters
  582. )
  583. /*++
  584. Routine Description:
  585. DMA functions can't be hooked in the normal way -- they are called via
  586. a pointer in the DmaAdapter structure -- so we are going to replace
  587. those pointers with our pointers after saving the real ones.
  588. N.B. ANY DEVICE THAT SUCCEEDS THIS FUNCTION WILL HAVE AN ELEVATED REF
  589. COUNT.
  590. So there will be a leak if ViReleaseDmaAdapter isn't called.
  591. ViReleaseDmaAdapter is, in the usual case, called from
  592. IoDeleteDevice. However, in order to do this, we have to be able
  593. to associate a device object with the adapter. Since there is an
  594. unsupported feature of the HAL that lets you pass NULL for the PDO
  595. when calling IoGetDmaAdapter, we have to try to find the device
  596. object when AllocateAdapterChannel etc is called. Some devices may
  597. decide to call ObDereferenceObject instead of calling PutDmaAdapter.
  598. While not very cool, I think that this is allowed for now. Anyway
  599. to make a long story short, if a driver passes a null PDO into
  600. PutDmaAdapter, doesn't call any dma functions, and doesn't call
  601. PutDmaAdapter, we will leak a reference. I think that this is a
  602. necessary evil since it will let us catch drivers that are being
  603. bad.
  604. Arguments:
  605. DmaAdapter -- adapter that has been returned from IoGetDmaAdapter.
  606. DeviceDescription -- Describes the device.
  607. NumberOfMapRegisters -- how many map registers the device got.
  608. Return Value:
  609. Returns either a pointer to the new adapter information structure or
  610. NULL if we fail.
  611. --*/
  612. {
  613. PADAPTER_INFORMATION newAdapterInformation;
  614. PDMA_OPERATIONS dmaOperations;
  615. PAGED_CODE();
  616. if ( VfInjectDmaFailure() == TRUE)
  617. {
  618. return NULL;
  619. }
  620. newAdapterInformation = ViGetAdapterInformation(DmaAdapter);
  621. if (newAdapterInformation)
  622. //
  623. // This is a bit of a tricky part -- since devices will ask the bus for
  624. // help creating an adapter, we can get called twice on the same stack--
  625. // i.e pci device calls IoGetDmaAdapter which calls PciGetDmaAdapter
  626. // which then calls IoGetDmaAdapter again. If we hook it all, than we'll
  627. // get called twice, add the same adapter twice, and destroy the real dma
  628. // operations.
  629. //
  630. // So in order to prevent bad things from happening, if we've seen
  631. // the adapter before, ignore it.
  632. //
  633. {
  634. return newAdapterInformation;
  635. }
  636. //
  637. // Allocate space to store the real dma operations for this new adapter
  638. //
  639. newAdapterInformation = ExAllocatePoolWithTag(
  640. NonPagedPool,
  641. sizeof(ADAPTER_INFORMATION),
  642. HAL_VERIFIER_POOL_TAG );
  643. if (! newAdapterInformation )
  644. {
  645. //
  646. // If we can't allocate space for the new adapter, we're not going to
  647. // hook the dma operations... thats ok though, but we won't be
  648. // verifying dma for this device
  649. //
  650. return NULL;
  651. }
  652. RtlZeroMemory(newAdapterInformation, sizeof(ADAPTER_INFORMATION) );
  653. newAdapterInformation->DmaAdapter = DmaAdapter;
  654. VF_ADD_TO_LOCKED_LIST(&ViAdapterList, newAdapterInformation);
  655. ASSERT(DmaAdapter->DmaOperations != &ViDmaOperations);
  656. //
  657. // Make sure that the dma adapter doesn't go away until we say it is ok
  658. // (we will deref the object in IoDeleteDevice)
  659. //
  660. ObReferenceObject(DmaAdapter);
  661. VF_INITIALIZE_LOCKED_LIST(&newAdapterInformation->ScatterGatherLists);
  662. VF_INITIALIZE_LOCKED_LIST(&newAdapterInformation->CommonBuffers);
  663. VF_INITIALIZE_LOCKED_LIST(&newAdapterInformation->MapRegisterFiles);
  664. //
  665. // Save the device description in case we want to look at it later.
  666. //
  667. RtlCopyMemory(&newAdapterInformation->DeviceDescription,
  668. DeviceDescription, sizeof(DEVICE_DESCRIPTION) );
  669. newAdapterInformation->MaximumMapRegisters = NumberOfMapRegisters;
  670. //
  671. // Do some calculations on the device description so that we can tell
  672. // at a glance what the device is doing.
  673. //
  674. if (VF_DOES_DEVICE_USE_DMA_CHANNEL(DeviceDescription))
  675. newAdapterInformation->UseDmaChannel = TRUE;
  676. KeInitializeSpinLock(&newAdapterInformation->AllocationLock);
  677. //
  678. // When we double buffer, we must remember that devices that don't do
  679. // scatter gather or aren't bus masters won't be able to play our double
  680. // buffering game, unless we come up with a better way to do double
  681. // buffering.
  682. //
  683. if (VF_DOES_DEVICE_REQUIRE_CONTIGUOUS_BUFFERS(DeviceDescription)) {
  684. newAdapterInformation->UseContiguousBuffers = TRUE;
  685. } else if (ViDoubleBufferDma) {
  686. //
  687. // Pre-allocate contiguous memory
  688. //
  689. ViAllocateContiguousMemory(newAdapterInformation);
  690. }
  691. //
  692. // Ok we've added the real dma operations structure to our adapter list--
  693. // so we're going to kill this one and replace it with ours
  694. //
  695. dmaOperations = DmaAdapter->DmaOperations;
  696. newAdapterInformation->RealDmaOperations = dmaOperations;
  697. DmaAdapter->DmaOperations = &ViDmaOperations;
  698. return newAdapterInformation;
  699. } // ViHookDmaAdapter //
  700. VOID
  701. ViReleaseDmaAdapter(
  702. IN PADAPTER_INFORMATION AdapterInformation
  703. )
  704. /*++
  705. Routine Description:
  706. Release all memory associated with a particular adapter -- this is the
  707. antithesis of ViHookDmaAdapter.
  708. N.B. -- we don't actually do this until VfHalDeleteDevice is called so
  709. that we can do reference counting until then.
  710. N.B. -- That is, unless we haven't been able to associate a device object
  711. with he adapter, in which case we call this function from
  712. VfPutDmaAdapter.
  713. Arguments:
  714. AdapterInformation -- structure containing the adapter to unhook.
  715. Return Value:
  716. None.
  717. --*/
  718. {
  719. PDMA_ADAPTER dmaAdapter;
  720. ULONG referenceCount;
  721. PVOID *contiguousBuffers;
  722. ULONG i;
  723. KIRQL oldIrql;
  724. ASSERT(AdapterInformation);
  725. dmaAdapter = AdapterInformation->DmaAdapter;
  726. //
  727. // Just in case this comes back to haunt us (which I think is happening
  728. // when we disable/enable a device)
  729. //
  730. dmaAdapter->DmaOperations = AdapterInformation->RealDmaOperations;
  731. //
  732. // Free the contiguous memory if any
  733. //
  734. KeAcquireSpinLock(&AdapterInformation->AllocationLock, &oldIrql);
  735. contiguousBuffers = AdapterInformation->ContiguousBuffers;
  736. AdapterInformation->ContiguousBuffers = NULL;
  737. KeReleaseSpinLock(&AdapterInformation->AllocationLock, oldIrql);
  738. if (contiguousBuffers) {
  739. for (i = 0; i < MAX_CONTIGUOUS_MAP_REGISTERS; i++) {
  740. if (contiguousBuffers[i]) {
  741. MmFreeContiguousMemory(contiguousBuffers[i]);
  742. }
  743. }
  744. ExFreePool(contiguousBuffers);
  745. }
  746. //
  747. // HalPutAdapter (the real hal function) will dereference the object
  748. // iff it has been called. Some people try dereffing the adapter
  749. // themselves, and according to JakeO, that's ok. Since we
  750. // artificially increased the pointer count when we hooked the
  751. // adapter, it should be 1 now (otherwise it would be 0).
  752. // If its not 1, then the driver hasn't dereferenced it (either
  753. // by calling ObDeref... or PutDmaAdapter).
  754. //
  755. referenceCount = ObDereferenceObject(dmaAdapter);
  756. VF_ASSERT(
  757. referenceCount == 0 ||
  758. (referenceCount == 1 &&
  759. AdapterInformation->UseDmaChannel ),
  760. HV_DID_NOT_PUT_ADAPTER,
  761. ( "Too many outstanding reference counts (%x) for adapter %p",
  762. referenceCount,
  763. dmaAdapter )
  764. );
  765. VF_REMOVE_FROM_LOCKED_LIST(&ViAdapterList, AdapterInformation);
  766. ExFreePool(AdapterInformation);
  767. } // ViReleaseDmaAdapter //
  768. PADAPTER_INFORMATION
  769. ViGetAdapterInformation(
  770. IN PDMA_ADAPTER DmaAdapter
  771. )
  772. /*++
  773. Routine Description:
  774. We store relevant information about each adapter in a linked list.
  775. This function goes through that list and tries to find the adapter
  776. and returns a pointer to the structure referencing the adapter.
  777. Arguments:
  778. DmaAdapter -- adapter that has been returned from IoGetDmaAdapter.
  779. Return Value:
  780. Pointer to the adapter information structure for adapter DmaAdapeer or
  781. NULL if we fail.
  782. --*/
  783. {
  784. PADAPTER_INFORMATION adapterInformation;
  785. KIRQL OldIrql;
  786. if (!DmaAdapter)
  787. return NULL;
  788. //
  789. // If the irql is greater than dispatch level we can't use our spinlock.
  790. // or we'll bugcheck
  791. //
  792. if (KeGetCurrentIrql() > DISPATCH_LEVEL)
  793. {
  794. //
  795. // Only assert when we're verifying dma. Note that during a crashdump.
  796. // dma verification is turned off.
  797. //
  798. if (ViVerifyDma)
  799. {
  800. VF_ASSERT_MAX_IRQL(DISPATCH_LEVEL);
  801. }
  802. return NULL;
  803. }
  804. VF_LOCK_LIST(&ViAdapterList, OldIrql);
  805. FOR_ALL_IN_LIST(ADAPTER_INFORMATION, &ViAdapterList.ListEntry, adapterInformation)
  806. {
  807. if (DmaAdapter == adapterInformation->DmaAdapter)
  808. {
  809. VF_UNLOCK_LIST(&ViAdapterList, OldIrql);
  810. VF_ASSERT( ! adapterInformation->Inactive,
  811. HV_ADAPTER_ALREADY_RELEASED,
  812. ("Driver has attempted to access an adapter (%p) that has already been released",
  813. DmaAdapter),
  814. );
  815. return adapterInformation;
  816. }
  817. }
  818. VF_UNLOCK_LIST(&ViAdapterList, OldIrql);
  819. //
  820. // Dma adapter not in the list //
  821. //
  822. return NULL;
  823. } // ViGetAdapterInformation //
  824. PVOID
  825. ViGetRealDmaOperation(
  826. IN PDMA_ADAPTER DmaAdapter,
  827. IN ULONG AdapterInformationOffset
  828. )
  829. /*++
  830. Routine Description:
  831. We've hooked the adapter operation and now the driver has called it so we
  832. want to find the real function that it was supposed to call. Since under
  833. the nt5 dma paradigm there can be multiple instances of dma functions
  834. (although to the best of my knowledge we don't do this yet), we can't
  835. just call a fixed function but we have to find the one that corresponds
  836. to this adapter.
  837. Arguments:
  838. DmaAdapter -- adapter that has been returned from IoGetDmaAdapter.
  839. AdapterInformationOffset -- the byte offset of the DMA_OPERATIONS
  840. structure that contains the function we are looking for. For
  841. example, offset 0x4 would be PutDmaAdapter and 0x8 is
  842. AllocateCommonBuffer.
  843. Return Value:
  844. TRUE -- hooked the adapter.
  845. FALSE -- we were unable to hook the functions in the adapter.
  846. --*/
  847. {
  848. PADAPTER_INFORMATION adapterInformation;
  849. PVOID dmaOperation;
  850. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  851. VF_ASSERT(
  852. ! (ViVerifyDma && DmaAdapter == NULL) ,
  853. HV_NULL_DMA_ADAPTER,
  854. ("DMA adapters aren't supposed to be NULL anymore")
  855. );
  856. #if !defined (NO_LEGACY_DRIVERS)
  857. //
  858. // Prevent against recursion when Hal.dll is being verified
  859. //
  860. //
  861. // This is a hack that will break when
  862. // dma is done in a filter driver -- but
  863. // this should only happen when NO_LEGACY_DRIVERs is set.
  864. //
  865. dmaOperation = DMA_INDEX(&ViLegacyDmaOperations, AdapterInformationOffset);
  866. if (NULL != dmaOperation)
  867. {
  868. return dmaOperation;
  869. }
  870. //
  871. // If we fall though here we must have hooked the adapter
  872. //
  873. #endif
  874. if (! adapterInformation) {
  875. //
  876. // If we can't find the adapter information, we must not have
  877. // hooked it.
  878. //
  879. dmaOperation = DMA_INDEX( DmaAdapter->DmaOperations, AdapterInformationOffset );
  880. }
  881. else {
  882. //
  883. // Dma adapter is hooked. Whether we are still verifying it or not,
  884. // we have to call the real dma operations structure.
  885. //
  886. dmaOperation = DMA_INDEX(adapterInformation->RealDmaOperations, AdapterInformationOffset);
  887. }
  888. return dmaOperation;
  889. } // ViGetRealDmaOperation //
  890. THUNKED_API
  891. PDMA_ADAPTER
  892. VfGetDmaAdapter(
  893. IN PDEVICE_OBJECT PhysicalDeviceObject,
  894. IN PDEVICE_DESCRIPTION DeviceDescription,
  895. IN OUT PULONG NumberOfMapRegisters
  896. )
  897. /*++
  898. Routine Description:
  899. This is the hooked version of IoGetDmaAdapter -- the only hook we need
  900. from the driver verifier for dma -- since all other hooks will come out
  901. of the DmaAdapter->DmaOperations structure. We don't actually do any
  902. verification here -- we just use this as an excuse to save off a bunch
  903. of stuff and set up the hooks to the rest of the dma operations.
  904. Arguments:
  905. PhysicalDeviceObject -- the PDO for the driver trying to get an adapter.
  906. DeviceDescription -- A structure describing the device we are trying to
  907. get an adapter for. At some point, I'm going to monkey around with
  908. this guy so we can convince the HAL that we are something that we're
  909. not, but for now just gets passed straight into IoGetDmaAdapter.
  910. Return Value:
  911. Returns a pointer to the dma adapter or
  912. NULL if we couldn't allocate one.
  913. --*/
  914. {
  915. PVOID callingAddress;
  916. PADAPTER_INFORMATION newAdapterInformation;
  917. PADAPTER_INFORMATION inactiveAdapter;
  918. PDMA_ADAPTER dmaAdapter;
  919. PAGED_CODE();
  920. GET_CALLING_ADDRESS(callingAddress);
  921. //
  922. // Give the option of not hooking dma adapters at all.
  923. // Also, if we're a PCI bus driver, we will be called on
  924. // behalf of a PCI device. We don't want to hook up this call
  925. // because we may end up hooking up the function table for the PCI device
  926. // (not the PCI bus) and they may not want this...
  927. //
  928. if (! ViVerifyDma ||
  929. VfIsPCIBus(PhysicalDeviceObject)) {
  930. return IoGetDmaAdapter(
  931. PhysicalDeviceObject,
  932. DeviceDescription,
  933. NumberOfMapRegisters );
  934. }
  935. if (VfInjectDmaFailure() == TRUE) {
  936. return NULL;
  937. }
  938. VF_ASSERT_IRQL(PASSIVE_LEVEL);
  939. //
  940. // Use the PDO, cause it's the only way to uniquely identify a stack...
  941. //
  942. if (PhysicalDeviceObject)
  943. {
  944. //
  945. // Clean up inactive adapters with the same device object
  946. //
  947. inactiveAdapter = VF_FIND_INACTIVE_ADAPTER(PhysicalDeviceObject);
  948. ///
  949. // A device may have more than one adapter. Release each of them.
  950. ///
  951. while (inactiveAdapter) {
  952. ViReleaseDmaAdapter(inactiveAdapter);
  953. inactiveAdapter = VF_FIND_INACTIVE_ADAPTER(PhysicalDeviceObject);
  954. }
  955. }
  956. if ( ViDoubleBufferDma &&
  957. *NumberOfMapRegisters > ViMaxMapRegistersPerAdapter ) {
  958. //
  959. // Harumph -- don't let drivers try to get too many adapters
  960. // Otherwise NDIS tries to allocate thousands. Since we allocate
  961. // three pages of non-paged memory for each map register, it
  962. // gets expensive unless we put our foot down here
  963. //
  964. *NumberOfMapRegisters = ViMaxMapRegistersPerAdapter;
  965. }
  966. dmaAdapter = IoGetDmaAdapter(
  967. PhysicalDeviceObject,
  968. DeviceDescription,
  969. NumberOfMapRegisters
  970. );
  971. if (! dmaAdapter ) {
  972. //
  973. // early opt-out here -- the hal couldn't allocate the adapter
  974. //
  975. return NULL;
  976. }
  977. //
  978. // Replace all of the dma operations that live in the adapter with our
  979. // dma operations.. If we can't do it, fail.
  980. //
  981. newAdapterInformation = ViHookDmaAdapter(
  982. dmaAdapter,
  983. DeviceDescription,
  984. *NumberOfMapRegisters
  985. );
  986. if (! newAdapterInformation) {
  987. dmaAdapter->DmaOperations->PutDmaAdapter(dmaAdapter);
  988. return NULL;
  989. }
  990. newAdapterInformation->DeviceObject = PhysicalDeviceObject;
  991. newAdapterInformation->CallingAddress = callingAddress;
  992. return dmaAdapter ;
  993. } // VfGetDmaAdapter //
  994. THUNKED_API
  995. VOID
  996. VfPutDmaAdapter(
  997. PDMA_ADAPTER DmaAdapter
  998. )
  999. /*++
  1000. Routine Description:
  1001. Releases dma adapter -- we are going to make sure that the driver was
  1002. nice and put away all of its toys before calling us .. i.e. free its
  1003. common buffers, put its scatter gather lists, etc.
  1004. Arguments:
  1005. DmaAdapter -- which adapter to put away.
  1006. Return Value:
  1007. None.
  1008. --*/
  1009. {
  1010. PPUT_DMA_ADAPTER putDmaAdapter;
  1011. PADAPTER_INFORMATION adapterInformation;
  1012. VF_ASSERT_MAX_IRQL(DISPATCH_LEVEL);
  1013. putDmaAdapter = (PPUT_DMA_ADAPTER)
  1014. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(PutDmaAdapter));
  1015. if (! putDmaAdapter) {
  1016. //
  1017. // This is bad but no other choice.
  1018. // -- note there is not default put adapter function
  1019. //
  1020. return;
  1021. }
  1022. //
  1023. // Make sure that the driver has freed all of its buffers etc
  1024. //
  1025. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1026. if ( adapterInformation ) {
  1027. adapterInformation->Inactive = TRUE;
  1028. VF_ASSERT(
  1029. adapterInformation->AllocatedAdapterChannels ==
  1030. adapterInformation->FreedAdapterChannels,
  1031. HV_LEFTOVER_ADAPTER_CHANNELS,
  1032. ( "Cannot put adapter %p until all adapter channels are freed (%x left)",
  1033. DmaAdapter,
  1034. adapterInformation->AllocatedAdapterChannels -
  1035. adapterInformation->FreedAdapterChannels )
  1036. );
  1037. VF_ASSERT(
  1038. adapterInformation->AllocatedCommonBuffers ==
  1039. adapterInformation->FreedCommonBuffers,
  1040. HV_LEFTOVER_ADAPTER_CHANNELS,
  1041. ( "Cannot put adapter %p until all common buffers are freed (%x left)",
  1042. DmaAdapter,
  1043. adapterInformation->AllocatedCommonBuffers -
  1044. adapterInformation->FreedCommonBuffers )
  1045. );
  1046. VF_ASSERT(
  1047. adapterInformation->ActiveMapRegisters == 0,
  1048. HV_LEFTOVER_MAP_REGISTERS,
  1049. ( "Cannot put adapter %p until all map registers are freed (%x left)",
  1050. DmaAdapter,
  1051. adapterInformation->ActiveMapRegisters )
  1052. );
  1053. VF_ASSERT(
  1054. adapterInformation->ActiveScatterGatherLists == 0,
  1055. HV_LEFTOVER_ADAPTER_CHANNELS,
  1056. ( "Cannot put adapter %p until all scatter gather lists are freed (%x left)",
  1057. DmaAdapter,
  1058. adapterInformation->ActiveScatterGatherLists)
  1059. );
  1060. //
  1061. // These are just to assure the verifier has done everything right.
  1062. //
  1063. #if DBG
  1064. ASSERT( VF_IS_LOCKED_LIST_EMPTY(
  1065. &adapterInformation->ScatterGatherLists ));
  1066. ASSERT( VF_IS_LOCKED_LIST_EMPTY(
  1067. &adapterInformation->CommonBuffers ));
  1068. #endif
  1069. //
  1070. // Ideally, we wouldn't do this here. It's a bit of a hack. However,
  1071. // if we don't want to leak adapter information structures etc, we
  1072. // have to. Since when we really want to do this, in IoDeleteDevice,
  1073. // we only have a device object, if we don't have a device
  1074. // object in our adapter information struct, we won't be able to do it.
  1075. //
  1076. if (! adapterInformation->DeviceObject)
  1077. ViReleaseDmaAdapter(adapterInformation);
  1078. //
  1079. // This is not a hack. The system dma adapters are persistent, so
  1080. // we don't want to get upset when they show up again.
  1081. //
  1082. if (adapterInformation->UseDmaChannel)
  1083. ViReleaseDmaAdapter(adapterInformation);
  1084. }
  1085. (putDmaAdapter)(DmaAdapter);
  1086. } // VfPutDmaAdapter //
  1087. THUNKED_API
  1088. PVOID
  1089. VfAllocateCommonBuffer(
  1090. IN PDMA_ADAPTER DmaAdapter,
  1091. IN ULONG Length,
  1092. OUT PPHYSICAL_ADDRESS LogicalAddress,
  1093. IN BOOLEAN CacheEnabled
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. Hooked version of allocate common buffer. We are going to allocate some
  1098. space on either side of the buffer so that we can tell if a driver
  1099. overruns (or underruns) its allocation.
  1100. Arguments:
  1101. DmaAdapter -- Which adapter we're looking at.
  1102. Length -- Size of the common buffer (note we are going to increase)
  1103. LogicalAddress -- Gets the *PHYSICAL* address of the common buffer.
  1104. CacheEnabled -- whether or not the memory should be cached.
  1105. Return Value:
  1106. Returns the *VIRTUAL* address of the common buffer or
  1107. NULL if it could not be allocated.
  1108. --*/
  1109. {
  1110. PVOID callingAddress;
  1111. PALLOCATE_COMMON_BUFFER allocateCommonBuffer;
  1112. PVOID commonBuffer;
  1113. PADAPTER_INFORMATION adapterInformation;
  1114. allocateCommonBuffer = (PALLOCATE_COMMON_BUFFER)
  1115. ViGetRealDmaOperation( DmaAdapter,
  1116. DMA_OFFSET(AllocateCommonBuffer) );
  1117. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1118. if (adapterInformation) {
  1119. GET_CALLING_ADDRESS(callingAddress);
  1120. VF_ASSERT_IRQL(PASSIVE_LEVEL);
  1121. if (VfInjectDmaFailure() == TRUE ) {
  1122. return NULL;
  1123. }
  1124. if (ViProtectBuffers) {
  1125. //
  1126. // Try to allocate an extra big common buffer so we can check for
  1127. // buffer overrun
  1128. //
  1129. commonBuffer = ViSpecialAllocateCommonBuffer(
  1130. allocateCommonBuffer,
  1131. adapterInformation,
  1132. callingAddress,
  1133. Length,
  1134. LogicalAddress,
  1135. CacheEnabled
  1136. );
  1137. if (commonBuffer)
  1138. return commonBuffer;
  1139. }
  1140. }
  1141. commonBuffer = (allocateCommonBuffer)(
  1142. DmaAdapter,
  1143. Length,
  1144. LogicalAddress,
  1145. CacheEnabled );
  1146. if(commonBuffer && adapterInformation) {
  1147. //
  1148. // Increment the number of known common buffers for this adapter
  1149. // (the dma adapter better be in our list because otherwise we
  1150. // couldn't have gotten the pointer to the allocateCommonBuffer
  1151. // struct
  1152. //
  1153. INCREMENT_COMMON_BUFFERS(adapterInformation);
  1154. }
  1155. return commonBuffer;
  1156. } // VfAllocateCommonBuffer //
  1157. THUNKED_API
  1158. VOID
  1159. VfFreeCommonBuffer(
  1160. IN PDMA_ADAPTER DmaAdapter,
  1161. IN ULONG Length,
  1162. IN PHYSICAL_ADDRESS LogicalAddress,
  1163. IN PVOID VirtualAddress,
  1164. IN BOOLEAN CacheEnabled
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. Hooked version of FreeCommonBuffer.
  1169. Arguments:
  1170. DmaAdapter -- Which adapter we're looking at.
  1171. Length -- Size of the common buffer (note we are going to increase)
  1172. LogicalAddress -- The *PHYSICAL* address of the common buffer.
  1173. VirtualAddress -- The *VIRTUAL* address of common buffer.
  1174. CacheEnabled -- whether or not the memory is cached.
  1175. Return Value:
  1176. None.
  1177. --*/
  1178. {
  1179. PFREE_COMMON_BUFFER freeCommonBuffer;
  1180. PADAPTER_INFORMATION adapterInformation;
  1181. freeCommonBuffer = (PFREE_COMMON_BUFFER)
  1182. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(FreeCommonBuffer));
  1183. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1184. if (adapterInformation) {
  1185. VF_ASSERT_IRQL(PASSIVE_LEVEL);
  1186. //
  1187. // We want to call this even if we're not doing common buffer
  1188. // protection. Why? because we may have switched it off manually
  1189. // (on the fly) and we don't want to try to free the wrong kind of
  1190. // buffer.
  1191. //
  1192. if (ViSpecialFreeCommonBuffer(
  1193. freeCommonBuffer,
  1194. adapterInformation,
  1195. VirtualAddress,
  1196. CacheEnabled
  1197. )) {
  1198. return;
  1199. }
  1200. }
  1201. //
  1202. // Call the real free common buffer routine.
  1203. //
  1204. (freeCommonBuffer)(
  1205. DmaAdapter,
  1206. Length,
  1207. LogicalAddress,
  1208. VirtualAddress,
  1209. CacheEnabled );
  1210. //
  1211. // Decrement the number of known common buffers for this adapter
  1212. //
  1213. if (adapterInformation) {
  1214. DECREMENT_COMMON_BUFFERS(adapterInformation);
  1215. }
  1216. } // VfFreeCommonBuffer //
  1217. THUNKED_API
  1218. NTSTATUS
  1219. VfAllocateAdapterChannel(
  1220. IN PDMA_ADAPTER DmaAdapter,
  1221. IN PDEVICE_OBJECT DeviceObject,
  1222. IN ULONG NumberOfMapRegisters,
  1223. IN PDRIVER_CONTROL ExecutionRoutine,
  1224. IN PVOID Context
  1225. )
  1226. /*++
  1227. Routine Description:
  1228. Hooked version of AllocateAdapterChannel ..
  1229. Arguments:
  1230. DmaAdapter -- adapter referenced.
  1231. DeviceObject -- we don't care about this.
  1232. NumberOfMapRegisters -- make sure that the driver isn't trying to be too
  1233. greedy and trying to allocate more map registers than it said that it
  1234. wanted when it allocated the adapter.
  1235. ExecutionRoutine -- call this routine when done (actually let the hal do
  1236. this). We are going to hook this routine so that we know when this
  1237. happens.
  1238. Context -- context parameter to pass into the execution routine.
  1239. Return Value:
  1240. NTSTATUS code ... up to the hal to decide this one.
  1241. --*/
  1242. {
  1243. PALLOCATE_ADAPTER_CHANNEL allocateAdapterChannel;
  1244. PADAPTER_INFORMATION adapterInformation;
  1245. PVF_WAIT_CONTEXT_BLOCK waitBlock;
  1246. NTSTATUS status;
  1247. allocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)
  1248. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(AllocateAdapterChannel));
  1249. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1250. if (adapterInformation) {
  1251. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  1252. //
  1253. // Fill in the wait context block so that the execution routine will
  1254. // know what is going on.
  1255. //
  1256. waitBlock = &adapterInformation->AdapterChannelContextBlock;
  1257. RtlZeroMemory(waitBlock, sizeof(VF_WAIT_CONTEXT_BLOCK));
  1258. waitBlock->RealContext = Context;
  1259. waitBlock->RealCallback = (PVOID)ExecutionRoutine;
  1260. waitBlock->AdapterInformation = adapterInformation;
  1261. waitBlock->NumberOfMapRegisters = NumberOfMapRegisters;
  1262. if (ViDoubleBufferDma && ! adapterInformation->UseContiguousBuffers) {
  1263. //
  1264. // Note if this fails, we simply won't have double buffer
  1265. //
  1266. waitBlock->MapRegisterFile = ViAllocateMapRegisterFile(
  1267. adapterInformation,
  1268. NumberOfMapRegisters
  1269. );
  1270. }
  1271. //
  1272. // We are going to save the device object if the adapter was created without
  1273. // a real PDO (there is an option to pass in NULL).
  1274. //
  1275. if (! adapterInformation->DeviceObject) {
  1276. adapterInformation->DeviceObject = DeviceObject;
  1277. }
  1278. //
  1279. // Use OUR execution routine and callback (we've already saved theirs)
  1280. //
  1281. ExecutionRoutine = VfAdapterCallback;
  1282. Context = waitBlock;
  1283. INCREMENT_ADAPTER_CHANNELS(adapterInformation);
  1284. ADD_MAP_REGISTERS(adapterInformation, NumberOfMapRegisters, FALSE);
  1285. } // if (adapterInformation)
  1286. status = (allocateAdapterChannel)(
  1287. DmaAdapter,
  1288. DeviceObject,
  1289. NumberOfMapRegisters,
  1290. ExecutionRoutine,
  1291. Context
  1292. );
  1293. if ( status != STATUS_SUCCESS && adapterInformation) {
  1294. DECREMENT_ADAPTER_CHANNELS(adapterInformation);
  1295. SUBTRACT_MAP_REGISTERS(adapterInformation, NumberOfMapRegisters);
  1296. }
  1297. return status;
  1298. } // VfAllocateAdapterChannel //
  1299. THUNKED_API
  1300. BOOLEAN
  1301. VfFlushAdapterBuffers(
  1302. IN PDMA_ADAPTER DmaAdapter,
  1303. IN PMDL Mdl,
  1304. IN PVOID MapRegisterBase,
  1305. IN PVOID CurrentVa,
  1306. IN ULONG Length,
  1307. IN BOOLEAN WriteToDevice
  1308. )
  1309. /*++
  1310. Routine Description:
  1311. Hooked version of FlushAdapterBuffers .. drivers that don't call this
  1312. after a map transfer must be punished.
  1313. Arguments:
  1314. DmaAdapter -- dma adapter for the device whose buffers we are flushing.
  1315. Mdl -- Mdl for transfer.
  1316. MapRegisterBase -- only the HAL really knows what this is.
  1317. CurrentVa -- virtual address indexing the Mdl to show where we want to
  1318. start flushing.
  1319. Length -- length of transfer (i.e how much to flush).
  1320. WriteToDevice -- direction of transfer. We should make sure that the
  1321. device has this set correctly (but not exactly sure how to do so).
  1322. Return Value:
  1323. TRUE -- flushed buffers.
  1324. FALSE -- couldn't flush buffers. I'm not sure what the driver is
  1325. actually supposed to do in the occasion that the flushing fails.
  1326. Re-flush ? Re-try the transfer?
  1327. --*/
  1328. {
  1329. PFLUSH_ADAPTER_BUFFERS flushAdapterBuffers;
  1330. PADAPTER_INFORMATION adapterInformation;
  1331. BOOLEAN buffersFlushed;
  1332. flushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)
  1333. ViGetRealDmaOperation( DmaAdapter,
  1334. DMA_OFFSET(FlushAdapterBuffers) );
  1335. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1336. if (adapterInformation) {
  1337. VF_ASSERT_MAX_IRQL(DISPATCH_LEVEL);
  1338. //
  1339. // It doesn't make any sense to flush adapter buffers with a length
  1340. // of zero.
  1341. //
  1342. if (MapRegisterBase == MRF_NULL_PLACEHOLDER) {
  1343. //
  1344. // Some drivers (scsiport for one) don't call
  1345. // HalFlushAdapterBuffers unless MapRegisterBase is non-null.
  1346. // In order to fool the drivers into thinking that they need
  1347. // to flush, we exchange the NULL MapRegisterBase (if in fact
  1348. // the hal uses a null map register base) for our
  1349. /// MRF_NULL_PLACEHOLDER in the adapter allocation callback.
  1350. // So now, if we find that placeholder, we must exchange it
  1351. // for NULL in order not to confuse the hal.
  1352. //
  1353. MapRegisterBase = NULL;
  1354. }
  1355. else if ( VALIDATE_MAP_REGISTER_FILE_SIGNATURE(
  1356. (PMAP_REGISTER_FILE) MapRegisterBase ) ) {
  1357. PMDL alternateMdl;
  1358. PVOID alternateVa;
  1359. PVOID alternateMapRegisterBase;
  1360. alternateMdl = Mdl;
  1361. alternateVa = CurrentVa;
  1362. alternateMapRegisterBase = MapRegisterBase;
  1363. //
  1364. // Find the mdl * va we used to map the transfer
  1365. // (i.e. the location of the double buffer)
  1366. //
  1367. if (!ViSwap(&alternateMapRegisterBase, &alternateMdl, &alternateVa)) {
  1368. //
  1369. // Assert only when the length is not zero, if they
  1370. // map and flush a zero length buffer
  1371. //
  1372. VF_ASSERT(Length == 0,
  1373. HV_FLUSH_NOT_MAPPED,
  1374. ("Cannot flush map register that isn't mapped!"
  1375. " (Map register base %p, flushing address %p, MDL %p)",
  1376. MapRegisterBase, CurrentVa, Mdl));
  1377. //
  1378. // Don't continue -- we don't know what should actually be flushed and
  1379. // the hal will get our map register base and corrupt it instead
  1380. // of using its own map register base.
  1381. //
  1382. return FALSE;
  1383. }
  1384. buffersFlushed = (flushAdapterBuffers)(
  1385. DmaAdapter,
  1386. alternateMdl,
  1387. alternateMapRegisterBase,
  1388. alternateVa,
  1389. Length,
  1390. WriteToDevice
  1391. );
  1392. ///
  1393. // Double buffer away!!!
  1394. // (remember we must use the original mdl and va).
  1395. ///
  1396. ViFlushDoubleBuffer(
  1397. (PMAP_REGISTER_FILE) MapRegisterBase,
  1398. Mdl,
  1399. CurrentVa,
  1400. Length,
  1401. WriteToDevice
  1402. );
  1403. if (buffersFlushed) {
  1404. DECREASE_MAPPED_TRANSFER_BYTE_COUNT( adapterInformation, Length);
  1405. }
  1406. return buffersFlushed;
  1407. } /// End double buffering //
  1408. } /// end we have adapter information //
  1409. buffersFlushed = (flushAdapterBuffers)(
  1410. DmaAdapter,
  1411. Mdl,
  1412. MapRegisterBase,
  1413. CurrentVa,
  1414. Length,
  1415. WriteToDevice
  1416. );
  1417. if (adapterInformation && buffersFlushed) {
  1418. DECREASE_MAPPED_TRANSFER_BYTE_COUNT( adapterInformation, Length);
  1419. }
  1420. return buffersFlushed;
  1421. } // VfFlushAdapterBuffers //
  1422. VOID
  1423. VfFreeAdapterChannel(
  1424. IN PDMA_ADAPTER DmaAdapter
  1425. )
  1426. /*++
  1427. Routine Description:
  1428. Hooked version of FreeAdapterChannel. Either this or FreeMapRegisters
  1429. must be called, depending on the return value of AllocateAdapterChannel
  1430. callback -- but not both.
  1431. Arguments:
  1432. DmaAdapter -- dma adapter that allocated the adapter channel.
  1433. Return Value:
  1434. None.
  1435. --*/
  1436. {
  1437. PFREE_ADAPTER_CHANNEL freeAdapterChannel;
  1438. PADAPTER_INFORMATION adapterInformation;
  1439. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  1440. freeAdapterChannel = (PFREE_ADAPTER_CHANNEL)
  1441. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(FreeAdapterChannel));
  1442. (freeAdapterChannel)(DmaAdapter);
  1443. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1444. if (! adapterInformation) {
  1445. return;
  1446. }
  1447. DECREASE_MAPPED_TRANSFER_BYTE_COUNT( adapterInformation, 0);
  1448. //
  1449. // Keep track of the adapter channel being freed
  1450. //
  1451. DECREMENT_ADAPTER_CHANNELS(adapterInformation);
  1452. //
  1453. // This also frees the map registers allocated this time.
  1454. //
  1455. SUBTRACT_MAP_REGISTERS( adapterInformation,
  1456. adapterInformation->AdapterChannelMapRegisters );
  1457. adapterInformation->AdapterChannelMapRegisters = 0;
  1458. //
  1459. // In this case, we can tell when we have double mapped the buffer
  1460. //
  1461. if(adapterInformation->AdapterChannelContextBlock.MapRegisterFile) {
  1462. ViFreeMapRegisterFile(
  1463. adapterInformation,
  1464. adapterInformation->AdapterChannelContextBlock.MapRegisterFile
  1465. );
  1466. }
  1467. } // VfFreeAdapterChannel //
  1468. THUNKED_API
  1469. VOID
  1470. VfFreeMapRegisters(
  1471. IN PDMA_ADAPTER DmaAdapter,
  1472. PVOID MapRegisterBase,
  1473. ULONG NumberOfMapRegisters
  1474. )
  1475. /*++
  1476. Routine Description:
  1477. Hooked version of FreeMapRegisters -- must be called if the adapter
  1478. allocation callback routine returned DeallocateObejcetKeepRegisters.
  1479. Arguments:
  1480. DmaAdapter -- adapter for the device that allocated the registers in
  1481. the first place.
  1482. MapRegisterBase -- secret hal pointer.
  1483. NumberOfMapRegisters -- how many map registers you're freeing. Must
  1484. be same as how many registers were allocated.
  1485. Return Value:
  1486. None.
  1487. --*/
  1488. {
  1489. PFREE_MAP_REGISTERS freeMapRegisters;
  1490. PMAP_REGISTER_FILE mapRegisterFile = NULL;
  1491. PADAPTER_INFORMATION adapterInformation;
  1492. freeMapRegisters = (PFREE_MAP_REGISTERS)
  1493. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(FreeMapRegisters));
  1494. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1495. if (adapterInformation) {
  1496. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  1497. mapRegisterFile = MapRegisterBase;
  1498. if (MapRegisterBase == MRF_NULL_PLACEHOLDER) {
  1499. //
  1500. // Some drivers (scsiport for one) don't call
  1501. // HalFlushAdapterBuffers unless MapRegisterBase is non-null.
  1502. // In order to fool the drivers into thinking that they need
  1503. // to flush, we exchange the NULL MapRegisterBase (if in fact
  1504. // the hal uses a null map register base) for our
  1505. /// MRF_NULL_PLACEHOLDER in the adapter allocation callback.
  1506. // So now, if we find that placeholder, we must exchange it
  1507. // for NULL in order not to confuse the hal.
  1508. //
  1509. MapRegisterBase = NULL;
  1510. mapRegisterFile = NULL;
  1511. }
  1512. else if (VALIDATE_MAP_REGISTER_FILE_SIGNATURE(mapRegisterFile)) {
  1513. MapRegisterBase = mapRegisterFile->MapRegisterBaseFromHal;
  1514. }
  1515. }
  1516. (freeMapRegisters)(DmaAdapter, MapRegisterBase, NumberOfMapRegisters);
  1517. if (! adapterInformation) {
  1518. return;
  1519. }
  1520. //
  1521. // Keep track of the map registers that are being freed.
  1522. //
  1523. SUBTRACT_MAP_REGISTERS(adapterInformation, NumberOfMapRegisters);
  1524. //
  1525. // Always do this -- if we're not actually doing double buffering, it
  1526. // will just return. Otherwise if we clear the double-buffering flag
  1527. // on the fly, we won't ever free our allocation.
  1528. //
  1529. ViFreeMapRegisterFile(
  1530. adapterInformation,
  1531. mapRegisterFile
  1532. );
  1533. } // VfFreeMapregisters //
  1534. THUNKED_API
  1535. PHYSICAL_ADDRESS
  1536. VfMapTransfer(
  1537. IN PDMA_ADAPTER DmaAdapter,
  1538. IN PMDL Mdl,
  1539. IN PVOID MapRegisterBase,
  1540. IN PVOID CurrentVa,
  1541. IN OUT PULONG Length,
  1542. IN BOOLEAN WriteToDevice
  1543. )
  1544. /*++
  1545. Routine Description:
  1546. Hooked version of MapTransfer.
  1547. Arguments:
  1548. DmaAdapter -- adapter we're using to map the transfer.
  1549. Mdl -- describes memory to map.
  1550. MapRegisterBase -- Lets the hal monkey around with the data. I hook
  1551. this if I am doing double buffering.
  1552. CurrentVa -- where in the transfer we are.
  1553. Length -- how many bytes to transfer (and how many bytes hal is going
  1554. to let you transfer).
  1555. WriteToDevice -- direction of transfer.
  1556. Return Value:
  1557. PHYSICAL_ADDRESS that is the memory to be transferred as seen by the
  1558. device.
  1559. --*/
  1560. {
  1561. PMAP_TRANSFER mapTransfer;
  1562. PHYSICAL_ADDRESS mappedAddress;
  1563. PADAPTER_INFORMATION adapterInformation;
  1564. mapTransfer = (PMAP_TRANSFER)
  1565. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(MapTransfer));
  1566. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1567. if (adapterInformation) {
  1568. VF_ASSERT_MAX_IRQL(DISPATCH_LEVEL);
  1569. //
  1570. // NOTE -- this may cause a page-fault while at dispatch level if
  1571. // the buffer is not locked down. Thats ok because we would bugcheck
  1572. // anyway if the buffer's not locked down.
  1573. //
  1574. VERIFY_BUFFER_LOCKED(Mdl);
  1575. if (MapRegisterBase == MRF_NULL_PLACEHOLDER) {
  1576. //
  1577. // Some drivers (scsiport for one) don't call
  1578. // HalFlushAdapterBuffers unless MapRegisterBase is non-null.
  1579. // In order to fool the drivers into thinking that they need
  1580. // to flush, we exchange the NULL MapRegisterBase (if in fact
  1581. // the hal uses a null map register base) for our
  1582. /// MRF_NULL_PLACEHOLDER in the adapter callback routine.
  1583. // So now, if we find that placeholder, we must exchange it
  1584. // for NULL in order not to confuse the hal.
  1585. //
  1586. MapRegisterBase = NULL;
  1587. }
  1588. else if (VALIDATE_MAP_REGISTER_FILE_SIGNATURE(
  1589. (PMAP_REGISTER_FILE) MapRegisterBase)) {
  1590. ULONG bytesMapped;
  1591. ///
  1592. // Double buffer away!!!
  1593. ///
  1594. //
  1595. // Note -- we only have to double buffer as much as we want....
  1596. //
  1597. bytesMapped = ViMapDoubleBuffer(
  1598. (PMAP_REGISTER_FILE) MapRegisterBase,
  1599. Mdl,
  1600. CurrentVa,
  1601. *Length,
  1602. WriteToDevice);
  1603. //
  1604. // If we fail to map, bytesMapped will be 0 and we will
  1605. // still use the real mdl & Va -- so we don't need any
  1606. // kind of special cases.
  1607. //
  1608. if (bytesMapped) {
  1609. *Length = bytesMapped;
  1610. //
  1611. // Get the values that IoMapTransfer is going to use
  1612. // i.e. the real map register base, but the
  1613. // mdl and virtual address for double buffering.
  1614. //
  1615. ViSwap(&MapRegisterBase, &Mdl, &CurrentVa);
  1616. }
  1617. else {
  1618. MapRegisterBase = ((PMAP_REGISTER_FILE) MapRegisterBase)->MapRegisterBaseFromHal;
  1619. }
  1620. } // IF double buffering //
  1621. //
  1622. // Make sure that this adapter's common buffers are ok
  1623. //
  1624. ViCheckAdapterBuffers(adapterInformation);
  1625. } // if we are verifying this adapter //
  1626. mappedAddress = (mapTransfer)(
  1627. DmaAdapter,
  1628. Mdl,
  1629. MapRegisterBase,
  1630. CurrentVa,
  1631. Length,
  1632. WriteToDevice
  1633. );
  1634. if (adapterInformation) {
  1635. INCREASE_MAPPED_TRANSFER_BYTE_COUNT( adapterInformation, *Length );
  1636. }
  1637. return mappedAddress;
  1638. } // VfMapTransfer //
  1639. THUNKED_API
  1640. ULONG
  1641. VfGetDmaAlignment(
  1642. IN PDMA_ADAPTER DmaAdapter
  1643. )
  1644. /*++
  1645. Routine Description:
  1646. Hooked GetDmaAlignment. It would be interesting to change this to a big
  1647. number and see how many drivers blow up. On a PC, this is alway 1 so
  1648. it's not particularly interesting (and why drivers may take it for
  1649. granted). Actually drivers can specify that they want this bumped up.
  1650. Arguments:
  1651. DmaAdapter -- get the dma alignment for this device.
  1652. Return Value:
  1653. Align on n byte boundaries where n is the return value.
  1654. --*/
  1655. {
  1656. PGET_DMA_ALIGNMENT getDmaAlignment;
  1657. ULONG dmaAlignment;
  1658. VF_ASSERT_IRQL(PASSIVE_LEVEL);
  1659. getDmaAlignment = (PGET_DMA_ALIGNMENT)
  1660. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(GetDmaAlignment));
  1661. if (! getDmaAlignment) {
  1662. //
  1663. // This should never happen but ..
  1664. //
  1665. return 1;
  1666. }
  1667. dmaAlignment = (getDmaAlignment)(DmaAdapter);
  1668. return dmaAlignment;
  1669. } // GetDmaAlignment //
  1670. ULONG
  1671. VfReadDmaCounter(
  1672. IN PDMA_ADAPTER DmaAdapter
  1673. )
  1674. /*++
  1675. Routine Description:
  1676. Hooked ReadDmaCounter. How much dma is left.
  1677. Arguments:
  1678. DmaAdapter -- read this device's dma counter.
  1679. Return Value:
  1680. Returns how much dma is left.
  1681. --*/
  1682. {
  1683. PREAD_DMA_COUNTER readDmaCounter;
  1684. ULONG dmaCounter;
  1685. VF_ASSERT_MAX_IRQL(DISPATCH_LEVEL);
  1686. readDmaCounter = (PREAD_DMA_COUNTER)
  1687. ViGetRealDmaOperation(DmaAdapter, DMA_OFFSET(ReadDmaCounter));
  1688. dmaCounter = (readDmaCounter)(DmaAdapter);
  1689. return dmaCounter;
  1690. } // VfReadDmaCounter //
  1691. THUNKED_API
  1692. NTSTATUS
  1693. VfGetScatterGatherList (
  1694. IN PDMA_ADAPTER DmaAdapter,
  1695. IN PDEVICE_OBJECT DeviceObject,
  1696. IN PMDL Mdl,
  1697. IN PVOID CurrentVa,
  1698. IN ULONG Length,
  1699. IN PDRIVER_LIST_CONTROL ExecutionRoutine,
  1700. IN PVOID Context,
  1701. IN BOOLEAN WriteToDevice
  1702. )
  1703. /*++
  1704. Routine Description:
  1705. Hooked version of get scatter gather list.
  1706. Arguments:
  1707. DmaAdapter -- Adapter getting the scatter gather list.
  1708. DeviceObject -- device object of device getting scatter gather list.
  1709. Mdl -- get a scatter gather list describing memory in this mdl.
  1710. CurrentVa -- where we are in the transfer.
  1711. Length -- how much to put into the scatter gather list.
  1712. ExecutionRoutine -- callback. We are going to hook this.
  1713. Context -- what to pass into the execution routine.
  1714. WriteToDevice -- direction of transfer.
  1715. Return Value:
  1716. NTSTATUS code.
  1717. --*/
  1718. {
  1719. PGET_SCATTER_GATHER_LIST getScatterGatherList;
  1720. PADAPTER_INFORMATION adapterInformation;
  1721. ULONG numberOfMapRegisters;
  1722. ULONG transferLength;
  1723. ULONG pageOffset;
  1724. ULONG mdlLength;
  1725. PUCHAR mdlVa;
  1726. PMDL tempMdl;
  1727. NTSTATUS status;
  1728. getScatterGatherList = (PGET_SCATTER_GATHER_LIST)
  1729. ViGetRealDmaOperation(
  1730. DmaAdapter,
  1731. DMA_OFFSET(GetScatterGatherList) );
  1732. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1733. if (adapterInformation) {
  1734. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  1735. if (VfInjectDmaFailure() == TRUE) {
  1736. return STATUS_INSUFFICIENT_RESOURCES;
  1737. }
  1738. INCREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  1739. //
  1740. // NOTE -- this may cause a page-fault while at dispatch level if
  1741. // the buffer is not locked down. Thats ok because we would bugcheck
  1742. // anyway if the buffer's not locked down.
  1743. //
  1744. VERIFY_BUFFER_LOCKED(Mdl);
  1745. if (ViDoubleBufferDma) {
  1746. PVF_WAIT_CONTEXT_BLOCK waitBlock;
  1747. PMAP_REGISTER_FILE mapRegisterFile;
  1748. ULONG bytesMapped;
  1749. waitBlock = ExAllocatePoolWithTag(
  1750. NonPagedPool,
  1751. sizeof(VF_WAIT_CONTEXT_BLOCK),
  1752. HAL_VERIFIER_POOL_TAG);
  1753. //
  1754. // If exalloc... failed we can't to double buffering
  1755. //
  1756. if (! waitBlock) {
  1757. goto __NoDoubleBuffer;
  1758. }
  1759. if(ViSuperDebug) {
  1760. DbgPrint(" %p Allocated Wait Block\n",waitBlock );
  1761. }
  1762. RtlZeroMemory(waitBlock, sizeof(VF_WAIT_CONTEXT_BLOCK));
  1763. waitBlock->RealContext = Context;
  1764. waitBlock->RealCallback = (PVOID)ExecutionRoutine;
  1765. mdlVa = MmGetMdlVirtualAddress(Mdl);
  1766. //
  1767. // Calculate the number of required map registers.
  1768. //
  1769. tempMdl = Mdl;
  1770. transferLength = (ULONG) ((ULONG_PTR) tempMdl->ByteCount - (ULONG_PTR) ((PUCHAR) CurrentVa - mdlVa));
  1771. mdlLength = transferLength;
  1772. pageOffset = BYTE_OFFSET(CurrentVa);
  1773. numberOfMapRegisters = 0;
  1774. //
  1775. // The virtual address should fit in the first MDL.
  1776. //
  1777. ASSERT((ULONG)((PUCHAR)CurrentVa - mdlVa) <= tempMdl->ByteCount);
  1778. //
  1779. // Loop through the any chained MDLs accumulating the required
  1780. // number of map registers.
  1781. //
  1782. while (transferLength < Length && tempMdl->Next != NULL) {
  1783. numberOfMapRegisters += (pageOffset + mdlLength + PAGE_SIZE - 1) >>
  1784. PAGE_SHIFT;
  1785. tempMdl = tempMdl->Next;
  1786. pageOffset = tempMdl->ByteOffset;
  1787. mdlLength = tempMdl->ByteCount;
  1788. transferLength += mdlLength;
  1789. }
  1790. if ((transferLength + PAGE_SIZE) < (Length + pageOffset )) {
  1791. ASSERT(transferLength >= Length);
  1792. DECREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  1793. return(STATUS_BUFFER_TOO_SMALL);
  1794. }
  1795. //
  1796. // Calculate the last number of map registers based on the requested
  1797. // length not the length of the last MDL.
  1798. //
  1799. ASSERT( transferLength <= mdlLength + Length );
  1800. numberOfMapRegisters += (pageOffset + Length + mdlLength - transferLength +
  1801. PAGE_SIZE - 1) >> PAGE_SHIFT;
  1802. waitBlock->NumberOfMapRegisters = numberOfMapRegisters;
  1803. waitBlock->AdapterInformation = adapterInformation;
  1804. mapRegisterFile = ViAllocateMapRegisterFile(
  1805. adapterInformation,
  1806. waitBlock->NumberOfMapRegisters
  1807. );
  1808. if (! mapRegisterFile ) {
  1809. if(ViSuperDebug) {
  1810. DbgPrint("%p Freeing Wait Block\n",waitBlock);
  1811. }
  1812. ExFreePool(waitBlock);
  1813. goto __NoDoubleBuffer;
  1814. }
  1815. //
  1816. // Signal that the map register file is for scatter gather
  1817. // this will make sure that the whole buffer gets mapped
  1818. //
  1819. mapRegisterFile->ScatterGather = TRUE;
  1820. waitBlock->MapRegisterFile = mapRegisterFile;
  1821. waitBlock->RealMdl = Mdl;
  1822. waitBlock->RealStartVa = CurrentVa;
  1823. waitBlock->RealLength = Length;
  1824. bytesMapped = ViMapDoubleBuffer(
  1825. mapRegisterFile,
  1826. Mdl,
  1827. CurrentVa,
  1828. Length,
  1829. WriteToDevice );
  1830. if (bytesMapped) {
  1831. //
  1832. // Since we mapped the buffer, we can hook the callback
  1833. // routine & send out wait block as the parameter
  1834. //
  1835. Context = waitBlock;
  1836. ExecutionRoutine = VfScatterGatherCallback;
  1837. //
  1838. // mapRegisterFile gets destroyed here but we don't
  1839. // need it any more
  1840. //
  1841. ViSwap(&mapRegisterFile, &Mdl, &CurrentVa);
  1842. }
  1843. else {
  1844. //
  1845. // If for some strange reason we couldn't map the whole buffer
  1846. // (that is bad because we just created the double- buffer to be exactly
  1847. // the size we wanted)
  1848. //
  1849. ASSERT(FALSE);
  1850. ViFreeMapRegisterFile(adapterInformation, mapRegisterFile);
  1851. ExFreePool(waitBlock);
  1852. }
  1853. } // IF double buffering //
  1854. } // If verifying adapter //
  1855. __NoDoubleBuffer:
  1856. status = (getScatterGatherList)(
  1857. DmaAdapter,
  1858. DeviceObject,
  1859. Mdl,
  1860. CurrentVa,
  1861. Length,
  1862. ExecutionRoutine,
  1863. Context,
  1864. WriteToDevice
  1865. );
  1866. if (adapterInformation && ! NT_SUCCESS(status)) {
  1867. DECREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  1868. }
  1869. return status;
  1870. } // VfGetScatterGatherList //
  1871. THUNKED_API
  1872. VOID
  1873. VfPutScatterGatherList(
  1874. IN PDMA_ADAPTER DmaAdapter,
  1875. IN PSCATTER_GATHER_LIST ScatterGather,
  1876. IN BOOLEAN WriteToDevice
  1877. )
  1878. /*++
  1879. Routine Description:
  1880. Hooked version of PutScatterGatherList.
  1881. Arguments:
  1882. DmaAdapter -- adapter of dma.
  1883. ScatterGather -- scatter gather list we are putting away.
  1884. WriteToDevice -- which direction we are transferring.
  1885. Return Value:
  1886. NONE.
  1887. --*/
  1888. {
  1889. PPUT_SCATTER_GATHER_LIST putScatterGatherList;
  1890. PADAPTER_INFORMATION adapterInformation;
  1891. putScatterGatherList = (PPUT_SCATTER_GATHER_LIST)
  1892. ViGetRealDmaOperation(
  1893. DmaAdapter,
  1894. DMA_OFFSET(PutScatterGatherList) );
  1895. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  1896. if (adapterInformation) {
  1897. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  1898. if ( ! VF_IS_LOCKED_LIST_EMPTY(&adapterInformation->ScatterGatherLists) ) {
  1899. //
  1900. // We've got some double bufferin candidates.
  1901. // Note we don't just check for whether doublebuffering is
  1902. // enabled since a. it can be turned off on the fly and b.
  1903. // we may have failed to allocate the overhead structures and
  1904. // not double buffered this particular list
  1905. //
  1906. PVF_WAIT_CONTEXT_BLOCK waitBlock;
  1907. KIRQL Irql;
  1908. VF_LOCK_LIST(&adapterInformation->ScatterGatherLists, Irql);
  1909. FOR_ALL_IN_LIST(VF_WAIT_CONTEXT_BLOCK, &adapterInformation->ScatterGatherLists.ListEntry, waitBlock) {
  1910. if (waitBlock->ScatterGatherList == ScatterGather) {
  1911. //
  1912. // We found what we're looking for.
  1913. //
  1914. ULONG elements = ScatterGather->NumberOfElements;
  1915. VF_REMOVE_FROM_LOCKED_LIST_DONT_LOCK(&adapterInformation->ScatterGatherLists, waitBlock);
  1916. VF_UNLOCK_LIST(&adapterInformation->ScatterGatherLists, Irql);
  1917. //
  1918. // Call the real scatter gather function
  1919. //
  1920. (putScatterGatherList)(
  1921. DmaAdapter,
  1922. ScatterGather,
  1923. WriteToDevice
  1924. );
  1925. SUBTRACT_MAP_REGISTERS(adapterInformation, elements);
  1926. DECREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  1927. //
  1928. // Un double buffer us
  1929. // (copy out the double buffer)
  1930. //
  1931. if (! ViFlushDoubleBuffer(
  1932. waitBlock->MapRegisterFile,
  1933. waitBlock->RealMdl,
  1934. waitBlock->RealStartVa,
  1935. waitBlock->RealLength,
  1936. WriteToDevice )) {
  1937. ASSERT(0 && "HAL Verifier error -- could not flush scatter gather double buffer");
  1938. }
  1939. //
  1940. // free the map register file
  1941. //
  1942. if (!ViFreeMapRegisterFile(
  1943. adapterInformation,
  1944. waitBlock->MapRegisterFile)) {
  1945. ASSERT(0 && "HAL Verifier error -- could not free map register file for scatter gather");
  1946. }
  1947. if(ViSuperDebug) {
  1948. DbgPrint("%p Freeing Wait Block\n",waitBlock);
  1949. }
  1950. ExFreePool(waitBlock);
  1951. return;
  1952. }
  1953. } // For each scatter gather list allocated for this adapter //
  1954. VF_UNLOCK_LIST(&adapterInformation->ScatterGatherLists, Irql);
  1955. }
  1956. }
  1957. (putScatterGatherList)(
  1958. DmaAdapter,
  1959. ScatterGather,
  1960. WriteToDevice
  1961. );
  1962. if (adapterInformation) {
  1963. DECREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  1964. }
  1965. } // VfPutScatterGatherList //
  1966. NTSTATUS
  1967. VfCalculateScatterGatherListSize(
  1968. IN PDMA_ADAPTER DmaAdapter,
  1969. IN OPTIONAL PMDL Mdl,
  1970. IN PVOID CurrentVa,
  1971. IN ULONG Length,
  1972. OUT PULONG ScatterGatherListSize,
  1973. OUT OPTIONAL PULONG pNumberOfMapRegisters
  1974. )
  1975. /*++
  1976. Routine Description:
  1977. Hooked version of CalculateScatterGatherListSize.
  1978. We don't do anything here
  1979. Arguments:
  1980. Same as CalculateScatterGatherListSize
  1981. Return Value:
  1982. NTSTATUS code
  1983. --*/
  1984. {
  1985. PCALCULATE_SCATTER_GATHER_LIST_SIZE calculateSgListSize;
  1986. calculateSgListSize = (PCALCULATE_SCATTER_GATHER_LIST_SIZE )
  1987. ViGetRealDmaOperation(
  1988. DmaAdapter,
  1989. DMA_OFFSET(CalculateScatterGatherList)
  1990. );
  1991. return (calculateSgListSize) (
  1992. DmaAdapter,
  1993. Mdl,
  1994. CurrentVa,
  1995. Length,
  1996. ScatterGatherListSize,
  1997. pNumberOfMapRegisters
  1998. );
  1999. } // VfCalculateScatterGatherListSize //
  2000. NTSTATUS
  2001. VfBuildScatterGatherList(
  2002. IN PDMA_ADAPTER DmaAdapter,
  2003. IN PDEVICE_OBJECT DeviceObject,
  2004. IN PMDL Mdl,
  2005. IN PVOID CurrentVa,
  2006. IN ULONG Length,
  2007. IN PDRIVER_LIST_CONTROL ExecutionRoutine,
  2008. IN PVOID Context,
  2009. IN BOOLEAN WriteToDevice,
  2010. IN PVOID ScatterGatherBuffer,
  2011. IN ULONG ScatterGatherLength
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. Hooked version of BuildScatterGatherList
  2016. Arguments:
  2017. Same as BuildScatterGatherList
  2018. Return Value:
  2019. NTSTATUS code
  2020. --*/
  2021. {
  2022. PBUILD_SCATTER_GATHER_LIST buildScatterGatherList;
  2023. PADAPTER_INFORMATION adapterInformation;
  2024. NTSTATUS status;
  2025. buildScatterGatherList = (PBUILD_SCATTER_GATHER_LIST)
  2026. ViGetRealDmaOperation(
  2027. DmaAdapter,
  2028. DMA_OFFSET(BuildScatterGatherList) );
  2029. adapterInformation = ViGetAdapterInformation(DmaAdapter);
  2030. if (adapterInformation) {
  2031. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  2032. if (VfInjectDmaFailure() == TRUE) {
  2033. return STATUS_INSUFFICIENT_RESOURCES;
  2034. }
  2035. INCREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  2036. //
  2037. // NOTE -- this may cause a page-fault while at dispatch level if
  2038. // the buffer is not locked down. Thats ok because we would bugcheck
  2039. // anyway if the buffer's not locked down.
  2040. //
  2041. VERIFY_BUFFER_LOCKED(Mdl);
  2042. if (ViDoubleBufferDma) {
  2043. PVF_WAIT_CONTEXT_BLOCK waitBlock;
  2044. PMAP_REGISTER_FILE mapRegisterFile;
  2045. ULONG bytesMapped;
  2046. waitBlock = ExAllocatePoolWithTag(
  2047. NonPagedPool,
  2048. sizeof(VF_WAIT_CONTEXT_BLOCK),
  2049. HAL_VERIFIER_POOL_TAG);
  2050. //
  2051. // If exalloc... failed we can't to double buffering
  2052. //
  2053. if (! waitBlock) {
  2054. goto __NoDoubleBuffer;
  2055. }
  2056. if(ViSuperDebug) {
  2057. DbgPrint(" %p Allocated Wait Block\n",waitBlock );
  2058. }
  2059. RtlZeroMemory(waitBlock, sizeof(VF_WAIT_CONTEXT_BLOCK));
  2060. waitBlock->RealContext = Context;
  2061. waitBlock->RealCallback = (PVOID)ExecutionRoutine;
  2062. waitBlock->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentVa, Length);
  2063. waitBlock->AdapterInformation = adapterInformation;
  2064. mapRegisterFile = ViAllocateMapRegisterFile(
  2065. adapterInformation,
  2066. waitBlock->NumberOfMapRegisters
  2067. );
  2068. if (! mapRegisterFile ) {
  2069. if(ViSuperDebug) {
  2070. DbgPrint("%p Freeing Wait Block\n",waitBlock);
  2071. }
  2072. ExFreePool(waitBlock);
  2073. goto __NoDoubleBuffer;
  2074. }
  2075. //
  2076. // Signal that the map register file is for scatter gather
  2077. // this will make sure that the whole buffer gets mapped
  2078. //
  2079. mapRegisterFile->ScatterGather = TRUE;
  2080. waitBlock->MapRegisterFile = mapRegisterFile;
  2081. waitBlock->RealMdl = Mdl;
  2082. waitBlock->RealStartVa = CurrentVa;
  2083. waitBlock->RealLength = Length;
  2084. bytesMapped = ViMapDoubleBuffer(
  2085. mapRegisterFile,
  2086. Mdl,
  2087. CurrentVa,
  2088. Length,
  2089. WriteToDevice );
  2090. if (bytesMapped) {
  2091. //
  2092. // Since we mapped the buffer, we can hook the callback
  2093. // routine & send out wait block as the parameter
  2094. //
  2095. Context = waitBlock;
  2096. ExecutionRoutine = VfScatterGatherCallback;
  2097. //
  2098. // mapRegisterFile gets destroyed here but we don't
  2099. // need it any more
  2100. //
  2101. ViSwap(&mapRegisterFile, &Mdl, &CurrentVa);
  2102. }
  2103. else {
  2104. //
  2105. // If for some strange reason we couldn't map the whole buffer
  2106. // (that is bad because we just created the double- buffer to be exactly
  2107. // the size we wanted)
  2108. //
  2109. ASSERT(FALSE);
  2110. ViFreeMapRegisterFile(adapterInformation, mapRegisterFile);
  2111. ExFreePool(waitBlock);
  2112. }
  2113. } // IF double buffering //
  2114. } // If verifying adapter //
  2115. __NoDoubleBuffer:
  2116. status = (buildScatterGatherList)(
  2117. DmaAdapter,
  2118. DeviceObject,
  2119. Mdl,
  2120. CurrentVa,
  2121. Length,
  2122. ExecutionRoutine,
  2123. Context,
  2124. WriteToDevice,
  2125. ScatterGatherBuffer,
  2126. ScatterGatherLength
  2127. );
  2128. if (adapterInformation && ! NT_SUCCESS(status)) {
  2129. DECREMENT_SCATTER_GATHER_LISTS(adapterInformation);
  2130. }
  2131. return status;
  2132. } // VfBuildScatterGatherList //
  2133. NTSTATUS
  2134. VfBuildMdlFromScatterGatherList(
  2135. IN PDMA_ADAPTER DmaAdapter,
  2136. IN PSCATTER_GATHER_LIST ScatterGather,
  2137. IN PMDL OriginalMdl,
  2138. OUT PMDL *TargetMdl
  2139. )
  2140. /*++
  2141. Routine Description:
  2142. Hooked version of BuildMdlFromScatterGatherList.
  2143. Don't really do anything here
  2144. Arguments:
  2145. Same as BuildMdlFromScatterGatherList
  2146. Return Value:
  2147. NTSTATUS code
  2148. --*/
  2149. {
  2150. PBUILD_MDL_FROM_SCATTER_GATHER_LIST buildMdlFromScatterGatherList;
  2151. buildMdlFromScatterGatherList = (PBUILD_MDL_FROM_SCATTER_GATHER_LIST)
  2152. ViGetRealDmaOperation(
  2153. DmaAdapter,
  2154. DMA_OFFSET(BuildMdlFromScatterGatherList) );
  2155. return (buildMdlFromScatterGatherList) (
  2156. DmaAdapter,
  2157. ScatterGather,
  2158. OriginalMdl,
  2159. TargetMdl
  2160. );
  2161. } // VfBuildMdlFromScatterGatherList //
  2162. IO_ALLOCATION_ACTION
  2163. VfAdapterCallback(
  2164. IN PDEVICE_OBJECT DeviceObject,
  2165. IN PIRP Irp,
  2166. IN PVOID MapRegisterBase,
  2167. IN PVOID Context
  2168. )
  2169. /*++
  2170. Routine Description:
  2171. We hook the callback from AllocateAdapterChannel so we that we can make
  2172. sure that the driver only tries to do this one at a time.
  2173. Arguments:
  2174. DeviceObject -- device object.
  2175. Irp -- current irp.
  2176. MapRegisterBase -- magic number provided by HAL
  2177. Context -- A special context block with relevant information inside.
  2178. Return Value:
  2179. NONE.
  2180. --*/
  2181. {
  2182. PVF_WAIT_CONTEXT_BLOCK contextBlock =
  2183. (PVF_WAIT_CONTEXT_BLOCK) Context;
  2184. IO_ALLOCATION_ACTION allocationAction;
  2185. PADAPTER_INFORMATION adapterInformation;
  2186. if (VALIDATE_MAP_REGISTER_FILE_SIGNATURE(contextBlock->MapRegisterFile)) {
  2187. //
  2188. // Do the old switcheroo -- we are now substituting *our* map
  2189. // register base for *theirs* (and hide a pointer to *theirs*
  2190. // in *ours*)
  2191. //
  2192. contextBlock->MapRegisterFile->MapRegisterBaseFromHal =
  2193. MapRegisterBase;
  2194. MapRegisterBase = contextBlock->MapRegisterFile;
  2195. }
  2196. else {
  2197. //
  2198. // Some drivers (scsiport for one) don't call
  2199. // HalFlushAdapterBuffers unless MapRegisterBase is non-null.
  2200. // In order to fool the drivers into thinking that they need
  2201. // to flush, we exchange the NULL MapRegisterBase (if in fact
  2202. // the hal uses a null map register base) for our
  2203. /// MRF_NULL_PLACEHOLDER.
  2204. //
  2205. //
  2206. // 12/15/2000 - Use the non-NULL placeholder
  2207. // only if the original MapRegisterBase is NULL,
  2208. // otherwise leave it alone...
  2209. //
  2210. if (NULL == MapRegisterBase) {
  2211. MapRegisterBase = MRF_NULL_PLACEHOLDER;
  2212. }
  2213. }
  2214. adapterInformation = contextBlock->AdapterInformation;
  2215. //
  2216. // Fix a weird race condition:
  2217. // - if we expect the callback to return something other than KeepObject
  2218. // we're going to decrement the adapter channel count in advance
  2219. // to prevent ndis from calling another AllocateAdapterChannel before
  2220. // we can make it to the DECREMENT_ADAPTER_CHANNEL call
  2221. //
  2222. if (adapterInformation &&
  2223. adapterInformation->DeviceDescription.Master) {
  2224. //
  2225. // Master devices are the ones that return
  2226. // DeallocateObjectKeepRegisters.
  2227. //
  2228. DECREMENT_ADAPTER_CHANNELS(adapterInformation);
  2229. }
  2230. //
  2231. // Call the *real* callback routine
  2232. //
  2233. allocationAction = ((PDRIVER_CONTROL) contextBlock->RealCallback)(
  2234. DeviceObject,
  2235. Irp,
  2236. MapRegisterBase,
  2237. contextBlock->RealContext
  2238. );
  2239. if (! adapterInformation) {
  2240. return allocationAction;
  2241. }
  2242. //
  2243. // Ok if we keep everything, just return
  2244. //
  2245. if (allocationAction == KeepObject) {
  2246. //
  2247. // Only slave devices should get here
  2248. //
  2249. if (adapterInformation->DeviceDescription.Master) {
  2250. //
  2251. // We should not get here. But if we do, compensate for the
  2252. // DECREMENT_ADAPTER_CHANNELS we did before just in case.
  2253. // We do a InterlockedDecrement instead of a
  2254. // INCREMENT_ADAPTER_CHANNELS so our allocated and freed
  2255. // count reflect the number of real alloc/free operations performed.
  2256. //
  2257. InterlockedDecrement((PLONG)(&adapterInformation->FreedAdapterChannels));
  2258. DbgPrint("Driver at address %p has a problem\n", adapterInformation->CallingAddress );
  2259. DbgPrint("Master devices should return DeallocateObjectKeepRegisters\n");
  2260. ASSERT(0);
  2261. }
  2262. adapterInformation->AdapterChannelMapRegisters =
  2263. contextBlock->NumberOfMapRegisters;
  2264. return allocationAction;
  2265. }
  2266. //
  2267. // Otherwise we are definitely freeing the adapter channel.
  2268. // Keep in mind that we have done this for Master devices,
  2269. // do it just for Slave devices.
  2270. //
  2271. if (!adapterInformation->DeviceDescription.Master) {
  2272. DECREMENT_ADAPTER_CHANNELS(adapterInformation);
  2273. }
  2274. if (allocationAction == DeallocateObjectKeepRegisters) {
  2275. return allocationAction;
  2276. }
  2277. //
  2278. // Ok now we know we're getting rid of map registers too...
  2279. //
  2280. SUBTRACT_MAP_REGISTERS( adapterInformation,
  2281. contextBlock->NumberOfMapRegisters );
  2282. //
  2283. // False alarm ... we went through all the trouble of allocating the
  2284. // double map buffer registers and they don't even want them. We should
  2285. // bugcheck out of spite.
  2286. //
  2287. if (VALIDATE_MAP_REGISTER_FILE_SIGNATURE(contextBlock->MapRegisterFile)) {
  2288. ViFreeMapRegisterFile(
  2289. adapterInformation,
  2290. contextBlock->MapRegisterFile);
  2291. }
  2292. return allocationAction;
  2293. } // VfAdapterCallback //
  2294. #if !defined (NO_LEGACY_DRIVERS)
  2295. PADAPTER_OBJECT
  2296. VfLegacyGetAdapter(
  2297. IN PDEVICE_DESCRIPTION DeviceDescription,
  2298. IN OUT PULONG NumberOfMapRegisters
  2299. )
  2300. /*++
  2301. Routine Description:
  2302. This function is a bit of a hack made necessary by the drivers that use
  2303. a different hack -- they use nt4 apis instead of the new ones. We
  2304. allocate an adapter and mark it as legacy -- we will have to hook the dma
  2305. functions the old fashioned way instead of from the dma operations.
  2306. We don't have to worry that the new-fangled dma apis call the old'ns
  2307. as long as the hal-kernel interface isn't hooked -- since the new apis
  2308. will call the old from the kernel, the thunks will still point to the
  2309. hal and not to us.
  2310. Arguments:
  2311. DeviceDescription -- A structure describing the device we are trying to
  2312. get an adapter for. At some point, I'm going to monkey around with
  2313. this guy so we can convince the HAL that we are something that we're
  2314. not, but for now just gets passed straight into IoGetDmaAdapter.
  2315. NumberOfMapRegisters -- maximum number of map registers that the driver
  2316. is going to try to allocate.
  2317. Return Value:
  2318. Returns a pointer to the dma adapter or
  2319. NULL if we couldn't allocate one.
  2320. --*/
  2321. {
  2322. PVOID callingAddress;
  2323. PADAPTER_INFORMATION newAdapterInformation;
  2324. PDMA_ADAPTER dmaAdapter;
  2325. //
  2326. // Give the option of not verifying at all
  2327. //
  2328. if (! ViVerifyDma ) {
  2329. return HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
  2330. }
  2331. if (VfInjectDmaFailure()) {
  2332. return NULL;
  2333. }
  2334. VF_ASSERT_IRQL(PASSIVE_LEVEL);
  2335. GET_CALLING_ADDRESS(callingAddress);
  2336. VF_ASSERT(
  2337. 0,
  2338. HV_OBSOLETE_API,
  2339. ("HalGetAdapter API obsolete -- use IoGetDmaAdapter instead")
  2340. );
  2341. if ( ViDoubleBufferDma &&
  2342. *NumberOfMapRegisters > ViMaxMapRegistersPerAdapter ) {
  2343. //
  2344. // Harumph -- don't let drivers try to get too many map registers
  2345. //
  2346. *NumberOfMapRegisters = ViMaxMapRegistersPerAdapter;
  2347. }
  2348. dmaAdapter = (PDMA_ADAPTER) HalGetAdapter(
  2349. DeviceDescription,
  2350. NumberOfMapRegisters
  2351. );
  2352. if (! dmaAdapter ) {
  2353. //
  2354. // early opt-out here -- the hal couldn't allocate the adapter
  2355. //
  2356. return NULL;
  2357. }
  2358. //
  2359. // Replace all of the dma operations that live in the adapter with our
  2360. // dma operations.. If we can't do it, fail.
  2361. //
  2362. newAdapterInformation = ViHookDmaAdapter(
  2363. dmaAdapter,
  2364. DeviceDescription,
  2365. *NumberOfMapRegisters
  2366. );
  2367. if (! newAdapterInformation) {
  2368. //
  2369. // remember to put away our toys -- even though we've been called
  2370. // with legacy apis, we can still do the right thing here.
  2371. //
  2372. dmaAdapter->DmaOperations->PutDmaAdapter(dmaAdapter);
  2373. return NULL;
  2374. }
  2375. newAdapterInformation->DeviceObject = NULL;
  2376. newAdapterInformation->CallingAddress = callingAddress;
  2377. return (PADAPTER_OBJECT) dmaAdapter;
  2378. } // VfLegacyGetAdapter //
  2379. #endif
  2380. PVOID
  2381. ViSpecialAllocateCommonBuffer(
  2382. IN PALLOCATE_COMMON_BUFFER AllocateCommonBuffer,
  2383. IN PADAPTER_INFORMATION AdapterInformation,
  2384. IN PVOID CallingAddress,
  2385. IN ULONG Length,
  2386. IN OUT PPHYSICAL_ADDRESS LogicalAddress,
  2387. IN LOGICAL CacheEnabled
  2388. )
  2389. /*++
  2390. Routine Description:
  2391. Special version of allocate common buffer that keeps close track of
  2392. allocations.
  2393. Arguments:
  2394. AllocateCommonBuffer -- pointer to the hal buffer allocation routine.
  2395. AdapterInformation -- contains information about the adapter we're using.
  2396. CallingAddress -- who called us -- (who called VfAllocateCommonBuffer).
  2397. Length -- Size of the common buffer (note we are going to increase).
  2398. LogicalAddress -- Gets the *PHYSICAL* address of the common buffer.
  2399. CacheEnabled -- whether or not the memory should be cached.
  2400. Return Value:
  2401. Returns the *VIRTUAL* address of the common buffer or
  2402. NULL if it could not be allocated.
  2403. --*/
  2404. {
  2405. ULONG desiredLength;
  2406. ULONG paddingLength;
  2407. ULONG prePadding;
  2408. ULONG postPadding;
  2409. PHAL_VERIFIER_BUFFER verifierBuffer;
  2410. PUCHAR commonBuffer;
  2411. PHYSICAL_ADDRESS realLogicalAddress;
  2412. verifierBuffer = ExAllocatePoolWithTag(
  2413. NonPagedPool,
  2414. sizeof(HAL_VERIFIER_BUFFER),
  2415. HAL_VERIFIER_POOL_TAG
  2416. );
  2417. if (!verifierBuffer) {
  2418. DbgPrint("Couldn't track common buffer allocation\n");
  2419. return NULL;
  2420. }
  2421. ViCommonBufferCalculatePadding(Length, &prePadding, &postPadding);
  2422. paddingLength = prePadding + postPadding;
  2423. desiredLength = paddingLength + Length;
  2424. if (ViSuperDebug) {
  2425. DbgPrint("Common buffer req len:%x alloc len %x, padding %x / %x\n",
  2426. Length, desiredLength, prePadding, postPadding);
  2427. }
  2428. if (ViProtectBuffers) {
  2429. ASSERT( !BYTE_OFFSET(desiredLength) );
  2430. // ASSERT( paddingLength >= 2 * sizeof(ViDmaVerifierTag));
  2431. }
  2432. //
  2433. // Call into the hal to try to get us a common buffer
  2434. //
  2435. commonBuffer = (AllocateCommonBuffer)(
  2436. AdapterInformation->DmaAdapter,
  2437. desiredLength,
  2438. &realLogicalAddress,
  2439. (BOOLEAN) CacheEnabled
  2440. );
  2441. if (! commonBuffer) {
  2442. #if DBG
  2443. DbgPrint("Could not allocate 'special' common buffer size %x\n",
  2444. desiredLength);
  2445. #endif
  2446. ExFreePool(verifierBuffer);
  2447. return NULL;
  2448. }
  2449. //
  2450. // This is our overhead structure we're zeroing out here
  2451. //
  2452. RtlZeroMemory(verifierBuffer, sizeof(HAL_VERIFIER_BUFFER));
  2453. //
  2454. // Save off all of the data we have
  2455. //
  2456. verifierBuffer->PrePadBytes = (USHORT) prePadding;
  2457. verifierBuffer->PostPadBytes = (USHORT) postPadding;
  2458. verifierBuffer->AdvertisedLength = Length;
  2459. verifierBuffer->RealLength = desiredLength;
  2460. verifierBuffer->RealStartAddress = commonBuffer;
  2461. verifierBuffer->AdvertisedStartAddress = commonBuffer + prePadding;
  2462. verifierBuffer->RealLogicalStartAddress = realLogicalAddress;
  2463. verifierBuffer->AllocatorAddress = CallingAddress;
  2464. //
  2465. // Fill the common buffer with junk to a. mark it and b. so no one uses
  2466. // it without initializing it.
  2467. //
  2468. ViInitializePadding(
  2469. verifierBuffer->RealStartAddress,
  2470. verifierBuffer->RealLength,
  2471. verifierBuffer->AdvertisedStartAddress,
  2472. verifierBuffer->AdvertisedLength
  2473. );
  2474. //
  2475. // Tell the driver that the allocation is in the middle of our guarded
  2476. // section
  2477. //
  2478. LogicalAddress->QuadPart = realLogicalAddress.QuadPart + prePadding;
  2479. VF_ADD_TO_LOCKED_LIST( &AdapterInformation->CommonBuffers,
  2480. verifierBuffer );
  2481. INCREMENT_COMMON_BUFFERS(AdapterInformation);
  2482. return (commonBuffer+prePadding);
  2483. } // ViSpecialAllocateCommonBuffer //
  2484. LOGICAL
  2485. ViSpecialFreeCommonBuffer(
  2486. IN PFREE_COMMON_BUFFER FreeCommonBuffer,
  2487. IN PADAPTER_INFORMATION AdapterInformation,
  2488. IN PVOID CommonBuffer,
  2489. LOGICAL CacheEnabled
  2490. )
  2491. /*++
  2492. Routine Description:
  2493. Tries to undo the damage done by the special common buffer allocator.
  2494. Arguments:
  2495. FreeCommonBuffer -- pointer to the hal buffer free routine.
  2496. AdapterInformation -- contains information about the adapter we're using.
  2497. CommonBuffer -- we use this to look up which allocation to free.
  2498. CacheEnabled -- whether or not the buffer was cached.
  2499. Return Value:
  2500. NONE
  2501. --*/
  2502. {
  2503. PHAL_VERIFIER_BUFFER verifierBuffer;
  2504. verifierBuffer = VF_FIND_BUFFER(&AdapterInformation->CommonBuffers,
  2505. CommonBuffer);
  2506. if (! verifierBuffer) {
  2507. //
  2508. // We couldn't find this buffer in the list
  2509. //
  2510. if (ViProtectBuffers) {
  2511. DbgPrint("HV: Couldn't find buffer %p\n",CommonBuffer);
  2512. }
  2513. return FALSE;
  2514. }
  2515. if (ViProtectBuffers) {
  2516. //
  2517. // When we created the buffer we built in a bit of padding at the
  2518. // beginning and end of the allocation -- make sure that nobody has
  2519. // touched it.
  2520. //
  2521. ViCheckPadding(
  2522. verifierBuffer->RealStartAddress,
  2523. verifierBuffer->RealLength,
  2524. verifierBuffer->AdvertisedStartAddress,
  2525. verifierBuffer->AdvertisedLength
  2526. );
  2527. }
  2528. //
  2529. // Take this buffer out of circulation.
  2530. //
  2531. VF_REMOVE_FROM_LOCKED_LIST( &AdapterInformation->CommonBuffers,
  2532. verifierBuffer);
  2533. //
  2534. // Zero out the common buffer memory so that nobody tries to access
  2535. // it after it gets freed
  2536. //
  2537. RtlZeroMemory(CommonBuffer, verifierBuffer->AdvertisedLength);
  2538. (FreeCommonBuffer)(
  2539. AdapterInformation->DmaAdapter,
  2540. verifierBuffer->RealLength,
  2541. verifierBuffer->RealLogicalStartAddress,
  2542. verifierBuffer->RealStartAddress,
  2543. (BOOLEAN) CacheEnabled
  2544. );
  2545. DECREMENT_COMMON_BUFFERS(AdapterInformation);
  2546. ExFreePool(verifierBuffer);
  2547. return TRUE;
  2548. } // ViSpecialFreeCommonBuffer //
  2549. PMAP_REGISTER_FILE
  2550. ViAllocateMapRegisterFile(
  2551. IN PADAPTER_INFORMATION AdapterInformation,
  2552. IN ULONG NumberOfMapRegisters
  2553. )
  2554. /*++
  2555. Routine Description:
  2556. In order to isolate a mapped buffer, we're going to do double buffering
  2557. ourselves. We allocate buffers that we will use when the driver calls
  2558. MapTransfer.
  2559. N.B. This function is almost as messy as my dorm room in college.
  2560. When we are doing dma, we have a buffer that will look like this:
  2561. Virtual Physical
  2562. Buffer memory
  2563. to do
  2564. dma with
  2565. +------+
  2566. +------+ | 3 |
  2567. | 1 | +------+
  2568. +------+ +------+
  2569. | 2 | <--> | 4 |
  2570. +------+ +------+ +------+
  2571. | 3 | | 1 | +------+
  2572. +------+ +------+ | 2 |
  2573. | 4 | +------+
  2574. +------+
  2575. The problem is that since the pages are scattered around physical memory,
  2576. If the hardware overruns the buffer, we'll never know or it will cause
  2577. a random failure down the line. What I want to do is allocate the pages
  2578. physically on either side of each page of the transfer like this:
  2579. (where the 'X' pages are filed with a known pattern that we can test to
  2580. make sure they haven't changed).
  2581. Virtual Physical
  2582. Buffer memory
  2583. to do +------+
  2584. dma with |XXXXXX|
  2585. +------+
  2586. +------+ | 3 | +------+
  2587. | 1 | +------+ |XXXXXX|
  2588. +------+ |XXXXXX|+------+ +------+
  2589. | 2 | <--> +------+|XXXXXX| | 4 | +------+
  2590. +------+ +------+ +------+ |XXXXXX|
  2591. | 3 | | 1 | |XXXXXX| +------+
  2592. +------+ +------+ +------+ | 2 |
  2593. | 4 | |XXXXXX| +------+
  2594. +------+ +------+ |XXXXXX|
  2595. +------+
  2596. In order to do this, for each map register needed by the device, I create
  2597. one of the 3-contiguous page entities shown above. Then I create an mdl
  2598. and map the center pages into a single virtual buffer. After this is set
  2599. up, during each map transfer, I have to copy the contents of the driver's
  2600. virtual buffer into my newly created buffer and pass this to the HAL.
  2601. (IoMapTransfer is really in the HAL despite the prefix). The contents are
  2602. copied back when a FlushAdapterBuffers is done.
  2603. N.B. For slave devices, the pages have to be contiguous in memory. So
  2604. the above won't work.
  2605. Arguments:
  2606. AdapterInformation -- contains information about the adapter we're using
  2607. NumberOfMapRegisters -- how many map registers to allocate.
  2608. Return Value:
  2609. New map register file pointer (of course we also add it to the
  2610. adapterinformation list) or NULL on failure.
  2611. --*/
  2612. {
  2613. ULONG mapRegisterBufferSize;
  2614. PMAP_REGISTER_FILE mapRegisterFile;
  2615. PMDL mapRegisterMdl;
  2616. PPFN_NUMBER registerFilePfnArray;
  2617. PFN_NUMBER registerPfn;
  2618. PMAP_REGISTER tempMapRegister;
  2619. ULONG mapRegistersLeft;
  2620. //
  2621. // Make sure we haven't tried to allocate too many map registers to
  2622. // this device
  2623. //
  2624. mapRegistersLeft = AdapterInformation->ActiveMapRegisters;
  2625. if ( mapRegistersLeft + NumberOfMapRegisters > ViMaxMapRegistersPerAdapter ) {
  2626. //
  2627. // Don't have enough room in this adpter's quota to allocate the
  2628. // map registers. Why do we need a quota at all? Because annoying
  2629. // drivers like NDIS etc. try to get around their maximum map
  2630. // register allocation by cheating. Ok so they don't cheat but
  2631. // they demand like thousands of map registers two at a time.
  2632. // Actually returning null here doesn't affect whether the driver
  2633. // gets the map registers or not .. we're just not going to double
  2634. // buffer them.
  2635. //
  2636. return NULL;
  2637. }
  2638. if (0 == NumberOfMapRegisters) {
  2639. //
  2640. // This is weird but still legal, just don't double
  2641. // buffer in this case.
  2642. //
  2643. return NULL;
  2644. }
  2645. //
  2646. // Allocate space for the register file
  2647. //
  2648. mapRegisterBufferSize =
  2649. sizeof(MAP_REGISTER_FILE) +
  2650. sizeof(MAP_REGISTER) * (NumberOfMapRegisters-1);
  2651. mapRegisterFile = ExAllocatePoolWithTag(
  2652. NonPagedPool,
  2653. mapRegisterBufferSize,
  2654. HAL_VERIFIER_POOL_TAG
  2655. );
  2656. if (! mapRegisterFile)
  2657. return NULL;
  2658. if (ViSuperDebug) {
  2659. DbgPrint("%p Allocated Map register file\n",mapRegisterFile);
  2660. }
  2661. RtlZeroMemory(mapRegisterFile, mapRegisterBufferSize);
  2662. //
  2663. // This is all we can set right now. We set the MapRegisterBaseFromHal
  2664. // in AllocateAdapterChannel and the MappedBuffer in MapTransfer
  2665. //
  2666. mapRegisterFile->NumberOfMapRegisters = NumberOfMapRegisters;
  2667. mapRegisterMdl = IoAllocateMdl(
  2668. NULL,
  2669. NumberOfMapRegisters << PAGE_SHIFT,
  2670. FALSE,
  2671. FALSE,
  2672. NULL
  2673. );
  2674. if (! mapRegisterMdl) {
  2675. goto CleanupFailure;
  2676. }
  2677. if (ViSuperDebug) {
  2678. DbgPrint(" %p Allocated MDL\n",mapRegisterMdl);
  2679. }
  2680. registerFilePfnArray = MmGetMdlPfnArray(mapRegisterMdl);
  2681. tempMapRegister = &mapRegisterFile->MapRegisters[0];
  2682. for(NOP;
  2683. NumberOfMapRegisters;
  2684. NumberOfMapRegisters--, tempMapRegister++, registerFilePfnArray++ ) {
  2685. PHYSICAL_ADDRESS registerPhysical;
  2686. //
  2687. // I really want to use MmAllocatePagesForMdl, which would make my
  2688. // life much easier, but it can only be called at IRQL <= APC_LEVEL.
  2689. // So I have to double-map these pages -- i.e. allocate them from the
  2690. // Cache aligned non paged pool which will most likely give me
  2691. // consecutive pages in physical memory. Then I take those pages and
  2692. // build a custom Mdl with them. Then I map them with
  2693. // MmMapLockedPagesSpecifyCache
  2694. //
  2695. //
  2696. // Allocate the map register, its index will be the hint
  2697. //
  2698. tempMapRegister->MapRegisterStart = ViAllocateFromContiguousMemory(
  2699. AdapterInformation,
  2700. mapRegisterFile->NumberOfMapRegisters - NumberOfMapRegisters
  2701. );
  2702. if (tempMapRegister->MapRegisterStart) {
  2703. InterlockedIncrement((PLONG)&AdapterInformation->ContiguousMapRegisters);
  2704. } else {
  2705. tempMapRegister->MapRegisterStart = ExAllocatePoolWithTag(
  2706. NonPagedPoolCacheAligned,
  2707. 3 * PAGE_SIZE,
  2708. HAL_VERIFIER_POOL_TAG
  2709. );
  2710. if (tempMapRegister->MapRegisterStart) {
  2711. InterlockedIncrement((PLONG)&AdapterInformation->NonContiguousMapRegisters);
  2712. } else {
  2713. goto CleanupFailure;
  2714. }
  2715. }
  2716. //
  2717. // Fill the map register padding area
  2718. // We don't want to tag it because we
  2719. // don't know where the buffer is going
  2720. // to get mapped.
  2721. // This essentially just zeroes
  2722. // out the whole buffer.
  2723. //
  2724. ViInitializePadding(
  2725. tempMapRegister->MapRegisterStart,
  2726. 3 * PAGE_SIZE,
  2727. NULL,
  2728. 0
  2729. );
  2730. if (ViSuperDebug) {
  2731. DbgPrint(" %p Allocated Map Register (%x)\n",
  2732. tempMapRegister->MapRegisterStart,
  2733. mapRegisterFile->NumberOfMapRegisters - NumberOfMapRegisters);
  2734. }
  2735. //
  2736. // Add the middle page of the allocation to our register
  2737. // file mdl
  2738. //
  2739. registerPhysical = MmGetPhysicalAddress(
  2740. (PUCHAR) tempMapRegister->MapRegisterStart + PAGE_SIZE );
  2741. registerPfn = (PFN_NUMBER) (registerPhysical.QuadPart >> PAGE_SHIFT);
  2742. RtlCopyMemory(
  2743. (PVOID) registerFilePfnArray,
  2744. (PVOID) &registerPfn,
  2745. sizeof(PFN_NUMBER) ) ;
  2746. } // For each map register //
  2747. //
  2748. // Now we have a mdl with all of our map registers physical pages entered
  2749. // in, we have to map this into virtual address space.
  2750. //
  2751. mapRegisterMdl->MdlFlags |= MDL_PAGES_LOCKED;
  2752. mapRegisterFile->MapRegisterBuffer = MmMapLockedPagesSpecifyCache (
  2753. mapRegisterMdl,
  2754. KernelMode,
  2755. MmCached,
  2756. NULL,
  2757. FALSE,
  2758. NormalPagePriority
  2759. );
  2760. if (! mapRegisterFile->MapRegisterBuffer) {
  2761. goto CleanupFailure;
  2762. }
  2763. mapRegisterFile->MapRegisterMdl = mapRegisterMdl;
  2764. //
  2765. // Since we are going to be mixing our map register files with system
  2766. // MapRegisterBase's we want to be able to make sure that it's really
  2767. // ours.
  2768. //
  2769. SIGN_MAP_REGISTER_FILE(mapRegisterFile);
  2770. KeInitializeSpinLock(&mapRegisterFile->AllocationLock);
  2771. VF_ADD_TO_LOCKED_LIST(
  2772. &AdapterInformation->MapRegisterFiles,
  2773. mapRegisterFile );
  2774. return mapRegisterFile;
  2775. CleanupFailure:
  2776. //
  2777. // Its all or nothing ... if we can't allocate the map register buffer,
  2778. // kill all of the memory that we've allocated and get out
  2779. //
  2780. #if DBG
  2781. DbgPrint("Halverifier: Failed to allocate double buffered dma registers\n");
  2782. #endif
  2783. tempMapRegister = &mapRegisterFile->MapRegisters[0];
  2784. for (NumberOfMapRegisters = mapRegisterFile->NumberOfMapRegisters;
  2785. NumberOfMapRegisters && tempMapRegister->MapRegisterStart;
  2786. NumberOfMapRegisters--, tempMapRegister++) {
  2787. if (!ViFreeToContiguousMemory(AdapterInformation,
  2788. tempMapRegister->MapRegisterStart,
  2789. mapRegisterFile->NumberOfMapRegisters - NumberOfMapRegisters)) {
  2790. //
  2791. // Could not find the address in the contiguous buffers pool
  2792. // it must be from non-paged pool.
  2793. //
  2794. ExFreePool(tempMapRegister->MapRegisterStart);
  2795. }
  2796. }
  2797. if (mapRegisterMdl) {
  2798. IoFreeMdl(mapRegisterMdl);
  2799. }
  2800. ExFreePool(mapRegisterFile);
  2801. return NULL;
  2802. } // ViAllocateMapRegisterFile//
  2803. LOGICAL
  2804. ViFreeMapRegisterFile(
  2805. IN PADAPTER_INFORMATION AdapterInformation,
  2806. IN PMAP_REGISTER_FILE MapRegisterFile
  2807. )
  2808. /*++
  2809. Routine Description:
  2810. Get rid of the map registers.
  2811. Arguments:
  2812. AdapterInformation -- contains information about the adapter we're using
  2813. MapRegisterFile -- what to free.
  2814. NumberOfMapRegisters -- We don't need this except to check that its the
  2815. same as the map registers were allocated. Only check this when doing
  2816. packet dma not scatter gather.
  2817. Return Value:
  2818. TRUE -- MapRegisterFile is really a MapRegisterFile.
  2819. FALSE -- MapRegisterFile wasn't really a MapRegisterFile.
  2820. --*/
  2821. {
  2822. PMAP_REGISTER tempMapRegister;
  2823. ULONG mapRegisterNumber;
  2824. if (! VALIDATE_MAP_REGISTER_FILE_SIGNATURE(MapRegisterFile)) {
  2825. //
  2826. // This could be a real MapRegisterBase that the hal returned
  2827. // But it's not one of ours.
  2828. //
  2829. return FALSE;
  2830. }
  2831. VF_REMOVE_FROM_LOCKED_LIST(&AdapterInformation->MapRegisterFiles,
  2832. MapRegisterFile );
  2833. //
  2834. // Clear the signature from memory so we don't find it after it's freed
  2835. // and think that it's real.
  2836. //
  2837. MapRegisterFile->Signature = 0;
  2838. MmUnmapLockedPages(
  2839. MapRegisterFile->MapRegisterBuffer,
  2840. MapRegisterFile->MapRegisterMdl );
  2841. tempMapRegister = &MapRegisterFile->MapRegisters[0];
  2842. for ( mapRegisterNumber = 0 ;
  2843. mapRegisterNumber < MapRegisterFile->NumberOfMapRegisters;
  2844. mapRegisterNumber++, tempMapRegister++ ) {
  2845. ASSERT(tempMapRegister->MapRegisterStart);
  2846. if(ViSuperDebug) {
  2847. DbgPrint(" %p Freeing Map Register (%x)\n",
  2848. tempMapRegister->MapRegisterStart,
  2849. mapRegisterNumber);
  2850. }
  2851. //
  2852. // Make sure that the driver or hw hasn't done anything funny in
  2853. // and around the area of the map register
  2854. //
  2855. if (tempMapRegister->MappedToSa) {
  2856. //
  2857. /// Map register is still mapped ...there better
  2858. // not be any data in the buffer
  2859. //
  2860. PUCHAR mappedSa =
  2861. (PUCHAR) tempMapRegister->MapRegisterStart +
  2862. PAGE_SIZE + BYTE_OFFSET(tempMapRegister->MappedToSa);
  2863. //
  2864. // Assert only for a transfer from the device,
  2865. // in this case the hardware transferred some data,
  2866. // but we didn't flush it.
  2867. //
  2868. if (tempMapRegister->Flags & MAP_REGISTER_READ) {
  2869. VF_ASSERT(
  2870. ! ViHasBufferBeenTouched(
  2871. mappedSa,
  2872. tempMapRegister->BytesMapped,
  2873. MAP_REGISTER_FILL_CHAR
  2874. ),
  2875. HV_DID_NOT_FLUSH_ADAPTER_BUFFERS,
  2876. ("Freeing map register (%p) that has data and was not flushed."
  2877. " This means that there was a data loss.",
  2878. tempMapRegister->MappedToSa)
  2879. );
  2880. }
  2881. //
  2882. // Make sure that the outside looks good
  2883. //
  2884. ViCheckPadding(
  2885. tempMapRegister->MapRegisterStart,
  2886. 3* PAGE_SIZE,
  2887. mappedSa,
  2888. tempMapRegister->BytesMapped
  2889. );
  2890. }
  2891. else
  2892. {
  2893. ViCheckPadding(tempMapRegister->MapRegisterStart, 3 * PAGE_SIZE, NULL, 0);
  2894. }
  2895. tempMapRegister->Flags = 0;
  2896. //
  2897. // Bye bye map register ...
  2898. //
  2899. if (!ViFreeToContiguousMemory(AdapterInformation,
  2900. tempMapRegister->MapRegisterStart,
  2901. mapRegisterNumber)) {
  2902. //
  2903. // Could not find the address in the contiguous buffers pool
  2904. // it must be from non-paged pool.
  2905. //
  2906. ExFreePool(tempMapRegister->MapRegisterStart);
  2907. }
  2908. }
  2909. if(ViSuperDebug)
  2910. {
  2911. DbgPrint(" %p Freeing MDL\n",MapRegisterFile->MapRegisterMdl);
  2912. }
  2913. IoFreeMdl(MapRegisterFile->MapRegisterMdl);
  2914. //
  2915. // N.B. -- we don't free the MapRegisterBuffer --- because all of its
  2916. // memory was just another way of looking at the MapRegisters
  2917. //
  2918. RtlZeroMemory(MapRegisterFile, sizeof(MapRegisterFile));
  2919. if(ViSuperDebug) {
  2920. DbgPrint("%p Freeing Map Register File\n",MapRegisterFile);
  2921. }
  2922. ExFreePool(MapRegisterFile);
  2923. return TRUE;
  2924. } // ViFreeMapRegisterFile //
  2925. ULONG
  2926. ViMapDoubleBuffer(
  2927. IN PMAP_REGISTER_FILE MapRegisterFile,
  2928. IN PMDL Mdl,
  2929. IN PVOID CurrentVa,
  2930. IN ULONG Length,
  2931. IN BOOLEAN WriteToDevice
  2932. )
  2933. /*++
  2934. Routine Description:
  2935. This and ViFlushDoubleBuffer take care of double buffering to and from
  2936. our map register files. Why do we do this? So that we can catch drivers
  2937. that a. don't flush adapter buffers, or b. make the hardware overrun
  2938. its allocation.
  2939. Arguments:
  2940. MapRegisterFile-- this is our map register file containing allocated
  2941. space for our double buffering.
  2942. Mdl -- the mdl to map.
  2943. CurrentVa -- in: index into the mdl to map.
  2944. Length -- how much to map. Note we don't have to map it all unless
  2945. ContiguousMap has been specified in the map register file.
  2946. WriteToDevice -- TRUE we have to double buffer since we are setting up a
  2947. write. if its false, we don't have to do much because it doesn't
  2948. matter whats in the buffer before it gets read.
  2949. Return Value:
  2950. Number of bytes mapped. If 0, we don't touch the mdl or current va.
  2951. --*/
  2952. {
  2953. PUCHAR mapRegisterCurrentSa;
  2954. PUCHAR driverCurrentSa;
  2955. ULONG mapRegisterNumber;
  2956. PMDL currentMdl;
  2957. ULONG bytesLeft;
  2958. ULONG currentTransferLength;
  2959. //
  2960. // Assert that the length cannot be 0
  2961. //
  2962. if (Length == 0) {
  2963. VF_ASSERT(Length != 0,
  2964. HV_MAP_ZERO_LENGTH_BUFFER,
  2965. ("Driver is attempting to map a 0-length transfer"));
  2966. return Length;
  2967. }
  2968. //
  2969. // Right off the bat -- if we are being called by getscattergather, we
  2970. // are going to need to map the whole thing. Otherwise just map as much
  2971. // as is contiguous. The hal had already done these calculations, so I
  2972. // just copied the code to determine the contiguous length of transfer.
  2973. //
  2974. if ( ! MapRegisterFile->ScatterGather) {
  2975. Length = MIN(Length, PAGE_SIZE- BYTE_OFFSET(CurrentVa));
  2976. }
  2977. //
  2978. // Now we know how many bytes we are going to transfer.
  2979. //
  2980. if ((PUCHAR) CurrentVa < (PUCHAR) MmGetMdlVirtualAddress(Mdl)) {
  2981. //
  2982. // System address before the beginning of the first MDL. This is bad.
  2983. //
  2984. VF_ASSERT((PUCHAR) CurrentVa >= (PUCHAR) MmGetMdlVirtualAddress(Mdl),
  2985. HV_BAD_MDL,
  2986. ("Virtual address %p is before the first MDL %p",CurrentVa, Mdl));
  2987. return FALSE;
  2988. }
  2989. if ((ULONG)((PUCHAR) CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(Mdl)) >= MmGetMdlByteCount(Mdl)) {
  2990. //
  2991. // System address is after the end of the first MDL. This is also bad.
  2992. //
  2993. VF_ASSERT((ULONG)((PUCHAR) CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(Mdl)) < MmGetMdlByteCount(Mdl),
  2994. HV_BAD_MDL,
  2995. ("Virtual address %p is after the first MDL %p",CurrentVa, Mdl));
  2996. return FALSE;
  2997. }
  2998. //
  2999. // Get a pointer into the Mdl that we can actually use
  3000. // N.B. this may bugcheck if the mdl isn't mapped but that's a bug
  3001. // in the first place.
  3002. //
  3003. driverCurrentSa = (PUCHAR) MmGetSystemAddressForMdl(Mdl) +
  3004. ((PUCHAR) CurrentVa -
  3005. (PUCHAR) MmGetMdlVirtualAddress(Mdl)) ;
  3006. //
  3007. // Allocate contiguous map registers from our map register file
  3008. //
  3009. if ( ! ViAllocateMapRegistersFromFile(
  3010. MapRegisterFile,
  3011. driverCurrentSa,
  3012. Length,
  3013. WriteToDevice,
  3014. &mapRegisterNumber
  3015. ) ) {
  3016. return FALSE;
  3017. }
  3018. //
  3019. // Get a pointer to the base of the map registers for
  3020. // double buffering.
  3021. //
  3022. mapRegisterCurrentSa =
  3023. MAP_REGISTER_SYSTEM_ADDRESS(
  3024. MapRegisterFile,
  3025. driverCurrentSa,
  3026. mapRegisterNumber );
  3027. //
  3028. // Note on a read, we don't have to double buffer at this end
  3029. //
  3030. if (WriteToDevice) {
  3031. //
  3032. // Copy chained mdls to a single buffer at mapRegisterCurrentSa
  3033. //
  3034. currentMdl = Mdl;
  3035. bytesLeft = Length;
  3036. while(bytesLeft) {
  3037. if (NULL == currentMdl) {
  3038. //
  3039. // 12/21/2000 - This should never happen
  3040. //
  3041. ASSERT(NULL != currentMdl);
  3042. return FALSE;
  3043. }
  3044. if (currentMdl->Next == NULL && bytesLeft > MmGetMdlByteCount(currentMdl)) {
  3045. //
  3046. // 12/21/2000 - There are some rare cases where the buffer described
  3047. // in the MDL is less than the transfer Length. This happens for instance
  3048. // when the file system rounds up the file size to a multiple of sector
  3049. // size but MM uses the exact file size in the MDL. The HAL compensates for
  3050. // this.
  3051. // If this is the case, use the size based on Length (bytesLeft)
  3052. // instead of the size in the MDL (ByteCount). Also check that
  3053. // this extra does not cross a page boundary.
  3054. //
  3055. if ((Length - 1) >> PAGE_SHIFT != (Length - (bytesLeft - MmGetMdlByteCount(currentMdl))) >> PAGE_SHIFT) {
  3056. VF_ASSERT((Length - 1) >> PAGE_SHIFT == (Length - (bytesLeft - MmGetMdlByteCount(currentMdl))) >> PAGE_SHIFT,
  3057. HV_BAD_MDL,
  3058. ("Extra transfer length crosses a page boundary: Mdl %p, Length %x", Mdl, Length));
  3059. return FALSE;
  3060. }
  3061. currentTransferLength = bytesLeft;
  3062. } else {
  3063. currentTransferLength = MIN(bytesLeft, MmGetMdlByteCount(currentMdl));
  3064. }
  3065. if (ViSuperDebug) {
  3066. DbgPrint("Dbl buffer: %x bytes, %p src, %p dest\n",
  3067. currentTransferLength,
  3068. driverCurrentSa,
  3069. mapRegisterCurrentSa);
  3070. }
  3071. //
  3072. // Since we are writing to the device, we must copy from the driver's
  3073. // buffer to our buffer.
  3074. //
  3075. RtlCopyMemory(
  3076. mapRegisterCurrentSa ,
  3077. driverCurrentSa,
  3078. currentTransferLength);
  3079. mapRegisterCurrentSa+= currentTransferLength;
  3080. currentMdl = currentMdl->Next;
  3081. //
  3082. // The system address for other mdls must start at the
  3083. // beginning of the MDL.
  3084. //
  3085. if (currentMdl) {
  3086. driverCurrentSa = (PUCHAR) MmGetSystemAddressForMdl(currentMdl);
  3087. }
  3088. bytesLeft -= currentTransferLength;
  3089. } // for each chained mdl //
  3090. } // if (WriteToDevice) //
  3091. //
  3092. // The buffer should have been filled in with a known
  3093. // pattern when we tagged it
  3094. //
  3095. //
  3096. // Flush the buffers for our MDL
  3097. //
  3098. if (MapRegisterFile->MapRegisterMdl) {
  3099. KeFlushIoBuffers(MapRegisterFile->MapRegisterMdl, !WriteToDevice, TRUE);
  3100. }
  3101. return Length;
  3102. } // ViMapDoubleBuffer //
  3103. LOGICAL
  3104. ViFlushDoubleBuffer(
  3105. IN PMAP_REGISTER_FILE MapRegisterFile,
  3106. IN PMDL Mdl,
  3107. IN PVOID CurrentVa,
  3108. IN ULONG Length,
  3109. IN BOOLEAN WriteToDevice
  3110. )
  3111. /*++
  3112. Routine Description:
  3113. This and ViMapDoubleBuffer take care of double buffering to and from
  3114. our map register files. Why do we do this? So that we can catch drivers
  3115. that a. don't flush adapter buffers, or b. make the hardware overrun
  3116. its allocation.
  3117. Arguments:
  3118. MapRegisterFile-- this is our map register file containing allocated
  3119. space for our double buffering.
  3120. Mdl -- the mdl to flush
  3121. CurrentVa -- index into the mdl to map
  3122. Length -- how much to flush.
  3123. WriteToDevice -- FALSE we have to double buffer since we are setting up a
  3124. read. if its TRUE, we don't have to do much because it doesn't matter
  3125. whats in the buffer after it gets written.
  3126. Return Value:
  3127. TRUE -- we succeeded in the mapping
  3128. FALSE -- we couldn't do it.
  3129. --*/
  3130. {
  3131. PUCHAR mapRegisterCurrentSa;
  3132. PUCHAR driverCurrentSa;
  3133. ULONG mapRegisterNumber;
  3134. ULONG bytesLeftInMdl;
  3135. //
  3136. // Get a pointer into the Mdl that we can actually use
  3137. // N.B. this may bugcheck if the mdl isn't mapped but that's a bug
  3138. // in the first place.
  3139. //
  3140. driverCurrentSa = (PUCHAR) MmGetSystemAddressForMdl(Mdl) +
  3141. ((PUCHAR) CurrentVa -
  3142. (PUCHAR) MmGetMdlVirtualAddress(Mdl)) ;
  3143. //
  3144. // Find the map register number of the start of the flush
  3145. // so that we can find out where to double buffer from
  3146. //
  3147. if (! ViFindMappedRegisterInFile(
  3148. MapRegisterFile,
  3149. driverCurrentSa,
  3150. &mapRegisterNumber) ) {
  3151. VF_ASSERT(
  3152. 0,
  3153. HV_FLUSH_EMPTY_BUFFERS,
  3154. ("Cannot flush buffers that aren't mapped (Addr %p)",
  3155. driverCurrentSa )
  3156. );
  3157. return FALSE;
  3158. }
  3159. mapRegisterCurrentSa =
  3160. MAP_REGISTER_SYSTEM_ADDRESS(
  3161. MapRegisterFile,
  3162. driverCurrentSa,
  3163. mapRegisterNumber );
  3164. //
  3165. // Check to make sure that the flush is being done with a reasonable
  3166. // length.(mdl byte count - mdl offset)
  3167. //
  3168. bytesLeftInMdl = MmGetMdlByteCount(MapRegisterFile->MapRegisterMdl) -
  3169. (ULONG) ( (PUCHAR) mapRegisterCurrentSa -
  3170. (PUCHAR) MmGetSystemAddressForMdl(MapRegisterFile->MapRegisterMdl) ) ;
  3171. VF_ASSERT(
  3172. Length <= bytesLeftInMdl,
  3173. HV_MISCELLANEOUS_ERROR,
  3174. ("FLUSH: Can only flush %x bytes to end of map register file (%x attempted)",
  3175. bytesLeftInMdl, Length)
  3176. );
  3177. if (Length > bytesLeftInMdl) {
  3178. //
  3179. // Salvage the situation by truncating the flush
  3180. //
  3181. Length = bytesLeftInMdl;
  3182. }
  3183. //
  3184. // Note on a write, we don't have to double buffer at this end
  3185. //
  3186. if (!WriteToDevice) {
  3187. //
  3188. // Since certain scsi miniports write to the mapped buffer and expect
  3189. // that data to be there when we flush, we have to check for this
  3190. // case ... and if it happens DON'T double buffer.
  3191. //
  3192. RTL_BITMAP bitmap;
  3193. bitmap.SizeOfBitMap = Length << 3;
  3194. bitmap.Buffer = (PULONG)mapRegisterCurrentSa;
  3195. //
  3196. // Only really flush the double buffer if the hardware has
  3197. // written to it.
  3198. //
  3199. if ( ViHasBufferBeenTouched(
  3200. mapRegisterCurrentSa,
  3201. Length,
  3202. MAP_REGISTER_FILL_CHAR )
  3203. ) {
  3204. //
  3205. // The hardware must have written some thing here ...
  3206. // so flush it.
  3207. //
  3208. //
  3209. // Since we are reading from the device, we must copy from our buffer to
  3210. // the driver's buffer .
  3211. //
  3212. if (ViSuperDebug) {
  3213. DbgPrint("Flush buffer: %x bytes, %p src, %p dest\n",Length, mapRegisterCurrentSa, driverCurrentSa );
  3214. }
  3215. RtlCopyMemory(
  3216. driverCurrentSa,
  3217. mapRegisterCurrentSa ,
  3218. Length );
  3219. }
  3220. else { // Map register buffer has not been changed //
  3221. if (Length) {
  3222. //
  3223. // If Length is 0, it's expected we have nothing to transfer...
  3224. //
  3225. VF_ASSERT(
  3226. FALSE,
  3227. HV_MAP_FLUSH_NO_TRANSFER,
  3228. ("Mapped and flushed transfer but hardware did not touch buffer %p", driverCurrentSa)
  3229. );
  3230. }
  3231. } // Map register buffer has not been changed //
  3232. } // if (!WriteToDevice) //
  3233. //
  3234. // Free map registers to our map register file
  3235. //
  3236. if (! ViFreeMapRegistersToFile(
  3237. MapRegisterFile,
  3238. driverCurrentSa,
  3239. Length) ) {
  3240. DbgPrint("Flushing too many map registers\n");
  3241. }
  3242. return TRUE;
  3243. } // ViFlushDoubleBuffer //
  3244. LOGICAL
  3245. ViAllocateMapRegistersFromFile(
  3246. IN PMAP_REGISTER_FILE MapRegisterFile,
  3247. IN PVOID CurrentSa,
  3248. IN ULONG Length,
  3249. IN BOOLEAN WriteToDevice,
  3250. OUT PULONG MapRegisterNumber
  3251. )
  3252. /*++
  3253. Routine Description:
  3254. We specify that certain map registers are in use and decide how long the
  3255. transfer should be based on the available map registers. For packet dma,
  3256. we are only going to map one page maximum. For scatter gather, on the
  3257. other hand, we have to map the whole thing.
  3258. Arguments:
  3259. MapRegisterFile -- the structure containing the map registers to allocate
  3260. CurrentSa -- page aligned address of the buffer to map
  3261. Length -- how many bytes the transfer is going to be. We only use
  3262. this to turn it into a number of pages.
  3263. WriteToDevice - the direction of the transfer
  3264. MapRegisterNumber -- returns the index into the map register file of the
  3265. start of the allocation.
  3266. Return Value:
  3267. TRUE -- succeeded
  3268. FALSE -- not.
  3269. --*/
  3270. {
  3271. KIRQL OldIrql;
  3272. ULONG mapRegistersNeeded;
  3273. ULONG mapRegisterNumber;
  3274. PMAP_REGISTER mapRegister;
  3275. ULONG numberOfContiguousMapRegisters;
  3276. mapRegistersNeeded = ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentSa, Length);
  3277. //
  3278. // find n available contiguous map registers
  3279. //
  3280. mapRegister = &MapRegisterFile->MapRegisters[0];
  3281. mapRegisterNumber = 0;
  3282. numberOfContiguousMapRegisters = 0;
  3283. //
  3284. // Must lock the list so that other processors don't access it while
  3285. // we're trying to.
  3286. //
  3287. KeAcquireSpinLock(&MapRegisterFile->AllocationLock, &OldIrql);
  3288. //
  3289. // Make sure that this address isn't already mapped
  3290. //
  3291. if (MapRegisterFile->NumberOfRegistersMapped) {
  3292. PUCHAR windowStart = CurrentSa;
  3293. PUCHAR windowEnd = windowStart + Length;
  3294. PMAP_REGISTER currentReg;
  3295. PMAP_REGISTER lastReg;
  3296. currentReg = &MapRegisterFile->MapRegisters[0];
  3297. lastReg = currentReg + MapRegisterFile->NumberOfMapRegisters;
  3298. while(currentReg < lastReg) {
  3299. if (currentReg->MappedToSa &&
  3300. (PUCHAR) currentReg->MappedToSa >= windowStart &&
  3301. (PUCHAR) currentReg->MappedToSa < windowEnd ) {
  3302. //
  3303. // This is bad. We're trying to map an address
  3304. // that is already mapped
  3305. //
  3306. VF_ASSERT(
  3307. FALSE,
  3308. HV_DOUBLE_MAP_REGISTER,
  3309. ("Driver is trying to map an address range(%p-%p) that is already mapped"
  3310. " at %p",
  3311. windowStart,
  3312. windowEnd,
  3313. currentReg->MappedToSa
  3314. ));
  3315. }
  3316. currentReg++;
  3317. } // for each map register //
  3318. } // Check to see if address is already mapped //
  3319. //
  3320. // Find contiguous free map registers
  3321. //
  3322. while(numberOfContiguousMapRegisters < mapRegistersNeeded) {
  3323. if (mapRegisterNumber == MapRegisterFile->NumberOfMapRegisters) {
  3324. //
  3325. // We've gotten to the end without finding enough map registers.
  3326. // thats bad. However I can picture getting false positives here
  3327. // if the map register file is large and gets fragmented.
  3328. // This is a pretty pathological case and I doubt it would ever
  3329. // happen.
  3330. //
  3331. VF_ASSERT(
  3332. FALSE,
  3333. HV_MISCELLANEOUS_ERROR,
  3334. ("Map registers needed: %x available: %x",
  3335. mapRegistersNeeded,
  3336. numberOfContiguousMapRegisters)
  3337. );
  3338. KeReleaseSpinLock(&MapRegisterFile->AllocationLock, OldIrql);
  3339. return FALSE;
  3340. }
  3341. if (mapRegister->MappedToSa) {
  3342. //
  3343. // This one's being used...must reset our contiguous count...
  3344. //
  3345. numberOfContiguousMapRegisters=0;
  3346. }
  3347. else {
  3348. //
  3349. // A free map register
  3350. //
  3351. numberOfContiguousMapRegisters++;
  3352. }
  3353. mapRegister++;
  3354. mapRegisterNumber++;
  3355. } // Find n contiguous map registers //
  3356. //
  3357. // got 'em ... we're now at the end of our area to be allocated
  3358. // go back to the beginning.
  3359. //
  3360. mapRegister -= mapRegistersNeeded;
  3361. mapRegisterNumber -= mapRegistersNeeded;
  3362. //
  3363. // Save the map register index number to return
  3364. //
  3365. *MapRegisterNumber = mapRegisterNumber;
  3366. //
  3367. // Go through and mark the map registers as used...
  3368. //
  3369. while(mapRegistersNeeded--) {
  3370. mapRegister->MappedToSa = CurrentSa;
  3371. mapRegister->BytesMapped = MIN( PAGE_SIZE - BYTE_OFFSET(CurrentSa), Length );
  3372. mapRegister->Flags = WriteToDevice ? MAP_REGISTER_WRITE : MAP_REGISTER_READ;
  3373. InterlockedIncrement((PLONG)(&MapRegisterFile->NumberOfRegistersMapped));
  3374. //
  3375. // Write some known quantities into the buffer so that we know
  3376. // if the device overwrites
  3377. //
  3378. ViTagBuffer(
  3379. (PUCHAR) mapRegister->MapRegisterStart + PAGE_SIZE + BYTE_OFFSET(CurrentSa),
  3380. mapRegister->BytesMapped,
  3381. TAG_BUFFER_START | TAG_BUFFER_END
  3382. );
  3383. CurrentSa = PAGE_ALIGN( (PUCHAR) CurrentSa + PAGE_SIZE);
  3384. Length -= mapRegister->BytesMapped;
  3385. mapRegister++;
  3386. }
  3387. KeReleaseSpinLock(&MapRegisterFile->AllocationLock, OldIrql);
  3388. return TRUE;
  3389. } // ViAllocateMapRegistersFromFile //
  3390. PMAP_REGISTER
  3391. ViFindMappedRegisterInFile(
  3392. IN PMAP_REGISTER_FILE MapRegisterFile,
  3393. IN PVOID CurrentSa,
  3394. OUT PULONG MapRegisterNumber OPTIONAL
  3395. )
  3396. /*++
  3397. Routine Description:
  3398. From a system address, find out which map register in a map register file
  3399. is mapped to that address.
  3400. Arguments:
  3401. MapRegisterFile -- the structure containing the map registers.
  3402. CurrentSa -- system address of where we are looking for the mapped map
  3403. register.
  3404. MapRegisterNumber -- gets the offset into the map register file.
  3405. Return Value:
  3406. Returns a pointer to the map register if we found it or NULL if we didn't
  3407. --*/
  3408. {
  3409. ULONG tempMapRegisterNumber;
  3410. PMAP_REGISTER mapRegister;
  3411. tempMapRegisterNumber = 0;
  3412. mapRegister = &MapRegisterFile->MapRegisters[0];
  3413. while(tempMapRegisterNumber < MapRegisterFile->NumberOfMapRegisters) {
  3414. if (CurrentSa == mapRegister->MappedToSa) {
  3415. if (MapRegisterNumber) {
  3416. //
  3417. // return the optional map register index
  3418. //
  3419. *MapRegisterNumber = tempMapRegisterNumber;
  3420. }
  3421. return mapRegister;
  3422. }
  3423. mapRegister++;
  3424. tempMapRegisterNumber++;
  3425. }
  3426. return NULL;
  3427. } // ViFindMappedRegisterInFile //
  3428. LOGICAL
  3429. ViFreeMapRegistersToFile(
  3430. IN PMAP_REGISTER_FILE MapRegisterFile,
  3431. IN PVOID CurrentSa,
  3432. IN ULONG Length
  3433. )
  3434. /*++
  3435. Routine Description:
  3436. Set the map registers in our map register file back to not being mapped.
  3437. Arguments:
  3438. MapRegisterFile -- the structure containing the map registers to
  3439. allocate.
  3440. CurrentSa -- system address of where to start the transfer. We use this
  3441. to help set the transfer length.
  3442. Length -- how much to free -- this is non-negotiable.
  3443. NOTE -- while we're freeing map registers, we don't have to use the spinlock.
  3444. Why? Because we're just clearing flags. In the allocation case we need
  3445. it so that someone doesn't take our map registers before we get a
  3446. chance to claim them. But if someone frees out map registers before we
  3447. get a chance to, it won't make a difference. (that would be a bug in
  3448. the first place and we'd hit an assert).
  3449. Return Value:
  3450. TRUE -- succeeded in unmapping at least some of the map registers.
  3451. FALSE -- not.
  3452. --*/
  3453. {
  3454. PMAP_REGISTER mapRegister;
  3455. ULONG numberOfRegistersToUnmap;
  3456. if (Length) {
  3457. numberOfRegistersToUnmap = MIN (
  3458. ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentSa, Length),
  3459. MapRegisterFile->NumberOfRegistersMapped
  3460. );
  3461. } else {
  3462. //
  3463. // Zero length usually signals an error condition, it may
  3464. // be possible that the hardware still transferred something, so
  3465. // let's (arbitrarily) unmap one register
  3466. // (otherwise we may find some partly transferred
  3467. // data and assert that it was lost)
  3468. //
  3469. numberOfRegistersToUnmap = MIN(1, MapRegisterFile->NumberOfRegistersMapped);
  3470. }
  3471. //
  3472. // Find the first map register
  3473. //
  3474. mapRegister = ViFindMappedRegisterInFile(
  3475. MapRegisterFile,
  3476. CurrentSa,
  3477. NULL);
  3478. if (! mapRegister ) {
  3479. return FALSE;
  3480. }
  3481. //
  3482. // Because a driver can just say "flush" and doesn't necessarily have to
  3483. // have anything mapped -- and also wants to flush the whole thing at one
  3484. // time, we are going to try unmap each map register and not get
  3485. // bent out of shape if we can't do it.
  3486. //
  3487. // Remember all map register allocations have to be contiguous
  3488. // (i.e a if a 2 page buffer gets mapped starting at map register 3
  3489. // the second page will be mapped to map register 4)
  3490. //
  3491. //
  3492. // NOTE -- the order of these does matter!!!
  3493. //
  3494. while(numberOfRegistersToUnmap && mapRegister->MappedToSa ) {
  3495. //
  3496. // Check the bits that we scribbled right before and after the map register
  3497. // make sure nobody's scribbled over them.
  3498. //
  3499. // This also removes the tag and zeroes out the whole map register buffer.
  3500. // Why ? Because next time this map register gets mapped, it may get mapped
  3501. // at a different offset so the tag will have to go in a different place.
  3502. // We've got to clear out the buffer.
  3503. //
  3504. // This way we can tell if someone is using this buffer after the flush
  3505. //
  3506. ViCheckTag(
  3507. (PUCHAR) mapRegister->MapRegisterStart +
  3508. PAGE_SIZE + BYTE_OFFSET(mapRegister->MappedToSa),
  3509. mapRegister->BytesMapped,
  3510. TRUE,
  3511. TAG_BUFFER_START | TAG_BUFFER_END
  3512. );
  3513. //
  3514. // Clear the RW flags
  3515. //
  3516. mapRegister->Flags &= ~MAP_REGISTER_RW_MASK;
  3517. //
  3518. // (Dirty debug trick) : save the MappedToSa field so we
  3519. // can tell who has flushed it before, if needed.
  3520. //
  3521. mapRegister->Flags = PtrToUlong(mapRegister->MappedToSa);
  3522. //
  3523. // Unmap the register
  3524. //
  3525. mapRegister->MappedToSa = NULL;
  3526. mapRegister->BytesMapped = 0;
  3527. //
  3528. // Clear the RW flags
  3529. //
  3530. InterlockedDecrement((PLONG)(&MapRegisterFile->NumberOfRegistersMapped));
  3531. //
  3532. // Go on to the next map register
  3533. //
  3534. mapRegister++;
  3535. numberOfRegistersToUnmap--;
  3536. }
  3537. return TRUE;
  3538. } // ViFreeMapRegistersToFile //
  3539. THUNKED_API
  3540. VOID
  3541. VfHalDeleteDevice(
  3542. IN PDEVICE_OBJECT DeviceObject
  3543. )
  3544. /*++
  3545. Routine Description:
  3546. Hooks the IoDeleteDevice routine -- we want to make sure that all
  3547. adapters are put away before calling this routine -- otherwise we
  3548. issue a big fat bugcheck to teach naughty drivers a lesson.
  3549. We have a list of all of the devices that we've hooked, and so here we
  3550. just make sure that we can't find this device object on the hooked list.
  3551. We are not calling IoDeleteDevice, since we're being called
  3552. from an I/O Verifier path and I/O Verifier will call IoDeleteDevice
  3553. subsequently.
  3554. Arguments:
  3555. DeviceObject -- Device object that is being deleted.
  3556. Return Value:
  3557. NTSTATUS code.
  3558. --*/
  3559. {
  3560. PADAPTER_INFORMATION adapterInformation;
  3561. PDEVICE_OBJECT pdo;
  3562. pdo = VfGetPDO(DeviceObject);
  3563. ASSERT(pdo);
  3564. if (pdo == DeviceObject) {
  3565. //
  3566. // The PDO goes away, do the clean up.
  3567. // Find adapter info for this device.
  3568. //
  3569. adapterInformation = VF_FIND_DEVICE_INFORMATION(DeviceObject);
  3570. ///
  3571. // A device may have more than one adapter. Release each of them.
  3572. ///
  3573. while (adapterInformation) {
  3574. ViReleaseDmaAdapter(adapterInformation);
  3575. adapterInformation = VF_FIND_DEVICE_INFORMATION(DeviceObject);
  3576. }
  3577. } else {
  3578. //
  3579. // A device in the stack is removed. Since we cannot be sure that the
  3580. // device object that is verified is DeviceObject (it may be a filter on
  3581. // top of it), we need to just mark the adapter for removal
  3582. //
  3583. VF_MARK_FOR_DEFERRED_REMOVE(pdo);
  3584. }
  3585. return;
  3586. } // VfHalDeletedevice //
  3587. LOGICAL
  3588. VfInjectDmaFailure (
  3589. VOID
  3590. )
  3591. /*++
  3592. Routine Description:
  3593. This function determines whether a dma operation should be
  3594. deliberately failed.
  3595. Arguments:
  3596. None.
  3597. Return Value:
  3598. TRUE if the operation should be failed. FALSE otherwise.
  3599. Environment:
  3600. Kernel mode. DISPATCH_LEVEL or below.
  3601. --*/
  3602. {
  3603. LARGE_INTEGER currentTime;
  3604. if ( ViInjectDmaFailures == FALSE) {
  3605. return FALSE;
  3606. }
  3607. //
  3608. // Don't fail during the beginning of boot.
  3609. //
  3610. if (ViSufficientlyBootedForDmaFailure == FALSE) {
  3611. KeQuerySystemTime (&currentTime);
  3612. if ( currentTime.QuadPart > KeBootTime.QuadPart +
  3613. ViRequiredTimeSinceBoot.QuadPart ) {
  3614. ViSufficientlyBootedForDmaFailure = TRUE;
  3615. }
  3616. }
  3617. if (ViSufficientlyBootedForDmaFailure == TRUE) {
  3618. KeQueryTickCount(&currentTime);
  3619. if ((currentTime.LowPart & 0x1F) == 0) {
  3620. ViAllocationsFailedDeliberately += 1;
  3621. //
  3622. // Deliberately fail this request.
  3623. //
  3624. return TRUE;
  3625. }
  3626. }
  3627. return FALSE;
  3628. } // VfInjectDmaFailure //
  3629. VOID
  3630. VfScatterGatherCallback(
  3631. IN struct _DEVICE_OBJECT *DeviceObject,
  3632. IN struct _IRP *Irp,
  3633. IN PSCATTER_GATHER_LIST ScatterGather,
  3634. IN PVOID Context
  3635. )
  3636. /*++
  3637. Routine Description:
  3638. This function is the hooked callback for GetScatterGatherList.
  3639. Arguments:
  3640. DeviceObject -- passed through (not used).
  3641. Irp -- passed through (not used).
  3642. ScatterGather -- scatter gather list built by system.
  3643. Context -- This is really our wait block.
  3644. Return Value:
  3645. NONE.
  3646. Environment:
  3647. Kernel mode. DISPATCH_LEVEL.
  3648. --*/
  3649. {
  3650. PVF_WAIT_CONTEXT_BLOCK waitBlock = (PVF_WAIT_CONTEXT_BLOCK) Context;
  3651. PADAPTER_INFORMATION adapterInformation = waitBlock->AdapterInformation;
  3652. ADD_MAP_REGISTERS(adapterInformation, ScatterGather->NumberOfElements, TRUE);
  3653. //
  3654. // Save the scatter gather list so we can look it up when we put it away
  3655. //
  3656. waitBlock->ScatterGatherList = ScatterGather;
  3657. VF_ADD_TO_LOCKED_LIST(&adapterInformation->ScatterGatherLists, waitBlock);
  3658. ((PDRIVER_LIST_CONTROL) waitBlock->RealCallback)(DeviceObject,Irp, ScatterGather, waitBlock->RealContext);
  3659. } // VfScatterGatherCallback //
  3660. LOGICAL
  3661. ViSwap(IN OUT PVOID * MapRegisterBase,
  3662. IN OUT PMDL * Mdl,
  3663. IN OUT PVOID * CurrentVa
  3664. )
  3665. /*++
  3666. Routine Description:
  3667. Swaps things that we hook in doing dma -- I.e. we replace the
  3668. map register base with our map register file, we replace the mdl with
  3669. our own, and the current va with the virtual address that indexes our
  3670. mdl.
  3671. Arguments:
  3672. MapRegisterBase:
  3673. IN -- our map register file
  3674. OUT -- the map register base returned by the HAL.
  3675. Mdl:
  3676. IN -- the mdl the driver is using for dma
  3677. OUT -- the mdl that we are using for double buffered dma.
  3678. CurrentVa:
  3679. IN -- the address indexing the mdl that the driver is doing dma to/from
  3680. OUT -- the address indexing our mdl for double buffered dma.
  3681. Return Value:
  3682. TRUE -- we could find all of the stuff we wanted.
  3683. FALSE -- not.
  3684. --*/
  3685. {
  3686. PMAP_REGISTER_FILE mapRegisterFile = (PMAP_REGISTER_FILE) *MapRegisterBase;
  3687. ULONG mapRegisterNumber;
  3688. PUCHAR currentSa;
  3689. PUCHAR driverCurrentSa;
  3690. driverCurrentSa = (PUCHAR) MmGetSystemAddressForMdl(*Mdl) +
  3691. ((PUCHAR) *CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(*Mdl));
  3692. //
  3693. // Make sure that the VA is actually in the mdl they gave us
  3694. //
  3695. if (MmGetMdlByteCount(*Mdl)) {
  3696. VF_ASSERT(
  3697. MmGetMdlByteCount(*Mdl) > (ULONG_PTR) ((PUCHAR) *CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(*Mdl)),
  3698. HV_ADDRESS_NOT_IN_MDL,
  3699. ("Virtual address %p out of bounds of MDL %p", *CurrentVa, *Mdl)
  3700. );
  3701. }
  3702. if (!ViFindMappedRegisterInFile(mapRegisterFile, driverCurrentSa, &mapRegisterNumber)) {
  3703. return FALSE;
  3704. }
  3705. currentSa = MAP_REGISTER_SYSTEM_ADDRESS(mapRegisterFile, driverCurrentSa, mapRegisterNumber);
  3706. *Mdl = mapRegisterFile->MapRegisterMdl;
  3707. *CurrentVa = MAP_REGISTER_VIRTUAL_ADDRESS(mapRegisterFile, driverCurrentSa, mapRegisterNumber);
  3708. *MapRegisterBase = mapRegisterFile->MapRegisterBaseFromHal;
  3709. return TRUE;
  3710. } // ViSwap //
  3711. VOID
  3712. ViCheckAdapterBuffers(
  3713. IN PADAPTER_INFORMATION AdapterInformation
  3714. )
  3715. /*++
  3716. Routine Description:
  3717. Since common buffer dma isn't transactional, we have to have a way of
  3718. checking to make sure that the common buffer's guard pages don't get
  3719. scribbled on. This function will each common buffer owned by the adapter
  3720. Arguments:
  3721. Return Value:
  3722. NONE.
  3723. --*/
  3724. {
  3725. KIRQL oldIrql;
  3726. PHAL_VERIFIER_BUFFER verifierBuffer;
  3727. const SIZE_T tagSize = sizeof(ViDmaVerifierTag);
  3728. USHORT whereToCheck = 0;
  3729. //
  3730. // This is expensive so if either:
  3731. // we're not adding padding to common buffers,
  3732. // we're not checking the padding except when stuff is being destroyed,
  3733. // or this adapter doesn't have any common buffers, quit right here.
  3734. //
  3735. if (! ViProtectBuffers ||
  3736. VF_IS_LOCKED_LIST_EMPTY(&AdapterInformation->CommonBuffers) ) {
  3737. return;
  3738. }
  3739. VF_LOCK_LIST(&AdapterInformation->CommonBuffers, oldIrql);
  3740. //
  3741. // Make sure each darn common buffer's paddin' looks good
  3742. //
  3743. FOR_ALL_IN_LIST(
  3744. HAL_VERIFIER_BUFFER,
  3745. &AdapterInformation->CommonBuffers.ListEntry,
  3746. verifierBuffer ) {
  3747. SIZE_T startPadSize = (PUCHAR)verifierBuffer->AdvertisedStartAddress - (PUCHAR)verifierBuffer->RealStartAddress;
  3748. if (startPadSize>= tagSize) {
  3749. whereToCheck |= TAG_BUFFER_START;
  3750. }
  3751. if (startPadSize + verifierBuffer->AdvertisedLength + tagSize <= verifierBuffer->RealLength) {
  3752. whereToCheck |= TAG_BUFFER_END;
  3753. }
  3754. ViCheckTag(
  3755. verifierBuffer->AdvertisedStartAddress,
  3756. verifierBuffer->AdvertisedLength,
  3757. FALSE, // DO NOT REMOVE TAG //
  3758. whereToCheck
  3759. );
  3760. } // FOR each buffer in list //
  3761. VF_UNLOCK_LIST(&AdapterInformation->CommonBuffers, oldIrql);
  3762. } // ViCheckAdapterBuffers //
  3763. VOID
  3764. ViTagBuffer(
  3765. IN PVOID AdvertisedBuffer,
  3766. IN ULONG AdvertisedLength,
  3767. IN USHORT WhereToTag
  3768. )
  3769. /*++
  3770. Routine Description:
  3771. Write a known string to the area right before of a buffer
  3772. and right after one -- so if there is an overrun, we'll
  3773. catch it.
  3774. Also write a known pattern to initialize the innards of the buffer.
  3775. Arguments:
  3776. AdvertisedBuffer -- The beginning of the buffer that the driver can see.
  3777. AdvertisedLength -- How long the driver thinks that the buffer is.
  3778. WhereToTag -- Indicates whether to tag the beginning of the buffer,
  3779. the end or both.
  3780. Return Value:
  3781. NONE.
  3782. --*/
  3783. {
  3784. const SIZE_T tagSize = sizeof(ViDmaVerifierTag);
  3785. if (WhereToTag & TAG_BUFFER_START) {
  3786. RtlCopyMemory( (PUCHAR) AdvertisedBuffer - tagSize , ViDmaVerifierTag, tagSize);
  3787. }
  3788. if (WhereToTag & TAG_BUFFER_END) {
  3789. RtlCopyMemory( (PUCHAR) AdvertisedBuffer + AdvertisedLength, ViDmaVerifierTag, tagSize);
  3790. }
  3791. //
  3792. // Initialize the buffer
  3793. //
  3794. RtlFillMemory( AdvertisedBuffer, (SIZE_T) AdvertisedLength, MAP_REGISTER_FILL_CHAR);
  3795. } // ViTagBuffer //
  3796. VOID
  3797. ViCheckTag(
  3798. IN PVOID AdvertisedBuffer,
  3799. IN ULONG AdvertisedLength,
  3800. IN BOOLEAN RemoveTag,
  3801. IN USHORT WhereToCheck
  3802. )
  3803. /*++
  3804. Routine Description:
  3805. Make sure our tag -- the bits we scribbled right before and right after
  3806. an allocation -- is still there. And perhaps kill it if we've
  3807. been so advised.
  3808. Arguments:
  3809. AdvertisedBuffer -- The beginning of the buffer that the driver can see.
  3810. AdvertisedLength -- how long the driver thinks that the buffer is.
  3811. RemoveTag -- do we want to clear the tag & the buffer? Why would we
  3812. want to do this? for map registers, who may get mapped to a
  3813. different place, we need to keep the environment pristine.
  3814. Return Value:
  3815. NONE.
  3816. --*/
  3817. {
  3818. const SIZE_T tagSize = sizeof(ViDmaVerifierTag);
  3819. PVOID endOfBuffer = (PUCHAR) AdvertisedBuffer + AdvertisedLength;
  3820. PUCHAR startOfRemoval = (PUCHAR)AdvertisedBuffer;
  3821. SIZE_T lengthOfRemoval = AdvertisedLength;
  3822. if (WhereToCheck & TAG_BUFFER_START) {
  3823. VF_ASSERT(
  3824. RtlCompareMemory((PUCHAR) AdvertisedBuffer - tagSize , ViDmaVerifierTag, tagSize) == tagSize,
  3825. HV_BOUNDARY_OVERRUN,
  3826. ( "Area before %x byte allocation at %p has been modified",
  3827. AdvertisedLength,
  3828. AdvertisedBuffer )
  3829. );
  3830. startOfRemoval -= tagSize;
  3831. lengthOfRemoval += tagSize;
  3832. }
  3833. if (WhereToCheck & TAG_BUFFER_END) {
  3834. VF_ASSERT(
  3835. RtlCompareMemory(endOfBuffer, ViDmaVerifierTag, tagSize) == tagSize,
  3836. HV_BOUNDARY_OVERRUN,
  3837. ( "Area after %x byte allocation at %p has been modified",
  3838. AdvertisedLength,
  3839. AdvertisedBuffer
  3840. ));
  3841. lengthOfRemoval += tagSize;
  3842. }
  3843. if (RemoveTag) {
  3844. //
  3845. // If we're getting rid of the tags, get rid of the data in the buffer too.
  3846. //
  3847. RtlFillMemory(
  3848. startOfRemoval,
  3849. lengthOfRemoval,
  3850. PADDING_FILL_CHAR
  3851. );
  3852. }
  3853. } // ViCheckTag //
  3854. VOID
  3855. ViInitializePadding(
  3856. IN PVOID RealBufferStart,
  3857. IN ULONG RealBufferLength,
  3858. IN PVOID AdvertisedBufferStart, OPTIONAL
  3859. IN ULONG AdvertisedBufferLength OPTIONAL
  3860. )
  3861. /*++
  3862. Routine Description:
  3863. Set up padding with whatever we want to put into it.
  3864. N.B. The padding should be PADDING_FILL_CHAR except for the tags.
  3865. Arguments:
  3866. RealBufferStart -- the beginning of the padding.
  3867. RealBufferLength -- total length of allocation.
  3868. AdvertisedBufferStart -- The beginning of the buffer that the driver can see.
  3869. AdvertisedBufferLength -- how long the driver thinks that the buffer is.
  3870. If AdvertisedBuffer/AdvertisedLength aren't present (they must
  3871. both be yea or nay) we won't tag the buffer. We need this option
  3872. because when we allocate map registers we don't know
  3873. where the tags need to go.
  3874. Return Value:
  3875. NONE.
  3876. --*/
  3877. {
  3878. PUCHAR postPadStart;
  3879. USHORT whereToTag = 0;
  3880. const SIZE_T tagSize = sizeof(ViDmaVerifierTag);
  3881. if (!AdvertisedBufferLength) {
  3882. RtlFillMemory(RealBufferStart, RealBufferLength, PADDING_FILL_CHAR);
  3883. return;
  3884. }
  3885. //
  3886. // Fill out the pre-padding
  3887. //
  3888. RtlFillMemory(
  3889. RealBufferStart,
  3890. (PUCHAR) AdvertisedBufferStart - (PUCHAR) RealBufferStart,
  3891. PADDING_FILL_CHAR
  3892. );
  3893. //
  3894. // Fill out the post padding
  3895. //
  3896. postPadStart = (PUCHAR) AdvertisedBufferStart + AdvertisedBufferLength;
  3897. RtlFillMemory(
  3898. postPadStart,
  3899. RealBufferLength - (postPadStart - (PUCHAR) RealBufferStart),
  3900. PADDING_FILL_CHAR
  3901. );
  3902. if ((PUCHAR)RealBufferStart + tagSize <= (PUCHAR)AdvertisedBufferStart) {
  3903. whereToTag |= TAG_BUFFER_START;
  3904. }
  3905. if ((postPadStart - (PUCHAR) RealBufferStart) + tagSize <= RealBufferLength) {
  3906. whereToTag |= TAG_BUFFER_END;
  3907. }
  3908. //
  3909. // And write our little tag ...
  3910. //
  3911. ViTagBuffer(AdvertisedBufferStart, AdvertisedBufferLength, whereToTag);
  3912. } // ViInitializePadding //
  3913. VOID
  3914. ViCheckPadding(
  3915. IN PVOID RealBufferStart,
  3916. IN ULONG RealBufferLength,
  3917. IN PVOID AdvertisedBufferStart, OPTIONAL
  3918. IN ULONG AdvertisedBufferLength OPTIONAL
  3919. )
  3920. /*++
  3921. Routine Description:
  3922. Make sure that the guard pages etc haven't been touched -- more exhaustive than
  3923. just checking the tag -- checks each byte.
  3924. N.B. The padding should be Zeros except for the tags.
  3925. Arguments:
  3926. RealBufferStart -- the beginning of the padding.
  3927. RealBufferLength -- total length of allocation.
  3928. AdvertisedBufferStart -- The beginning of the buffer that the driver can see.
  3929. AdvertisedLength -- how long the driver thinks that the buffer is.
  3930. If AdvertisedBuffer/AdvertisedLength aren't present (they must
  3931. both be yea or nay) we won't check for a valid tag.
  3932. Return Value:
  3933. NONE.
  3934. --*/
  3935. {
  3936. const ULONG tagSize = sizeof(ViDmaVerifierTag);
  3937. PULONG_PTR corruptedAddress;
  3938. if (AdvertisedBufferLength == RealBufferLength) {
  3939. //
  3940. // No padding to check.
  3941. //
  3942. return;
  3943. }
  3944. if (! AdvertisedBufferLength) {
  3945. //
  3946. // There is no intervening buffer to worry about --
  3947. // so the *whole* thing has to be the padding fill char
  3948. //
  3949. corruptedAddress = ViHasBufferBeenTouched(
  3950. RealBufferStart,
  3951. RealBufferLength,
  3952. PADDING_FILL_CHAR
  3953. );
  3954. VF_ASSERT(
  3955. NULL == corruptedAddress,
  3956. HV_BOUNDARY_OVERRUN,
  3957. ( "Verified driver or hardware has corrupted memory at %p",
  3958. corruptedAddress )
  3959. );
  3960. } // ! AdvertisedBufferLength //
  3961. else {
  3962. PUCHAR prePadStart;
  3963. PUCHAR postPadStart;
  3964. ULONG_PTR prePadBytes;
  3965. ULONG_PTR postPadBytes;
  3966. USHORT whereToCheck = 0;
  3967. prePadStart = (PUCHAR) RealBufferStart;
  3968. prePadBytes = (PUCHAR) AdvertisedBufferStart - prePadStart;
  3969. postPadStart = (PUCHAR) AdvertisedBufferStart + AdvertisedBufferLength;
  3970. postPadBytes = RealBufferLength - (postPadStart - (PUCHAR) RealBufferStart);
  3971. //
  3972. // Now factor in the tag... it's the only thing in the padding that is allowed to be
  3973. // non-zero.
  3974. //
  3975. if (prePadBytes >= tagSize) {
  3976. prePadBytes -= tagSize;
  3977. whereToCheck |= TAG_BUFFER_START;
  3978. }
  3979. if (postPadBytes >= tagSize) {
  3980. postPadBytes -= tagSize;
  3981. postPadStart += tagSize;
  3982. whereToCheck |= TAG_BUFFER_END;
  3983. }
  3984. //
  3985. // Make sure the tag is in place.
  3986. //
  3987. ViCheckTag(AdvertisedBufferStart, AdvertisedBufferLength , FALSE, whereToCheck);
  3988. corruptedAddress = ViHasBufferBeenTouched(
  3989. prePadStart,
  3990. prePadBytes,
  3991. PADDING_FILL_CHAR
  3992. );
  3993. VF_ASSERT(
  3994. NULL == corruptedAddress,
  3995. HV_BOUNDARY_OVERRUN,
  3996. ( "Padding before allocation at %p has been illegally modified at %p",
  3997. AdvertisedBufferStart,
  3998. corruptedAddress
  3999. )
  4000. );
  4001. corruptedAddress = ViHasBufferBeenTouched(
  4002. postPadStart,
  4003. postPadBytes,
  4004. PADDING_FILL_CHAR
  4005. );
  4006. VF_ASSERT(
  4007. NULL == corruptedAddress,
  4008. HV_BOUNDARY_OVERRUN,
  4009. ( "Padding after allocation at %p has been illegally modified at %p",
  4010. AdvertisedBufferStart,
  4011. corruptedAddress
  4012. )
  4013. );
  4014. } // if AdvertisedLength //
  4015. } // ViCheckPadding //
  4016. PULONG_PTR
  4017. ViHasBufferBeenTouched(
  4018. IN PVOID Address,
  4019. IN ULONG_PTR Length,
  4020. IN UCHAR ExpectedFillChar
  4021. )
  4022. /*++
  4023. Routine Description:
  4024. Check if a buffer contains a repetition of a certain character.
  4025. Arguments:
  4026. Address -- address of buffer to check.
  4027. Length -- length of buffer.
  4028. ExpectedFillChar -- the character that should be repeated.
  4029. Return Value:
  4030. The address at which it has been touched.
  4031. or NULL if it hasn't been touched
  4032. --*/
  4033. {
  4034. PULONG_PTR currentChunk;
  4035. PUCHAR currentByte;
  4036. ULONG_PTR expectedFillChunk;
  4037. ULONG counter;
  4038. expectedFillChunk = (ULONG_PTR) ExpectedFillChar;
  4039. counter = 1;
  4040. //
  4041. // How is this for non-obvious code!
  4042. // What it does is fills in a ULONG_PTR with
  4043. // the character
  4044. //
  4045. while( counter < sizeof(ULONG_PTR) ) {
  4046. expectedFillChunk |= expectedFillChunk << (counter << 3);
  4047. counter <<=1;
  4048. }
  4049. //
  4050. // Get aligned natively
  4051. //
  4052. currentByte = Address;
  4053. while((ULONG_PTR) currentByte % sizeof(ULONG_PTR) && Length) {
  4054. if(*currentByte != ExpectedFillChar) {
  4055. return (PULONG_PTR) currentByte;
  4056. }
  4057. currentByte++;
  4058. Length--;
  4059. }
  4060. currentChunk = (PULONG_PTR) currentByte;
  4061. //
  4062. // Check 4 (or 8 depending on architecture) bytes at a time
  4063. //
  4064. while(Length >= sizeof(ULONG_PTR)) {
  4065. if (*currentChunk != expectedFillChunk) {
  4066. return currentChunk;
  4067. }
  4068. currentChunk++;
  4069. Length-=sizeof(ULONG_PTR);
  4070. }
  4071. currentByte = (PUCHAR) currentChunk;
  4072. //
  4073. // Check the remaining few bytes
  4074. //
  4075. while(Length) {
  4076. if(*currentByte != ExpectedFillChar) {
  4077. return (PULONG_PTR) currentByte;
  4078. }
  4079. currentByte++;
  4080. Length--;
  4081. }
  4082. return NULL;
  4083. } // ViHasMapRegisterBeenTouched //
  4084. VOID
  4085. VfAssert(
  4086. IN LOGICAL Condition,
  4087. IN ULONG Code,
  4088. IN OUT PULONG Enable
  4089. )
  4090. /*++
  4091. Routine Description:
  4092. Verifier Assert.
  4093. Arguments:
  4094. Condition -- is this true?
  4095. Code -- code to pass to KeBugcheck if need be.
  4096. Enable -- lets us Zap the assert
  4097. Return Value:
  4098. None
  4099. --*/
  4100. {
  4101. ULONG enableCode = *Enable;
  4102. if (Condition) {
  4103. return;
  4104. }
  4105. if (enableCode & HVC_ONCE) {
  4106. //
  4107. // HVC_ONCE does a self-zap
  4108. //
  4109. *Enable = HVC_IGNORE;
  4110. }
  4111. if (enableCode & HVC_WARN) {
  4112. //
  4113. // Already warned
  4114. //
  4115. return;
  4116. }
  4117. if(enableCode & HVC_BUGCHECK || ! KdDebuggerEnabled ) {
  4118. KeBugCheckEx (
  4119. HAL_VERIFIER_DETECTED_VIOLATION,
  4120. Code,
  4121. 0,
  4122. 0,
  4123. 0
  4124. );
  4125. return;
  4126. }
  4127. if (enableCode & HVC_ASSERT) {
  4128. char response[2];
  4129. while (TRUE) {
  4130. DbgPrint( "\n*** Verifier assertion failed ***\n");
  4131. DbgPrompt( "(B)reak, (I)gnore, (W)arn only, (R)emove assert? ",
  4132. response,
  4133. sizeof( response )
  4134. );
  4135. switch (response[0]) {
  4136. case 'B':
  4137. case 'b':
  4138. DbgBreakPoint();
  4139. break;
  4140. case 'I':
  4141. case 'i':
  4142. return;
  4143. case 'W':
  4144. case 'w':
  4145. //
  4146. // Next time we hit this, we aren't going to assert, just
  4147. // print out a warning
  4148. //
  4149. *Enable = HVC_WARN;
  4150. return;
  4151. case 'R':
  4152. case 'r':
  4153. //
  4154. // Next time we hit this we are going to ignore it
  4155. //
  4156. *Enable = HVC_IGNORE;
  4157. return;
  4158. } // end of switch //
  4159. } // while true //
  4160. } // if we want to assert //
  4161. } // VfAssert //
  4162. PVOID
  4163. VfAllocateCrashDumpRegisters(
  4164. IN PADAPTER_OBJECT AdapterObject,
  4165. IN PULONG NumberOfMapRegisters
  4166. )
  4167. /*++
  4168. Routine Description:
  4169. Hook HalAllocateCrashDumpRegisters so that we can bump up the number
  4170. of map registers the device is allowed to have.
  4171. Arguments:
  4172. Same as HalAllocateCrashDumpRegisters
  4173. Return Value:
  4174. PVOID -- pointer to the map registers
  4175. --*/
  4176. {
  4177. PVOID mapRegisterBase;
  4178. PADAPTER_INFORMATION adapterInformation;
  4179. //
  4180. // Note -- turn off dma verification when we're doing a crash dump (but leave it
  4181. // on for a hibernate). Crash dumps are done at IRQL == HIGH_LEVEL, and we'd
  4182. // crash the machine a second time if we tried to use spin locks, allocate
  4183. // memory, and all of the other stuff that we do.
  4184. //
  4185. if (KeGetCurrentIrql() > DISPATCH_LEVEL &&
  4186. ViVerifyDma) {
  4187. ViVerifyDma = FALSE;
  4188. //
  4189. // Reset the DMA operations table to the real one for all adapters
  4190. // we have. Otherwise, because ViVerifyDma is not set, we'll believe
  4191. // he have never hooked the operations and we'll recursively call
  4192. // the verifier routines. Do not worry about synchronization now.
  4193. //
  4194. FOR_ALL_IN_LIST(ADAPTER_INFORMATION, &ViAdapterList.ListEntry, adapterInformation)
  4195. {
  4196. if (adapterInformation->DmaAdapter) {
  4197. adapterInformation->DmaAdapter->DmaOperations = adapterInformation->RealDmaOperations;
  4198. }
  4199. }
  4200. }
  4201. adapterInformation = ViGetAdapterInformation((DMA_ADAPTER *)AdapterObject);
  4202. mapRegisterBase = HalAllocateCrashDumpRegisters(
  4203. AdapterObject,
  4204. NumberOfMapRegisters
  4205. );
  4206. if (adapterInformation) {
  4207. //
  4208. // Note we only get here if this is a hibernate, not a crash dump
  4209. //
  4210. VF_ASSERT_IRQL(DISPATCH_LEVEL);
  4211. //
  4212. // Do not double buffer crash dump registers. They are special.
  4213. //
  4214. //
  4215. // Add these map registers -- but also add to the maximum number that can
  4216. // be mapped
  4217. //
  4218. InterlockedExchangeAdd((PLONG)(&adapterInformation->MaximumMapRegisters), *NumberOfMapRegisters);
  4219. ADD_MAP_REGISTERS(adapterInformation, *NumberOfMapRegisters, FALSE);
  4220. } // if (adapterInformation)
  4221. //
  4222. // Some drivers (hiber_scsiport for one) don't call FlushAdapterBuffers
  4223. // unless the MapRegisterBase is non-NULL. This breaks our
  4224. // calculations in the hibernation path.
  4225. // So, in order to fool the drivers into thinking that they need
  4226. // to flush, we exchange the NULL MapRegisterBase (if in fact
  4227. // the hal uses a null map register base) for our
  4228. // MRF_NULL_PLACEHOLDER and take care to replace back with NULL
  4229. // in our wrappers before passing it to the HAL.
  4230. // Also, make sure not to mess with the crash dump case.
  4231. //
  4232. if (ViVerifyDma &&
  4233. NULL == mapRegisterBase) {
  4234. mapRegisterBase = MRF_NULL_PLACEHOLDER;
  4235. }
  4236. return mapRegisterBase;
  4237. } // VfAllocateCrashDumpRegisters //
  4238. VOID
  4239. ViCommonBufferCalculatePadding(
  4240. IN ULONG Length,
  4241. OUT PULONG PrePadding,
  4242. OUT PULONG PostPadding
  4243. )
  4244. /*++
  4245. Routine Description:
  4246. Calculates how many bytes to reserve for padding before and
  4247. after a common buffer. The reason to make this a function is
  4248. to be able to have more granular per-buffer padding policies.
  4249. The prePadding will be page aligned.
  4250. Arguments:
  4251. Length -- the allocation real length
  4252. PrePadding -- how many bytes to reserve for padding before the start
  4253. of the common buffer
  4254. PostPadding -- how many bytes to reserve for padding before the
  4255. end of the common buffer
  4256. Return Value:
  4257. None.
  4258. --*/
  4259. {
  4260. if (!ViProtectBuffers) {
  4261. //
  4262. // Don't add any padding if we're not padding buffers
  4263. //
  4264. *PrePadding = *PostPadding = 0;
  4265. return;
  4266. }
  4267. //
  4268. // Use one full guard page, so the buffer returned to the caller
  4269. // will be page-aligned
  4270. //
  4271. *PrePadding = PAGE_SIZE;
  4272. if (Length + sizeof(ViDmaVerifierTag) <= PAGE_SIZE) {
  4273. //
  4274. // For small buffers, just allocate a page
  4275. //
  4276. *PostPadding = PAGE_SIZE - Length;
  4277. }
  4278. else if ( BYTE_OFFSET(Length)) {
  4279. //
  4280. // For longer buffers that aren't an even number of pages,
  4281. // just round up the number of pages necessary
  4282. // (we need space at least for our tag)
  4283. //
  4284. *PostPadding = (BYTES_TO_PAGES( Length + sizeof(ViDmaVerifierTag) )
  4285. << PAGE_SHIFT ) - Length;
  4286. }
  4287. else { // PAGE ALIGNED LENGTH //
  4288. //
  4289. // Since if the length is an even number of pages the driver might expect
  4290. // a page aligned buffer, we allocate the page before and after the allocation
  4291. //
  4292. *PostPadding = PAGE_SIZE;
  4293. }
  4294. return;
  4295. } //ViCommonBufferCalculatePadding
  4296. VOID
  4297. ViAllocateContiguousMemory (
  4298. IN OUT PADAPTER_INFORMATION AdapterInformation
  4299. )
  4300. /*++
  4301. Routine Description:
  4302. Attempts to allocate 3 * MAX_CONTIGUOUS_MAP_REGISTERS contiguous
  4303. physical pages to form a pool from where we can give 3-page buffers for
  4304. double buffering map registers. Note that if we fail, or if we use more
  4305. than MAX_CONTIGUOUS_MAP_REGISTERS at a time, we'll just default to
  4306. non-contiguous non paged pool, so we can still test a number of assertions
  4307. that come with double buffering.
  4308. Arguments:
  4309. AdapterInformation - information about our adapter.
  4310. Return Value:
  4311. None.
  4312. --*/
  4313. {
  4314. PHYSICAL_ADDRESS highestAddress;
  4315. ULONG i;
  4316. PAGED_CODE();
  4317. //
  4318. // Default to a less than 1 MB visible
  4319. //
  4320. highestAddress.HighPart = 0;
  4321. highestAddress.LowPart = 0x000FFFF;
  4322. //
  4323. // Determine the highest acceptable physical address to be used
  4324. // in calls to MmAllocateContiguousMemory
  4325. //
  4326. if (AdapterInformation->DeviceDescription.Dma64BitAddresses) {
  4327. //
  4328. // Can use any address in the 64 bit address space
  4329. //
  4330. highestAddress.QuadPart = (ULONGLONG)-1;
  4331. } else if (AdapterInformation->DeviceDescription.Dma32BitAddresses) {
  4332. //
  4333. // Can use any address in the 32 bit (<4GB) address space
  4334. //
  4335. highestAddress.LowPart = 0xFFFFFFFF;
  4336. } else if (AdapterInformation->DeviceDescription.InterfaceType == Isa) {
  4337. //
  4338. // Can see 16MB (24-bit addresses)
  4339. //
  4340. highestAddress.LowPart = 0x00FFFFFF;
  4341. }
  4342. //
  4343. // Initialize the allocator bitmap
  4344. //
  4345. RtlInitializeBitMap(&AdapterInformation->AllocationMap,
  4346. (PULONG)&AdapterInformation->AllocationStorage,
  4347. MAX_CONTIGUOUS_MAP_REGISTERS);
  4348. //
  4349. // Initially no blocks are allocated
  4350. //
  4351. RtlClearAllBits(&AdapterInformation->AllocationMap);
  4352. AdapterInformation->ContiguousBuffers = ExAllocatePoolWithTag(NonPagedPool,
  4353. MAX_CONTIGUOUS_MAP_REGISTERS * sizeof(PVOID),
  4354. HAL_VERIFIER_POOL_TAG);
  4355. if (AdapterInformation->ContiguousBuffers) {
  4356. //
  4357. // Allocate contiguous buffers
  4358. //
  4359. for (i = 0; i < MAX_CONTIGUOUS_MAP_REGISTERS; i++) {
  4360. AdapterInformation->ContiguousBuffers[i] = MmAllocateContiguousMemory(3 * PAGE_SIZE,
  4361. highestAddress);
  4362. if (NULL == AdapterInformation->ContiguousBuffers[i]) {
  4363. //
  4364. // Mark as in use, so we don't hand it over
  4365. //
  4366. RtlSetBits(&AdapterInformation->AllocationMap, i, 1);
  4367. InterlockedIncrement((PLONG)&AdapterInformation->FailedContiguousAllocations);
  4368. } else {
  4369. InterlockedIncrement((PLONG)&AdapterInformation->SuccessfulContiguousAllocations);
  4370. }
  4371. }
  4372. }
  4373. return;
  4374. } // ViAllocateContiguousMemory
  4375. PVOID
  4376. ViAllocateFromContiguousMemory (
  4377. IN OUT PADAPTER_INFORMATION AdapterInformation,
  4378. IN ULONG HintIndex
  4379. )
  4380. /*++
  4381. Routine Description:
  4382. Attempts to 'allocate' a 3 page buffer from our pre-allocated
  4383. contiguous memory.
  4384. Arguments:
  4385. AdapterInformation - adapter data
  4386. HintIndex - gives a hint where to look for the next free block
  4387. Return Value:
  4388. A virtual address from our contiguous memory pool or NULL if none
  4389. is available.
  4390. --*/
  4391. {
  4392. PVOID address = NULL;
  4393. ULONG index;
  4394. KIRQL oldIrql;
  4395. if (NULL == AdapterInformation ||
  4396. NULL == AdapterInformation->ContiguousBuffers) {
  4397. return NULL;
  4398. }
  4399. //
  4400. // Find the first available location
  4401. //
  4402. KeAcquireSpinLock(&AdapterInformation->AllocationLock, &oldIrql);
  4403. index = RtlFindClearBitsAndSet(&AdapterInformation->AllocationMap, 1, HintIndex);
  4404. if (index != 0xFFFFFFFF) {
  4405. address = AdapterInformation->ContiguousBuffers[index];
  4406. }
  4407. KeReleaseSpinLock(&AdapterInformation->AllocationLock, oldIrql);
  4408. return address;
  4409. } // ViAllocateFromContiguousMemory
  4410. LOGICAL
  4411. ViFreeToContiguousMemory (
  4412. IN OUT PADAPTER_INFORMATION AdapterInformation,
  4413. IN PVOID Address,
  4414. IN ULONG HintIndex
  4415. )
  4416. /*++
  4417. Routine Description:
  4418. Frees a 3-pahe contiguous buffer into our pool of contiguous buffers
  4419. contiguous memory.
  4420. Arguments:
  4421. AdapterInformation - adapter data.
  4422. Address - the memory to be freed.
  4423. HintIndex - gives a hint where to look for the address to free. Usually
  4424. the address at this index is what we need to free. If not, we
  4425. search the whole buffer.
  4426. Return Value:
  4427. TRUE is the address is from the contiguous buffer pool, FALSE if not.
  4428. --*/
  4429. {
  4430. ULONG index = 0xFFFFFFFF;
  4431. KIRQL oldIrql;
  4432. ULONG i;
  4433. if (NULL == AdapterInformation->ContiguousBuffers) {
  4434. return FALSE;
  4435. }
  4436. ASSERT(BYTE_OFFSET(Address) == 0);
  4437. if (HintIndex < MAX_CONTIGUOUS_MAP_REGISTERS &&
  4438. AdapterInformation->ContiguousBuffers[HintIndex] == Address) {
  4439. index = HintIndex;
  4440. } else {
  4441. for (i = 0; i < MAX_CONTIGUOUS_MAP_REGISTERS; i++) {
  4442. if (AdapterInformation->ContiguousBuffers[i] == Address) {
  4443. index = i;
  4444. break;
  4445. }
  4446. }
  4447. }
  4448. if (index < MAX_CONTIGUOUS_MAP_REGISTERS) {
  4449. KeAcquireSpinLock(&AdapterInformation->AllocationLock, &oldIrql);
  4450. ASSERT(RtlAreBitsSet(&AdapterInformation->AllocationMap, index, 1));
  4451. RtlClearBits(&AdapterInformation->AllocationMap, index, 1);
  4452. KeReleaseSpinLock(&AdapterInformation->AllocationLock, oldIrql);
  4453. return TRUE;
  4454. } else {
  4455. return FALSE;
  4456. }
  4457. } // ViFreeToContiguousMemory
  4458. LOGICAL
  4459. VfIsPCIBus (
  4460. IN PDEVICE_OBJECT PhysicalDeviceObject
  4461. )
  4462. /*++
  4463. Routine Description:
  4464. Checks if a PDO is for a PCI bus, in which case we do not hook up
  4465. the adapter (because we may do this when called for a PCI device on that
  4466. bus and they may not want it).
  4467. Arguments:
  4468. PhysicalDeviceObject - the PDO to be checked
  4469. Return Value:
  4470. TRUE is the PDO is for a PCI bus, FALSE if not.
  4471. --*/
  4472. {
  4473. LOGICAL result = FALSE;
  4474. NTSTATUS status;
  4475. WCHAR deviceDesc[40];
  4476. ULONG length = 0;
  4477. if (NULL == PhysicalDeviceObject) {
  4478. //
  4479. // If the PDO is NULL, assume it is not
  4480. // a PCI bus...
  4481. //
  4482. return FALSE;
  4483. }
  4484. status = IoGetDeviceProperty(PhysicalDeviceObject,
  4485. DevicePropertyDeviceDescription,
  4486. sizeof(WCHAR) * 40,
  4487. deviceDesc,
  4488. &length);
  4489. if (status == STATUS_SUCCESS &&
  4490. 0 == _wcsicmp(deviceDesc, L"PCI bus")) {
  4491. result = TRUE;
  4492. }
  4493. return result;
  4494. } // VfIsPCIBus
  4495. PDEVICE_OBJECT
  4496. VfGetPDO (
  4497. IN PDEVICE_OBJECT DeviceObject
  4498. )
  4499. /*++
  4500. Routine Description:
  4501. Gets the device object at the bottom of a device stack (PDO)
  4502. Arguments:
  4503. DeviceObject - device object in the device stack
  4504. Return Value:
  4505. A pointer to a physical device object.
  4506. --*/
  4507. {
  4508. PDEVICE_OBJECT pdo;
  4509. pdo = DeviceObject;
  4510. while (pdo->DeviceObjectExtension &&
  4511. pdo->DeviceObjectExtension->AttachedTo) {
  4512. pdo = pdo->DeviceObjectExtension->AttachedTo;
  4513. }
  4514. return pdo;
  4515. } // VfGetPDO
  4516. VOID
  4517. VfDisableHalVerifier (
  4518. VOID
  4519. )
  4520. /*++
  4521. Routine Description:
  4522. Disables HAL Verifier when we do a crash dump.
  4523. Arguments:
  4524. None.
  4525. Return Value:
  4526. None.
  4527. --*/
  4528. {
  4529. PADAPTER_INFORMATION adapterInformation;
  4530. if (ViVerifyDma) {
  4531. ViVerifyDma = FALSE;
  4532. //
  4533. // Reset the DMA operations table to the real one for all adapters
  4534. // we have. Otherwise, because ViVerifyDma is not set, we'll believe
  4535. // he have never hooked the operations and we'll recursively call
  4536. // the verifier routines. Do not worry about synchronization now.
  4537. //
  4538. FOR_ALL_IN_LIST(ADAPTER_INFORMATION, &ViAdapterList.ListEntry, adapterInformation)
  4539. {
  4540. if (adapterInformation->DmaAdapter) {
  4541. adapterInformation->DmaAdapter->DmaOperations = adapterInformation->RealDmaOperations;
  4542. }
  4543. }
  4544. }
  4545. return;
  4546. } // VfDisableHalVerifier