xref: /reactos/drivers/bus/pci/pci.c (revision 139a3d66)
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