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