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