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