1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002 - 2005 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 extern BOOLEAN VpBaseVideo;
28
29 /* PRIVATE FUNCTIONS **********************************************************/
30
31 static BOOLEAN
IntIsVgaSaveDriver(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)32 IntIsVgaSaveDriver(
33 IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)
34 {
35 UNICODE_STRING VgaSave = RTL_CONSTANT_STRING(L"\\Driver\\VgaSave");
36 return RtlEqualUnicodeString(&VgaSave, &DeviceExtension->DriverObject->DriverName, TRUE);
37 }
38
39 NTSTATUS NTAPI
IntVideoPortGetLegacyResources(IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,OUT PVIDEO_ACCESS_RANGE * AccessRanges,OUT PULONG AccessRangeCount)40 IntVideoPortGetLegacyResources(
41 IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
42 IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
43 OUT PVIDEO_ACCESS_RANGE *AccessRanges,
44 OUT PULONG AccessRangeCount)
45 {
46 PCI_COMMON_CONFIG PciConfig;
47 ULONG ReadLength;
48
49 if (!DriverExtension->InitializationData.HwGetLegacyResources &&
50 !DriverExtension->InitializationData.HwLegacyResourceCount)
51 {
52 /* No legacy resources to report */
53 *AccessRangeCount = 0;
54 return STATUS_SUCCESS;
55 }
56
57 if (DriverExtension->InitializationData.HwGetLegacyResources)
58 {
59 ReadLength = HalGetBusData(PCIConfiguration,
60 DeviceExtension->SystemIoBusNumber,
61 DeviceExtension->SystemIoSlotNumber,
62 &PciConfig,
63 sizeof(PciConfig));
64 if (ReadLength != sizeof(PciConfig))
65 {
66 /* This device doesn't exist */
67 return STATUS_NO_SUCH_DEVICE;
68 }
69
70 DriverExtension->InitializationData.HwGetLegacyResources(PciConfig.VendorID,
71 PciConfig.DeviceID,
72 AccessRanges,
73 AccessRangeCount);
74 }
75 else
76 {
77 *AccessRanges = DriverExtension->InitializationData.HwLegacyResourceList;
78 *AccessRangeCount = DriverExtension->InitializationData.HwLegacyResourceCount;
79 }
80
81 INFO_(VIDEOPRT, "Got %d legacy access ranges\n", *AccessRangeCount);
82
83 return STATUS_SUCCESS;
84 }
85
86 NTSTATUS NTAPI
IntVideoPortFilterResourceRequirements(IN PDEVICE_OBJECT DeviceObject,IN PIO_STACK_LOCATION IrpStack,IN PIRP Irp)87 IntVideoPortFilterResourceRequirements(
88 IN PDEVICE_OBJECT DeviceObject,
89 IN PIO_STACK_LOCATION IrpStack,
90 IN PIRP Irp)
91 {
92 PDRIVER_OBJECT DriverObject;
93 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
94 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
95 PVIDEO_ACCESS_RANGE AccessRanges;
96 ULONG AccessRangeCount, ListSize, i;
97 PIO_RESOURCE_REQUIREMENTS_LIST ResList;
98 PIO_RESOURCE_REQUIREMENTS_LIST OldResList = IrpStack->Parameters.FilterResourceRequirements.IoResourceRequirementList;
99 PIO_RESOURCE_DESCRIPTOR CurrentDescriptor;
100 NTSTATUS Status;
101
102 DriverObject = DeviceObject->DriverObject;
103 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
104 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
105
106 Status = IntVideoPortGetLegacyResources(DriverExtension, DeviceExtension, &AccessRanges, &AccessRangeCount);
107 if (!NT_SUCCESS(Status))
108 return Status;
109 if (!AccessRangeCount)
110 {
111 /* No legacy resources to report */
112 return Irp->IoStatus.Status;
113 }
114
115 /* OK, we've got the access ranges now. Let's set up the resource requirements list */
116
117 if (OldResList)
118 {
119 /* Already one there so let's add to it */
120 ListSize = OldResList->ListSize + sizeof(IO_RESOURCE_DESCRIPTOR) * AccessRangeCount;
121 ResList = ExAllocatePool(NonPagedPool,
122 ListSize);
123 if (!ResList) return STATUS_NO_MEMORY;
124
125 RtlCopyMemory(ResList, OldResList, OldResList->ListSize);
126
127 ASSERT(ResList->AlternativeLists == 1);
128
129 ResList->ListSize = ListSize;
130 ResList->List[0].Count += AccessRangeCount;
131
132 CurrentDescriptor = (PIO_RESOURCE_DESCRIPTOR)((PUCHAR)ResList + OldResList->ListSize);
133
134 ExFreePool(OldResList);
135 Irp->IoStatus.Information = 0;
136 }
137 else
138 {
139 /* We need to make a new one */
140 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + sizeof(IO_RESOURCE_DESCRIPTOR) * (AccessRangeCount - 1);
141 ResList = ExAllocatePool(NonPagedPool,
142 ListSize);
143 if (!ResList) return STATUS_NO_MEMORY;
144
145 RtlZeroMemory(ResList, ListSize);
146
147 /* We need to initialize some fields */
148 ResList->ListSize = ListSize;
149 ResList->InterfaceType = DeviceExtension->AdapterInterfaceType;
150 ResList->BusNumber = DeviceExtension->SystemIoBusNumber;
151 ResList->SlotNumber = DeviceExtension->SystemIoSlotNumber;
152 ResList->AlternativeLists = 1;
153 ResList->List[0].Version = 1;
154 ResList->List[0].Revision = 1;
155 ResList->List[0].Count = AccessRangeCount;
156
157 CurrentDescriptor = ResList->List[0].Descriptors;
158 }
159
160 for (i = 0; i < AccessRangeCount; i++)
161 {
162 /* This is a required resource */
163 CurrentDescriptor->Option = 0;
164
165 if (AccessRanges[i].RangeInIoSpace)
166 CurrentDescriptor->Type = CmResourceTypePort;
167 else
168 CurrentDescriptor->Type = CmResourceTypeMemory;
169
170 CurrentDescriptor->ShareDisposition =
171 (AccessRanges[i].RangeShareable ? CmResourceShareShared : CmResourceShareDeviceExclusive);
172
173 CurrentDescriptor->Flags = 0;
174
175 if (CurrentDescriptor->Type == CmResourceTypePort)
176 {
177 CurrentDescriptor->u.Port.Length = AccessRanges[i].RangeLength;
178 CurrentDescriptor->u.Port.MinimumAddress = AccessRanges[i].RangeStart;
179 CurrentDescriptor->u.Port.MaximumAddress.QuadPart = AccessRanges[i].RangeStart.QuadPart + AccessRanges[i].RangeLength - 1;
180 CurrentDescriptor->u.Port.Alignment = 1;
181 if (AccessRanges[i].RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
182 CurrentDescriptor->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
183 if (AccessRanges[i].RangePassive & VIDEO_RANGE_10_BIT_DECODE)
184 CurrentDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
185 }
186 else
187 {
188 CurrentDescriptor->u.Memory.Length = AccessRanges[i].RangeLength;
189 CurrentDescriptor->u.Memory.MinimumAddress = AccessRanges[i].RangeStart;
190 CurrentDescriptor->u.Memory.MaximumAddress.QuadPart = AccessRanges[i].RangeStart.QuadPart + AccessRanges[i].RangeLength - 1;
191 CurrentDescriptor->u.Memory.Alignment = 1;
192 CurrentDescriptor->Flags |= CM_RESOURCE_MEMORY_READ_WRITE;
193 }
194
195 CurrentDescriptor++;
196 }
197
198 Irp->IoStatus.Information = (ULONG_PTR)ResList;
199
200 return STATUS_SUCCESS;
201 }
202
203 VOID
IntVideoPortReleaseResources(_In_ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)204 IntVideoPortReleaseResources(
205 _In_ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension)
206 {
207 NTSTATUS Status;
208 BOOLEAN ConflictDetected;
209 // An empty CM_RESOURCE_LIST
210 UCHAR EmptyResourceList[FIELD_OFFSET(CM_RESOURCE_LIST, List)] = {0};
211
212 Status = IoReportResourceForDetection(
213 DeviceExtension->DriverObject,
214 NULL, 0, /* Driver List */
215 DeviceExtension->PhysicalDeviceObject,
216 (PCM_RESOURCE_LIST)EmptyResourceList,
217 sizeof(EmptyResourceList),
218 &ConflictDetected);
219
220 if (!NT_SUCCESS(Status))
221 {
222 DPRINT1("VideoPortReleaseResources IoReportResource failed with 0x%08lx ; ConflictDetected: %s\n",
223 Status, ConflictDetected ? "TRUE" : "FALSE");
224 }
225 /* Ignore the returned status however... */
226 }
227
228 NTSTATUS NTAPI
IntVideoPortMapPhysicalMemory(IN HANDLE Process,IN PHYSICAL_ADDRESS PhysicalAddress,IN ULONG SizeInBytes,IN ULONG Protect,IN OUT PVOID * VirtualAddress OPTIONAL)229 IntVideoPortMapPhysicalMemory(
230 IN HANDLE Process,
231 IN PHYSICAL_ADDRESS PhysicalAddress,
232 IN ULONG SizeInBytes,
233 IN ULONG Protect,
234 IN OUT PVOID *VirtualAddress OPTIONAL)
235 {
236 OBJECT_ATTRIBUTES ObjAttribs;
237 UNICODE_STRING UnicodeString;
238 HANDLE hMemObj;
239 NTSTATUS Status;
240 SIZE_T Size;
241
242 /* Initialize object attribs */
243 RtlInitUnicodeString(&UnicodeString, L"\\Device\\PhysicalMemory");
244 InitializeObjectAttributes(&ObjAttribs,
245 &UnicodeString,
246 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
247 NULL, NULL);
248
249 /* Open physical memory section */
250 Status = ZwOpenSection(&hMemObj, SECTION_ALL_ACCESS, &ObjAttribs);
251 if (!NT_SUCCESS(Status))
252 {
253 WARN_(VIDEOPRT, "ZwOpenSection() failed! (0x%x)\n", Status);
254 return Status;
255 }
256
257 /* Map view of section */
258 Size = SizeInBytes;
259 Status = ZwMapViewOfSection(hMemObj,
260 Process,
261 VirtualAddress,
262 0,
263 Size,
264 (PLARGE_INTEGER)(&PhysicalAddress),
265 &Size,
266 ViewUnmap,
267 0,
268 Protect);
269 ZwClose(hMemObj);
270 if (!NT_SUCCESS(Status))
271 {
272 WARN_(VIDEOPRT, "ZwMapViewOfSection() failed! (0x%x)\n", Status);
273 }
274
275 return Status;
276 }
277
278
279 PVOID NTAPI
IntVideoPortMapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,IN PHYSICAL_ADDRESS IoAddress,IN ULONG NumberOfUchars,IN ULONG InIoSpace,IN HANDLE ProcessHandle,OUT VP_STATUS * Status)280 IntVideoPortMapMemory(
281 IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
282 IN PHYSICAL_ADDRESS IoAddress,
283 IN ULONG NumberOfUchars,
284 IN ULONG InIoSpace,
285 IN HANDLE ProcessHandle,
286 OUT VP_STATUS *Status)
287 {
288 PHYSICAL_ADDRESS TranslatedAddress;
289 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
290 ULONG AddressSpace;
291 PVOID MappedAddress;
292 PLIST_ENTRY Entry;
293
294 INFO_(VIDEOPRT, "- IoAddress: %lx\n", IoAddress.u.LowPart);
295 INFO_(VIDEOPRT, "- NumberOfUchars: %lx\n", NumberOfUchars);
296 INFO_(VIDEOPRT, "- InIoSpace: %x\n", InIoSpace);
297
298 InIoSpace &= ~VIDEO_MEMORY_SPACE_DENSE;
299 if ((InIoSpace & VIDEO_MEMORY_SPACE_P6CACHE) != 0)
300 {
301 INFO_(VIDEOPRT, "VIDEO_MEMORY_SPACE_P6CACHE not supported, turning off\n");
302 InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE;
303 }
304
305 if (ProcessHandle != NULL && (InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0)
306 {
307 INFO_(VIDEOPRT, "ProcessHandle is not NULL (0x%x) but InIoSpace does not have "
308 "VIDEO_MEMORY_SPACE_USER_MODE set! Setting "
309 "VIDEO_MEMORY_SPACE_USER_MODE.\n",
310 ProcessHandle);
311 InIoSpace |= VIDEO_MEMORY_SPACE_USER_MODE;
312 }
313 else if (ProcessHandle == NULL && (InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
314 {
315 INFO_(VIDEOPRT, "ProcessHandle is NULL (0x%x) but InIoSpace does have "
316 "VIDEO_MEMORY_SPACE_USER_MODE set! Setting ProcessHandle "
317 "to NtCurrentProcess()\n",
318 ProcessHandle);
319 ProcessHandle = NtCurrentProcess();
320 }
321
322 if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0 &&
323 !IsListEmpty(&DeviceExtension->AddressMappingListHead))
324 {
325 Entry = DeviceExtension->AddressMappingListHead.Flink;
326 while (Entry != &DeviceExtension->AddressMappingListHead)
327 {
328 AddressMapping = CONTAINING_RECORD(
329 Entry,
330 VIDEO_PORT_ADDRESS_MAPPING,
331 List);
332 if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
333 NumberOfUchars <= AddressMapping->NumberOfUchars)
334 {
335 {
336 AddressMapping->MappingCount++;
337 if (Status)
338 *Status = NO_ERROR;
339 return AddressMapping->MappedAddress;
340 }
341 }
342 Entry = Entry->Flink;
343 }
344 }
345
346 AddressSpace = (ULONG)InIoSpace;
347 AddressSpace &= ~VIDEO_MEMORY_SPACE_USER_MODE;
348 if (HalTranslateBusAddress(
349 DeviceExtension->AdapterInterfaceType,
350 DeviceExtension->SystemIoBusNumber,
351 IoAddress,
352 &AddressSpace,
353 &TranslatedAddress) == FALSE)
354 {
355 if (Status)
356 *Status = ERROR_NOT_ENOUGH_MEMORY;
357
358 return NULL;
359 }
360
361 /* I/O space */
362 if (AddressSpace != 0)
363 {
364 ASSERT(0 == TranslatedAddress.u.HighPart);
365 if (Status)
366 *Status = NO_ERROR;
367
368 return (PVOID)(ULONG_PTR)TranslatedAddress.u.LowPart;
369 }
370
371 /* user space */
372 if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
373 {
374 NTSTATUS NtStatus;
375 MappedAddress = NULL;
376 NtStatus = IntVideoPortMapPhysicalMemory(ProcessHandle,
377 TranslatedAddress,
378 NumberOfUchars,
379 PAGE_READWRITE/* | PAGE_WRITECOMBINE*/,
380 &MappedAddress);
381 if (!NT_SUCCESS(NtStatus))
382 {
383 WARN_(VIDEOPRT, "IntVideoPortMapPhysicalMemory() failed! (0x%x)\n", NtStatus);
384 if (Status)
385 *Status = NO_ERROR;
386 return NULL;
387 }
388 INFO_(VIDEOPRT, "Mapped user address = 0x%08x\n", MappedAddress);
389 }
390 else /* kernel space */
391 {
392 MappedAddress = MmMapIoSpace(
393 TranslatedAddress,
394 NumberOfUchars,
395 MmNonCached);
396 }
397
398 if (MappedAddress != NULL)
399 {
400 if (Status)
401 {
402 *Status = NO_ERROR;
403 }
404 if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0)
405 {
406 AddressMapping = ExAllocatePoolWithTag(
407 PagedPool,
408 sizeof(VIDEO_PORT_ADDRESS_MAPPING),
409 TAG_VIDEO_PORT);
410
411 if (AddressMapping == NULL)
412 return MappedAddress;
413
414 RtlZeroMemory(AddressMapping, sizeof(VIDEO_PORT_ADDRESS_MAPPING));
415 AddressMapping->NumberOfUchars = NumberOfUchars;
416 AddressMapping->IoAddress = IoAddress;
417 AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
418 AddressMapping->MappedAddress = MappedAddress;
419 AddressMapping->MappingCount = 1;
420 InsertHeadList(
421 &DeviceExtension->AddressMappingListHead,
422 &AddressMapping->List);
423 }
424
425 return MappedAddress;
426 }
427
428 if (Status)
429 *Status = NO_ERROR;
430
431 return NULL;
432 }
433
434 VOID NTAPI
IntVideoPortUnmapMemory(IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,IN PVOID MappedAddress)435 IntVideoPortUnmapMemory(
436 IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
437 IN PVOID MappedAddress)
438 {
439 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
440 PLIST_ENTRY Entry;
441 NTSTATUS Status;
442
443 Entry = DeviceExtension->AddressMappingListHead.Flink;
444 while (Entry != &DeviceExtension->AddressMappingListHead)
445 {
446 AddressMapping = CONTAINING_RECORD(
447 Entry,
448 VIDEO_PORT_ADDRESS_MAPPING,
449 List);
450 if (AddressMapping->MappedAddress == MappedAddress)
451 {
452 ASSERT(AddressMapping->MappingCount > 0);
453 AddressMapping->MappingCount--;
454 if (AddressMapping->MappingCount == 0)
455 {
456 MmUnmapIoSpace(
457 AddressMapping->MappedAddress,
458 AddressMapping->NumberOfUchars);
459 RemoveEntryList(Entry);
460 ExFreePool(AddressMapping);
461 }
462 return;
463 }
464
465 Entry = Entry->Flink;
466 }
467
468 /* If there was no kernelmode mapping for the given address found we assume
469 * that the given address is a usermode mapping and try to unmap it.
470 *
471 * FIXME: Is it ok to use NtCurrentProcess?
472 */
473 Status = ZwUnmapViewOfSection(NtCurrentProcess(), MappedAddress);
474 if (!NT_SUCCESS(Status))
475 {
476 WARN_(VIDEOPRT, "Warning: Mapping for address 0x%p not found!\n", MappedAddress);
477 }
478 }
479
480 /* PUBLIC FUNCTIONS ***********************************************************/
481
482 /*
483 * @implemented
484 */
485
486 PVOID NTAPI
VideoPortGetDeviceBase(IN PVOID HwDeviceExtension,IN PHYSICAL_ADDRESS IoAddress,IN ULONG NumberOfUchars,IN UCHAR InIoSpace)487 VideoPortGetDeviceBase(
488 IN PVOID HwDeviceExtension,
489 IN PHYSICAL_ADDRESS IoAddress,
490 IN ULONG NumberOfUchars,
491 IN UCHAR InIoSpace)
492 {
493 TRACE_(VIDEOPRT, "VideoPortGetDeviceBase\n");
494 return IntVideoPortMapMemory(
495 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension),
496 IoAddress,
497 NumberOfUchars,
498 InIoSpace,
499 NULL,
500 NULL);
501 }
502
503 /*
504 * @implemented
505 */
506
507 VOID NTAPI
VideoPortFreeDeviceBase(IN PVOID HwDeviceExtension,IN PVOID MappedAddress)508 VideoPortFreeDeviceBase(
509 IN PVOID HwDeviceExtension,
510 IN PVOID MappedAddress)
511 {
512 TRACE_(VIDEOPRT, "VideoPortFreeDeviceBase\n");
513 IntVideoPortUnmapMemory(
514 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension),
515 MappedAddress);
516 }
517
518 /*
519 * @unimplemented
520 */
521
522 VP_STATUS NTAPI
VideoPortMapBankedMemory(IN PVOID HwDeviceExtension,IN PHYSICAL_ADDRESS PhysicalAddress,IN PULONG Length,IN PULONG InIoSpace,OUT PVOID * VirtualAddress,IN ULONG BankLength,IN UCHAR ReadWriteBank,IN PBANKED_SECTION_ROUTINE BankRoutine,IN PVOID Context)523 VideoPortMapBankedMemory(
524 IN PVOID HwDeviceExtension,
525 IN PHYSICAL_ADDRESS PhysicalAddress,
526 IN PULONG Length,
527 IN PULONG InIoSpace,
528 OUT PVOID *VirtualAddress,
529 IN ULONG BankLength,
530 IN UCHAR ReadWriteBank,
531 IN PBANKED_SECTION_ROUTINE BankRoutine,
532 IN PVOID Context)
533 {
534 TRACE_(VIDEOPRT, "VideoPortMapBankedMemory\n");
535 UNIMPLEMENTED;
536 return ERROR_INVALID_FUNCTION;
537 }
538
539
540 /*
541 * @implemented
542 */
543
544 VP_STATUS NTAPI
VideoPortMapMemory(IN PVOID HwDeviceExtension,IN PHYSICAL_ADDRESS PhysicalAddress,IN PULONG Length,IN PULONG InIoSpace,OUT PVOID * VirtualAddress)545 VideoPortMapMemory(
546 IN PVOID HwDeviceExtension,
547 IN PHYSICAL_ADDRESS PhysicalAddress,
548 IN PULONG Length,
549 IN PULONG InIoSpace,
550 OUT PVOID *VirtualAddress)
551 {
552 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
553 NTSTATUS Status;
554
555 TRACE_(VIDEOPRT, "VideoPortMapMemory\n");
556 INFO_(VIDEOPRT, "- *VirtualAddress: 0x%x\n", *VirtualAddress);
557
558 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
559 *VirtualAddress = IntVideoPortMapMemory(
560 DeviceExtension,
561 PhysicalAddress,
562 *Length,
563 *InIoSpace,
564 (HANDLE)*VirtualAddress,
565 &Status);
566
567 return Status;
568 }
569
570 /*
571 * @implemented
572 */
573
574 VP_STATUS NTAPI
VideoPortUnmapMemory(IN PVOID HwDeviceExtension,IN PVOID VirtualAddress,IN HANDLE ProcessHandle)575 VideoPortUnmapMemory(
576 IN PVOID HwDeviceExtension,
577 IN PVOID VirtualAddress,
578 IN HANDLE ProcessHandle)
579 {
580 TRACE_(VIDEOPRT, "VideoPortFreeDeviceBase\n");
581
582 IntVideoPortUnmapMemory(
583 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension),
584 VirtualAddress);
585
586 return NO_ERROR;
587 }
588
589 /**
590 * @brief
591 * Retrieves bus-relative (mainly PCI) hardware resources access ranges
592 * and, if possible, claims these resources for the caller.
593 *
594 * @param[in] HwDeviceExtension
595 * The miniport device extension.
596 *
597 * @param[in] NumRequestedResources
598 * The number of hardware resources in the @p RequestedResources array.
599 *
600 * @param[in] RequestedResources
601 * An optional array of IO_RESOURCE_DESCRIPTOR elements describing hardware
602 * resources the miniport requires.
603 *
604 * @param[in] NumAccessRanges
605 * The number of ranges in the @p AccessRanges array the miniport expects
606 * to retrieve.
607 *
608 * @param[out] AccessRanges
609 * A pointer to an array of hardware resource ranges VideoPortGetAccessRanges
610 * fills with bus-relative device memory ACCESS_RANGE's for the adapter.
611 *
612 * @param[in] VendorId
613 * For a PCI device, points to a USHORT-type value that identifies
614 * the PCI manufacturer of the adapter. Otherwise, should be NULL.
615 *
616 * @param[in] DeviceId
617 * For a PCI device, points to a USHORT-type value that identifies
618 * a particular PCI adapter model, assigned by the manufacturer.
619 * Otherwise, should be NULL.
620 *
621 * @param[out] Slot
622 * Points to a ULONG value that receives the logical slot / location of
623 * the adapter (bus-dependent). For a PCI adapter, @p Slot points to a
624 * @p PCI_SLOT_NUMBER structure that locates the adapter on the PCI bus.
625 *
626 * @return
627 * - NO_ERROR if the resources have been successfully claimed or released.
628 * - ERROR_INVALID_PARAMETER if an error or a conflict occurred.
629 * - ERROR_DEV_NOT_EXIST if the device is not found.
630 * - ERROR_MORE_DATA if there exist more device access ranges available
631 * than what is specified by @p NumAccessRanges.
632 * - ERROR_NOT_ENOUGH_MEMORY if there is not enough memory available.
633 **/
634 VP_STATUS
635 NTAPI
VideoPortGetAccessRanges(_In_ PVOID HwDeviceExtension,_In_opt_ ULONG NumRequestedResources,_In_reads_opt_ (NumRequestedResources)PIO_RESOURCE_DESCRIPTOR RequestedResources,_In_ ULONG NumAccessRanges,_Out_writes_ (NumAccessRanges)PVIDEO_ACCESS_RANGE AccessRanges,_In_ PVOID VendorId,_In_ PVOID DeviceId,_Out_ PULONG Slot)636 VideoPortGetAccessRanges(
637 _In_ PVOID HwDeviceExtension,
638 _In_opt_ ULONG NumRequestedResources,
639 _In_reads_opt_(NumRequestedResources)
640 PIO_RESOURCE_DESCRIPTOR RequestedResources,
641 _In_ ULONG NumAccessRanges,
642 _Out_writes_(NumAccessRanges) PVIDEO_ACCESS_RANGE AccessRanges,
643 _In_ PVOID VendorId,
644 _In_ PVOID DeviceId,
645 _Out_ PULONG Slot)
646 {
647 PCI_SLOT_NUMBER PciSlotNumber;
648 ULONG DeviceNumber;
649 ULONG FunctionNumber;
650 PCI_COMMON_CONFIG Config;
651 PCM_RESOURCE_LIST AllocatedResources;
652 NTSTATUS Status;
653 UINT AssignedCount = 0;
654 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
655 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
656 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
657 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
658 USHORT VendorIdToFind;
659 USHORT DeviceIdToFind;
660 ULONG ReturnedLength;
661 PVIDEO_ACCESS_RANGE LegacyAccessRanges;
662 ULONG LegacyAccessRangeCount;
663 PDRIVER_OBJECT DriverObject;
664 ULONG ListSize;
665 PIO_RESOURCE_REQUIREMENTS_LIST ResReqList;
666 BOOLEAN DeviceAndVendorFound = FALSE;
667
668 TRACE_(VIDEOPRT, "VideoPortGetAccessRanges(%d, %p, %d, %p)\n",
669 NumRequestedResources, RequestedResources, NumAccessRanges, AccessRanges);
670
671 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
672 DriverObject = DeviceExtension->DriverObject;
673 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
674
675 if (NumRequestedResources == 0)
676 {
677 AllocatedResources = DeviceExtension->AllocatedResources;
678 if (AllocatedResources == NULL &&
679 DeviceExtension->AdapterInterfaceType == PCIBus)
680 {
681 if (DeviceExtension->PhysicalDeviceObject != NULL)
682 {
683 PciSlotNumber.u.AsULONG = DeviceExtension->SystemIoSlotNumber;
684
685 ReturnedLength = HalGetBusData(PCIConfiguration,
686 DeviceExtension->SystemIoBusNumber,
687 PciSlotNumber.u.AsULONG,
688 &Config,
689 sizeof(Config));
690
691 if (ReturnedLength != sizeof(Config))
692 {
693 return ERROR_NOT_ENOUGH_MEMORY;
694 }
695 }
696 else
697 {
698 VendorIdToFind = VendorId != NULL ? *(PUSHORT)VendorId : 0;
699 DeviceIdToFind = DeviceId != NULL ? *(PUSHORT)DeviceId : 0;
700
701 if (VendorIdToFind == 0 && DeviceIdToFind == 0)
702 {
703 /* We're screwed */
704 return ERROR_DEV_NOT_EXIST;
705 }
706
707 INFO_(VIDEOPRT, "Looking for VendorId 0x%04x DeviceId 0x%04x\n",
708 VendorIdToFind, DeviceIdToFind);
709
710 /*
711 * Search for the device id and vendor id on this bus.
712 */
713 PciSlotNumber.u.bits.Reserved = 0;
714 for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
715 {
716 PciSlotNumber.u.bits.DeviceNumber = DeviceNumber;
717 for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
718 {
719 INFO_(VIDEOPRT, "- Function number: %d\n", FunctionNumber);
720 PciSlotNumber.u.bits.FunctionNumber = FunctionNumber;
721 ReturnedLength = HalGetBusData(PCIConfiguration,
722 DeviceExtension->SystemIoBusNumber,
723 PciSlotNumber.u.AsULONG,
724 &Config,
725 sizeof(Config));
726
727 INFO_(VIDEOPRT, "- Length of data: %x\n", ReturnedLength);
728
729 if (ReturnedLength == sizeof(Config))
730 {
731 INFO_(VIDEOPRT, "- Slot 0x%02x (Device %d Function %d) VendorId 0x%04x "
732 "DeviceId 0x%04x\n",
733 PciSlotNumber.u.AsULONG,
734 PciSlotNumber.u.bits.DeviceNumber,
735 PciSlotNumber.u.bits.FunctionNumber,
736 Config.VendorID,
737 Config.DeviceID);
738
739 if ((VendorIdToFind == 0 || Config.VendorID == VendorIdToFind) &&
740 (DeviceIdToFind == 0 || Config.DeviceID == DeviceIdToFind))
741 {
742 DeviceAndVendorFound = TRUE;
743 break;
744 }
745 }
746 }
747 if (DeviceAndVendorFound)
748 break;
749 }
750 if (FunctionNumber == PCI_MAX_FUNCTION)
751 {
752 WARN_(VIDEOPRT, "Didn't find device.\n");
753 return ERROR_DEV_NOT_EXIST;
754 }
755 }
756
757 Status = HalAssignSlotResources(&DeviceExtension->RegistryPath,
758 NULL,
759 DeviceExtension->DriverObject,
760 DeviceExtension->DriverObject->DeviceObject,
761 DeviceExtension->AdapterInterfaceType,
762 DeviceExtension->SystemIoBusNumber,
763 PciSlotNumber.u.AsULONG,
764 &AllocatedResources);
765 if (!NT_SUCCESS(Status))
766 {
767 WARN_(VIDEOPRT, "HalAssignSlotResources failed with status %x.\n",Status);
768 return Status;
769 }
770 DeviceExtension->AllocatedResources = AllocatedResources;
771 DeviceExtension->SystemIoSlotNumber = PciSlotNumber.u.AsULONG;
772
773 /* Add legacy resources to the resources from HAL */
774 Status = IntVideoPortGetLegacyResources(DriverExtension, DeviceExtension,
775 &LegacyAccessRanges, &LegacyAccessRangeCount);
776 if (!NT_SUCCESS(Status))
777 return ERROR_DEV_NOT_EXIST;
778
779 if (NumAccessRanges < LegacyAccessRangeCount)
780 {
781 ERR_(VIDEOPRT, "Too many legacy access ranges found\n");
782 return ERROR_NOT_ENOUGH_MEMORY; // ERROR_MORE_DATA;
783 }
784
785 RtlCopyMemory(AccessRanges, LegacyAccessRanges, LegacyAccessRangeCount * sizeof(VIDEO_ACCESS_RANGE));
786 AssignedCount = LegacyAccessRangeCount;
787 }
788 }
789 else
790 {
791 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + (NumRequestedResources - 1) * sizeof(IO_RESOURCE_DESCRIPTOR);
792 ResReqList = ExAllocatePool(NonPagedPool, ListSize);
793 if (!ResReqList)
794 return ERROR_NOT_ENOUGH_MEMORY;
795
796 ResReqList->ListSize = ListSize;
797 ResReqList->InterfaceType = DeviceExtension->AdapterInterfaceType;
798 ResReqList->BusNumber = DeviceExtension->SystemIoBusNumber;
799 ResReqList->SlotNumber = DeviceExtension->SystemIoSlotNumber;
800 ResReqList->AlternativeLists = 1;
801 ResReqList->List[0].Version = 1;
802 ResReqList->List[0].Revision = 1;
803 ResReqList->List[0].Count = NumRequestedResources;
804
805 /* Copy in the caller's resource list */
806 RtlCopyMemory(ResReqList->List[0].Descriptors,
807 RequestedResources,
808 NumRequestedResources * sizeof(IO_RESOURCE_DESCRIPTOR));
809
810 Status = IoAssignResources(&DeviceExtension->RegistryPath,
811 NULL,
812 DeviceExtension->DriverObject,
813 DeviceExtension->PhysicalDeviceObject ?
814 DeviceExtension->PhysicalDeviceObject :
815 DeviceExtension->DriverObject->DeviceObject,
816 ResReqList,
817 &AllocatedResources);
818
819 if (!NT_SUCCESS(Status))
820 return Status;
821
822 if (!DeviceExtension->AllocatedResources)
823 DeviceExtension->AllocatedResources = AllocatedResources;
824 }
825
826 if (AllocatedResources == NULL)
827 return ERROR_NOT_ENOUGH_MEMORY;
828
829 /* Return the slot number if the caller wants it */
830 if (Slot != NULL) *Slot = DeviceExtension->SystemIoBusNumber;
831
832 FullList = AllocatedResources->List;
833 ASSERT(AllocatedResources->Count == 1);
834 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
835 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber,
836 FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
837
838 ASSERT(FullList->InterfaceType == PCIBus);
839 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
840 ASSERT(1 == FullList->PartialResourceList.Version);
841 ASSERT(1 == FullList->PartialResourceList.Revision);
842
843 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
844 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
845 Descriptor++)
846 {
847 if ((Descriptor->Type == CmResourceTypeMemory ||
848 Descriptor->Type == CmResourceTypePort) &&
849 AssignedCount >= NumAccessRanges)
850 {
851 ERR_(VIDEOPRT, "Too many access ranges found\n");
852 return ERROR_MORE_DATA;
853 }
854 else if (Descriptor->Type == CmResourceTypeMemory)
855 {
856 INFO_(VIDEOPRT, "Memory range starting at 0x%08x length 0x%08x\n",
857 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
858 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
859 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
860 AccessRanges[AssignedCount].RangeInIoSpace = 0;
861 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
862 AccessRanges[AssignedCount].RangeShareable =
863 (Descriptor->ShareDisposition == CmResourceShareShared);
864 AccessRanges[AssignedCount].RangePassive = 0;
865 AssignedCount++;
866 }
867 else if (Descriptor->Type == CmResourceTypePort)
868 {
869 INFO_(VIDEOPRT, "Port range starting at 0x%04x length %d\n",
870 Descriptor->u.Port.Start.u.LowPart, Descriptor->u.Port.Length);
871 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
872 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
873 AccessRanges[AssignedCount].RangeInIoSpace = 1;
874 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
875 AccessRanges[AssignedCount].RangeShareable =
876 (Descriptor->ShareDisposition == CmResourceShareShared);
877 AccessRanges[AssignedCount].RangePassive = 0;
878 if (Descriptor->Flags & CM_RESOURCE_PORT_10_BIT_DECODE)
879 AccessRanges[AssignedCount].RangePassive |= VIDEO_RANGE_10_BIT_DECODE;
880 if (Descriptor->Flags & CM_RESOURCE_PORT_PASSIVE_DECODE)
881 AccessRanges[AssignedCount].RangePassive |= VIDEO_RANGE_PASSIVE_DECODE;
882 AssignedCount++;
883 }
884 else if (Descriptor->Type == CmResourceTypeInterrupt)
885 {
886 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
887 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
888 if (Descriptor->ShareDisposition == CmResourceShareShared)
889 DeviceExtension->InterruptShared = TRUE;
890 else
891 DeviceExtension->InterruptShared = FALSE;
892 }
893 // else if (Descriptor->Type == CmResourceTypeDma) // TODO!
894 else
895 {
896 ASSERT(FALSE);
897 return ERROR_INVALID_PARAMETER;
898 }
899 }
900
901 return NO_ERROR;
902 }
903
904 /**
905 * @brief
906 * Claims or releases a range of hardware resources and checks for conflicts.
907 *
908 * @param[in] HwDeviceExtension
909 * The miniport device extension.
910 *
911 * @param[in] NumAccessRanges
912 * The number of hardware resource ranges in the @p AccessRanges array.
913 * Specify zero to release the hardware resources held by the miniport.
914 *
915 * @param[in] AccessRanges
916 * The array of hardware resource ranges to claim ownership.
917 * Specify NULL to release the hardware resources held by the miniport.
918 *
919 * @return
920 * - NO_ERROR if the resources have been successfully claimed or released.
921 * - ERROR_INVALID_PARAMETER if an error or a conflict occurred.
922 * - ERROR_NOT_ENOUGH_MEMORY if there is not enough memory available.
923 **/
924 VP_STATUS
925 NTAPI
VideoPortVerifyAccessRanges(_In_ PVOID HwDeviceExtension,_In_opt_ ULONG NumAccessRanges,_In_reads_opt_ (NumAccessRanges)PVIDEO_ACCESS_RANGE AccessRanges)926 VideoPortVerifyAccessRanges(
927 _In_ PVOID HwDeviceExtension,
928 _In_opt_ ULONG NumAccessRanges,
929 _In_reads_opt_(NumAccessRanges) PVIDEO_ACCESS_RANGE AccessRanges)
930 {
931 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
932 BOOLEAN ConflictDetected;
933 ULONG ResourceListSize;
934 PCM_RESOURCE_LIST ResourceList;
935 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
936 ULONG i;
937 NTSTATUS Status;
938
939 TRACE_(VIDEOPRT, "VideoPortVerifyAccessRanges\n");
940
941 /* Verify parameters */
942 if (NumAccessRanges && !AccessRanges)
943 return ERROR_INVALID_PARAMETER;
944
945 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
946
947 if (NumAccessRanges == 0)
948 {
949 /* Release the resources and do nothing more for now... */
950 IntVideoPortReleaseResources(DeviceExtension);
951 return NO_ERROR;
952 }
953
954 /* Create the resource list */
955 ResourceListSize = sizeof(CM_RESOURCE_LIST)
956 + (NumAccessRanges - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
957 ResourceList = ExAllocatePoolWithTag(PagedPool, ResourceListSize, TAG_VIDEO_PORT);
958 if (!ResourceList)
959 {
960 WARN_(VIDEOPRT, "ExAllocatePool() failed\n");
961 return ERROR_NOT_ENOUGH_MEMORY;
962 }
963
964 /* Fill resource list */
965 ResourceList->Count = 1;
966 ResourceList->List[0].InterfaceType = DeviceExtension->AdapterInterfaceType;
967 ResourceList->List[0].BusNumber = DeviceExtension->SystemIoBusNumber;
968 ResourceList->List[0].PartialResourceList.Version = 1;
969 ResourceList->List[0].PartialResourceList.Revision = 1;
970 ResourceList->List[0].PartialResourceList.Count = NumAccessRanges;
971 for (i = 0; i < NumAccessRanges; i++, AccessRanges++)
972 {
973 PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
974 if (AccessRanges->RangeInIoSpace)
975 {
976 PartialDescriptor->Type = CmResourceTypePort;
977 PartialDescriptor->u.Port.Start = AccessRanges->RangeStart;
978 PartialDescriptor->u.Port.Length = AccessRanges->RangeLength;
979 }
980 else
981 {
982 PartialDescriptor->Type = CmResourceTypeMemory;
983 PartialDescriptor->u.Memory.Start = AccessRanges->RangeStart;
984 PartialDescriptor->u.Memory.Length = AccessRanges->RangeLength;
985 }
986 if (AccessRanges->RangeShareable)
987 PartialDescriptor->ShareDisposition = CmResourceShareShared;
988 else
989 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
990 PartialDescriptor->Flags = 0;
991 if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
992 PartialDescriptor->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
993 if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE)
994 PartialDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
995 }
996
997 /* Try to acquire all resource ranges */
998 Status = IoReportResourceForDetection(
999 DeviceExtension->DriverObject,
1000 NULL, 0, /* Driver List */
1001 DeviceExtension->PhysicalDeviceObject,
1002 ResourceList, ResourceListSize,
1003 &ConflictDetected);
1004
1005 ExFreePoolWithTag(ResourceList, TAG_VIDEO_PORT);
1006
1007 /* If VgaSave driver is conflicting and we don't explicitely want
1008 * to use it, ignore the problem (because win32k will try to use
1009 * this driver only if all other ones are failing). */
1010 if (Status == STATUS_CONFLICTING_ADDRESSES &&
1011 IntIsVgaSaveDriver(DeviceExtension) &&
1012 !VpBaseVideo)
1013 {
1014 return NO_ERROR;
1015 }
1016
1017 if (!NT_SUCCESS(Status) || ConflictDetected)
1018 return ERROR_INVALID_PARAMETER;
1019 else
1020 return NO_ERROR;
1021 }
1022
1023 /*
1024 * @unimplemented
1025 */
1026
1027 VP_STATUS NTAPI
VideoPortGetDeviceData(IN PVOID HwDeviceExtension,IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,IN PVOID Context)1028 VideoPortGetDeviceData(
1029 IN PVOID HwDeviceExtension,
1030 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
1031 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
1032 IN PVOID Context)
1033 {
1034 TRACE_(VIDEOPRT, "VideoPortGetDeviceData\n");
1035 UNIMPLEMENTED;
1036 return ERROR_INVALID_FUNCTION;
1037 }
1038
1039 /*
1040 * @implemented
1041 */
1042
1043 PVOID NTAPI
VideoPortAllocatePool(IN PVOID HwDeviceExtension,IN VP_POOL_TYPE PoolType,IN SIZE_T NumberOfBytes,IN ULONG Tag)1044 VideoPortAllocatePool(
1045 IN PVOID HwDeviceExtension,
1046 IN VP_POOL_TYPE PoolType,
1047 IN SIZE_T NumberOfBytes,
1048 IN ULONG Tag)
1049 {
1050 TRACE_(VIDEOPRT, "VideoPortAllocatePool\n");
1051 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
1052 }
1053
1054 /*
1055 * @implemented
1056 */
1057
1058 VOID NTAPI
VideoPortFreePool(IN PVOID HwDeviceExtension,IN PVOID Ptr)1059 VideoPortFreePool(
1060 IN PVOID HwDeviceExtension,
1061 IN PVOID Ptr)
1062 {
1063 ExFreePool(Ptr);
1064 }
1065
1066 /*
1067 * @implemented
1068 */
1069
1070 VP_STATUS NTAPI
VideoPortAllocateBuffer(IN PVOID HwDeviceExtension,IN ULONG Size,OUT PVOID * Buffer)1071 VideoPortAllocateBuffer(
1072 IN PVOID HwDeviceExtension,
1073 IN ULONG Size,
1074 OUT PVOID *Buffer)
1075 {
1076 TRACE_(VIDEOPRT, "VideoPortAllocateBuffer\n");
1077 *Buffer = ExAllocatePoolWithTag ( PagedPool, Size, TAG_VIDEO_PORT_BUFFER ) ;
1078 return *Buffer == NULL ? ERROR_NOT_ENOUGH_MEMORY : NO_ERROR;
1079 }
1080
1081 /*
1082 * @implemented
1083 */
1084
1085 VOID NTAPI
VideoPortReleaseBuffer(IN PVOID HwDeviceExtension,IN PVOID Ptr)1086 VideoPortReleaseBuffer(
1087 IN PVOID HwDeviceExtension,
1088 IN PVOID Ptr)
1089 {
1090 TRACE_(VIDEOPRT, "VideoPortReleaseBuffer\n");
1091 ExFreePool(Ptr);
1092 }
1093
1094 /*
1095 * @implemented
1096 */
1097
1098 PVOID NTAPI
VideoPortLockBuffer(IN PVOID HwDeviceExtension,IN PVOID BaseAddress,IN ULONG Length,IN VP_LOCK_OPERATION Operation)1099 VideoPortLockBuffer(
1100 IN PVOID HwDeviceExtension,
1101 IN PVOID BaseAddress,
1102 IN ULONG Length,
1103 IN VP_LOCK_OPERATION Operation)
1104 {
1105 PMDL Mdl;
1106
1107 Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, FALSE, NULL);
1108 if (!Mdl)
1109 {
1110 return NULL;
1111 }
1112 /* FIXME use seh */
1113 MmProbeAndLockPages(Mdl, KernelMode,Operation);
1114 return Mdl;
1115 }
1116
1117 /*
1118 * @implemented
1119 */
1120
1121 BOOLEAN
1122 NTAPI
VideoPortLockPages(IN PVOID HwDeviceExtension,IN OUT PVIDEO_REQUEST_PACKET pVrp,IN PEVENT pUEvent,IN PEVENT pDisplayEvent,IN DMA_FLAGS DmaFlags)1123 VideoPortLockPages(
1124 IN PVOID HwDeviceExtension,
1125 IN OUT PVIDEO_REQUEST_PACKET pVrp,
1126 IN PEVENT pUEvent,
1127 IN PEVENT pDisplayEvent,
1128 IN DMA_FLAGS DmaFlags)
1129 {
1130 PVOID Buffer;
1131
1132 /* clear output buffer */
1133 pVrp->OutputBuffer = NULL;
1134
1135 if (DmaFlags != VideoPortDmaInitOnly)
1136 {
1137 /* VideoPortKeepPagesLocked / VideoPortUnlockAfterDma is no-op */
1138 return FALSE;
1139 }
1140
1141 /* lock the buffer */
1142 Buffer = VideoPortLockBuffer(HwDeviceExtension, pVrp->InputBuffer, pVrp->InputBufferLength, IoModifyAccess);
1143
1144 if (Buffer)
1145 {
1146 /* store result buffer & length */
1147 pVrp->OutputBuffer = Buffer;
1148 pVrp->OutputBufferLength = pVrp->InputBufferLength;
1149
1150 /* operation succeeded */
1151 return TRUE;
1152 }
1153
1154 /* operation failed */
1155 return FALSE;
1156 }
1157
1158
1159 /*
1160 * @implemented
1161 */
1162
1163 VOID NTAPI
VideoPortUnlockBuffer(IN PVOID HwDeviceExtension,IN PVOID Mdl)1164 VideoPortUnlockBuffer(
1165 IN PVOID HwDeviceExtension,
1166 IN PVOID Mdl)
1167 {
1168 if (Mdl)
1169 {
1170 MmUnlockPages((PMDL)Mdl);
1171 IoFreeMdl(Mdl);
1172 }
1173 }
1174
1175 /*
1176 * @unimplemented
1177 */
1178
1179 VP_STATUS NTAPI
VideoPortSetTrappedEmulatorPorts(IN PVOID HwDeviceExtension,IN ULONG NumAccessRanges,IN PVIDEO_ACCESS_RANGE AccessRange)1180 VideoPortSetTrappedEmulatorPorts(
1181 IN PVOID HwDeviceExtension,
1182 IN ULONG NumAccessRanges,
1183 IN PVIDEO_ACCESS_RANGE AccessRange)
1184 {
1185 UNIMPLEMENTED;
1186 /* Should store the ranges in the device extension for use by ntvdm. */
1187 return NO_ERROR;
1188 }
1189
1190 /*
1191 * @implemented
1192 */
1193
1194 ULONG NTAPI
VideoPortGetBusData(IN PVOID HwDeviceExtension,IN BUS_DATA_TYPE BusDataType,IN ULONG SlotNumber,OUT PVOID Buffer,IN ULONG Offset,IN ULONG Length)1195 VideoPortGetBusData(
1196 IN PVOID HwDeviceExtension,
1197 IN BUS_DATA_TYPE BusDataType,
1198 IN ULONG SlotNumber,
1199 OUT PVOID Buffer,
1200 IN ULONG Offset,
1201 IN ULONG Length)
1202 {
1203 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1204
1205 TRACE_(VIDEOPRT, "VideoPortGetBusData\n");
1206
1207 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1208
1209 if (BusDataType != Cmos)
1210 {
1211 /* Legacy vs. PnP behaviour */
1212 if (DeviceExtension->PhysicalDeviceObject != NULL)
1213 SlotNumber = DeviceExtension->SystemIoSlotNumber;
1214 }
1215
1216 return HalGetBusDataByOffset(
1217 BusDataType,
1218 DeviceExtension->SystemIoBusNumber,
1219 SlotNumber,
1220 Buffer,
1221 Offset,
1222 Length);
1223 }
1224
1225 /*
1226 * @implemented
1227 */
1228
1229 ULONG NTAPI
VideoPortSetBusData(IN PVOID HwDeviceExtension,IN BUS_DATA_TYPE BusDataType,IN ULONG SlotNumber,IN PVOID Buffer,IN ULONG Offset,IN ULONG Length)1230 VideoPortSetBusData(
1231 IN PVOID HwDeviceExtension,
1232 IN BUS_DATA_TYPE BusDataType,
1233 IN ULONG SlotNumber,
1234 IN PVOID Buffer,
1235 IN ULONG Offset,
1236 IN ULONG Length)
1237 {
1238 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1239
1240 TRACE_(VIDEOPRT, "VideoPortSetBusData\n");
1241
1242 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1243
1244 if (BusDataType != Cmos)
1245 {
1246 /* Legacy vs. PnP behaviour */
1247 if (DeviceExtension->PhysicalDeviceObject != NULL)
1248 SlotNumber = DeviceExtension->SystemIoSlotNumber;
1249 }
1250
1251 return HalSetBusDataByOffset(
1252 BusDataType,
1253 DeviceExtension->SystemIoBusNumber,
1254 SlotNumber,
1255 Buffer,
1256 Offset,
1257 Length);
1258 }
1259