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