8 USBPORT_MakeSplitTransfer(IN PDEVICE_OBJECT FdoDevice
,
9 IN PUSBPORT_TRANSFER Transfer
,
10 IN PUSBPORT_TRANSFER SplitTransfer
,
11 IN ULONG MaxTransferSize
,
14 IN ULONG TransferRemainLen
,
15 IN ULONG TransferOffset
)
17 PUSBPORT_SCATTER_GATHER_LIST SplitSgList
;
18 PUSBPORT_SCATTER_GATHER_ELEMENT Element0
;
19 PUSBPORT_SCATTER_GATHER_ELEMENT Element1
;
23 DPRINT("USBPORT_MakeSplitTransfer: ... \n");
25 SplitSgList
= &SplitTransfer
->SgList
;
26 Element0
= &SplitSgList
->SgElement
[0];
28 SgLength
= Transfer
->SgList
.SgElement
[*SgIdx
].SgTransferLength
- *SgOffset
;
30 if (SgLength
> MaxTransferSize
)
32 /* SgLength > MaxTransferSize */
33 SplitTransfer
->SgList
.SgElementCount
= 1;
35 Element0
->SgOffset
= 0;
36 Element0
->SgTransferLength
= MaxTransferSize
;
37 Element0
->SgPhysicalAddress
.LowPart
= Transfer
->SgList
.SgElement
[*SgIdx
].SgPhysicalAddress
.LowPart
+ *SgOffset
;
39 SplitTransfer
->TransferParameters
.IsTransferSplited
= TRUE
;
40 SplitTransfer
->TransferParameters
.TransferBufferLength
= MaxTransferSize
;
42 SplitTransfer
->SgList
.CurrentVa
= Transfer
->SgList
.CurrentVa
+ TransferOffset
;
43 SplitTransfer
->SgList
.MappedSystemVa
= (PVOID
)((ULONG_PTR
)Transfer
->SgList
.MappedSystemVa
+ TransferOffset
);
45 SplitTransfer
->Flags
|= TRANSFER_FLAG_SPLITED
;
47 *SgOffset
+= MaxTransferSize
;
48 TransferRemainLen
-= MaxTransferSize
;
49 return TransferRemainLen
;
52 /* SgLength <= MaxTransferSize */
53 SplitTransfer
->SgList
.SgElementCount
= 1;
54 TransferRemainLen
-= SgLength
;
56 Element0
->SgOffset
= 0;
57 Element0
->SgTransferLength
= SgLength
;
58 Element0
->SgPhysicalAddress
.LowPart
= Transfer
->SgList
.SgElement
[*SgIdx
].SgPhysicalAddress
.LowPart
+ *SgOffset
;
60 SplitTransfer
->TransferParameters
.TransferBufferLength
= SgLength
;
61 SplitTransfer
->TransferParameters
.IsTransferSplited
= TRUE
;
63 SplitTransfer
->SgList
.CurrentVa
= Transfer
->SgList
.CurrentVa
+ TransferOffset
;
64 SplitTransfer
->SgList
.MappedSystemVa
= (PVOID
)((ULONG_PTR
)Transfer
->SgList
.MappedSystemVa
+ TransferOffset
);
66 SplitTransfer
->Flags
|= TRANSFER_FLAG_SPLITED
;
68 *SgOffset
+= SgLength
;
70 SgRemainLen
= MaxTransferSize
- SgLength
;
72 if (SgRemainLen
> TransferRemainLen
)
74 SgRemainLen
= TransferRemainLen
;
79 /* SgLength == MaxTransferSize */
82 return TransferRemainLen
;
85 /* SgLength < MaxTransferSize */
87 DPRINT1("MakeSplitTransfer: SgRemainLen - %x\n", SgRemainLen
);
88 DPRINT1("MakeSplitTransfer: SgIdx - %x\n", *SgIdx
);
92 SplitTransfer
->SgList
.SgElementCount
++;
94 Element1
= &SplitSgList
->SgElement
[1];
96 Element1
->SgOffset
= SgRemainLen
;
97 Element1
->SgTransferLength
= Element0
->SgTransferLength
;
98 Element1
->SgPhysicalAddress
.LowPart
= Transfer
->SgList
.SgElement
[*SgIdx
].SgPhysicalAddress
.LowPart
+ *SgOffset
;
100 SplitTransfer
->TransferParameters
.TransferBufferLength
+= SgRemainLen
;
102 *SgOffset
+= SgRemainLen
;
103 TransferRemainLen
-= SgRemainLen
;
105 return TransferRemainLen
;
110 USBPORT_SplitBulkInterruptTransfer(IN PDEVICE_OBJECT FdoDevice
,
111 IN PUSBPORT_ENDPOINT Endpoint
,
112 IN PUSBPORT_TRANSFER Transfer
,
115 PUSBPORT_TRANSFER SplitTransfer
;
118 SIZE_T TransferBufferLength
;
119 SIZE_T MaxTransferSize
;
120 SIZE_T TransferOffset
= 0;
126 DPRINT("USBPORT_SplitBulkInterruptTransfer: ... \n");
128 MaxTransferSize
= Endpoint
->EndpointProperties
.TotalMaxPacketSize
*
129 (Endpoint
->EndpointProperties
.MaxTransferSize
/
130 Endpoint
->EndpointProperties
.TotalMaxPacketSize
);
132 if (Endpoint
->EndpointProperties
.MaxTransferSize
> PAGE_SIZE
)
134 KeBugCheckEx(BUGCODE_USB_DRIVER
, 1, 0, 0, 0);
137 TransferBufferLength
= Transfer
->TransferParameters
.TransferBufferLength
;
138 Transfer
->Flags
|= TRANSFER_FLAG_PARENT
;
140 NeedSplits
= TransferBufferLength
/ MaxTransferSize
+ 1;
142 InitializeListHead(&tmplist
);
144 DPRINT1("USBPORT_SplitBulkInterruptTransfer: TransferBufferLength - %x, NeedSplits - %x\n",
145 TransferBufferLength
, NeedSplits
);
149 DPRINT1("USBPORT_SplitBulkInterruptTransfer: DbgBreakPoint \n");
154 for (ix
= 0; ix
< NeedSplits
; ++ix
)
156 SplitTransfer
= ExAllocatePoolWithTag(NonPagedPool
,
157 Transfer
->FullTransferLength
,
162 DPRINT1("USBPORT_SplitBulkInterruptTransfer: DbgBreakPoint \n");
167 RtlCopyMemory(SplitTransfer
, Transfer
, Transfer
->FullTransferLength
);
169 SplitTransfer
->MiniportTransfer
= (PVOID
)((ULONG_PTR
)SplitTransfer
+
170 SplitTransfer
->PortTransferLength
);
172 InsertTailList(&tmplist
, &SplitTransfer
->TransferLink
);
175 if (Transfer
->TransferParameters
.TransferBufferLength
== 0)
180 RemainLength
= Transfer
->TransferParameters
.TransferBufferLength
;
184 SplitTransfer
= CONTAINING_RECORD(tmplist
.Flink
,
188 RemoveHeadList(&tmplist
);
190 RemainLength
= USBPORT_MakeSplitTransfer(FdoDevice
,
199 TransferOffset
+= SplitTransfer
->TransferParameters
.TransferBufferLength
;
201 InsertTailList(List
, &SplitTransfer
->TransferLink
);
202 InsertTailList(&Transfer
->SplitTransfersList
,&SplitTransfer
->SplitLink
);
204 while (RemainLength
!= 0);
208 while (!IsListEmpty(&tmplist
))
210 DPRINT1("USBPORT_SplitBulkInterruptTransfer: ... \n");
212 SplitTransfer
= CONTAINING_RECORD(tmplist
.Flink
,
215 RemoveHeadList(&tmplist
);
217 ExFreePoolWithTag(SplitTransfer
, USB_PORT_TAG
);
225 USBPORT_SplitTransfer(IN PDEVICE_OBJECT FdoDevice
,
226 IN PUSBPORT_ENDPOINT Endpoint
,
227 IN PUSBPORT_TRANSFER Transfer
,
232 DPRINT("USBPORT_SplitTransfer ... \n");
234 InitializeListHead(List
);
235 InitializeListHead(&Transfer
->SplitTransfersList
);
237 Transfer
->USBDStatus
= USBD_STATUS_SUCCESS
;
239 if (Transfer
->TransferParameters
.TransferBufferLength
>
240 Endpoint
->EndpointProperties
.MaxTransferSize
)
242 TransferType
= Endpoint
->EndpointProperties
.TransferType
;
244 if (TransferType
== USBPORT_TRANSFER_TYPE_BULK
||
245 TransferType
== USBPORT_TRANSFER_TYPE_INTERRUPT
)
247 USBPORT_SplitBulkInterruptTransfer(FdoDevice
,
252 else if (TransferType
== USBPORT_TRANSFER_TYPE_ISOCHRONOUS
||
253 TransferType
== USBPORT_TRANSFER_TYPE_CONTROL
)
255 KeBugCheckEx(BUGCODE_USB_DRIVER
, 1, 0, 0, 0);
259 DPRINT1("USBPORT_SplitTransfer: Unknown TransferType - %x\n",
265 InsertTailList(List
, &Transfer
->TransferLink
);
271 USBPORT_DoneSplitTransfer(IN PUSBPORT_TRANSFER SplitTransfer
)
273 PUSBPORT_TRANSFER ParentTransfer
;
276 DPRINT("USBPORT_DoneSplitTransfer: ... \n");
278 ParentTransfer
= SplitTransfer
->ParentTransfer
;
279 ParentTransfer
->CompletedTransferLen
+= SplitTransfer
->CompletedTransferLen
;
281 if (SplitTransfer
->USBDStatus
!= USBD_STATUS_SUCCESS
)
283 DPRINT1("USBPORT_DoneSplitTransfer: SplitTransfer->USBDStatus - %X\n",
284 SplitTransfer
->USBDStatus
);
286 ParentTransfer
->USBDStatus
= SplitTransfer
->USBDStatus
;
289 KeAcquireSpinLock(&ParentTransfer
->TransferSpinLock
, &OldIrql
);
291 RemoveEntryList(&SplitTransfer
->SplitLink
);
292 ExFreePoolWithTag(SplitTransfer
, USB_PORT_TAG
);
294 if (IsListEmpty(&ParentTransfer
->SplitTransfersList
))
296 KeReleaseSpinLock(&ParentTransfer
->TransferSpinLock
, OldIrql
);
297 USBPORT_DoneTransfer(ParentTransfer
);
301 KeReleaseSpinLock(&ParentTransfer
->TransferSpinLock
, OldIrql
);
307 USBPORT_CancelSplitTransfer(IN PUSBPORT_TRANSFER SplitTransfer
)
309 PUSBPORT_TRANSFER ParentTransfer
;
310 PUSBPORT_ENDPOINT Endpoint
;
313 DPRINT("USBPORT_CancelSplitTransfer \n");
315 Endpoint
= SplitTransfer
->Endpoint
;
316 ParentTransfer
= SplitTransfer
->ParentTransfer
;
317 ParentTransfer
->CompletedTransferLen
+= SplitTransfer
->CompletedTransferLen
;
319 KeAcquireSpinLock(&ParentTransfer
->TransferSpinLock
, &OldIrql
);
320 RemoveEntryList(&SplitTransfer
->SplitLink
);
321 KeReleaseSpinLock(&ParentTransfer
->TransferSpinLock
, OldIrql
);
323 ExFreePool(SplitTransfer
);
325 if (IsListEmpty(&ParentTransfer
->SplitTransfersList
))
327 InsertTailList(&Endpoint
->CancelList
, &ParentTransfer
->TransferLink
);