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
24 /* PRIVATE FUNCTIONS **********************************************************/
28 PDEVICE_OBJECT DeviceObject
,
29 PIO_STATUS_BLOCK IoStatusBlock
,
31 PIO_STACK_LOCATION Stack OPTIONAL
)
33 PDEVICE_OBJECT TopDeviceObject
;
34 PIO_STACK_LOCATION IrpSp
;
39 /* Always call the top of the device stack */
40 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
47 Irp
= IoBuildSynchronousFsdRequest(
56 /* PNP IRPs are always initialized with a status code of
57 STATUS_NOT_SUPPORTED */
58 Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
59 Irp
->IoStatus
.Information
= 0;
61 IrpSp
= IoGetNextIrpStackLocation(Irp
);
62 IrpSp
->MinorFunction
= MinorFunction
;
69 sizeof(Stack
->Parameters
));
72 Status
= IoCallDriver(TopDeviceObject
, Irp
);
73 if (Status
== STATUS_PENDING
)
75 KeWaitForSingleObject(
81 Status
= IoStatusBlock
->Status
;
84 ObDereferenceObject(TopDeviceObject
);
92 IN PVOID HwDeviceExtension
,
93 IN PVOID PhysicalContext
,
97 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
98 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
99 PHYSICAL_ADDRESS MappingAddr
= {{0, 0}};
100 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
103 TRACE_(VIDEOPRT
, "AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
104 PhysicalContext
, Pages
, Offset
);
106 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
107 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
108 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
110 Status
= AgpBusInterface
->CommitMemory(AgpBusInterface
->AgpContext
,
111 AgpMapping
->MapHandle
, Pages
, Offset
,
114 if (!NT_SUCCESS(Status
))
116 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n",
119 return NT_SUCCESS(Status
);
124 IN PVOID HwDeviceExtension
,
125 IN PVOID PhysicalContext
,
129 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
130 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
131 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
134 TRACE_(VIDEOPRT
, "AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
135 PhysicalContext
, Pages
, Offset
);
137 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
138 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
139 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
141 Status
= AgpBusInterface
->FreeMemory(AgpBusInterface
->AgpContext
,
142 AgpMapping
->MapHandle
, Pages
, Offset
);
143 if (!NT_SUCCESS(Status
))
145 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n",
151 IntAgpReleasePhysical(
152 IN PVOID HwDeviceExtension
,
153 IN PVOID PhysicalContext
)
155 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
156 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
157 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
160 TRACE_(VIDEOPRT
, "AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext
);
162 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
163 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
164 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
167 Status
= AgpBusInterface
->ReleaseMemory(AgpBusInterface
->AgpContext
,
168 AgpMapping
->MapHandle
);
169 if (!NT_SUCCESS(Status
))
171 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n",
176 ExFreePool(AgpMapping
);
179 PHYSICAL_ADDRESS NTAPI
180 IntAgpReservePhysical(
181 IN PVOID HwDeviceExtension
,
183 IN VIDEO_PORT_CACHE_TYPE Caching
,
184 OUT PVOID
*PhysicalContext
)
186 PHYSICAL_ADDRESS ZeroAddress
= {{0, 0}};
187 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
188 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
189 MEMORY_CACHING_TYPE MemCachingType
;
190 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
193 TRACE_(VIDEOPRT
, "AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages
, Caching
);
195 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
196 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
198 /* Translate memory caching type */
199 if (Caching
== VpNonCached
)
200 MemCachingType
= MmNonCached
;
201 else if (Caching
== VpCached
)
202 MemCachingType
= MmCached
;
203 else if (Caching
== VpWriteCombined
)
204 MemCachingType
= MmWriteCombined
;
207 WARN_(VIDEOPRT
, "Invalid caching type %d!\n", Caching
);
211 /* Allocate an AGP mapping structure */
212 AgpMapping
= ExAllocatePoolWithTag(PagedPool
,
213 sizeof(VIDEO_PORT_AGP_MAPPING
),
215 if (AgpMapping
== NULL
)
217 WARN_(VIDEOPRT
, "Out of memory! Couldn't allocate AGP mapping structure!\n");
220 RtlZeroMemory(AgpMapping
, sizeof(VIDEO_PORT_AGP_MAPPING
));
222 /* Reserve memory for the AGP bus */
223 Status
= AgpBusInterface
->ReserveMemory(AgpBusInterface
->AgpContext
,
226 &AgpMapping
->MapHandle
,
227 &AgpMapping
->PhysicalAddress
);
228 if (!NT_SUCCESS(Status
) || AgpMapping
->MapHandle
== NULL
)
230 ExFreePool(AgpMapping
);
231 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n",
236 /* Fill the rest of the AGP mapping */
237 AgpMapping
->NumberOfPages
= Pages
;
239 *PhysicalContext
= (PVOID
)AgpMapping
;
240 return AgpMapping
->PhysicalAddress
;
246 IN PVOID HwDeviceExtension
,
247 IN PVOID VirtualContext
,
251 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
252 PVOID BaseAddress
= NULL
;
253 PHYSICAL_ADDRESS PhysicalAddress
;
256 TRACE_(VIDEOPRT
, "AgpCommitVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
257 VirtualContext
, Pages
, Offset
);
259 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
261 /* I think the NT API provides no way of reserving a part of the address space
262 * and setting it up to map into a specified range of physical memory later.
263 * This means that we will have to release some of the reserved virtual memory
264 * and map the physical memory into it using MapViewOfSection.
266 * - blight (2004-12-21)
269 if (VirtualMapping
->ProcessHandle
== NULL
)
271 /* FIXME: not implemented */
273 else /* ProcessHandle != NULL */
275 /* Release some virtual memory */
276 SIZE_T Size
= Pages
* PAGE_SIZE
;
277 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
278 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
280 PhysicalAddress
= VirtualMapping
->AgpMapping
->PhysicalAddress
;
281 PhysicalAddress
.QuadPart
+= OffsetInBytes
;
283 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
286 if (!NT_SUCCESS(Status
))
288 WARN_(VIDEOPRT
, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status
);
291 ASSERT(Size
== Pages
* PAGE_SIZE
);
292 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
295 /* Map the physical memory into the released virtual memory area */
296 Status
= IntVideoPortMapPhysicalMemory(VirtualMapping
->ProcessHandle
,
301 if (!NT_SUCCESS(Status
))
303 WARN_(VIDEOPRT
, "Warning: IntVideoPortMapPhysicalMemory() failed: Status = 0x%x\n", Status
);
304 /* Reserve the released virtual memory area again */
305 Status
= ZwAllocateVirtualMemory(VirtualMapping
->ProcessHandle
,
306 &BaseAddress
, 0, &Size
, MEM_RESERVE
,
308 if (!NT_SUCCESS(Status
))
310 WARN_(VIDEOPRT
, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
311 /* FIXME: What to do now?? */
315 ASSERT(Size
== Pages
* PAGE_SIZE
);
316 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
320 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
329 IN PVOID HwDeviceExtension
,
330 IN PVOID VirtualContext
,
334 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
335 PVOID BaseAddress
= NULL
;
338 TRACE_(VIDEOPRT
, "AgpFreeVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
339 VirtualContext
, Pages
, Offset
);
341 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
343 if (VirtualMapping
->ProcessHandle
== NULL
)
345 /* FIXME: not implemented */
347 else /* ProcessHandle != NULL */
349 /* Unmap the section view */
350 SIZE_T Size
= Pages
* PAGE_SIZE
;
351 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
352 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
355 Status
= ZwUnmapViewOfSection(VirtualMapping
->ProcessHandle
, BaseAddress
);
356 if (!NT_SUCCESS(Status
))
358 WARN_(VIDEOPRT
, "Warning: ZwUnmapViewOfSection() failed: Status = 0x%x\n", Status
);
359 /* FIXME: What to do now?? */
364 /* And reserve the virtual memory area again */
365 Status
= ZwAllocateVirtualMemory(VirtualMapping
->ProcessHandle
,
366 &BaseAddress
, 0, &Size
, MEM_RESERVE
,
368 if (!NT_SUCCESS(Status
))
370 WARN_(VIDEOPRT
, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
371 /* FIXME: What to do now?? */
375 ASSERT(Size
== Pages
* PAGE_SIZE
);
376 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
382 IntAgpReleaseVirtual(
383 IN PVOID HwDeviceExtension
,
384 IN PVOID VirtualContext
)
386 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
389 TRACE_(VIDEOPRT
, "AgpReleaseVirtual - VirtualContext: 0x%x\n", VirtualContext
);
391 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
393 /* Release the virtual memory */
394 if (VirtualMapping
->ProcessHandle
== NULL
)
396 /* FIXME: not implemented */
398 else /* ProcessHandle != NULL */
400 /* Release the allocated virtual memory */
401 SIZE_T Size
= VirtualMapping
->AgpMapping
->NumberOfPages
* PAGE_SIZE
;
402 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
403 &VirtualMapping
->MappedAddress
,
405 if (!NT_SUCCESS(Status
))
407 WARN_(VIDEOPRT
, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status
);
412 ExFreePool(VirtualMapping
);
416 IntAgpReserveVirtual(
417 IN PVOID HwDeviceExtension
,
418 IN HANDLE ProcessHandle
,
419 IN PVOID PhysicalContext
,
420 OUT PVOID
*VirtualContext
)
422 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
423 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
427 TRACE_(VIDEOPRT
, "AgpReserveVirtual - ProcessHandle: 0x%x PhysicalContext: 0x%x\n",
428 ProcessHandle
, PhysicalContext
);
430 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
432 /* Allocate an AGP virtual mapping structure */
433 VirtualMapping
= ExAllocatePoolWithTag(PagedPool
,
434 sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING
),
436 if (VirtualMapping
== NULL
)
438 WARN_(VIDEOPRT
, "Out of memory! Couldn't allocate AGP virtual mapping structure!\n");
441 RtlZeroMemory(VirtualMapping
, sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING
));
443 /* Reserve a virtual memory area for the physical pages. */
444 if (ProcessHandle
== NULL
)
446 /* FIXME: What to do in this case? */
447 ExFreePool(VirtualMapping
);
450 else /* ProcessHandle != NULL */
452 /* Reserve memory for usermode */
453 SIZE_T Size
= AgpMapping
->NumberOfPages
* PAGE_SIZE
;
454 MappedAddress
= NULL
;
455 Status
= ZwAllocateVirtualMemory(ProcessHandle
, &MappedAddress
, 0, &Size
,
456 MEM_RESERVE
, PAGE_NOACCESS
);
457 if (!NT_SUCCESS(Status
))
459 ExFreePool(VirtualMapping
);
460 WARN_(VIDEOPRT
, "ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
465 /* Fill the AGP virtual mapping */
466 VirtualMapping
->AgpMapping
= AgpMapping
;
467 VirtualMapping
->ProcessHandle
= ProcessHandle
;
468 VirtualMapping
->MappedAddress
= MappedAddress
;
470 *VirtualContext
= (PVOID
)VirtualMapping
;
471 return MappedAddress
;
477 IN PVOID HwDeviceExtension
,
480 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
481 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
483 TRACE_(VIDEOPRT
, "AgpSetRate - Rate: %d\n", Rate
);
485 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
486 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
488 return NT_SUCCESS(AgpBusInterface
->SetRate(AgpBusInterface
->AgpContext
, Rate
));
494 IN PVOID HwDeviceExtension
,
495 IN OUT PINTERFACE Interface
)
497 IO_STATUS_BLOCK IoStatusBlock
;
498 IO_STACK_LOCATION IoStack
;
500 PVIDEO_PORT_AGP_INTERFACE_2 AgpInterface
;
501 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
502 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
504 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
505 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
506 AgpInterface
= (PVIDEO_PORT_AGP_INTERFACE_2
)Interface
;
508 ASSERT(Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_2
||
509 Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
);
510 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
512 ASSERT(Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE_2
));
514 else if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
516 ASSERT(Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE
));
519 if (DeviceExtension
->NextDeviceObject
== NULL
)
521 WARN_(VIDEOPRT
, "DeviceExtension->NextDeviceObject is NULL!\n");
522 return STATUS_UNSUCCESSFUL
;
525 /* Query the interface from the AGP bus driver */
526 if (DeviceExtension
->AgpInterface
.Size
== 0)
528 AgpBusInterface
->Size
= sizeof(AGP_BUS_INTERFACE_STANDARD
);
529 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
530 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V1
;
531 else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */
532 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V2
;
533 IoStack
.Parameters
.QueryInterface
.Size
= AgpBusInterface
->Size
;
534 IoStack
.Parameters
.QueryInterface
.Version
= AgpBusInterface
->Version
;
535 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)AgpBusInterface
;
536 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
537 &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD
;
538 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
539 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
540 if (!NT_SUCCESS(Status
))
542 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status
);
545 INFO_(VIDEOPRT
, "Got AGP driver interface!\n");
548 /* FIXME: Not sure if we should wrap the reference/dereference functions */
549 AgpInterface
->Context
= AgpBusInterface
->AgpContext
;
550 AgpInterface
->InterfaceReference
= AgpBusInterface
->InterfaceReference
;
551 AgpInterface
->InterfaceDereference
= AgpBusInterface
->InterfaceDereference
;
552 AgpInterface
->AgpReservePhysical
= IntAgpReservePhysical
;
553 AgpInterface
->AgpReleasePhysical
= IntAgpReleasePhysical
;
554 AgpInterface
->AgpCommitPhysical
= IntAgpCommitPhysical
;
555 AgpInterface
->AgpFreePhysical
= IntAgpFreePhysical
;
556 AgpInterface
->AgpReserveVirtual
= IntAgpReserveVirtual
;
557 AgpInterface
->AgpReleaseVirtual
= IntAgpReleaseVirtual
;
558 AgpInterface
->AgpCommitVirtual
= IntAgpCommitVirtual
;
559 AgpInterface
->AgpFreeVirtual
= IntAgpFreeVirtual
;
560 AgpInterface
->AgpAllocationLimit
= 0x1000000; /* FIXME: using 16 MB for now */
562 if (AgpInterface
->Version
>= VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
564 AgpInterface
->AgpSetRate
= IntAgpSetRate
;
567 return STATUS_SUCCESS
;