xref: /reactos/drivers/usb/usbport/queue.c (revision 0c2cdcae)
1 /*
2  * PROJECT:     ReactOS USB Port Driver
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     USBPort queue implementation
5  * COPYRIGHT:   Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6  */
7 
8 #include "usbport.h"
9 
10 #define NDEBUG
11 #include <debug.h>
12 
13 #define NDEBUG_USBPORT_CORE
14 #define NDEBUG_USBPORT_QUEUE
15 #define NDEBUG_USBPORT_URB
16 #include "usbdebug.h"
17 
18 VOID
19 NTAPI
USBPORT_InsertIdleIrp(IN PIO_CSQ Csq,IN PIRP Irp)20 USBPORT_InsertIdleIrp(IN PIO_CSQ Csq,
21                       IN PIRP Irp)
22 {
23     PUSBPORT_DEVICE_EXTENSION FdoExtension;
24 
25     DPRINT_QUEUE("USBPORT_InsertIdleIrp: Irp - %p\n", Irp);
26 
27     FdoExtension = CONTAINING_RECORD(Csq,
28                                      USBPORT_DEVICE_EXTENSION,
29                                      IdleIoCsq);
30 
31     InsertTailList(&FdoExtension->IdleIrpList,
32                    &Irp->Tail.Overlay.ListEntry);
33 }
34 
35 VOID
36 NTAPI
USBPORT_RemoveIdleIrp(IN PIO_CSQ Csq,IN PIRP Irp)37 USBPORT_RemoveIdleIrp(IN PIO_CSQ Csq,
38                       IN PIRP Irp)
39 {
40     DPRINT_QUEUE("USBPORT_RemoveIdleIrp: Irp - %p\n", Irp);
41     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
42 }
43 
44 PIRP
45 NTAPI
USBPORT_PeekNextIdleIrp(IN PIO_CSQ Csq,IN PIRP Irp,IN PVOID PeekContext)46 USBPORT_PeekNextIdleIrp(IN PIO_CSQ Csq,
47                         IN PIRP Irp,
48                         IN PVOID PeekContext)
49 {
50     PUSBPORT_DEVICE_EXTENSION FdoExtension;
51     PLIST_ENTRY NextEntry;
52     PLIST_ENTRY ListHead;
53     PIRP NextIrp = NULL;
54 
55     DPRINT_QUEUE("USBPORT_PeekNextIdleIrp: Irp - %p, PeekContext - %p\n",
56                  Irp,
57                  PeekContext);
58 
59     FdoExtension = CONTAINING_RECORD(Csq,
60                                      USBPORT_DEVICE_EXTENSION,
61                                      IdleIoCsq);
62 
63     ListHead = &FdoExtension->IdleIrpList;
64 
65     if (Irp)
66     {
67         NextEntry = Irp->Tail.Overlay.ListEntry.Flink;
68     }
69     else
70     {
71         NextEntry = ListHead->Flink;
72     }
73 
74     while (NextEntry != ListHead)
75     {
76         NextIrp = CONTAINING_RECORD(NextEntry,
77                                     IRP,
78                                     Tail.Overlay.ListEntry);
79 
80         if (!PeekContext)
81             break;
82 
83         NextEntry = NextEntry->Flink;
84     }
85 
86     return NextIrp;
87 }
88 
89 VOID
90 NTAPI
USBPORT_AcquireIdleLock(IN PIO_CSQ Csq,IN PKIRQL Irql)91 USBPORT_AcquireIdleLock(IN PIO_CSQ Csq,
92                         IN PKIRQL Irql)
93 {
94     PUSBPORT_DEVICE_EXTENSION FdoExtension;
95 
96     DPRINT_QUEUE("USBPORT_AcquireIdleLock: ... \n");
97 
98     FdoExtension = CONTAINING_RECORD(Csq,
99                                      USBPORT_DEVICE_EXTENSION,
100                                      IdleIoCsq);
101 
102     KeAcquireSpinLock(&FdoExtension->IdleIoCsqSpinLock, Irql);
103 }
104 
105 VOID
106 NTAPI
USBPORT_ReleaseIdleLock(IN PIO_CSQ Csq,IN KIRQL Irql)107 USBPORT_ReleaseIdleLock(IN PIO_CSQ Csq,
108                         IN KIRQL Irql)
109 {
110     PUSBPORT_DEVICE_EXTENSION FdoExtension;
111 
112     DPRINT_QUEUE("USBPORT_ReleaseIdleLock: ... \n");
113 
114     FdoExtension = CONTAINING_RECORD(Csq,
115                                      USBPORT_DEVICE_EXTENSION,
116                                      IdleIoCsq);
117 
118     KeReleaseSpinLock(&FdoExtension->IdleIoCsqSpinLock, Irql);
119 }
120 
121 VOID
122 NTAPI
USBPORT_CompleteCanceledIdleIrp(IN PIO_CSQ Csq,IN PIRP Irp)123 USBPORT_CompleteCanceledIdleIrp(IN PIO_CSQ Csq,
124                                 IN PIRP Irp)
125 {
126     PUSBPORT_DEVICE_EXTENSION FdoExtension;
127 
128     DPRINT_QUEUE("USBPORT_CompleteCanceledIdleIrp: ... \n");
129 
130     FdoExtension = CONTAINING_RECORD(Csq,
131                                      USBPORT_DEVICE_EXTENSION,
132                                      IdleIoCsq);
133 
134     InterlockedDecrement(&FdoExtension->IdleLockCounter);
135 
136     Irp->IoStatus.Status = STATUS_CANCELLED;
137     Irp->IoStatus.Information = 0;
138     IoCompleteRequest(Irp, IO_NO_INCREMENT);
139 }
140 
141 VOID
142 NTAPI
USBPORT_InsertBadRequest(IN PIO_CSQ Csq,IN PIRP Irp)143 USBPORT_InsertBadRequest(IN PIO_CSQ Csq,
144                          IN PIRP Irp)
145 {
146     PUSBPORT_DEVICE_EXTENSION FdoExtension;
147 
148     DPRINT_QUEUE("USBPORT_InsertBadRequest: Irp - %p\n", Irp);
149 
150     FdoExtension = CONTAINING_RECORD(Csq,
151                                      USBPORT_DEVICE_EXTENSION,
152                                      BadRequestIoCsq);
153 
154     InsertTailList(&FdoExtension->BadRequestList,
155                    &Irp->Tail.Overlay.ListEntry);
156 }
157 
158 VOID
159 NTAPI
USBPORT_RemoveBadRequest(IN PIO_CSQ Csq,IN PIRP Irp)160 USBPORT_RemoveBadRequest(IN PIO_CSQ Csq,
161                          IN PIRP Irp)
162 {
163     DPRINT_QUEUE("USBPORT_RemoveBadRequest: Irp - %p\n", Irp);
164     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
165 }
166 
167 PIRP
168 NTAPI
USBPORT_PeekNextBadRequest(IN PIO_CSQ Csq,IN PIRP Irp,IN PVOID PeekContext)169 USBPORT_PeekNextBadRequest(IN PIO_CSQ Csq,
170                            IN PIRP Irp,
171                            IN PVOID PeekContext)
172 {
173     PUSBPORT_DEVICE_EXTENSION FdoExtension;
174     PLIST_ENTRY NextEntry;
175     PLIST_ENTRY ListHead;
176     PIRP NextIrp = NULL;
177 
178     DPRINT_QUEUE("USBPORT_PeekNextBadRequest: Irp - %p, PeekContext - %p\n",
179                  Irp,
180                  PeekContext);
181 
182     FdoExtension = CONTAINING_RECORD(Csq,
183                                      USBPORT_DEVICE_EXTENSION,
184                                      BadRequestIoCsq);
185 
186     ListHead = &FdoExtension->BadRequestList;
187 
188     if (Irp)
189     {
190         NextEntry = Irp->Tail.Overlay.ListEntry.Flink;
191     }
192     else
193     {
194         NextEntry = ListHead->Flink;
195     }
196 
197     while (NextEntry != ListHead)
198     {
199         NextIrp = CONTAINING_RECORD(NextEntry,
200                                     IRP,
201                                     Tail.Overlay.ListEntry);
202 
203         if (!PeekContext)
204             break;
205 
206         NextEntry = NextEntry->Flink;
207     }
208 
209     return NextIrp;
210 }
211 
212 VOID
213 NTAPI
USBPORT_AcquireBadRequestLock(IN PIO_CSQ Csq,IN PKIRQL Irql)214 USBPORT_AcquireBadRequestLock(IN PIO_CSQ Csq,
215                               IN PKIRQL Irql)
216 {
217     PUSBPORT_DEVICE_EXTENSION FdoExtension;
218 
219     DPRINT_QUEUE("USBPORT_AcquireBadRequestLock: ... \n");
220 
221     FdoExtension = CONTAINING_RECORD(Csq,
222                                      USBPORT_DEVICE_EXTENSION,
223                                      BadRequestIoCsq);
224 
225     KeAcquireSpinLock(&FdoExtension->BadRequestIoCsqSpinLock, Irql);
226 }
227 
228 VOID
229 NTAPI
USBPORT_ReleaseBadRequestLock(IN PIO_CSQ Csq,IN KIRQL Irql)230 USBPORT_ReleaseBadRequestLock(IN PIO_CSQ Csq,
231                               IN KIRQL Irql)
232 {
233     PUSBPORT_DEVICE_EXTENSION FdoExtension;
234 
235     DPRINT_QUEUE("USBPORT_ReleaseBadRequestLock: ... \n");
236 
237     FdoExtension = CONTAINING_RECORD(Csq,
238                                      USBPORT_DEVICE_EXTENSION,
239                                      BadRequestIoCsq);
240 
241     KeReleaseSpinLock(&FdoExtension->BadRequestIoCsqSpinLock, Irql);
242 }
243 
244 VOID
245 NTAPI
USBPORT_CompleteCanceledBadRequest(IN PIO_CSQ Csq,IN PIRP Irp)246 USBPORT_CompleteCanceledBadRequest(IN PIO_CSQ Csq,
247                                    IN PIRP Irp)
248 {
249     PUSBPORT_DEVICE_EXTENSION FdoExtension;
250 
251     DPRINT_QUEUE("USBPORT_CompleteCanceledBadRequest: Irp - %p\n", Irp);
252 
253     FdoExtension = CONTAINING_RECORD(Csq,
254                                      USBPORT_DEVICE_EXTENSION,
255                                      BadRequestIoCsq);
256 
257     InterlockedDecrement(&FdoExtension->BadRequestLockCounter);
258 
259     Irp->IoStatus.Status = STATUS_CANCELLED;
260     Irp->IoStatus.Information = 0;
261     IoCompleteRequest(Irp, IO_NO_INCREMENT);
262 }
263 
264 VOID
265 NTAPI
USBPORT_InsertIrpInTable(IN PUSBPORT_IRP_TABLE IrpTable,IN PIRP Irp)266 USBPORT_InsertIrpInTable(IN PUSBPORT_IRP_TABLE IrpTable,
267                          IN PIRP Irp)
268 {
269     ULONG ix;
270 
271     DPRINT_CORE("USBPORT_InsertIrpInTable: IrpTable - %p, Irp - %p\n",
272                 IrpTable,
273                 Irp);
274 
275     ASSERT(IrpTable != NULL);
276 
277     while (TRUE)
278     {
279         for (ix = 0; ix < 0x200; ix++)
280         {
281             if (IrpTable->irp[ix] == NULL)
282             {
283                 IrpTable->irp[ix] = Irp;
284 
285                 if (ix > 0)
286                 {
287                     DPRINT_CORE("USBPORT_InsertIrpInTable: ix - %x\n", ix);
288                 }
289 
290                 return;
291             }
292         }
293 
294         if (ix != 0x200)
295         {
296             KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
297         }
298 
299         IrpTable->LinkNextTable = ExAllocatePoolWithTag(NonPagedPool,
300                                                         sizeof(USBPORT_IRP_TABLE),
301                                                         USB_PORT_TAG);
302 
303         if (IrpTable->LinkNextTable == NULL)
304         {
305             KeBugCheckEx(BUGCODE_USB_DRIVER, 1, 0, 0, 0);
306         }
307 
308         RtlZeroMemory(IrpTable->LinkNextTable, sizeof(USBPORT_IRP_TABLE));
309 
310         IrpTable = IrpTable->LinkNextTable;
311     }
312 }
313 
314 PIRP
315 NTAPI
USBPORT_RemoveIrpFromTable(IN PUSBPORT_IRP_TABLE IrpTable,IN PIRP Irp)316 USBPORT_RemoveIrpFromTable(IN PUSBPORT_IRP_TABLE IrpTable,
317                            IN PIRP Irp)
318 {
319     ULONG ix;
320 
321     DPRINT_CORE("USBPORT_RemoveIrpFromTable: IrpTable - %p, Irp - %p\n",
322                 IrpTable,
323                 Irp);
324 
325     ASSERT(IrpTable != NULL);
326 
327     while (TRUE)
328     {
329         for (ix = 0; ix < 0x200; ix++)
330         {
331             if (IrpTable->irp[ix] == Irp)
332             {
333                 IrpTable->irp[ix] = NULL;
334 
335                 if (ix > 0)
336                 {
337                     DPRINT_CORE("USBPORT_RemoveIrpFromTable: ix - %x\n", ix);
338                 }
339 
340                 return Irp;
341             }
342         }
343 
344         if (IrpTable->LinkNextTable == NULL)
345             break;
346 
347         IrpTable = IrpTable->LinkNextTable;
348         continue;
349     }
350 
351     DPRINT1("USBPORT_RemoveIrpFromTable: return NULL. ix - %x\n", ix);
352     return NULL;
353 }
354 
355 PIRP
356 NTAPI
USBPORT_RemoveActiveTransferIrp(IN PDEVICE_OBJECT FdoDevice,IN PIRP Irp)357 USBPORT_RemoveActiveTransferIrp(IN PDEVICE_OBJECT FdoDevice,
358                                 IN PIRP Irp)
359 {
360     PUSBPORT_DEVICE_EXTENSION FdoExtension;
361 
362     DPRINT_CORE("USBPORT_RemoveActiveTransferIrp: Irp - %p\n", Irp);
363     FdoExtension = FdoDevice->DeviceExtension;
364     return USBPORT_RemoveIrpFromTable(FdoExtension->ActiveIrpTable, Irp);
365 }
366 
367 PIRP
368 NTAPI
USBPORT_RemovePendingTransferIrp(IN PDEVICE_OBJECT FdoDevice,IN PIRP Irp)369 USBPORT_RemovePendingTransferIrp(IN PDEVICE_OBJECT FdoDevice,
370                                  IN PIRP Irp)
371 {
372     PUSBPORT_DEVICE_EXTENSION FdoExtension;
373 
374     DPRINT_CORE("USBPORT_RemovePendingTransferIrp: Irp - %p\n", Irp);
375     FdoExtension = FdoDevice->DeviceExtension;
376     return USBPORT_RemoveIrpFromTable(FdoExtension->PendingIrpTable, Irp);
377 }
378 
379 VOID
380 NTAPI
USBPORT_FindUrbInIrpTable(IN PUSBPORT_IRP_TABLE IrpTable,IN PURB Urb,IN PIRP Irp)381 USBPORT_FindUrbInIrpTable(IN PUSBPORT_IRP_TABLE IrpTable,
382                           IN PURB Urb,
383                           IN PIRP Irp)
384 {
385     ULONG ix;
386     PIRP irp;
387     PURB urbIn;
388 
389     DPRINT_CORE("USBPORT_FindUrbInIrpTable: IrpTable - %p, Urb - %p, Irp - %p\n",
390                 IrpTable,
391                 Urb,
392                 Irp);
393 
394     ASSERT(IrpTable != NULL);
395 
396     do
397     {
398         for (ix = 0; ix < 0x200; ix++)
399         {
400             irp = IrpTable->irp[ix];
401 
402             if (irp)
403             {
404                 urbIn = URB_FROM_IRP(irp);
405 
406                 if (urbIn == Urb)
407                 {
408                     if (irp == Irp)
409                     {
410                         KeBugCheckEx(BUGCODE_USB_DRIVER,
411                                      4,
412                                      (ULONG_PTR)irp,
413                                      (ULONG_PTR)urbIn,
414                                      0);
415                     }
416 
417                     KeBugCheckEx(BUGCODE_USB_DRIVER,
418                                  2,
419                                  (ULONG_PTR)irp,
420                                  (ULONG_PTR)Irp,
421                                  (ULONG_PTR)urbIn);
422                 }
423             }
424         }
425 
426         IrpTable = IrpTable->LinkNextTable;
427     }
428     while (IrpTable);
429 }
430 
431 PIRP
432 NTAPI
USBPORT_FindIrpInTable(IN PUSBPORT_IRP_TABLE IrpTable,IN PIRP Irp)433 USBPORT_FindIrpInTable(IN PUSBPORT_IRP_TABLE IrpTable,
434                        IN PIRP Irp)
435 {
436     ULONG ix;
437     PIRP irp;
438 
439     DPRINT_CORE("USBPORT_FindIrpInTable: IrpTable - %p, Irp - %p\n",
440                 IrpTable,
441                 Irp);
442 
443     ASSERT(IrpTable != NULL);
444 
445     do
446     {
447         for (ix = 0; ix < 0x200; ix++)
448         {
449             irp = IrpTable->irp[ix];
450 
451             if (irp && irp == Irp)
452             {
453                 return irp;
454             }
455         }
456 
457         IrpTable = IrpTable->LinkNextTable;
458     }
459     while (IrpTable->LinkNextTable);
460 
461     DPRINT_CORE("USBPORT_FindIrpInTable: Not found!!!\n");
462     return NULL;
463 }
464 
465 PIRP
466 NTAPI
USBPORT_FindActiveTransferIrp(IN PDEVICE_OBJECT FdoDevice,IN PIRP Irp)467 USBPORT_FindActiveTransferIrp(IN PDEVICE_OBJECT FdoDevice,
468                               IN PIRP Irp)
469 {
470     PUSBPORT_DEVICE_EXTENSION FdoExtension;
471 
472     DPRINT_CORE("USBPORT_FindActiveTransferIrp: Irp - %p\n", Irp);
473     FdoExtension = FdoDevice->DeviceExtension;
474     return USBPORT_FindIrpInTable(FdoExtension->ActiveIrpTable, Irp);
475 }
476 
477 VOID
478 NTAPI
USBPORT_CancelPendingTransferIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)479 USBPORT_CancelPendingTransferIrp(IN PDEVICE_OBJECT DeviceObject,
480                                  IN PIRP Irp)
481 {
482     PURB Urb;
483     PUSBPORT_TRANSFER Transfer;
484     PUSBPORT_ENDPOINT Endpoint;
485     PDEVICE_OBJECT FdoDevice;
486     PUSBPORT_DEVICE_EXTENSION FdoExtension;
487     KIRQL OldIrql;
488     PIRP irp;
489 
490     DPRINT_CORE("USBPORT_CancelPendingTransferIrp: DeviceObject - %p, Irp - %p\n",
491                 DeviceObject,
492                 Irp);
493 
494     Urb = URB_FROM_IRP(Irp);
495     Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
496     Endpoint = Transfer->Endpoint;
497 
498     FdoDevice = Endpoint->FdoDevice;
499     FdoExtension = DeviceObject->DeviceExtension;
500 
501     IoReleaseCancelSpinLock(Irp->CancelIrql);
502 
503     KeAcquireSpinLock(&FdoExtension->FlushPendingTransferSpinLock, &OldIrql);
504 
505     irp = USBPORT_RemovePendingTransferIrp(FdoDevice, Irp);
506 
507     if (!irp)
508     {
509         KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
510                           OldIrql);
511         return;
512     }
513 
514     KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
515 
516     RemoveEntryList(&Transfer->TransferLink);
517 
518     Transfer->TransferLink.Flink = NULL;
519     Transfer->TransferLink.Blink = NULL;
520 
521     KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
522     KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock, OldIrql);
523 
524     USBPORT_CompleteTransfer(Transfer->Urb, USBD_STATUS_CANCELED);
525 }
526 
527 VOID
528 NTAPI
USBPORT_CancelActiveTransferIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)529 USBPORT_CancelActiveTransferIrp(IN PDEVICE_OBJECT DeviceObject,
530                                 IN PIRP Irp)
531 {
532     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
533     PDEVICE_OBJECT FdoDevice;
534     PUSBPORT_DEVICE_EXTENSION FdoExtension;
535     PURB Urb;
536     PUSBPORT_TRANSFER Transfer;
537     PUSBPORT_ENDPOINT Endpoint;
538     PIRP irp;
539     PUSBPORT_TRANSFER SplitTransfer;
540     PLIST_ENTRY Entry;
541     KIRQL OldIrql;
542 
543     DPRINT_CORE("USBPORT_CancelActiveTransferIrp: Irp - %p\n", Irp);
544 
545     PdoExtension = DeviceObject->DeviceExtension;
546     FdoDevice = PdoExtension->FdoDevice;
547     FdoExtension = FdoDevice->DeviceExtension;
548 
549     IoReleaseCancelSpinLock(Irp->CancelIrql);
550 
551     KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
552 
553     irp = USBPORT_FindActiveTransferIrp(FdoDevice, Irp);
554 
555     if (!irp)
556     {
557         KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
558         return;
559     }
560 
561     Urb = URB_FROM_IRP(irp);
562     Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
563     Endpoint = Transfer->Endpoint;
564 
565     DPRINT_CORE("USBPORT_CancelActiveTransferIrp: irp - %p, Urb - %p, Transfer - %p\n",
566                 irp,
567                 Urb,
568                 Transfer);
569 
570     KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
571 
572     Transfer->Flags |= TRANSFER_FLAG_CANCELED;
573 
574     if (Transfer->Flags & TRANSFER_FLAG_PARENT)
575     {
576         KeAcquireSpinLockAtDpcLevel(&Transfer->TransferSpinLock);
577 
578         Entry = Transfer->SplitTransfersList.Flink;
579 
580         while (Entry && Entry != &Transfer->SplitTransfersList)
581         {
582             SplitTransfer = CONTAINING_RECORD(Entry,
583                                               USBPORT_TRANSFER,
584                                               SplitLink);
585 
586             SplitTransfer->Flags |= TRANSFER_FLAG_CANCELED;
587 
588             Entry = Entry->Flink;
589         }
590 
591         KeReleaseSpinLockFromDpcLevel(&Transfer->TransferSpinLock);
592     }
593 
594     KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
595     KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
596 
597     USBPORT_InvalidateEndpointHandler(FdoDevice,
598                                       Endpoint,
599                                       INVALIDATE_ENDPOINT_WORKER_THREAD);
600     return;
601 }
602 
603 VOID
604 NTAPI
USBPORT_FlushAbortList(IN PUSBPORT_ENDPOINT Endpoint)605 USBPORT_FlushAbortList(IN PUSBPORT_ENDPOINT Endpoint)
606 {
607     PLIST_ENTRY Entry;
608     PUSBPORT_TRANSFER Transfer;
609     PLIST_ENTRY AbortList;
610     LIST_ENTRY List;
611     NTSTATUS Status;
612     PIRP Irp;
613     PURB Urb;
614     PUSBPORT_DEVICE_HANDLE DeviceHandle = NULL;
615 
616     DPRINT_CORE("USBPORT_FlushAbortList: Endpoint - %p\n", Endpoint);
617 
618     InitializeListHead(&List);
619 
620     KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
621 
622     if (IsListEmpty(&Endpoint->AbortList))
623     {
624         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
625                           Endpoint->EndpointOldIrql);
626         return;
627     }
628 
629     Entry = Endpoint->PendingTransferList.Flink;
630 
631     while (Entry && Entry != &Endpoint->PendingTransferList)
632     {
633         Transfer = CONTAINING_RECORD(Entry,
634                                      USBPORT_TRANSFER,
635                                      TransferLink);
636 
637         if (Transfer->Flags & TRANSFER_FLAG_ABORTED)
638         {
639             DPRINT_CORE("USBPORT_FlushAbortList: Aborted PendingTransfer  - %p\n",
640                         Transfer);
641 
642             KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
643                               Endpoint->EndpointOldIrql);
644             return;
645         }
646 
647         Entry = Transfer->TransferLink.Flink;
648     }
649 
650     Entry = Endpoint->TransferList.Flink;
651 
652     while (Entry && Entry != &Endpoint->TransferList)
653     {
654         Transfer = CONTAINING_RECORD(Entry,
655                                      USBPORT_TRANSFER,
656                                      TransferLink);
657 
658         if (Transfer->Flags & TRANSFER_FLAG_ABORTED)
659         {
660             DPRINT_CORE("USBPORT_FlushAbortList: Aborted ActiveTransfer - %p\n",
661                         Transfer);
662 
663             KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
664                               Endpoint->EndpointOldIrql);
665             return;
666         }
667 
668         Entry = Transfer->TransferLink.Flink;
669     }
670 
671     AbortList = &Endpoint->AbortList;
672 
673     while (!IsListEmpty(AbortList))
674     {
675         //DbgBreakPoint();
676 
677         Irp = CONTAINING_RECORD(AbortList->Flink,
678                                 IRP,
679                                 Tail.Overlay.ListEntry);
680 
681         RemoveHeadList(AbortList);
682         InsertTailList(&List, &Irp->Tail.Overlay.ListEntry);
683     }
684 
685     KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
686 
687     while (!IsListEmpty(&List))
688     {
689         //DbgBreakPoint();
690 
691         Irp = CONTAINING_RECORD(List.Flink,
692                                 IRP,
693                                 Tail.Overlay.ListEntry);
694 
695         RemoveHeadList(&List);
696 
697         Urb = URB_FROM_IRP(Irp);
698 
699         DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
700         InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
701 
702         Status = USBPORT_USBDStatusToNtStatus(Urb, USBD_STATUS_SUCCESS);
703 
704         DPRINT_CORE("USBPORT_FlushAbortList: complete Irp - %p\n", Irp);
705 
706         Irp->IoStatus.Status = Status;
707         Irp->IoStatus.Information = 0;
708         IoCompleteRequest(Irp, IO_NO_INCREMENT);
709     }
710 }
711 
712 VOID
713 NTAPI
USBPORT_FlushCancelList(IN PUSBPORT_ENDPOINT Endpoint)714 USBPORT_FlushCancelList(IN PUSBPORT_ENDPOINT Endpoint)
715 {
716     PDEVICE_OBJECT FdoDevice;
717     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
718     PUSBPORT_TRANSFER Transfer;
719     PIRP Irp;
720     KIRQL OldIrql;
721     KIRQL PrevIrql;
722 
723     DPRINT_CORE("USBPORT_FlushCancelList: ... \n");
724 
725     FdoDevice = Endpoint->FdoDevice;
726     FdoExtension = FdoDevice->DeviceExtension;
727 
728     KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
729     KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
730 
731     while (!IsListEmpty(&Endpoint->CancelList))
732     {
733         Transfer = CONTAINING_RECORD(Endpoint->CancelList.Flink,
734                                      USBPORT_TRANSFER,
735                                      TransferLink);
736 
737         RemoveHeadList(&Endpoint->CancelList);
738 
739         Irp = Transfer->Irp;
740 
741         if (Irp)
742         {
743             DPRINT("USBPORT_FlushCancelList: Irp - %p\n", Irp);
744 
745             IoAcquireCancelSpinLock(&PrevIrql);
746             IoSetCancelRoutine(Irp, NULL);
747             IoReleaseCancelSpinLock(PrevIrql);
748 
749             USBPORT_RemoveActiveTransferIrp(FdoDevice, Irp);
750         }
751 
752         KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
753         KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
754 
755         if (Endpoint->Flags & ENDPOINT_FLAG_NUKE)
756         {
757             USBPORT_CompleteTransfer(Transfer->Urb, USBD_STATUS_DEVICE_GONE);
758         }
759         else
760         {
761             if (Transfer->Flags & TRANSFER_FLAG_DEVICE_GONE)
762             {
763                 USBPORT_CompleteTransfer(Transfer->Urb,
764                                          USBD_STATUS_DEVICE_GONE);
765             }
766             else
767             {
768                 USBPORT_CompleteTransfer(Transfer->Urb,
769                                          USBD_STATUS_CANCELED);
770             }
771         }
772 
773         KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
774         KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
775     }
776 
777     KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
778     KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
779 
780     USBPORT_FlushAbortList(Endpoint);
781 }
782 
783 VOID
784 NTAPI
USBPORT_FlushPendingTransfers(IN PUSBPORT_ENDPOINT Endpoint)785 USBPORT_FlushPendingTransfers(IN PUSBPORT_ENDPOINT Endpoint)
786 {
787     PDEVICE_OBJECT FdoDevice;
788     PUSBPORT_DEVICE_EXTENSION FdoExtension;
789     BOOLEAN IsMapTransfer;
790     BOOLEAN IsEnd = FALSE;
791     PLIST_ENTRY List;
792     PUSBPORT_TRANSFER Transfer;
793     PURB Urb;
794     PIRP Irp;
795     KIRQL OldIrql;
796     BOOLEAN Result;
797 
798     DPRINT_CORE("USBPORT_FlushPendingTransfers: Endpoint - %p\n", Endpoint);
799 
800     FdoDevice = Endpoint->FdoDevice;
801     FdoExtension = FdoDevice->DeviceExtension;
802 
803     if (InterlockedCompareExchange(&Endpoint->FlushPendingLock, 1, 0))
804     {
805         DPRINT_CORE("USBPORT_FlushPendingTransfers: Endpoint Locked \n");
806         return;
807     }
808 
809     while (TRUE)
810     {
811         IsMapTransfer = 0;
812 
813         KeAcquireSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
814                           &OldIrql);
815 
816         KeAcquireSpinLockAtDpcLevel(&Endpoint->EndpointSpinLock);
817 
818         if (FdoExtension->Flags & USBPORT_FLAG_HC_SUSPEND)
819         {
820             IsEnd = TRUE;
821 
822             KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
823             KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
824                               OldIrql);
825             goto Next;
826         }
827 
828         if (!(Endpoint->Flags & ENDPOINT_FLAG_ROOTHUB_EP0))
829         {
830             if (!IsListEmpty(&Endpoint->TransferList))
831             {
832                 List = Endpoint->TransferList.Flink;
833 
834                 while (List && List != &Endpoint->TransferList)
835                 {
836                     Transfer = CONTAINING_RECORD(List,
837                                                  USBPORT_TRANSFER,
838                                                  TransferLink);
839 
840                     if (!(Transfer->Flags & TRANSFER_FLAG_SUBMITED))
841                     {
842                         KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
843                         KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
844                                           OldIrql);
845 
846                         IsEnd = TRUE;
847                         goto Worker;
848                     }
849 
850                     List = Transfer->TransferLink.Flink;
851                 }
852             }
853         }
854 
855         List = Endpoint->PendingTransferList.Flink;
856 
857         if (List == NULL || IsListEmpty(&Endpoint->PendingTransferList))
858         {
859             KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
860             KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
861                               OldIrql);
862 
863             IsEnd = TRUE;
864             goto Worker;
865         }
866 
867         Transfer = CONTAINING_RECORD(List,
868                                      USBPORT_TRANSFER,
869                                      TransferLink);
870 
871         if (Transfer->Irp)
872         {
873             DPRINT_CORE("USBPORT_FlushPendingTransfers: Transfer->Irp->CancelRoutine - %p\n",
874                         Transfer->Irp->CancelRoutine);
875         }
876 
877         if (Transfer->Irp &&
878             (IoSetCancelRoutine(Transfer->Irp, NULL) == NULL))
879         {
880             DPRINT_CORE("USBPORT_FlushPendingTransfers: Transfer->Irp - %p\n",
881                         Transfer->Irp);
882 
883             Transfer = NULL;
884             IsEnd = TRUE;
885         }
886 
887         if (!Transfer)
888         {
889             KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
890             KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
891                               OldIrql);
892 
893             if (IsMapTransfer)
894             {
895                 USBPORT_FlushMapTransfers(FdoDevice);
896                 goto Next;
897             }
898 
899             goto Worker;
900         }
901 
902         Irp = Transfer->Irp;
903         Urb = Transfer->Urb;
904 
905         RemoveEntryList(&Transfer->TransferLink);
906         Transfer->TransferLink.Flink = NULL;
907         Transfer->TransferLink.Blink = NULL;
908 
909         if (Irp)
910         {
911             Irp = USBPORT_RemovePendingTransferIrp(FdoDevice, Irp);
912         }
913 
914         KeReleaseSpinLockFromDpcLevel(&Endpoint->EndpointSpinLock);
915         KeReleaseSpinLock(&FdoExtension->FlushPendingTransferSpinLock,
916                           OldIrql);
917 
918         KeAcquireSpinLock(&FdoExtension->FlushTransferSpinLock, &OldIrql);
919 
920         if (Irp)
921         {
922             IoSetCancelRoutine(Irp, USBPORT_CancelActiveTransferIrp);
923 
924             if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
925             {
926                 DPRINT_CORE("USBPORT_FlushPendingTransfers: irp - %p\n", Irp);
927 
928                 KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock,
929                                   OldIrql);
930 
931                 USBPORT_CompleteTransfer(Transfer->Urb, USBD_STATUS_CANCELED);
932                 goto Worker;
933             }
934 
935             USBPORT_FindUrbInIrpTable(FdoExtension->ActiveIrpTable, Urb, Irp);
936             USBPORT_InsertIrpInTable(FdoExtension->ActiveIrpTable, Irp);
937         }
938 
939         IsMapTransfer = USBPORT_QueueActiveUrbToEndpoint(Endpoint, Urb);
940 
941         KeReleaseSpinLock(&FdoExtension->FlushTransferSpinLock, OldIrql);
942 
943         if (IsMapTransfer)
944         {
945             USBPORT_FlushMapTransfers(FdoDevice);
946             goto Next;
947         }
948 
949 Worker:
950         KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
951         Result = USBPORT_EndpointWorker(Endpoint, FALSE);
952         KeLowerIrql(OldIrql);
953 
954         if (Result)
955             USBPORT_InvalidateEndpointHandler(FdoDevice,
956                                               Endpoint,
957                                               INVALIDATE_ENDPOINT_WORKER_THREAD);
958 
959 Next:
960         if (IsEnd)
961         {
962             InterlockedDecrement(&Endpoint->FlushPendingLock);
963             DPRINT_CORE("USBPORT_FlushPendingTransfers: Endpoint Unlocked. Exit\n");
964             return;
965         }
966     }
967 }
968 
969 VOID
970 NTAPI
USBPORT_QueuePendingUrbToEndpoint(IN PUSBPORT_ENDPOINT Endpoint,IN PURB Urb)971 USBPORT_QueuePendingUrbToEndpoint(IN PUSBPORT_ENDPOINT Endpoint,
972                                   IN PURB Urb)
973 {
974     PUSBPORT_TRANSFER Transfer;
975 
976     DPRINT_CORE("USBPORT_QueuePendingUrbToEndpoint: Endpoint - %p, Urb - %p\n",
977                 Endpoint,
978                 Urb);
979 
980     Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
981     //FIXME USBPORT_ResetEndpointIdle();
982     InsertTailList(&Endpoint->PendingTransferList, &Transfer->TransferLink);
983     Urb->UrbHeader.Status = USBD_STATUS_PENDING;
984 }
985 
986 BOOLEAN
987 NTAPI
USBPORT_QueueActiveUrbToEndpoint(IN PUSBPORT_ENDPOINT Endpoint,IN PURB Urb)988 USBPORT_QueueActiveUrbToEndpoint(IN PUSBPORT_ENDPOINT Endpoint,
989                                  IN PURB Urb)
990 {
991     PUSBPORT_TRANSFER Transfer;
992     PDEVICE_OBJECT FdoDevice;
993     PUSBPORT_DEVICE_EXTENSION FdoExtension;
994     PUSBPORT_DEVICE_HANDLE DeviceHandle;
995     KIRQL OldIrql;
996 
997     DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: Endpoint - %p, Urb - %p\n",
998                 Endpoint,
999                 Urb);
1000 
1001     Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
1002     FdoDevice = Endpoint->FdoDevice;
1003     FdoExtension = FdoDevice->DeviceExtension;
1004 
1005     KeAcquireSpinLock(&Endpoint->EndpointSpinLock,
1006                       &Endpoint->EndpointOldIrql);
1007 
1008     if ((Endpoint->Flags & ENDPOINT_FLAG_NUKE) ||
1009         (Transfer->Flags & TRANSFER_FLAG_ABORTED))
1010     {
1011         InsertTailList(&Endpoint->CancelList, &Transfer->TransferLink);
1012 
1013         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
1014                           Endpoint->EndpointOldIrql);
1015 
1016         //DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: return FALSE\n");
1017         return FALSE;
1018     }
1019 
1020     if (Transfer->TransferParameters.TransferBufferLength == 0 ||
1021         !(Endpoint->Flags & ENDPOINT_FLAG_DMA_TYPE))
1022     {
1023         InsertTailList(&Endpoint->TransferList, &Transfer->TransferLink);
1024 
1025         KeReleaseSpinLock(&Endpoint->EndpointSpinLock,
1026                           Endpoint->EndpointOldIrql);
1027 
1028         //DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: return FALSE\n");
1029         return FALSE;
1030     }
1031 
1032     KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
1033 
1034     KeAcquireSpinLock(&FdoExtension->MapTransferSpinLock, &OldIrql);
1035 
1036     InsertTailList(&FdoExtension->MapTransferList, &Transfer->TransferLink);
1037 
1038     DeviceHandle = Transfer->Urb->UrbHeader.UsbdDeviceHandle;
1039     InterlockedIncrement(&DeviceHandle->DeviceHandleLock);
1040 
1041     KeReleaseSpinLock(&FdoExtension->MapTransferSpinLock, OldIrql);
1042 
1043     //DPRINT_CORE("USBPORT_QueueActiveUrbToEndpoint: return TRUE\n");
1044     return TRUE;
1045 }
1046 
1047 VOID
1048 NTAPI
USBPORT_QueuePendingTransferIrp(IN PIRP Irp)1049 USBPORT_QueuePendingTransferIrp(IN PIRP Irp)
1050 {
1051     PURB Urb;
1052     PUSBPORT_TRANSFER Transfer;
1053     PUSBPORT_ENDPOINT Endpoint;
1054     PDEVICE_OBJECT FdoDevice;
1055     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1056 
1057     DPRINT_CORE("USBPORT_QueuePendingTransferIrp: Irp - %p\n", Irp);
1058 
1059     Urb = URB_FROM_IRP(Irp);
1060 
1061     Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
1062     Endpoint = Transfer->Endpoint;
1063 
1064     FdoDevice = Endpoint->FdoDevice;
1065     FdoExtension = FdoDevice->DeviceExtension;
1066 
1067     Irp->IoStatus.Status = STATUS_PENDING;
1068     IoMarkIrpPending(Irp);
1069 
1070     IoSetCancelRoutine(Irp, USBPORT_CancelPendingTransferIrp);
1071 
1072     if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
1073     {
1074         USBPORT_CompleteTransfer(Urb, USBD_STATUS_CANCELED);
1075     }
1076     else
1077     {
1078         USBPORT_InsertIrpInTable(FdoExtension->PendingIrpTable, Irp);
1079         USBPORT_QueuePendingUrbToEndpoint(Endpoint, Urb);
1080     }
1081 }
1082 
1083 VOID
1084 NTAPI
USBPORT_QueueTransferUrb(IN PURB Urb)1085 USBPORT_QueueTransferUrb(IN PURB Urb)
1086 {
1087     PUSBPORT_TRANSFER Transfer;
1088     PUSBPORT_ENDPOINT Endpoint;
1089     PIRP Irp;
1090     PUSBPORT_DEVICE_HANDLE DeviceHandle;
1091     PUSBPORT_TRANSFER_PARAMETERS Parameters;
1092 
1093     DPRINT_CORE("USBPORT_QueueTransferUrb: Urb - %p\n", Urb);
1094 
1095     if (Urb->UrbControlTransfer.TransferFlags & USBD_DEFAULT_PIPE_TRANSFER)
1096         Urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
1097 
1098     Transfer = Urb->UrbControlTransfer.hca.Reserved8[0];
1099     Parameters = &Transfer->TransferParameters;
1100 
1101     Endpoint = Transfer->Endpoint;
1102     Endpoint->Flags &= ~ENDPOINT_FLAG_QUEUENE_EMPTY;
1103 
1104     Parameters->TransferBufferLength = Urb->UrbControlTransfer.TransferBufferLength;
1105     Parameters->TransferFlags = Urb->UrbControlTransfer.TransferFlags;
1106 
1107     Transfer->TransferBufferMDL = Urb->UrbControlTransfer.TransferBufferMDL;
1108 
1109     if (Urb->UrbControlTransfer.TransferFlags & USBD_TRANSFER_DIRECTION_IN)
1110     {
1111         Transfer->Direction = USBPORT_DMA_DIRECTION_FROM_DEVICE;
1112     }
1113     else
1114     {
1115         Transfer->Direction = USBPORT_DMA_DIRECTION_TO_DEVICE;
1116     }
1117 
1118     if (Endpoint->EndpointProperties.TransferType == USBPORT_TRANSFER_TYPE_CONTROL)
1119     {
1120         RtlCopyMemory(&Parameters->SetupPacket,
1121                       Urb->UrbControlTransfer.SetupPacket,
1122                       sizeof(USB_DEFAULT_PIPE_SETUP_PACKET));
1123     }
1124 
1125     DPRINT_URB("... URB TransferBufferLength - %x\n",
1126            Urb->UrbControlTransfer.TransferBufferLength);
1127 
1128     Urb->UrbControlTransfer.TransferBufferLength = 0;
1129 
1130     Irp = Transfer->Irp;
1131 
1132     if (Irp)
1133     {
1134         USBPORT_QueuePendingTransferIrp(Irp);
1135     }
1136     else
1137     {
1138         USBPORT_QueuePendingUrbToEndpoint(Endpoint, Urb);
1139     }
1140 
1141     DeviceHandle = Urb->UrbHeader.UsbdDeviceHandle;
1142     InterlockedDecrement(&DeviceHandle->DeviceHandleLock);
1143 
1144     USBPORT_FlushPendingTransfers(Endpoint);
1145 
1146     DPRINT_URB("... URB TransferBufferLength - %x\n",
1147            Urb->UrbControlTransfer.TransferBufferLength);
1148 
1149     if (Urb->UrbControlTransfer.TransferBufferLength)
1150     {
1151         PULONG Buffer;
1152         ULONG BufferLength;
1153         ULONG_PTR BufferEnd;
1154         ULONG ix;
1155 
1156         Buffer = Urb->UrbControlTransfer.TransferBuffer;
1157         BufferLength = Urb->UrbControlTransfer.TransferBufferLength;
1158         BufferEnd = (ULONG_PTR)Buffer + BufferLength;
1159 
1160         DPRINT_URB("URB TransferBuffer - %p\n", Buffer);
1161 
1162         for (ix = 0; (ULONG_PTR)(Buffer + ix) < BufferEnd; ix++)
1163         {
1164             DPRINT_URB("Buffer[%02X] - %p\n", ix, Buffer[ix]);
1165         }
1166     }
1167 }
1168 
1169 VOID
1170 NTAPI
USBPORT_FlushAllEndpoints(IN PDEVICE_OBJECT FdoDevice)1171 USBPORT_FlushAllEndpoints(IN PDEVICE_OBJECT FdoDevice)
1172 {
1173     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1174     PLIST_ENTRY Entry;
1175     PUSBPORT_ENDPOINT Endpoint;
1176     LIST_ENTRY List;
1177     KIRQL OldIrql;
1178 
1179     DPRINT_CORE("USBPORT_FlushAllEndpoints: ... \n");
1180 
1181     FdoExtension = FdoDevice->DeviceExtension;
1182 
1183     KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
1184 
1185     InitializeListHead(&List);
1186 
1187     Entry = FdoExtension->EndpointList.Flink;
1188 
1189     while (Entry && Entry != &FdoExtension->EndpointList)
1190     {
1191         Endpoint = CONTAINING_RECORD(Entry,
1192                                      USBPORT_ENDPOINT,
1193                                      EndpointLink);
1194 
1195         if (USBPORT_GetEndpointState(Endpoint) != USBPORT_ENDPOINT_CLOSED)
1196         {
1197             InsertTailList(&List, &Endpoint->FlushLink);
1198         }
1199 
1200         Entry = Endpoint->EndpointLink.Flink;
1201     }
1202 
1203     KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
1204 
1205     while (!IsListEmpty(&List))
1206     {
1207         Endpoint = CONTAINING_RECORD(List.Flink,
1208                                      USBPORT_ENDPOINT,
1209                                      FlushLink);
1210 
1211         RemoveHeadList(&List);
1212 
1213         Endpoint->FlushLink.Flink = NULL;
1214         Endpoint->FlushLink.Blink = NULL;
1215 
1216         if (!IsListEmpty(&Endpoint->PendingTransferList))
1217         {
1218             USBPORT_FlushPendingTransfers(Endpoint);
1219         }
1220     }
1221 
1222     DPRINT_CORE("USBPORT_FlushAllEndpoints: exit\n");
1223 }
1224 
1225 ULONG
1226 NTAPI
USBPORT_KillEndpointActiveTransfers(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_ENDPOINT Endpoint)1227 USBPORT_KillEndpointActiveTransfers(IN PDEVICE_OBJECT FdoDevice,
1228                                     IN PUSBPORT_ENDPOINT Endpoint)
1229 {
1230     PLIST_ENTRY ActiveList;
1231     PUSBPORT_TRANSFER Transfer;
1232     ULONG KilledTransfers = 0;
1233 
1234     DPRINT_CORE("USBPORT_KillEndpointActiveTransfers \n");
1235 
1236     ActiveList = Endpoint->TransferList.Flink;
1237 
1238     while (ActiveList && ActiveList != &Endpoint->TransferList)
1239     {
1240         ++KilledTransfers;
1241 
1242         Transfer = CONTAINING_RECORD(ActiveList,
1243                                      USBPORT_TRANSFER,
1244                                      TransferLink);
1245 
1246         Transfer->Flags |= TRANSFER_FLAG_ABORTED;
1247 
1248         ActiveList = Transfer->TransferLink.Flink;
1249     }
1250 
1251     USBPORT_FlushPendingTransfers(Endpoint);
1252     USBPORT_FlushCancelList(Endpoint);
1253 
1254     return KilledTransfers;
1255 }
1256 
1257 VOID
1258 NTAPI
USBPORT_FlushController(IN PDEVICE_OBJECT FdoDevice)1259 USBPORT_FlushController(IN PDEVICE_OBJECT FdoDevice)
1260 {
1261     PUSBPORT_DEVICE_EXTENSION  FdoExtension;
1262     PLIST_ENTRY Entry;
1263     PUSBPORT_ENDPOINT Endpoint;
1264     ULONG KilledTransfers;
1265     PLIST_ENTRY EndpointList;
1266     KIRQL OldIrql;
1267     LIST_ENTRY FlushList;
1268 
1269     DPRINT_CORE("USBPORT_FlushController \n");
1270 
1271     FdoExtension = FdoDevice->DeviceExtension;
1272 
1273     EndpointList = &FdoExtension->EndpointList;
1274 
1275     while (TRUE)
1276     {
1277         KeAcquireSpinLock(&FdoExtension->EndpointListSpinLock, &OldIrql);
1278 
1279         InitializeListHead(&FlushList);
1280 
1281         Entry = EndpointList->Flink;
1282 
1283         if (!IsListEmpty(EndpointList))
1284         {
1285             while (Entry && Entry != EndpointList)
1286             {
1287                 Endpoint = CONTAINING_RECORD(Entry,
1288                                              USBPORT_ENDPOINT,
1289                                              EndpointLink);
1290 
1291                 if (Endpoint->StateLast != USBPORT_ENDPOINT_REMOVE &&
1292                     Endpoint->StateLast != USBPORT_ENDPOINT_CLOSED)
1293                 {
1294                     InterlockedIncrement(&Endpoint->LockCounter);
1295                     InsertTailList(&FlushList, &Endpoint->FlushControllerLink);
1296                 }
1297 
1298                 Entry = Endpoint->EndpointLink.Flink;
1299             }
1300         }
1301 
1302         KeReleaseSpinLock(&FdoExtension->EndpointListSpinLock, OldIrql);
1303 
1304         KilledTransfers = 0;
1305         while (!IsListEmpty(&FlushList))
1306         {
1307             Endpoint = CONTAINING_RECORD(FlushList.Flink,
1308                                          USBPORT_ENDPOINT,
1309                                          FlushControllerLink);
1310 
1311             RemoveHeadList(&FlushList);
1312 
1313             KilledTransfers += USBPORT_KillEndpointActiveTransfers(FdoDevice,
1314                                                                    Endpoint);
1315 
1316             InterlockedDecrement(&Endpoint->LockCounter);
1317         }
1318 
1319         if (!KilledTransfers)
1320             break;
1321 
1322         USBPORT_Wait(FdoDevice, 100);
1323     }
1324 }
1325 
1326 VOID
1327 NTAPI
USBPORT_BadRequestFlush(IN PDEVICE_OBJECT FdoDevice)1328 USBPORT_BadRequestFlush(IN PDEVICE_OBJECT FdoDevice)
1329 {
1330     PUSBPORT_DEVICE_EXTENSION FdoExtension;
1331     PIRP Irp;
1332 
1333     DPRINT_QUEUE("USBPORT_BadRequestFlush: ... \n");
1334 
1335     FdoExtension = FdoDevice->DeviceExtension;
1336 
1337     while (TRUE)
1338     {
1339         Irp = IoCsqRemoveNextIrp(&FdoExtension->BadRequestIoCsq, 0);
1340 
1341         if (!Irp)
1342             break;
1343 
1344         DPRINT1("USBPORT_BadRequestFlush: Irp - %p\n", Irp);
1345 
1346         Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
1347         Irp->IoStatus.Information = 0;
1348         IoCompleteRequest(Irp, IO_NO_INCREMENT);
1349     }
1350 }
1351 
1352 VOID
1353 NTAPI
USBPORT_AbortEndpoint(IN PDEVICE_OBJECT FdoDevice,IN PUSBPORT_ENDPOINT Endpoint,IN PIRP Irp)1354 USBPORT_AbortEndpoint(IN PDEVICE_OBJECT FdoDevice,
1355                       IN PUSBPORT_ENDPOINT Endpoint,
1356                       IN PIRP Irp)
1357 {
1358     PLIST_ENTRY PendingList;
1359     PUSBPORT_TRANSFER PendingTransfer;
1360     PLIST_ENTRY ActiveList;
1361     PUSBPORT_TRANSFER ActiveTransfer;
1362 
1363     DPRINT_CORE("USBPORT_AbortEndpoint: Irp - %p\n", Irp);
1364 
1365     KeAcquireSpinLock(&Endpoint->EndpointSpinLock, &Endpoint->EndpointOldIrql);
1366 
1367     if (Irp)
1368     {
1369         InsertTailList(&Endpoint->AbortList, &Irp->Tail.Overlay.ListEntry);
1370     }
1371 
1372     PendingList = Endpoint->PendingTransferList.Flink;
1373 
1374     while (PendingList && PendingList != &Endpoint->PendingTransferList)
1375     {
1376         PendingTransfer = CONTAINING_RECORD(PendingList,
1377                                             USBPORT_TRANSFER,
1378                                             TransferLink);
1379 
1380         DPRINT_CORE("USBPORT_AbortEndpoint: Abort PendingTransfer - %p\n",
1381                     PendingTransfer);
1382 
1383         PendingTransfer->Flags |= TRANSFER_FLAG_ABORTED;
1384 
1385         PendingList = PendingTransfer->TransferLink.Flink;
1386     }
1387 
1388     ActiveList = Endpoint->TransferList.Flink;
1389 
1390     while (ActiveList && ActiveList != &Endpoint->TransferList)
1391     {
1392         ActiveTransfer = CONTAINING_RECORD(ActiveList,
1393                                            USBPORT_TRANSFER,
1394                                            TransferLink);
1395 
1396         DPRINT_CORE("USBPORT_AbortEndpoint: Abort ActiveTransfer - %p\n",
1397                     ActiveTransfer);
1398 
1399         ActiveTransfer->Flags |= TRANSFER_FLAG_ABORTED;
1400 
1401         if (Endpoint->Flags & ENDPOINT_FLAG_ABORTING)
1402         {
1403             ActiveTransfer->Flags |= TRANSFER_FLAG_DEVICE_GONE;
1404         }
1405 
1406         ActiveList = ActiveTransfer->TransferLink.Flink;
1407     }
1408 
1409     KeReleaseSpinLock(&Endpoint->EndpointSpinLock, Endpoint->EndpointOldIrql);
1410 
1411     USBPORT_InvalidateEndpointHandler(FdoDevice,
1412                                       Endpoint,
1413                                       INVALIDATE_ENDPOINT_INT_NEXT_SOF);
1414 
1415     USBPORT_FlushPendingTransfers(Endpoint);
1416     USBPORT_FlushCancelList(Endpoint);
1417 }
1418