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