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
26 /* PRIVATE FUNCTIONS **********************************************************/
30 PDEVICE_OBJECT DeviceObject
,
31 PIO_STATUS_BLOCK IoStatusBlock
,
33 PIO_STACK_LOCATION Stack OPTIONAL
)
35 PDEVICE_OBJECT TopDeviceObject
;
36 PIO_STACK_LOCATION IrpSp
;
41 /* Always call the top of the device stack */
42 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
49 Irp
= IoBuildSynchronousFsdRequest(
58 /* PNP IRPs are always initialized with a status code of
59 STATUS_NOT_IMPLEMENTED */
60 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
61 Irp
->IoStatus
.Information
= 0;
63 IrpSp
= IoGetNextIrpStackLocation(Irp
);
64 IrpSp
->MinorFunction
= MinorFunction
;
71 sizeof(Stack
->Parameters
));
74 Status
= IoCallDriver(TopDeviceObject
, Irp
);
75 if (Status
== STATUS_PENDING
)
77 KeWaitForSingleObject(
83 Status
= IoStatusBlock
->Status
;
86 ObDereferenceObject(TopDeviceObject
);
94 IN PVOID HwDeviceExtension
,
95 IN PVOID PhysicalContext
,
99 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
100 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
101 PHYSICAL_ADDRESS MappingAddr
= {{0, 0}};
102 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
105 TRACE_(VIDEOPRT
, "AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
106 PhysicalContext
, Pages
, Offset
);
108 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
109 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
110 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
112 Status
= AgpBusInterface
->CommitMemory(AgpBusInterface
->AgpContext
,
113 AgpMapping
->MapHandle
, Pages
, Offset
,
116 if (!NT_SUCCESS(Status
))
118 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n",
121 return NT_SUCCESS(Status
);
126 IN PVOID HwDeviceExtension
,
127 IN PVOID PhysicalContext
,
131 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
132 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
133 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
136 TRACE_(VIDEOPRT
, "AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
137 PhysicalContext
, Pages
, Offset
);
139 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
140 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
141 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
143 Status
= AgpBusInterface
->FreeMemory(AgpBusInterface
->AgpContext
,
144 AgpMapping
->MapHandle
, Pages
, Offset
);
145 if (!NT_SUCCESS(Status
))
147 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n",
153 IntAgpReleasePhysical(
154 IN PVOID HwDeviceExtension
,
155 IN PVOID PhysicalContext
)
157 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
158 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
159 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
162 TRACE_(VIDEOPRT
, "AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext
);
164 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
165 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
166 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
169 Status
= AgpBusInterface
->ReleaseMemory(AgpBusInterface
->AgpContext
,
170 AgpMapping
->MapHandle
);
171 if (!NT_SUCCESS(Status
))
173 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n",
178 ExFreePool(AgpMapping
);
181 PHYSICAL_ADDRESS NTAPI
182 IntAgpReservePhysical(
183 IN PVOID HwDeviceExtension
,
185 IN VIDEO_PORT_CACHE_TYPE Caching
,
186 OUT PVOID
*PhysicalContext
)
188 PHYSICAL_ADDRESS ZeroAddress
= {{0, 0}};
189 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
190 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
191 MEMORY_CACHING_TYPE MemCachingType
;
192 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
195 TRACE_(VIDEOPRT
, "AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages
, Caching
);
197 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
198 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
200 /* Translate memory caching type */
201 if (Caching
== VpNonCached
)
202 MemCachingType
= MmNonCached
;
203 else if (Caching
== VpCached
)
204 MemCachingType
= MmCached
;
205 else if (Caching
== VpWriteCombined
)
206 MemCachingType
= MmWriteCombined
;
209 WARN_(VIDEOPRT
, "Invalid caching type %d!\n", Caching
);
213 /* Allocate an AGP mapping structure */
214 AgpMapping
= ExAllocatePoolWithTag(PagedPool
,
215 sizeof(VIDEO_PORT_AGP_MAPPING
),
217 if (AgpMapping
== NULL
)
219 WARN_(VIDEOPRT
, "Out of memory! Couldn't allocate AGP mapping structure!\n");
222 RtlZeroMemory(AgpMapping
, sizeof(VIDEO_PORT_AGP_MAPPING
));
224 /* Reserve memory for the AGP bus */
225 Status
= AgpBusInterface
->ReserveMemory(AgpBusInterface
->AgpContext
,
228 &AgpMapping
->MapHandle
,
229 &AgpMapping
->PhysicalAddress
);
230 if (!NT_SUCCESS(Status
) || AgpMapping
->MapHandle
== NULL
)
232 ExFreePool(AgpMapping
);
233 WARN_(VIDEOPRT
, "Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n",
238 /* Fill the rest of the AGP mapping */
239 AgpMapping
->NumberOfPages
= Pages
;
241 *PhysicalContext
= (PVOID
)AgpMapping
;
242 return AgpMapping
->PhysicalAddress
;
248 IN PVOID HwDeviceExtension
,
249 IN PVOID VirtualContext
,
253 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
254 PVOID BaseAddress
= NULL
;
255 PHYSICAL_ADDRESS PhysicalAddress
;
258 TRACE_(VIDEOPRT
, "AgpCommitVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
259 VirtualContext
, Pages
, Offset
);
261 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
263 /* I think the NT API provides no way of reserving a part of the address space
264 * and setting it up to map into a specified range of physical memory later.
265 * This means that we will have to release some of the reserved virtual memory
266 * and map the physical memory into it using MapViewOfSection.
268 * - blight (2004-12-21)
271 if (VirtualMapping
->ProcessHandle
== NULL
)
273 /* FIXME: not implemented */
275 else /* ProcessHandle != NULL */
277 /* Release some virtual memory */
278 SIZE_T Size
= Pages
* PAGE_SIZE
;
279 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
280 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
282 PhysicalAddress
= VirtualMapping
->AgpMapping
->PhysicalAddress
;
283 PhysicalAddress
.QuadPart
+= OffsetInBytes
;
285 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
288 if (!NT_SUCCESS(Status
))
290 WARN_(VIDEOPRT
, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status
);
293 ASSERT(Size
== Pages
* PAGE_SIZE
);
294 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
297 /* Map the physical memory into the released virtual memory area */
298 Status
= IntVideoPortMapPhysicalMemory(VirtualMapping
->ProcessHandle
,
303 if (!NT_SUCCESS(Status
))
305 WARN_(VIDEOPRT
, "Warning: IntVideoPortMapPhysicalMemory() failed: Status = 0x%x\n", Status
);
306 /* Reserve the released virtual memory area again */
307 Status
= ZwAllocateVirtualMemory(VirtualMapping
->ProcessHandle
,
308 &BaseAddress
, 0, &Size
, MEM_RESERVE
,
310 if (!NT_SUCCESS(Status
))
312 WARN_(VIDEOPRT
, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
313 /* FIXME: What to do now?? */
317 ASSERT(Size
== Pages
* PAGE_SIZE
);
318 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
322 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
331 IN PVOID HwDeviceExtension
,
332 IN PVOID VirtualContext
,
336 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
337 PVOID BaseAddress
= NULL
;
340 TRACE_(VIDEOPRT
, "AgpFreeVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
341 VirtualContext
, Pages
, Offset
);
343 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
345 if (VirtualMapping
->ProcessHandle
== NULL
)
347 /* FIXME: not implemented */
349 else /* ProcessHandle != NULL */
351 /* Unmap the section view */
352 SIZE_T Size
= Pages
* PAGE_SIZE
;
353 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
354 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
357 Status
= ZwUnmapViewOfSection(VirtualMapping
->ProcessHandle
, BaseAddress
);
358 if (!NT_SUCCESS(Status
))
360 WARN_(VIDEOPRT
, "Warning: ZwUnmapViewOfSection() failed: Status = 0x%x\n", Status
);
361 /* FIXME: What to do now?? */
366 /* And reserve the virtual memory area again */
367 Status
= ZwAllocateVirtualMemory(VirtualMapping
->ProcessHandle
,
368 &BaseAddress
, 0, &Size
, MEM_RESERVE
,
370 if (!NT_SUCCESS(Status
))
372 WARN_(VIDEOPRT
, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
373 /* FIXME: What to do now?? */
377 ASSERT(Size
== Pages
* PAGE_SIZE
);
378 ASSERT(BaseAddress
== (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
384 IntAgpReleaseVirtual(
385 IN PVOID HwDeviceExtension
,
386 IN PVOID VirtualContext
)
388 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
391 TRACE_(VIDEOPRT
, "AgpReleaseVirtual - VirtualContext: 0x%x\n", VirtualContext
);
393 VirtualMapping
= (PVIDEO_PORT_AGP_VIRTUAL_MAPPING
)VirtualContext
;
395 /* Release the virtual memory */
396 if (VirtualMapping
->ProcessHandle
== NULL
)
398 /* FIXME: not implemented */
400 else /* ProcessHandle != NULL */
402 /* Release the allocated virtual memory */
403 SIZE_T Size
= VirtualMapping
->AgpMapping
->NumberOfPages
* PAGE_SIZE
;
404 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
405 &VirtualMapping
->MappedAddress
,
407 if (!NT_SUCCESS(Status
))
409 WARN_(VIDEOPRT
, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status
);
414 ExFreePool(VirtualMapping
);
418 IntAgpReserveVirtual(
419 IN PVOID HwDeviceExtension
,
420 IN HANDLE ProcessHandle
,
421 IN PVOID PhysicalContext
,
422 OUT PVOID
*VirtualContext
)
424 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
425 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
429 TRACE_(VIDEOPRT
, "AgpReserveVirtual - ProcessHandle: 0x%x PhysicalContext: 0x%x\n",
430 ProcessHandle
, PhysicalContext
);
432 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
434 /* Allocate an AGP virtual mapping structure */
435 VirtualMapping
= ExAllocatePoolWithTag(PagedPool
,
436 sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING
),
438 if (VirtualMapping
== NULL
)
440 WARN_(VIDEOPRT
, "Out of memory! Couldn't allocate AGP virtual mapping structure!\n");
443 RtlZeroMemory(VirtualMapping
, sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING
));
445 /* Reserve a virtual memory area for the physical pages. */
446 if (ProcessHandle
== NULL
)
448 /* FIXME: What to do in this case? */
449 ExFreePool(VirtualMapping
);
452 else /* ProcessHandle != NULL */
454 /* Reserve memory for usermode */
455 SIZE_T Size
= AgpMapping
->NumberOfPages
* PAGE_SIZE
;
456 MappedAddress
= NULL
;
457 Status
= ZwAllocateVirtualMemory(ProcessHandle
, &MappedAddress
, 0, &Size
,
458 MEM_RESERVE
, PAGE_NOACCESS
);
459 if (!NT_SUCCESS(Status
))
461 ExFreePool(VirtualMapping
);
462 WARN_(VIDEOPRT
, "ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status
);
467 /* Fill the AGP virtual mapping */
468 VirtualMapping
->AgpMapping
= AgpMapping
;
469 VirtualMapping
->ProcessHandle
= ProcessHandle
;
470 VirtualMapping
->MappedAddress
= MappedAddress
;
472 *VirtualContext
= (PVOID
)VirtualMapping
;
473 return MappedAddress
;
479 IN PVOID HwDeviceExtension
,
482 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
483 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
485 TRACE_(VIDEOPRT
, "AgpSetRate - Rate: %d\n", Rate
);
487 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
488 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
490 return NT_SUCCESS(AgpBusInterface
->SetRate(AgpBusInterface
->AgpContext
, Rate
));
496 IN PVOID HwDeviceExtension
,
497 IN OUT PINTERFACE Interface
)
499 IO_STATUS_BLOCK IoStatusBlock
;
500 IO_STACK_LOCATION IoStack
;
502 PVIDEO_PORT_AGP_INTERFACE_2 AgpInterface
;
503 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
504 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
506 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
507 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
508 AgpInterface
= (PVIDEO_PORT_AGP_INTERFACE_2
)Interface
;
510 ASSERT(Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_2
||
511 Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
);
512 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
514 ASSERT(Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE_2
));
516 else if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
518 ASSERT(Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE
));
521 if (DeviceExtension
->NextDeviceObject
== NULL
)
523 WARN_(VIDEOPRT
, "DeviceExtension->NextDeviceObject is NULL!\n");
524 return STATUS_UNSUCCESSFUL
;
527 /* Query the interface from the AGP bus driver */
528 if (DeviceExtension
->AgpInterface
.Size
== 0)
530 AgpBusInterface
->Size
= sizeof(AGP_BUS_INTERFACE_STANDARD
);
531 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
532 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V1
;
533 else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */
534 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V2
;
535 IoStack
.Parameters
.QueryInterface
.Size
= AgpBusInterface
->Size
;
536 IoStack
.Parameters
.QueryInterface
.Version
= AgpBusInterface
->Version
;
537 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)AgpBusInterface
;
538 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
539 &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD
;
540 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
541 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
542 if (!NT_SUCCESS(Status
))
544 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status
);
547 INFO_(VIDEOPRT
, "Got AGP driver interface!\n");
550 /* FIXME: Not sure if we should wrap the reference/dereference functions */
551 AgpInterface
->Context
= AgpBusInterface
->AgpContext
;
552 AgpInterface
->InterfaceReference
= AgpBusInterface
->InterfaceReference
;
553 AgpInterface
->InterfaceDereference
= AgpBusInterface
->InterfaceDereference
;
554 AgpInterface
->AgpReservePhysical
= IntAgpReservePhysical
;
555 AgpInterface
->AgpReleasePhysical
= IntAgpReleasePhysical
;
556 AgpInterface
->AgpCommitPhysical
= IntAgpCommitPhysical
;
557 AgpInterface
->AgpFreePhysical
= IntAgpFreePhysical
;
558 AgpInterface
->AgpReserveVirtual
= IntAgpReserveVirtual
;
559 AgpInterface
->AgpReleaseVirtual
= IntAgpReleaseVirtual
;
560 AgpInterface
->AgpCommitVirtual
= IntAgpCommitVirtual
;
561 AgpInterface
->AgpFreeVirtual
= IntAgpFreeVirtual
;
562 AgpInterface
->AgpAllocationLimit
= 0x1000000; /* FIXME: using 16 MB for now */
564 if (AgpInterface
->Version
>= VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
566 AgpInterface
->AgpSetRate
= IntAgpSetRate
;
569 return STATUS_SUCCESS
;