4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 /* PRIVATE FUNCTIONS **********************************************************/
31 PDEVICE_OBJECT DeviceObject
,
32 PIO_STATUS_BLOCK IoStatusBlock
,
34 PIO_STACK_LOCATION Stack OPTIONAL
)
36 PDEVICE_OBJECT TopDeviceObject
;
37 PIO_STACK_LOCATION IrpSp
;
42 /* Always call the top of the device stack */
43 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
50 Irp
= IoBuildSynchronousFsdRequest(
59 /* PNP IRPs are always initialized with a status code of
60 STATUS_NOT_SUPPORTED */
61 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
62 Irp
->IoStatus
.Information
= 0;
64 IrpSp
= IoGetNextIrpStackLocation(Irp
);
65 IrpSp
->MinorFunction
= MinorFunction
;
72 sizeof(Stack
->Parameters
));
75 Status
= IoCallDriver(TopDeviceObject
, Irp
);
76 if (Status
== STATUS_PENDING
)
78 KeWaitForSingleObject(
84 Status
= IoStatusBlock
->Status
;
87 ObDereferenceObject(TopDeviceObject
);
95 IN PVOID HwDeviceExtension
,
96 IN PVOID PhysicalContext
,
100 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
101 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
102 PHYSICAL_ADDRESS MappingAddr
= {{0, 0}};
103 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
106 TRACE_(VIDEOPRT
, "AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
107 PhysicalContext
, Pages
, Offset
);
109 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
110 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
111 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
113 Status
= AgpBusInterface
->CommitMemory(AgpBusInterface
->AgpContext
,
114 AgpMapping
->MapHandle
, Pages
, Offset
,
117 if (!NT_SUCCESS(Status
))
119 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n",
122 return NT_SUCCESS(Status
);
127 IN PVOID HwDeviceExtension
,
128 IN PVOID PhysicalContext
,
132 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
133 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
134 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
137 TRACE_(VIDEOPRT
, "AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
138 PhysicalContext
, Pages
, Offset
);
140 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
141 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
142 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
144 Status
= AgpBusInterface
->FreeMemory(AgpBusInterface
->AgpContext
,
145 AgpMapping
->MapHandle
, Pages
, Offset
);
146 if (!NT_SUCCESS(Status
))
148 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n",
154 IntAgpReleasePhysical(
155 IN PVOID HwDeviceExtension
,
156 IN PVOID PhysicalContext
)
158 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
159 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
160 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
163 TRACE_(VIDEOPRT
, "AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext
);
165 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
166 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
167 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
170 Status
= AgpBusInterface
->ReleaseMemory(AgpBusInterface
->AgpContext
,
171 AgpMapping
->MapHandle
);
172 if (!NT_SUCCESS(Status
))
174 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n",
179 ExFreePool(AgpMapping
);
182 PHYSICAL_ADDRESS NTAPI
183 IntAgpReservePhysical(
184 IN PVOID HwDeviceExtension
,
186 IN VIDEO_PORT_CACHE_TYPE Caching
,
187 OUT PVOID
*PhysicalContext
)
189 PHYSICAL_ADDRESS ZeroAddress
= {{0, 0}};
190 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
191 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
192 MEMORY_CACHING_TYPE MemCachingType
;
193 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
196 TRACE_(VIDEOPRT
, "AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages
, Caching
);
198 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
199 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
201 /* Translate memory caching type */
202 if (Caching
== VpNonCached
)
203 MemCachingType
= MmNonCached
;
204 else if (Caching
== VpCached
)
205 MemCachingType
= MmCached
;
206 else if (Caching
== VpWriteCombined
)
207 MemCachingType
= MmWriteCombined
;
210 WARN_(VIDEOPRT
, "Invalid caching type %d!\n", Caching
);
214 /* Allocate an AGP mapping structure */
215 AgpMapping
= ExAllocatePoolWithTag(PagedPool
,
216 sizeof(VIDEO_PORT_AGP_MAPPING
),
218 if (AgpMapping
== NULL
)
220 WARN_(VIDEOPRT
, "Out of memory! Couldn't allocate AGP mapping structure!\n");
223 RtlZeroMemory(AgpMapping
, sizeof(VIDEO_PORT_AGP_MAPPING
));
225 /* Reserve memory for the AGP bus */
226 Status
= AgpBusInterface
->ReserveMemory(AgpBusInterface
->AgpContext
,
229 &AgpMapping
->MapHandle
,
230 &AgpMapping
->PhysicalAddress
);
231 if (!NT_SUCCESS(Status
) || AgpMapping
->MapHandle
== NULL
)
233 ExFreePool(AgpMapping
);
234 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n",
239 /* Fill the rest of the AGP mapping */
240 AgpMapping
->NumberOfPages
= Pages
;
242 *PhysicalContext
= (PVOID
)AgpMapping
;
243 return AgpMapping
->PhysicalAddress
;
249 IN PVOID HwDeviceExtension
,
250 IN PVOID VirtualContext
,
254 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
255 PVOID BaseAddress
= NULL
;
256 PHYSICAL_ADDRESS PhysicalAddress
;
259 TRACE_(VIDEOPRT
, "AgpCommitVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
260 VirtualContext
, Pages
, Offset
);
262 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
264 /* I think the NT API provides no way of reserving a part of the address space
265 * and setting it up to map into a specified range of physical memory later.
266 * This means that we will have to release some of the reserved virtual memory
267 * and map the physical memory into it using MapViewOfSection.
269 * - blight (2004-12-21)
272 if (VirtualMapping
->ProcessHandle
== NULL
)
274 /* FIXME: not implemented */
276 else /* ProcessHandle != NULL */
278 /* Release some virtual memory */
279 SIZE_T Size
= Pages
* PAGE_SIZE
;
280 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
281 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
283 PhysicalAddress
= VirtualMapping
->AgpMapping
->PhysicalAddress
;
284 PhysicalAddress
.QuadPart
+= OffsetInBytes
;
286 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
289 if (!NT_SUCCESS(Status
))
291 WARN_(VIDEOPRT
, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status
);
294 ASSERT(Size
== Pages
* PAGE_SIZE
);
295 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
298 /* Map the physical memory into the released virtual memory area */
299 Status
= IntVideoPortMapPhysicalMemory(VirtualMapping
->ProcessHandle
,
304 if (!NT_SUCCESS(Status
))
306 WARN_(VIDEOPRT
, "Warning: IntVideoPortMapPhysicalMemory() failed: Status = 0x%x\n", Status
);
307 /* Reserve the released virtual memory area again */
308 Status
= ZwAllocateVirtualMemory(VirtualMapping
->ProcessHandle
,
309 &BaseAddress
, 0, &Size
, MEM_RESERVE
,
311 if (!NT_SUCCESS(Status
))
313 WARN_(VIDEOPRT
, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
314 /* FIXME: What to do now?? */
318 ASSERT(Size
== Pages
* PAGE_SIZE
);
319 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
323 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
332 IN PVOID HwDeviceExtension
,
333 IN PVOID VirtualContext
,
337 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
338 PVOID BaseAddress
= NULL
;
341 TRACE_(VIDEOPRT
, "AgpFreeVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
342 VirtualContext
, Pages
, Offset
);
344 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
346 if (VirtualMapping
->ProcessHandle
== NULL
)
348 /* FIXME: not implemented */
350 else /* ProcessHandle != NULL */
352 /* Unmap the section view */
353 SIZE_T Size
= Pages
* PAGE_SIZE
;
354 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
355 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
358 Status
= ZwUnmapViewOfSection(VirtualMapping
->ProcessHandle
, BaseAddress
);
359 if (!NT_SUCCESS(Status
))
361 WARN_(VIDEOPRT
, "Warning: ZwUnmapViewOfSection() failed: Status = 0x%x\n", Status
);
362 /* FIXME: What to do now?? */
367 /* And reserve the virtual memory area again */
368 Status
= ZwAllocateVirtualMemory(VirtualMapping
->ProcessHandle
,
369 &BaseAddress
, 0, &Size
, MEM_RESERVE
,
371 if (!NT_SUCCESS(Status
))
373 WARN_(VIDEOPRT
, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
374 /* FIXME: What to do now?? */
378 ASSERT(Size
== Pages
* PAGE_SIZE
);
379 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
385 IntAgpReleaseVirtual(
386 IN PVOID HwDeviceExtension
,
387 IN PVOID VirtualContext
)
389 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
392 TRACE_(VIDEOPRT
, "AgpReleaseVirtual - VirtualContext: 0x%x\n", VirtualContext
);
394 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
396 /* Release the virtual memory */
397 if (VirtualMapping
->ProcessHandle
== NULL
)
399 /* FIXME: not implemented */
401 else /* ProcessHandle != NULL */
403 /* Release the allocated virtual memory */
404 SIZE_T Size
= VirtualMapping
->AgpMapping
->NumberOfPages
* PAGE_SIZE
;
405 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
406 &VirtualMapping
->MappedAddress
,
408 if (!NT_SUCCESS(Status
))
410 WARN_(VIDEOPRT
, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status
);
415 ExFreePool(VirtualMapping
);
419 IntAgpReserveVirtual(
420 IN PVOID HwDeviceExtension
,
421 IN HANDLE ProcessHandle
,
422 IN PVOID PhysicalContext
,
423 OUT PVOID
*VirtualContext
)
425 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
426 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
430 TRACE_(VIDEOPRT
, "AgpReserveVirtual - ProcessHandle: 0x%x PhysicalContext: 0x%x\n",
431 ProcessHandle
, PhysicalContext
);
433 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
435 /* Allocate an AGP virtual mapping structure */
436 VirtualMapping
= ExAllocatePoolWithTag(PagedPool
,
437 sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING
),
439 if (VirtualMapping
== NULL
)
441 WARN_(VIDEOPRT
, "Out of memory! Couldn't allocate AGP virtual mapping structure!\n");
444 RtlZeroMemory(VirtualMapping
, sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING
));
446 /* Reserve a virtual memory area for the physical pages. */
447 if (ProcessHandle
== NULL
)
449 /* FIXME: What to do in this case? */
450 ExFreePool(VirtualMapping
);
453 else /* ProcessHandle != NULL */
455 /* Reserve memory for usermode */
456 SIZE_T Size
= AgpMapping
->NumberOfPages
* PAGE_SIZE
;
457 MappedAddress
= NULL
;
458 Status
= ZwAllocateVirtualMemory(ProcessHandle
, &MappedAddress
, 0, &Size
,
459 MEM_RESERVE
, PAGE_NOACCESS
);
460 if (!NT_SUCCESS(Status
))
462 ExFreePool(VirtualMapping
);
463 WARN_(VIDEOPRT
, "ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
468 /* Fill the AGP virtual mapping */
469 VirtualMapping
->AgpMapping
= AgpMapping
;
470 VirtualMapping
->ProcessHandle
= ProcessHandle
;
471 VirtualMapping
->MappedAddress
= MappedAddress
;
473 *VirtualContext
= (PVOID
)VirtualMapping
;
474 return MappedAddress
;
480 IN PVOID HwDeviceExtension
,
483 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
484 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
486 TRACE_(VIDEOPRT
, "AgpSetRate - Rate: %d\n", Rate
);
488 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
489 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
491 return NT_SUCCESS(AgpBusInterface
->SetRate(AgpBusInterface
->AgpContext
, Rate
));
497 IN PVOID HwDeviceExtension
,
498 IN OUT PINTERFACE Interface
)
500 IO_STATUS_BLOCK IoStatusBlock
;
501 IO_STACK_LOCATION IoStack
;
503 PVIDEO_PORT_AGP_INTERFACE_2 AgpInterface
;
504 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
505 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
507 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
508 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
509 AgpInterface
= (PVIDEO_PORT_AGP_INTERFACE_2
)Interface
;
511 ASSERT(Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_2
||
512 Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
);
513 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
515 ASSERT(Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE_2
));
517 else if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
519 ASSERT(Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE
));
522 if (DeviceExtension
->NextDeviceObject
== NULL
)
524 WARN_(VIDEOPRT
, "DeviceExtension->NextDeviceObject is NULL!\n");
525 return STATUS_UNSUCCESSFUL
;
528 /* Query the interface from the AGP bus driver */
529 if (DeviceExtension
->AgpInterface
.Size
== 0)
531 AgpBusInterface
->Size
= sizeof(AGP_BUS_INTERFACE_STANDARD
);
532 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
533 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V1
;
534 else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */
535 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V2
;
536 IoStack
.Parameters
.QueryInterface
.Size
= AgpBusInterface
->Size
;
537 IoStack
.Parameters
.QueryInterface
.Version
= AgpBusInterface
->Version
;
538 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)AgpBusInterface
;
539 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
540 &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD
;
541 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
542 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
543 if (!NT_SUCCESS(Status
))
545 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status
);
548 INFO_(VIDEOPRT
, "Got AGP driver interface!\n");
551 /* FIXME: Not sure if we should wrap the reference/dereference functions */
552 AgpInterface
->Context
= AgpBusInterface
->AgpContext
;
553 AgpInterface
->InterfaceReference
= AgpBusInterface
->InterfaceReference
;
554 AgpInterface
->InterfaceDereference
= AgpBusInterface
->InterfaceDereference
;
555 AgpInterface
->AgpReservePhysical
= IntAgpReservePhysical
;
556 AgpInterface
->AgpReleasePhysical
= IntAgpReleasePhysical
;
557 AgpInterface
->AgpCommitPhysical
= IntAgpCommitPhysical
;
558 AgpInterface
->AgpFreePhysical
= IntAgpFreePhysical
;
559 AgpInterface
->AgpReserveVirtual
= IntAgpReserveVirtual
;
560 AgpInterface
->AgpReleaseVirtual
= IntAgpReleaseVirtual
;
561 AgpInterface
->AgpCommitVirtual
= IntAgpCommitVirtual
;
562 AgpInterface
->AgpFreeVirtual
= IntAgpFreeVirtual
;
563 AgpInterface
->AgpAllocationLimit
= 0x1000000; /* FIXME: using 16 MB for now */
565 if (AgpInterface
->Version
>= VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
567 AgpInterface
->AgpSetRate
= IntAgpSetRate
;
570 return STATUS_SUCCESS
;