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