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