[VIDEOPRT] Fix uninitialized Reserved bit field in PciSlotNumber
[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 PciSlotNumber.u.bits.Reserved = 0;
633 for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
634 {
635 PciSlotNumber.u.bits.DeviceNumber = DeviceNumber;
636 for (FunctionNumber = 0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
637 {
638 INFO_(VIDEOPRT, "- Function number: %d\n", FunctionNumber);
639 PciSlotNumber.u.bits.FunctionNumber = FunctionNumber;
640 ReturnedLength = HalGetBusData(PCIConfiguration,
641 DeviceExtension->SystemIoBusNumber,
642 PciSlotNumber.u.AsULONG,
643 &Config,
644 sizeof(PCI_COMMON_CONFIG));
645 INFO_(VIDEOPRT, "- Length of data: %x\n", ReturnedLength);
646 if (ReturnedLength == sizeof(PCI_COMMON_CONFIG))
647 {
648 INFO_(VIDEOPRT, "- Slot 0x%02x (Device %d Function %d) VendorId 0x%04x "
649 "DeviceId 0x%04x\n",
650 PciSlotNumber.u.AsULONG,
651 PciSlotNumber.u.bits.DeviceNumber,
652 PciSlotNumber.u.bits.FunctionNumber,
653 Config.VendorID,
654 Config.DeviceID);
655
656 if ((VendorIdToFind == 0 || Config.VendorID == VendorIdToFind) &&
657 (DeviceIdToFind == 0 || Config.DeviceID == DeviceIdToFind))
658 {
659 DeviceAndVendorFound = TRUE;
660 break;
661 }
662 }
663 }
664 if (DeviceAndVendorFound) break;
665 }
666 if (FunctionNumber == PCI_MAX_FUNCTION)
667 {
668 WARN_(VIDEOPRT, "Didn't find device.\n");
669 return ERROR_DEV_NOT_EXIST;
670 }
671 }
672
673 Status = HalAssignSlotResources(&DeviceExtension->RegistryPath,
674 NULL,
675 DeviceExtension->DriverObject,
676 DeviceExtension->DriverObject->DeviceObject,
677 DeviceExtension->AdapterInterfaceType,
678 DeviceExtension->SystemIoBusNumber,
679 PciSlotNumber.u.AsULONG,
680 &AllocatedResources);
681
682 if (!NT_SUCCESS(Status))
683 {
684 WARN_(VIDEOPRT, "HalAssignSlotResources failed with status %x.\n",Status);
685 return Status;
686 }
687 DeviceExtension->AllocatedResources = AllocatedResources;
688 DeviceExtension->SystemIoSlotNumber = PciSlotNumber.u.AsULONG;
689
690 /* Add legacy resources to the resources from HAL */
691 Status = IntVideoPortGetLegacyResources(DriverExtension, DeviceExtension,
692 &LegacyAccessRanges, &LegacyAccessRangeCount);
693 if (!NT_SUCCESS(Status))
694 return ERROR_DEV_NOT_EXIST;
695
696 if (NumAccessRanges < LegacyAccessRangeCount)
697 {
698 ERR_(VIDEOPRT, "Too many legacy access ranges found\n");
699 return ERROR_NOT_ENOUGH_MEMORY;
700 }
701
702 RtlCopyMemory(AccessRanges, LegacyAccessRanges, LegacyAccessRangeCount * sizeof(VIDEO_ACCESS_RANGE));
703 AssignedCount = LegacyAccessRangeCount;
704 }
705 }
706 else
707 {
708 ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + (NumRequestedResources - 1) * sizeof(IO_RESOURCE_DESCRIPTOR);
709 ResReqList = ExAllocatePool(NonPagedPool, ListSize);
710 if (!ResReqList) return ERROR_NOT_ENOUGH_MEMORY;
711
712 ResReqList->ListSize = ListSize;
713 ResReqList->InterfaceType = DeviceExtension->AdapterInterfaceType;
714 ResReqList->BusNumber = DeviceExtension->SystemIoBusNumber;
715 ResReqList->SlotNumber = DeviceExtension->SystemIoSlotNumber;
716 ResReqList->AlternativeLists = 1;
717 ResReqList->List[0].Version = 1;
718 ResReqList->List[0].Revision = 1;
719 ResReqList->List[0].Count = NumRequestedResources;
720
721 /* Copy in the caller's resource list */
722 RtlCopyMemory(ResReqList->List[0].Descriptors,
723 RequestedResources,
724 NumRequestedResources * sizeof(IO_RESOURCE_DESCRIPTOR));
725
726 Status = IoAssignResources(&DeviceExtension->RegistryPath,
727 NULL,
728 DeviceExtension->DriverObject,
729 DeviceExtension->PhysicalDeviceObject ?
730 DeviceExtension->PhysicalDeviceObject :
731 DeviceExtension->DriverObject->DeviceObject,
732 ResReqList,
733 &AllocatedResources);
734
735 if (!NT_SUCCESS(Status))
736 return Status;
737
738 if (!DeviceExtension->AllocatedResources)
739 DeviceExtension->AllocatedResources = AllocatedResources;
740 }
741
742 if (AllocatedResources == NULL)
743 return ERROR_NOT_ENOUGH_MEMORY;
744
745 /* Return the slot number if the caller wants it */
746 if (Slot != NULL) *Slot = DeviceExtension->SystemIoBusNumber;
747
748 FullList = AllocatedResources->List;
749 ASSERT(AllocatedResources->Count == 1);
750 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
751 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
752
753 ASSERT(FullList->InterfaceType == PCIBus);
754 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
755 ASSERT(1 == FullList->PartialResourceList.Version);
756 ASSERT(1 == FullList->PartialResourceList.Revision);
757 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
758 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
759 Descriptor++)
760 {
761 if ((Descriptor->Type == CmResourceTypeMemory ||
762 Descriptor->Type == CmResourceTypePort) &&
763 AssignedCount >= NumAccessRanges)
764 {
765 ERR_(VIDEOPRT, "Too many access ranges found\n");
766 return ERROR_NOT_ENOUGH_MEMORY;
767 }
768 if (Descriptor->Type == CmResourceTypeMemory)
769 {
770 INFO_(VIDEOPRT, "Memory range starting at 0x%08x length 0x%08x\n",
771 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
772 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
773 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
774 AccessRanges[AssignedCount].RangeInIoSpace = 0;
775 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
776 AccessRanges[AssignedCount].RangeShareable =
777 (Descriptor->ShareDisposition == CmResourceShareShared);
778 AccessRanges[AssignedCount].RangePassive = 0;
779 AssignedCount++;
780 }
781 else if (Descriptor->Type == CmResourceTypePort)
782 {
783 INFO_(VIDEOPRT, "Port range starting at 0x%04x length %d\n",
784 Descriptor->u.Port.Start.u.LowPart, Descriptor->u.Port.Length);
785 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
786 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
787 AccessRanges[AssignedCount].RangeInIoSpace = 1;
788 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
789 AccessRanges[AssignedCount].RangeShareable =
790 (Descriptor->ShareDisposition == CmResourceShareShared);
791 AccessRanges[AssignedCount].RangePassive = 0;
792 if (Descriptor->Flags & CM_RESOURCE_PORT_10_BIT_DECODE)
793 AccessRanges[AssignedCount].RangePassive |= VIDEO_RANGE_10_BIT_DECODE;
794 if (Descriptor->Flags & CM_RESOURCE_PORT_PASSIVE_DECODE)
795 AccessRanges[AssignedCount].RangePassive |= VIDEO_RANGE_PASSIVE_DECODE;
796 AssignedCount++;
797 }
798 else if (Descriptor->Type == CmResourceTypeInterrupt)
799 {
800 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
801 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
802 if (Descriptor->ShareDisposition == CmResourceShareShared)
803 DeviceExtension->InterruptShared = TRUE;
804 else
805 DeviceExtension->InterruptShared = FALSE;
806 }
807 }
808
809 return NO_ERROR;
810 }
811
812 /*
813 * @implemented
814 */
815
816 VP_STATUS NTAPI
817 VideoPortVerifyAccessRanges(
818 IN PVOID HwDeviceExtension,
819 IN ULONG NumAccessRanges,
820 IN PVIDEO_ACCESS_RANGE AccessRanges)
821 {
822 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
823 BOOLEAN ConflictDetected;
824 ULONG i;
825 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
826 PCM_RESOURCE_LIST ResourceList;
827 ULONG ResourceListSize;
828 NTSTATUS Status;
829
830 TRACE_(VIDEOPRT, "VideoPortVerifyAccessRanges\n");
831
832 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
833
834 /* Create the resource list */
835 ResourceListSize = sizeof(CM_RESOURCE_LIST)
836 + (NumAccessRanges - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
837 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
838 if (!ResourceList)
839 {
840 WARN_(VIDEOPRT, "ExAllocatePool() failed\n");
841 return ERROR_INVALID_PARAMETER;
842 }
843
844 /* Fill resource list */
845 ResourceList->Count = 1;
846 ResourceList->List[0].InterfaceType = DeviceExtension->AdapterInterfaceType;
847 ResourceList->List[0].BusNumber = DeviceExtension->SystemIoBusNumber;
848 ResourceList->List[0].PartialResourceList.Version = 1;
849 ResourceList->List[0].PartialResourceList.Revision = 1;
850 ResourceList->List[0].PartialResourceList.Count = NumAccessRanges;
851 for (i = 0; i < NumAccessRanges; i++, AccessRanges++)
852 {
853 PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
854 if (AccessRanges->RangeInIoSpace)
855 {
856 PartialDescriptor->Type = CmResourceTypePort;
857 PartialDescriptor->u.Port.Start = AccessRanges->RangeStart;
858 PartialDescriptor->u.Port.Length = AccessRanges->RangeLength;
859 }
860 else
861 {
862 PartialDescriptor->Type = CmResourceTypeMemory;
863 PartialDescriptor->u.Memory.Start = AccessRanges->RangeStart;
864 PartialDescriptor->u.Memory.Length = AccessRanges->RangeLength;
865 }
866 if (AccessRanges->RangeShareable)
867 PartialDescriptor->ShareDisposition = CmResourceShareShared;
868 else
869 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
870 PartialDescriptor->Flags = 0;
871 if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
872 PartialDescriptor->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
873 if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE)
874 PartialDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
875 }
876
877 /* Try to acquire all resource ranges */
878 Status = IoReportResourceForDetection(
879 DeviceExtension->DriverObject,
880 NULL, 0, /* Driver List */
881 DeviceExtension->PhysicalDeviceObject,
882 ResourceList, ResourceListSize,
883 &ConflictDetected);
884 ExFreePool(ResourceList);
885
886 if (!NT_SUCCESS(Status) || ConflictDetected)
887 return ERROR_INVALID_PARAMETER;
888 else
889 return NO_ERROR;
890 }
891
892 /*
893 * @unimplemented
894 */
895
896 VP_STATUS NTAPI
897 VideoPortGetDeviceData(
898 IN PVOID HwDeviceExtension,
899 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
900 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
901 IN PVOID Context)
902 {
903 TRACE_(VIDEOPRT, "VideoPortGetDeviceData\n");
904 UNIMPLEMENTED;
905 return ERROR_INVALID_FUNCTION;
906 }
907
908 /*
909 * @implemented
910 */
911
912 PVOID NTAPI
913 VideoPortAllocatePool(
914 IN PVOID HwDeviceExtension,
915 IN VP_POOL_TYPE PoolType,
916 IN SIZE_T NumberOfBytes,
917 IN ULONG Tag)
918 {
919 TRACE_(VIDEOPRT, "VideoPortAllocatePool\n");
920 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
921 }
922
923 /*
924 * @implemented
925 */
926
927 VOID NTAPI
928 VideoPortFreePool(
929 IN PVOID HwDeviceExtension,
930 IN PVOID Ptr)
931 {
932 ExFreePool(Ptr);
933 }
934
935 /*
936 * @implemented
937 */
938
939 VP_STATUS NTAPI
940 VideoPortAllocateBuffer(
941 IN PVOID HwDeviceExtension,
942 IN ULONG Size,
943 OUT PVOID *Buffer)
944 {
945 TRACE_(VIDEOPRT, "VideoPortAllocateBuffer\n");
946 *Buffer = ExAllocatePoolWithTag ( PagedPool, Size, TAG_VIDEO_PORT_BUFFER ) ;
947 return *Buffer == NULL ? ERROR_NOT_ENOUGH_MEMORY : NO_ERROR;
948 }
949
950 /*
951 * @implemented
952 */
953
954 VOID NTAPI
955 VideoPortReleaseBuffer(
956 IN PVOID HwDeviceExtension,
957 IN PVOID Ptr)
958 {
959 TRACE_(VIDEOPRT, "VideoPortReleaseBuffer\n");
960 ExFreePool(Ptr);
961 }
962
963 /*
964 * @implemented
965 */
966
967 PVOID NTAPI
968 VideoPortLockBuffer(
969 IN PVOID HwDeviceExtension,
970 IN PVOID BaseAddress,
971 IN ULONG Length,
972 IN VP_LOCK_OPERATION Operation)
973 {
974 PMDL Mdl;
975
976 Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, FALSE, NULL);
977 if (!Mdl)
978 {
979 return NULL;
980 }
981 /* FIXME use seh */
982 MmProbeAndLockPages(Mdl, KernelMode,Operation);
983 return Mdl;
984 }
985
986 /*
987 * @implemented
988 */
989
990 BOOLEAN
991 NTAPI
992 VideoPortLockPages(
993 IN PVOID HwDeviceExtension,
994 IN OUT PVIDEO_REQUEST_PACKET pVrp,
995 IN PEVENT pUEvent,
996 IN PEVENT pDisplayEvent,
997 IN DMA_FLAGS DmaFlags)
998 {
999 PVOID Buffer;
1000
1001 /* clear output buffer */
1002 pVrp->OutputBuffer = NULL;
1003
1004 if (DmaFlags != VideoPortDmaInitOnly)
1005 {
1006 /* VideoPortKeepPagesLocked / VideoPortUnlockAfterDma is no-op */
1007 return FALSE;
1008 }
1009
1010 /* lock the buffer */
1011 Buffer = VideoPortLockBuffer(HwDeviceExtension, pVrp->InputBuffer, pVrp->InputBufferLength, IoModifyAccess);
1012
1013 if (Buffer)
1014 {
1015 /* store result buffer & length */
1016 pVrp->OutputBuffer = Buffer;
1017 pVrp->OutputBufferLength = pVrp->InputBufferLength;
1018
1019 /* operation succeeded */
1020 return TRUE;
1021 }
1022
1023 /* operation failed */
1024 return FALSE;
1025 }
1026
1027
1028 /*
1029 * @implemented
1030 */
1031
1032 VOID NTAPI
1033 VideoPortUnlockBuffer(
1034 IN PVOID HwDeviceExtension,
1035 IN PVOID Mdl)
1036 {
1037 if (Mdl)
1038 {
1039 MmUnlockPages((PMDL)Mdl);
1040 IoFreeMdl(Mdl);
1041 }
1042 }
1043
1044 /*
1045 * @unimplemented
1046 */
1047
1048 VP_STATUS NTAPI
1049 VideoPortSetTrappedEmulatorPorts(
1050 IN PVOID HwDeviceExtension,
1051 IN ULONG NumAccessRanges,
1052 IN PVIDEO_ACCESS_RANGE AccessRange)
1053 {
1054 UNIMPLEMENTED;
1055 /* Should store the ranges in the device extension for use by ntvdm. */
1056 return NO_ERROR;
1057 }
1058
1059 /*
1060 * @implemented
1061 */
1062
1063 ULONG NTAPI
1064 VideoPortGetBusData(
1065 IN PVOID HwDeviceExtension,
1066 IN BUS_DATA_TYPE BusDataType,
1067 IN ULONG SlotNumber,
1068 OUT PVOID Buffer,
1069 IN ULONG Offset,
1070 IN ULONG Length)
1071 {
1072 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1073
1074 TRACE_(VIDEOPRT, "VideoPortGetBusData\n");
1075
1076 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1077
1078 if (BusDataType != Cmos)
1079 {
1080 /* Legacy vs. PnP behaviour */
1081 if (DeviceExtension->PhysicalDeviceObject != NULL)
1082 SlotNumber = DeviceExtension->SystemIoSlotNumber;
1083 }
1084
1085 return HalGetBusDataByOffset(
1086 BusDataType,
1087 DeviceExtension->SystemIoBusNumber,
1088 SlotNumber,
1089 Buffer,
1090 Offset,
1091 Length);
1092 }
1093
1094 /*
1095 * @implemented
1096 */
1097
1098 ULONG NTAPI
1099 VideoPortSetBusData(
1100 IN PVOID HwDeviceExtension,
1101 IN BUS_DATA_TYPE BusDataType,
1102 IN ULONG SlotNumber,
1103 IN PVOID Buffer,
1104 IN ULONG Offset,
1105 IN ULONG Length)
1106 {
1107 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1108
1109 TRACE_(VIDEOPRT, "VideoPortSetBusData\n");
1110
1111 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1112
1113 if (BusDataType != Cmos)
1114 {
1115 /* Legacy vs. PnP behaviour */
1116 if (DeviceExtension->PhysicalDeviceObject != NULL)
1117 SlotNumber = DeviceExtension->SystemIoSlotNumber;
1118 }
1119
1120 return HalSetBusDataByOffset(
1121 BusDataType,
1122 DeviceExtension->SystemIoBusNumber,
1123 SlotNumber,
1124 Buffer,
1125 Offset,
1126 Length);
1127 }