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