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.

1045 lines
26 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. dma.c
  5. Abstract:
  6. This is the NT Video port driver dma support module.
  7. Author:
  8. Bruce McQuistan (brucemc) Mar. 1996
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "videoprt.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, VideoPortGetCommonBuffer)
  17. #pragma alloc_text(PAGE, VideoPortFreeCommonBuffer)
  18. #pragma alloc_text(PAGE, VideoPortDoDma)
  19. #pragma alloc_text(PAGE, VideoPortUnlockPages)
  20. #pragma alloc_text(PAGE, VideoPortSetBytesUsed)
  21. #pragma alloc_text(PAGE, VideoPortMapDmaMemory)
  22. #pragma alloc_text(PAGE, VideoPortUnmapDmaMemory)
  23. #pragma alloc_text(PAGE, VideoPortGetDmaAdapter)
  24. #pragma alloc_text(PAGE, VideoPortPutDmaAdapter)
  25. #pragma alloc_text(PAGE, VideoPortAllocateCommonBuffer)
  26. #pragma alloc_text(PAGE, VideoPortReleaseCommonBuffer)
  27. #pragma alloc_text(PAGE, VideoPortLockBuffer)
  28. #endif
  29. #define MAX_COMMON_BUFFER_SIZE 0x40000
  30. PVOID
  31. VideoPortAllocateContiguousMemory(
  32. IN PVOID HwDeviceExtension,
  33. IN ULONG NumberOfBytes,
  34. IN PHYSICAL_ADDRESS HighestAcceptableAddress
  35. )
  36. {
  37. if ((NumberOfBytes > MAX_COMMON_BUFFER_SIZE))
  38. return NULL;
  39. return MmAllocateContiguousMemory(NumberOfBytes, HighestAcceptableAddress);
  40. }
  41. PVOID
  42. VideoPortGetCommonBuffer(
  43. IN PVOID HwDeviceExtension,
  44. IN ULONG DesiredLength,
  45. IN ULONG Alignment,
  46. OUT PPHYSICAL_ADDRESS LogicalAddress,
  47. OUT PULONG ActualLength,
  48. IN BOOLEAN CacheEnabled
  49. )
  50. /*++
  51. Routine Description:
  52. Provides physical address visible to both device and system. Memory
  53. seen as contiguous by device.
  54. Arguments:
  55. HwDeviceExtension - device extension available to miniport.
  56. DesiredLength - size of desired memory (should be minimal).
  57. Alignment - Desired alignment of buffer, currently unused.
  58. LogicalAddress - [out] parameter which will hold physical address of
  59. of the buffer upon function return.
  60. ActualLength - Actual length of buffer.
  61. CacheEnabled - Specifies whether the allocated memory can be cached.
  62. Return Value:
  63. Virtual address of the common buffer.
  64. --*/
  65. {
  66. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  67. VP_DMA_ADAPTER vpDmaAdapter;
  68. PVOID VirtualAddress;
  69. if (DesiredLength > MAX_COMMON_BUFFER_SIZE) {
  70. return NULL;
  71. }
  72. vpDmaAdapter.DmaAdapterObject = fdoExtension->DmaAdapterObject;
  73. VirtualAddress = VideoPortAllocateCommonBuffer(HwDeviceExtension,
  74. &vpDmaAdapter,
  75. DesiredLength,
  76. LogicalAddress,
  77. CacheEnabled,
  78. NULL);
  79. *ActualLength = VirtualAddress ? DesiredLength : 0;
  80. return (VirtualAddress);
  81. }
  82. VOID
  83. VideoPortFreeCommonBuffer(
  84. IN PVOID HwDeviceExtension,
  85. IN ULONG Length,
  86. IN PVOID VirtualAddress,
  87. IN PHYSICAL_ADDRESS LogicalAddress,
  88. IN BOOLEAN CacheEnabled
  89. )
  90. /*++
  91. Routine Description:
  92. Frees memory allocated by VideoPortGetCommonBuffer.
  93. Arguments:
  94. HwDeviceExtension - device extension available to miniport.
  95. DesiredLength - size of memory allocated.
  96. Alignment - Desired liagnment of buffer, currently unused.
  97. VirtualAddress - [out] parameter which will hold virtual address of
  98. the buffer upon function return.
  99. LogicalAddress - [out] parameter which will hold physical address of
  100. of the buffer upon function return.
  101. CacheEnabled - Specifies whether the allocated memory can be cached.
  102. Return Value:
  103. VOID.
  104. --*/
  105. {
  106. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  107. VP_DMA_ADAPTER vpDmaAdapter;
  108. vpDmaAdapter.DmaAdapterObject = fdoExtension->DmaAdapterObject;
  109. VideoPortReleaseCommonBuffer( HwDeviceExtension,
  110. &vpDmaAdapter,
  111. Length,
  112. LogicalAddress,
  113. VirtualAddress,
  114. CacheEnabled );
  115. }
  116. PDMA
  117. VideoPortDoDma(
  118. IN PVOID HwDeviceExtension,
  119. IN PDMA pDma,
  120. IN DMA_FLAGS DmaFlags
  121. )
  122. /*++
  123. This function is obsolete.
  124. --*/
  125. {
  126. return NULL;
  127. }
  128. PDMA
  129. VideoPortAssociateEventsWithDmaHandle(
  130. IN PVOID HwDeviceExtension,
  131. IN OUT PVIDEO_REQUEST_PACKET pVrp,
  132. IN PVOID MappedUserEvent,
  133. IN PVOID DisplayDriverEvent
  134. )
  135. /*++
  136. This function is obsolete.
  137. --*/
  138. {
  139. return NULL;
  140. }
  141. BOOLEAN
  142. VideoPortLockPages(
  143. IN PVOID HwDeviceExtension,
  144. IN OUT PVIDEO_REQUEST_PACKET pVrp,
  145. IN PEVENT pMappedUserEvent,
  146. IN PEVENT pDisplayEvent,
  147. IN DMA_FLAGS DmaFlags
  148. )
  149. /*++
  150. Routine Description:
  151. This function is obsolete. For the purpose of compatability, we
  152. lock the memory when DmaFlags == VideoPortDmaInitOnly. But we do
  153. nothing more than that.
  154. --*/
  155. {
  156. PMDL Mdl;
  157. pVideoDebugPrint((Error, "VideoPortLockPages is obsolete!\n"));
  158. *(PULONG_PTR)(pVrp->OutputBuffer) = (ULONG_PTR) 0;
  159. if (DmaFlags != VideoPortDmaInitOnly) {
  160. return FALSE;
  161. }
  162. Mdl = VideoPortLockBuffer( HwDeviceExtension,
  163. pVrp->InputBuffer,
  164. pVrp->InputBufferLength,
  165. VpModifyAccess );
  166. if( Mdl == NULL ){
  167. return FALSE;
  168. }
  169. //
  170. // Put pMdl into OutputBuffer.
  171. //
  172. *(PULONG_PTR)(pVrp->OutputBuffer) = (ULONG_PTR) Mdl;
  173. return TRUE;
  174. }
  175. BOOLEAN
  176. VideoPortUnlockPages(
  177. PVOID HwDeviceExtension,
  178. PDMA pDma
  179. )
  180. /*++
  181. Routine Description:
  182. This function is obsolete. For the purpose of compatability, we
  183. just unlock the memory and does nothing more than that.
  184. --*/
  185. {
  186. PMDL Mdl = (PMDL) pDma;
  187. pVideoDebugPrint((Error, "VideoPortUnLockPages is obsolete!\n"));
  188. VideoPortUnlockBuffer( HwDeviceExtension, Mdl );
  189. return TRUE;
  190. }
  191. PVOID
  192. VideoPortGetDmaContext(
  193. PVOID HwDeviceExtension,
  194. IN PDMA pDma
  195. )
  196. /*++
  197. This function is obsolete.
  198. --*/
  199. {
  200. return NULL;
  201. }
  202. VOID
  203. VideoPortSetDmaContext(
  204. IN PVOID HwDeviceExtension,
  205. IN OUT PDMA pDma,
  206. IN PVOID InstanceContext
  207. )
  208. /*++
  209. This function is obsolete.
  210. --*/
  211. {
  212. }
  213. PVOID
  214. VideoPortGetMdl(
  215. IN PVOID HwDeviceExtension,
  216. IN PDMA pDma
  217. )
  218. /*++
  219. Routine Description:
  220. This function is obsolete. We still return the Mdl for the purpose
  221. of compatibility.
  222. --*/
  223. {
  224. //
  225. // pDma is the Mdl ( see VideoPortLockPages )
  226. //
  227. return (PVOID) pDma;
  228. }
  229. ULONG
  230. VideoPortGetBytesUsed(
  231. IN PVOID HwDeviceExtension,
  232. IN PDMA pDma
  233. )
  234. /*++
  235. This function is obsolete.
  236. --*/
  237. {
  238. return 0;
  239. }
  240. VOID
  241. VideoPortSetBytesUsed(
  242. IN PVOID HwDeviceExtension,
  243. IN OUT PDMA pDma,
  244. IN ULONG BytesUsed
  245. )
  246. /*++
  247. Routine Description:
  248. This function is obsolete.
  249. --*/
  250. {
  251. }
  252. PDMA
  253. VideoPortMapDmaMemory(
  254. IN PVOID HwDeviceExtension,
  255. IN PVIDEO_REQUEST_PACKET pVrp,
  256. IN PHYSICAL_ADDRESS BoardAddress,
  257. IN PULONG Length,
  258. IN PULONG InIoSpace,
  259. IN PVOID MappedUserEvent,
  260. IN PVOID DisplayDriverEvent,
  261. IN OUT PVOID * VirtualAddress
  262. )
  263. /*++
  264. This function is obsolete.
  265. --*/
  266. {
  267. return NULL;
  268. }
  269. BOOLEAN
  270. VideoPortUnmapDmaMemory(
  271. PVOID HwDeviceExtension,
  272. PVOID VirtualAddress,
  273. HANDLE ProcessHandle,
  274. PDMA BoardMemoryHandle
  275. )
  276. /*++
  277. This function is obsolete.
  278. --*/
  279. {
  280. return FALSE;
  281. }
  282. //
  283. // New DMA code start here
  284. //
  285. PVP_DMA_ADAPTER
  286. VideoPortGetDmaAdapter(
  287. IN PVOID HwDeviceExtension,
  288. IN PVP_DEVICE_DESCRIPTION VpDeviceDescription
  289. )
  290. /*++
  291. Routine Description:
  292. Arguments:
  293. HwDeviceExtension - Points to the miniport driver's device extension.
  294. VpDeviceDescription - Points to a DEVICE_DESCRIPTION structure, which
  295. describes the attributes of the physical device.
  296. Return Value:
  297. Returns a pointer to a VP_DMA_ADAPTER on sucess, or NULL otherwise.
  298. --*/
  299. {
  300. DEVICE_DESCRIPTION DeviceDescription;
  301. ULONG numberOfMapRegisters;
  302. PVP_DMA_ADAPTER VpDmaAdapter, p;
  303. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  304. VpDmaAdapter = ExAllocatePoolWithTag( NonPagedPool,
  305. sizeof(VP_DMA_ADAPTER),
  306. VP_TAG );
  307. if(!VpDmaAdapter) {
  308. return NULL;
  309. } else {
  310. RtlZeroMemory((PVOID) VpDmaAdapter, sizeof(VP_DMA_ADAPTER));
  311. }
  312. //
  313. // Fill in DEVICE_DESCRITION with the data passed in. We also assume
  314. // the this is a busmaster device.
  315. //
  316. DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
  317. DeviceDescription.ScatterGather = VpDeviceDescription->ScatterGather;
  318. DeviceDescription.Dma32BitAddresses = VpDeviceDescription->Dma32BitAddresses;
  319. DeviceDescription.Dma64BitAddresses = VpDeviceDescription->Dma64BitAddresses;
  320. DeviceDescription.MaximumLength = VpDeviceDescription->MaximumLength;
  321. DeviceDescription.BusNumber = fdoExtension->SystemIoBusNumber;
  322. DeviceDescription.InterfaceType = fdoExtension->AdapterInterfaceType;
  323. DeviceDescription.Master = TRUE;
  324. DeviceDescription.DemandMode = FALSE;
  325. DeviceDescription.AutoInitialize = FALSE;
  326. DeviceDescription.IgnoreCount = FALSE;
  327. DeviceDescription.Reserved1 = FALSE;
  328. DeviceDescription.DmaWidth = FALSE;
  329. DeviceDescription.DmaSpeed = FALSE;
  330. DeviceDescription.DmaPort = FALSE;
  331. DeviceDescription.DmaChannel = 0;
  332. VpDmaAdapter->DmaAdapterObject = IoGetDmaAdapter(
  333. fdoExtension->PhysicalDeviceObject,
  334. &DeviceDescription,
  335. &numberOfMapRegisters
  336. );
  337. if(!(VpDmaAdapter->DmaAdapterObject)) {
  338. ExFreePool((PVOID)VpDmaAdapter);
  339. return NULL;
  340. } else {
  341. //
  342. // Initialize the other fields of VP_DMA_ADAPTER
  343. //
  344. VpDmaAdapter->NumberOfMapRegisters = numberOfMapRegisters;
  345. }
  346. //
  347. // Add the new VpDmaAdapter to the list
  348. //
  349. VpDmaAdapter->NextVpDmaAdapter = fdoExtension->VpDmaAdapterHead;
  350. fdoExtension->VpDmaAdapterHead = VpDmaAdapter;
  351. return(VpDmaAdapter);
  352. }
  353. VOID
  354. VideoPortPutDmaAdapter(
  355. IN PVOID HwDeviceExtension,
  356. IN PVP_DMA_ADAPTER VpDmaAdapter
  357. )
  358. /*++
  359. Routine Description:
  360. Arguments:
  361. HwDeviceExtension - Points to the miniport driver's device extension.
  362. VpDmaAdapter - Points to the VP_DMA_ADAPTER structure returned by
  363. VideoPortGetDmaAdapter.
  364. Return Value:
  365. Frees the resource allocated in VideoPortGetDmaAdapter
  366. --*/
  367. {
  368. PVP_DMA_ADAPTER p, q;
  369. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  370. //
  371. // Frees the DMA_ADAPTER structure allocated by IoGetDmaAdapter
  372. //
  373. DMA_OPERATION(PutDmaAdapter)(VpDmaAdapter->DmaAdapterObject);
  374. //
  375. // Remove this VpDmaAdapter from the list
  376. //
  377. p = fdoExtension->VpDmaAdapterHead;
  378. if ( p == VpDmaAdapter ) {
  379. fdoExtension->VpDmaAdapterHead = p->NextVpDmaAdapter;
  380. } else {
  381. q = p->NextVpDmaAdapter;
  382. while ( q != NULL) {
  383. if ( q == VpDmaAdapter ) {
  384. p->NextVpDmaAdapter = q->NextVpDmaAdapter;
  385. break;
  386. }
  387. p = q;
  388. q = p->NextVpDmaAdapter;
  389. }
  390. ASSERT (q);
  391. }
  392. ExFreePool((PVOID)VpDmaAdapter);
  393. }
  394. PVOID
  395. VideoPortAllocateCommonBuffer(
  396. IN PVOID HwDeviceExtension,
  397. IN PVP_DMA_ADAPTER VpDmaAdapter,
  398. IN ULONG DesiredLength,
  399. OUT PPHYSICAL_ADDRESS LogicalAddress,
  400. IN BOOLEAN CacheEnabled,
  401. OUT PVOID Reserved
  402. )
  403. /*++
  404. Routine Description:
  405. This function allocates and maps system memory so that it is simultaneously
  406. accessible from both the processor and a device for common-buffer DMA
  407. operations.
  408. Arguments:
  409. HwDeviceExtension - Points to the miniport driver's device extension.
  410. VpDmaAdapter - Points to the VP_DMA_ADAPTER structure returned by
  411. VideoPortGetDmaAdapter.
  412. DesiredLength - Specifies the requested number of bytes of memory.
  413. LogicalAddress - Points to a variable that receives the logical
  414. address to be used by the adapter to access the
  415. allocated buffer.
  416. CacheEnabled - Specifies whether the allocated memory can be cached.
  417. Reserved - Reserved
  418. Return Value:
  419. Returns the base virtual address of the allocated buffer if successful.
  420. Otherwise, returns NULL if the buffer cannot be allocated.
  421. --*/
  422. {
  423. PVOID VirtualAddress;
  424. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  425. if ((VpDmaAdapter == NULL) || (VpDmaAdapter->DmaAdapterObject == NULL)) {
  426. pVideoDebugPrint((Error,
  427. "VideoPortAllocateCommonBuffer: Invalid DMA adapter!\n"));
  428. ASSERT(FALSE);
  429. return NULL;
  430. }
  431. VirtualAddress =
  432. DMA_OPERATION(AllocateCommonBuffer)(VpDmaAdapter->DmaAdapterObject,
  433. DesiredLength,
  434. LogicalAddress,
  435. CacheEnabled);
  436. if (Reserved) {
  437. *(PULONG)Reserved = VirtualAddress ? DesiredLength : 0;
  438. pVideoDebugPrint((Error,
  439. "VideoPortAllocateCommonBuffer: The last parameter of this function is reserved and should be set to NULL!\n"));
  440. }
  441. return VirtualAddress;
  442. }
  443. VOID
  444. VideoPortReleaseCommonBuffer(
  445. IN PVOID HwDeviceExtension,
  446. IN PVP_DMA_ADAPTER VpDmaAdapter,
  447. IN ULONG Length,
  448. IN PHYSICAL_ADDRESS LogicalAddress,
  449. IN PVOID VirtualAddress,
  450. IN BOOLEAN CacheEnabled
  451. )
  452. /*++
  453. Routine Description:
  454. This function frees a common buffer allocated by VideoPortAllocateCommonBuffer
  455. Arguments:
  456. HwDeviceExtension - Points to the miniport driver's device extension.
  457. VpDmaAdapter - Points to the VP_DMA_ADAPTER structure returned by
  458. VideoPortGetDmaAdapter.
  459. Length - Specifies the number of bytes of memory to be freed.
  460. LogicalAddress - Specifies the logical address of the buffer to be freed.
  461. VirtualAddress - Points to the corresponding virtual address of the
  462. allocated memory range.
  463. CacheEnabled - Specifies whether the allocated memory can be cached.
  464. Return Value:
  465. None
  466. --*/
  467. {
  468. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  469. if ((VpDmaAdapter == NULL) || (VpDmaAdapter->DmaAdapterObject == NULL)) {
  470. pVideoDebugPrint((Error,
  471. " VideoPortReleaseCommonBuffer: Invalid DMA Adapter!\n" ));
  472. ASSERT(FALSE);
  473. return;
  474. }
  475. DMA_OPERATION(FreeCommonBuffer)( VpDmaAdapter->DmaAdapterObject,
  476. Length,
  477. LogicalAddress,
  478. VirtualAddress,
  479. CacheEnabled );
  480. }
  481. PVOID
  482. VideoPortLockBuffer(
  483. IN PVOID HwDeviceExtension,
  484. IN PVOID BaseAddress,
  485. IN ULONG Length,
  486. IN VP_LOCK_OPERATION Operation
  487. )
  488. /*++
  489. Routine Description:
  490. This function probes specified buffer, makes them resident, and locks
  491. the physical pages mapped by the virtual address range in memory.
  492. Arguments:
  493. HwDeviceExtension - Points to the miniport driver's device extension.
  494. BaseAddress - Virtual address of the buffer to be locked.
  495. Length - Specifies the length in bytes of the buffer to be locked.
  496. Operation - Specifies the type of operation for which the caller
  497. wants the access rights probed and the pages locked,
  498. one of VpReadAccess, VpWriteAccess, or VpModifyAccess.
  499. Return Value:
  500. Returns a pointer to an MDL, or NULL if the MDL cannot be allocated.
  501. --*/
  502. {
  503. PMDL Mdl;
  504. //
  505. // Allocate the MDL, but don't stuff it in the Irp, as IoCompleteRequest
  506. // will free it!
  507. //
  508. Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, FALSE, NULL);
  509. if (!Mdl) {
  510. pVideoDebugPrint((Warn, "VideoPortLockBuffer: No MDL address!\n"));
  511. return NULL;
  512. }
  513. //
  514. // Lock down the users buffer
  515. //
  516. __try {
  517. MmProbeAndLockPages( Mdl, KernelMode, Operation );
  518. }
  519. __except(EXCEPTION_EXECUTE_HANDLER) {
  520. IoFreeMdl(Mdl);
  521. pVideoDebugPrint((Error,
  522. "VideoPortLockBuffer: MmProbeandLockPages exception\n"));
  523. Mdl = NULL;
  524. }
  525. return Mdl;
  526. }
  527. VOID
  528. VideoPortUnlockBuffer(
  529. IN PVOID HwDeviceExtension,
  530. IN PVOID Mdl
  531. )
  532. /*++
  533. Routine Description:
  534. This function unlocks physical pages described by a given MDL.
  535. Arguments:
  536. HwDeviceExtension - Points to the miniport driver's device extension.
  537. Mdl - A Pointer that returned from VideoPortLockBuffer.
  538. Return Value:
  539. None
  540. --*/
  541. {
  542. if(Mdl == NULL) {
  543. ASSERT(FALSE);
  544. return;
  545. }
  546. MmUnlockPages(Mdl);
  547. IoFreeMdl(Mdl);
  548. }
  549. typedef struct __LIST_CONTROL_CONTEXT {
  550. PVOID MiniportContext;
  551. PVOID HwDeviceExtension;
  552. PVP_DMA_ADAPTER VpDmaAdapter;
  553. PEXECUTE_DMA ExecuteDmaRoutine;
  554. PVP_SCATTER_GATHER_LIST VpScatterGather;
  555. } LIST_CONTROL_CONTEXT, *PLIST_CONTROL_CONTEXT;
  556. VP_STATUS
  557. VideoPortStartDma(
  558. IN PVOID HwDeviceExtension,
  559. IN PVP_DMA_ADAPTER VpDmaAdapter,
  560. IN PVOID Mdl,
  561. IN ULONG Offset,
  562. IN OUT PULONG pLength,
  563. IN PEXECUTE_DMA ExecuteDmaRoutine,
  564. IN PVOID MiniportContext,
  565. IN BOOLEAN WriteToDevice
  566. )
  567. /*++
  568. Routine Description:
  569. This function flushes the memory from caches of host processors and
  570. calls GetScatterGatherList to build scatter/gather list
  571. Arguments:
  572. HwDeviceExtension - Points to the miniport driver's device extension.
  573. VpDmaAdapter - Points to the VP_DMA_ADAPTER structure returned by
  574. VideoPortGetDmaAdapter.
  575. Mdl - Points to the MDL that describes the buffer
  576. Offset - The byte offset in the buffer from where DMA operation
  577. starts.
  578. pLength - Specifies the requested transfer size in bytes.
  579. On return, this points to the actual size to be
  580. transferred.
  581. ExecuteDmaRoutine - Points to a miniport driver-supplied ExecuteDmaRoutine
  582. routine which will be called to program hardware
  583. registers to start actual DMA operation.
  584. MiniportContext - Points to the miniport driver-determined context to
  585. be passed to the ExecuteDmaRoutine.
  586. WriteToDevice - Indicates the direction of the DMA transfer:
  587. TRUE for a transfer from the buffer to the device,
  588. and FALSE otherwise.
  589. Return Value:
  590. VP_STATUS
  591. --*/
  592. {
  593. KIRQL currentIrql;
  594. ULONG NumberOfMapRegisters;
  595. NTSTATUS ntStatus;
  596. PLIST_CONTROL_CONTEXT Context;
  597. PVOID CurrentVa;
  598. PFDO_EXTENSION fdoExtension = GET_FDO_EXT(HwDeviceExtension);
  599. Context = ( PLIST_CONTROL_CONTEXT )
  600. ExAllocatePoolWithTag ( NonPagedPool,
  601. sizeof(LIST_CONTROL_CONTEXT),
  602. VP_TAG );
  603. if (Context == NULL) {
  604. *pLength = 0;
  605. return ERROR_NOT_ENOUGH_MEMORY;
  606. }
  607. //
  608. // Flush the buffer
  609. //
  610. KeFlushIoBuffers( Mdl, !WriteToDevice, TRUE );
  611. //
  612. // Calculate the number of map registers needed.
  613. //
  614. CurrentVa = (PVOID)((PUCHAR)MmGetMdlVirtualAddress((PMDL)Mdl) + Offset);
  615. NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES (CurrentVa, *pLength);
  616. //
  617. // If the number of map registers needed is greater than the maximum
  618. // number we can handle, we will do a partial transfer.
  619. //
  620. // We updated *pLength here so that it is safe to check this value
  621. // when the miniport callback routine get called.
  622. //
  623. if (NumberOfMapRegisters > VpDmaAdapter->NumberOfMapRegisters) {
  624. NumberOfMapRegisters = VpDmaAdapter->NumberOfMapRegisters;
  625. *pLength = NumberOfMapRegisters * PAGE_SIZE - BYTE_OFFSET(CurrentVa);
  626. }
  627. //
  628. // Prepare Context for pVideoPortListControl
  629. //
  630. Context->HwDeviceExtension = HwDeviceExtension;
  631. Context->MiniportContext = MiniportContext;
  632. Context->VpDmaAdapter = VpDmaAdapter;
  633. Context->ExecuteDmaRoutine = ExecuteDmaRoutine;
  634. //
  635. // Call GetScatterGatherList which will call pVideoPortListControl to
  636. // build scatter-gather list
  637. //
  638. KeRaiseIrql( DISPATCH_LEVEL, &currentIrql );
  639. ntStatus = DMA_OPERATION(GetScatterGatherList) (
  640. VpDmaAdapter->DmaAdapterObject, // AdapterObject
  641. fdoExtension->FunctionalDeviceObject, // DeviceObject
  642. Mdl, // Mdl
  643. CurrentVa, // CurrentVa
  644. *pLength, // Transfer Size
  645. pVideoPortListControl, // ExecutionRoutine
  646. Context, // Context
  647. WriteToDevice ); // WriteToDevice
  648. KeLowerIrql(currentIrql);
  649. if(!NT_SUCCESS(ntStatus)) {
  650. *pLength = 0;
  651. ExFreePool((PVOID) Context);
  652. return ERROR_NOT_ENOUGH_MEMORY;
  653. }
  654. return NO_ERROR;
  655. }
  656. BOOLEAN
  657. pVideoPortSynchronizeExecuteDma(
  658. PLIST_CONTROL_CONTEXT Context
  659. )
  660. {
  661. (Context->ExecuteDmaRoutine)( Context->HwDeviceExtension,
  662. Context->VpDmaAdapter,
  663. Context->VpScatterGather,
  664. Context->MiniportContext );
  665. return TRUE;
  666. }
  667. VOID
  668. pVideoPortListControl (
  669. IN PDEVICE_OBJECT DeviceObject,
  670. IN PIRP Irp,
  671. IN PSCATTER_GATHER_LIST ScatterGather,
  672. IN PVOID ListControlContext
  673. )
  674. /*++
  675. Routine Description:
  676. Get scatter/gather list and calls the miniport callback function to
  677. start actual DMA transfer
  678. Arguments:
  679. Return Value:
  680. None
  681. --*/
  682. {
  683. PLIST_CONTROL_CONTEXT Context;
  684. PFDO_EXTENSION fdoExtension;
  685. PVP_SCATTER_GATHER_LIST VpScatterGather;
  686. Context = (PLIST_CONTROL_CONTEXT)ListControlContext;
  687. fdoExtension = GET_FDO_EXT(Context->HwDeviceExtension);
  688. VpScatterGather = (PVP_SCATTER_GATHER_LIST )(ScatterGather);
  689. Context->VpScatterGather = VpScatterGather;
  690. VideoPortSynchronizeExecution( fdoExtension->HwDeviceExtension,
  691. VpMediumPriority,
  692. pVideoPortSynchronizeExecuteDma,
  693. Context );
  694. ExFreePool((PVOID) Context);
  695. }
  696. VP_STATUS
  697. VideoPortCompleteDma(
  698. IN PVOID HwDeviceExtension,
  699. IN PVP_DMA_ADAPTER VpDmaAdapter,
  700. IN PVP_SCATTER_GATHER_LIST VpScatterGather,
  701. IN BOOLEAN WriteToDevice
  702. )
  703. /*++
  704. Routine Description:
  705. This function flushs the adapter buffers, frees the map registers and
  706. frees the scatter/gather list previously allocated by GetScatterGatherList.
  707. Arguments:
  708. HwDeviceExtension - Points to the miniport driver's device extension.
  709. VpScatterGather - Points to a scatter/gather list previously passed
  710. to miniport callback routine ExecuteDmaRoutine.
  711. WriteToDevice - Indicates the direction of the DMA transfer:
  712. specify TRUE for a transfer from the buffer to
  713. the device, and FALSE otherwise.
  714. --*/
  715. {
  716. KIRQL currentIrql;
  717. //
  718. // Call PutScatterGatherList to flush the adapter buffers, free
  719. // the map registers and the scatter/gather list previously
  720. // allocated by GetScatterGatherList.
  721. //
  722. KeRaiseIrql( DISPATCH_LEVEL, &currentIrql );
  723. DMA_OPERATION(PutScatterGatherList)( VpDmaAdapter->DmaAdapterObject,
  724. (PSCATTER_GATHER_LIST)VpScatterGather,
  725. WriteToDevice );
  726. KeLowerIrql(currentIrql);
  727. return NO_ERROR;
  728. }
  729. #if DBG
  730. VOID
  731. pDumpScatterGather(PVP_SCATTER_GATHER_LIST SGList)
  732. {
  733. PVP_SCATTER_GATHER_ELEMENT Element;
  734. LONG i;
  735. pVideoDebugPrint((Info, "NumberOfElements = %d\n", SGList->NumberOfElements));
  736. Element = SGList->Elements;
  737. for(i = 0; i < (LONG)(SGList->NumberOfElements); i++) {
  738. pVideoDebugPrint((Error, "Length = 0x%x, Address = 0x%x\n",
  739. Element[i].Length, Element[i].Address));
  740. }
  741. }
  742. #endif // DBG