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