Revert "[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)" (#6800)
[reactos.git] / drivers / usb / usbport / usbport.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort main driver functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbport.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 #define NDEBUG_USBPORT_CORE
14 #define NDEBUG_USBPORT_INTERRUPT
15 #define NDEBUG_USBPORT_TIMER
16 #include "usbdebug.h"
17
18 LIST_ENTRY USBPORT_MiniPortDrivers = {NULL, NULL};
19 LIST_ENTRY USBPORT_USB1FdoList = {NULL, NULL};
20 LIST_ENTRY USBPORT_USB2FdoList = {NULL, NULL};
21
22 KSPIN_LOCK USBPORT_SpinLock;
23 BOOLEAN USBPORT_Initialized = FALSE;
24
25 PDEVICE_OBJECT
26 NTAPI
27 USBPORT_FindUSB2Controller(IN PDEVICE_OBJECT FdoDevice)
28 {
29 PUSBPORT_DEVICE_EXTENSION FdoExtension;
30 PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
31 KIRQL OldIrql;
32 PLIST_ENTRY USB2FdoEntry;
33 PDEVICE_OBJECT USB2FdoDevice = NULL;
34
35 DPRINT("USBPORT_FindUSB2Controller: FdoDevice - %p\n", FdoDevice);
36
37 FdoExtension = FdoDevice->DeviceExtension;
38
39 KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
40
41 USB2FdoEntry = USBPORT_USB2FdoList.Flink;
42
43 while (USB2FdoEntry && USB2FdoEntry != &USBPORT_USB2FdoList)
44 {
45 USB2FdoExtension = CONTAINING_RECORD(USB2FdoEntry,
46 USBPORT_DEVICE_EXTENSION,
47 ControllerLink);
48
49 if (USB2FdoExtension->BusNumber == FdoExtension->BusNumber &&
50 USB2FdoExtension->PciDeviceNumber == FdoExtension->PciDeviceNumber)
51 {
52 USB2FdoDevice = USB2FdoExtension->CommonExtension.SelfDevice;
53 break;
54 }
55
56 USB2FdoEntry = USB2FdoEntry->Flink;
57 }
58
59 KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
60
61 return USB2FdoDevice;
62 }
63
64 VOID
65 NTAPI
66 USBPORT_AddUSB1Fdo(IN PDEVICE_OBJECT FdoDevice)
67 {
68 PUSBPORT_DEVICE_EXTENSION FdoExtension;
69
70 DPRINT("USBPORT_AddUSB1Fdo: FdoDevice - %p\n", FdoDevice);
71
72 FdoExtension = FdoDevice->DeviceExtension;
73 FdoExtension->Flags |= USBPORT_FLAG_REGISTERED_FDO;
74
75 ExInterlockedInsertTailList(&USBPORT_USB1FdoList,
76 &FdoExtension->ControllerLink,
77 &USBPORT_SpinLock);
78 }
79
80 VOID
81 NTAPI
82 USBPORT_AddUSB2Fdo(IN PDEVICE_OBJECT FdoDevice)
83 {
84 PUSBPORT_DEVICE_EXTENSION FdoExtension;
85
86 DPRINT("USBPORT_AddUSB2Fdo: FdoDevice - %p\n", FdoDevice);
87
88 FdoExtension = FdoDevice->DeviceExtension;
89 FdoExtension->Flags |= USBPORT_FLAG_REGISTERED_FDO;
90
91 ExInterlockedInsertTailList(&USBPORT_USB2FdoList,
92 &FdoExtension->ControllerLink,
93 &USBPORT_SpinLock);
94 }
95
96 VOID
97 NTAPI
98 USBPORT_RemoveUSBxFdo(IN PDEVICE_OBJECT FdoDevice)
99 {
100 PUSBPORT_DEVICE_EXTENSION FdoExtension;
101 KIRQL OldIrql;
102
103 DPRINT("USBPORT_RemoveUSBxFdo: FdoDevice - %p\n", FdoDevice);
104
105 FdoExtension = FdoDevice->DeviceExtension;
106
107 KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
108 RemoveEntryList(&FdoExtension->ControllerLink);
109 KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
110
111 FdoExtension->Flags &= ~USBPORT_FLAG_REGISTERED_FDO;
112
113 FdoExtension->ControllerLink.Flink = NULL;
114 FdoExtension->ControllerLink.Blink = NULL;
115 }
116
117 BOOLEAN
118 NTAPI
119 USBPORT_IsCompanionFdoExtension(IN PDEVICE_OBJECT USB2FdoDevice,
120 IN PUSBPORT_DEVICE_EXTENSION USB1FdoExtension)
121 {
122 PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
123
124 DPRINT("USBPORT_IsCompanionFdoExtension: USB2Fdo - %p, USB1FdoExtension - %p\n",
125 USB2FdoDevice,
126 USB1FdoExtension);
127
128 USB2FdoExtension = USB2FdoDevice->DeviceExtension;
129
130 return USB2FdoExtension->BusNumber == USB1FdoExtension->BusNumber &&
131 USB2FdoExtension->PciDeviceNumber == USB1FdoExtension->PciDeviceNumber;
132 }
133
134 PDEVICE_RELATIONS
135 NTAPI
136 USBPORT_FindCompanionControllers(IN PDEVICE_OBJECT USB2FdoDevice,
137 IN BOOLEAN IsObRefer,
138 IN BOOLEAN IsFDOsReturned)
139 {
140 PLIST_ENTRY USB1FdoList;
141 PUSBPORT_DEVICE_EXTENSION USB1FdoExtension;
142 ULONG NumControllers = 0;
143 PDEVICE_OBJECT * Entry;
144 PDEVICE_RELATIONS ControllersList = NULL;
145 KIRQL OldIrql;
146
147 DPRINT("USBPORT_FindCompanionControllers: USB2Fdo - %p, IsObRefer - %x, IsFDOs - %x\n",
148 USB2FdoDevice,
149 IsObRefer,
150 IsFDOsReturned);
151
152 KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
153
154 USB1FdoList = USBPORT_USB1FdoList.Flink;
155
156 while (USB1FdoList && USB1FdoList != &USBPORT_USB1FdoList)
157 {
158 USB1FdoExtension = CONTAINING_RECORD(USB1FdoList,
159 USBPORT_DEVICE_EXTENSION,
160 ControllerLink);
161
162 if (USB1FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC &&
163 USBPORT_IsCompanionFdoExtension(USB2FdoDevice, USB1FdoExtension))
164 {
165 ++NumControllers;
166 }
167
168 USB1FdoList = USB1FdoExtension->ControllerLink.Flink;
169 }
170
171 DPRINT("USBPORT_FindCompanionControllers: NumControllers - %x\n",
172 NumControllers);
173
174 if (!NumControllers)
175 {
176 goto Exit;
177 }
178
179 ControllersList = ExAllocatePoolWithTag(NonPagedPool,
180 NumControllers * sizeof(DEVICE_RELATIONS),
181 USB_PORT_TAG);
182
183 if (!ControllersList)
184 {
185 goto Exit;
186 }
187
188 RtlZeroMemory(ControllersList, NumControllers * sizeof(DEVICE_RELATIONS));
189
190 ControllersList->Count = NumControllers;
191
192 USB1FdoList = USBPORT_USB1FdoList.Flink;
193
194 Entry = &ControllersList->Objects[0];
195
196 while (USB1FdoList && USB1FdoList != &USBPORT_USB1FdoList)
197 {
198 USB1FdoExtension = CONTAINING_RECORD(USB1FdoList,
199 USBPORT_DEVICE_EXTENSION,
200 ControllerLink);
201
202 if (USB1FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC &&
203 USBPORT_IsCompanionFdoExtension(USB2FdoDevice, USB1FdoExtension))
204 {
205 *Entry = USB1FdoExtension->CommonExtension.LowerPdoDevice;
206
207 if (IsObRefer)
208 {
209 ObReferenceObject(USB1FdoExtension->CommonExtension.LowerPdoDevice);
210 }
211
212 if (IsFDOsReturned)
213 {
214 *Entry = USB1FdoExtension->CommonExtension.SelfDevice;
215 }
216
217 ++Entry;
218 }
219
220 USB1FdoList = USB1FdoExtension->ControllerLink.Flink;
221 }
222
223 Exit:
224
225 KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
226
227 return ControllersList;
228 }
229
230 MPSTATUS
231 NTAPI
232 USBPORT_NtStatusToMpStatus(NTSTATUS NtStatus)
233 {
234 DPRINT("USBPORT_NtStatusToMpStatus: NtStatus - %x\n", NtStatus);
235
236 if (NtStatus == STATUS_SUCCESS)
237 {
238 return MP_STATUS_SUCCESS;
239 }
240 else
241 {
242 return MP_STATUS_UNSUCCESSFUL;
243 }
244 }
245
246 NTSTATUS
247 NTAPI
248 USBPORT_SetRegistryKeyValue(IN PDEVICE_OBJECT DeviceObject,
249 IN BOOL UseDriverKey,
250 IN ULONG Type,
251 IN PCWSTR ValueNameString,
252 IN PVOID Data,
253 IN ULONG DataSize)
254 {
255 UNICODE_STRING ValueName;
256 HANDLE KeyHandle;
257 NTSTATUS Status;
258
259 DPRINT("USBPORT_SetRegistryKeyValue: ValueNameString - %S \n",
260 ValueNameString);
261
262 if (UseDriverKey)
263 {
264 Status = IoOpenDeviceRegistryKey(DeviceObject,
265 PLUGPLAY_REGKEY_DRIVER,
266 STANDARD_RIGHTS_ALL,
267 &KeyHandle);
268 }
269 else
270 {
271 Status = IoOpenDeviceRegistryKey(DeviceObject,
272 PLUGPLAY_REGKEY_DEVICE,
273 STANDARD_RIGHTS_ALL,
274 &KeyHandle);
275 }
276
277 if (NT_SUCCESS(Status))
278 {
279 RtlInitUnicodeString(&ValueName, ValueNameString);
280
281 Status = ZwSetValueKey(KeyHandle,
282 &ValueName,
283 0,
284 Type,
285 Data,
286 DataSize);
287
288 ZwClose(KeyHandle);
289 }
290
291 return Status;
292 }
293
294 NTSTATUS
295 NTAPI
296 USBPORT_GetRegistryKeyValueFullInfo(IN PDEVICE_OBJECT FdoDevice,
297 IN PDEVICE_OBJECT PdoDevice,
298 IN BOOL UseDriverKey,
299 IN PCWSTR SourceString,
300 IN ULONG LengthStr,
301 IN PVOID Buffer,
302 IN ULONG BufferLength)
303 {
304 NTSTATUS Status;
305 PKEY_VALUE_FULL_INFORMATION KeyValue;
306 UNICODE_STRING ValueName;
307 HANDLE KeyHandle;
308 ULONG LengthKey;
309
310 DPRINT("USBPORT_GetRegistryKeyValue: UseDriverKey - %x, SourceString - %S, LengthStr - %x, Buffer - %p, BufferLength - %x\n",
311 UseDriverKey,
312 SourceString,
313 LengthStr,
314 Buffer,
315 BufferLength);
316
317 if (UseDriverKey)
318 {
319 Status = IoOpenDeviceRegistryKey(PdoDevice,
320 PLUGPLAY_REGKEY_DRIVER,
321 STANDARD_RIGHTS_ALL,
322 &KeyHandle);
323 }
324 else
325 {
326 Status = IoOpenDeviceRegistryKey(PdoDevice,
327 PLUGPLAY_REGKEY_DEVICE,
328 STANDARD_RIGHTS_ALL,
329 &KeyHandle);
330 }
331
332 if (NT_SUCCESS(Status))
333 {
334 RtlInitUnicodeString(&ValueName, SourceString);
335
336 LengthKey = sizeof(KEY_VALUE_FULL_INFORMATION) +
337 LengthStr +
338 BufferLength;
339
340 KeyValue = ExAllocatePoolWithTag(PagedPool,
341 LengthKey,
342 USB_PORT_TAG);
343
344 if (KeyValue)
345 {
346 RtlZeroMemory(KeyValue, LengthKey);
347
348 Status = ZwQueryValueKey(KeyHandle,
349 &ValueName,
350 KeyValueFullInformation,
351 KeyValue,
352 LengthKey,
353 &LengthKey);
354
355 if (NT_SUCCESS(Status))
356 {
357 RtlCopyMemory(Buffer,
358 (PUCHAR)KeyValue + KeyValue->DataOffset,
359 BufferLength);
360 }
361
362 ExFreePoolWithTag(KeyValue, USB_PORT_TAG);
363 }
364
365 ZwClose(KeyHandle);
366 }
367
368 return Status;
369 }
370
371 MPSTATUS
372 NTAPI
373 USBPORT_GetMiniportRegistryKeyValue(IN PVOID MiniPortExtension,
374 IN BOOL UseDriverKey,
375 IN PCWSTR SourceString,
376 IN SIZE_T LengthStr,
377 IN PVOID Buffer,
378 IN SIZE_T BufferLength)
379 {
380 PUSBPORT_DEVICE_EXTENSION FdoExtension;
381 PDEVICE_OBJECT FdoDevice;
382 NTSTATUS Status;
383
384 DPRINT("USBPORT_GetMiniportRegistryKeyValue: MiniPortExtension - %p, UseDriverKey - %x, SourceString - %S, LengthStr - %x, Buffer - %p, BufferLength - %x\n",
385 MiniPortExtension,
386 UseDriverKey,
387 SourceString,
388 LengthStr,
389 Buffer,
390 BufferLength);
391
392 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
393 sizeof(USBPORT_DEVICE_EXTENSION));
394
395 FdoDevice = FdoExtension->CommonExtension.SelfDevice;
396
397 Status = USBPORT_GetRegistryKeyValueFullInfo(FdoDevice,
398 FdoExtension->CommonExtension.LowerPdoDevice,
399 UseDriverKey,
400 SourceString,
401 LengthStr,
402 Buffer,
403 BufferLength);
404
405 return USBPORT_NtStatusToMpStatus(Status);
406 }
407
408 NTSTATUS
409 NTAPI
410 USBPORT_GetSetConfigSpaceData(IN PDEVICE_OBJECT FdoDevice,
411 IN BOOLEAN IsReadData,
412 IN PVOID Buffer,
413 IN ULONG Offset,
414 IN ULONG Length)
415 {
416 PUSBPORT_DEVICE_EXTENSION FdoExtension;
417 ULONG BytesReadWrite;
418
419 DPRINT("USBPORT_GetSetConfigSpaceData ... \n");
420
421 FdoExtension = FdoDevice->DeviceExtension;
422
423 BytesReadWrite = Length;
424
425 if (IsReadData)
426 {
427 RtlZeroMemory(Buffer, Length);
428
429 BytesReadWrite = (*FdoExtension->BusInterface.GetBusData)
430 (FdoExtension->BusInterface.Context,
431 PCI_WHICHSPACE_CONFIG,
432 Buffer,
433 Offset,
434 Length);
435 }
436 else
437 {
438 BytesReadWrite = (*FdoExtension->BusInterface.SetBusData)
439 (FdoExtension->BusInterface.Context,
440 PCI_WHICHSPACE_CONFIG,
441 Buffer,
442 Offset,
443 Length);
444 }
445
446 if (BytesReadWrite == Length)
447 {
448 return STATUS_SUCCESS;
449 }
450
451 return STATUS_UNSUCCESSFUL;
452 }
453
454 MPSTATUS
455 NTAPI
456 USBPORT_ReadWriteConfigSpace(IN PVOID MiniPortExtension,
457 IN BOOLEAN IsReadData,
458 IN PVOID Buffer,
459 IN ULONG Offset,
460 IN ULONG Length)
461 {
462 NTSTATUS Status;
463 PUSBPORT_DEVICE_EXTENSION FdoExtension;
464 PDEVICE_OBJECT FdoDevice;
465
466 DPRINT("USBPORT_ReadWriteConfigSpace: ... \n");
467
468 //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
469 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
470 sizeof(USBPORT_DEVICE_EXTENSION));
471
472 FdoDevice = FdoExtension->CommonExtension.SelfDevice;
473
474 Status = USBPORT_GetSetConfigSpaceData(FdoDevice,
475 IsReadData,
476 Buffer,
477 Offset,
478 Length);
479
480 return USBPORT_NtStatusToMpStatus(Status);
481 }
482
483 NTSTATUS
484 NTAPI
485 USBPORT_USBDStatusToNtStatus(IN PURB Urb,
486 IN USBD_STATUS USBDStatus)
487 {
488 NTSTATUS Status;
489
490 if (USBD_ERROR(USBDStatus))
491 {
492 DPRINT1("USBPORT_USBDStatusToNtStatus: Urb - %p, USBDStatus - %x\n",
493 Urb,
494 USBDStatus);
495 }
496
497 if (Urb)
498 Urb->UrbHeader.Status = USBDStatus;
499
500 switch (USBDStatus)
501 {
502 case USBD_STATUS_SUCCESS:
503 Status = STATUS_SUCCESS;
504 break;
505
506 case USBD_STATUS_INSUFFICIENT_RESOURCES:
507 Status = STATUS_INSUFFICIENT_RESOURCES;
508 break;
509
510 case USBD_STATUS_DEVICE_GONE:
511 Status = STATUS_DEVICE_NOT_CONNECTED;
512 break;
513
514 case USBD_STATUS_CANCELED:
515 Status = STATUS_CANCELLED;
516 break;
517
518 case USBD_STATUS_NOT_SUPPORTED:
519 Status = STATUS_NOT_SUPPORTED;
520 break;
521
522 case USBD_STATUS_INVALID_URB_FUNCTION:
523 case USBD_STATUS_INVALID_PARAMETER:
524 case USBD_STATUS_INVALID_PIPE_HANDLE:
525 case USBD_STATUS_BAD_START_FRAME:
526 Status = STATUS_INVALID_PARAMETER;
527 break;
528
529 default:
530 if (USBD_ERROR(USBDStatus))
531 Status = STATUS_UNSUCCESSFUL;
532 else
533 Status = STATUS_SUCCESS;
534
535 break;
536 }
537
538 return Status;
539 }
540
541 NTSTATUS
542 NTAPI
543 USBPORT_Wait(IN PVOID MiniPortExtension,
544 IN ULONG Milliseconds)
545 {
546 LARGE_INTEGER Interval = {{0, 0}};
547
548 DPRINT("USBPORT_Wait: Milliseconds - %x\n", Milliseconds);
549 Interval.QuadPart -= 10000 * Milliseconds + (KeQueryTimeIncrement() - 1);
550 return KeDelayExecutionThread(KernelMode, FALSE, &Interval);
551 }
552
553 VOID
554 NTAPI
555 USBPORT_MiniportInterrupts(IN PDEVICE_OBJECT FdoDevice,
556 IN BOOLEAN IsEnable)
557 {
558 PUSBPORT_DEVICE_EXTENSION FdoExtension;
559 PUSBPORT_REGISTRATION_PACKET Packet;
560 BOOLEAN IsLock;
561 KIRQL OldIrql;
562
563 DPRINT_INT("USBPORT_MiniportInterrupts: IsEnable - %p\n", IsEnable);
564
565 FdoExtension = FdoDevice->DeviceExtension;
566 Packet = &FdoExtension->MiniPortInterface->Packet;
567
568 IsLock = (Packet->MiniPortFlags & USB_MINIPORT_FLAGS_NOT_LOCK_INT) == 0;
569
570 if (IsLock)
571 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
572
573 if (IsEnable)
574 {
575 FdoExtension->Flags |= USBPORT_FLAG_INTERRUPT_ENABLED;
576 Packet->EnableInterrupts(FdoExtension->MiniPortExt);
577 }
578 else
579 {
580 Packet->DisableInterrupts(FdoExtension->MiniPortExt);
581 FdoExtension->Flags &= ~USBPORT_FLAG_INTERRUPT_ENABLED;
582 }
583
584 if (IsLock)
585 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
586 }
587
588 VOID
589 NTAPI
590 USBPORT_SoftInterruptDpc(IN PRKDPC Dpc,
591 IN PVOID DeferredContext,
592 IN PVOID SystemArgument1,
593 IN PVOID SystemArgument2)
594 {
595 PDEVICE_OBJECT FdoDevice;
596 PUSBPORT_DEVICE_EXTENSION FdoExtension;
597
598 DPRINT_INT("USBPORT_SoftInterruptDpc: ... \n");
599
600 FdoDevice = DeferredContext;
601 FdoExtension = FdoDevice->DeviceExtension;
602
603 if (!KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, (PVOID)1))
604 {
605 InterlockedDecrement(&FdoExtension->IsrDpcCounter);
606 }
607 }
608
609 VOID
610 NTAPI
611 USBPORT_SoftInterrupt(IN PDEVICE_OBJECT FdoDevice)
612 {
613 PUSBPORT_DEVICE_EXTENSION FdoExtension;
614 LARGE_INTEGER DueTime = {{0, 0}};
615
616 DPRINT_INT("USBPORT_SoftInterrupt: ... \n");
617
618 FdoExtension = FdoDevice->DeviceExtension;
619
620 KeInitializeTimer(&FdoExtension->TimerSoftInterrupt);
621
622 KeInitializeDpc(&FdoExtension->SoftInterruptDpc,
623 USBPORT_SoftInterruptDpc,
624 FdoDevice);
625
626 DueTime.QuadPart -= 10000 + (KeQueryTimeIncrement() - 1);
627
628 KeSetTimer(&FdoExtension->TimerSoftInterrupt,
629 DueTime,
630 &FdoExtension->SoftInterruptDpc);
631 }
632
633 VOID
634 NTAPI
635 USBPORT_InvalidateControllerHandler(IN PDEVICE_OBJECT FdoDevice,
636 IN ULONG Type)
637 {
638 PUSBPORT_DEVICE_EXTENSION FdoExtension;
639
640 DPRINT_CORE("USBPORT_InvalidateControllerHandler: Invalidate Type - %x\n",
641 Type);
642
643 FdoExtension = FdoDevice->DeviceExtension;
644
645 switch (Type)
646 {
647 case USBPORT_INVALIDATE_CONTROLLER_RESET:
648 DPRINT1("USBPORT_InvalidateControllerHandler: INVALIDATE_CONTROLLER_RESET UNIMPLEMENTED. FIXME. \n");
649 break;
650
651 case USBPORT_INVALIDATE_CONTROLLER_SURPRISE_REMOVE:
652 DPRINT1("USBPORT_InvalidateControllerHandler: INVALIDATE_CONTROLLER_SURPRISE_REMOVE UNIMPLEMENTED. FIXME. \n");
653 break;
654
655 case USBPORT_INVALIDATE_CONTROLLER_SOFT_INTERRUPT:
656 if (InterlockedIncrement(&FdoExtension->IsrDpcCounter))
657 {
658 InterlockedDecrement(&FdoExtension->IsrDpcCounter);
659 }
660 else
661 {
662 USBPORT_SoftInterrupt(FdoDevice);
663 }
664 break;
665 }
666 }
667
668 ULONG
669 NTAPI
670 USBPORT_InvalidateController(IN PVOID MiniPortExtension,
671 IN ULONG Type)
672 {
673 PUSBPORT_DEVICE_EXTENSION FdoExtension;
674 PDEVICE_OBJECT FdoDevice;
675
676 DPRINT("USBPORT_InvalidateController: Invalidate Type - %x\n", Type);
677
678 //FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension + sizeof(USBPORT_DEVICE_EXTENSION));
679 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
680 sizeof(USBPORT_DEVICE_EXTENSION));
681 FdoDevice = FdoExtension->CommonExtension.SelfDevice;
682
683 USBPORT_InvalidateControllerHandler(FdoDevice, Type);
684
685 return 0;
686 }
687
688 ULONG
689 NTAPI
690 USBPORT_NotifyDoubleBuffer(IN PVOID MiniPortExtension,
691 IN PVOID MiniPortTransfer,
692 IN PVOID Buffer,
693 IN SIZE_T Length)
694 {
695 DPRINT1("USBPORT_NotifyDoubleBuffer: UNIMPLEMENTED. FIXME. \n");
696 return 0;
697 }
698
699 VOID
700 NTAPI
701 USBPORT_WorkerRequestDpc(IN PRKDPC Dpc,
702 IN PVOID DeferredContext,
703 IN PVOID SystemArgument1,
704 IN PVOID SystemArgument2)
705 {
706 PDEVICE_OBJECT FdoDevice;
707 PUSBPORT_DEVICE_EXTENSION FdoExtension;
708
709 DPRINT("USBPORT_WorkerRequestDpc: ... \n");
710
711 FdoDevice = DeferredContext;
712 FdoExtension = FdoDevice->DeviceExtension;
713
714 if (!InterlockedIncrement(&FdoExtension->IsrDpcHandlerCounter))
715 {
716 USBPORT_DpcHandler(FdoDevice);
717 }
718
719 InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
720 }
721
722 VOID
723 NTAPI
724 USBPORT_DoneTransfer(IN PUSBPORT_TRANSFER Transfer)
725 {
726 PUSBPORT_ENDPOINT Endpoint;
727 PDEVICE_OBJECT FdoDevice;
728 PUSBPORT_DEVICE_EXTENSION FdoExtension;
729 PURB Urb;
730 PIRP Irp;
731 KIRQL CancelIrql;
732 KIRQL OldIrql;
733
734 DPRINT_CORE("USBPORT_DoneTransfer: Transfer - %p\n", Transfer);
735
736 Endpoint = Transfer->Endpoint;
737 FdoDevice = Endpoint->FdoDevice;
738 FdoExtension = FdoDevice->DeviceExtension;
739
740 Urb = Transfer->Urb;
741 Irp = Transfer->Irp;
742
743 KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
744
745 if (Irp)
746 {
747 IoAcquireCancelSpinLock(&CancelIrql);
748 IoSetCancelRoutine(Irp, NULL);
749 IoReleaseCancelSpinLock(CancelIrql);
750
751 USBPORT_RemoveActiveTransferIrp(FdoDevice, Irp);
752 }
753
754 KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
755
756 USBPORT_USBDStatusToNtStatus(Transfer->Urb, Transfer->USBDStatus);
757 USBPORT_CompleteTransfer(Urb, Urb->UrbHeader.Status);
758
759 DPRINT_CORE("USBPORT_DoneTransfer: exit\n");
760 }
761
762 VOID
763 NTAPI
764 USBPORT_FlushDoneTransfers(IN PDEVICE_OBJECT FdoDevice)
765 {
766 PUSBPORT_DEVICE_EXTENSION FdoExtension;
767 PLIST_ENTRY DoneTransferList;
768 PUSBPORT_TRANSFER Transfer;
769 PUSBPORT_ENDPOINT Endpoint;
770 ULONG TransferCount;
771 KIRQL OldIrql;
772 BOOLEAN IsHasTransfers;
773
774 DPRINT_CORE("USBPORT_FlushDoneTransfers: ... \n");
775
776 FdoExtension = FdoDevice->DeviceExtension;
777 DoneTransferList = &FdoExtension->DoneTransferList;
778
779 while (TRUE)
780 {
781 KeAcquireSpinLock(&FdoExtension->DoneTransferSpinLock, &OldIrql);
782
783 if (IsListEmpty(DoneTransferList))
784 break;
785
786 Transfer = CONTAINING_RECORD(DoneTransferList->Flink,
787 USBPORT_TRANSFER,
788 TransferLink);
789
790 RemoveHeadList(DoneTransferList);
791 KeReleaseSpinLock(&FdoExtension->DoneTransferSpinLock, OldIrql);
792
793 if (Transfer)
794 {
795 Endpoint = Transfer->Endpoint;
796
797 if ((Transfer->Flags & TRANSFER_FLAG_SPLITED))
798 {
799 USBPORT_DoneSplitTransfer(Transfer);
800 }
801 else
802 {
803 USBPORT_DoneTransfer(Transfer);
804 }
805
806 IsHasTransfers = USBPORT_EndpointHasQueuedTransfers(FdoDevice,
807 Endpoint,
808 &TransferCount);
809
810 if (IsHasTransfers && !TransferCount)
811 {
812 USBPORT_InvalidateEndpointHandler(FdoDevice,
813 Endpoint,
814 INVALIDATE_ENDPOINT_WORKER_DPC);
815 }
816 }
817 }
818
819 KeReleaseSpinLock(&FdoExtension->DoneTransferSpinLock, OldIrql);
820 }
821
822
823 VOID
824 NTAPI
825 USBPORT_TransferFlushDpc(IN PRKDPC Dpc,
826 IN PVOID DeferredContext,
827 IN PVOID SystemArgument1,
828 IN PVOID SystemArgument2)
829 {
830 PDEVICE_OBJECT FdoDevice;
831
832 DPRINT_CORE("USBPORT_TransferFlushDpc: ... \n");
833 FdoDevice = DeferredContext;
834 USBPORT_FlushDoneTransfers(FdoDevice);
835 }
836
837 BOOLEAN
838 NTAPI
839 USBPORT_QueueDoneTransfer(IN PUSBPORT_TRANSFER Transfer,
840 IN USBD_STATUS USBDStatus)
841 {
842 PDEVICE_OBJECT FdoDevice;
843 PUSBPORT_DEVICE_EXTENSION FdoExtension;
844
845 DPRINT_CORE("USBPORT_QueueDoneTransfer: Transfer - %p, USBDStatus - %p\n",
846 Transfer,
847 USBDStatus);
848
849 FdoDevice = Transfer->Endpoint->FdoDevice;
850 FdoExtension = FdoDevice->DeviceExtension;
851
852 RemoveEntryList(&Transfer->TransferLink);
853 Transfer->USBDStatus = USBDStatus;
854
855 ExInterlockedInsertTailList(&FdoExtension->DoneTransferList,
856 &Transfer->TransferLink,
857 &FdoExtension->DoneTransferSpinLock);
858
859 return KeInsertQueueDpc(&FdoExtension->TransferFlushDpc, NULL, NULL);
860 }
861
862 VOID
863 NTAPI
864 USBPORT_DpcHandler(IN PDEVICE_OBJECT FdoDevice)
865 {
866 PUSBPORT_DEVICE_EXTENSION FdoExtension;
867 PUSBPORT_ENDPOINT Endpoint;
868 PLIST_ENTRY Entry;
869 LIST_ENTRY List;
870 LONG LockCounter;
871
872 DPRINT_CORE("USBPORT_DpcHandler: ... \n");
873
874 FdoExtension = FdoDevice->DeviceExtension;
875
876 InitializeListHead(&List);
877
878 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
879 Entry = FdoExtension->EndpointList.Flink;
880
881 while (Entry && Entry != &FdoExtension->EndpointList)
882 {
883 Endpoint = CONTAINING_RECORD(Entry,
884 USBPORT_ENDPOINT,
885 EndpointLink);
886
887 LockCounter = InterlockedIncrement(&Endpoint->LockCounter);
888
889 if (USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_ACTIVE ||
890 LockCounter ||
891 Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0)
892 {
893 InterlockedDecrement(&Endpoint->LockCounter);
894 }
895 else
896 {
897 InsertTailList(&List, &Endpoint->DispatchLink);
898
899 if (Endpoint->WorkerLink.Flink && Endpoint->WorkerLink.Blink)
900 {
901 RemoveEntryList(&Endpoint->WorkerLink);
902
903 Endpoint->WorkerLink.Flink = NULL;
904 Endpoint->WorkerLink.Blink = NULL;
905 }
906 }
907
908 Entry = Endpoint->EndpointLink.Flink;
909 }
910
911 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
912
913 while (!IsListEmpty(&List))
914 {
915 Endpoint = CONTAINING_RECORD(List.Flink,
916 USBPORT_ENDPOINT,
917 DispatchLink);
918
919 RemoveEntryList(List.Flink);
920 Endpoint->DispatchLink.Flink = NULL;
921 Endpoint->DispatchLink.Blink = NULL;
922
923 USBPORT_EndpointWorker(Endpoint, TRUE);
924 USBPORT_FlushPendingTransfers(Endpoint);
925 }
926
927 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
928
929 if (!IsListEmpty(&FdoExtension->WorkerList))
930 {
931 USBPORT_SignalWorkerThread(FdoDevice);
932 }
933
934 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
935
936 USBPORT_FlushDoneTransfers(FdoDevice);
937 }
938
939 VOID
940 NTAPI
941 USBPORT_IsrDpcHandler(IN PDEVICE_OBJECT FdoDevice,
942 IN BOOLEAN IsDpcHandler)
943 {
944 PUSBPORT_DEVICE_EXTENSION FdoExtension;
945 PUSBPORT_REGISTRATION_PACKET Packet;
946 PUSBPORT_ENDPOINT Endpoint;
947 PLIST_ENTRY List;
948 ULONG FrameNumber;
949
950 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
951
952 DPRINT_CORE("USBPORT_IsrDpcHandler: IsDpcHandler - %x\n", IsDpcHandler);
953
954 FdoExtension = FdoDevice->DeviceExtension;
955 Packet = &FdoExtension->MiniPortInterface->Packet;
956
957 if (InterlockedIncrement(&FdoExtension->IsrDpcHandlerCounter))
958 {
959 KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, NULL);
960 InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
961 return;
962 }
963
964 for (List = ExInterlockedRemoveHeadList(&FdoExtension->EpStateChangeList,
965 &FdoExtension->EpStateChangeSpinLock);
966 List != NULL;
967 List = ExInterlockedRemoveHeadList(&FdoExtension->EpStateChangeList,
968 &FdoExtension->EpStateChangeSpinLock))
969 {
970 Endpoint = CONTAINING_RECORD(List,
971 USBPORT_ENDPOINT,
972 StateChangeLink);
973
974 DPRINT_CORE("USBPORT_IsrDpcHandler: Endpoint - %p\n", Endpoint);
975
976 KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
977
978 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
979 FrameNumber = Packet->Get32BitFrameNumber(FdoExtension->MiniPortExt);
980 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
981
982 if (FrameNumber <= Endpoint->FrameNumber &&
983 !(Endpoint->Flags & ENDPOINT_FLAG_NUKE))
984 {
985 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
986
987 ExInterlockedInsertHeadList(&FdoExtension->EpStateChangeList,
988 &Endpoint->StateChangeLink,
989 &FdoExtension->EpStateChangeSpinLock);
990
991 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportSpinLock);
992 Packet->InterruptNextSOF(FdoExtension->MiniPortExt);
993 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportSpinLock);
994
995 break;
996 }
997
998 KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
999
1000 KeAcquireSpinLockAtDpcLevel(&Endpoint->StateChangeSpinLock);
1001 Endpoint->StateLast = Endpoint->StateNext;
1002 KeReleaseSpinLockFromDpcLevel(&Endpoint->StateChangeSpinLock);
1003
1004 DPRINT_CORE("USBPORT_IsrDpcHandler: Endpoint->StateLast - %x\n",
1005 Endpoint->StateLast);
1006
1007 if (IsDpcHandler)
1008 {
1009 USBPORT_InvalidateEndpointHandler(FdoDevice,
1010 Endpoint,
1011 INVALIDATE_ENDPOINT_ONLY);
1012 }
1013 else
1014 {
1015 USBPORT_InvalidateEndpointHandler(FdoDevice,
1016 Endpoint,
1017 INVALIDATE_ENDPOINT_WORKER_THREAD);
1018 }
1019 }
1020
1021 if (IsDpcHandler)
1022 {
1023 USBPORT_DpcHandler(FdoDevice);
1024 }
1025
1026 InterlockedDecrement(&FdoExtension->IsrDpcHandlerCounter);
1027 }
1028
1029 VOID
1030 NTAPI
1031 USBPORT_IsrDpc(IN PRKDPC Dpc,
1032 IN PVOID DeferredContext,
1033 IN PVOID SystemArgument1,
1034 IN PVOID SystemArgument2)
1035 {
1036 PDEVICE_OBJECT FdoDevice;
1037 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1038 PUSBPORT_REGISTRATION_PACKET Packet;
1039 BOOLEAN InterruptEnable;
1040
1041 DPRINT_INT("USBPORT_IsrDpc: DeferredContext - %p, SystemArgument2 - %p\n",
1042 DeferredContext,
1043 SystemArgument2);
1044
1045 FdoDevice = DeferredContext;
1046 FdoExtension = FdoDevice->DeviceExtension;
1047 Packet = &FdoExtension->MiniPortInterface->Packet;
1048
1049 if (SystemArgument2)
1050 {
1051 InterlockedDecrement(&FdoExtension->IsrDpcCounter);
1052 }
1053
1054 KeAcquireSpinLockAtDpcLevel(&FdoExtension->MiniportInterruptsSpinLock);
1055 InterruptEnable = (FdoExtension->Flags & USBPORT_FLAG_INTERRUPT_ENABLED) ==
1056 USBPORT_FLAG_INTERRUPT_ENABLED;
1057
1058 Packet->InterruptDpc(FdoExtension->MiniPortExt, InterruptEnable);
1059
1060 KeReleaseSpinLockFromDpcLevel(&FdoExtension->MiniportInterruptsSpinLock);
1061
1062 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
1063 FdoExtension->TimerFlags & USBPORT_TMFLAG_WAKE)
1064 {
1065 USBPORT_CompletePdoWaitWake(FdoDevice);
1066 }
1067 else
1068 {
1069 USBPORT_IsrDpcHandler(FdoDevice, TRUE);
1070 }
1071
1072 DPRINT_INT("USBPORT_IsrDpc: exit\n");
1073 }
1074
1075 BOOLEAN
1076 NTAPI
1077 USBPORT_InterruptService(IN PKINTERRUPT Interrupt,
1078 IN PVOID ServiceContext)
1079 {
1080 PDEVICE_OBJECT FdoDevice;
1081 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1082 PUSBPORT_REGISTRATION_PACKET Packet;
1083 BOOLEAN Result = FALSE;
1084
1085 FdoDevice = ServiceContext;
1086 FdoExtension = FdoDevice->DeviceExtension;
1087 Packet = &FdoExtension->MiniPortInterface->Packet;
1088
1089 DPRINT_INT("USBPORT_InterruptService: FdoExtension[%p]->Flags - %08X\n",
1090 FdoExtension,
1091 FdoExtension->Flags);
1092
1093 if (FdoExtension->Flags & USBPORT_FLAG_INTERRUPT_ENABLED &&
1094 FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
1095 {
1096 Result = Packet->InterruptService(FdoExtension->MiniPortExt);
1097
1098 if (Result)
1099 {
1100 KeInsertQueueDpc(&FdoExtension->IsrDpc, NULL, NULL);
1101 }
1102 }
1103
1104 DPRINT_INT("USBPORT_InterruptService: return - %x\n", Result);
1105
1106 return Result;
1107 }
1108
1109 VOID
1110 NTAPI
1111 USBPORT_SignalWorkerThread(IN PDEVICE_OBJECT FdoDevice)
1112 {
1113 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1114 KIRQL OldIrql;
1115
1116 DPRINT_CORE("USBPORT_SignalWorkerThread ... \n");
1117
1118 FdoExtension = FdoDevice->DeviceExtension;
1119
1120 KeAcquireSpinLock(&FdoExtension->WorkerThreadEventSpinLock, &OldIrql);
1121 KeSetEvent(&FdoExtension->WorkerThreadEvent, EVENT_INCREMENT, FALSE);
1122 KeReleaseSpinLock(&FdoExtension->WorkerThreadEventSpinLock, OldIrql);
1123 }
1124
1125 VOID
1126 NTAPI
1127 USBPORT_WorkerThreadHandler(IN PDEVICE_OBJECT FdoDevice)
1128 {
1129 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1130 PUSBPORT_REGISTRATION_PACKET Packet;
1131 PLIST_ENTRY workerList;
1132 KIRQL OldIrql;
1133 PUSBPORT_ENDPOINT Endpoint;
1134 LIST_ENTRY list;
1135 BOOLEAN Result;
1136
1137 DPRINT_CORE("USBPORT_WorkerThreadHandler: ... \n");
1138
1139 FdoExtension = FdoDevice->DeviceExtension;
1140 Packet = &FdoExtension->MiniPortInterface->Packet;
1141
1142 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1143
1144 if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
1145 {
1146 Packet->CheckController(FdoExtension->MiniPortExt);
1147 }
1148
1149 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1150
1151 InitializeListHead(&list);
1152
1153 USBPORT_FlushAllEndpoints(FdoDevice);
1154
1155 while (TRUE)
1156 {
1157 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1158 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
1159
1160 workerList = &FdoExtension->WorkerList;
1161
1162 if (IsListEmpty(workerList))
1163 break;
1164
1165 Endpoint = CONTAINING_RECORD(workerList->Flink,
1166 USBPORT_ENDPOINT,
1167 WorkerLink);
1168
1169 DPRINT_CORE("USBPORT_WorkerThreadHandler: Endpoint - %p\n", Endpoint);
1170
1171 RemoveHeadList(workerList);
1172 Endpoint->WorkerLink.Blink = NULL;
1173 Endpoint->WorkerLink.Flink = NULL;
1174
1175 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1176
1177 Result = USBPORT_EndpointWorker(Endpoint, FALSE);
1178 KeAcquireSpinLockAtDpcLevel(&FdoExtension->EndpointListSpinLock);
1179
1180 if (Result)
1181 {
1182 if (Endpoint->FlushAbortLink.Flink == NULL ||
1183 Endpoint->FlushAbortLink.Blink == NULL)
1184 {
1185 InsertTailList(&list, &Endpoint->FlushAbortLink);
1186 }
1187 }
1188
1189 while (!IsListEmpty(&list))
1190 {
1191 Endpoint = CONTAINING_RECORD(list.Flink,
1192 USBPORT_ENDPOINT,
1193 FlushAbortLink);
1194
1195 RemoveHeadList(&list);
1196
1197 Endpoint->FlushAbortLink.Flink = NULL;
1198 Endpoint->FlushAbortLink.Blink = NULL;
1199
1200 if (Endpoint->WorkerLink.Flink == NULL ||
1201 Endpoint->WorkerLink.Blink == NULL)
1202 {
1203 InsertTailList(&FdoExtension->WorkerList,
1204 &Endpoint->WorkerLink);
1205
1206 USBPORT_SignalWorkerThread(FdoDevice);
1207 }
1208 }
1209
1210 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1211 KeLowerIrql(OldIrql);
1212 }
1213
1214 KeReleaseSpinLockFromDpcLevel(&FdoExtension->EndpointListSpinLock);
1215 KeLowerIrql(OldIrql);
1216
1217 USBPORT_FlushClosedEndpointList(FdoDevice);
1218 }
1219
1220 VOID
1221 NTAPI
1222 USBPORT_DoRootHubCallback(IN PDEVICE_OBJECT FdoDevice)
1223 {
1224 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1225 PDEVICE_OBJECT PdoDevice;
1226 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1227 PRH_INIT_CALLBACK RootHubInitCallback;
1228 PVOID RootHubInitContext;
1229
1230 FdoExtension = FdoDevice->DeviceExtension;
1231
1232 DPRINT("USBPORT_DoRootHubCallback: FdoDevice - %p\n", FdoDevice);
1233
1234 PdoDevice = FdoExtension->RootHubPdo;
1235
1236 if (PdoDevice)
1237 {
1238 PdoExtension = PdoDevice->DeviceExtension;
1239
1240 RootHubInitContext = PdoExtension->RootHubInitContext;
1241 RootHubInitCallback = PdoExtension->RootHubInitCallback;
1242
1243 PdoExtension->RootHubInitCallback = NULL;
1244 PdoExtension->RootHubInitContext = NULL;
1245
1246 if (RootHubInitCallback)
1247 {
1248 RootHubInitCallback(RootHubInitContext);
1249 }
1250 }
1251
1252 DPRINT("USBPORT_DoRootHubCallback: exit\n");
1253 }
1254
1255 VOID
1256 NTAPI
1257 USBPORT_SynchronizeRootHubCallback(IN PDEVICE_OBJECT FdoDevice,
1258 IN PDEVICE_OBJECT Usb2FdoDevice)
1259 {
1260 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1261 PUSBPORT_REGISTRATION_PACKET Packet;
1262 PUSBPORT_DEVICE_EXTENSION Usb2FdoExtension;
1263 PDEVICE_RELATIONS CompanionControllersList;
1264 PUSBPORT_DEVICE_EXTENSION CompanionFdoExtension;
1265 PDEVICE_OBJECT * Entry;
1266 ULONG ix;
1267
1268 DPRINT("USBPORT_SynchronizeRootHubCallback: FdoDevice - %p, Usb2FdoDevice - %p\n",
1269 FdoDevice,
1270 Usb2FdoDevice);
1271
1272 FdoExtension = FdoDevice->DeviceExtension;
1273 Packet = &FdoExtension->MiniPortInterface->Packet;
1274
1275 if (Usb2FdoDevice == NULL &&
1276 !(Packet->MiniPortFlags & USB_MINIPORT_FLAGS_USB2))
1277 {
1278 /* Not Companion USB11 Controller */
1279 USBPORT_DoRootHubCallback(FdoDevice);
1280
1281 FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
1282 InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 0, 1);
1283
1284 DPRINT("USBPORT_SynchronizeRootHubCallback: exit \n");
1285 return;
1286 }
1287
1288 /* USB2 or Companion USB11 */
1289
1290 DPRINT("USBPORT_SynchronizeRootHubCallback: FdoExtension->Flags - %p\n",
1291 FdoExtension->Flags);
1292
1293 if (!(FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC))
1294 {
1295 KeWaitForSingleObject(&FdoExtension->ControllerSemaphore,
1296 Executive,
1297 KernelMode,
1298 FALSE,
1299 NULL);
1300
1301 FdoExtension->Flags |= USBPORT_FLAG_PWR_AND_CHIRP_LOCK;
1302
1303 if (!(FdoExtension->Flags & (USBPORT_FLAG_HC_SUSPEND |
1304 USBPORT_FLAG_POWER_AND_CHIRP_OK)))
1305 {
1306 USBPORT_RootHubPowerAndChirpAllCcPorts(FdoDevice);
1307 FdoExtension->Flags |= USBPORT_FLAG_POWER_AND_CHIRP_OK;
1308 }
1309
1310 FdoExtension->Flags &= ~USBPORT_FLAG_PWR_AND_CHIRP_LOCK;
1311
1312 KeReleaseSemaphore(&FdoExtension->ControllerSemaphore,
1313 LOW_REALTIME_PRIORITY,
1314 1,
1315 FALSE);
1316
1317 CompanionControllersList = USBPORT_FindCompanionControllers(FdoDevice,
1318 FALSE,
1319 TRUE);
1320
1321 if (CompanionControllersList)
1322 {
1323 Entry = &CompanionControllersList->Objects[0];
1324
1325 for (ix = 0; ix < CompanionControllersList->Count; ++ix)
1326 {
1327 CompanionFdoExtension = ((*Entry)->DeviceExtension);
1328
1329 InterlockedCompareExchange(&CompanionFdoExtension->RHInitCallBackLock,
1330 0,
1331 1);
1332
1333 ++Entry;
1334 }
1335
1336 ExFreePoolWithTag(CompanionControllersList, USB_PORT_TAG);
1337 }
1338
1339 USBPORT_DoRootHubCallback(FdoDevice);
1340
1341 FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
1342 InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 0, 1);
1343 }
1344 else
1345 {
1346 Usb2FdoExtension = Usb2FdoDevice->DeviceExtension;
1347
1348 USBPORT_Wait(FdoDevice, 50);
1349
1350 while (FdoExtension->RHInitCallBackLock)
1351 {
1352 USBPORT_Wait(FdoDevice, 10);
1353
1354 Usb2FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
1355 USBPORT_SignalWorkerThread(Usb2FdoDevice);
1356 }
1357
1358 USBPORT_DoRootHubCallback(FdoDevice);
1359
1360 FdoExtension->Flags &= ~USBPORT_FLAG_RH_INIT_CALLBACK;
1361 }
1362
1363 DPRINT("USBPORT_SynchronizeRootHubCallback: exit \n");
1364 }
1365
1366 VOID
1367 NTAPI
1368 USBPORT_WorkerThread(IN PVOID StartContext)
1369 {
1370 PDEVICE_OBJECT FdoDevice;
1371 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1372 LARGE_INTEGER OldTime;
1373 LARGE_INTEGER NewTime;
1374 KIRQL OldIrql;
1375
1376 DPRINT_CORE("USBPORT_WorkerThread ... \n");
1377
1378 FdoDevice = StartContext;
1379 FdoExtension = FdoDevice->DeviceExtension;
1380
1381 FdoExtension->WorkerThread = KeGetCurrentThread();
1382
1383 do
1384 {
1385 KeQuerySystemTime(&OldTime);
1386
1387 KeWaitForSingleObject(&FdoExtension->WorkerThreadEvent,
1388 Suspended,
1389 KernelMode,
1390 FALSE,
1391 NULL);
1392
1393 KeQuerySystemTime(&NewTime);
1394
1395 KeAcquireSpinLock(&FdoExtension->WorkerThreadEventSpinLock, &OldIrql);
1396 KeClearEvent(&FdoExtension->WorkerThreadEvent);
1397 KeReleaseSpinLock(&FdoExtension->WorkerThreadEventSpinLock, OldIrql);
1398 DPRINT_CORE("USBPORT_WorkerThread: run \n");
1399
1400 if (FdoExtension->MiniPortFlags & USBPORT_MPFLAG_INTERRUPTS_ENABLED)
1401 {
1402 USBPORT_DoSetPowerD0(FdoDevice);
1403
1404 if (FdoExtension->Flags & USBPORT_FLAG_RH_INIT_CALLBACK)
1405 {
1406 PDEVICE_OBJECT USB2FdoDevice = NULL;
1407
1408 USB2FdoDevice = USBPORT_FindUSB2Controller(FdoDevice);
1409 USBPORT_SynchronizeRootHubCallback(FdoDevice, USB2FdoDevice);
1410 }
1411 }
1412
1413 USBPORT_WorkerThreadHandler(FdoDevice);
1414 }
1415 while (!(FdoExtension->Flags & USBPORT_FLAG_WORKER_THREAD_ON));
1416
1417 PsTerminateSystemThread(0);
1418 }
1419
1420 NTSTATUS
1421 NTAPI
1422 USBPORT_CreateWorkerThread(IN PDEVICE_OBJECT FdoDevice)
1423 {
1424 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1425 NTSTATUS Status;
1426
1427 DPRINT("USBPORT_CreateWorkerThread ... \n");
1428
1429 FdoExtension = FdoDevice->DeviceExtension;
1430
1431 FdoExtension->Flags &= ~USBPORT_FLAG_WORKER_THREAD_ON;
1432
1433 KeInitializeEvent(&FdoExtension->WorkerThreadEvent,
1434 NotificationEvent,
1435 FALSE);
1436
1437 Status = PsCreateSystemThread(&FdoExtension->WorkerThreadHandle,
1438 THREAD_ALL_ACCESS,
1439 NULL,
1440 NULL,
1441 NULL,
1442 USBPORT_WorkerThread,
1443 (PVOID)FdoDevice);
1444
1445 return Status;
1446 }
1447
1448 VOID
1449 NTAPI
1450 USBPORT_SynchronizeControllersStart(IN PDEVICE_OBJECT FdoDevice)
1451 {
1452 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1453 PDEVICE_OBJECT PdoDevice;
1454 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
1455 PDEVICE_OBJECT USB2FdoDevice = NULL;
1456 PUSBPORT_DEVICE_EXTENSION USB2FdoExtension;
1457 BOOLEAN IsOn;
1458
1459 DPRINT_TIMER("USBPORT_SynchronizeControllersStart: FdoDevice - %p\n",
1460 FdoDevice);
1461
1462 FdoExtension = FdoDevice->DeviceExtension;
1463
1464 PdoDevice = FdoExtension->RootHubPdo;
1465
1466 if (!PdoDevice)
1467 {
1468 return;
1469 }
1470
1471 PdoExtension = PdoDevice->DeviceExtension;
1472
1473 if (PdoExtension->RootHubInitCallback == NULL ||
1474 FdoExtension->Flags & USBPORT_FLAG_RH_INIT_CALLBACK)
1475 {
1476 return;
1477 }
1478
1479 DPRINT_TIMER("USBPORT_SynchronizeControllersStart: Flags - %p\n",
1480 FdoExtension->Flags);
1481
1482 if (FdoExtension->Flags & USBPORT_FLAG_COMPANION_HC)
1483 {
1484 IsOn = FALSE;
1485
1486 USB2FdoDevice = USBPORT_FindUSB2Controller(FdoDevice);
1487
1488 DPRINT_TIMER("USBPORT_SynchronizeControllersStart: USB2FdoDevice - %p\n",
1489 USB2FdoDevice);
1490
1491 if (USB2FdoDevice)
1492 {
1493 USB2FdoExtension = USB2FdoDevice->DeviceExtension;
1494
1495 if (USB2FdoExtension->CommonExtension.PnpStateFlags &
1496 USBPORT_PNP_STATE_STARTED)
1497 {
1498 IsOn = TRUE;
1499 }
1500 }
1501
1502 if (!(FdoExtension->Flags & USBPORT_FLAG_NO_HACTION))
1503 {
1504 goto Start;
1505 }
1506
1507 USB2FdoDevice = NULL;
1508 }
1509
1510 IsOn = TRUE;
1511
1512 Start:
1513
1514 if (IsOn &&
1515 !InterlockedCompareExchange(&FdoExtension->RHInitCallBackLock, 1, 0))
1516 {
1517 FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
1518 USBPORT_SignalWorkerThread(FdoDevice);
1519
1520 if (USB2FdoDevice)
1521 {
1522 USB2FdoExtension = USB2FdoDevice->DeviceExtension;
1523
1524 USB2FdoExtension->Flags |= USBPORT_FLAG_RH_INIT_CALLBACK;
1525 USBPORT_SignalWorkerThread(USB2FdoDevice);
1526 }
1527 }
1528
1529 DPRINT_TIMER("USBPORT_SynchronizeControllersStart: exit\n");
1530 }
1531
1532 VOID
1533 NTAPI
1534 USBPORT_TimerDpc(IN PRKDPC Dpc,
1535 IN PVOID DeferredContext,
1536 IN PVOID SystemArgument1,
1537 IN PVOID SystemArgument2)
1538 {
1539 PDEVICE_OBJECT FdoDevice;
1540 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1541 PUSBPORT_REGISTRATION_PACKET Packet;
1542 LARGE_INTEGER DueTime = {{0, 0}};
1543 ULONG TimerFlags;
1544 PTIMER_WORK_QUEUE_ITEM IdleQueueItem;
1545 KIRQL OldIrql;
1546 KIRQL TimerOldIrql;
1547
1548 DPRINT_TIMER("USBPORT_TimerDpc: Dpc - %p, DeferredContext - %p\n",
1549 Dpc,
1550 DeferredContext);
1551
1552 FdoDevice = DeferredContext;
1553 FdoExtension = FdoDevice->DeviceExtension;
1554 Packet = &FdoExtension->MiniPortInterface->Packet;
1555
1556 KeAcquireSpinLock(&FdoExtension->TimerFlagsSpinLock, &TimerOldIrql);
1557
1558 TimerFlags = FdoExtension->TimerFlags;
1559
1560 DPRINT_TIMER("USBPORT_TimerDpc: Flags - %p, TimerFlags - %p\n",
1561 FdoExtension->Flags,
1562 TimerFlags);
1563
1564 if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND &&
1565 FdoExtension->Flags & USBPORT_FLAG_HC_WAKE_SUPPORT &&
1566 !(TimerFlags & USBPORT_TMFLAG_HC_RESUME))
1567 {
1568 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1569 Packet->PollController(FdoExtension->MiniPortExt);
1570 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1571 }
1572
1573 USBPORT_SynchronizeControllersStart(FdoDevice);
1574
1575 if (TimerFlags & USBPORT_TMFLAG_HC_SUSPENDED)
1576 {
1577 USBPORT_BadRequestFlush(FdoDevice);
1578 goto Exit;
1579 }
1580
1581 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1582
1583 if (!(FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND))
1584 {
1585 Packet->CheckController(FdoExtension->MiniPortExt);
1586 }
1587
1588 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1589
1590 if (FdoExtension->Flags & USBPORT_FLAG_HC_POLLING)
1591 {
1592 KeAcquireSpinLock(&FdoExtension->MiniportSpinLock, &OldIrql);
1593 Packet->PollController(FdoExtension->MiniPortExt);
1594 KeReleaseSpinLock(&FdoExtension->MiniportSpinLock, OldIrql);
1595 }
1596
1597 USBPORT_IsrDpcHandler(FdoDevice, FALSE);
1598
1599 DPRINT_TIMER("USBPORT_TimerDpc: USBPORT_TimeoutAllEndpoints UNIMPLEMENTED.\n");
1600 //USBPORT_TimeoutAllEndpoints(FdoDevice);
1601 DPRINT_TIMER("USBPORT_TimerDpc: USBPORT_CheckIdleEndpoints UNIMPLEMENTED.\n");
1602 //USBPORT_CheckIdleEndpoints(FdoDevice);
1603
1604 USBPORT_BadRequestFlush(FdoDevice);
1605
1606 if (FdoExtension->IdleLockCounter > -1 &&
1607 !(TimerFlags & USBPORT_TMFLAG_IDLE_QUEUEITEM_ON))
1608 {
1609 IdleQueueItem = ExAllocatePoolWithTag(NonPagedPool,
1610 sizeof(TIMER_WORK_QUEUE_ITEM),
1611 USB_PORT_TAG);
1612
1613 DPRINT("USBPORT_TimerDpc: IdleLockCounter - %x, IdleQueueItem - %p\n",
1614 FdoExtension->IdleLockCounter,
1615 IdleQueueItem);
1616
1617 if (IdleQueueItem)
1618 {
1619 RtlZeroMemory(IdleQueueItem, sizeof(TIMER_WORK_QUEUE_ITEM));
1620
1621 IdleQueueItem->WqItem.List.Flink = NULL;
1622 IdleQueueItem->WqItem.WorkerRoutine = USBPORT_DoIdleNotificationCallback;
1623 IdleQueueItem->WqItem.Parameter = IdleQueueItem;
1624
1625 IdleQueueItem->FdoDevice = FdoDevice;
1626 IdleQueueItem->Context = 0;
1627
1628 FdoExtension->TimerFlags |= USBPORT_TMFLAG_IDLE_QUEUEITEM_ON;
1629
1630 ExQueueWorkItem(&IdleQueueItem->WqItem, CriticalWorkQueue);
1631 }
1632 }
1633
1634 Exit:
1635
1636 KeReleaseSpinLock(&FdoExtension->TimerFlagsSpinLock, TimerOldIrql);
1637
1638 if (TimerFlags & USBPORT_TMFLAG_TIMER_QUEUED)
1639 {
1640 DueTime.QuadPart -= FdoExtension->TimerValue * 10000 +
1641 (KeQueryTimeIncrement() - 1);
1642
1643 KeSetTimer(&FdoExtension->TimerObject,
1644 DueTime,
1645 &FdoExtension->TimerDpc);
1646 }
1647
1648 DPRINT_TIMER("USBPORT_TimerDpc: exit\n");
1649 }
1650
1651 BOOLEAN
1652 NTAPI
1653 USBPORT_StartTimer(IN PDEVICE_OBJECT FdoDevice,
1654 IN ULONG Time)
1655 {
1656 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1657 LARGE_INTEGER DueTime = {{0, 0}};
1658 ULONG TimeIncrement;
1659 BOOLEAN Result;
1660
1661 DPRINT_TIMER("USBPORT_StartTimer: FdoDevice - %p, Time - %x\n",
1662 FdoDevice,
1663 Time);
1664
1665 FdoExtension = FdoDevice->DeviceExtension;
1666
1667 TimeIncrement = KeQueryTimeIncrement();
1668
1669 FdoExtension->TimerFlags |= USBPORT_TMFLAG_TIMER_QUEUED;
1670 FdoExtension->TimerValue = Time;
1671
1672 KeInitializeTimer(&FdoExtension->TimerObject);
1673 KeInitializeDpc(&FdoExtension->TimerDpc, USBPORT_TimerDpc, FdoDevice);
1674
1675 DueTime.QuadPart -= 10000 * Time + (TimeIncrement - 1);
1676
1677 Result = KeSetTimer(&FdoExtension->TimerObject,
1678 DueTime,
1679 &FdoExtension->TimerDpc);
1680
1681 return Result;
1682 }
1683
1684 PUSBPORT_COMMON_BUFFER_HEADER
1685 NTAPI
1686 USBPORT_AllocateCommonBuffer(IN PDEVICE_OBJECT FdoDevice,
1687 IN SIZE_T BufferLength)
1688 {
1689 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer = NULL;
1690 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1691 PDMA_ADAPTER DmaAdapter;
1692 PDMA_OPERATIONS DmaOperations;
1693 SIZE_T HeaderSize;
1694 ULONG Length = 0;
1695 ULONG LengthPadded;
1696 PHYSICAL_ADDRESS LogicalAddress;
1697 ULONG_PTR BaseVA;
1698 ULONG_PTR StartBufferVA;
1699 ULONG StartBufferPA;
1700
1701 DPRINT("USBPORT_AllocateCommonBuffer: FdoDevice - %p, BufferLength - %p\n",
1702 FdoDevice,
1703 BufferLength);
1704
1705 if (BufferLength == 0)
1706 goto Exit;
1707
1708 FdoExtension = FdoDevice->DeviceExtension;
1709
1710 DmaAdapter = FdoExtension->DmaAdapter;
1711 DmaOperations = DmaAdapter->DmaOperations;
1712
1713 HeaderSize = sizeof(USBPORT_COMMON_BUFFER_HEADER);
1714 Length = ROUND_TO_PAGES(BufferLength + HeaderSize);
1715 LengthPadded = Length - (BufferLength + HeaderSize);
1716
1717 BaseVA = (ULONG_PTR)DmaOperations->AllocateCommonBuffer(DmaAdapter,
1718 Length,
1719 &LogicalAddress,
1720 TRUE);
1721
1722 if (!BaseVA)
1723 goto Exit;
1724
1725 StartBufferVA = BaseVA & ~(PAGE_SIZE - 1);
1726 StartBufferPA = LogicalAddress.LowPart & ~(PAGE_SIZE - 1);
1727
1728 HeaderBuffer = (PUSBPORT_COMMON_BUFFER_HEADER)(StartBufferVA +
1729 BufferLength +
1730 LengthPadded);
1731
1732 HeaderBuffer->Length = Length;
1733 HeaderBuffer->BaseVA = BaseVA;
1734 HeaderBuffer->LogicalAddress = LogicalAddress;
1735
1736 HeaderBuffer->BufferLength = BufferLength + LengthPadded;
1737 HeaderBuffer->VirtualAddress = StartBufferVA;
1738 HeaderBuffer->PhysicalAddress = StartBufferPA;
1739
1740 RtlZeroMemory((PVOID)StartBufferVA, BufferLength + LengthPadded);
1741
1742 Exit:
1743 return HeaderBuffer;
1744 }
1745
1746 VOID
1747 NTAPI
1748 USBPORT_FreeCommonBuffer(IN PDEVICE_OBJECT FdoDevice,
1749 IN PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer)
1750 {
1751 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1752 PDMA_ADAPTER DmaAdapter;
1753 PDMA_OPERATIONS DmaOperations;
1754
1755 DPRINT("USBPORT_FreeCommonBuffer: ... \n");
1756
1757 FdoExtension = FdoDevice->DeviceExtension;
1758
1759 DmaAdapter = FdoExtension->DmaAdapter;
1760 DmaOperations = DmaAdapter->DmaOperations;
1761
1762 DmaOperations->FreeCommonBuffer(FdoExtension->DmaAdapter,
1763 HeaderBuffer->Length,
1764 HeaderBuffer->LogicalAddress,
1765 (PVOID)HeaderBuffer->VirtualAddress,
1766 TRUE);
1767 }
1768
1769 PUSBPORT_MINIPORT_INTERFACE
1770 NTAPI
1771 USBPORT_FindMiniPort(IN PDRIVER_OBJECT DriverObject)
1772 {
1773 KIRQL OldIrql;
1774 PLIST_ENTRY List;
1775 PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1776 BOOLEAN IsFound = FALSE;
1777
1778 DPRINT("USBPORT_FindMiniPort: ... \n");
1779
1780 KeAcquireSpinLock(&USBPORT_SpinLock, &OldIrql);
1781
1782 for (List = USBPORT_MiniPortDrivers.Flink;
1783 List != &USBPORT_MiniPortDrivers;
1784 List = List->Flink)
1785 {
1786 MiniPortInterface = CONTAINING_RECORD(List,
1787 USBPORT_MINIPORT_INTERFACE,
1788 DriverLink);
1789
1790 if (MiniPortInterface->DriverObject == DriverObject)
1791 {
1792 DPRINT("USBPORT_FindMiniPort: find MiniPortInterface - %p\n",
1793 MiniPortInterface);
1794
1795 IsFound = TRUE;
1796 break;
1797 }
1798 }
1799
1800 KeReleaseSpinLock(&USBPORT_SpinLock, OldIrql);
1801
1802 if (IsFound)
1803 return MiniPortInterface;
1804 else
1805 return NULL;
1806
1807 }
1808
1809 NTSTATUS
1810 NTAPI
1811 USBPORT_AddDevice(IN PDRIVER_OBJECT DriverObject,
1812 IN PDEVICE_OBJECT PhysicalDeviceObject)
1813 {
1814 NTSTATUS Status;
1815 PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1816 ULONG DeviceNumber = 0;
1817 WCHAR CharDeviceName[64];
1818 UNICODE_STRING DeviceName;
1819 PDEVICE_OBJECT DeviceObject;
1820 PUSBPORT_DEVICE_EXTENSION FdoExtension;
1821 PUSBPORT_COMMON_DEVICE_EXTENSION FdoCommonExtension;
1822 PDEVICE_OBJECT LowerDevice;
1823 ULONG Length;
1824
1825 DPRINT("USBPORT_AddDevice: DriverObject - %p, PhysicalDeviceObject - %p\n",
1826 DriverObject,
1827 PhysicalDeviceObject);
1828
1829 MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
1830
1831 if (!MiniPortInterface)
1832 {
1833 DPRINT("USBPORT_AddDevice: USBPORT_FindMiniPort not found MiniPortInterface\n");
1834 return STATUS_UNSUCCESSFUL;
1835 }
1836
1837 while (TRUE)
1838 {
1839 /* Construct device name */
1840 RtlStringCbPrintfW(CharDeviceName,
1841 sizeof(CharDeviceName),
1842 L"\\Device\\USBFDO-%d",
1843 DeviceNumber);
1844
1845 RtlInitUnicodeString(&DeviceName, CharDeviceName);
1846
1847 ASSERT(MiniPortInterface->Packet.MiniPortExtensionSize <=
1848 MAXULONG - sizeof(USBPORT_DEVICE_EXTENSION) - sizeof(USB2_HC_EXTENSION));
1849 Length = (ULONG)(sizeof(USBPORT_DEVICE_EXTENSION) +
1850 MiniPortInterface->Packet.MiniPortExtensionSize +
1851 sizeof(USB2_HC_EXTENSION));
1852
1853 /* Create device */
1854 Status = IoCreateDevice(DriverObject,
1855 Length,
1856 &DeviceName,
1857 FILE_DEVICE_CONTROLLER,
1858 0,
1859 FALSE,
1860 &DeviceObject);
1861
1862 /* Check for success */
1863 if (NT_SUCCESS(Status)) break;
1864
1865 /* Is there a device object with that same name */
1866 if ((Status == STATUS_OBJECT_NAME_EXISTS) ||
1867 (Status == STATUS_OBJECT_NAME_COLLISION))
1868 {
1869 /* Try the next name */
1870 DeviceNumber++;
1871 continue;
1872 }
1873
1874 /* Bail out on other errors */
1875 if (!NT_SUCCESS(Status))
1876 {
1877 DPRINT1("USBPORT_AddDevice: failed to create %wZ, Status %x\n",
1878 &DeviceName,
1879 Status);
1880
1881 return Status;
1882 }
1883 }
1884
1885 DPRINT("USBPORT_AddDevice: created device %p <%wZ>, Status %x\n",
1886 DeviceObject,
1887 &DeviceName,
1888 Status);
1889
1890 FdoExtension = DeviceObject->DeviceExtension;
1891 FdoCommonExtension = &FdoExtension->CommonExtension;
1892
1893 RtlZeroMemory(FdoExtension, sizeof(USBPORT_DEVICE_EXTENSION));
1894
1895 FdoCommonExtension->SelfDevice = DeviceObject;
1896 FdoCommonExtension->LowerPdoDevice = PhysicalDeviceObject;
1897 FdoCommonExtension->IsPDO = FALSE;
1898
1899 LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject,
1900 PhysicalDeviceObject);
1901
1902 FdoCommonExtension->LowerDevice = LowerDevice;
1903
1904 FdoCommonExtension->DevicePowerState = PowerDeviceD3;
1905
1906 FdoExtension->MiniPortExt = (PVOID)((ULONG_PTR)FdoExtension +
1907 sizeof(USBPORT_DEVICE_EXTENSION));
1908
1909 if (MiniPortInterface->Packet.MiniPortFlags & USB_MINIPORT_FLAGS_USB2)
1910 {
1911 FdoExtension->Usb2Extension =
1912 (PUSB2_HC_EXTENSION)((ULONG_PTR)FdoExtension->MiniPortExt +
1913 MiniPortInterface->Packet.MiniPortExtensionSize);
1914
1915 DPRINT("USBPORT_AddDevice: Usb2Extension - %p\n",
1916 FdoExtension->Usb2Extension);
1917
1918 USB2_InitController(FdoExtension->Usb2Extension);
1919 }
1920 else
1921 {
1922 FdoExtension->Usb2Extension = NULL;
1923 }
1924
1925 FdoExtension->MiniPortInterface = MiniPortInterface;
1926 FdoExtension->FdoNameNumber = DeviceNumber;
1927
1928 KeInitializeSemaphore(&FdoExtension->DeviceSemaphore, 1, 1);
1929 KeInitializeSemaphore(&FdoExtension->ControllerSemaphore, 1, 1);
1930
1931 InitializeListHead(&FdoExtension->EndpointList);
1932 InitializeListHead(&FdoExtension->DoneTransferList);
1933 InitializeListHead(&FdoExtension->WorkerList);
1934 InitializeListHead(&FdoExtension->EpStateChangeList);
1935 InitializeListHead(&FdoExtension->MapTransferList);
1936 InitializeListHead(&FdoExtension->DeviceHandleList);
1937 InitializeListHead(&FdoExtension->IdleIrpList);
1938 InitializeListHead(&FdoExtension->BadRequestList);
1939 InitializeListHead(&FdoExtension->EndpointClosedList);
1940
1941 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1942
1943 return Status;
1944 }
1945
1946 VOID
1947 NTAPI
1948 USBPORT_Unload(IN PDRIVER_OBJECT DriverObject)
1949 {
1950 PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
1951
1952 DPRINT1("USBPORT_Unload: FIXME!\n");
1953
1954 MiniPortInterface = USBPORT_FindMiniPort(DriverObject);
1955
1956 if (!MiniPortInterface)
1957 {
1958 DPRINT("USBPORT_Unload: CRITICAL ERROR!!! Not found MiniPortInterface\n");
1959 KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
1960 }
1961
1962 DPRINT1("USBPORT_Unload: UNIMPLEMENTED. FIXME. \n");
1963 //MiniPortInterface->DriverUnload(DriverObject); // Call MiniPort _HCI_Unload
1964 }
1965
1966 VOID
1967 NTAPI
1968 USBPORT_MiniportCompleteTransfer(IN PVOID MiniPortExtension,
1969 IN PVOID MiniPortEndpoint,
1970 IN PVOID TransferParameters,
1971 IN USBD_STATUS USBDStatus,
1972 IN ULONG TransferLength)
1973 {
1974 PUSBPORT_TRANSFER Transfer;
1975 PUSBPORT_TRANSFER ParentTransfer;
1976 PUSBPORT_TRANSFER SplitTransfer;
1977 PLIST_ENTRY SplitHead;
1978 PLIST_ENTRY Entry;
1979 KIRQL OldIrql;
1980
1981 DPRINT_CORE("USBPORT_MiniportCompleteTransfer: USBDStatus - %x, TransferLength - %x\n",
1982 USBDStatus,
1983 TransferLength);
1984
1985 Transfer = CONTAINING_RECORD(TransferParameters,
1986 USBPORT_TRANSFER,
1987 TransferParameters);
1988
1989 Transfer->Flags |= TRANSFER_FLAG_COMPLETED;
1990 Transfer->CompletedTransferLen = TransferLength;
1991
1992 if (((Transfer->Flags & TRANSFER_FLAG_SPLITED) == 0) ||
1993 TransferLength >= Transfer->TransferParameters.TransferBufferLength)
1994 {
1995 goto Exit;
1996 }
1997
1998 ParentTransfer = Transfer->ParentTransfer;
1999
2000 KeAcquireSpinLock(&ParentTransfer->TransferSpinLock, &OldIrql);
2001
2002 if (IsListEmpty(&ParentTransfer->SplitTransfersList))
2003 {
2004 goto Exit;
2005 }
2006
2007 SplitHead = &ParentTransfer->SplitTransfersList;
2008 Entry = SplitHead->Flink;
2009
2010 while (Entry && !IsListEmpty(SplitHead))
2011 {
2012 SplitTransfer = CONTAINING_RECORD(Entry,
2013 USBPORT_TRANSFER,
2014 SplitLink);
2015
2016 if (!(SplitTransfer->Flags & TRANSFER_FLAG_SUBMITED))
2017 {
2018 DPRINT1("USBPORT_MiniportCompleteTransfer: SplitTransfer->Flags - %X\n",
2019 SplitTransfer->Flags);
2020 //Add TRANSFER_FLAG_xxx
2021 }
2022
2023 Entry = Entry->Flink;
2024 }
2025
2026 KeReleaseSpinLock(&ParentTransfer->TransferSpinLock, OldIrql);
2027
2028 Exit:
2029 USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
2030 }
2031
2032 VOID
2033 NTAPI
2034 USBPORT_AsyncTimerDpc(IN PRKDPC Dpc,
2035 IN PVOID DeferredContext,
2036 IN PVOID SystemArgument1,
2037 IN PVOID SystemArgument2)
2038 {
2039 PDEVICE_OBJECT FdoDevice;
2040 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2041 PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
2042
2043 DPRINT("USBPORT_AsyncTimerDpc: ... \n");
2044
2045 AsyncCallbackData = DeferredContext;
2046 FdoDevice = AsyncCallbackData->FdoDevice;
2047 FdoExtension = FdoDevice->DeviceExtension;
2048
2049 (*AsyncCallbackData->CallbackFunction)(FdoExtension->MiniPortExt,
2050 &AsyncCallbackData->CallbackContext);
2051
2052 ExFreePoolWithTag(AsyncCallbackData, USB_PORT_TAG);
2053 }
2054
2055 ULONG
2056 NTAPI
2057 USBPORT_RequestAsyncCallback(IN PVOID MiniPortExtension,
2058 IN ULONG TimerValue,
2059 IN PVOID Buffer,
2060 IN SIZE_T Length,
2061 IN ASYNC_TIMER_CALLBACK * Callback)
2062 {
2063 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2064 PDEVICE_OBJECT FdoDevice;
2065 PUSBPORT_ASYNC_CALLBACK_DATA AsyncCallbackData;
2066 LARGE_INTEGER DueTime = {{0, 0}};
2067
2068 DPRINT("USBPORT_RequestAsyncCallback: ... \n");
2069
2070 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
2071 sizeof(USBPORT_DEVICE_EXTENSION));
2072
2073 FdoDevice = FdoExtension->CommonExtension.SelfDevice;
2074
2075 AsyncCallbackData = ExAllocatePoolWithTag(NonPagedPool,
2076 sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length,
2077 USB_PORT_TAG);
2078
2079 if (!AsyncCallbackData)
2080 {
2081 DPRINT1("USBPORT_RequestAsyncCallback: Not allocated AsyncCallbackData!\n");
2082 return 0;
2083 }
2084
2085 RtlZeroMemory(AsyncCallbackData,
2086 sizeof(USBPORT_ASYNC_CALLBACK_DATA) + Length);
2087
2088 if (Length)
2089 {
2090 RtlCopyMemory(&AsyncCallbackData->CallbackContext, Buffer, Length);
2091 }
2092
2093 AsyncCallbackData->FdoDevice = FdoDevice;
2094 AsyncCallbackData->CallbackFunction = Callback;
2095
2096 KeInitializeTimer(&AsyncCallbackData->AsyncTimer);
2097
2098 KeInitializeDpc(&AsyncCallbackData->AsyncTimerDpc,
2099 USBPORT_AsyncTimerDpc,
2100 AsyncCallbackData);
2101
2102 DueTime.QuadPart -= (KeQueryTimeIncrement() - 1) + 10000 * TimerValue;
2103
2104 KeSetTimer(&AsyncCallbackData->AsyncTimer,
2105 DueTime,
2106 &AsyncCallbackData->AsyncTimerDpc);
2107
2108 return 0;
2109 }
2110
2111 PVOID
2112 NTAPI
2113 USBPORT_GetMappedVirtualAddress(IN ULONG PhysicalAddress,
2114 IN PVOID MiniPortExtension,
2115 IN PVOID MiniPortEndpoint)
2116 {
2117 PUSBPORT_COMMON_BUFFER_HEADER HeaderBuffer;
2118 PUSBPORT_ENDPOINT Endpoint;
2119 ULONG Offset;
2120 ULONG_PTR VirtualAddress;
2121
2122 DPRINT_CORE("USBPORT_GetMappedVirtualAddress ... \n");
2123
2124 Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
2125 sizeof(USBPORT_ENDPOINT));
2126
2127 if (!Endpoint)
2128 {
2129 ASSERT(FALSE);
2130 }
2131
2132 HeaderBuffer = Endpoint->HeaderBuffer;
2133
2134 Offset = PhysicalAddress - HeaderBuffer->PhysicalAddress;
2135 VirtualAddress = HeaderBuffer->VirtualAddress + Offset;
2136
2137 return (PVOID)VirtualAddress;
2138 }
2139
2140 ULONG
2141 NTAPI
2142 USBPORT_InvalidateEndpoint(IN PVOID MiniPortExtension,
2143 IN PVOID MiniPortEndpoint)
2144 {
2145 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2146 PDEVICE_OBJECT FdoDevice;
2147 PUSBPORT_ENDPOINT Endpoint;
2148
2149 DPRINT_CORE("USBPORT_InvalidateEndpoint: ... \n");
2150
2151 FdoExtension = (PUSBPORT_DEVICE_EXTENSION)((ULONG_PTR)MiniPortExtension -
2152 sizeof(USBPORT_DEVICE_EXTENSION));
2153
2154 FdoDevice = FdoExtension->CommonExtension.SelfDevice;
2155
2156 if (!MiniPortEndpoint)
2157 {
2158 USBPORT_InvalidateEndpointHandler(FdoDevice,
2159 NULL,
2160 INVALIDATE_ENDPOINT_ONLY);
2161 return 0;
2162 }
2163
2164 Endpoint = (PUSBPORT_ENDPOINT)((ULONG_PTR)MiniPortEndpoint -
2165 sizeof(USBPORT_ENDPOINT));
2166
2167 USBPORT_InvalidateEndpointHandler(FdoDevice,
2168 Endpoint,
2169 INVALIDATE_ENDPOINT_ONLY);
2170
2171 return 0;
2172 }
2173
2174 VOID
2175 NTAPI
2176 USBPORT_CompleteTransfer(IN PURB Urb,
2177 IN USBD_STATUS TransferStatus)
2178 {
2179 struct _URB_CONTROL_TRANSFER *UrbTransfer;
2180 PUSBPORT_TRANSFER Transfer;
2181 NTSTATUS Status;
2182 PIRP Irp;
2183 KIRQL OldIrql;
2184 PRKEVENT Event;
2185 BOOLEAN WriteToDevice;
2186 BOOLEAN IsFlushSuccess;
2187 PMDL Mdl;
2188 ULONG_PTR CurrentVa;
2189 SIZE_T TransferLength;
2190 PUSBPORT_ENDPOINT Endpoint;
2191 PDEVICE_OBJECT FdoDevice;
2192 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2193 PDMA_OPERATIONS DmaOperations;
2194
2195 DPRINT("USBPORT_CompleteTransfer: Urb - %p, TransferStatus - %X\n",
2196 Urb,
2197 TransferStatus);
2198
2199 UrbTransfer = &Urb->UrbControlTransfer;
2200 Transfer = UrbTransfer->hca.Reserved8[0];
2201
2202 Transfer->USBDStatus = TransferStatus;
2203 Status = USBPORT_USBDStatusToNtStatus(Urb, TransferStatus);
2204
2205 UrbTransfer->TransferBufferLength = Transfer->CompletedTransferLen;
2206
2207 if (Transfer->Flags & TRANSFER_FLAG_DMA_MAPPED)
2208 {
2209 Endpoint = Transfer->Endpoint;
2210 FdoDevice = Endpoint->FdoDevice;
2211 FdoExtension = FdoDevice->DeviceExtension;
2212 DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
2213
2214 WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
2215 Mdl = UrbTransfer->TransferBufferMDL;
2216 CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2217 TransferLength = UrbTransfer->TransferBufferLength;
2218
2219 IsFlushSuccess = DmaOperations->FlushAdapterBuffers(FdoExtension->DmaAdapter,
2220 Mdl,
2221 Transfer->MapRegisterBase,
2222 (PVOID)CurrentVa,
2223 TransferLength,
2224 WriteToDevice);
2225
2226 if (!IsFlushSuccess)
2227 {
2228 DPRINT("USBPORT_CompleteTransfer: no FlushAdapterBuffers !!!\n");
2229 ASSERT(FALSE);
2230 }
2231
2232 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2233
2234 DmaOperations->FreeMapRegisters(FdoExtension->DmaAdapter,
2235 Transfer->MapRegisterBase,
2236 Transfer->NumberOfMapRegisters);
2237
2238 KeLowerIrql(OldIrql);
2239 }
2240
2241 if (Urb->UrbHeader.UsbdFlags & USBD_FLAG_ALLOCATED_MDL)
2242 {
2243 IoFreeMdl(Transfer->TransferBufferMDL);
2244 Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_MDL;
2245 }
2246
2247 Urb->UrbControlTransfer.hca.Reserved8[0] = NULL;
2248 Urb->UrbHeader.UsbdFlags |= ~USBD_FLAG_ALLOCATED_TRANSFER;
2249
2250 Irp = Transfer->Irp;
2251
2252 if (Irp)
2253 {
2254 if (!NT_SUCCESS(Status))
2255 {
2256 //DbgBreakPoint();
2257 DPRINT1("USBPORT_CompleteTransfer: Irp - %p complete with Status - %lx\n",
2258 Irp,
2259 Status);
2260
2261 USBPORT_DumpingURB(Urb);
2262 }
2263
2264 Irp->IoStatus.Status = Status;
2265 Irp->IoStatus.Information = 0;
2266
2267 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2268 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2269 KeLowerIrql(OldIrql);
2270 }
2271
2272 Event = Transfer->Event;
2273
2274 if (Event)
2275 {
2276 KeSetEvent(Event, EVENT_INCREMENT, FALSE);
2277 }
2278
2279 ExFreePoolWithTag(Transfer, USB_PORT_TAG);
2280
2281 DPRINT_CORE("USBPORT_CompleteTransfer: exit\n");
2282 }
2283
2284 IO_ALLOCATION_ACTION
2285 NTAPI
2286 USBPORT_MapTransfer(IN PDEVICE_OBJECT FdoDevice,
2287 IN PIRP Irp,
2288 IN PVOID MapRegisterBase,
2289 IN PVOID Context)
2290 {
2291 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2292 PDMA_ADAPTER DmaAdapter;
2293 PUSBPORT_TRANSFER Transfer;
2294 PURB Urb;
2295 PUSBPORT_ENDPOINT Endpoint;
2296 PMDL Mdl;
2297 ULONG_PTR CurrentVa;
2298 PUSBPORT_SCATTER_GATHER_LIST sgList;
2299 SIZE_T CurrentLength;
2300 ULONG ix;
2301 BOOLEAN WriteToDevice;
2302 PHYSICAL_ADDRESS PhAddr = {{0, 0}};
2303 PHYSICAL_ADDRESS PhAddress = {{0, 0}};
2304 ULONG TransferLength;
2305 SIZE_T SgCurrentLength;
2306 SIZE_T ElementLength;
2307 PUSBPORT_DEVICE_HANDLE DeviceHandle;
2308 PDMA_OPERATIONS DmaOperations;
2309 USBD_STATUS USBDStatus;
2310 LIST_ENTRY List;
2311 PUSBPORT_TRANSFER transfer;
2312
2313 DPRINT_CORE("USBPORT_MapTransfer: ... \n");
2314
2315 FdoExtension = FdoDevice->DeviceExtension;
2316 DmaAdapter = FdoExtension->DmaAdapter;
2317 DmaOperations = DmaAdapter->DmaOperations;
2318
2319 Transfer = Context;
2320
2321 Urb = Transfer->Urb;
2322 Endpoint = Transfer->Endpoint;
2323 TransferLength = Transfer->TransferParameters.TransferBufferLength;
2324
2325 Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
2326 CurrentVa = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2327
2328 sgList = &Transfer->SgList;
2329
2330 sgList->Flags = 0;
2331 sgList->CurrentVa = CurrentVa;
2332 sgList->MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl,
2333 NormalPagePriority);
2334 Transfer->MapRegisterBase = MapRegisterBase;
2335
2336 ix = 0;
2337 CurrentLength = 0;
2338
2339 do
2340 {
2341 WriteToDevice = Transfer->Direction == USBPORT_DMA_DIRECTION_TO_DEVICE;
2342 ASSERT(Transfer->Direction != 0);
2343
2344 PhAddress = DmaOperations->MapTransfer(DmaAdapter,
2345 Mdl,
2346 MapRegisterBase,
2347 (PVOID)CurrentVa,
2348 &TransferLength,
2349 WriteToDevice);
2350
2351 DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, PhAddress.HighPart - %x, TransferLength - %x\n",
2352 PhAddress.LowPart,
2353 PhAddress.HighPart,
2354 TransferLength);
2355
2356 PhAddress.HighPart = 0;
2357 SgCurrentLength = TransferLength;
2358
2359 do
2360 {
2361 ElementLength = PAGE_SIZE - (PhAddress.LowPart & (PAGE_SIZE - 1));
2362
2363 if (ElementLength > SgCurrentLength)
2364 ElementLength = SgCurrentLength;
2365
2366 DPRINT_CORE("USBPORT_MapTransfer: PhAddress.LowPart - %p, HighPart - %x, ElementLength - %x\n",
2367 PhAddress.LowPart,
2368 PhAddress.HighPart,
2369 ElementLength);
2370
2371 sgList->SgElement[ix].SgPhysicalAddress = PhAddress;
2372 sgList->SgElement[ix].SgTransferLength = ElementLength;
2373 sgList->SgElement[ix].SgOffset = CurrentLength +
2374 (TransferLength - SgCurrentLength);
2375
2376 PhAddress.LowPart += ElementLength;
2377 SgCurrentLength -= ElementLength;
2378
2379 ++ix;
2380 }
2381 while (SgCurrentLength);
2382
2383 if (PhAddr.QuadPart == PhAddress.QuadPart)
2384 {
2385 DPRINT1("USBPORT_MapTransfer: PhAddr == PhAddress\n");
2386 ASSERT(FALSE);
2387 }
2388
2389 PhAddr = PhAddress;
2390
2391 CurrentLength += TransferLength;
2392 CurrentVa += TransferLength;
2393
2394 TransferLength = Transfer->TransferParameters.TransferBufferLength -
2395 CurrentLength;
2396 }
2397 while (CurrentLength != Transfer->TransferParameters.TransferBufferLength);
2398
2399 sgList->SgElementCount = ix;
2400
2401 if (Endpoint->EndpointProperties.DeviceSpeed == UsbHighSpeed)
2402 {
2403 Transfer->Flags |= TRANSFER_FLAG_HIGH_SPEED;
2404 }
2405
2406 Transfer->Flags |= TRANSFER_FLAG_DMA_MAPPED;
2407
2408 if ((Transfer->Flags & TRANSFER_FLAG_ISO) == 0)
2409 {
2410 KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
2411 &Endpoint->EndpointOldIrql);
2412
2413 USBPORT_SplitTransfer(FdoDevice, Endpoint, Transfer, &List);
2414
2415 while (!IsListEmpty(&List))
2416 {
2417 transfer = CONTAINING_RECORD(List.Flink,
2418 USBPORT_TRANSFER,
2419 TransferLink);
2420
2421 RemoveHeadList(&List);
2422 InsertTailList(&Endpoint->TransferList, &transfer->TransferLink);
2423 }
2424
2425 KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
2426 Endpoint->EndpointOldIrql);
2427 }
2428 else
2429 {
2430 USBDStatus = USBPORT_InitializeIsoTransfer(FdoDevice,
2431 &Urb->UrbIsochronousTransfer,
2432 Transfer);
2433
2434 if (USBDStatus != USBD_STATUS_SUCCESS)
2435 {
2436 KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
2437 &Endpoint->EndpointOldIrql);
2438
2439 USBPORT_QueueDoneTransfer(Transfer, USBDStatus);
2440
2441 KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
2442 Endpoint->EndpointOldIrql);
2443 }
2444 }
2445
2446 DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
2447 InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
2448
2449 if (USBPORT_EndpointWorker(Endpoint, 0))
2450 {
2451 USBPORT_InvalidateEndpointHandler(FdoDevice,
2452 Endpoint,
2453 INVALIDATE_ENDPOINT_WORKER_THREAD);
2454 }
2455
2456 return DeallocateObjectKeepRegisters;
2457 }
2458
2459 VOID
2460 NTAPI
2461 USBPORT_FlushMapTransfers(IN PDEVICE_OBJECT FdoDevice)
2462 {
2463 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2464 PLIST_ENTRY MapTransferList;
2465 PUSBPORT_TRANSFER Transfer;
2466 ULONG NumMapRegisters;
2467 PMDL Mdl;
2468 SIZE_T TransferBufferLength;
2469 ULONG_PTR VirtualAddr;
2470 KIRQL OldIrql;
2471 NTSTATUS Status;
2472 PDMA_OPERATIONS DmaOperations;
2473
2474 DPRINT_CORE("USBPORT_FlushMapTransfers: ... \n");
2475
2476 FdoExtension = FdoDevice->DeviceExtension;
2477 DmaOperations = FdoExtension->DmaAdapter->DmaOperations;
2478
2479 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2480
2481 while (TRUE)
2482 {
2483 MapTransferList = &FdoExtension->MapTransferList;
2484
2485 if (IsListEmpty(&FdoExtension->MapTransferList))
2486 {
2487 KeLowerIrql(OldIrql);
2488 return;
2489 }
2490
2491 Transfer = CONTAINING_RECORD(MapTransferList->Flink,
2492 USBPORT_TRANSFER,
2493 TransferLink);
2494
2495 RemoveHeadList(MapTransferList);
2496
2497 Mdl = Transfer->Urb->UrbControlTransfer.TransferBufferMDL;
2498 TransferBufferLength = Transfer->TransferParameters.TransferBufferLength;
2499 VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2500
2501 NumMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
2502 TransferBufferLength);
2503
2504 Transfer->NumberOfMapRegisters = NumMapRegisters;
2505
2506 Status = DmaOperations->AllocateAdapterChannel(FdoExtension->DmaAdapter,
2507 FdoDevice,
2508 NumMapRegisters,
2509 USBPORT_MapTransfer,
2510 Transfer);
2511
2512 if (!NT_SUCCESS(Status))
2513 ASSERT(FALSE);
2514 }
2515
2516 KeLowerIrql(OldIrql);
2517 }
2518
2519 USBD_STATUS
2520 NTAPI
2521 USBPORT_AllocateTransfer(IN PDEVICE_OBJECT FdoDevice,
2522 IN PURB Urb,
2523 IN PUSBPORT_DEVICE_HANDLE DeviceHandle,
2524 IN PIRP Irp,
2525 IN PRKEVENT Event)
2526 {
2527 PUSBPORT_DEVICE_EXTENSION FdoExtension;
2528 SIZE_T TransferLength;
2529 PMDL Mdl;
2530 ULONG_PTR VirtualAddr;
2531 ULONG PagesNeed = 0;
2532 SIZE_T PortTransferLength;
2533 SIZE_T FullTransferLength;
2534 PUSBPORT_TRANSFER Transfer;
2535 PUSBPORT_PIPE_HANDLE PipeHandle;
2536 USBD_STATUS USBDStatus;
2537 SIZE_T IsoBlockLen = 0;
2538
2539 DPRINT_CORE("USBPORT_AllocateTransfer: FdoDevice - %p, Urb - %p, DeviceHandle - %p, Irp - %p, Event - %p\n",
2540 FdoDevice,
2541 Urb,
2542 DeviceHandle,
2543 Irp,
2544 Event);
2545
2546 FdoExtension = FdoDevice->DeviceExtension;
2547
2548 TransferLength = Urb->UrbControlTransfer.TransferBufferLength;
2549 PipeHandle = Urb->UrbControlTransfer.PipeHandle;
2550
2551 if (TransferLength)
2552 {
2553 Mdl = Urb->UrbControlTransfer.TransferBufferMDL;
2554 VirtualAddr = (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
2555
2556 PagesNeed = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddr,
2557 TransferLength);
2558 if (PagesNeed > 0)
2559 {
2560 PagesNeed--;
2561 }
2562 }
2563
2564 if (Urb->UrbHeader.Function == URB_FUNCTION_ISOCH_TRANSFER)
2565 {
2566 DPRINT1("USBPORT_AllocateTransfer: ISOCH_TRANSFER UNIMPLEMENTED. FIXME\n");
2567
2568 //IsoBlockLen = sizeof(USBPORT_ISO_BLOCK) +
2569 // Urb->UrbIsochronousTransfer.NumberOfPackets *
2570 // sizeof(USBPORT_ISO_BLOCK_PACKET);
2571 }
2572
2573 PortTransferLength = sizeof(USBPORT_TRANSFER) +
2574 PagesNeed * sizeof(USBPORT_SCATTER_GATHER_ELEMENT) +
2575 IsoBlockLen;
2576
2577 FullTransferLength = PortTransferLength +
2578 FdoExtension->MiniPortInterface->Packet.MiniPortTransferSize;
2579
2580 Transfer = ExAllocatePoolWithTag(NonPagedPool,
2581 FullTransferLength,
2582 USB_PORT_TAG);
2583
2584 if (!Transfer)
2585 {
2586 DPRINT1("USBPORT_AllocateTransfer: Transfer not allocated!\n");
2587 return USBD_STATUS_INSUFFICIENT_RESOURCES;
2588 }
2589
2590 RtlZeroMemory(Transfer, FullTransferLength);
2591
2592 Transfer->Irp = Irp;
2593 Transfer->Urb = Urb;
2594 Transfer->Endpoint = PipeHandle->Endpoint;
2595 Transfer->Event = Event;
2596 Transfer->PortTransferLength = PortTransferLength;
2597 Transfer->FullTransferLength = FullTransferLength;
2598 Transfer->IsoBlockPtr = NULL;
2599 Transfer->Period = 0;
2600 Transfer->ParentTransfer = Transfer;
2601
2602 if (IsoBlockLen)
2603 {
2604 Transfer->IsoBlockPtr = (PVOID)((ULONG_PTR)Transfer +
2605 PortTransferLength - IsoBlockLen);
2606
2607 Transfer->Period = PipeHandle->Endpoint->EndpointProperties.Period;
2608 Transfer->Flags |= TRANSFER_FLAG_ISO;
2609 }
2610
2611 Transfer->MiniportTransfer = (PVOID)((ULONG_PTR)Transfer +
2612 PortTransferLength);
2613
2614 KeInitializeSpinLock(&Transfer->TransferSpinLock);
2615
2616 Urb->UrbControlTransfer.hca.Reserved8[0] = Transfer;
2617 Urb->UrbHeader.UsbdFlags |= USBD_FLAG_ALLOCATED_TRANSFER;
2618
2619 USBDStatus = USBD_STATUS_SUCCESS;
2620
2621 DPRINT_CORE("USBPORT_AllocateTransfer: return USBDStatus - %x\n",
2622 USBDStatus);
2623
2624 return USBDStatus;
2625 }
2626
2627 NTSTATUS
2628 NTAPI
2629 USBPORT_Dispatch(IN PDEVICE_OBJECT DeviceObject,
2630 IN PIRP Irp)
2631 {
2632 PUSBPORT_COMMON_DEVICE_EXTENSION DeviceExtension;
2633 PIO_STACK_LOCATION IoStack;
2634 NTSTATUS Status = STATUS_SUCCESS;
2635
2636 DeviceExtension = DeviceObject->DeviceExtension;
2637 IoStack = IoGetCurrentIrpStackLocation(Irp);
2638
2639 if (DeviceExtension->PnpStateFlags & USBPORT_PNP_STATE_FAILED)
2640 {
2641 DPRINT1("USBPORT_Dispatch: USBPORT_PNP_STATE_FAILED\n");
2642 DbgBreakPoint();
2643 }
2644
2645 switch (IoStack->MajorFunction)
2646 {
2647 case IRP_MJ_DEVICE_CONTROL:
2648 if (DeviceExtension->IsPDO)
2649 {
2650 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2651 IoStack->MajorFunction,
2652 IoStack->MinorFunction);
2653
2654 Status = USBPORT_PdoDeviceControl(DeviceObject, Irp);
2655 }
2656 else
2657 {
2658 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2659 IoStack->MajorFunction,
2660 IoStack->MinorFunction);
2661
2662 Status = USBPORT_FdoDeviceControl(DeviceObject, Irp);
2663 }
2664
2665 break;
2666
2667 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
2668 if (DeviceExtension->IsPDO)
2669 {
2670 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2671 IoStack->MajorFunction,
2672 IoStack->MinorFunction);
2673
2674 Status = USBPORT_PdoInternalDeviceControl(DeviceObject, Irp);
2675 }
2676 else
2677 {
2678 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_INTERNAL_DEVICE_CONTROL. Major - %d, Minor - %d\n",
2679 IoStack->MajorFunction,
2680 IoStack->MinorFunction);
2681
2682 Status = USBPORT_FdoInternalDeviceControl(DeviceObject, Irp);
2683 }
2684
2685 break;
2686
2687 case IRP_MJ_POWER:
2688 if (DeviceExtension->IsPDO)
2689 {
2690 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
2691 IoStack->MajorFunction,
2692 IoStack->MinorFunction);
2693
2694 Status = USBPORT_PdoPower(DeviceObject, Irp);
2695 }
2696 else
2697 {
2698 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_POWER. Major - %d, Minor - %d\n",
2699 IoStack->MajorFunction,
2700 IoStack->MinorFunction);
2701
2702 Status = USBPORT_FdoPower(DeviceObject, Irp);
2703 }
2704
2705 break;
2706
2707 case IRP_MJ_SYSTEM_CONTROL:
2708 if (DeviceExtension->IsPDO)
2709 {
2710 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
2711 IoStack->MajorFunction,
2712 IoStack->MinorFunction);
2713
2714 Status = Irp->IoStatus.Status;
2715 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2716 }
2717 else
2718 {
2719 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_SYSTEM_CONTROL. Major - %d, Minor - %d\n",
2720 IoStack->MajorFunction,
2721 IoStack->MinorFunction);
2722
2723 IoSkipCurrentIrpStackLocation(Irp);
2724 Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
2725 }
2726
2727 break;
2728
2729 case IRP_MJ_PNP:
2730 if (DeviceExtension->IsPDO)
2731 {
2732 DPRINT("USBPORT_Dispatch: PDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
2733 IoStack->MajorFunction,
2734 IoStack->MinorFunction);
2735
2736 Status = USBPORT_PdoPnP(DeviceObject, Irp);
2737 }
2738 else
2739 {
2740 DPRINT("USBPORT_Dispatch: FDO IRP_MJ_PNP. Major - %d, Minor - %d\n",
2741 IoStack->MajorFunction,
2742 IoStack->MinorFunction);
2743
2744 Status = USBPORT_FdoPnP(DeviceObject, Irp);
2745 }
2746
2747 break;
2748
2749 case IRP_MJ_CREATE:
2750 case IRP_MJ_CLOSE:
2751 DPRINT("USBPORT_Dispatch: IRP_MJ_CREATE | IRP_MJ_CLOSE\n");
2752 Irp->IoStatus.Status = Status;
2753 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2754 break;
2755
2756 default:
2757 if (DeviceExtension->IsPDO)
2758 {
2759 DPRINT("USBPORT_Dispatch: PDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
2760 IoStack->MajorFunction,
2761 IoStack->MinorFunction);
2762 }
2763 else
2764 {
2765 DPRINT("USBPORT_Dispatch: FDO unhandled IRP_MJ_???. Major - %d, Minor - %d\n",
2766 IoStack->MajorFunction,
2767 IoStack->MinorFunction);
2768 }
2769
2770 Status = STATUS_INVALID_DEVICE_REQUEST;
2771 Irp->IoStatus.Status = Status;
2772 IoCompleteRequest(Irp, IO_NO_INCREMENT);
2773 break;
2774 }
2775
2776 DPRINT("USBPORT_Dispatch: Status - %x\n", Status);
2777 return Status;
2778 }
2779
2780 ULONG
2781 NTAPI
2782 USBPORT_GetHciMn(VOID)
2783 {
2784 return USBPORT_HCI_MN;
2785 }
2786
2787 NTSTATUS
2788 NTAPI
2789 USBPORT_RegisterUSBPortDriver(IN PDRIVER_OBJECT DriverObject,
2790 IN ULONG Version,
2791 IN PUSBPORT_REGISTRATION_PACKET RegPacket)
2792 {
2793 PUSBPORT_MINIPORT_INTERFACE MiniPortInterface;
2794
2795 DPRINT("USBPORT_RegisterUSBPortDriver: DriverObject - %p, Version - %p, RegPacket - %p\n",
2796 DriverObject,
2797 Version,
2798 RegPacket);
2799
2800 DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_MINIPORT_INTERFACE) - %x\n",
2801 sizeof(USBPORT_MINIPORT_INTERFACE));
2802
2803 DPRINT("USBPORT_RegisterUSBPortDriver: sizeof(USBPORT_DEVICE_EXTENSION) - %x\n",
2804 sizeof(USBPORT_DEVICE_EXTENSION));
2805
2806 if (Version < USB10_MINIPORT_INTERFACE_VERSION)
2807 {
2808 return STATUS_UNSUCCESSFUL;
2809 }
2810
2811 if (!USBPORT_Initialized)
2812 {
2813 InitializeListHead(&USBPORT_MiniPortDrivers);
2814 InitializeListHead(&USBPORT_USB1FdoList);
2815 InitializeListHead(&USBPORT_USB2FdoList);
2816
2817 KeInitializeSpinLock(&USBPORT_SpinLock);
2818 USBPORT_Initialized = TRUE;
2819 }
2820
2821 MiniPortInterface = ExAllocatePoolWithTag(NonPagedPool,
2822 sizeof(USBPORT_MINIPORT_INTERFACE),
2823 USB_PORT_TAG);
2824 if (!MiniPortInterface)
2825 {
2826 return STATUS_INSUFFICIENT_RESOURCES;
2827 }
2828
2829 RtlZeroMemory(MiniPortInterface, sizeof(USBPORT_MINIPORT_INTERFACE));
2830
2831 MiniPortInterface->DriverObject = DriverObject;
2832 MiniPortInterface->DriverUnload = DriverObject->DriverUnload;
2833 MiniPortInterface->Version = Version;
2834
2835 ExInterlockedInsertTailList(&USBPORT_MiniPortDrivers,
2836 &MiniPortInterface->DriverLink,
2837 &USBPORT_SpinLock);
2838
2839 DriverObject->DriverExtension->AddDevice = USBPORT_AddDevice;
2840 DriverObject->DriverUnload = USBPORT_Unload;
2841
2842 DriverObject->MajorFunction[IRP_MJ_CREATE] = USBPORT_Dispatch;
2843 DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBPORT_Dispatch;
2844 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBPORT_Dispatch;
2845 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = USBPORT_Dispatch;
2846 DriverObject->MajorFunction[IRP_MJ_PNP] = USBPORT_Dispatch;
2847 DriverObject->MajorFunction[IRP_MJ_POWER] = USBPORT_Dispatch;
2848 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = USBPORT_Dispatch;
2849
2850 RegPacket->UsbPortDbgPrint = USBPORT_DbgPrint;
2851 RegPacket->UsbPortTestDebugBreak = USBPORT_TestDebugBreak;
2852 RegPacket->UsbPortAssertFailure = USBPORT_AssertFailure;
2853 RegPacket->UsbPortGetMiniportRegistryKeyValue = USBPORT_GetMiniportRegistryKeyValue;
2854 RegPacket->UsbPortInvalidateRootHub = USBPORT_InvalidateRootHub;
2855 RegPacket->UsbPortInvalidateEndpoint = USBPORT_InvalidateEndpoint;
2856 RegPacket->UsbPortCompleteTransfer = USBPORT_MiniportCompleteTransfer;
2857 RegPacket->UsbPortCompleteIsoTransfer = USBPORT_CompleteIsoTransfer;
2858 RegPacket->UsbPortLogEntry = USBPORT_LogEntry;
2859 RegPacket->UsbPortGetMappedVirtualAddress = USBPORT_GetMappedVirtualAddress;
2860 RegPacket->UsbPortRequestAsyncCallback = USBPORT_RequestAsyncCallback;
2861 RegPacket->UsbPortReadWriteConfigSpace = USBPORT_ReadWriteConfigSpace;
2862 RegPacket->UsbPortWait = USBPORT_Wait;
2863 RegPacket->UsbPortInvalidateController = USBPORT_InvalidateController;
2864 RegPacket->UsbPortBugCheck = USBPORT_BugCheck;
2865 RegPacket->UsbPortNotifyDoubleBuffer = USBPORT_NotifyDoubleBuffer;
2866
2867 RtlCopyMemory(&MiniPortInterface->Packet,
2868 RegPacket,
2869 sizeof(USBPORT_REGISTRATION_PACKET));
2870
2871 return STATUS_SUCCESS;
2872 }
2873
2874 NTSTATUS
2875 NTAPI
2876 DriverEntry(IN PDRIVER_OBJECT DriverObject,
2877 IN PUNICODE_STRING RegistryPath)
2878 {
2879 return STATUS_SUCCESS;
2880 }