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