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