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