The real, definitive, Visual C++ support branch. Accept no substitutes
[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 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 */