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