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