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