ff31d77e47241ee3238bb0cca9cbc1a6e4941639
[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 Buffer[Index] = UNICODE_NULL;
292
293 Length = (Index + 1) * sizeof(WCHAR);
294 HardwareIDs->Buffer = ExAllocatePool(PagedPool, Length);
295 if (HardwareIDs->Buffer == NULL)
296 {
297 return FALSE;
298 }
299
300 HardwareIDs->Length = Length - sizeof(WCHAR);
301 HardwareIDs->MaximumLength = Length;
302 RtlCopyMemory(HardwareIDs->Buffer, Buffer, Length);
303
304 return TRUE;
305 }
306
307
308 BOOLEAN
309 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs,
310 PPCI_DEVICE Device)
311 {
312 WCHAR Buffer[256];
313 ULONG Length;
314 ULONG Index;
315
316 Index = 0;
317 Index += swprintf(&Buffer[Index],
318 L"PCI\\VEN_%04X&DEV_%04X&REV_%02X&CC_%02X%02X",
319 Device->PciConfig.VendorID,
320 Device->PciConfig.DeviceID,
321 Device->PciConfig.RevisionID,
322 Device->PciConfig.BaseClass,
323 Device->PciConfig.SubClass);
324 Index++;
325
326 Index += swprintf(&Buffer[Index],
327 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",
328 Device->PciConfig.VendorID,
329 Device->PciConfig.DeviceID,
330 Device->PciConfig.BaseClass,
331 Device->PciConfig.SubClass,
332 Device->PciConfig.ProgIf);
333 Index++;
334
335 Index += swprintf(&Buffer[Index],
336 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",
337 Device->PciConfig.VendorID,
338 Device->PciConfig.DeviceID,
339 Device->PciConfig.BaseClass,
340 Device->PciConfig.SubClass);
341 Index++;
342
343 Index += swprintf(&Buffer[Index],
344 L"PCI\\VEN_%04X&CC_%02X%02X%02X",
345 Device->PciConfig.VendorID,
346 Device->PciConfig.BaseClass,
347 Device->PciConfig.SubClass,
348 Device->PciConfig.ProgIf);
349 Index++;
350
351 Index += swprintf(&Buffer[Index],
352 L"PCI\\VEN_%04X&CC_%02X%02X",
353 Device->PciConfig.VendorID,
354 Device->PciConfig.BaseClass,
355 Device->PciConfig.SubClass);
356 Index++;
357
358 Index += swprintf(&Buffer[Index],
359 L"PCI\\VEN_%04X",
360 Device->PciConfig.VendorID);
361 Index++;
362
363 Index += swprintf(&Buffer[Index],
364 L"PCI\\CC_%02X%02X%02X",
365 Device->PciConfig.BaseClass,
366 Device->PciConfig.SubClass,
367 Device->PciConfig.ProgIf);
368 Index++;
369
370 Index += swprintf(&Buffer[Index],
371 L"PCI\\CC_%02X%02X",
372 Device->PciConfig.BaseClass,
373 Device->PciConfig.SubClass);
374 Index++;
375
376 Buffer[Index] = UNICODE_NULL;
377
378 Length = (Index + 1) * sizeof(WCHAR);
379 CompatibleIDs->Buffer = ExAllocatePool(PagedPool, Length);
380 if (CompatibleIDs->Buffer == NULL)
381 {
382 return FALSE;
383 }
384
385 CompatibleIDs->Length = Length - sizeof(WCHAR);
386 CompatibleIDs->MaximumLength = Length;
387 RtlCopyMemory(CompatibleIDs->Buffer, Buffer, Length);
388
389 return TRUE;
390 }
391
392
393 BOOLEAN
394 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription,
395 PPCI_DEVICE Device)
396 {
397 PWSTR Description;
398 ULONG Length;
399
400 switch (Device->PciConfig.BaseClass)
401 {
402 case PCI_CLASS_PRE_20:
403 switch (Device->PciConfig.SubClass)
404 {
405 case PCI_SUBCLASS_PRE_20_VGA:
406 Description = L"VGA device";
407 break;
408
409 default:
410 case PCI_SUBCLASS_PRE_20_NON_VGA:
411 Description = L"PCI device";
412 break;
413 }
414 break;
415
416 case PCI_CLASS_MASS_STORAGE_CTLR:
417 switch (Device->PciConfig.SubClass)
418 {
419 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR:
420 Description = L"SCSI controller";
421 break;
422
423 case PCI_SUBCLASS_MSC_IDE_CTLR:
424 Description = L"IDE controller";
425 break;
426
427 case PCI_SUBCLASS_MSC_FLOPPY_CTLR:
428 Description = L"Floppy disk controller";
429 break;
430
431 case PCI_SUBCLASS_MSC_IPI_CTLR:
432 Description = L"IPI controller";
433 break;
434
435 case PCI_SUBCLASS_MSC_RAID_CTLR:
436 Description = L"RAID controller";
437 break;
438
439 default:
440 Description = L"Mass storage controller";
441 break;
442 }
443 break;
444
445 case PCI_CLASS_NETWORK_CTLR:
446 switch (Device->PciConfig.SubClass)
447 {
448 case PCI_SUBCLASS_NET_ETHERNET_CTLR:
449 Description = L"Ethernet controller";
450 break;
451
452 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR:
453 Description = L"Token-Ring controller";
454 break;
455
456 case PCI_SUBCLASS_NET_FDDI_CTLR:
457 Description = L"FDDI controller";
458 break;
459
460 case PCI_SUBCLASS_NET_ATM_CTLR:
461 Description = L"ATM controller";
462 break;
463
464 default:
465 Description = L"Network controller";
466 break;
467 }
468 break;
469
470 case PCI_CLASS_DISPLAY_CTLR:
471 switch (Device->PciConfig.SubClass)
472 {
473 case PCI_SUBCLASS_VID_VGA_CTLR:
474 Description = L"VGA display controller";
475 break;
476
477 case PCI_SUBCLASS_VID_XGA_CTLR:
478 Description = L"XGA display controller";
479 break;
480
481 case PCI_SUBLCASS_VID_3D_CTLR:
482 Description = L"Multimedia display controller";
483 break;
484
485 default:
486 Description = L"Other display controller";
487 break;
488 }
489 break;
490
491 case PCI_CLASS_MULTIMEDIA_DEV:
492 switch (Device->PciConfig.SubClass)
493 {
494 case PCI_SUBCLASS_MM_VIDEO_DEV:
495 Description = L"Multimedia video device";
496 break;
497
498 case PCI_SUBCLASS_MM_AUDIO_DEV:
499 Description = L"Multimedia audio device";
500 break;
501
502 case PCI_SUBCLASS_MM_TELEPHONY_DEV:
503 Description = L"Multimedia telephony device";
504 break;
505
506 default:
507 Description = L"Other multimedia device";
508 break;
509 }
510 break;
511
512 case PCI_CLASS_MEMORY_CTLR:
513 switch (Device->PciConfig.SubClass)
514 {
515 case PCI_SUBCLASS_MEM_RAM:
516 Description = L"PCI Memory";
517 break;
518
519 case PCI_SUBCLASS_MEM_FLASH:
520 Description = L"PCI Flash Memory";
521 break;
522
523 default:
524 Description = L"Other memory controller";
525 break;
526 }
527 break;
528
529 case PCI_CLASS_BRIDGE_DEV:
530 switch (Device->PciConfig.SubClass)
531 {
532 case PCI_SUBCLASS_BR_HOST:
533 Description = L"PCI-Host bridge";
534 break;
535
536 case PCI_SUBCLASS_BR_ISA:
537 Description = L"PCI-ISA bridge";
538 break;
539
540 case PCI_SUBCLASS_BR_EISA:
541 Description = L"PCI-EISA bridge";
542 break;
543
544 case PCI_SUBCLASS_BR_MCA:
545 Description = L"PCI-Micro Channel bridge";
546 break;
547
548 case PCI_SUBCLASS_BR_PCI_TO_PCI:
549 Description = L"PCI-PCI bridge";
550 break;
551
552 case PCI_SUBCLASS_BR_PCMCIA:
553 Description = L"PCI-PCMCIA bridge";
554 break;
555
556 case PCI_SUBCLASS_BR_NUBUS:
557 Description = L"PCI-NUBUS bridge";
558 break;
559
560 case PCI_SUBCLASS_BR_CARDBUS:
561 Description = L"PCI-CARDBUS bridge";
562 break;
563
564 default:
565 Description = L"Other bridge device";
566 break;
567 }
568 break;
569
570 case PCI_CLASS_SIMPLE_COMMS_CTLR:
571 switch (Device->PciConfig.SubClass)
572 {
573
574 default:
575 Description = L"Communication device";
576 break;
577 }
578 break;
579
580 case PCI_CLASS_BASE_SYSTEM_DEV:
581 switch (Device->PciConfig.SubClass)
582 {
583
584 default:
585 Description = L"System device";
586 break;
587 }
588 break;
589
590 case PCI_CLASS_INPUT_DEV:
591 switch (Device->PciConfig.SubClass)
592 {
593
594 default:
595 Description = L"Input device";
596 break;
597 }
598 break;
599
600 case PCI_CLASS_DOCKING_STATION:
601 switch (Device->PciConfig.SubClass)
602 {
603
604 default:
605 Description = L"Docking station";
606 break;
607 }
608 break;
609
610 case PCI_CLASS_PROCESSOR:
611 switch (Device->PciConfig.SubClass)
612 {
613
614 default:
615 Description = L"Processor";
616 break;
617 }
618 break;
619
620 case PCI_CLASS_SERIAL_BUS_CTLR:
621 switch (Device->PciConfig.SubClass)
622 {
623 case PCI_SUBCLASS_SB_IEEE1394:
624 Description = L"FireWire controller";
625 break;
626
627 case PCI_SUBCLASS_SB_ACCESS:
628 Description = L"ACCESS bus controller";
629 break;
630
631 case PCI_SUBCLASS_SB_SSA:
632 Description = L"SSA controller";
633 break;
634
635 case PCI_SUBCLASS_SB_USB:
636 Description = L"USB controller";
637 break;
638
639 case PCI_SUBCLASS_SB_FIBRE_CHANNEL:
640 Description = L"Fibre Channel controller";
641 break;
642
643 default:
644 Description = L"Other serial bus controller";
645 break;
646 }
647 break;
648
649 default:
650 Description = L"Other PCI Device";
651 break;
652 }
653
654 Length = (wcslen(Description) + 1) * sizeof(WCHAR);
655 DeviceDescription->Buffer = ExAllocatePool(PagedPool, Length);
656 if (DeviceDescription->Buffer == NULL)
657 {
658 return FALSE;
659 }
660
661 DeviceDescription->Length = Length - sizeof(WCHAR);
662 DeviceDescription->MaximumLength = Length;
663 RtlCopyMemory(DeviceDescription->Buffer, Description, Length);
664
665 return TRUE;
666 }
667
668
669 BOOLEAN
670 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation,
671 PPCI_DEVICE Device)
672 {
673 WCHAR Buffer[256];
674 ULONG Length;
675 ULONG Index;
676
677 Index = 0;
678 Index += swprintf(&Buffer[Index],
679 L"PCI-Bus %lu, Device %u, Function %u",
680 Device->BusNumber,
681 Device->SlotNumber.u.bits.DeviceNumber,
682 Device->SlotNumber.u.bits.FunctionNumber);
683 Index++;
684
685 Buffer[Index] = UNICODE_NULL;
686
687 Length = (Index + 1) * sizeof(WCHAR);
688 DeviceLocation->Buffer = ExAllocatePool(PagedPool, Length);
689 if (DeviceLocation->Buffer == NULL)
690 {
691 return FALSE;
692 }
693
694 DeviceLocation->Length = Length - sizeof(WCHAR);
695 DeviceLocation->MaximumLength = Length;
696 RtlCopyMemory(DeviceLocation->Buffer, Buffer, Length);
697
698 return TRUE;
699 }
700
701 /* EOF */