[USBPORT]
[reactos.git] / reactos / drivers / usb / usbport / pnp.c
1 #include "usbport.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 #define NDEBUG_USBPORT_CORE
7 #include "usbdebug.h"
8
9 IO_COMPLETION_ROUTINE USBPORT_FdoStartCompletion;
10
11 NTSTATUS
12 NTAPI
13 USBPORT_FdoStartCompletion(IN PDEVICE_OBJECT DeviceObject,
14 IN PIRP Irp,
15 IN PVOID Context)
16 {
17 KeSetEvent((PKEVENT)Context, EVENT_INCREMENT, FALSE);
18 return STATUS_MORE_PROCESSING_REQUIRED;
19 }
20
21 NTSTATUS
22 NTAPI
23 USBPORT_RegisterDeviceInterface(IN PDEVICE_OBJECT PdoDevice,
24 IN PDEVICE_OBJECT DeviceObject,
25 IN CONST GUID *InterfaceClassGuid,
26 IN BOOLEAN Enable)
27 {
28 PUSBPORT_RHDEVICE_EXTENSION DeviceExtension;
29 PUNICODE_STRING SymbolicLinkName;
30 NTSTATUS Status;
31
32 DPRINT("USBPORT_RegisterDeviceInterface: Enable - %x\n", Enable);
33
34 DeviceExtension = DeviceObject->DeviceExtension;
35 SymbolicLinkName = &DeviceExtension->CommonExtension.SymbolicLinkName;
36
37 if (Enable)
38 {
39 Status = IoRegisterDeviceInterface(PdoDevice,
40 InterfaceClassGuid,
41 NULL,
42 SymbolicLinkName);
43
44 if (NT_SUCCESS(Status))
45 {
46 DeviceExtension->CommonExtension.IsInterfaceEnabled = 1;
47
48 Status = USBPORT_SetRegistryKeyValue(PdoDevice,
49 FALSE,
50 REG_SZ,
51 L"SymbolicName",
52 SymbolicLinkName->Buffer,
53 SymbolicLinkName->Length);
54
55 if (NT_SUCCESS(Status))
56 {
57 DPRINT("USBPORT_RegisterDeviceInterface: LinkName - %wZ\n",
58 &DeviceExtension->CommonExtension.SymbolicLinkName);
59
60 Status = IoSetDeviceInterfaceState(SymbolicLinkName, TRUE);
61 }
62 }
63 }
64 else
65 {
66 /* Disable device interface */
67 Status = IoSetDeviceInterfaceState(SymbolicLinkName, FALSE);
68
69 if (NT_SUCCESS(Status))
70 {
71 RtlFreeUnicodeString(SymbolicLinkName);
72 DeviceExtension->CommonExtension.IsInterfaceEnabled = 0; // Disabled interface
73 }
74 }
75
76 return Status;
77 }
78
79 BOOLEAN
80 NTAPI
81 USBPORT_IsSelectiveSuspendEnabled(IN PDEVICE_OBJECT FdoDevice)
82 {
83 PUSBPORT_DEVICE_EXTENSION FdoExtension;
84 ULONG Disabled = 0;
85
86 DPRINT("USBPORT_IsSelectiveSuspendEnabled: ... \n");
87
88 FdoExtension = FdoDevice->DeviceExtension;
89
90 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
91 FdoExtension->CommonExtension.LowerPdoDevice,
92 TRUE,
93 L"HcDisableSelectiveSuspend",
94 sizeof(L"HcDisableSelectiveSuspend"),
95 &Disabled,
96 sizeof(Disabled));
97
98 return (Disabled == 0);
99 }
100
101 NTSTATUS
102 NTAPI
103 USBPORT_GetConfigValue(IN PWSTR ValueName,
104 IN ULONG ValueType,
105 IN PVOID ValueData,
106 IN ULONG ValueLength,
107 IN PVOID Context,
108 IN PVOID EntryContext)
109 {
110 NTSTATUS Status = STATUS_SUCCESS;
111
112 DPRINT("USBPORT_GetConfigValue \n");
113
114 if (ValueType == REG_DWORD)
115 {
116 *(PULONG)EntryContext = *(PULONG)ValueData;
117 }
118 else
119 {
120 Status = STATUS_INVALID_PARAMETER;
121 }
122
123 return Status;
124 }
125
126 NTSTATUS
127 NTAPI
128 USBPORT_GetDefaultBIOSx(IN PDEVICE_OBJECT FdoDevice,
129 IN PULONG UsbBIOSx,
130 IN PULONG DisableSelectiveSuspend,
131 IN PULONG DisableCcDetect,
132 IN PULONG IdleEpSupport,
133 IN PULONG IdleEpSupportEx,
134 IN PULONG SoftRetry)
135 {
136 RTL_QUERY_REGISTRY_TABLE QueryTable[7];
137
138 DPRINT("USBPORT_GetDefaultBIOS_X: ... \n");
139
140 RtlZeroMemory(QueryTable, sizeof(QueryTable));
141
142 *UsbBIOSx = 2;
143
144 QueryTable[0].QueryRoutine = USBPORT_GetConfigValue;
145 QueryTable[0].Flags = 0;
146 QueryTable[0].Name = L"UsbBIOSx";
147 QueryTable[0].EntryContext = UsbBIOSx;
148 QueryTable[0].DefaultType = REG_DWORD;
149 QueryTable[0].DefaultData = UsbBIOSx;
150 QueryTable[0].DefaultLength = sizeof(ULONG);
151
152 QueryTable[1].QueryRoutine = USBPORT_GetConfigValue;
153 QueryTable[1].Flags = 0;
154 QueryTable[1].Name = L"DisableSelectiveSuspend";
155 QueryTable[1].EntryContext = DisableSelectiveSuspend;
156 QueryTable[1].DefaultType = REG_DWORD;
157 QueryTable[1].DefaultData = DisableSelectiveSuspend;
158 QueryTable[1].DefaultLength = sizeof(ULONG);
159
160 QueryTable[2].QueryRoutine = USBPORT_GetConfigValue;
161 QueryTable[2].Flags = 0;
162 QueryTable[2].Name = L"DisableCcDetect";
163 QueryTable[2].EntryContext = DisableCcDetect;
164 QueryTable[2].DefaultType = REG_DWORD;
165 QueryTable[2].DefaultData = DisableCcDetect;
166 QueryTable[2].DefaultLength = sizeof(ULONG);
167
168 QueryTable[3].QueryRoutine = USBPORT_GetConfigValue;
169 QueryTable[3].Flags = 0;
170 QueryTable[3].Name = L"EnIdleEndpointSupport";
171 QueryTable[3].EntryContext = IdleEpSupport;
172 QueryTable[3].DefaultType = REG_DWORD;
173 QueryTable[3].DefaultData = IdleEpSupport;
174 QueryTable[3].DefaultLength = sizeof(ULONG);
175
176 QueryTable[4].QueryRoutine = USBPORT_GetConfigValue;
177 QueryTable[4].Flags = 0;
178 QueryTable[4].Name = L"EnIdleEndpointSupportEx";
179 QueryTable[4].EntryContext = IdleEpSupportEx;
180 QueryTable[4].DefaultType = REG_DWORD;
181 QueryTable[4].DefaultData = IdleEpSupportEx;
182 QueryTable[4].DefaultLength = sizeof(ULONG);
183
184 QueryTable[5].QueryRoutine = USBPORT_GetConfigValue;
185 QueryTable[5].Flags = 0;
186 QueryTable[5].Name = L"EnSoftRetry";
187 QueryTable[5].EntryContext = SoftRetry;
188 QueryTable[5].DefaultType = REG_DWORD;
189 QueryTable[5].DefaultData = SoftRetry;
190 QueryTable[5].DefaultLength = sizeof(ULONG);
191
192 return RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
193 L"usb",
194 QueryTable,
195 NULL,
196 NULL);
197 }
198
199 NTSTATUS
200 NTAPI
201 USBPORT_IsCompanionController(IN PDEVICE_OBJECT DeviceObject,
202 IN BOOLEAN *IsCompanion)
203 {
204 PDEVICE_OBJECT HighestDevice;
205 PIRP Irp;
206 KEVENT Event;
207 PIO_STACK_LOCATION IoStack;
208 PCI_DEVICE_PRESENT_INTERFACE PciInterface = {0};
209 PCI_DEVICE_PRESENCE_PARAMETERS Parameters = {0};
210 IO_STATUS_BLOCK IoStatusBlock;
211 NTSTATUS Status;
212 BOOLEAN IsPresent;
213
214 DPRINT("USBPORT_IsCompanionController: ... \n");
215
216 *IsCompanion = FALSE;
217
218 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
219
220 HighestDevice = IoGetAttachedDeviceReference(DeviceObject);
221
222 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
223 HighestDevice,
224 NULL,
225 0,
226 NULL,
227 &Event,
228 &IoStatusBlock);
229
230 if (!Irp)
231 {
232 Status = STATUS_INSUFFICIENT_RESOURCES;
233 ObDereferenceObject(HighestDevice);
234 return Status;
235 }
236
237 IoStack = IoGetNextIrpStackLocation(Irp);
238
239 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
240 Irp->IoStatus.Information = 0;
241
242 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
243
244 IoStack->Parameters.QueryInterface.InterfaceType = &GUID_PCI_DEVICE_PRESENT_INTERFACE;
245 IoStack->Parameters.QueryInterface.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
246 IoStack->Parameters.QueryInterface.Version = 1;
247 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)&PciInterface;
248 IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
249
250 Status = IoCallDriver(HighestDevice, Irp);
251
252 if (Status == STATUS_PENDING)
253 {
254 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
255 Status = IoStatusBlock.Status;
256 }
257
258 if (!NT_SUCCESS(Status))
259 {
260 DPRINT1("USBPORT_IsCompanionController: query interface failed\\n");
261 ObDereferenceObject(HighestDevice);
262 return Status;
263 }
264
265 DPRINT("USBPORT_IsCompanionController: query interface succeeded\n");
266
267 if (PciInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
268 {
269 DPRINT1("USBPORT_IsCompanionController: old version\n");
270 ObDereferenceObject(HighestDevice);
271 return Status;
272 }
273
274 Parameters.Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
275
276 Parameters.BaseClass = PCI_CLASS_SERIAL_BUS_CTLR;
277 Parameters.SubClass = PCI_SUBCLASS_SB_USB;
278 Parameters.ProgIf = PCI_INTERFACE_USB_ID_EHCI;
279
280 Parameters.Flags = PCI_USE_LOCAL_BUS |
281 PCI_USE_LOCAL_DEVICE |
282 PCI_USE_CLASS_SUBCLASS |
283 PCI_USE_PROGIF;
284
285 IsPresent = (PciInterface.IsDevicePresentEx)(PciInterface.Context,
286 &Parameters);
287
288 if (IsPresent)
289 {
290 DPRINT("USBPORT_IsCompanionController: Present EHCI controller for FDO - %p\n",
291 DeviceObject);
292 }
293 else
294 {
295 DPRINT("USBPORT_IsCompanionController: No EHCI controller for FDO - %p\n",
296 DeviceObject);
297 }
298
299 *IsCompanion = IsPresent;
300
301 (PciInterface.InterfaceDereference)(PciInterface.Context);
302
303 ObDereferenceObject(HighestDevice);
304
305 return Status;
306 }
307
308 NTSTATUS
309 NTAPI
310 USBPORT_QueryPciBusInterface(IN PDEVICE_OBJECT FdoDevice)
311 {
312 PUSBPORT_DEVICE_EXTENSION FdoExtension;
313 PBUS_INTERFACE_STANDARD BusInterface;
314 PIO_STACK_LOCATION IoStack;
315 IO_STATUS_BLOCK IoStatusBlock;
316 PDEVICE_OBJECT HighestDevice;
317 KEVENT Event;
318 PIRP Irp;
319 NTSTATUS Status;
320
321 DPRINT("USBPORT_QueryPciBusInterface: ... \n");
322
323 FdoExtension = FdoDevice->DeviceExtension;
324 BusInterface = &FdoExtension->BusInterface;
325
326 RtlZeroMemory(BusInterface, sizeof(BUS_INTERFACE_STANDARD));
327 KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
328 HighestDevice = IoGetAttachedDeviceReference(FdoDevice);
329
330 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
331 HighestDevice,
332 NULL,
333 0,
334 NULL,
335 &Event,
336 &IoStatusBlock);
337
338 if (Irp)
339 {
340 IoStack = IoGetNextIrpStackLocation(Irp);
341
342 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
343 Irp->IoStatus.Information = 0;
344
345 IoStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
346
347 IoStack->Parameters.QueryInterface.InterfaceType = &GUID_BUS_INTERFACE_STANDARD;
348 IoStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
349 IoStack->Parameters.QueryInterface.Version = 1;
350 IoStack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
351 IoStack->Parameters.QueryInterface.InterfaceSpecificData = 0;
352
353 Status = IoCallDriver(HighestDevice, Irp);
354
355 if (Status == STATUS_PENDING)
356 {
357 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
358 Status = IoStatusBlock.Status;
359 }
360 }
361 else
362 {
363 Status = STATUS_INSUFFICIENT_RESOURCES;
364 }
365
366 ObDereferenceObject(HighestDevice);
367
368 DPRINT("USBPORT_QueryPciBusInterface: return Status - %x\n", Status);
369
370 return Status;
371 }
372
373 NTSTATUS
374 NTAPI
375 USBPORT_QueryCapabilities(IN PDEVICE_OBJECT FdoDevice,
376 IN PDEVICE_CAPABILITIES Capabilities)
377 {
378 PUSBPORT_DEVICE_EXTENSION FdoExtention;
379 PIRP Irp;
380 NTSTATUS Status;
381 PIO_STACK_LOCATION IoStack;
382 KEVENT Event;
383
384 DPRINT("USBPORT_QueryCapabilities: ... \n");
385
386 FdoExtention = FdoDevice->DeviceExtension;
387
388 RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES));
389
390 Capabilities->Size = sizeof(DEVICE_CAPABILITIES);
391 Capabilities->Version = 1;
392 Capabilities->Address = MAXULONG;
393 Capabilities->UINumber = MAXULONG;
394
395 Irp = IoAllocateIrp(FdoExtention->CommonExtension.LowerDevice->StackSize,
396 FALSE);
397
398 if (!Irp)
399 {
400 DPRINT1("USBPORT_QueryCapabilities: No resources - IoAllocateIrp!\n");
401 return STATUS_INSUFFICIENT_RESOURCES;
402 }
403
404 IoStack = IoGetCurrentIrpStackLocation(Irp);
405 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
406
407 IoStack = IoGetNextIrpStackLocation(Irp);
408 IoStack->MajorFunction = IRP_MJ_PNP;
409 IoStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
410
411 KeInitializeEvent(&Event, NotificationEvent, FALSE);
412
413 IoSetCompletionRoutine(Irp,
414 USBPORT_FdoStartCompletion,
415 &Event,
416 TRUE,
417 TRUE,
418 TRUE);
419
420 IoStack->Parameters.DeviceCapabilities.Capabilities = Capabilities;
421
422 Status = IoCallDriver(FdoExtention->CommonExtension.LowerDevice, Irp);
423
424 if (Status == STATUS_PENDING)
425 {
426 KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
427 Status = Irp->IoStatus.Status;
428 }
429
430 if (NT_SUCCESS(Status) && Capabilities)
431 {
432 USBPORT_DumpingCapabilities(Capabilities);
433 }
434
435 IoFreeIrp(Irp);
436
437 return Status;
438 }
439
440 NTSTATUS
441 NTAPI
442 USBPORT_CreateLegacySymbolicLink(IN PDEVICE_OBJECT FdoDevice)
443 {
444 PUSBPORT_DEVICE_EXTENSION FdoExtension;
445 WCHAR CharName[255] = {0};
446 WCHAR CharDosName[255] = {0};
447 UNICODE_STRING DeviceName;
448 NTSTATUS Status;
449
450 FdoExtension = FdoDevice->DeviceExtension;
451
452 RtlStringCbPrintfW(CharName,
453 sizeof(CharName),
454 L"\\Device\\USBFDO-%d",
455 FdoExtension->FdoNameNumber);
456
457 RtlInitUnicodeString(&DeviceName, CharName);
458
459 RtlStringCbPrintfW(CharDosName,
460 sizeof(CharDosName),
461 L"\\DosDevices\\HCD%d",
462 FdoExtension->FdoNameNumber);
463
464 RtlInitUnicodeString(&FdoExtension->DosDeviceSymbolicName, CharDosName);
465
466 DPRINT("USBPORT_CreateLegacySymbolicLink: DeviceName - %wZ, DosSymbolicName - %wZ\n",
467 &DeviceName,
468 &FdoExtension->DosDeviceSymbolicName);
469
470 Status = IoCreateSymbolicLink(&FdoExtension->DosDeviceSymbolicName,
471 &DeviceName);
472
473 if (NT_SUCCESS(Status))
474 {
475 FdoExtension->Flags |= USBPORT_FLAG_DOS_SYMBOLIC_NAME;
476 }
477
478 return Status;
479 }
480
481 NTSTATUS
482 NTAPI
483 USBPORT_StopDevice(IN PDEVICE_OBJECT FdoDevice)
484 {
485 DPRINT1("USBPORT_StopDevice: UNIMPLEMENTED. FIXME\n");
486 DbgBreakPoint();
487 return STATUS_SUCCESS;
488 }
489
490 NTSTATUS
491 NTAPI
492 USBPORT_StartDevice(IN PDEVICE_OBJECT FdoDevice,
493 IN PUSBPORT_RESOURCES UsbPortResources)
494 {
495 PUSBPORT_DEVICE_EXTENSION FdoExtension;
496 PUSBPORT_REGISTRATION_PACKET Packet;
497 NTSTATUS Status;
498 PCI_COMMON_CONFIG PciConfig;
499 ULONG BytesRead;
500 DEVICE_DESCRIPTION DeviceDescription;
501 PDMA_ADAPTER DmaAdapter = NULL;
502 ULONG MiniPortStatus;
503 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
504 ULONG ResultLength;
505 ULONG DisableSelectiveSuspend = 0;
506 ULONG DisableCcDetect = 0;
507 ULONG IdleEpSupport = 0;
508 ULONG IdleEpSupportEx = 0;
509 ULONG SoftRetry = 0;
510 ULONG Limit2GB = 0;
511 ULONG TotalBusBandwidth = 0;
512 BOOLEAN IsCompanion = FALSE;
513 ULONG LegacyBIOS;
514 ULONG MiniportFlags;
515
516 DPRINT("USBPORT_StartDevice: FdoDevice - %p, UsbPortResources - %p\n",
517 FdoDevice,
518 UsbPortResources);
519
520 FdoExtension = FdoDevice->DeviceExtension;
521 Packet = &FdoExtension->MiniPortInterface->Packet;
522
523 Status = USBPORT_QueryPciBusInterface(FdoDevice);
524 if (!NT_SUCCESS(Status))
525 goto ExitWithError;
526
527 BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
528 PCI_WHICHSPACE_CONFIG,
529 &PciConfig,
530 0,
531 PCI_COMMON_HDR_LENGTH);
532
533 if (BytesRead != PCI_COMMON_HDR_LENGTH)
534 {
535 DPRINT1("USBPORT_StartDevice: Failed to get pci config information!\n");
536 goto ExitWithError;
537 }
538
539 FdoExtension->VendorID = PciConfig.VendorID;
540 FdoExtension->DeviceID = PciConfig.DeviceID;
541 FdoExtension->RevisionID = PciConfig.RevisionID;
542 FdoExtension->ProgIf = PciConfig.ProgIf;
543 FdoExtension->SubClass = PciConfig.SubClass;
544 FdoExtension->BaseClass = PciConfig.BaseClass;
545
546 RtlZeroMemory(&DeviceDescription, sizeof(DeviceDescription));
547
548 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
549 DeviceDescription.Master = TRUE;
550 DeviceDescription.ScatterGather = TRUE;
551 DeviceDescription.Dma32BitAddresses = TRUE;
552 DeviceDescription.InterfaceType = PCIBus;
553 DeviceDescription.DmaWidth = Width32Bits;
554 DeviceDescription.DmaSpeed = Compatible;
555 DeviceDescription.MaximumLength = MAXULONG;
556
557 DmaAdapter = IoGetDmaAdapter(FdoExtension->CommonExtension.LowerPdoDevice,
558 &DeviceDescription,
559 &FdoExtension->NumberMapRegs);
560
561 FdoExtension->DmaAdapter = DmaAdapter;
562
563 if (!DmaAdapter)
564 {
565 DPRINT1("USBPORT_StartDevice: Failed to get DmaAdapter!\n");
566 Status = STATUS_INSUFFICIENT_RESOURCES;
567 goto ExitWithError;
568 }
569
570 Status = USBPORT_CreateWorkerThread(FdoDevice);
571 if (!NT_SUCCESS(Status))
572 goto ExitWithError;
573
574 Status = USBPORT_QueryCapabilities(FdoDevice, &FdoExtension->Capabilities);
575 if (!NT_SUCCESS(Status))
576 goto ExitWithError;
577
578 FdoExtension->PciDeviceNumber = FdoExtension->Capabilities.Address >> 16;
579 FdoExtension->PciFunctionNumber = FdoExtension->Capabilities.Address & 0xFFFF;
580
581 Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
582 DevicePropertyBusNumber,
583 sizeof(ULONG),
584 &FdoExtension->BusNumber,
585 &ResultLength);
586
587 if (!NT_SUCCESS(Status))
588 goto ExitWithError;
589
590 KeInitializeSpinLock(&FdoExtension->EndpointListSpinLock);
591 KeInitializeSpinLock(&FdoExtension->EpStateChangeSpinLock);
592 KeInitializeSpinLock(&FdoExtension->EndpointClosedSpinLock);
593 KeInitializeSpinLock(&FdoExtension->DeviceHandleSpinLock);
594 KeInitializeSpinLock(&FdoExtension->IdleIoCsqSpinLock);
595 KeInitializeSpinLock(&FdoExtension->BadRequestIoCsqSpinLock);
596 KeInitializeSpinLock(&FdoExtension->MapTransferSpinLock);
597 KeInitializeSpinLock(&FdoExtension->FlushTransferSpinLock);
598 KeInitializeSpinLock(&FdoExtension->FlushPendingTransferSpinLock);
599 KeInitializeSpinLock(&FdoExtension->DoneTransferSpinLock);
600 KeInitializeSpinLock(&FdoExtension->WorkerThreadEventSpinLock);
601 KeInitializeSpinLock(&FdoExtension->MiniportSpinLock);
602 KeInitializeSpinLock(&FdoExtension->TimerFlagsSpinLock);
603 KeInitializeSpinLock(&FdoExtension->PowerWakeSpinLock);
604 KeInitializeSpinLock(&FdoExtension->SetPowerD0SpinLock);
605 KeInitializeSpinLock(&FdoExtension->RootHubCallbackSpinLock);
606
607 KeInitializeDpc(&FdoExtension->IsrDpc, USBPORT_IsrDpc, FdoDevice);
608
609 KeInitializeDpc(&FdoExtension->TransferFlushDpc,
610 USBPORT_TransferFlushDpc,
611 FdoDevice);
612
613 KeInitializeDpc(&FdoExtension->WorkerRequestDpc,
614 USBPORT_WorkerRequestDpc,
615 FdoDevice);
616
617 KeInitializeDpc(&FdoExtension->HcWakeDpc,
618 USBPORT_HcWakeDpc,
619 FdoDevice);
620
621 IoCsqInitialize(&FdoExtension->IdleIoCsq,
622 USBPORT_InsertIdleIrp,
623 USBPORT_RemoveIdleIrp,
624 USBPORT_PeekNextIdleIrp,
625 USBPORT_AcquireIdleLock,
626 USBPORT_ReleaseIdleLock,
627 USBPORT_CompleteCanceledIdleIrp);
628
629 IoCsqInitialize(&FdoExtension->BadRequestIoCsq,
630 USBPORT_InsertBadRequest,
631 USBPORT_RemoveBadRequest,
632 USBPORT_PeekNextBadRequest,
633 USBPORT_AcquireBadRequestLock,
634 USBPORT_ReleaseBadRequestLock,
635 USBPORT_CompleteCanceledBadRequest);
636
637 FdoExtension->IsrDpcCounter = -1;
638 FdoExtension->IsrDpcHandlerCounter = -1;
639 FdoExtension->IdleLockCounter = -1;
640 FdoExtension->BadRequestLockCounter = -1;
641 FdoExtension->ChirpRootPortLock = -1;
642
643 FdoExtension->RHInitCallBackLock = 0;
644
645 FdoExtension->UsbAddressBitMap[0] = 1;
646 FdoExtension->UsbAddressBitMap[1] = 0;
647 FdoExtension->UsbAddressBitMap[2] = 0;
648 FdoExtension->UsbAddressBitMap[3] = 0;
649
650 USBPORT_GetDefaultBIOSx(FdoDevice,
651 &FdoExtension->UsbBIOSx,
652 &DisableSelectiveSuspend,
653 &DisableCcDetect,
654 &IdleEpSupport,
655 &IdleEpSupportEx,
656 &SoftRetry);
657
658 if (DisableSelectiveSuspend)
659 FdoExtension->Flags |= USBPORT_FLAG_BIOS_DISABLE_SS;
660
661 if (!DisableSelectiveSuspend &&
662 USBPORT_IsSelectiveSuspendEnabled(FdoDevice))
663 {
664 FdoExtension->Flags |= USBPORT_FLAG_SELECTIVE_SUSPEND;
665 }
666
667 MiniportFlags = Packet->MiniPortFlags;
668
669 if (MiniportFlags & USB_MINIPORT_FLAGS_POLLING)
670 FdoExtension->Flags |= USBPORT_FLAG_HC_POLLING;
671
672 if (MiniportFlags & USB_MINIPORT_FLAGS_WAKE_SUPPORT)
673 FdoExtension->Flags |= USBPORT_FLAG_HC_WAKE_SUPPORT;
674
675 if (MiniportFlags & USB_MINIPORT_FLAGS_DISABLE_SS)
676 FdoExtension->Flags = (FdoExtension->Flags & ~USBPORT_FLAG_SELECTIVE_SUSPEND) |
677 USBPORT_FLAG_BIOS_DISABLE_SS;
678
679 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
680 TRUE,
681 REG_DWORD,
682 L"EnIdleEndpointSupport",
683 &IdleEpSupport,
684 sizeof(IdleEpSupport));
685
686 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
687 TRUE,
688 REG_DWORD,
689 L"EnIdleEndpointSupportEx",
690 &IdleEpSupportEx,
691 sizeof(IdleEpSupportEx));
692
693 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
694 TRUE,
695 REG_DWORD,
696 L"EnSoftRetry",
697 &SoftRetry,
698 sizeof(SoftRetry));
699
700 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
701 FdoExtension->CommonExtension.LowerPdoDevice,
702 TRUE,
703 L"CommonBuffer2GBLimit",
704 sizeof(L"CommonBuffer2GBLimit"),
705 &Limit2GB,
706 sizeof(Limit2GB));
707
708 FdoExtension->CommonBufferLimit = (Limit2GB != 0);
709
710 if (FdoExtension->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR &&
711 FdoExtension->SubClass == PCI_SUBCLASS_SB_USB &&
712 FdoExtension->ProgIf < PCI_INTERFACE_USB_ID_EHCI)
713 {
714 Status = USBPORT_IsCompanionController(FdoDevice, &IsCompanion);
715
716 if (!NT_SUCCESS(Status))
717 {
718 if (IsCompanion)
719 {
720 FdoExtension->Flags |= USBPORT_FLAG_COMPANION_HC;
721 }
722 else
723 {
724 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
725 }
726 }
727 }
728
729 if (DisableCcDetect)
730 {
731 FdoExtension->Flags &= ~USBPORT_FLAG_COMPANION_HC;
732 }
733
734 TotalBusBandwidth = Packet->MiniPortBusBandwidth;
735 FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
736
737 USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
738 FdoExtension->CommonExtension.LowerPdoDevice,
739 TRUE,
740 L"TotalBusBandwidth",
741 sizeof(L"TotalBusBandwidth"),
742 &TotalBusBandwidth,
743 sizeof(TotalBusBandwidth));
744
745 if (TotalBusBandwidth != FdoExtension->TotalBusBandwidth)
746 {
747 FdoExtension->TotalBusBandwidth = TotalBusBandwidth;
748 }
749
750 FdoExtension->ActiveIrpTable = ExAllocatePoolWithTag(NonPagedPool,
751 sizeof(USBPORT_IRP_TABLE),
752 USB_PORT_TAG);
753
754 if (!FdoExtension->ActiveIrpTable)
755 {
756 DPRINT1("USBPORT_StartDevice: Allocate ActiveIrpTable failed!\n");
757 goto ExitWithError;
758 }
759
760 RtlZeroMemory(FdoExtension->ActiveIrpTable, sizeof(USBPORT_IRP_TABLE));
761
762 FdoExtension->PendingIrpTable = ExAllocatePoolWithTag(NonPagedPool,
763 sizeof(USBPORT_IRP_TABLE),
764 USB_PORT_TAG);
765
766 if (!FdoExtension->PendingIrpTable)
767 {
768 DPRINT1("USBPORT_StartDevice: Allocate PendingIrpTable failed!\n");
769 goto ExitWithError;
770 }
771
772 RtlZeroMemory(FdoExtension->PendingIrpTable, sizeof(USBPORT_IRP_TABLE));
773
774 Status = IoConnectInterrupt(&FdoExtension->InterruptObject,
775 USBPORT_InterruptService,
776 (PVOID)FdoDevice,
777 0,
778 UsbPortResources->InterruptVector,
779 UsbPortResources->InterruptLevel,
780 UsbPortResources->InterruptLevel,
781 UsbPortResources->InterruptMode,
782 UsbPortResources->ShareVector,
783 UsbPortResources->InterruptAffinity,
784 0);
785
786
787 if (!NT_SUCCESS(Status))
788 {
789 DPRINT1("USBPORT_StartDevice: IoConnectInterrupt failed!\n");
790 goto ExitWithError;
791 }
792
793 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
794
795 if (Packet->MiniPortExtensionSize)
796 {
797 RtlZeroMemory(FdoExtension->MiniPortExt, Packet->MiniPortExtensionSize);
798 }
799
800 if (Packet->MiniPortResourcesSize)
801 {
802 HeaderBuffer = USBPORT_AllocateCommonBuffer(FdoDevice,
803 Packet->MiniPortResourcesSize);
804
805 if (!HeaderBuffer)
806 {
807 DPRINT1("USBPORT_StartDevice: Failed to AllocateCommonBuffer!\n");
808 Status = STATUS_INSUFFICIENT_RESOURCES;
809 goto ExitWithError;
810 }
811
812 UsbPortResources->StartVA = (PVOID)HeaderBuffer->VirtualAddress;
813 UsbPortResources->StartPA = (PVOID)HeaderBuffer->PhysicalAddress;
814
815 FdoExtension->MiniPortCommonBuffer = HeaderBuffer;
816 }
817 else
818 {
819 FdoExtension->MiniPortCommonBuffer = NULL;
820 }
821
822 MiniPortStatus = Packet->StartController(FdoExtension->MiniPortExt,
823 UsbPortResources);
824
825 if (UsbPortResources->LegacySupport)
826 {
827 FdoExtension->Flags |= USBPORT_FLAG_LEGACY_SUPPORT;
828 LegacyBIOS = 1;
829 }
830 else
831 {
832 LegacyBIOS = 0;
833 }
834
835 USBPORT_SetRegistryKeyValue(FdoExtension->CommonExtension.LowerPdoDevice,
836 FALSE,
837 REG_DWORD,
838 L"DetectedLegacyBIOS",
839 &LegacyBIOS,
840 sizeof(LegacyBIOS));
841
842 if (MiniPortStatus)
843 {
844 DPRINT1("USBPORT_StartDevice: Failed to Start MiniPort. MiniPortStatus - %x\n",
845 MiniPortStatus);
846
847 if (FdoExtension->Flags & USBPORT_FLAG_INT_CONNECTED)
848 {
849 IoDisconnectInterrupt(FdoExtension->InterruptObject);
850 FdoExtension->Flags &= ~USBPORT_FLAG_INT_CONNECTED;
851 }
852
853 if (FdoExtension->MiniPortCommonBuffer)
854 {
855 USBPORT_FreeCommonBuffer(FdoDevice, FdoExtension->MiniPortCommonBuffer);
856 FdoExtension->MiniPortCommonBuffer = NULL;
857 }
858
859 goto ExitWithError;
860 }
861 else
862 {
863 FdoExtension->MiniPortFlags |= USBPORT_MPFLAG_INTERRUPTS_ENABLED;
864 USBPORT_MiniportInterrupts(FdoDevice, TRUE);
865 }
866
867 FdoExtension->TimerValue = 500;
868 USBPORT_StartTimer((PVOID)FdoDevice, 500);
869
870 Status = USBPORT_RegisterDeviceInterface(FdoExtension->CommonExtension.LowerPdoDevice,
871 FdoDevice,
872 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
873 TRUE);
874
875 if (!NT_SUCCESS(Status))
876 {
877 DPRINT1("USBPORT_StartDevice: RegisterDeviceInterface failed!\n");
878 goto ExitWithError;
879 }
880
881 USBPORT_CreateLegacySymbolicLink(FdoDevice);
882
883 FdoExtension->Flags |= USBPORT_FLAG_HC_STARTED;
884
885 DPRINT("USBPORT_StartDevice: Exit Status - %p\n", Status);
886 return Status;
887
888 ExitWithError:
889 USBPORT_StopDevice(FdoDevice);
890
891 DPRINT1("USBPORT_StartDevice: ExitWithError Status - %lx\n", Status);
892 return Status;
893 }
894
895 NTSTATUS
896 NTAPI
897 USBPORT_ParseResources(IN PDEVICE_OBJECT FdoDevice,
898 IN PIRP Irp,
899 IN PUSBPORT_RESOURCES UsbPortResources)
900 {
901 PCM_RESOURCE_LIST AllocatedResourcesTranslated;
902 PCM_PARTIAL_RESOURCE_LIST ResourceList;
903 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
904 PCM_PARTIAL_RESOURCE_DESCRIPTOR PortDescriptor = NULL;
905 PCM_PARTIAL_RESOURCE_DESCRIPTOR MemoryDescriptor = NULL;
906 PCM_PARTIAL_RESOURCE_DESCRIPTOR InterruptDescriptor = NULL;
907 PIO_STACK_LOCATION IoStack;
908 ULONG ix;
909 NTSTATUS Status = STATUS_SUCCESS;
910
911 DPRINT("USBPORT_ParseResources: ... \n");
912
913 IoStack = IoGetCurrentIrpStackLocation(Irp);
914 AllocatedResourcesTranslated = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
915
916 if (AllocatedResourcesTranslated)
917 {
918 RtlZeroMemory(UsbPortResources, sizeof(USBPORT_RESOURCES));
919
920 ResourceList = &AllocatedResourcesTranslated->List[0].PartialResourceList;
921
922 PartialDescriptor = &ResourceList->PartialDescriptors[0];
923
924 for (ix = 0; ix < ResourceList->Count; ++ix)
925 {
926 if (PartialDescriptor->Type == CmResourceTypePort)
927 {
928 if (!PortDescriptor)
929 PortDescriptor = PartialDescriptor;
930 }
931 else if (PartialDescriptor->Type == CmResourceTypeInterrupt)
932 {
933 if (!InterruptDescriptor)
934 InterruptDescriptor = PartialDescriptor;
935 }
936 else if (PartialDescriptor->Type == CmResourceTypeMemory)
937 {
938 if (!MemoryDescriptor)
939 MemoryDescriptor = PartialDescriptor;
940 }
941
942 PartialDescriptor += 1;
943 }
944
945 if (PortDescriptor)
946 {
947 if (PortDescriptor->Flags & CM_RESOURCE_PORT_IO)
948 {
949 UsbPortResources->ResourceBase = (PVOID)PortDescriptor->u.Port.Start.LowPart;
950 }
951 else
952 {
953 UsbPortResources->ResourceBase = MmMapIoSpace(PortDescriptor->u.Port.Start,
954 PortDescriptor->u.Port.Length,
955 0);
956 }
957
958 UsbPortResources->IoSpaceLength = PortDescriptor->u.Port.Length;
959
960 if (UsbPortResources->ResourceBase)
961 {
962 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_PORT;
963 }
964 else
965 {
966 Status = STATUS_NONE_MAPPED;
967 }
968 }
969
970 if (MemoryDescriptor && NT_SUCCESS(Status))
971 {
972 UsbPortResources->IoSpaceLength = MemoryDescriptor->u.Memory.Length;
973
974 UsbPortResources->ResourceBase = MmMapIoSpace(MemoryDescriptor->u.Memory.Start,
975 MemoryDescriptor->u.Memory.Length,
976 0);
977
978 if (UsbPortResources->ResourceBase)
979 {
980 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_MEMORY;
981 }
982 else
983 {
984 Status = STATUS_NONE_MAPPED;
985 }
986 }
987
988 if (InterruptDescriptor && NT_SUCCESS(Status))
989 {
990 UsbPortResources->ResourcesTypes |= USBPORT_RESOURCES_INTERRUPT;
991
992 UsbPortResources->InterruptVector = InterruptDescriptor->u.Interrupt.Vector;
993 UsbPortResources->InterruptLevel = InterruptDescriptor->u.Interrupt.Level;
994 UsbPortResources->InterruptAffinity = InterruptDescriptor->u.Interrupt.Affinity;
995
996 UsbPortResources->ShareVector = InterruptDescriptor->ShareDisposition ==
997 CmResourceShareShared;
998
999 UsbPortResources->InterruptMode = InterruptDescriptor->Flags ==
1000 CM_RESOURCE_INTERRUPT_LATCHED;
1001 }
1002 }
1003 else
1004 {
1005 Status = STATUS_NONE_MAPPED;
1006 }
1007
1008 return Status;
1009 }
1010
1011 NTSTATUS
1012 NTAPI
1013 USBPORT_CreatePdo(IN PDEVICE_OBJECT FdoDevice,
1014 OUT PDEVICE_OBJECT *RootHubPdo)
1015 {
1016 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1017 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1018 UNICODE_STRING DeviceName;
1019 ULONG DeviceNumber = 0;
1020 PDEVICE_OBJECT DeviceObject = NULL;
1021 WCHAR CharDeviceName[64];
1022 NTSTATUS Status = STATUS_SUCCESS;
1023
1024 DPRINT("USBPORT_CreatePdo: FdoDevice - %p, RootHubPdo - %p\n",
1025 FdoDevice,
1026 RootHubPdo);
1027
1028 FdoExtension = FdoDevice->DeviceExtension;
1029
1030 do
1031 {
1032 RtlStringCbPrintfW(CharDeviceName,
1033 sizeof(CharDeviceName),
1034 L"\\Device\\USBPDO-%d",
1035 DeviceNumber);
1036
1037 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1038
1039 DPRINT("USBPORT_CreatePdo: DeviceName - %wZ\n", &DeviceName);
1040
1041 Status = IoCreateDevice(FdoExtension->MiniPortInterface->DriverObject,
1042 sizeof(USBPORT_RHDEVICE_EXTENSION),
1043 &DeviceName,
1044 FILE_DEVICE_BUS_EXTENDER,
1045 0,
1046 FALSE,
1047 &DeviceObject);
1048
1049 ++DeviceNumber;
1050 }
1051 while (Status == STATUS_OBJECT_NAME_COLLISION);
1052
1053 if (!NT_SUCCESS(Status))
1054 {
1055 *RootHubPdo = NULL;
1056 DPRINT1("USBPORT_CreatePdo: Filed create HubPdo!\n");
1057 return Status;
1058 }
1059
1060 if (DeviceObject)
1061 {
1062 PdoExtension = DeviceObject->DeviceExtension;
1063
1064 RtlZeroMemory(PdoExtension, sizeof(USBPORT_RHDEVICE_EXTENSION));
1065
1066 PdoExtension->CommonExtension.SelfDevice = DeviceObject;
1067 PdoExtension->CommonExtension.IsPDO = TRUE;
1068
1069 PdoExtension->FdoDevice = FdoDevice;
1070 PdoExtension->PdoNameNumber = DeviceNumber;
1071
1072 USBPORT_AdjustDeviceCapabilities(FdoDevice, DeviceObject);
1073
1074 DeviceObject->StackSize = FdoDevice->StackSize;
1075
1076 DeviceObject->Flags |= DO_POWER_PAGABLE;
1077 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1078 }
1079 else
1080 {
1081 Status = STATUS_UNSUCCESSFUL;
1082 }
1083
1084 if (!NT_SUCCESS(Status))
1085 *RootHubPdo = NULL;
1086 else
1087 *RootHubPdo = DeviceObject;
1088
1089 DPRINT("USBPORT_CreatePdo: HubPdo - %p\n", DeviceObject);
1090 return Status;
1091 }
1092
1093 NTSTATUS
1094 NTAPI
1095 USBPORT_FdoPnP(IN PDEVICE_OBJECT FdoDevice,
1096 IN PIRP Irp)
1097 {
1098 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1099 PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
1100 PUSBPORT_REGISTRATION_PACKET Packet;
1101 PUSBPORT_RESOURCES UsbPortResources;
1102 PIO_STACK_LOCATION IoStack;
1103 UCHAR Minor;
1104 KEVENT Event;
1105 NTSTATUS Status;
1106 DEVICE_RELATION_TYPE RelationType;
1107 PDEVICE_RELATIONS DeviceRelations;
1108 PDEVICE_OBJECT RootHubPdo;
1109
1110 FdoExtension = FdoDevice->DeviceExtension;
1111 FdoCommonExtension = &FdoExtension->CommonExtension;
1112 UsbPortResources = &FdoExtension->UsbPortResources;
1113 Packet = &FdoExtension->MiniPortInterface->Packet;
1114
1115 IoStack = IoGetCurrentIrpStackLocation(Irp);
1116 Minor = IoStack->MinorFunction;
1117
1118 DPRINT("USBPORT_FdoPnP: FdoDevice - %p, Minor - %x\n", FdoDevice, Minor);
1119
1120 RelationType = IoStack->Parameters.QueryDeviceRelations.Type;
1121
1122 switch (Minor)
1123 {
1124 case IRP_MN_START_DEVICE:
1125 DPRINT("IRP_MN_START_DEVICE\n");
1126
1127 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1128
1129 IoCopyCurrentIrpStackLocationToNext(Irp);
1130
1131 IoSetCompletionRoutine(Irp,
1132 USBPORT_FdoStartCompletion,
1133 &Event,
1134 TRUE,
1135 TRUE,
1136 TRUE);
1137
1138 Status = IoCallDriver(FdoCommonExtension->LowerDevice,
1139 Irp);
1140
1141 if (Status == STATUS_PENDING)
1142 {
1143 KeWaitForSingleObject(&Event,
1144 Suspended,
1145 KernelMode,
1146 FALSE,
1147 NULL);
1148
1149 Status = Irp->IoStatus.Status;
1150 }
1151
1152 if (!NT_SUCCESS(Status))
1153 {
1154 goto Exit;
1155 }
1156
1157 Status = USBPORT_ParseResources(FdoDevice,
1158 Irp,
1159 UsbPortResources);
1160
1161 if (!NT_SUCCESS(Status))
1162 {
1163 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1164 goto Exit;
1165 }
1166
1167 Status = USBPORT_StartDevice(FdoDevice, UsbPortResources);
1168
1169 if (!NT_SUCCESS(Status))
1170 {
1171 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STOPPED;
1172 goto Exit;
1173 }
1174
1175 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_NOT_INIT;
1176 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_STARTED;
1177
1178 FdoCommonExtension->DevicePowerState = PowerDeviceD0;
1179
1180 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1181 {
1182 USBPORT_AddUSB2Fdo(FdoDevice);
1183 }
1184 else
1185 {
1186 USBPORT_AddUSB1Fdo(FdoDevice);
1187 }
1188
1189 Exit:
1190 Irp->IoStatus.Status = Status;
1191 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1192 return Status;
1193
1194 case IRP_MN_QUERY_REMOVE_DEVICE:
1195 DPRINT("IRP_MN_QUERY_REMOVE_DEVICE\n");
1196 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1197 {
1198 DPRINT1("USBPORT_FdoPnP: Haction registry write FIXME\n");
1199 }
1200
1201 Irp->IoStatus.Status = STATUS_SUCCESS;
1202 goto ForwardIrp;
1203
1204 case IRP_MN_REMOVE_DEVICE:
1205 DPRINT("USBPORT_FdoPnP: IRP_MN_REMOVE_DEVICE\n");
1206 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_FAILED;
1207
1208 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED &&
1209 !(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_NOT_INIT))
1210 {
1211 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1212 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1213 }
1214
1215 Irp->IoStatus.Status = STATUS_SUCCESS;
1216 IoSkipCurrentIrpStackLocation(Irp);
1217 Status = IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1218
1219 IoDetachDevice(FdoCommonExtension->LowerDevice);
1220
1221 RootHubPdo = FdoExtension->RootHubPdo;
1222
1223 IoDeleteDevice(FdoDevice);
1224
1225 if (RootHubPdo)
1226 {
1227 IoDeleteDevice(RootHubPdo);
1228 }
1229
1230 return Status;
1231
1232 case IRP_MN_CANCEL_REMOVE_DEVICE:
1233 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1234 Irp->IoStatus.Status = STATUS_SUCCESS;
1235 goto ForwardIrp;
1236
1237 case IRP_MN_STOP_DEVICE:
1238 DPRINT("IRP_MN_STOP_DEVICE\n");
1239 if (FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_STARTED)
1240 {
1241 DPRINT1("USBPORT_FdoPnP: stop fdo FIXME\n");
1242
1243 FdoCommonExtension->PnpStateFlags &= ~USBPORT_PNP_STATE_STARTED;
1244 FdoCommonExtension->PnpStateFlags |= USBPORT_PNP_STATE_NOT_INIT;
1245 }
1246
1247 Irp->IoStatus.Status = STATUS_SUCCESS;
1248 goto ForwardIrp;
1249
1250 case IRP_MN_QUERY_STOP_DEVICE:
1251 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1252 Irp->IoStatus.Status = STATUS_SUCCESS;
1253 goto ForwardIrp;
1254
1255 case IRP_MN_CANCEL_STOP_DEVICE:
1256 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1257 Irp->IoStatus.Status = STATUS_SUCCESS;
1258 goto ForwardIrp;
1259
1260 case IRP_MN_QUERY_DEVICE_RELATIONS:
1261 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1262 if (RelationType == BusRelations)
1263 {
1264 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1265 sizeof(DEVICE_RELATIONS),
1266 USB_PORT_TAG);
1267
1268 if (!DeviceRelations)
1269 {
1270 Status = STATUS_INSUFFICIENT_RESOURCES;
1271 Irp->IoStatus.Status = Status;
1272 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1273 return Status;
1274 }
1275
1276 DeviceRelations->Count = 0;
1277 DeviceRelations->Objects[0] = NULL;
1278
1279 if (!FdoExtension->RootHubPdo)
1280 {
1281 Status = USBPORT_CreatePdo(FdoDevice,
1282 &FdoExtension->RootHubPdo);
1283
1284 if (!NT_SUCCESS(Status))
1285 {
1286 ExFreePoolWithTag(DeviceRelations, USB_PORT_TAG);
1287 goto ForwardIrp;
1288 }
1289 }
1290 else
1291 {
1292 Status = STATUS_SUCCESS;
1293 }
1294
1295 DeviceRelations->Count = 1;
1296 DeviceRelations->Objects[0] = FdoExtension->RootHubPdo;
1297
1298 ObReferenceObject(FdoExtension->RootHubPdo);
1299 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1300 }
1301 else
1302 {
1303 if (RelationType == RemovalRelations)
1304 {
1305 DPRINT1("USBPORT_FdoPnP: FIXME IRP_MN_QUERY_DEVICE_RELATIONS/RemovalRelations\n");
1306 }
1307
1308 goto ForwardIrp;
1309 }
1310
1311 Irp->IoStatus.Status = Status;
1312 goto ForwardIrp;
1313
1314 case IRP_MN_QUERY_INTERFACE:
1315 DPRINT("IRP_MN_QUERY_INTERFACE\n");
1316 goto ForwardIrp;
1317
1318 case IRP_MN_QUERY_CAPABILITIES:
1319 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1320 goto ForwardIrp;
1321
1322 case IRP_MN_QUERY_RESOURCES:
1323 DPRINT("IRP_MN_QUERY_RESOURCES\n");
1324 goto ForwardIrp;
1325
1326 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1327 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1328 goto ForwardIrp;
1329
1330 case IRP_MN_QUERY_DEVICE_TEXT:
1331 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1332 goto ForwardIrp;
1333
1334 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1335 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1336 goto ForwardIrp;
1337
1338 case IRP_MN_READ_CONFIG:
1339 DPRINT("IRP_MN_READ_CONFIG\n");
1340 goto ForwardIrp;
1341
1342 case IRP_MN_WRITE_CONFIG:
1343 DPRINT("IRP_MN_WRITE_CONFIG\n");
1344 goto ForwardIrp;
1345
1346 case IRP_MN_EJECT:
1347 DPRINT("IRP_MN_EJECT\n");
1348 goto ForwardIrp;
1349
1350 case IRP_MN_SET_LOCK:
1351 DPRINT("IRP_MN_SET_LOCK\n");
1352 goto ForwardIrp;
1353
1354 case IRP_MN_QUERY_ID:
1355 DPRINT("IRP_MN_QUERY_ID\n");
1356 goto ForwardIrp;
1357
1358 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1359 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1360 goto ForwardIrp;
1361
1362 case IRP_MN_QUERY_BUS_INFORMATION:
1363 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1364 goto ForwardIrp;
1365
1366 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1367 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1368 goto ForwardIrp;
1369
1370 case IRP_MN_SURPRISE_REMOVAL:
1371 DPRINT1("IRP_MN_SURPRISE_REMOVAL\n");
1372 if (!(FdoCommonExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED))
1373 {
1374 USBPORT_InvalidateControllerHandler(FdoDevice,
1375 USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE);
1376 }
1377 goto ForwardIrp;
1378
1379 default:
1380 DPRINT("unknown IRP_MN_???\n");
1381 ForwardIrp:
1382 /* forward irp to next device object */
1383 IoSkipCurrentIrpStackLocation(Irp);
1384 break;
1385 }
1386
1387 return IoCallDriver(FdoCommonExtension->LowerDevice, Irp);
1388 }
1389
1390 PVOID
1391 NTAPI
1392 USBPORT_GetDeviceHwIds(IN PDEVICE_OBJECT FdoDevice,
1393 IN USHORT VendorID,
1394 IN USHORT DeviceID,
1395 IN USHORT RevisionID)
1396 {
1397 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1398 PUSBPORT_REGISTRATION_PACKET Packet;
1399 PVOID Id;
1400 WCHAR Buffer[300] = {0};
1401 ULONG Length = 0;
1402 size_t Remaining = sizeof(Buffer);
1403 PWCHAR EndBuffer;
1404
1405 FdoExtension = FdoDevice->DeviceExtension;
1406 Packet = &FdoExtension->MiniPortInterface->Packet;
1407
1408 DPRINT("USBPORT_GetDeviceHwIds: FdoDevice - %p, Packet->MiniPortFlags - %p\n",
1409 FdoDevice,
1410 Packet->MiniPortFlags);
1411
1412 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1413 {
1414 RtlStringCbPrintfExW(Buffer,
1415 Remaining,
1416 &EndBuffer,
1417 &Remaining,
1418 0,
1419 L"USB\\ROOT_HUB20&VID%04x&PID%04x&REV%04x",
1420 VendorID,
1421 DeviceID,
1422 RevisionID);
1423
1424 EndBuffer++;
1425 Remaining -= sizeof(UNICODE_NULL);
1426
1427 RtlStringCbPrintfExW(EndBuffer,
1428 Remaining,
1429 &EndBuffer,
1430 &Remaining,
1431 0,
1432 L"USB\\ROOT_HUB20&VID%04x&PID%04x",
1433 VendorID,
1434 DeviceID);
1435
1436 EndBuffer++;
1437 Remaining -= sizeof(UNICODE_NULL);
1438
1439 RtlStringCbPrintfExW(EndBuffer,
1440 Remaining,
1441 NULL,
1442 &Remaining,
1443 0,
1444 L"USB\\ROOT_HUB20");
1445 }
1446 else
1447 {
1448 RtlStringCbPrintfExW(Buffer,
1449 Remaining,
1450 &EndBuffer,
1451 &Remaining,
1452 0,
1453 L"USB\\ROOT_HUB&VID%04x&PID%04x&REV%04x",
1454 VendorID,
1455 DeviceID,
1456 RevisionID);
1457
1458 EndBuffer++;
1459 Remaining -= sizeof(UNICODE_NULL);
1460
1461 RtlStringCbPrintfExW(EndBuffer,
1462 Remaining,
1463 &EndBuffer,
1464 &Remaining,
1465 0,
1466 L"USB\\ROOT_HUB&VID%04x&PID%04x",
1467 VendorID,
1468 DeviceID);
1469
1470 EndBuffer++;
1471 Remaining -= sizeof(UNICODE_NULL);
1472
1473 RtlStringCbPrintfExW(EndBuffer,
1474 Remaining,
1475 NULL,
1476 &Remaining,
1477 0,
1478 L"USB\\ROOT_HUB");
1479 }
1480
1481 Length = (sizeof(Buffer) - Remaining + sizeof(UNICODE_NULL));
1482
1483 /* for debug only */
1484 if (FALSE)
1485 {
1486 DPRINT("Hardware IDs:\n");
1487 USBPORT_DumpingIDs(Buffer);
1488 }
1489
1490 Id = ExAllocatePoolWithTag(PagedPool, Length, USB_PORT_TAG);
1491
1492 if (!Id)
1493 return NULL;
1494
1495 RtlMoveMemory(Id, Buffer, Length);
1496
1497 return Id;
1498 }
1499
1500 NTSTATUS
1501 NTAPI
1502 USBPORT_PdoPnP(IN PDEVICE_OBJECT PdoDevice,
1503 IN PIRP Irp)
1504 {
1505 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1506 PUSBPORT_COMMON_DEVICE_EXTENSION PdoCommonExtension;
1507 PDEVICE_OBJECT FdoDevice;
1508 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1509 PIO_STACK_LOCATION IoStack;
1510 UCHAR Minor;
1511 NTSTATUS Status;
1512 PPNP_BUS_INFORMATION BusInformation;
1513 PDEVICE_CAPABILITIES DeviceCapabilities;
1514
1515 PdoExtension = PdoDevice->DeviceExtension;
1516 PdoCommonExtension = &PdoExtension->CommonExtension;
1517
1518 FdoDevice = PdoExtension->FdoDevice;
1519 FdoExtension = FdoDevice->DeviceExtension;
1520
1521 IoStack = IoGetCurrentIrpStackLocation(Irp);
1522 Minor = IoStack->MinorFunction;
1523
1524 Status = Irp->IoStatus.Status;
1525
1526 DPRINT("USBPORT_PdoPnP: PdoDevice - %p, Minor - %x\n", PdoDevice, Minor);
1527
1528 switch (Minor)
1529 {
1530 case IRP_MN_START_DEVICE:
1531 DPRINT("IRP_MN_START_DEVICE\n");
1532
1533 Status = USBPORT_RootHubCreateDevice(FdoDevice, PdoDevice);
1534
1535 if (NT_SUCCESS(Status))
1536 {
1537 Status = USBPORT_RegisterDeviceInterface(PdoDevice,
1538 PdoDevice,
1539 &GUID_DEVINTERFACE_USB_HUB,
1540 TRUE);
1541
1542 if (NT_SUCCESS(Status))
1543 {
1544 PdoCommonExtension->DevicePowerState = PowerDeviceD0;
1545 PdoCommonExtension->PnpStateFlags = USBPORT_PNP_STATE_STARTED;
1546 }
1547 }
1548
1549 break;
1550
1551 case IRP_MN_QUERY_REMOVE_DEVICE:
1552 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_REMOVE_DEVICE\n");
1553 Status = STATUS_SUCCESS;
1554 break;
1555
1556 case IRP_MN_REMOVE_DEVICE:
1557 DPRINT1("USBPORT_PdoPnP: IRP_MN_REMOVE_DEVICE UNIMPLEMENTED. FIXME. \n");
1558 //USBPORT_StopRootHub();
1559 Status = STATUS_SUCCESS;
1560 break;
1561
1562 case IRP_MN_CANCEL_REMOVE_DEVICE:
1563 DPRINT("IRP_MN_CANCEL_REMOVE_DEVICE\n");
1564 Status = STATUS_SUCCESS;
1565 break;
1566
1567 case IRP_MN_STOP_DEVICE:
1568 DPRINT1("USBPORT_PdoPnP: IRP_MN_STOP_DEVICE UNIMPLEMENTED. FIXME. \n");
1569 //USBPORT_StopRootHub();
1570 Status = STATUS_SUCCESS;
1571 break;
1572
1573 case IRP_MN_QUERY_STOP_DEVICE:
1574 DPRINT("IRP_MN_QUERY_STOP_DEVICE\n");
1575 Status = STATUS_SUCCESS;
1576 break;
1577
1578 case IRP_MN_CANCEL_STOP_DEVICE:
1579 DPRINT("IRP_MN_CANCEL_STOP_DEVICE\n");
1580 Status = STATUS_SUCCESS;
1581 break;
1582
1583 case IRP_MN_QUERY_DEVICE_RELATIONS:
1584 {
1585 PDEVICE_RELATIONS DeviceRelations;
1586
1587 DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS\n");
1588 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
1589 {
1590 break;
1591 }
1592
1593 DeviceRelations = ExAllocatePoolWithTag(PagedPool,
1594 sizeof(DEVICE_RELATIONS),
1595 USB_PORT_TAG);
1596
1597 if (!DeviceRelations)
1598 {
1599 Status = STATUS_INSUFFICIENT_RESOURCES;
1600 Irp->IoStatus.Information = 0;
1601 break;
1602 }
1603
1604 DeviceRelations->Count = 1;
1605 DeviceRelations->Objects[0] = PdoDevice;
1606
1607 ObReferenceObject(PdoDevice);
1608
1609 Status = STATUS_SUCCESS;
1610 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
1611 break;
1612 }
1613
1614 case IRP_MN_QUERY_INTERFACE:
1615 DPRINT("IRP_MN_QUERY_INTERFACE\n");
1616 Status = USBPORT_PdoQueryInterface(FdoDevice, PdoDevice, Irp);
1617 break;
1618
1619 case IRP_MN_QUERY_CAPABILITIES:
1620 DPRINT("IRP_MN_QUERY_CAPABILITIES\n");
1621
1622 DeviceCapabilities = IoStack->Parameters.DeviceCapabilities.Capabilities;
1623
1624 RtlCopyMemory(DeviceCapabilities,
1625 &PdoExtension->Capabilities,
1626 sizeof(DEVICE_CAPABILITIES));
1627
1628 Status = STATUS_SUCCESS;
1629 break;
1630
1631 case IRP_MN_QUERY_RESOURCES:
1632 DPRINT("USBPORT_PdoPnP: IRP_MN_QUERY_RESOURCES\n");
1633 break;
1634
1635 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1636 DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
1637 break;
1638
1639 case IRP_MN_QUERY_DEVICE_TEXT:
1640 DPRINT("IRP_MN_QUERY_DEVICE_TEXT\n");
1641 break;
1642
1643 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
1644 DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
1645 break;
1646
1647 case IRP_MN_READ_CONFIG:
1648 DPRINT("IRP_MN_READ_CONFIG\n");
1649 ASSERT(FALSE);
1650 break;
1651
1652 case IRP_MN_WRITE_CONFIG:
1653 DPRINT("IRP_MN_WRITE_CONFIG\n");
1654 ASSERT(FALSE);
1655 break;
1656
1657 case IRP_MN_EJECT:
1658 DPRINT("IRP_MN_EJECT\n");
1659 ASSERT(FALSE);
1660 break;
1661
1662 case IRP_MN_SET_LOCK:
1663 DPRINT("IRP_MN_SET_LOCK\n");
1664 ASSERT(FALSE);
1665 break;
1666
1667 case IRP_MN_QUERY_ID:
1668 {
1669 ULONG IdType;
1670 LONG Length;
1671 WCHAR Buffer[64] = {0};
1672 PVOID Id;
1673
1674 Status = STATUS_SUCCESS;
1675 IdType = IoStack->Parameters.QueryId.IdType;
1676
1677 DPRINT("IRP_MN_QUERY_ID/Type %x\n", IdType);
1678
1679 if (IdType == BusQueryDeviceID)
1680 {
1681 PUSBPORT_REGISTRATION_PACKET Packet;
1682 Packet = &FdoExtension->MiniPortInterface->Packet;
1683
1684 if (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1685 {
1686 RtlStringCbPrintfW(Buffer,
1687 sizeof(Buffer),
1688 L"USB\\ROOT_HUB20");
1689 }
1690 else
1691 {
1692 RtlStringCbPrintfW(Buffer,
1693 sizeof(Buffer),
1694 L"USB\\ROOT_HUB");
1695 }
1696
1697 Length = (wcslen(Buffer) + 1);
1698
1699 Id = ExAllocatePoolWithTag(PagedPool,
1700 Length * sizeof(WCHAR),
1701 USB_PORT_TAG);
1702
1703 if (Id)
1704 {
1705 RtlZeroMemory(Id, Length * sizeof(WCHAR));
1706 RtlStringCbCopyW(Id, Length * sizeof(WCHAR), Buffer);
1707
1708 DPRINT("BusQueryDeviceID - %S, TotalLength - %hu\n",
1709 Id,
1710 Length);
1711 }
1712
1713 Irp->IoStatus.Information = (ULONG_PTR)Id;
1714 break;
1715 }
1716
1717 if (IdType == BusQueryHardwareIDs)
1718 {
1719 Id = USBPORT_GetDeviceHwIds(FdoDevice,
1720 FdoExtension->VendorID,
1721 FdoExtension->DeviceID,
1722 FdoExtension->RevisionID);
1723
1724 Irp->IoStatus.Information = (ULONG_PTR)Id;
1725 break;
1726 }
1727
1728 if (IdType == BusQueryCompatibleIDs ||
1729 IdType == BusQueryInstanceID)
1730 {
1731 Irp->IoStatus.Information = 0;
1732 break;
1733 }
1734
1735 /* IdType == BusQueryDeviceSerialNumber */
1736 Status = Irp->IoStatus.Status;
1737 break;
1738 }
1739
1740 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1741 DPRINT("IRP_MN_QUERY_PNP_DEVICE_STATE\n");
1742 Status = STATUS_SUCCESS;
1743 break;
1744
1745 case IRP_MN_QUERY_BUS_INFORMATION:
1746 DPRINT("IRP_MN_QUERY_BUS_INFORMATION\n");
1747
1748 /* Allocate buffer for bus information */
1749 BusInformation = ExAllocatePoolWithTag(PagedPool,
1750 sizeof(PNP_BUS_INFORMATION),
1751 USB_PORT_TAG);
1752
1753 if (!BusInformation)
1754 {
1755 /* No memory */
1756 Status = STATUS_INSUFFICIENT_RESOURCES;
1757 break;
1758 }
1759
1760 RtlZeroMemory(BusInformation, sizeof(PNP_BUS_INFORMATION));
1761
1762 /* Copy BUS GUID */
1763 RtlMoveMemory(&BusInformation->BusTypeGuid,
1764 &GUID_BUS_TYPE_USB,
1765 sizeof(GUID));
1766
1767 /* Set bus type */
1768 BusInformation->LegacyBusType = PNPBus;
1769 BusInformation->BusNumber = 0;
1770
1771 Status = STATUS_SUCCESS;
1772 Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
1773 break;
1774
1775 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1776 DPRINT("IRP_MN_DEVICE_USAGE_NOTIFICATION\n");
1777 break;
1778
1779 case IRP_MN_SURPRISE_REMOVAL:
1780 DPRINT("USBPORT_PdoPnP: IRP_MN_SURPRISE_REMOVAL\n");
1781 Status = STATUS_SUCCESS;
1782 break;
1783
1784 default:
1785 DPRINT("unknown IRP_MN_???\n");
1786 break;
1787 }
1788
1789 Irp->IoStatus.Status = Status;
1790 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1791 return Status;
1792 }