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