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