1 /* 2 * PROJECT: ReactOS PCI Bus driver 3 * FILE: pci.c 4 * PURPOSE: Driver entry 5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 6 * UPDATE HISTORY: 7 * 10-09-2001 CSH Created 8 */ 9 10 #include "pci.h" 11 12 #include <stdio.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 static DRIVER_DISPATCH PciDispatchDeviceControl; 18 static NTSTATUS NTAPI PciDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 19 20 static DRIVER_ADD_DEVICE PciAddDevice; 21 static NTSTATUS NTAPI PciAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject); 22 23 static DRIVER_DISPATCH PciPowerControl; 24 static NTSTATUS NTAPI PciPowerControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 25 26 static DRIVER_DISPATCH PciPnpControl; 27 static NTSTATUS NTAPI PciPnpControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 28 29 30 #ifdef ALLOC_PRAGMA 31 32 // Make the initialization routines discardable, so that they 33 // don't waste space 34 35 #pragma alloc_text(INIT, DriverEntry) 36 37 #endif /* ALLOC_PRAGMA */ 38 39 /*** PUBLIC ******************************************************************/ 40 41 PPCI_DRIVER_EXTENSION DriverExtension = NULL; 42 43 /*** PRIVATE *****************************************************************/ 44 45 static NTSTATUS 46 NTAPI 47 PciDispatchDeviceControl( 48 IN PDEVICE_OBJECT DeviceObject, 49 IN PIRP Irp) 50 { 51 PIO_STACK_LOCATION IrpSp; 52 NTSTATUS Status; 53 54 UNREFERENCED_PARAMETER(DeviceObject); 55 DPRINT("Called. IRP is at (0x%p)\n", Irp); 56 57 Irp->IoStatus.Information = 0; 58 59 IrpSp = IoGetCurrentIrpStackLocation(Irp); 60 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) 61 { 62 default: 63 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); 64 Status = STATUS_NOT_IMPLEMENTED; 65 break; 66 } 67 68 if (Status != STATUS_PENDING) 69 { 70 Irp->IoStatus.Status = Status; 71 72 DPRINT("Completing IRP at 0x%p\n", Irp); 73 74 IoCompleteRequest(Irp, IO_NO_INCREMENT); 75 } 76 77 DPRINT("Leaving. Status 0x%X\n", Status); 78 79 return Status; 80 } 81 82 83 static NTSTATUS 84 NTAPI 85 PciPnpControl( 86 IN PDEVICE_OBJECT DeviceObject, 87 IN PIRP Irp) 88 /* 89 * FUNCTION: Handle Plug and Play IRPs 90 * ARGUMENTS: 91 * DeviceObject = Pointer to PDO or FDO 92 * Irp = Pointer to IRP that should be handled 93 * RETURNS: 94 * Status 95 */ 96 { 97 PCOMMON_DEVICE_EXTENSION DeviceExtension; 98 NTSTATUS Status; 99 100 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 101 102 DPRINT("IsFDO %u\n", DeviceExtension->IsFDO); 103 104 if (DeviceExtension->IsFDO) 105 { 106 Status = FdoPnpControl(DeviceObject, Irp); 107 } 108 else 109 { 110 Status = PdoPnpControl(DeviceObject, Irp); 111 } 112 113 return Status; 114 } 115 116 117 static NTSTATUS 118 NTAPI 119 PciPowerControl( 120 IN PDEVICE_OBJECT DeviceObject, 121 IN PIRP Irp) 122 /* 123 * FUNCTION: Handle power management IRPs 124 * ARGUMENTS: 125 * DeviceObject = Pointer to PDO or FDO 126 * Irp = Pointer to IRP that should be handled 127 * RETURNS: 128 * Status 129 */ 130 { 131 PCOMMON_DEVICE_EXTENSION DeviceExtension; 132 NTSTATUS Status; 133 134 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 135 136 if (DeviceExtension->IsFDO) 137 { 138 Status = FdoPowerControl(DeviceObject, Irp); 139 } 140 else 141 { 142 Status = PdoPowerControl(DeviceObject, Irp); 143 } 144 145 return Status; 146 } 147 148 149 static NTSTATUS 150 NTAPI 151 PciAddDevice( 152 IN PDRIVER_OBJECT DriverObject, 153 IN PDEVICE_OBJECT PhysicalDeviceObject) 154 { 155 PFDO_DEVICE_EXTENSION DeviceExtension; 156 PDEVICE_OBJECT Fdo; 157 NTSTATUS Status; 158 159 DPRINT("Called\n"); 160 if (PhysicalDeviceObject == NULL) 161 return STATUS_SUCCESS; 162 163 Status = IoCreateDevice(DriverObject, 164 sizeof(FDO_DEVICE_EXTENSION), 165 NULL, 166 FILE_DEVICE_BUS_EXTENDER, 167 FILE_DEVICE_SECURE_OPEN, 168 TRUE, 169 &Fdo); 170 if (!NT_SUCCESS(Status)) 171 { 172 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); 173 return Status; 174 } 175 176 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; 177 178 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION)); 179 180 DeviceExtension->Common.IsFDO = TRUE; 181 182 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(Fdo, 183 PhysicalDeviceObject); 184 185 DeviceExtension->State = dsStopped; 186 187 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 188 189 //Fdo->Flags |= DO_POWER_PAGABLE; 190 191 DPRINT("Done AddDevice\n"); 192 193 return STATUS_SUCCESS; 194 } 195 196 DRIVER_UNLOAD PciUnload; 197 198 VOID 199 NTAPI 200 PciUnload( 201 IN PDRIVER_OBJECT DriverObject) 202 { 203 /* The driver object extension is destroyed by the I/O manager */ 204 UNREFERENCED_PARAMETER(DriverObject); 205 } 206 207 NTSTATUS 208 NTAPI 209 DriverEntry( 210 IN PDRIVER_OBJECT DriverObject, 211 IN PUNICODE_STRING RegistryPath) 212 { 213 NTSTATUS Status; 214 215 UNREFERENCED_PARAMETER(RegistryPath); 216 DPRINT("Peripheral Component Interconnect Bus Driver\n"); 217 218 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl; 219 DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl; 220 DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl; 221 DriverObject->DriverExtension->AddDevice = PciAddDevice; 222 DriverObject->DriverUnload = PciUnload; 223 224 Status = IoAllocateDriverObjectExtension(DriverObject, 225 DriverObject, 226 sizeof(PCI_DRIVER_EXTENSION), 227 (PVOID*)&DriverExtension); 228 if (!NT_SUCCESS(Status)) 229 return Status; 230 231 RtlZeroMemory(DriverExtension, sizeof(PCI_DRIVER_EXTENSION)); 232 233 InitializeListHead(&DriverExtension->BusListHead); 234 KeInitializeSpinLock(&DriverExtension->BusListLock); 235 236 return STATUS_SUCCESS; 237 } 238 239 240 NTSTATUS 241 PciCreateDeviceIDString(PUNICODE_STRING DeviceID, 242 PPCI_DEVICE Device) 243 { 244 WCHAR Buffer[256]; 245 246 swprintf(Buffer, 247 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", 248 Device->PciConfig.VendorID, 249 Device->PciConfig.DeviceID, 250 (Device->PciConfig.u.type0.SubSystemID << 16) + 251 Device->PciConfig.u.type0.SubVendorID, 252 Device->PciConfig.RevisionID); 253 254 return RtlCreateUnicodeString(DeviceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 255 } 256 257 258 NTSTATUS 259 PciCreateInstanceIDString(PUNICODE_STRING InstanceID, 260 PPCI_DEVICE Device) 261 { 262 WCHAR Buffer[3]; 263 264 swprintf(Buffer, L"%02X", Device->SlotNumber.u.AsULONG & 0xff); 265 266 return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 267 } 268 269 270 NTSTATUS 271 PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs, 272 PPCI_DEVICE Device) 273 { 274 WCHAR Buffer[256]; 275 UNICODE_STRING BufferU; 276 ULONG Index; 277 278 Index = 0; 279 Index += swprintf(&Buffer[Index], 280 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", 281 Device->PciConfig.VendorID, 282 Device->PciConfig.DeviceID, 283 (Device->PciConfig.u.type0.SubSystemID << 16) + 284 Device->PciConfig.u.type0.SubVendorID, 285 Device->PciConfig.RevisionID); 286 Index++; 287 288 Index += swprintf(&Buffer[Index], 289 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X", 290 Device->PciConfig.VendorID, 291 Device->PciConfig.DeviceID, 292 (Device->PciConfig.u.type0.SubSystemID << 16) + 293 Device->PciConfig.u.type0.SubVendorID); 294 Index++; 295 296 Index += swprintf(&Buffer[Index], 297 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X", 298 Device->PciConfig.VendorID, 299 Device->PciConfig.DeviceID, 300 Device->PciConfig.BaseClass, 301 Device->PciConfig.SubClass, 302 Device->PciConfig.ProgIf); 303 Index++; 304 305 Index += swprintf(&Buffer[Index], 306 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X", 307 Device->PciConfig.VendorID, 308 Device->PciConfig.DeviceID, 309 Device->PciConfig.BaseClass, 310 Device->PciConfig.SubClass); 311 Index++; 312 313 Buffer[Index] = UNICODE_NULL; 314 315 BufferU.Length = BufferU.MaximumLength = (USHORT) Index * sizeof(WCHAR); 316 BufferU.Buffer = Buffer; 317 318 return PciDuplicateUnicodeString(0, &BufferU, HardwareIDs); 319 } 320 321 322 NTSTATUS 323 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs, 324 PPCI_DEVICE Device) 325 { 326 WCHAR Buffer[256]; 327 UNICODE_STRING BufferU; 328 ULONG Index; 329 330 Index = 0; 331 Index += swprintf(&Buffer[Index], 332 L"PCI\\VEN_%04X&DEV_%04X&REV_%02X", 333 Device->PciConfig.VendorID, 334 Device->PciConfig.DeviceID, 335 Device->PciConfig.RevisionID); 336 Index++; 337 338 Index += swprintf(&Buffer[Index], 339 L"PCI\\VEN_%04X&DEV_%04X", 340 Device->PciConfig.VendorID, 341 Device->PciConfig.DeviceID); 342 Index++; 343 344 Index += swprintf(&Buffer[Index], 345 L"PCI\\VEN_%04X&CC_%02X%02X%02X", 346 Device->PciConfig.VendorID, 347 Device->PciConfig.BaseClass, 348 Device->PciConfig.SubClass, 349 Device->PciConfig.ProgIf); 350 Index++; 351 352 Index += swprintf(&Buffer[Index], 353 L"PCI\\VEN_%04X&CC_%02X%02X", 354 Device->PciConfig.VendorID, 355 Device->PciConfig.BaseClass, 356 Device->PciConfig.SubClass); 357 Index++; 358 359 Index += swprintf(&Buffer[Index], 360 L"PCI\\VEN_%04X", 361 Device->PciConfig.VendorID); 362 Index++; 363 364 Index += swprintf(&Buffer[Index], 365 L"PCI\\CC_%02X%02X%02X", 366 Device->PciConfig.BaseClass, 367 Device->PciConfig.SubClass, 368 Device->PciConfig.ProgIf); 369 Index++; 370 371 Index += swprintf(&Buffer[Index], 372 L"PCI\\CC_%02X%02X", 373 Device->PciConfig.BaseClass, 374 Device->PciConfig.SubClass); 375 Index++; 376 377 Buffer[Index] = UNICODE_NULL; 378 379 BufferU.Length = BufferU.MaximumLength = (USHORT)Index * sizeof(WCHAR); 380 BufferU.Buffer = Buffer; 381 382 return PciDuplicateUnicodeString(0, &BufferU, CompatibleIDs); 383 } 384 385 386 NTSTATUS 387 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription, 388 PPCI_DEVICE Device) 389 { 390 PCWSTR Description; 391 392 switch (Device->PciConfig.BaseClass) 393 { 394 case PCI_CLASS_PRE_20: 395 switch (Device->PciConfig.SubClass) 396 { 397 case PCI_SUBCLASS_PRE_20_VGA: 398 Description = L"VGA device"; 399 break; 400 401 default: 402 case PCI_SUBCLASS_PRE_20_NON_VGA: 403 Description = L"PCI device"; 404 break; 405 } 406 break; 407 408 case PCI_CLASS_MASS_STORAGE_CTLR: 409 switch (Device->PciConfig.SubClass) 410 { 411 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR: 412 Description = L"SCSI controller"; 413 break; 414 415 case PCI_SUBCLASS_MSC_IDE_CTLR: 416 Description = L"IDE controller"; 417 break; 418 419 case PCI_SUBCLASS_MSC_FLOPPY_CTLR: 420 Description = L"Floppy disk controller"; 421 break; 422 423 case PCI_SUBCLASS_MSC_IPI_CTLR: 424 Description = L"IPI controller"; 425 break; 426 427 case PCI_SUBCLASS_MSC_RAID_CTLR: 428 Description = L"RAID controller"; 429 break; 430 431 default: 432 Description = L"Mass storage controller"; 433 break; 434 } 435 break; 436 437 case PCI_CLASS_NETWORK_CTLR: 438 switch (Device->PciConfig.SubClass) 439 { 440 case PCI_SUBCLASS_NET_ETHERNET_CTLR: 441 Description = L"Ethernet controller"; 442 break; 443 444 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR: 445 Description = L"Token-Ring controller"; 446 break; 447 448 case PCI_SUBCLASS_NET_FDDI_CTLR: 449 Description = L"FDDI controller"; 450 break; 451 452 case PCI_SUBCLASS_NET_ATM_CTLR: 453 Description = L"ATM controller"; 454 break; 455 456 default: 457 Description = L"Network controller"; 458 break; 459 } 460 break; 461 462 case PCI_CLASS_DISPLAY_CTLR: 463 switch (Device->PciConfig.SubClass) 464 { 465 case PCI_SUBCLASS_VID_VGA_CTLR: 466 Description = L"VGA display controller"; 467 break; 468 469 case PCI_SUBCLASS_VID_XGA_CTLR: 470 Description = L"XGA display controller"; 471 break; 472 473 case PCI_SUBCLASS_VID_3D_CTLR: 474 Description = L"Multimedia display controller"; 475 break; 476 477 default: 478 Description = L"Other display controller"; 479 break; 480 } 481 break; 482 483 case PCI_CLASS_MULTIMEDIA_DEV: 484 switch (Device->PciConfig.SubClass) 485 { 486 case PCI_SUBCLASS_MM_VIDEO_DEV: 487 Description = L"Multimedia video device"; 488 break; 489 490 case PCI_SUBCLASS_MM_AUDIO_DEV: 491 Description = L"Multimedia audio device"; 492 break; 493 494 case PCI_SUBCLASS_MM_TELEPHONY_DEV: 495 Description = L"Multimedia telephony device"; 496 break; 497 498 default: 499 Description = L"Other multimedia device"; 500 break; 501 } 502 break; 503 504 case PCI_CLASS_MEMORY_CTLR: 505 switch (Device->PciConfig.SubClass) 506 { 507 case PCI_SUBCLASS_MEM_RAM: 508 Description = L"PCI Memory"; 509 break; 510 511 case PCI_SUBCLASS_MEM_FLASH: 512 Description = L"PCI Flash Memory"; 513 break; 514 515 default: 516 Description = L"Other memory controller"; 517 break; 518 } 519 break; 520 521 case PCI_CLASS_BRIDGE_DEV: 522 switch (Device->PciConfig.SubClass) 523 { 524 case PCI_SUBCLASS_BR_HOST: 525 Description = L"PCI-Host bridge"; 526 break; 527 528 case PCI_SUBCLASS_BR_ISA: 529 Description = L"PCI-ISA bridge"; 530 break; 531 532 case PCI_SUBCLASS_BR_EISA: 533 Description = L"PCI-EISA bridge"; 534 break; 535 536 case PCI_SUBCLASS_BR_MCA: 537 Description = L"PCI-Micro Channel bridge"; 538 break; 539 540 case PCI_SUBCLASS_BR_PCI_TO_PCI: 541 Description = L"PCI-PCI bridge"; 542 break; 543 544 case PCI_SUBCLASS_BR_PCMCIA: 545 Description = L"PCI-PCMCIA bridge"; 546 break; 547 548 case PCI_SUBCLASS_BR_NUBUS: 549 Description = L"PCI-NUBUS bridge"; 550 break; 551 552 case PCI_SUBCLASS_BR_CARDBUS: 553 Description = L"PCI-CARDBUS bridge"; 554 break; 555 556 default: 557 Description = L"Other bridge device"; 558 break; 559 } 560 break; 561 562 case PCI_CLASS_SIMPLE_COMMS_CTLR: 563 switch (Device->PciConfig.SubClass) 564 { 565 566 default: 567 Description = L"Communication device"; 568 break; 569 } 570 break; 571 572 case PCI_CLASS_BASE_SYSTEM_DEV: 573 switch (Device->PciConfig.SubClass) 574 { 575 576 default: 577 Description = L"System device"; 578 break; 579 } 580 break; 581 582 case PCI_CLASS_INPUT_DEV: 583 switch (Device->PciConfig.SubClass) 584 { 585 586 default: 587 Description = L"Input device"; 588 break; 589 } 590 break; 591 592 case PCI_CLASS_DOCKING_STATION: 593 switch (Device->PciConfig.SubClass) 594 { 595 596 default: 597 Description = L"Docking station"; 598 break; 599 } 600 break; 601 602 case PCI_CLASS_PROCESSOR: 603 switch (Device->PciConfig.SubClass) 604 { 605 606 default: 607 Description = L"Processor"; 608 break; 609 } 610 break; 611 612 case PCI_CLASS_SERIAL_BUS_CTLR: 613 switch (Device->PciConfig.SubClass) 614 { 615 case PCI_SUBCLASS_SB_IEEE1394: 616 Description = L"FireWire controller"; 617 break; 618 619 case PCI_SUBCLASS_SB_ACCESS: 620 Description = L"ACCESS bus controller"; 621 break; 622 623 case PCI_SUBCLASS_SB_SSA: 624 Description = L"SSA controller"; 625 break; 626 627 case PCI_SUBCLASS_SB_USB: 628 Description = L"USB controller"; 629 break; 630 631 case PCI_SUBCLASS_SB_FIBRE_CHANNEL: 632 Description = L"Fibre Channel controller"; 633 break; 634 635 case PCI_SUBCLASS_SB_SMBUS: 636 Description = L"SMBus controller"; 637 break; 638 639 default: 640 Description = L"Other serial bus controller"; 641 break; 642 } 643 break; 644 645 default: 646 Description = L"Other PCI Device"; 647 break; 648 } 649 650 return RtlCreateUnicodeString(DeviceDescription, Description) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 651 } 652 653 654 NTSTATUS 655 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation, 656 PPCI_DEVICE Device) 657 { 658 WCHAR Buffer[256]; 659 660 swprintf(Buffer, 661 L"PCI-Bus %lu, Device %u, Function %u", 662 Device->BusNumber, 663 Device->SlotNumber.u.bits.DeviceNumber, 664 Device->SlotNumber.u.bits.FunctionNumber); 665 666 return RtlCreateUnicodeString(DeviceLocation, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 667 } 668 669 NTSTATUS 670 PciDuplicateUnicodeString( 671 IN ULONG Flags, 672 IN PCUNICODE_STRING SourceString, 673 OUT PUNICODE_STRING DestinationString) 674 { 675 if (SourceString == NULL || 676 DestinationString == NULL || 677 SourceString->Length > SourceString->MaximumLength || 678 (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) || 679 Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || 680 Flags >= 4) 681 { 682 return STATUS_INVALID_PARAMETER; 683 } 684 685 if ((SourceString->Length == 0) && 686 (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 687 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 688 { 689 DestinationString->Length = 0; 690 DestinationString->MaximumLength = 0; 691 DestinationString->Buffer = NULL; 692 } 693 else 694 { 695 USHORT DestMaxLength = SourceString->Length; 696 697 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 698 DestMaxLength += sizeof(UNICODE_NULL); 699 700 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, TAG_PCI); 701 if (DestinationString->Buffer == NULL) 702 return STATUS_NO_MEMORY; 703 704 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 705 DestinationString->Length = SourceString->Length; 706 DestinationString->MaximumLength = DestMaxLength; 707 708 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 709 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 710 } 711 712 return STATUS_SUCCESS; 713 } 714 715 /* EOF */ 716