1 /* 2 * PROJECT: ReactOS Videoport 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: win32ss/drivers/videoprt/dma.c 5 * PURPOSE: Videoport Direct Memory Access Support 6 * PROGRAMMERS: ... 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <videoprt.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 typedef struct 17 { 18 LIST_ENTRY Entry; 19 PDMA_ADAPTER Adapter; 20 ULONG MapRegisters; 21 PVOID HwDeviceExtension; 22 23 }VIP_DMA_ADAPTER, *PVIP_DMA_ADAPTER; 24 25 typedef struct 26 { 27 PVOID HwDeviceExtension; 28 PSCATTER_GATHER_LIST ScatterGatherList; 29 PEXECUTE_DMA ExecuteDmaRoutine; 30 PVOID Context; 31 PVP_DMA_ADAPTER VpDmaAdapter; 32 33 }DMA_START_CONTEXT, *PDMA_START_CONTEXT; 34 35 36 /* PUBLIC FUNCTIONS ***********************************************************/ 37 38 /* 39 * @implemented 40 */ 41 PVOID 42 NTAPI 43 VideoPortAllocateCommonBuffer(IN PVOID HwDeviceExtension, 44 IN PVP_DMA_ADAPTER VpDmaAdapter, 45 IN ULONG DesiredLength, 46 OUT PPHYSICAL_ADDRESS LogicalAddress, 47 IN BOOLEAN CacheEnabled, 48 PVOID Reserved) 49 { 50 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter; 51 52 /* check for valid arguments */ 53 if (!Adapter || !Adapter->Adapter) 54 { 55 /* invalid parameter */ 56 return NULL; 57 } 58 59 /* allocate common buffer */ 60 return Adapter->Adapter->DmaOperations->AllocateCommonBuffer(Adapter->Adapter, DesiredLength, LogicalAddress, CacheEnabled); 61 } 62 63 /* 64 * @implemented 65 */ 66 VOID 67 NTAPI 68 VideoPortReleaseCommonBuffer(IN PVOID HwDeviceExtension, 69 IN PVP_DMA_ADAPTER VpDmaAdapter, 70 IN ULONG Length, 71 IN PHYSICAL_ADDRESS LogicalAddress, 72 IN PVOID VirtualAddress, 73 IN BOOLEAN CacheEnabled) 74 { 75 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter; 76 77 /* check for valid arguments */ 78 if (!Adapter || !Adapter->Adapter) 79 { 80 /* invalid parameter */ 81 return; 82 } 83 84 /* release common buffer */ 85 Adapter->Adapter->DmaOperations->FreeCommonBuffer(Adapter->Adapter, Length, LogicalAddress, VirtualAddress, CacheEnabled); 86 } 87 88 /* 89 * @implemented 90 */ 91 VOID 92 NTAPI 93 VideoPortPutDmaAdapter(IN PVOID HwDeviceExtension, 94 IN PVP_DMA_ADAPTER VpDmaAdapter) 95 { 96 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; 97 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter; 98 99 /* get hw device extension */ 100 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 101 102 /* sanity check */ 103 ASSERT(!IsListEmpty(&DeviceExtension->DmaAdapterList)); 104 105 /* remove dma adapter from list */ 106 RemoveEntryList(&Adapter->Entry); 107 108 /* release dma adapter */ 109 Adapter->Adapter->DmaOperations->PutDmaAdapter(Adapter->Adapter); 110 111 /* free memory */ 112 ExFreePool(Adapter); 113 } 114 115 /* 116 * @implemented 117 */ 118 PVP_DMA_ADAPTER 119 NTAPI 120 VideoPortGetDmaAdapter(IN PVOID HwDeviceExtension, 121 IN PVP_DEVICE_DESCRIPTION VpDeviceExtension) 122 { 123 DEVICE_DESCRIPTION DeviceDescription; 124 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 125 ULONG NumberOfMapRegisters; 126 PVIP_DMA_ADAPTER Adapter; 127 PDMA_ADAPTER DmaAdapter; 128 129 /* allocate private adapter structure */ 130 Adapter = ExAllocatePool(NonPagedPool, sizeof(VIP_DMA_ADAPTER)); 131 if (!Adapter) 132 { 133 /* failed to allocate adapter structure */ 134 return NULL; 135 } 136 137 /* Zero the structure */ 138 RtlZeroMemory(&DeviceDescription, 139 sizeof(DEVICE_DESCRIPTION)); 140 141 /* Initialize the structure */ 142 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION; 143 DeviceDescription.Master = TRUE; 144 DeviceDescription.DmaWidth = Width8Bits; 145 DeviceDescription.DmaSpeed = Compatible; 146 147 /* Copy data from caller's device extension */ 148 DeviceDescription.ScatterGather = VpDeviceExtension->ScatterGather; 149 DeviceDescription.Dma32BitAddresses = VpDeviceExtension->Dma32BitAddresses; 150 DeviceDescription.Dma64BitAddresses = VpDeviceExtension->Dma64BitAddresses; 151 DeviceDescription.MaximumLength = VpDeviceExtension->MaximumLength; 152 153 /* Copy data from the internal device extension */ 154 DeviceDescription.BusNumber = DeviceExtension->SystemIoBusNumber; 155 DeviceDescription.InterfaceType = DeviceExtension->AdapterInterfaceType; 156 157 /* acquire dma adapter */ 158 DmaAdapter = IoGetDmaAdapter(DeviceExtension->PhysicalDeviceObject, &DeviceDescription, &NumberOfMapRegisters); 159 if (!DmaAdapter) 160 { 161 /* failed to acquire dma */ 162 ExFreePool(Adapter); 163 return NULL; 164 } 165 166 /* store dma adapter */ 167 Adapter->Adapter = DmaAdapter; 168 169 /* store map register count */ 170 Adapter->MapRegisters = NumberOfMapRegisters; 171 172 /* store hw device extension */ 173 Adapter->HwDeviceExtension = HwDeviceExtension; 174 175 /* store in dma adapter list */ 176 InsertTailList(&DeviceExtension->DmaAdapterList, &Adapter->Entry); 177 178 /* return result */ 179 return (PVP_DMA_ADAPTER)Adapter; 180 } 181 182 /* 183 * @implemented 184 */ 185 VOID 186 NTAPI 187 VideoPortFreeCommonBuffer(IN PVOID HwDeviceExtension, 188 IN ULONG Length, 189 IN PVOID VirtualAddress, 190 IN PHYSICAL_ADDRESS LogicalAddress, 191 IN BOOLEAN CacheEnabled) 192 { 193 PVIP_DMA_ADAPTER VpDmaAdapter; 194 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 195 196 /* sanity check */ 197 ASSERT(!IsListEmpty(&DeviceExtension->DmaAdapterList)); 198 199 /* grab first dma adapter */ 200 VpDmaAdapter = (PVIP_DMA_ADAPTER)CONTAINING_RECORD(DeviceExtension->DmaAdapterList.Flink, VIP_DMA_ADAPTER, Entry); 201 202 /* sanity checks */ 203 ASSERT(VpDmaAdapter->HwDeviceExtension == HwDeviceExtension); 204 ASSERT(VpDmaAdapter->Adapter != NULL); 205 ASSERT(VpDmaAdapter->MapRegisters != 0); 206 207 VideoPortReleaseCommonBuffer(HwDeviceExtension, (PVP_DMA_ADAPTER)VpDmaAdapter, Length, LogicalAddress, VirtualAddress, CacheEnabled); 208 } 209 210 /* 211 * @implemented 212 */ 213 PVOID 214 NTAPI 215 VideoPortGetCommonBuffer(IN PVOID HwDeviceExtension, 216 IN ULONG DesiredLength, 217 IN ULONG Alignment, 218 OUT PPHYSICAL_ADDRESS LogicalAddress, 219 OUT PULONG pActualLength, 220 IN BOOLEAN CacheEnabled) 221 { 222 PVOID Result; 223 PVIP_DMA_ADAPTER VpDmaAdapter; 224 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 225 226 /* maximum palette size */ 227 if (DesiredLength > 262144) 228 { 229 /* size exceeded */ 230 return NULL; 231 } 232 233 if (IsListEmpty(&DeviceExtension->DmaAdapterList)) 234 { 235 /* no adapter available */ 236 return NULL; 237 } 238 239 /* grab first dma adapter */ 240 VpDmaAdapter = (PVIP_DMA_ADAPTER)CONTAINING_RECORD(DeviceExtension->DmaAdapterList.Flink, VIP_DMA_ADAPTER, Entry); 241 242 /* sanity checks */ 243 ASSERT(VpDmaAdapter->HwDeviceExtension == HwDeviceExtension); 244 ASSERT(VpDmaAdapter->Adapter != NULL); 245 ASSERT(VpDmaAdapter->MapRegisters != 0); 246 247 /* allocate common buffer */ 248 Result = VideoPortAllocateCommonBuffer(HwDeviceExtension, (PVP_DMA_ADAPTER)VpDmaAdapter, DesiredLength, LogicalAddress, CacheEnabled, NULL); 249 250 if (Result) 251 { 252 /* store length */ 253 *pActualLength = DesiredLength; 254 } 255 else 256 { 257 /* failed to allocate common buffer */ 258 *pActualLength = 0; 259 } 260 261 return Result; 262 } 263 264 /* 265 * @implemented 266 */ 267 BOOLEAN 268 NTAPI 269 VideoPortUnmapDmaMemory( 270 PVOID HwDeviceExtension, 271 PVOID VirtualAddress, 272 HANDLE ProcessHandle, 273 PDMA BoardMemoryHandle) 274 { 275 /* Deprecated */ 276 return FALSE; 277 } 278 279 /* 280 * @implemented 281 */ 282 PDMA 283 NTAPI 284 VideoPortMapDmaMemory(IN PVOID HwDeviceExtension, 285 IN PVIDEO_REQUEST_PACKET pVrp, 286 IN PHYSICAL_ADDRESS BoardAddress, 287 IN PULONG Length, 288 IN PULONG InIoSpace, 289 IN PVOID MappedUserEvent, 290 IN PVOID DisplayDriverEvent, 291 IN OUT PVOID *VirtualAddress) 292 { 293 /* Deprecated */ 294 return NULL; 295 } 296 297 /* 298 * @implemented 299 */ 300 VOID 301 NTAPI 302 VideoPortSetDmaContext(IN PVOID HwDeviceExtension, 303 OUT PDMA pDma, 304 IN PVOID InstanceContext) 305 { 306 /* Deprecated */ 307 return; 308 } 309 310 /* 311 * @implemented 312 */ 313 BOOLEAN 314 NTAPI 315 VideoPortSignalDmaComplete(IN PVOID HwDeviceExtension, 316 IN PDMA pDmaHandle) 317 { 318 /* Deprecated */ 319 return FALSE; 320 } 321 322 323 BOOLEAN 324 NTAPI 325 SyncScatterRoutine( 326 IN PVOID Context) 327 { 328 PDMA_START_CONTEXT StartContext = (PDMA_START_CONTEXT)Context; 329 330 StartContext->ExecuteDmaRoutine(StartContext->HwDeviceExtension, StartContext->VpDmaAdapter, (PVP_SCATTER_GATHER_LIST)StartContext->ScatterGatherList, StartContext->Context); 331 return TRUE; 332 } 333 334 VOID 335 NTAPI 336 ScatterAdapterControl( 337 IN PDEVICE_OBJECT *DeviceObject, 338 IN PIRP *Irp, 339 IN PSCATTER_GATHER_LIST ScatterGather, 340 IN PVOID Context) 341 { 342 PDMA_START_CONTEXT StartContext = (PDMA_START_CONTEXT)Context; 343 344 StartContext->ScatterGatherList = ScatterGather; 345 346 VideoPortSynchronizeExecution(StartContext->HwDeviceExtension, VpMediumPriority, SyncScatterRoutine, StartContext); 347 ExFreePool(StartContext); 348 } 349 350 /* 351 * @implemented 352 */ 353 VP_STATUS 354 NTAPI 355 VideoPortStartDma(IN PVOID HwDeviceExtension, 356 IN PVP_DMA_ADAPTER VpDmaAdapter, 357 IN PVOID Mdl, 358 IN ULONG Offset, 359 IN OUT PULONG pLength, 360 IN PEXECUTE_DMA ExecuteDmaRoutine, 361 IN PVOID Context, 362 IN BOOLEAN WriteToDevice) 363 { 364 NTSTATUS Status; 365 KIRQL OldIrql; 366 PDMA_START_CONTEXT StartContext; 367 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension); 368 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter; 369 370 StartContext = ExAllocatePool(NonPagedPool, sizeof(DMA_START_CONTEXT)); 371 if (!StartContext) 372 { 373 return ERROR_NOT_ENOUGH_MEMORY; 374 } 375 376 StartContext->Context = Context; 377 StartContext->ExecuteDmaRoutine = ExecuteDmaRoutine; 378 StartContext->HwDeviceExtension = HwDeviceExtension; 379 StartContext->VpDmaAdapter = VpDmaAdapter; 380 381 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 382 383 Status = Adapter->Adapter->DmaOperations->GetScatterGatherList(Adapter->Adapter, 384 DeviceExtension->PhysicalDeviceObject, 385 Mdl, 386 MmGetSystemAddressForMdl((PMDL)Mdl), 387 MmGetMdlByteCount((PMDL)Mdl), 388 (PDRIVER_LIST_CONTROL)ScatterAdapterControl, 389 StartContext, 390 WriteToDevice); 391 392 KeLowerIrql(OldIrql); 393 394 if (!NT_SUCCESS(Status)) 395 { 396 *pLength = 0; 397 ExFreePool(StartContext); 398 Status = ERROR_NOT_ENOUGH_MEMORY; 399 } 400 else 401 { 402 Status = NO_ERROR; 403 } 404 405 /* Return status */ 406 return Status; 407 } 408 409 /* 410 * @implemented 411 */ 412 PVOID 413 NTAPI 414 VideoPortGetDmaContext(IN PVOID HwDeviceExtension, 415 IN PDMA pDma) 416 { 417 /* Deprecated */ 418 return NULL; 419 } 420 421 /* 422 * @implemented 423 */ 424 PDMA 425 NTAPI 426 VideoPortDoDma(IN PVOID HwDeviceExtension, 427 IN PDMA pDma, 428 IN DMA_FLAGS DmaFlags) 429 { 430 /* Deprecated */ 431 return NULL; 432 } 433 434 /* 435 * @implemented 436 */ 437 PDMA 438 NTAPI 439 VideoPortAssociateEventsWithDmaHandle(IN PVOID HwDeviceExtension, 440 IN OUT PVIDEO_REQUEST_PACKET pVrp, 441 IN PVOID MappedUserEvent, 442 IN PVOID DisplayDriverEvent) 443 { 444 /* Deprecated */ 445 return NULL; 446 } 447 448 /* 449 * @implemented 450 */ 451 VP_STATUS 452 NTAPI 453 VideoPortCompleteDma(IN PVOID HwDeviceExtension, 454 IN PVP_DMA_ADAPTER VpDmaAdapter, 455 IN PVP_SCATTER_GATHER_LIST VpScatterGather, 456 IN BOOLEAN WriteToDevice) 457 { 458 KIRQL OldIrql; 459 PVIP_DMA_ADAPTER Adapter = (PVIP_DMA_ADAPTER)VpDmaAdapter; 460 461 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 462 Adapter->Adapter->DmaOperations->PutScatterGatherList(Adapter->Adapter, (PSCATTER_GATHER_LIST)VpScatterGather, WriteToDevice); 463 KeLowerIrql(OldIrql); 464 465 return NO_ERROR; 466 } 467