xref: /reactos/win32ss/drivers/videoprt/resource.c (revision 08a68340)
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