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.
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_IMPLEMENTED */
61 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
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}};
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}};
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
;
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 ULONG Size
= Pages
* PAGE_SIZE
;
279 ULONG OffsetInBytes
= Offset
* PAGE_SIZE
;
280 BaseAddress
= (PVOID
)((ULONG_PTR
)VirtualMapping
->MappedAddress
+
282 PHYSICAL_ADDRESS 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 ULONG 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 ULONG 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 ULONG 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
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE_2
)) ||
512 (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
&&
513 Interface
->Size
>= sizeof(VIDEO_PORT_AGP_INTERFACE
)));
515 if (DeviceExtension
->NextDeviceObject
== NULL
)
517 WARN_(VIDEOPRT
, "DeviceExtension->NextDeviceObject is NULL!\n");
518 return STATUS_UNSUCCESSFUL
;
521 /* Query the interface from the AGP bus driver */
522 if (DeviceExtension
->AgpInterface
.Size
== 0)
524 AgpBusInterface
->Size
= sizeof(AGP_BUS_INTERFACE_STANDARD
);
525 if (Interface
->Version
== VIDEO_PORT_AGP_INTERFACE_VERSION_1
)
526 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V1
;
527 else /* if (InterfaceVersion == VIDEO_PORT_AGP_INTERFACE_VERSION_2) */
528 AgpBusInterface
->Version
= AGP_BUS_INTERFACE_V2
;
529 IoStack
.Parameters
.QueryInterface
.Size
= AgpBusInterface
->Size
;
530 IoStack
.Parameters
.QueryInterface
.Version
= AgpBusInterface
->Version
;
531 IoStack
.Parameters
.QueryInterface
.Interface
= (PINTERFACE
)AgpBusInterface
;
532 IoStack
.Parameters
.QueryInterface
.InterfaceType
=
533 &GUID_AGP_TARGET_BUS_INTERFACE_STANDARD
;
534 Status
= IopInitiatePnpIrp(DeviceExtension
->NextDeviceObject
,
535 &IoStatusBlock
, IRP_MN_QUERY_INTERFACE
, &IoStack
);
536 if (!NT_SUCCESS(Status
))
538 WARN_(VIDEOPRT
, "IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status
);
541 INFO_(VIDEOPRT
, "Got AGP driver interface!\n");
544 /* FIXME: Not sure if we should wrap the reference/dereference functions */
545 AgpInterface
->Context
= AgpBusInterface
->AgpContext
;
546 AgpInterface
->InterfaceReference
= AgpBusInterface
->InterfaceReference
;
547 AgpInterface
->InterfaceDereference
= AgpBusInterface
->InterfaceDereference
;
548 AgpInterface
->AgpReservePhysical
= IntAgpReservePhysical
;
549 AgpInterface
->AgpReleasePhysical
= IntAgpReleasePhysical
;
550 AgpInterface
->AgpCommitPhysical
= IntAgpCommitPhysical
;
551 AgpInterface
->AgpFreePhysical
= IntAgpFreePhysical
;
552 AgpInterface
->AgpReserveVirtual
= IntAgpReserveVirtual
;
553 AgpInterface
->AgpReleaseVirtual
= IntAgpReleaseVirtual
;
554 AgpInterface
->AgpCommitVirtual
= IntAgpCommitVirtual
;
555 AgpInterface
->AgpFreeVirtual
= IntAgpFreeVirtual
;
556 AgpInterface
->AgpAllocationLimit
= 0x1000000; /* FIXME: using 16 MB for now */
558 if (AgpInterface
->Version
>= VIDEO_PORT_AGP_INTERFACE_VERSION_2
)
560 AgpInterface
->AgpSetRate
= IntAgpSetRate
;
563 return STATUS_SUCCESS
;