[SHELL-EXPERIMENTS]
[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 for (FullList = AllocatedResources->List;
748 FullList < AllocatedResources->List + AllocatedResources->Count;
749 FullList++)
750 {
751 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
752 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
753
754 ASSERT(FullList->InterfaceType == PCIBus);
755 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
756 ASSERT(1 == FullList->PartialResourceList.Version);
757 ASSERT(1 == FullList->PartialResourceList.Revision);
758 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
759 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
760 Descriptor++)
761 {
762 if ((Descriptor->Type == CmResourceTypeMemory ||
763 Descriptor->Type == CmResourceTypePort) &&
764 AssignedCount >= NumAccessRanges)
765 {
766 ERR_(VIDEOPRT, "Too many access ranges found\n");
767 return ERROR_NOT_ENOUGH_MEMORY;
768 }
769 if (Descriptor->Type == CmResourceTypeMemory)
770 {
771 INFO_(VIDEOPRT, "Memory range starting at 0x%08x length 0x%08x\n",
772 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
773 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
774 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
775 AccessRanges[AssignedCount].RangeInIoSpace = 0;
776 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
777 AccessRanges[AssignedCount].RangeShareable =
778 (Descriptor->ShareDisposition == CmResourceShareShared);
779 AccessRanges[AssignedCount].RangePassive = 0;
780 AssignedCount++;
781 }
782 else if (Descriptor->Type == CmResourceTypePort)
783 {
784 INFO_(VIDEOPRT, "Port range starting at 0x%04x length %d\n",
785 Descriptor->u.Port.Start.u.LowPart, Descriptor->u.Port.Length);
786 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
787 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
788 AccessRanges[AssignedCount].RangeInIoSpace = 1;
789 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
790 AccessRanges[AssignedCount].RangeShareable =
791 (Descriptor->ShareDisposition == CmResourceShareShared);
792 AccessRanges[AssignedCount].RangePassive = 0;
793 if (Descriptor->Flags & CM_RESOURCE_PORT_10_BIT_DECODE)
794 AccessRanges[AssignedCount].RangePassive |= VIDEO_RANGE_10_BIT_DECODE;
795 if (Descriptor->Flags & CM_RESOURCE_PORT_PASSIVE_DECODE)
796 AccessRanges[AssignedCount].RangePassive |= VIDEO_RANGE_PASSIVE_DECODE;
797 AssignedCount++;
798 }
799 else if (Descriptor->Type == CmResourceTypeInterrupt)
800 {
801 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
802 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
803 if (Descriptor->ShareDisposition == CmResourceShareShared)
804 DeviceExtension->InterruptShared = TRUE;
805 else
806 DeviceExtension->InterruptShared = FALSE;
807 }
808 }
809 }
810
811 return NO_ERROR;
812 }
813
814 /*
815 * @implemented
816 */
817
818 VP_STATUS NTAPI
819 VideoPortVerifyAccessRanges(
820 IN PVOID HwDeviceExtension,
821 IN ULONG NumAccessRanges,
822 IN PVIDEO_ACCESS_RANGE AccessRanges)
823 {
824 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
825 BOOLEAN ConflictDetected;
826 ULONG i;
827 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
828 PCM_RESOURCE_LIST ResourceList;
829 ULONG ResourceListSize;
830 NTSTATUS Status;
831
832 TRACE_(VIDEOPRT, "VideoPortVerifyAccessRanges\n");
833
834 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
835
836 /* Create the resource list */
837 ResourceListSize = sizeof(CM_RESOURCE_LIST)
838 + (NumAccessRanges - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
839 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
840 if (!ResourceList)
841 {
842 WARN_(VIDEOPRT, "ExAllocatePool() failed\n");
843 return ERROR_INVALID_PARAMETER;
844 }
845
846 /* Fill resource list */
847 ResourceList->Count = 1;
848 ResourceList->List[0].InterfaceType = DeviceExtension->AdapterInterfaceType;
849 ResourceList->List[0].BusNumber = DeviceExtension->SystemIoBusNumber;
850 ResourceList->List[0].PartialResourceList.Version = 1;
851 ResourceList->List[0].PartialResourceList.Revision = 1;
852 ResourceList->List[0].PartialResourceList.Count = NumAccessRanges;
853 for (i = 0; i < NumAccessRanges; i++, AccessRanges++)
854 {
855 PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
856 if (AccessRanges->RangeInIoSpace)
857 {
858 PartialDescriptor->Type = CmResourceTypePort;
859 PartialDescriptor->u.Port.Start = AccessRanges->RangeStart;
860 PartialDescriptor->u.Port.Length = AccessRanges->RangeLength;
861 }
862 else
863 {
864 PartialDescriptor->Type = CmResourceTypeMemory;
865 PartialDescriptor->u.Memory.Start = AccessRanges->RangeStart;
866 PartialDescriptor->u.Memory.Length = AccessRanges->RangeLength;
867 }
868 if (AccessRanges->RangeShareable)
869 PartialDescriptor->ShareDisposition = CmResourceShareShared;
870 else
871 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
872 PartialDescriptor->Flags = 0;
873 if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
874 PartialDescriptor->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
875 if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE)
876 PartialDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
877 }
878
879 /* Try to acquire all resource ranges */
880 Status = IoReportResourceForDetection(
881 DeviceExtension->DriverObject,
882 NULL, 0, /* Driver List */
883 DeviceExtension->PhysicalDeviceObject,
884 ResourceList, ResourceListSize,
885 &ConflictDetected);
886 ExFreePool(ResourceList);
887
888 if (!NT_SUCCESS(Status) || ConflictDetected)
889 return ERROR_INVALID_PARAMETER;
890 else
891 return NO_ERROR;
892 }
893
894 /*
895 * @unimplemented
896 */
897
898 VP_STATUS NTAPI
899 VideoPortGetDeviceData(
900 IN PVOID HwDeviceExtension,
901 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
902 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
903 IN PVOID Context)
904 {
905 TRACE_(VIDEOPRT, "VideoPortGetDeviceData\n");
906 UNIMPLEMENTED;
907 return ERROR_INVALID_FUNCTION;
908 }
909
910 /*
911 * @implemented
912 */
913
914 PVOID NTAPI
915 VideoPortAllocatePool(
916 IN PVOID HwDeviceExtension,
917 IN VP_POOL_TYPE PoolType,
918 IN SIZE_T NumberOfBytes,
919 IN ULONG Tag)
920 {
921 TRACE_(VIDEOPRT, "VideoPortAllocatePool\n");
922 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
923 }
924
925 /*
926 * @implemented
927 */
928
929 VOID NTAPI
930 VideoPortFreePool(
931 IN PVOID HwDeviceExtension,
932 IN PVOID Ptr)
933 {
934 ExFreePool(Ptr);
935 }
936
937 /*
938 * @implemented
939 */
940
941 VP_STATUS NTAPI
942 VideoPortAllocateBuffer(
943 IN PVOID HwDeviceExtension,
944 IN ULONG Size,
945 OUT PVOID *Buffer)
946 {
947 TRACE_(VIDEOPRT, "VideoPortAllocateBuffer\n");
948 *Buffer = ExAllocatePoolWithTag ( PagedPool, Size, TAG_VIDEO_PORT_BUFFER ) ;
949 return *Buffer == NULL ? ERROR_NOT_ENOUGH_MEMORY : NO_ERROR;
950 }
951
952 /*
953 * @implemented
954 */
955
956 VOID NTAPI
957 VideoPortReleaseBuffer(
958 IN PVOID HwDeviceExtension,
959 IN PVOID Ptr)
960 {
961 TRACE_(VIDEOPRT, "VideoPortReleaseBuffer\n");
962 ExFreePool(Ptr);
963 }
964
965 /*
966 * @implemented
967 */
968
969 PVOID NTAPI
970 VideoPortLockBuffer(
971 IN PVOID HwDeviceExtension,
972 IN PVOID BaseAddress,
973 IN ULONG Length,
974 IN VP_LOCK_OPERATION Operation)
975 {
976 PMDL Mdl;
977
978 Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, FALSE, NULL);
979 if (!Mdl)
980 {
981 return NULL;
982 }
983 /* FIXME use seh */
984 MmProbeAndLockPages(Mdl, KernelMode,Operation);
985 return Mdl;
986 }
987
988 /*
989 * @implemented
990 */
991
992 BOOLEAN
993 NTAPI
994 VideoPortLockPages(
995 IN PVOID HwDeviceExtension,
996 IN OUT PVIDEO_REQUEST_PACKET pVrp,
997 IN PEVENT pUEvent,
998 IN PEVENT pDisplayEvent,
999 IN DMA_FLAGS DmaFlags)
1000 {
1001 PVOID Buffer;
1002
1003 /* clear output buffer */
1004 pVrp->OutputBuffer = NULL;
1005
1006 if (DmaFlags != VideoPortDmaInitOnly)
1007 {
1008 /* VideoPortKeepPagesLocked / VideoPortUnlockAfterDma is no-op */
1009 return FALSE;
1010 }
1011
1012 /* lock the buffer */
1013 Buffer = VideoPortLockBuffer(HwDeviceExtension, pVrp->InputBuffer, pVrp->InputBufferLength, IoModifyAccess);
1014
1015 if (Buffer)
1016 {
1017 /* store result buffer & length */
1018 pVrp->OutputBuffer = Buffer;
1019 pVrp->OutputBufferLength = pVrp->InputBufferLength;
1020
1021 /* operation succeeded */
1022 return TRUE;
1023 }
1024
1025 /* operation failed */
1026 return FALSE;
1027 }
1028
1029
1030 /*
1031 * @implemented
1032 */
1033
1034 VOID NTAPI
1035 VideoPortUnlockBuffer(
1036 IN PVOID HwDeviceExtension,
1037 IN PVOID Mdl)
1038 {
1039 if (Mdl)
1040 {
1041 MmUnlockPages((PMDL)Mdl);
1042 IoFreeMdl(Mdl);
1043 }
1044 }
1045
1046 /*
1047 * @unimplemented
1048 */
1049
1050 VP_STATUS NTAPI
1051 VideoPortSetTrappedEmulatorPorts(
1052 IN PVOID HwDeviceExtension,
1053 IN ULONG NumAccessRanges,
1054 IN PVIDEO_ACCESS_RANGE AccessRange)
1055 {
1056 UNIMPLEMENTED;
1057 /* Should store the ranges in the device extension for use by ntvdm. */
1058 return NO_ERROR;
1059 }
1060
1061 /*
1062 * @implemented
1063 */
1064
1065 ULONG NTAPI
1066 VideoPortGetBusData(
1067 IN PVOID HwDeviceExtension,
1068 IN BUS_DATA_TYPE BusDataType,
1069 IN ULONG SlotNumber,
1070 OUT PVOID Buffer,
1071 IN ULONG Offset,
1072 IN ULONG Length)
1073 {
1074 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1075
1076 TRACE_(VIDEOPRT, "VideoPortGetBusData\n");
1077
1078 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1079
1080 if (BusDataType != Cmos)
1081 {
1082 /* Legacy vs. PnP behaviour */
1083 if (DeviceExtension->PhysicalDeviceObject != NULL)
1084 SlotNumber = DeviceExtension->SystemIoSlotNumber;
1085 }
1086
1087 return HalGetBusDataByOffset(
1088 BusDataType,
1089 DeviceExtension->SystemIoBusNumber,
1090 SlotNumber,
1091 Buffer,
1092 Offset,
1093 Length);
1094 }
1095
1096 /*
1097 * @implemented
1098 */
1099
1100 ULONG NTAPI
1101 VideoPortSetBusData(
1102 IN PVOID HwDeviceExtension,
1103 IN BUS_DATA_TYPE BusDataType,
1104 IN ULONG SlotNumber,
1105 IN PVOID Buffer,
1106 IN ULONG Offset,
1107 IN ULONG Length)
1108 {
1109 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
1110
1111 TRACE_(VIDEOPRT, "VideoPortSetBusData\n");
1112
1113 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
1114
1115 if (BusDataType != Cmos)
1116 {
1117 /* Legacy vs. PnP behaviour */
1118 if (DeviceExtension->PhysicalDeviceObject != NULL)
1119 SlotNumber = DeviceExtension->SystemIoSlotNumber;
1120 }
1121
1122 return HalSetBusDataByOffset(
1123 BusDataType,
1124 DeviceExtension->SystemIoBusNumber,
1125 SlotNumber,
1126 Buffer,
1127 Offset,
1128 Length);
1129 }