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 Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 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 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; see the file COPYING.LIB.
18 * If not, write to the Free Software Foundation,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include <ddk/wdmguid.h>
28 /* PRIVATE FUNCTIONS **********************************************************/
32 PDEVICE_OBJECT DeviceObject
,
33 PIO_STATUS_BLOCK IoStatusBlock
,
35 PIO_STACK_LOCATION Stack OPTIONAL
)
37 PDEVICE_OBJECT TopDeviceObject
;
38 PIO_STACK_LOCATION IrpSp
;
43 /* Always call the top of the device stack */
44 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
51 Irp
= IoBuildSynchronousFsdRequest(
60 /* PNP IRPs are always initialized with a status code of
61 STATUS_NOT_IMPLEMENTED */
62 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
63 Irp
->IoStatus
.Information
= 0;
65 IrpSp
= IoGetNextIrpStackLocation(Irp
);
66 IrpSp
->MinorFunction
= MinorFunction
;
73 sizeof(Stack
->Parameters
));
76 Status
= IoCallDriver(TopDeviceObject
, Irp
);
77 if (Status
== STATUS_PENDING
)
79 KeWaitForSingleObject(
85 Status
= IoStatusBlock
->Status
;
88 ObDereferenceObject(TopDeviceObject
);
96 IN PVOID HwDeviceExtension
,
97 IN PVOID PhysicalContext
,
101 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
102 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
103 PHYSICAL_ADDRESS MappingAddr
= {{0}};
104 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
107 DPRINT("AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
108 PhysicalContext
, Pages
, Offset
);
110 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
111 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
112 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
114 Status
= AgpBusInterface
->CommitMemory(AgpBusInterface
->AgpContext
,
115 AgpMapping
->MapHandle
, Pages
, Offset
,
118 if (!NT_SUCCESS(Status
))
120 DPRINT1("Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n",
123 return NT_SUCCESS(Status
);
128 IN PVOID HwDeviceExtension
,
129 IN PVOID PhysicalContext
,
133 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
134 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
135 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
138 DPRINT("AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
139 PhysicalContext
, Pages
, Offset
);
141 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
142 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
143 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
145 Status
= AgpBusInterface
->FreeMemory(AgpBusInterface
->AgpContext
,
146 AgpMapping
->MapHandle
, Pages
, Offset
);
147 if (!NT_SUCCESS(Status
))
149 DPRINT1("Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n",
155 IntAgpReleasePhysical(
156 IN PVOID HwDeviceExtension
,
157 IN PVOID PhysicalContext
)
159 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
160 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
161 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
164 DPRINT("AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext
);
166 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
167 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
168 AgpMapping
= (PVIDEO_PORT_AGP_MAPPING
)PhysicalContext
;
171 Status
= AgpBusInterface
->ReleaseMemory(AgpBusInterface
->AgpContext
,
172 AgpMapping
->MapHandle
);
173 if (!NT_SUCCESS(Status
))
175 DPRINT1("Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n",
180 ExFreePool(AgpMapping
);
183 PHYSICAL_ADDRESS STDCALL
184 IntAgpReservePhysical(
185 IN PVOID HwDeviceExtension
,
187 IN VIDEO_PORT_CACHE_TYPE Caching
,
188 OUT PVOID
*PhysicalContext
)
190 PHYSICAL_ADDRESS ZeroAddress
= {{0}};
191 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension
;
192 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface
;
193 MEMORY_CACHING_TYPE MemCachingType
;
194 PVIDEO_PORT_AGP_MAPPING AgpMapping
;
197 DPRINT("AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages
, Caching
);
199 DeviceExtension
= VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension
);
200 AgpBusInterface
= &DeviceExtension
->AgpInterface
;
202 /* Translate memory caching type */
203 if (Caching
== VpNonCached
)
204 MemCachingType
= MmNonCached
;
205 else if (Caching
== VpCached
)
206 MemCachingType
= MmCached
;
207 else if (Caching
== VpWriteCombined
)
208 MemCachingType
= MmWriteCombined
;
211 DPRINT1("Invalid caching type %d!\n", Caching
);
215 /* Allocate an AGP mapping structure */
216 AgpMapping
= ExAllocatePoolWithTag(PagedPool
,
217 sizeof(VIDEO_PORT_AGP_MAPPING
),
219 if (AgpMapping
== NULL
)
221 DPRINT1("Out of memory! Couldn't allocate AGP mapping structure!\n");
224 RtlZeroMemory(AgpMapping
, sizeof(VIDEO_PORT_AGP_MAPPING
));
226 /* Reserve memory for the AGP bus */
227 Status
= AgpBusInterface
->ReserveMemory(AgpBusInterface
->AgpContext
,
230 &AgpMapping
->MapHandle
,
231 &AgpMapping
->PhysicalAddress
);
232 if (!NT_SUCCESS(Status
) || AgpMapping
->MapHandle
== NULL
)
234 ExFreePool(AgpMapping
);
235 DPRINT1("Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n",
240 /* Fill the rest of the AGP mapping */
241 AgpMapping
->NumberOfPages
= Pages
;
243 *PhysicalContext
= (PVOID
)AgpMapping
;
244 return AgpMapping
->PhysicalAddress
;
250 IN PVOID HwDeviceExtension
,
251 IN PVOID VirtualContext
,
255 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping
;
256 PVOID BaseAddress
= NULL
;
259 DPRINT("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 ULONG Size
= Pages
* PAGE_SIZE
;
280 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
281 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
283 PHYSICAL_ADDRESS PhysicalAddress
= VirtualMapping
->AgpMapping
->PhysicalAddress
;
284 PhysicalAddress
.QuadPart
+= OffsetInBytes
;
286 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
289 if (!NT_SUCCESS(Status
))
291 DPRINT1("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 DPRINT1("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 DPRINT1("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 DPRINT("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 ULONG 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 DPRINT1("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 DPRINT1("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 DPRINT("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 ULONG Size
= VirtualMapping
->AgpMapping
->NumberOfPages
* PAGE_SIZE
;
405 Status
= ZwFreeVirtualMemory(VirtualMapping
->ProcessHandle
,
406 &VirtualMapping
->MappedAddress
,
408 if (!NT_SUCCESS(Status
))
410 DPRINT1("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 DPRINT("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 DPRINT1("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 ULONG 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 DPRINT("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 DPRINT("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
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE_2
)) ||
513 (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
&&
514 Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE
)));
516 if (DeviceExtension
->NextDeviceObject
== NULL
)
518 DPRINT("DeviceExtension->NextDeviceObject is NULL!\n");
519 return STATUS_UNSUCCESSFUL
;
522 /* Query the interface from the AGP bus driver */
523 if (DeviceExtension
->AgpInterface
.Size
== 0)
525 AgpBusInterface
->Size
= sizeof(AGP_BUS_INTERFACE_STANDARD
);
526 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
527 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V1
;
528 else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */
529 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V2
;
530 IoStack
.Parameters
.QueryInterface
.Size
= AgpBusInterface
->Size
;
531 IoStack
.Parameters
.QueryInterface
.Version
= AgpBusInterface
->Version
;
532 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)AgpBusInterface
;
533 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
534 &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD
;
535 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
536 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
537 if (!NT_SUCCESS(Status
))
539 DPRINT("IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status
);
542 DPRINT("Got AGP driver interface!\n");
545 /* FIXME: Not sure if we should wrap the reference/dereference functions */
546 AgpInterface
->Context
= AgpBusInterface
->AgpContext
;
547 AgpInterface
->InterfaceReference
= AgpBusInterface
->InterfaceReference
;
548 AgpInterface
->InterfaceDereference
= AgpBusInterface
->InterfaceDereference
;
549 AgpInterface
->AgpReservePhysical
= IntAgpReservePhysical
;
550 AgpInterface
->AgpReleasePhysical
= IntAgpReleasePhysical
;
551 AgpInterface
->AgpCommitPhysical
= IntAgpCommitPhysical
;
552 AgpInterface
->AgpFreePhysical
= IntAgpFreePhysical
;
553 AgpInterface
->AgpReserveVirtual
= IntAgpReserveVirtual
;
554 AgpInterface
->AgpReleaseVirtual
= IntAgpReleaseVirtual
;
555 AgpInterface
->AgpCommitVirtual
= IntAgpCommitVirtual
;
556 AgpInterface
->AgpFreeVirtual
= IntAgpFreeVirtual
;
557 AgpInterface
->AgpAllocationLimit
= 0x1000000; /* FIXME: using 16 MB for now */
559 if (AgpInterface
->Version
>= VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
561 AgpInterface
->AgpSetRate
= IntAgpSetRate
;
564 return STATUS_SUCCESS
;