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