- Update to r53061
[reactos.git] / drivers / video / 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 /* PRIVATE FUNCTIONS **********************************************************/
25
26 NTSTATUS NTAPI
27 IntVideoPortMapPhysicalMemory(
28 IN HANDLE Process,
29 IN PHYSICAL_ADDRESS PhysicalAddress,
30 IN ULONG SizeInBytes,
31 IN ULONG Protect,
32 IN OUT PVOID *VirtualAddress OPTIONAL)
33 {
34 OBJECT_ATTRIBUTES ObjAttribs;
35 UNICODE_STRING UnicodeString;
36 HANDLE hMemObj;
37 NTSTATUS Status;
38 SIZE_T Size;
39
40 /* Initialize object attribs */
41 RtlInitUnicodeString(&UnicodeString, L"\\Device\\PhysicalMemory");
42 InitializeObjectAttributes(&ObjAttribs,
43 &UnicodeString,
44 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
45 NULL, NULL);
46
47 /* Open physical memory section */
48 Status = ZwOpenSection(&hMemObj, SECTION_ALL_ACCESS, &ObjAttribs);
49 if (!NT_SUCCESS(Status))
50 {
51 WARN_(VIDEOPRT, "ZwOpenSection() failed! (0x%x)\n", Status);
52 return Status;
53 }
54
55 /* Map view of section */
56 Size = SizeInBytes;
57 Status = ZwMapViewOfSection(hMemObj,
58 Process,
59 VirtualAddress,
60 0,
61 Size,
62 (PLARGE_INTEGER)(&PhysicalAddress),
63 &Size,
64 ViewUnmap,
65 0,
66 Protect);
67 ZwClose(hMemObj);
68 if (!NT_SUCCESS(Status))
69 {
70 WARN_(VIDEOPRT, "ZwMapViewOfSection() failed! (0x%x)\n", Status);
71 }
72
73 return Status;
74 }
75
76
77 PVOID NTAPI
78 IntVideoPortMapMemory(
79 IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
80 IN PHYSICAL_ADDRESS IoAddress,
81 IN ULONG NumberOfUchars,
82 IN ULONG InIoSpace,
83 IN HANDLE ProcessHandle,
84 OUT VP_STATUS *Status)
85 {
86 PHYSICAL_ADDRESS TranslatedAddress;
87 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
88 ULONG AddressSpace;
89 PVOID MappedAddress;
90 PLIST_ENTRY Entry;
91
92 INFO_(VIDEOPRT, "- IoAddress: %lx\n", IoAddress.u.LowPart);
93 INFO_(VIDEOPRT, "- NumberOfUchars: %lx\n", NumberOfUchars);
94 INFO_(VIDEOPRT, "- InIoSpace: %x\n", InIoSpace);
95
96 InIoSpace &= ~VIDEO_MEMORY_SPACE_DENSE;
97 if ((InIoSpace & VIDEO_MEMORY_SPACE_P6CACHE) != 0)
98 {
99 INFO_(VIDEOPRT, "VIDEO_MEMORY_SPACE_P6CACHE not supported, turning off\n");
100 InIoSpace &= ~VIDEO_MEMORY_SPACE_P6CACHE;
101 }
102
103 if (ProcessHandle != NULL && (InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0)
104 {
105 INFO_(VIDEOPRT, "ProcessHandle is not NULL (0x%x) but InIoSpace does not have "
106 "VIDEO_MEMORY_SPACE_USER_MODE set! Setting "
107 "VIDEO_MEMORY_SPACE_USER_MODE.\n",
108 ProcessHandle);
109 InIoSpace |= VIDEO_MEMORY_SPACE_USER_MODE;
110 }
111 else if (ProcessHandle == NULL && (InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
112 {
113 INFO_(VIDEOPRT, "ProcessHandle is NULL (0x%x) but InIoSpace does have "
114 "VIDEO_MEMORY_SPACE_USER_MODE set! Setting ProcessHandle "
115 "to NtCurrentProcess()\n",
116 ProcessHandle);
117 ProcessHandle = NtCurrentProcess();
118 }
119
120 if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0 &&
121 !IsListEmpty(&DeviceExtension->AddressMappingListHead))
122 {
123 Entry = DeviceExtension->AddressMappingListHead.Flink;
124 while (Entry != &DeviceExtension->AddressMappingListHead)
125 {
126 AddressMapping = CONTAINING_RECORD(
127 Entry,
128 VIDEO_PORT_ADDRESS_MAPPING,
129 List);
130 if (IoAddress.QuadPart == AddressMapping->IoAddress.QuadPart &&
131 NumberOfUchars <= AddressMapping->NumberOfUchars)
132 {
133 {
134 AddressMapping->MappingCount++;
135 if (Status)
136 *Status = NO_ERROR;
137 return AddressMapping->MappedAddress;
138 }
139 }
140 Entry = Entry->Flink;
141 }
142 }
143
144 AddressSpace = (ULONG)InIoSpace;
145 AddressSpace &= ~VIDEO_MEMORY_SPACE_USER_MODE;
146 if (HalTranslateBusAddress(
147 DeviceExtension->AdapterInterfaceType,
148 DeviceExtension->SystemIoBusNumber,
149 IoAddress,
150 &AddressSpace,
151 &TranslatedAddress) == FALSE)
152 {
153 if (Status)
154 *Status = ERROR_NOT_ENOUGH_MEMORY;
155
156 return NULL;
157 }
158
159 /* I/O space */
160 if (AddressSpace != 0)
161 {
162 ASSERT(0 == TranslatedAddress.u.HighPart);
163 if (Status)
164 *Status = NO_ERROR;
165
166 return (PVOID)(ULONG_PTR)TranslatedAddress.u.LowPart;
167 }
168
169 /* user space */
170 if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) != 0)
171 {
172 NTSTATUS NtStatus;
173 MappedAddress = NULL;
174 NtStatus = IntVideoPortMapPhysicalMemory(ProcessHandle,
175 TranslatedAddress,
176 NumberOfUchars,
177 PAGE_READWRITE/* | PAGE_WRITECOMBINE*/,
178 &MappedAddress);
179 if (!NT_SUCCESS(NtStatus))
180 {
181 WARN_(VIDEOPRT, "IntVideoPortMapPhysicalMemory() failed! (0x%x)\n", NtStatus);
182 if (Status)
183 *Status = NO_ERROR;
184 return NULL;
185 }
186 INFO_(VIDEOPRT, "Mapped user address = 0x%08x\n", MappedAddress);
187 }
188 else /* kernel space */
189 {
190 MappedAddress = MmMapIoSpace(
191 TranslatedAddress,
192 NumberOfUchars,
193 MmNonCached);
194 }
195
196 if (MappedAddress != NULL)
197 {
198 if (Status)
199 {
200 *Status = NO_ERROR;
201 }
202 if ((InIoSpace & VIDEO_MEMORY_SPACE_USER_MODE) == 0)
203 {
204 AddressMapping = ExAllocatePoolWithTag(
205 PagedPool,
206 sizeof(VIDEO_PORT_ADDRESS_MAPPING),
207 TAG_VIDEO_PORT);
208
209 if (AddressMapping == NULL)
210 return MappedAddress;
211
212 RtlZeroMemory(AddressMapping, sizeof(VIDEO_PORT_ADDRESS_MAPPING));
213 AddressMapping->NumberOfUchars = NumberOfUchars;
214 AddressMapping->IoAddress = IoAddress;
215 AddressMapping->SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
216 AddressMapping->MappedAddress = MappedAddress;
217 AddressMapping->MappingCount = 1;
218 InsertHeadList(
219 &DeviceExtension->AddressMappingListHead,
220 &AddressMapping->List);
221 }
222
223 return MappedAddress;
224 }
225
226 if (Status)
227 *Status = NO_ERROR;
228
229 return NULL;
230 }
231
232 VOID NTAPI
233 IntVideoPortUnmapMemory(
234 IN PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension,
235 IN PVOID MappedAddress)
236 {
237 PVIDEO_PORT_ADDRESS_MAPPING AddressMapping;
238 PLIST_ENTRY Entry;
239 NTSTATUS Status;
240
241 Entry = DeviceExtension->AddressMappingListHead.Flink;
242 while (Entry != &DeviceExtension->AddressMappingListHead)
243 {
244 AddressMapping = CONTAINING_RECORD(
245 Entry,
246 VIDEO_PORT_ADDRESS_MAPPING,
247 List);
248 if (AddressMapping->MappedAddress == MappedAddress)
249 {
250 ASSERT(AddressMapping->MappingCount > 0);
251 AddressMapping->MappingCount--;
252 if (AddressMapping->MappingCount == 0)
253 {
254 MmUnmapIoSpace(
255 AddressMapping->MappedAddress,
256 AddressMapping->NumberOfUchars);
257 RemoveEntryList(Entry);
258 ExFreePool(AddressMapping);
259 }
260 return;
261 }
262
263 Entry = Entry->Flink;
264 }
265
266 /* If there was no kernelmode mapping for the given address found we assume
267 * that the given address is a usermode mapping and try to unmap it.
268 *
269 * FIXME: Is it ok to use NtCurrentProcess?
270 */
271 Status = ZwUnmapViewOfSection(NtCurrentProcess(), MappedAddress);
272 if (!NT_SUCCESS(Status))
273 {
274 WARN_(VIDEOPRT, "Warning: Mapping for address 0x%p not found!\n", MappedAddress);
275 }
276 }
277
278 /* PUBLIC FUNCTIONS ***********************************************************/
279
280 /*
281 * @implemented
282 */
283
284 PVOID NTAPI
285 VideoPortGetDeviceBase(
286 IN PVOID HwDeviceExtension,
287 IN PHYSICAL_ADDRESS IoAddress,
288 IN ULONG NumberOfUchars,
289 IN UCHAR InIoSpace)
290 {
291 TRACE_(VIDEOPRT, "VideoPortGetDeviceBase\n");
292 return IntVideoPortMapMemory(
293 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension),
294 IoAddress,
295 NumberOfUchars,
296 InIoSpace,
297 NULL,
298 NULL);
299 }
300
301 /*
302 * @implemented
303 */
304
305 VOID NTAPI
306 VideoPortFreeDeviceBase(
307 IN PVOID HwDeviceExtension,
308 IN PVOID MappedAddress)
309 {
310 TRACE_(VIDEOPRT, "VideoPortFreeDeviceBase\n");
311 IntVideoPortUnmapMemory(
312 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension),
313 MappedAddress);
314 }
315
316 /*
317 * @unimplemented
318 */
319
320 VP_STATUS NTAPI
321 VideoPortMapBankedMemory(
322 IN PVOID HwDeviceExtension,
323 IN PHYSICAL_ADDRESS PhysicalAddress,
324 IN PULONG Length,
325 IN PULONG InIoSpace,
326 OUT PVOID *VirtualAddress,
327 IN ULONG BankLength,
328 IN UCHAR ReadWriteBank,
329 IN PBANKED_SECTION_ROUTINE BankRoutine,
330 IN PVOID Context)
331 {
332 TRACE_(VIDEOPRT, "VideoPortMapBankedMemory\n");
333 UNIMPLEMENTED;
334 return ERROR_INVALID_FUNCTION;
335 }
336
337
338 /*
339 * @implemented
340 */
341
342 VP_STATUS NTAPI
343 VideoPortMapMemory(
344 IN PVOID HwDeviceExtension,
345 IN PHYSICAL_ADDRESS PhysicalAddress,
346 IN PULONG Length,
347 IN PULONG InIoSpace,
348 OUT PVOID *VirtualAddress)
349 {
350 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
351 NTSTATUS Status;
352
353 TRACE_(VIDEOPRT, "VideoPortMapMemory\n");
354 INFO_(VIDEOPRT, "- *VirtualAddress: 0x%x\n", *VirtualAddress);
355
356 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
357 *VirtualAddress = IntVideoPortMapMemory(
358 DeviceExtension,
359 PhysicalAddress,
360 *Length,
361 *InIoSpace,
362 (HANDLE)*VirtualAddress,
363 &Status);
364
365 return Status;
366 }
367
368 /*
369 * @implemented
370 */
371
372 VP_STATUS NTAPI
373 VideoPortUnmapMemory(
374 IN PVOID HwDeviceExtension,
375 IN PVOID VirtualAddress,
376 IN HANDLE ProcessHandle)
377 {
378 TRACE_(VIDEOPRT, "VideoPortFreeDeviceBase\n");
379
380 IntVideoPortUnmapMemory(
381 VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension),
382 VirtualAddress);
383
384 return NO_ERROR;
385 }
386
387 /*
388 * @implemented
389 */
390
391 VP_STATUS NTAPI
392 VideoPortGetAccessRanges(
393 IN PVOID HwDeviceExtension,
394 IN ULONG NumRequestedResources,
395 IN PIO_RESOURCE_DESCRIPTOR RequestedResources OPTIONAL,
396 IN ULONG NumAccessRanges,
397 IN PVIDEO_ACCESS_RANGE AccessRanges,
398 IN PVOID VendorId,
399 IN PVOID DeviceId,
400 IN PULONG Slot)
401 {
402 PCI_SLOT_NUMBER PciSlotNumber;
403 ULONG DeviceNumber;
404 ULONG FunctionNumber;
405 PCI_COMMON_CONFIG Config;
406 PCM_RESOURCE_LIST AllocatedResources;
407 NTSTATUS Status;
408 UINT AssignedCount;
409 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
410 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
411 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
412 USHORT VendorIdToFind;
413 USHORT DeviceIdToFind;
414 ULONG SlotIdToFind;
415 ULONG ReturnedLength;
416 BOOLEAN DeviceAndVendorFound = FALSE;
417
418 TRACE_(VIDEOPRT, "VideoPortGetAccessRanges\n");
419
420 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
421
422 if (NumRequestedResources == 0)
423 {
424 AllocatedResources = DeviceExtension->AllocatedResources;
425 if (AllocatedResources == NULL &&
426 DeviceExtension->AdapterInterfaceType == PCIBus)
427 {
428 if (DeviceExtension->PhysicalDeviceObject != NULL)
429 {
430 PciSlotNumber.u.AsULONG = DeviceExtension->SystemIoSlotNumber;
431
432 ReturnedLength = HalGetBusData(
433 PCIConfiguration,
434 DeviceExtension->SystemIoBusNumber,
435 PciSlotNumber.u.AsULONG,
436 &Config,
437 sizeof(PCI_COMMON_CONFIG));
438
439 if (ReturnedLength != sizeof(PCI_COMMON_CONFIG))
440 {
441 return ERROR_NOT_ENOUGH_MEMORY;
442 }
443 }
444 else
445 {
446 VendorIdToFind = VendorId != NULL ? *(PUSHORT)VendorId : 0;
447 DeviceIdToFind = DeviceId != NULL ? *(PUSHORT)DeviceId : 0;
448 SlotIdToFind = Slot != NULL ? *Slot : 0;
449 PciSlotNumber.u.AsULONG = SlotIdToFind;
450
451 INFO_(VIDEOPRT, "Looking for VendorId 0x%04x DeviceId 0x%04x\n",
452 VendorIdToFind, DeviceIdToFind);
453
454 /*
455 * Search for the device id and vendor id on this bus.
456 */
457 for (DeviceNumber = 0; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
458 {
459 PciSlotNumber.u.bits.DeviceNumber = DeviceNumber;
460 for (FunctionNumber = 0; FunctionNumber < 8; FunctionNumber++)
461 {
462 INFO_(VIDEOPRT, "- Function number: %d\n", FunctionNumber);
463 PciSlotNumber.u.bits.FunctionNumber = FunctionNumber;
464 ReturnedLength = HalGetBusData(
465 PCIConfiguration,
466 DeviceExtension->SystemIoBusNumber,
467 PciSlotNumber.u.AsULONG,
468 &Config,
469 sizeof(PCI_COMMON_CONFIG));
470 INFO_(VIDEOPRT, "- Length of data: %x\n", ReturnedLength);
471 if (ReturnedLength == sizeof(PCI_COMMON_CONFIG))
472 {
473 INFO_(VIDEOPRT, "- Slot 0x%02x (Device %d Function %d) VendorId 0x%04x "
474 "DeviceId 0x%04x\n",
475 PciSlotNumber.u.AsULONG,
476 PciSlotNumber.u.bits.DeviceNumber,
477 PciSlotNumber.u.bits.FunctionNumber,
478 Config.VendorID,
479 Config.DeviceID);
480
481 if ((VendorIdToFind == 0 || Config.VendorID == VendorIdToFind) &&
482 (DeviceIdToFind == 0 || Config.DeviceID == DeviceIdToFind))
483 {
484 DeviceAndVendorFound = TRUE;
485 break;
486 }
487 }
488 }
489 if (DeviceAndVendorFound) break;
490 }
491 if (FunctionNumber == 8)
492 {
493 WARN_(VIDEOPRT, "Didn't find device.\n");
494 return ERROR_DEV_NOT_EXIST;
495 }
496 }
497
498 Status = HalAssignSlotResources(
499 &DeviceExtension->RegistryPath,
500 NULL,
501 DeviceExtension->DriverObject,
502 DeviceExtension->DriverObject->DeviceObject,
503 DeviceExtension->AdapterInterfaceType,
504 DeviceExtension->SystemIoBusNumber,
505 PciSlotNumber.u.AsULONG,
506 &AllocatedResources);
507
508 if (!NT_SUCCESS(Status))
509 {
510 WARN_(VIDEOPRT, "HalAssignSlotResources failed with status %x.\n",Status);
511 return Status;
512 }
513 DeviceExtension->AllocatedResources = AllocatedResources;
514 }
515 if (AllocatedResources == NULL)
516 return ERROR_NOT_ENOUGH_MEMORY;
517 AssignedCount = 0;
518 for (FullList = AllocatedResources->List;
519 FullList < AllocatedResources->List + AllocatedResources->Count;
520 FullList++)
521 {
522 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
523 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
524
525 ASSERT(FullList->InterfaceType == PCIBus);
526 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
527 ASSERT(1 == FullList->PartialResourceList.Version);
528 ASSERT(1 == FullList->PartialResourceList.Revision);
529 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
530 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
531 Descriptor++)
532 {
533 if ((Descriptor->Type == CmResourceTypeMemory ||
534 Descriptor->Type == CmResourceTypePort) &&
535 AssignedCount >= NumAccessRanges)
536 {
537 WARN_(VIDEOPRT, "Too many access ranges found\n");
538 return ERROR_NOT_ENOUGH_MEMORY;
539 }
540 if (Descriptor->Type == CmResourceTypeMemory)
541 {
542 if (NumAccessRanges <= AssignedCount)
543 {
544 WARN_(VIDEOPRT, "Too many access ranges found\n");
545 return ERROR_NOT_ENOUGH_MEMORY;
546 }
547 INFO_(VIDEOPRT, "Memory range starting at 0x%08x length 0x%08x\n",
548 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
549 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Memory.Start;
550 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Memory.Length;
551 AccessRanges[AssignedCount].RangeInIoSpace = 0;
552 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
553 AccessRanges[AssignedCount].RangeShareable =
554 (Descriptor->ShareDisposition == CmResourceShareShared);
555 AssignedCount++;
556 }
557 else if (Descriptor->Type == CmResourceTypePort)
558 {
559 INFO_(VIDEOPRT, "Port range starting at 0x%04x length %d\n",
560 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length);
561 AccessRanges[AssignedCount].RangeStart = Descriptor->u.Port.Start;
562 AccessRanges[AssignedCount].RangeLength = Descriptor->u.Port.Length;
563 AccessRanges[AssignedCount].RangeInIoSpace = 1;
564 AccessRanges[AssignedCount].RangeVisible = 0; /* FIXME: Just guessing */
565 AccessRanges[AssignedCount].RangeShareable = 0;
566 AssignedCount++;
567 }
568 else if (Descriptor->Type == CmResourceTypeInterrupt)
569 {
570 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
571 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
572 if (Descriptor->ShareDisposition == CmResourceShareShared)
573 DeviceExtension->InterruptShared = TRUE;
574 else
575 DeviceExtension->InterruptShared = FALSE;
576 }
577 }
578 }
579 }
580 else
581 {
582 UNIMPLEMENTED
583 }
584
585 return NO_ERROR;
586 }
587
588 /*
589 * @implemented
590 */
591
592 VP_STATUS NTAPI
593 VideoPortVerifyAccessRanges(
594 IN PVOID HwDeviceExtension,
595 IN ULONG NumAccessRanges,
596 IN PVIDEO_ACCESS_RANGE AccessRanges)
597 {
598 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
599 BOOLEAN ConflictDetected;
600 ULONG i;
601 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
602 PCM_RESOURCE_LIST ResourceList;
603 ULONG ResourceListSize;
604 NTSTATUS Status;
605
606 TRACE_(VIDEOPRT, "VideoPortVerifyAccessRanges\n");
607
608 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
609
610 /* Create the resource list */
611 ResourceListSize = sizeof(CM_RESOURCE_LIST)
612 + (NumAccessRanges - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
613 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
614 if (!ResourceList)
615 {
616 WARN_(VIDEOPRT, "ExAllocatePool() failed\n");
617 return ERROR_INVALID_PARAMETER;
618 }
619
620 /* Fill resource list */
621 ResourceList->Count = 1;
622 ResourceList->List[0].InterfaceType = DeviceExtension->AdapterInterfaceType;
623 ResourceList->List[0].BusNumber = DeviceExtension->SystemIoBusNumber;
624 ResourceList->List[0].PartialResourceList.Version = 1;
625 ResourceList->List[0].PartialResourceList.Revision = 1;
626 ResourceList->List[0].PartialResourceList.Count = NumAccessRanges;
627 for (i = 0; i < NumAccessRanges; i++, AccessRanges++)
628 {
629 PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
630 if (AccessRanges->RangeInIoSpace)
631 {
632 PartialDescriptor->Type = CmResourceTypePort;
633 PartialDescriptor->u.Port.Start = AccessRanges->RangeStart;
634 PartialDescriptor->u.Port.Length = AccessRanges->RangeLength;
635 }
636 else
637 {
638 PartialDescriptor->Type = CmResourceTypeMemory;
639 PartialDescriptor->u.Memory.Start = AccessRanges->RangeStart;
640 PartialDescriptor->u.Memory.Length = AccessRanges->RangeLength;
641 }
642 if (AccessRanges->RangeShareable)
643 PartialDescriptor->ShareDisposition = CmResourceShareShared;
644 else
645 PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
646 PartialDescriptor->Flags = 0;
647 if (AccessRanges->RangePassive & VIDEO_RANGE_PASSIVE_DECODE)
648 PartialDescriptor->Flags |= CM_RESOURCE_PORT_PASSIVE_DECODE;
649 if (AccessRanges->RangePassive & VIDEO_RANGE_10_BIT_DECODE)
650 PartialDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
651 }
652
653 /* Try to acquire all resource ranges */
654 Status = IoReportResourceForDetection(
655 DeviceExtension->DriverObject,
656 NULL, 0, /* Driver List */
657 DeviceExtension->PhysicalDeviceObject,
658 ResourceList, ResourceListSize,
659 &ConflictDetected);
660 ExFreePool(ResourceList);
661
662 if (!NT_SUCCESS(Status) || ConflictDetected)
663 return ERROR_INVALID_PARAMETER;
664 else
665 return NO_ERROR;
666 }
667
668 /*
669 * @unimplemented
670 */
671
672 VP_STATUS NTAPI
673 VideoPortGetDeviceData(
674 IN PVOID HwDeviceExtension,
675 IN VIDEO_DEVICE_DATA_TYPE DeviceDataType,
676 IN PMINIPORT_QUERY_DEVICE_ROUTINE CallbackRoutine,
677 IN PVOID Context)
678 {
679 TRACE_(VIDEOPRT, "VideoPortGetDeviceData\n");
680 UNIMPLEMENTED;
681 return ERROR_INVALID_FUNCTION;
682 }
683
684 /*
685 * @implemented
686 */
687
688 PVOID NTAPI
689 VideoPortAllocatePool(
690 IN PVOID HwDeviceExtension,
691 IN VP_POOL_TYPE PoolType,
692 IN SIZE_T NumberOfBytes,
693 IN ULONG Tag)
694 {
695 TRACE_(VIDEOPRT, "VideoPortAllocatePool\n");
696 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
697 }
698
699 /*
700 * @implemented
701 */
702
703 VOID NTAPI
704 VideoPortFreePool(
705 IN PVOID HwDeviceExtension,
706 IN PVOID Ptr)
707 {
708 ExFreePool(Ptr);
709 }
710
711 /*
712 * @implemented
713 */
714
715 VP_STATUS NTAPI
716 VideoPortAllocateBuffer(
717 IN PVOID HwDeviceExtension,
718 IN ULONG Size,
719 OUT PVOID *Buffer)
720 {
721 TRACE_(VIDEOPRT, "VideoPortAllocateBuffer\n");
722 *Buffer = ExAllocatePoolWithTag ( PagedPool, Size, TAG_VIDEO_PORT_BUFFER ) ;
723 return *Buffer == NULL ? ERROR_NOT_ENOUGH_MEMORY : NO_ERROR;
724 }
725
726 /*
727 * @implemented
728 */
729
730 VOID NTAPI
731 VideoPortReleaseBuffer(
732 IN PVOID HwDeviceExtension,
733 IN PVOID Ptr)
734 {
735 TRACE_(VIDEOPRT, "VideoPortReleaseBuffer\n");
736 ExFreePool(Ptr);
737 }
738
739 /*
740 * @implemented
741 */
742
743 PVOID NTAPI
744 VideoPortLockBuffer(
745 IN PVOID HwDeviceExtension,
746 IN PVOID BaseAddress,
747 IN ULONG Length,
748 IN VP_LOCK_OPERATION Operation)
749 {
750 PMDL Mdl;
751
752 Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, FALSE, NULL);
753 if (!Mdl)
754 {
755 return NULL;
756 }
757 /* FIXME use seh */
758 MmProbeAndLockPages(Mdl, KernelMode,Operation);
759 return Mdl;
760 }
761
762 /*
763 * @implemented
764 */
765
766 BOOLEAN
767 NTAPI
768 VideoPortLockPages(
769 IN PVOID HwDeviceExtension,
770 IN OUT PVIDEO_REQUEST_PACKET pVrp,
771 IN PEVENT pUEvent,
772 IN PEVENT pDisplayEvent,
773 IN DMA_FLAGS DmaFlags)
774 {
775 PVOID Buffer;
776
777 /* clear output buffer */
778 pVrp->OutputBuffer = NULL;
779
780 if (DmaFlags != VideoPortDmaInitOnly)
781 {
782 /* VideoPortKeepPagesLocked / VideoPortUnlockAfterDma is no-op */
783 return FALSE;
784 }
785
786 /* lock the buffer */
787 Buffer = VideoPortLockBuffer(HwDeviceExtension, pVrp->InputBuffer, pVrp->InputBufferLength, IoModifyAccess);
788
789 if (Buffer)
790 {
791 /* store result buffer & length */
792 pVrp->OutputBuffer = Buffer;
793 pVrp->OutputBufferLength = pVrp->InputBufferLength;
794
795 /* operation succeeded */
796 return TRUE;
797 }
798
799 /* operation failed */
800 return FALSE;
801 }
802
803
804 /*
805 * @implemented
806 */
807
808 VOID NTAPI
809 VideoPortUnlockBuffer(
810 IN PVOID HwDeviceExtension,
811 IN PVOID Mdl)
812 {
813 if (Mdl)
814 {
815 MmUnlockPages((PMDL)Mdl);
816 IoFreeMdl(Mdl);
817 }
818 }
819
820 /*
821 * @unimplemented
822 */
823
824 VP_STATUS NTAPI
825 VideoPortSetTrappedEmulatorPorts(
826 IN PVOID HwDeviceExtension,
827 IN ULONG NumAccessRanges,
828 IN PVIDEO_ACCESS_RANGE AccessRange)
829 {
830 UNIMPLEMENTED;
831 /* Should store the ranges in the device extension for use by ntvdm. */
832 return NO_ERROR;
833 }
834
835 /*
836 * @implemented
837 */
838
839 ULONG NTAPI
840 VideoPortGetBusData(
841 IN PVOID HwDeviceExtension,
842 IN BUS_DATA_TYPE BusDataType,
843 IN ULONG SlotNumber,
844 OUT PVOID Buffer,
845 IN ULONG Offset,
846 IN ULONG Length)
847 {
848 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
849
850 TRACE_(VIDEOPRT, "VideoPortGetBusData\n");
851
852 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
853
854 if (BusDataType != Cmos)
855 {
856 /* Legacy vs. PnP behaviour */
857 if (DeviceExtension->PhysicalDeviceObject != NULL)
858 SlotNumber = DeviceExtension->SystemIoSlotNumber;
859 }
860
861 return HalGetBusDataByOffset(
862 BusDataType,
863 DeviceExtension->SystemIoBusNumber,
864 SlotNumber,
865 Buffer,
866 Offset,
867 Length);
868 }
869
870 /*
871 * @implemented
872 */
873
874 ULONG NTAPI
875 VideoPortSetBusData(
876 IN PVOID HwDeviceExtension,
877 IN BUS_DATA_TYPE BusDataType,
878 IN ULONG SlotNumber,
879 IN PVOID Buffer,
880 IN ULONG Offset,
881 IN ULONG Length)
882 {
883 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
884
885 TRACE_(VIDEOPRT, "VideoPortSetBusData\n");
886
887 DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
888
889 if (BusDataType != Cmos)
890 {
891 /* Legacy vs. PnP behaviour */
892 if (DeviceExtension->PhysicalDeviceObject != NULL)
893 SlotNumber = DeviceExtension->SystemIoSlotNumber;
894 }
895
896 return HalSetBusDataByOffset(
897 BusDataType,
898 DeviceExtension->SystemIoBusNumber,
899 SlotNumber,
900 Buffer,
901 Offset,
902 Length);
903 }