* Sync up to trunk HEAD (r62975).
[reactos.git] / win32ss / drivers / videoprt / agp.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 *
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.
10 *
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.
15 *
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
19 *
20 */
21
22 #include "videoprt.h"
23
24 #define NDEBUG
25 #include <debug.h>
26
27 /* PRIVATE FUNCTIONS **********************************************************/
28
29 NTSTATUS
30 IopInitiatePnpIrp(
31 PDEVICE_OBJECT DeviceObject,
32 PIO_STATUS_BLOCK IoStatusBlock,
33 UCHAR MinorFunction,
34 PIO_STACK_LOCATION Stack OPTIONAL)
35 {
36 PDEVICE_OBJECT TopDeviceObject;
37 PIO_STACK_LOCATION IrpSp;
38 NTSTATUS Status;
39 KEVENT Event;
40 PIRP Irp;
41
42 /* Always call the top of the device stack */
43 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
44
45 KeInitializeEvent(
46 &Event,
47 NotificationEvent,
48 FALSE);
49
50 Irp = IoBuildSynchronousFsdRequest(
51 IRP_MJ_PNP,
52 TopDeviceObject,
53 NULL,
54 0,
55 NULL,
56 &Event,
57 IoStatusBlock);
58
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;
63
64 IrpSp = IoGetNextIrpStackLocation(Irp);
65 IrpSp->MinorFunction = MinorFunction;
66
67 if (Stack)
68 {
69 RtlMoveMemory(
70 &IrpSp->Parameters,
71 &Stack->Parameters,
72 sizeof(Stack->Parameters));
73 }
74
75 Status = IoCallDriver(TopDeviceObject, Irp);
76 if (Status == STATUS_PENDING)
77 {
78 KeWaitForSingleObject(
79 &Event,
80 Executive,
81 KernelMode,
82 FALSE,
83 NULL);
84 Status = IoStatusBlock->Status;
85 }
86
87 ObDereferenceObject(TopDeviceObject);
88
89 return Status;
90 }
91
92
93 BOOLEAN NTAPI
94 IntAgpCommitPhysical(
95 IN PVOID HwDeviceExtension,
96 IN PVOID PhysicalContext,
97 IN ULONG Pages,
98 IN ULONG Offset)
99 {
100 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
101 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
102 PHYSICAL_ADDRESS MappingAddr = {{0, 0}};
103 PVIDEO_PORT_AGP_MAPPING AgpMapping;
104 NTSTATUS Status;
105
106 TRACE_(VIDEOPRT, "AgpCommitPhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
107 PhysicalContext, Pages, Offset);
108
109 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
110 AgpBusInterface = &DeviceExtension->AgpInterface;
111 AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
112
113 Status = AgpBusInterface->CommitMemory(AgpBusInterface->AgpContext,
114 AgpMapping->MapHandle, Pages, Offset,
115 NULL, &MappingAddr);
116
117 if (!NT_SUCCESS(Status))
118 {
119 WARN_(VIDEOPRT, "Warning: AgpBusInterface->CommitMemory failed (Status = 0x%x)\n",
120 Status);
121 }
122 return NT_SUCCESS(Status);
123 }
124
125 VOID NTAPI
126 IntAgpFreePhysical(
127 IN PVOID HwDeviceExtension,
128 IN PVOID PhysicalContext,
129 IN ULONG Pages,
130 IN ULONG Offset)
131 {
132 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
133 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
134 PVIDEO_PORT_AGP_MAPPING AgpMapping;
135 NTSTATUS Status;
136
137 TRACE_(VIDEOPRT, "AgpFreePhysical - PhysicalContext: 0x%x Pages: %d, Offset: 0x%x\n",
138 PhysicalContext, Pages, Offset);
139
140 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
141 AgpBusInterface = &DeviceExtension->AgpInterface;
142 AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
143
144 Status = AgpBusInterface->FreeMemory(AgpBusInterface->AgpContext,
145 AgpMapping->MapHandle, Pages, Offset);
146 if (!NT_SUCCESS(Status))
147 {
148 WARN_(VIDEOPRT, "Warning: AgpBusInterface->FreeMemory failed (Status = 0x%x)\n",
149 Status);
150 }
151 }
152
153 VOID NTAPI
154 IntAgpReleasePhysical(
155 IN PVOID HwDeviceExtension,
156 IN PVOID PhysicalContext)
157 {
158 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
159 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
160 PVIDEO_PORT_AGP_MAPPING AgpMapping;
161 NTSTATUS Status;
162
163 TRACE_(VIDEOPRT, "AgpReleasePhysical - PhysicalContext: 0x%x\n", PhysicalContext);
164
165 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
166 AgpBusInterface = &DeviceExtension->AgpInterface;
167 AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
168
169 /* Release memory */
170 Status = AgpBusInterface->ReleaseMemory(AgpBusInterface->AgpContext,
171 AgpMapping->MapHandle);
172 if (!NT_SUCCESS(Status))
173 {
174 WARN_(VIDEOPRT, "Warning: AgpBusInterface->ReleaseMemory failed (Status = 0x%x)\n",
175 Status);
176 }
177
178 /* Free resources */
179 ExFreePool(AgpMapping);
180 }
181
182 PHYSICAL_ADDRESS NTAPI
183 IntAgpReservePhysical(
184 IN PVOID HwDeviceExtension,
185 IN ULONG Pages,
186 IN VIDEO_PORT_CACHE_TYPE Caching,
187 OUT PVOID *PhysicalContext)
188 {
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;
194 NTSTATUS Status;
195
196 TRACE_(VIDEOPRT, "AgpReservePhysical - Pages: %d, Caching: 0x%x\n", Pages, Caching);
197
198 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
199 AgpBusInterface = &DeviceExtension->AgpInterface;
200
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;
208 else
209 {
210 WARN_(VIDEOPRT, "Invalid caching type %d!\n", Caching);
211 return ZeroAddress;
212 }
213
214 /* Allocate an AGP mapping structure */
215 AgpMapping = ExAllocatePoolWithTag(PagedPool,
216 sizeof(VIDEO_PORT_AGP_MAPPING),
217 TAG_VIDEO_PORT);
218 if (AgpMapping == NULL)
219 {
220 WARN_(VIDEOPRT, "Out of memory! Couldn't allocate AGP mapping structure!\n");
221 return ZeroAddress;
222 }
223 RtlZeroMemory(AgpMapping, sizeof(VIDEO_PORT_AGP_MAPPING));
224
225 /* Reserve memory for the AGP bus */
226 Status = AgpBusInterface->ReserveMemory(AgpBusInterface->AgpContext,
227 Pages,
228 MemCachingType,
229 &AgpMapping->MapHandle,
230 &AgpMapping->PhysicalAddress);
231 if (!NT_SUCCESS(Status) || AgpMapping->MapHandle == NULL)
232 {
233 ExFreePool(AgpMapping);
234 WARN_(VIDEOPRT, "Warning: AgpBusInterface->ReserveMemory failed (Status = 0x%x)\n",
235 Status);
236 return ZeroAddress;
237 }
238
239 /* Fill the rest of the AGP mapping */
240 AgpMapping->NumberOfPages = Pages;
241
242 *PhysicalContext = (PVOID)AgpMapping;
243 return AgpMapping->PhysicalAddress;
244 }
245
246
247 PVOID NTAPI
248 IntAgpCommitVirtual(
249 IN PVOID HwDeviceExtension,
250 IN PVOID VirtualContext,
251 IN ULONG Pages,
252 IN ULONG Offset)
253 {
254 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
255 PVOID BaseAddress = NULL;
256 PHYSICAL_ADDRESS PhysicalAddress;
257 NTSTATUS Status;
258
259 TRACE_(VIDEOPRT, "AgpCommitVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
260 VirtualContext, Pages, Offset);
261
262 VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext;
263
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.
268 *
269 * - blight (2004-12-21)
270 */
271
272 if (VirtualMapping->ProcessHandle == NULL)
273 {
274 /* FIXME: not implemented */
275 }
276 else /* ProcessHandle != NULL */
277 {
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 +
282 OffsetInBytes);
283 PhysicalAddress = VirtualMapping->AgpMapping->PhysicalAddress;
284 PhysicalAddress.QuadPart += OffsetInBytes;
285
286 Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle,
287 &BaseAddress,
288 &Size, MEM_RELEASE);
289 if (!NT_SUCCESS(Status))
290 {
291 WARN_(VIDEOPRT, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status);
292 return NULL;
293 }
294 ASSERT(Size == Pages * PAGE_SIZE);
295 ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
296 OffsetInBytes));
297
298 /* Map the physical memory into the released virtual memory area */
299 Status = IntVideoPortMapPhysicalMemory(VirtualMapping->ProcessHandle,
300 PhysicalAddress,
301 Size,
302 PAGE_READWRITE,
303 &BaseAddress);
304 if (!NT_SUCCESS(Status))
305 {
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,
310 PAGE_NOACCESS);
311 if (!NT_SUCCESS(Status))
312 {
313 WARN_(VIDEOPRT, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status);
314 /* FIXME: What to do now?? */
315 ASSERT(0);
316 return NULL;
317 }
318 ASSERT(Size == Pages * PAGE_SIZE);
319 ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
320 OffsetInBytes));
321 return NULL;
322 }
323 ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
324 OffsetInBytes));
325 }
326
327 return BaseAddress;
328 }
329
330 VOID NTAPI
331 IntAgpFreeVirtual(
332 IN PVOID HwDeviceExtension,
333 IN PVOID VirtualContext,
334 IN ULONG Pages,
335 IN ULONG Offset)
336 {
337 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
338 PVOID BaseAddress = NULL;
339 NTSTATUS Status;
340
341 TRACE_(VIDEOPRT, "AgpFreeVirtual - VirtualContext: 0x%x Pages: %d, Offset: 0x%x\n",
342 VirtualContext, Pages, Offset);
343
344 VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext;
345
346 if (VirtualMapping->ProcessHandle == NULL)
347 {
348 /* FIXME: not implemented */
349 }
350 else /* ProcessHandle != NULL */
351 {
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 +
356 OffsetInBytes);
357
358 Status = ZwUnmapViewOfSection(VirtualMapping->ProcessHandle, BaseAddress);
359 if (!NT_SUCCESS(Status))
360 {
361 WARN_(VIDEOPRT, "Warning: ZwUnmapViewOfSection() failed: Status = 0x%x\n", Status);
362 /* FIXME: What to do now?? */
363 ASSERT(0);
364 return;
365 }
366
367 /* And reserve the virtual memory area again */
368 Status = ZwAllocateVirtualMemory(VirtualMapping->ProcessHandle,
369 &BaseAddress, 0, &Size, MEM_RESERVE,
370 PAGE_NOACCESS);
371 if (!NT_SUCCESS(Status))
372 {
373 WARN_(VIDEOPRT, "Warning: ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status);
374 /* FIXME: What to do now?? */
375 ASSERT(0);
376 return;
377 }
378 ASSERT(Size == Pages * PAGE_SIZE);
379 ASSERT(BaseAddress == (PVOID)((ULONG_PTR)VirtualMapping->MappedAddress +
380 OffsetInBytes));
381 }
382 }
383
384 VOID NTAPI
385 IntAgpReleaseVirtual(
386 IN PVOID HwDeviceExtension,
387 IN PVOID VirtualContext)
388 {
389 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
390 NTSTATUS Status;
391
392 TRACE_(VIDEOPRT, "AgpReleaseVirtual - VirtualContext: 0x%x\n", VirtualContext);
393
394 VirtualMapping = (PVIDEO_PORT_AGP_VIRTUAL_MAPPING)VirtualContext;
395
396 /* Release the virtual memory */
397 if (VirtualMapping->ProcessHandle == NULL)
398 {
399 /* FIXME: not implemented */
400 }
401 else /* ProcessHandle != NULL */
402 {
403 /* Release the allocated virtual memory */
404 SIZE_T Size = VirtualMapping->AgpMapping->NumberOfPages * PAGE_SIZE;
405 Status = ZwFreeVirtualMemory(VirtualMapping->ProcessHandle,
406 &VirtualMapping->MappedAddress,
407 &Size, MEM_RELEASE);
408 if (!NT_SUCCESS(Status))
409 {
410 WARN_(VIDEOPRT, "Warning: ZwFreeVirtualMemory() failed: Status = 0x%x\n", Status);
411 }
412 }
413
414 /* Free resources */
415 ExFreePool(VirtualMapping);
416 }
417
418 PVOID NTAPI
419 IntAgpReserveVirtual(
420 IN PVOID HwDeviceExtension,
421 IN HANDLE ProcessHandle,
422 IN PVOID PhysicalContext,
423 OUT PVOID *VirtualContext)
424 {
425 PVIDEO_PORT_AGP_MAPPING AgpMapping;
426 PVIDEO_PORT_AGP_VIRTUAL_MAPPING VirtualMapping;
427 PVOID MappedAddress;
428 NTSTATUS Status;
429
430 TRACE_(VIDEOPRT, "AgpReserveVirtual - ProcessHandle: 0x%x PhysicalContext: 0x%x\n",
431 ProcessHandle, PhysicalContext);
432
433 AgpMapping = (PVIDEO_PORT_AGP_MAPPING)PhysicalContext;
434
435 /* Allocate an AGP virtual mapping structure */
436 VirtualMapping = ExAllocatePoolWithTag(PagedPool,
437 sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING),
438 TAG_VIDEO_PORT);
439 if (VirtualMapping == NULL)
440 {
441 WARN_(VIDEOPRT, "Out of memory! Couldn't allocate AGP virtual mapping structure!\n");
442 return NULL;
443 }
444 RtlZeroMemory(VirtualMapping, sizeof(VIDEO_PORT_AGP_VIRTUAL_MAPPING));
445
446 /* Reserve a virtual memory area for the physical pages. */
447 if (ProcessHandle == NULL)
448 {
449 /* FIXME: What to do in this case? */
450 ExFreePool(VirtualMapping);
451 return NULL;
452 }
453 else /* ProcessHandle != NULL */
454 {
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))
461 {
462 ExFreePool(VirtualMapping);
463 WARN_(VIDEOPRT, "ZwAllocateVirtualMemory() failed: Status = 0x%x\n", Status);
464 return NULL;
465 }
466 }
467
468 /* Fill the AGP virtual mapping */
469 VirtualMapping->AgpMapping = AgpMapping;
470 VirtualMapping->ProcessHandle = ProcessHandle;
471 VirtualMapping->MappedAddress = MappedAddress;
472
473 *VirtualContext = (PVOID)VirtualMapping;
474 return MappedAddress;
475 }
476
477
478 BOOLEAN NTAPI
479 IntAgpSetRate(
480 IN PVOID HwDeviceExtension,
481 IN ULONG Rate)
482 {
483 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
484 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
485
486 TRACE_(VIDEOPRT, "AgpSetRate - Rate: %d\n", Rate);
487
488 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
489 AgpBusInterface = &DeviceExtension->AgpInterface;
490
491 return NT_SUCCESS(AgpBusInterface->SetRate(AgpBusInterface->AgpContext, Rate));
492 }
493
494
495 NTSTATUS NTAPI
496 IntAgpGetInterface(
497 IN PVOID HwDeviceExtension,
498 IN OUT PINTERFACE Interface)
499 {
500 IO_STATUS_BLOCK IoStatusBlock;
501 IO_STACK_LOCATION IoStack;
502 NTSTATUS Status;
503 PVIDEO_PORT_AGP_INTERFACE_2 AgpInterface;
504 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
505 PAGP_BUS_INTERFACE_STANDARD AgpBusInterface;
506
507 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
508 AgpBusInterface = &DeviceExtension->AgpInterface;
509 AgpInterface = (PVIDEO_PORT_AGP_INTERFACE_2)Interface;
510
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)
514 {
515 ASSERT(Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE_2));
516 }
517 else if (Interface->Version == VIDEO_PORT_AGP_INTERFACE_VERSION_1)
518 {
519 ASSERT(Interface->Size >= sizeof(VIDEO_PORT_AGP_INTERFACE));
520 }
521
522 if (DeviceExtension->NextDeviceObject == NULL)
523 {
524 WARN_(VIDEOPRT, "DeviceExtension->NextDeviceObject is NULL!\n");
525 return STATUS_UNSUCCESSFUL;
526 }
527
528 /* Query the interface from the AGP bus driver */
529 if (DeviceExtension->AgpInterface.Size == 0)
530 {
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))
544 {
545 WARN_(VIDEOPRT, "IopInitiatePnpIrp() failed! (Status 0x%x)\n", Status);
546 return Status;
547 }
548 INFO_(VIDEOPRT, "Got AGP driver interface!\n");
549 }
550
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 */
564
565 if (AgpInterface->Version >= VIDEO_PORT_AGP_INTERFACE_VERSION_2)
566 {
567 AgpInterface->AgpSetRate = IntAgpSetRate;
568 }
569
570 return STATUS_SUCCESS;
571 }