- Merge from trunk up to r45543
[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 NTSTATUS
185 NTAPI
186 DriverEntry(
187 IN PDRIVER_OBJECT DriverObject,
188 IN PUNICODE_STRING RegistryPath)
189 {
190 NTSTATUS Status;
191
192 UNREFERENCED_PARAMETER(RegistryPath);
193 DPRINT("Peripheral Component Interconnect Bus Driver\n");
194
195 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
196 DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl;
197 DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl;
198 DriverObject->DriverExtension->AddDevice = PciAddDevice;
199
200 Status = IoAllocateDriverObjectExtension(
201 DriverObject,
202 DriverObject,
203 sizeof(PCI_DRIVER_EXTENSION),
204 (PVOID*)&DriverExtension);
205 if (!NT_SUCCESS(Status))
206 return Status;
207 RtlZeroMemory(DriverExtension, sizeof(PCI_DRIVER_EXTENSION));
208
209 InitializeListHead(&DriverExtension->BusListHead);
210 KeInitializeSpinLock(&DriverExtension->BusListLock);
211
212 return STATUS_SUCCESS;
213 }
214
215
216 NTSTATUS
217 PciCreateDeviceIDString(PUNICODE_STRING DeviceID,
218 PPCI_DEVICE Device)
219 {
220 WCHAR Buffer[256];
221
222 swprintf(Buffer,
223 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
224 Device->PciConfig.VendorID,
225 Device->PciConfig.DeviceID,
226 (Device->PciConfig.u.type0.SubSystemID << 16) +
227 Device->PciConfig.u.type0.SubVendorID,
228 Device->PciConfig.RevisionID);
229
230 return RtlCreateUnicodeString(DeviceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
231 }
232
233
234 NTSTATUS
235 PciCreateInstanceIDString(PUNICODE_STRING InstanceID,
236 PPCI_DEVICE Device)
237 {
238 WCHAR Buffer[3];
239
240 swprintf(Buffer, L"%02X", Device->SlotNumber.u.AsULONG & 0xff);
241
242 return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
243 }
244
245
246 NTSTATUS
247 PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs,
248 PPCI_DEVICE Device)
249 {
250 WCHAR Buffer[256];
251 UNICODE_STRING BufferU;
252 ULONG Index;
253
254 Index = 0;
255 Index += swprintf(&Buffer[Index],
256 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
257 Device->PciConfig.VendorID,
258 Device->PciConfig.DeviceID,
259 (Device->PciConfig.u.type0.SubSystemID << 16) +
260 Device->PciConfig.u.type0.SubVendorID,
261 Device->PciConfig.RevisionID);
262 Index++;
263
264 Index += swprintf(&Buffer[Index],
265 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X",
266 Device->PciConfig.VendorID,
267 Device->PciConfig.DeviceID,
268 (Device->PciConfig.u.type0.SubSystemID << 16) +
269 Device->PciConfig.u.type0.SubVendorID);
270 Index++;
271
272 Index += swprintf(&Buffer[Index],
273 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",
274 Device->PciConfig.VendorID,
275 Device->PciConfig.DeviceID,
276 Device->PciConfig.BaseClass,
277 Device->PciConfig.SubClass,
278 Device->PciConfig.ProgIf);
279 Index++;
280
281 Index += swprintf(&Buffer[Index],
282 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",
283 Device->PciConfig.VendorID,
284 Device->PciConfig.DeviceID,
285 Device->PciConfig.BaseClass,
286 Device->PciConfig.SubClass);
287 Index++;
288
289 Buffer[Index] = UNICODE_NULL;
290
291 BufferU.Length = BufferU.MaximumLength = (USHORT) Index * sizeof(WCHAR);
292 BufferU.Buffer = Buffer;
293
294 return PciDuplicateUnicodeString(0, &BufferU, HardwareIDs);
295 }
296
297
298 NTSTATUS
299 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs,
300 PPCI_DEVICE Device)
301 {
302 WCHAR Buffer[256];
303 UNICODE_STRING BufferU;
304 ULONG Index;
305
306 Index = 0;
307 Index += swprintf(&Buffer[Index],
308 L"PCI\\VEN_%04X&DEV_%04X&REV_%02X",
309 Device->PciConfig.VendorID,
310 Device->PciConfig.DeviceID,
311 Device->PciConfig.RevisionID);
312 Index++;
313
314 Index += swprintf(&Buffer[Index],
315 L"PCI\\VEN_%04X&DEV_%04X",
316 Device->PciConfig.VendorID,
317 Device->PciConfig.DeviceID);
318 Index++;
319
320 Index += swprintf(&Buffer[Index],
321 L"PCI\\VEN_%04X&CC_%02X%02X%02X",
322 Device->PciConfig.VendorID,
323 Device->PciConfig.BaseClass,
324 Device->PciConfig.SubClass,
325 Device->PciConfig.ProgIf);
326 Index++;
327
328 Index += swprintf(&Buffer[Index],
329 L"PCI\\VEN_%04X&CC_%02X%02X",
330 Device->PciConfig.VendorID,
331 Device->PciConfig.BaseClass,
332 Device->PciConfig.SubClass);
333 Index++;
334
335 Index += swprintf(&Buffer[Index],
336 L"PCI\\VEN_%04X",
337 Device->PciConfig.VendorID);
338 Index++;
339
340 Index += swprintf(&Buffer[Index],
341 L"PCI\\CC_%02X%02X%02X",
342 Device->PciConfig.BaseClass,
343 Device->PciConfig.SubClass,
344 Device->PciConfig.ProgIf);
345 Index++;
346
347 Index += swprintf(&Buffer[Index],
348 L"PCI\\CC_%02X%02X",
349 Device->PciConfig.BaseClass,
350 Device->PciConfig.SubClass);
351 Index++;
352
353 Buffer[Index] = UNICODE_NULL;
354
355 BufferU.Length = BufferU.MaximumLength = (USHORT)Index * sizeof(WCHAR);
356 BufferU.Buffer = Buffer;
357
358 return PciDuplicateUnicodeString(0, &BufferU, CompatibleIDs);
359 }
360
361
362 NTSTATUS
363 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription,
364 PPCI_DEVICE Device)
365 {
366 PCWSTR Description;
367
368 switch (Device->PciConfig.BaseClass)
369 {
370 case PCI_CLASS_PRE_20:
371 switch (Device->PciConfig.SubClass)
372 {
373 case PCI_SUBCLASS_PRE_20_VGA:
374 Description = L"VGA device";
375 break;
376
377 default:
378 case PCI_SUBCLASS_PRE_20_NON_VGA:
379 Description = L"PCI device";
380 break;
381 }
382 break;
383
384 case PCI_CLASS_MASS_STORAGE_CTLR:
385 switch (Device->PciConfig.SubClass)
386 {
387 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR:
388 Description = L"SCSI controller";
389 break;
390
391 case PCI_SUBCLASS_MSC_IDE_CTLR:
392 Description = L"IDE controller";
393 break;
394
395 case PCI_SUBCLASS_MSC_FLOPPY_CTLR:
396 Description = L"Floppy disk controller";
397 break;
398
399 case PCI_SUBCLASS_MSC_IPI_CTLR:
400 Description = L"IPI controller";
401 break;
402
403 case PCI_SUBCLASS_MSC_RAID_CTLR:
404 Description = L"RAID controller";
405 break;
406
407 default:
408 Description = L"Mass storage controller";
409 break;
410 }
411 break;
412
413 case PCI_CLASS_NETWORK_CTLR:
414 switch (Device->PciConfig.SubClass)
415 {
416 case PCI_SUBCLASS_NET_ETHERNET_CTLR:
417 Description = L"Ethernet controller";
418 break;
419
420 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR:
421 Description = L"Token-Ring controller";
422 break;
423
424 case PCI_SUBCLASS_NET_FDDI_CTLR:
425 Description = L"FDDI controller";
426 break;
427
428 case PCI_SUBCLASS_NET_ATM_CTLR:
429 Description = L"ATM controller";
430 break;
431
432 default:
433 Description = L"Network controller";
434 break;
435 }
436 break;
437
438 case PCI_CLASS_DISPLAY_CTLR:
439 switch (Device->PciConfig.SubClass)
440 {
441 case PCI_SUBCLASS_VID_VGA_CTLR:
442 Description = L"VGA display controller";
443 break;
444
445 case PCI_SUBCLASS_VID_XGA_CTLR:
446 Description = L"XGA display controller";
447 break;
448
449 case PCI_SUBCLASS_VID_3D_CTLR:
450 Description = L"Multimedia display controller";
451 break;
452
453 default:
454 Description = L"Other display controller";
455 break;
456 }
457 break;
458
459 case PCI_CLASS_MULTIMEDIA_DEV:
460 switch (Device->PciConfig.SubClass)
461 {
462 case PCI_SUBCLASS_MM_VIDEO_DEV:
463 Description = L"Multimedia video device";
464 break;
465
466 case PCI_SUBCLASS_MM_AUDIO_DEV:
467 Description = L"Multimedia audio device";
468 break;
469
470 case PCI_SUBCLASS_MM_TELEPHONY_DEV:
471 Description = L"Multimedia telephony device";
472 break;
473
474 default:
475 Description = L"Other multimedia device";
476 break;
477 }
478 break;
479
480 case PCI_CLASS_MEMORY_CTLR:
481 switch (Device->PciConfig.SubClass)
482 {
483 case PCI_SUBCLASS_MEM_RAM:
484 Description = L"PCI Memory";
485 break;
486
487 case PCI_SUBCLASS_MEM_FLASH:
488 Description = L"PCI Flash Memory";
489 break;
490
491 default:
492 Description = L"Other memory controller";
493 break;
494 }
495 break;
496
497 case PCI_CLASS_BRIDGE_DEV:
498 switch (Device->PciConfig.SubClass)
499 {
500 case PCI_SUBCLASS_BR_HOST:
501 Description = L"PCI-Host bridge";
502 break;
503
504 case PCI_SUBCLASS_BR_ISA:
505 Description = L"PCI-ISA bridge";
506 break;
507
508 case PCI_SUBCLASS_BR_EISA:
509 Description = L"PCI-EISA bridge";
510 break;
511
512 case PCI_SUBCLASS_BR_MCA:
513 Description = L"PCI-Micro Channel bridge";
514 break;
515
516 case PCI_SUBCLASS_BR_PCI_TO_PCI:
517 Description = L"PCI-PCI bridge";
518 break;
519
520 case PCI_SUBCLASS_BR_PCMCIA:
521 Description = L"PCI-PCMCIA bridge";
522 break;
523
524 case PCI_SUBCLASS_BR_NUBUS:
525 Description = L"PCI-NUBUS bridge";
526 break;
527
528 case PCI_SUBCLASS_BR_CARDBUS:
529 Description = L"PCI-CARDBUS bridge";
530 break;
531
532 default:
533 Description = L"Other bridge device";
534 break;
535 }
536 break;
537
538 case PCI_CLASS_SIMPLE_COMMS_CTLR:
539 switch (Device->PciConfig.SubClass)
540 {
541
542 default:
543 Description = L"Communication device";
544 break;
545 }
546 break;
547
548 case PCI_CLASS_BASE_SYSTEM_DEV:
549 switch (Device->PciConfig.SubClass)
550 {
551
552 default:
553 Description = L"System device";
554 break;
555 }
556 break;
557
558 case PCI_CLASS_INPUT_DEV:
559 switch (Device->PciConfig.SubClass)
560 {
561
562 default:
563 Description = L"Input device";
564 break;
565 }
566 break;
567
568 case PCI_CLASS_DOCKING_STATION:
569 switch (Device->PciConfig.SubClass)
570 {
571
572 default:
573 Description = L"Docking station";
574 break;
575 }
576 break;
577
578 case PCI_CLASS_PROCESSOR:
579 switch (Device->PciConfig.SubClass)
580 {
581
582 default:
583 Description = L"Processor";
584 break;
585 }
586 break;
587
588 case PCI_CLASS_SERIAL_BUS_CTLR:
589 switch (Device->PciConfig.SubClass)
590 {
591 case PCI_SUBCLASS_SB_IEEE1394:
592 Description = L"FireWire controller";
593 break;
594
595 case PCI_SUBCLASS_SB_ACCESS:
596 Description = L"ACCESS bus controller";
597 break;
598
599 case PCI_SUBCLASS_SB_SSA:
600 Description = L"SSA controller";
601 break;
602
603 case PCI_SUBCLASS_SB_USB:
604 Description = L"USB controller";
605 break;
606
607 case PCI_SUBCLASS_SB_FIBRE_CHANNEL:
608 Description = L"Fibre Channel controller";
609 break;
610
611 case PCI_SUBCLASS_SB_SMBUS:
612 Description = L"SMBus controller";
613 break;
614
615 default:
616 Description = L"Other serial bus controller";
617 break;
618 }
619 break;
620
621 default:
622 Description = L"Other PCI Device";
623 break;
624 }
625
626 return RtlCreateUnicodeString(DeviceDescription, Description) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
627 }
628
629
630 NTSTATUS
631 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation,
632 PPCI_DEVICE Device)
633 {
634 WCHAR Buffer[256];
635
636 swprintf(Buffer,
637 L"PCI-Bus %lu, Device %u, Function %u",
638 Device->BusNumber,
639 Device->SlotNumber.u.bits.DeviceNumber,
640 Device->SlotNumber.u.bits.FunctionNumber);
641
642 return RtlCreateUnicodeString(DeviceLocation, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
643 }
644
645 NTSTATUS
646 PciDuplicateUnicodeString(
647 IN ULONG Flags,
648 IN PCUNICODE_STRING SourceString,
649 OUT PUNICODE_STRING DestinationString)
650 {
651 if (SourceString == NULL || DestinationString == NULL
652 || SourceString->Length > SourceString->MaximumLength
653 || (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL)
654 || Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4)
655 {
656 return STATUS_INVALID_PARAMETER;
657 }
658
659
660 if ((SourceString->Length == 0)
661 && (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
662 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
663 {
664 DestinationString->Length = 0;
665 DestinationString->MaximumLength = 0;
666 DestinationString->Buffer = NULL;
667 }
668 else
669 {
670 USHORT DestMaxLength = SourceString->Length;
671
672 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
673 DestMaxLength += sizeof(UNICODE_NULL);
674
675 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, TAG_PCI);
676 if (DestinationString->Buffer == NULL)
677 return STATUS_NO_MEMORY;
678
679 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
680 DestinationString->Length = SourceString->Length;
681 DestinationString->MaximumLength = DestMaxLength;
682
683 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
684 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
685 }
686
687 return STATUS_SUCCESS;
688 }
689
690 /* EOF */