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