Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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