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