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