Implement InterfacePciDevicePresent(Ex) of PCI_DEVICE_PRESENT_INTERFACE
[reactos.git] / reactos / 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 <ddk/ntddk.h>
11 #include <ddk/ntifs.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 PPCI_DRIVER_EXTENSION DriverExtension = NULL;
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 NTSTATUS Status;
178
179 DPRINT("Peripheral Component Interconnect Bus Driver\n");
180
181 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
182 DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl;
183 DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl;
184 DriverObject->DriverExtension->AddDevice = PciAddDevice;
185
186 Status = IoAllocateDriverObjectExtension(
187 DriverObject,
188 DriverObject,
189 sizeof(PCI_DRIVER_EXTENSION),
190 (PVOID*)&DriverExtension);
191 if (!NT_SUCCESS(Status))
192 return Status;
193 RtlZeroMemory(DriverExtension, sizeof(PCI_DRIVER_EXTENSION));
194
195 InitializeListHead(&DriverExtension->BusListHead);
196 KeInitializeSpinLock(&DriverExtension->BusListLock);
197
198 return STATUS_SUCCESS;
199 }
200
201
202 NTSTATUS
203 PciCreateDeviceIDString(PUNICODE_STRING DeviceID,
204 PPCI_DEVICE Device)
205 {
206 WCHAR Buffer[256];
207
208 swprintf(Buffer,
209 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
210 Device->PciConfig.VendorID,
211 Device->PciConfig.DeviceID,
212 (Device->PciConfig.u.type0.SubSystemID << 16) +
213 Device->PciConfig.u.type0.SubVendorID,
214 Device->PciConfig.RevisionID);
215
216 return RtlCreateUnicodeString(DeviceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
217 }
218
219
220 NTSTATUS
221 PciCreateInstanceIDString(PUNICODE_STRING InstanceID,
222 PPCI_DEVICE Device)
223 {
224 WCHAR Buffer[32];
225 ULONG Index;
226
227 Index = 0;
228 if (((PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension)->PciDevice->BusNumber != 0)
229 {
230 /* FIXME: Copy InstanceID of parent PCI bus to Buffer */
231 // Index += swprintf(Buffer, ....);
232 }
233
234 swprintf(&Buffer[Index], L"%02X", Device->SlotNumber.u.AsULONG & 0xff);
235
236 return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
237 }
238
239
240 NTSTATUS
241 PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs,
242 PPCI_DEVICE Device)
243 {
244 WCHAR Buffer[256];
245 UNICODE_STRING BufferU;
246 ULONG Index;
247
248 Index = 0;
249 Index += swprintf(&Buffer[Index],
250 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
251 Device->PciConfig.VendorID,
252 Device->PciConfig.DeviceID,
253 (Device->PciConfig.u.type0.SubSystemID << 16) +
254 Device->PciConfig.u.type0.SubVendorID,
255 Device->PciConfig.RevisionID);
256 Index++;
257
258 Index += swprintf(&Buffer[Index],
259 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X",
260 Device->PciConfig.VendorID,
261 Device->PciConfig.DeviceID,
262 (Device->PciConfig.u.type0.SubSystemID << 16) +
263 Device->PciConfig.u.type0.SubVendorID);
264 Index++;
265
266 Index += swprintf(&Buffer[Index],
267 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",
268 Device->PciConfig.VendorID,
269 Device->PciConfig.DeviceID,
270 Device->PciConfig.BaseClass,
271 Device->PciConfig.SubClass,
272 Device->PciConfig.ProgIf);
273 Index++;
274
275 Index += swprintf(&Buffer[Index],
276 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",
277 Device->PciConfig.VendorID,
278 Device->PciConfig.DeviceID,
279 Device->PciConfig.BaseClass,
280 Device->PciConfig.SubClass);
281 Index++;
282
283 Buffer[Index] = UNICODE_NULL;
284
285 BufferU.Length = BufferU.MaximumLength = Index * sizeof(WCHAR);
286 BufferU.Buffer = Buffer;
287
288 return RtlDuplicateUnicodeString(0, &BufferU, HardwareIDs);
289 }
290
291
292 NTSTATUS
293 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs,
294 PPCI_DEVICE Device)
295 {
296 WCHAR Buffer[256];
297 UNICODE_STRING BufferU;
298 ULONG Index;
299
300 Index = 0;
301 Index += swprintf(&Buffer[Index],
302 L"PCI\\VEN_%04X&DEV_%04X&REV_%02X",
303 Device->PciConfig.VendorID,
304 Device->PciConfig.DeviceID,
305 Device->PciConfig.RevisionID);
306 Index++;
307
308 Index += swprintf(&Buffer[Index],
309 L"PCI\\VEN_%04X&DEV_%04X",
310 Device->PciConfig.VendorID,
311 Device->PciConfig.DeviceID);
312 Index++;
313
314 Index += swprintf(&Buffer[Index],
315 L"PCI\\VEN_%04X&CC_%02X%02X%02X",
316 Device->PciConfig.VendorID,
317 Device->PciConfig.BaseClass,
318 Device->PciConfig.SubClass,
319 Device->PciConfig.ProgIf);
320 Index++;
321
322 Index += swprintf(&Buffer[Index],
323 L"PCI\\VEN_%04X&CC_%02X%02X",
324 Device->PciConfig.VendorID,
325 Device->PciConfig.BaseClass,
326 Device->PciConfig.SubClass);
327 Index++;
328
329 Index += swprintf(&Buffer[Index],
330 L"PCI\\VEN_%04X",
331 Device->PciConfig.VendorID);
332 Index++;
333
334 Index += swprintf(&Buffer[Index],
335 L"PCI\\CC_%02X%02X%02X",
336 Device->PciConfig.BaseClass,
337 Device->PciConfig.SubClass,
338 Device->PciConfig.ProgIf);
339 Index++;
340
341 Index += swprintf(&Buffer[Index],
342 L"PCI\\CC_%02X%02X",
343 Device->PciConfig.BaseClass,
344 Device->PciConfig.SubClass);
345 Index++;
346
347 Buffer[Index] = UNICODE_NULL;
348
349 BufferU.Length = BufferU.MaximumLength = Index * sizeof(WCHAR);
350 BufferU.Buffer = Buffer;
351
352 return RtlDuplicateUnicodeString(0, &BufferU, CompatibleIDs);
353 }
354
355
356 NTSTATUS
357 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription,
358 PPCI_DEVICE Device)
359 {
360 PCWSTR Description;
361
362 switch (Device->PciConfig.BaseClass)
363 {
364 case PCI_CLASS_PRE_20:
365 switch (Device->PciConfig.SubClass)
366 {
367 case PCI_SUBCLASS_PRE_20_VGA:
368 Description = L"VGA device";
369 break;
370
371 default:
372 case PCI_SUBCLASS_PRE_20_NON_VGA:
373 Description = L"PCI device";
374 break;
375 }
376 break;
377
378 case PCI_CLASS_MASS_STORAGE_CTLR:
379 switch (Device->PciConfig.SubClass)
380 {
381 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR:
382 Description = L"SCSI controller";
383 break;
384
385 case PCI_SUBCLASS_MSC_IDE_CTLR:
386 Description = L"IDE controller";
387 break;
388
389 case PCI_SUBCLASS_MSC_FLOPPY_CTLR:
390 Description = L"Floppy disk controller";
391 break;
392
393 case PCI_SUBCLASS_MSC_IPI_CTLR:
394 Description = L"IPI controller";
395 break;
396
397 case PCI_SUBCLASS_MSC_RAID_CTLR:
398 Description = L"RAID controller";
399 break;
400
401 default:
402 Description = L"Mass storage controller";
403 break;
404 }
405 break;
406
407 case PCI_CLASS_NETWORK_CTLR:
408 switch (Device->PciConfig.SubClass)
409 {
410 case PCI_SUBCLASS_NET_ETHERNET_CTLR:
411 Description = L"Ethernet controller";
412 break;
413
414 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR:
415 Description = L"Token-Ring controller";
416 break;
417
418 case PCI_SUBCLASS_NET_FDDI_CTLR:
419 Description = L"FDDI controller";
420 break;
421
422 case PCI_SUBCLASS_NET_ATM_CTLR:
423 Description = L"ATM controller";
424 break;
425
426 default:
427 Description = L"Network controller";
428 break;
429 }
430 break;
431
432 case PCI_CLASS_DISPLAY_CTLR:
433 switch (Device->PciConfig.SubClass)
434 {
435 case PCI_SUBCLASS_VID_VGA_CTLR:
436 Description = L"VGA display controller";
437 break;
438
439 case PCI_SUBCLASS_VID_XGA_CTLR:
440 Description = L"XGA display controller";
441 break;
442
443 case PCI_SUBLCASS_VID_3D_CTLR:
444 Description = L"Multimedia display controller";
445 break;
446
447 default:
448 Description = L"Other display controller";
449 break;
450 }
451 break;
452
453 case PCI_CLASS_MULTIMEDIA_DEV:
454 switch (Device->PciConfig.SubClass)
455 {
456 case PCI_SUBCLASS_MM_VIDEO_DEV:
457 Description = L"Multimedia video device";
458 break;
459
460 case PCI_SUBCLASS_MM_AUDIO_DEV:
461 Description = L"Multimedia audio device";
462 break;
463
464 case PCI_SUBCLASS_MM_TELEPHONY_DEV:
465 Description = L"Multimedia telephony device";
466 break;
467
468 default:
469 Description = L"Other multimedia device";
470 break;
471 }
472 break;
473
474 case PCI_CLASS_MEMORY_CTLR:
475 switch (Device->PciConfig.SubClass)
476 {
477 case PCI_SUBCLASS_MEM_RAM:
478 Description = L"PCI Memory";
479 break;
480
481 case PCI_SUBCLASS_MEM_FLASH:
482 Description = L"PCI Flash Memory";
483 break;
484
485 default:
486 Description = L"Other memory controller";
487 break;
488 }
489 break;
490
491 case PCI_CLASS_BRIDGE_DEV:
492 switch (Device->PciConfig.SubClass)
493 {
494 case PCI_SUBCLASS_BR_HOST:
495 Description = L"PCI-Host bridge";
496 break;
497
498 case PCI_SUBCLASS_BR_ISA:
499 Description = L"PCI-ISA bridge";
500 break;
501
502 case PCI_SUBCLASS_BR_EISA:
503 Description = L"PCI-EISA bridge";
504 break;
505
506 case PCI_SUBCLASS_BR_MCA:
507 Description = L"PCI-Micro Channel bridge";
508 break;
509
510 case PCI_SUBCLASS_BR_PCI_TO_PCI:
511 Description = L"PCI-PCI bridge";
512 break;
513
514 case PCI_SUBCLASS_BR_PCMCIA:
515 Description = L"PCI-PCMCIA bridge";
516 break;
517
518 case PCI_SUBCLASS_BR_NUBUS:
519 Description = L"PCI-NUBUS bridge";
520 break;
521
522 case PCI_SUBCLASS_BR_CARDBUS:
523 Description = L"PCI-CARDBUS bridge";
524 break;
525
526 default:
527 Description = L"Other bridge device";
528 break;
529 }
530 break;
531
532 case PCI_CLASS_SIMPLE_COMMS_CTLR:
533 switch (Device->PciConfig.SubClass)
534 {
535
536 default:
537 Description = L"Communication device";
538 break;
539 }
540 break;
541
542 case PCI_CLASS_BASE_SYSTEM_DEV:
543 switch (Device->PciConfig.SubClass)
544 {
545
546 default:
547 Description = L"System device";
548 break;
549 }
550 break;
551
552 case PCI_CLASS_INPUT_DEV:
553 switch (Device->PciConfig.SubClass)
554 {
555
556 default:
557 Description = L"Input device";
558 break;
559 }
560 break;
561
562 case PCI_CLASS_DOCKING_STATION:
563 switch (Device->PciConfig.SubClass)
564 {
565
566 default:
567 Description = L"Docking station";
568 break;
569 }
570 break;
571
572 case PCI_CLASS_PROCESSOR:
573 switch (Device->PciConfig.SubClass)
574 {
575
576 default:
577 Description = L"Processor";
578 break;
579 }
580 break;
581
582 case PCI_CLASS_SERIAL_BUS_CTLR:
583 switch (Device->PciConfig.SubClass)
584 {
585 case PCI_SUBCLASS_SB_IEEE1394:
586 Description = L"FireWire controller";
587 break;
588
589 case PCI_SUBCLASS_SB_ACCESS:
590 Description = L"ACCESS bus controller";
591 break;
592
593 case PCI_SUBCLASS_SB_SSA:
594 Description = L"SSA controller";
595 break;
596
597 case PCI_SUBCLASS_SB_USB:
598 Description = L"USB controller";
599 break;
600
601 case PCI_SUBCLASS_SB_FIBRE_CHANNEL:
602 Description = L"Fibre Channel controller";
603 break;
604
605 default:
606 Description = L"Other serial bus controller";
607 break;
608 }
609 break;
610
611 default:
612 Description = L"Other PCI Device";
613 break;
614 }
615
616 return RtlCreateUnicodeString(DeviceDescription, Description) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
617 }
618
619
620 NTSTATUS
621 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation,
622 PPCI_DEVICE Device)
623 {
624 WCHAR Buffer[256];
625
626 swprintf(Buffer,
627 L"PCI-Bus %lu, Device %u, Function %u",
628 Device->BusNumber,
629 Device->SlotNumber.u.bits.DeviceNumber,
630 Device->SlotNumber.u.bits.FunctionNumber);
631
632 return RtlCreateUnicodeString(DeviceLocation, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
633 }
634
635 /* EOF */