]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugCommunicationLibUsb3/DebugCommunicationLibUsb3Transfer.c
Use MaxPacketSize as the initial buffer size to read data.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugCommunicationLibUsb3 / DebugCommunicationLibUsb3Transfer.c
1 /** @file
2 Debug Port Library implementation based on usb3 debug port.
3
4 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14 #include "DebugCommunicationLibUsb3Internal.h"
15
16 /**
17 Synchronize the specified transfer ring to update the enqueue and dequeue pointer.
18
19 @param Handle Debug port handle.
20 @param TrsRing The transfer ring to sync.
21
22 @retval EFI_SUCCESS The transfer ring is synchronized successfully.
23
24 **/
25 EFI_STATUS
26 EFIAPI
27 XhcSyncTrsRing (
28 IN USB3_DEBUG_PORT_HANDLE *Handle,
29 IN TRANSFER_RING *TrsRing
30 )
31 {
32 UINTN Index;
33 TRB_TEMPLATE *TrsTrb;
34 UINT32 CycleBit;
35
36 ASSERT (TrsRing != NULL);
37
38 //
39 // Calculate the latest RingEnqueue and RingPCS
40 //
41 TrsTrb = (TRB_TEMPLATE *)(UINTN) TrsRing->RingEnqueue;
42
43 ASSERT (TrsTrb != NULL);
44
45 for (Index = 0; Index < TrsRing->TrbNumber; Index++) {
46 if (TrsTrb->CycleBit != (TrsRing->RingPCS & BIT0)) {
47 break;
48 }
49 TrsTrb++;
50 if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) {
51 ASSERT (((LINK_TRB*)TrsTrb)->TC != 0);
52 //
53 // set cycle bit in Link TRB as normal
54 //
55 ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0;
56 //
57 // Toggle PCS maintained by software
58 //
59 TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1;
60 TrsTrb = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F);
61 }
62 }
63 ASSERT (Index != TrsRing->TrbNumber);
64
65 if ((EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb != TrsRing->RingEnqueue) {
66 TrsRing->RingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN) TrsTrb;
67 }
68
69 //
70 // Clear the Trb context for enqueue, but reserve the PCS bit which indicates free Trb.
71 //
72 CycleBit = TrsTrb->CycleBit;
73 ZeroMem (TrsTrb, sizeof (TRB_TEMPLATE));
74 TrsTrb->CycleBit = CycleBit;
75
76 return EFI_SUCCESS;
77 }
78
79 /**
80 Synchronize the specified event ring to update the enqueue and dequeue pointer.
81
82 @param Handle Debug port handle.
83 @param EvtRing The event ring to sync.
84
85 @retval EFI_SUCCESS The event ring is synchronized successfully.
86
87 **/
88 EFI_STATUS
89 EFIAPI
90 XhcSyncEventRing (
91 IN USB3_DEBUG_PORT_HANDLE *Handle,
92 IN EVENT_RING *EvtRing
93 )
94 {
95 UINTN Index;
96 TRB_TEMPLATE *EvtTrb1;
97
98 ASSERT (EvtRing != NULL);
99
100 //
101 // Calculate the EventRingEnqueue and EventRingCCS.
102 // Note: only support single Segment
103 //
104 EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
105
106 for (Index = 0; Index < EvtRing->TrbNumber; Index++) {
107 if (EvtTrb1->CycleBit != EvtRing->EventRingCCS) {
108 break;
109 }
110
111 EvtTrb1++;
112
113 if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
114 EvtTrb1 = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingSeg0;
115 EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1;
116 }
117 }
118
119 if (Index < EvtRing->TrbNumber) {
120 EvtRing->EventRingEnqueue = (EFI_PHYSICAL_ADDRESS)(UINTN)EvtTrb1;
121 } else {
122 ASSERT (FALSE);
123 }
124
125 return EFI_SUCCESS;
126 }
127
128 /**
129 Check if there is a new generated event.
130
131 @param Handle Debug port handle.
132 @param EvtRing The event ring to check.
133 @param NewEvtTrb The new event TRB found.
134
135 @retval EFI_SUCCESS Found a new event TRB at the event ring.
136 @retval EFI_NOT_READY The event ring has no new event.
137
138 **/
139 EFI_STATUS
140 EFIAPI
141 XhcCheckNewEvent (
142 IN USB3_DEBUG_PORT_HANDLE *Handle,
143 IN EVENT_RING *EvtRing,
144 OUT TRB_TEMPLATE **NewEvtTrb
145 )
146 {
147 EFI_STATUS Status;
148 TRB_TEMPLATE *EvtTrb;
149
150 ASSERT (EvtRing != NULL);
151
152 EvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
153 *NewEvtTrb = (TRB_TEMPLATE *)(UINTN) EvtRing->EventRingDequeue;
154
155 if (EvtRing->EventRingDequeue == EvtRing->EventRingEnqueue) {
156 return EFI_NOT_READY;
157 }
158
159 Status = EFI_SUCCESS;
160
161 EvtRing->EventRingDequeue += sizeof (TRB_TEMPLATE);
162 //
163 // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring.
164 //
165 if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) {
166 EvtRing->EventRingDequeue = EvtRing->EventRingSeg0;
167 }
168
169 return Status;
170 }
171
172 /**
173 Check if the Trb is a transaction of the URB.
174
175 @param Ring The transfer ring to be checked.
176 @param Trb The TRB to be checked.
177
178 @retval TRUE It is a transaction of the URB.
179 @retval FALSE It is not any transaction of the URB.
180
181 **/
182 BOOLEAN
183 IsTrbInTrsRing (
184 IN TRANSFER_RING *Ring,
185 IN TRB_TEMPLATE *Trb
186 )
187 {
188 TRB_TEMPLATE *CheckedTrb;
189 UINTN Index;
190
191 CheckedTrb = (TRB_TEMPLATE *)(UINTN) Ring->RingSeg0;
192
193 ASSERT (Ring->TrbNumber == TR_RING_TRB_NUMBER);
194
195 for (Index = 0; Index < Ring->TrbNumber; Index++) {
196 if (Trb == CheckedTrb) {
197 return TRUE;
198 }
199 CheckedTrb++;
200 }
201
202 return FALSE;
203 }
204
205 /**
206 Check the URB's execution result and update the URB's
207 result accordingly.
208
209 @param Handle Debug port handle.
210 @param Urb The URB to check result.
211
212 **/
213 VOID
214 XhcCheckUrbResult (
215 IN USB3_DEBUG_PORT_HANDLE *Handle,
216 IN URB *Urb
217 )
218 {
219 EVT_TRB_TRANSFER *EvtTrb;
220 TRB_TEMPLATE *TRBPtr;
221 UINTN Index;
222 EFI_STATUS Status;
223 URB *CheckedUrb;
224 UINT64 XhcDequeue;
225 UINT32 High;
226 UINT32 Low;
227
228 ASSERT ((Handle != NULL) && (Urb != NULL));
229
230 if (Urb->Finished) {
231 goto EXIT;
232 }
233
234 EvtTrb = NULL;
235
236 //
237 // Traverse the event ring to find out all new events from the previous check.
238 //
239 XhcSyncEventRing (Handle, &Handle->EventRing);
240
241 for (Index = 0; Index < Handle->EventRing.TrbNumber; Index++) {
242
243 Status = XhcCheckNewEvent (Handle, &Handle->EventRing, ((TRB_TEMPLATE **)&EvtTrb));
244 if (Status == EFI_NOT_READY) {
245 //
246 // All new events are handled, return directly.
247 //
248 goto EXIT;
249 }
250
251 if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {
252 continue;
253 }
254
255 TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
256
257 if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Urb->Ring), TRBPtr)) {
258 CheckedUrb = Urb;
259 } else if (IsTrbInTrsRing ((TRANSFER_RING *)(UINTN)(Handle->UrbIn.Ring), TRBPtr)) {
260 //
261 // If it is read event and it should be generated by poll, and current operation is write, we need save data into internal buffer.
262 // Internal buffer is used by next read.
263 //
264 Handle->DataCount = (UINT8) (Handle->UrbIn.DataLen - EvtTrb->Length);
265 CopyMem ((VOID *)(UINTN)Handle->Data, (VOID *)(UINTN)Handle->UrbIn.Data, Handle->DataCount);
266 //
267 // Fill this TRB complete with CycleBit, otherwise next read will fail with old TRB.
268 //
269 TRBPtr->CycleBit = (TRBPtr->CycleBit & BIT0) ? 0 : 1;
270 continue;
271 } else {
272 continue;
273 }
274
275 if ((EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) ||
276 (EvtTrb->Completecode == TRB_COMPLETION_SUCCESS)) {
277 //
278 // The length of data which were transferred.
279 //
280 CheckedUrb->Completed += (CheckedUrb->DataLen - EvtTrb->Length);
281 } else {
282 CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;
283 }
284 //
285 // This Urb has been processed
286 //
287 CheckedUrb->Finished = TRUE;
288 }
289
290 EXIT:
291 //
292 // Advance event ring to last available entry
293 //
294 // Some 3rd party XHCI external cards don't support single 64-bytes width register access,
295 // So divide it to two 32-bytes width register access.
296 //
297 Low = XhcReadDebugReg (Handle, XHC_DC_DCERDP);
298 High = XhcReadDebugReg (Handle, XHC_DC_DCERDP + 4);
299 XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);
300
301 if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Handle->EventRing.EventRingDequeue & (~0x0F))) {
302 //
303 // Some 3rd party XHCI external cards don't support single 64-bytes width register access,
304 // So divide it to two 32-bytes width register access.
305 //
306 XhcWriteDebugReg (Handle, XHC_DC_DCERDP, XHC_LOW_32BIT (Handle->EventRing.EventRingDequeue));
307 XhcWriteDebugReg (Handle, XHC_DC_DCERDP + 4, XHC_HIGH_32BIT (Handle->EventRing.EventRingDequeue));
308 }
309 }
310
311 /**
312 Ring the door bell to notify XHCI there is a transaction to be executed.
313
314 @param Handle Debug port handle.
315 @param Urb The pointer to URB.
316
317 @retval EFI_SUCCESS Successfully ring the door bell.
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 XhcRingDoorBell (
323 IN USB3_DEBUG_PORT_HANDLE *Handle,
324 IN URB *Urb
325 )
326 {
327 UINT32 Dcdb;
328
329 //
330 // 7.6.8.2 DCDB Register
331 //
332 Dcdb = (Urb->Direction == EfiUsbDataIn) ? 0x100 : 0x0;
333
334 XhcWriteDebugReg (
335 Handle,
336 XHC_DC_DCDB,
337 Dcdb
338 );
339
340 return EFI_SUCCESS;
341 }
342
343 /**
344 Execute the transfer by polling the URB. This is a synchronous operation.
345
346 @param Handle Debug port handle.
347 @param Urb The URB to execute.
348 @param Timeout The time to wait before abort, in microsecond.
349
350 **/
351 VOID
352 XhcExecTransfer (
353 IN USB3_DEBUG_PORT_HANDLE *Handle,
354 IN URB *Urb,
355 IN UINTN Timeout
356 )
357 {
358 TRANSFER_RING *Ring;
359 UINT64 Begin;
360 UINT64 TimeoutTicker;
361 UINT64 TimerRound;
362 TRB_TEMPLATE *Trb;
363
364 Begin = 0;
365 TimeoutTicker = 0;
366 TimerRound = 0;
367
368 XhcRingDoorBell (Handle, Urb);
369
370 if (Timeout != 0) {
371 Begin = GetPerformanceCounter ();
372 TimeoutTicker = DivU64x32 (
373 MultU64x64 (
374 Handle->TimerFrequency,
375 Timeout
376 ),
377 1000000u
378 );
379 TimerRound = DivU64x64Remainder (
380 TimeoutTicker,
381 DivU64x32 (Handle->TimerCycle, 2),
382 &TimeoutTicker
383 );
384 }
385
386 //
387 // Event Ring Not Empty bit can only be set to 1 by XHC after ringing door bell with some delay.
388 //
389 while (TRUE) {
390 if (Timeout != 0) {
391 if (TimerRound == 0) {
392 if (IsTimerTimeout (Handle, Begin, TimeoutTicker)) {
393 //
394 // If time out occurs.
395 //
396 Urb->Result |= EFI_USB_ERR_TIMEOUT;
397 break;
398 }
399 } else {
400 if (IsTimerTimeout (Handle, Begin, DivU64x32 (Handle->TimerCycle, 2))) {
401 TimerRound --;
402 }
403 }
404 }
405 XhcCheckUrbResult (Handle, Urb);
406 if (Urb->Finished) {
407 break;
408 }
409 }
410
411 //
412 // If URB transfer is error, restore transfer ring to original value before URB transfer
413 // This will make the current transfer TRB is always at the latest unused one in transfer ring.
414 //
415 Ring = (TRANSFER_RING *)(UINTN) Urb->Ring;
416 if ((Urb->Result != EFI_USB_NOERROR) && (Urb->Direction == EfiUsbDataIn)) {
417 //
418 // Adjust Enqueue pointer
419 //
420 Ring->RingEnqueue = Urb->Trb;
421 //
422 // Clear CCS flag for next use
423 //
424 Trb = (TRB_TEMPLATE *)(UINTN) Urb->Trb;
425 Trb->CycleBit = ((~Ring->RingPCS) & BIT0);
426 } else {
427 //
428 // Update transfer ring for next transfer.
429 //
430 XhcSyncTrsRing (Handle, Ring);
431 }
432 }
433
434 /**
435 Create a transfer TRB.
436
437 @param Handle Debug port handle.
438 @param Urb The urb used to construct the transfer TRB.
439
440 @return Created TRB or NULL
441
442 **/
443 EFI_STATUS
444 XhcCreateTransferTrb (
445 IN USB3_DEBUG_PORT_HANDLE *Handle,
446 IN URB *Urb
447 )
448 {
449 TRANSFER_RING *EPRing;
450 TRB *Trb;
451
452 if (Urb->Direction == EfiUsbDataIn) {
453 EPRing = &Handle->TransferRingIn;
454 } else {
455 EPRing = &Handle->TransferRingOut;
456 }
457
458 Urb->Ring = (EFI_PHYSICAL_ADDRESS)(UINTN) EPRing;
459 XhcSyncTrsRing (Handle, EPRing);
460
461 Urb->Trb = EPRing->RingEnqueue;
462 Trb = (TRB *)(UINTN)EPRing->RingEnqueue;
463 Trb->TrbNormal.TRBPtrLo = XHC_LOW_32BIT (Urb->Data);
464 Trb->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT (Urb->Data);
465 Trb->TrbNormal.Length = Urb->DataLen;
466 Trb->TrbNormal.TDSize = 0;
467 Trb->TrbNormal.IntTarget = 0;
468 Trb->TrbNormal.ISP = 1;
469 Trb->TrbNormal.IOC = 1;
470 Trb->TrbNormal.Type = TRB_TYPE_NORMAL;
471
472 //
473 // Update the cycle bit to indicate this TRB has been consumed.
474 //
475 Trb->TrbNormal.CycleBit = EPRing->RingPCS & BIT0;
476
477 return EFI_SUCCESS;
478 }
479
480 /**
481 Create a new URB for a new transaction.
482
483 @param Handle Debug port handle.
484 @param Direction The direction of data flow.
485 @param Data The user data to transfer
486 @param DataLen The length of data buffer
487
488 @return Created URB or NULL
489
490 **/
491 URB*
492 XhcCreateUrb (
493 IN USB3_DEBUG_PORT_HANDLE *Handle,
494 IN EFI_USB_DATA_DIRECTION Direction,
495 IN VOID *Data,
496 IN UINTN DataLen
497 )
498 {
499 EFI_STATUS Status;
500 URB *Urb;
501 EFI_PHYSICAL_ADDRESS UrbData;
502
503 if (Direction == EfiUsbDataIn) {
504 Urb = &Handle->UrbIn;
505 } else {
506 Urb = &Handle->UrbOut;
507 }
508
509 UrbData = Urb->Data;
510
511 ZeroMem (Urb, sizeof (URB));
512 Urb->Direction = Direction;
513
514 //
515 // Allocate memory to move data from CAR or SMRAM to normal memory
516 // to make XHCI DMA successfully
517 // re-use the pre-allocate buffer in PEI to avoid DXE memory service or gBS are not ready
518 //
519 Urb->Data = UrbData;
520
521 if (Direction == EfiUsbDataIn) {
522 //
523 // Do not break URB data in buffer as it may contain the data which were just put in via DMA by XHC
524 //
525 Urb->DataLen = (UINT32) DataLen;
526 } else {
527 //
528 // Put data into URB data out buffer which will create TRBs
529 //
530 ZeroMem ((VOID*)(UINTN) Urb->Data, DataLen);
531 CopyMem ((VOID*)(UINTN) Urb->Data, Data, DataLen);
532 Urb->DataLen = (UINT32) DataLen;
533 }
534
535 Status = XhcCreateTransferTrb (Handle, Urb);
536 ASSERT_EFI_ERROR (Status);
537
538 return Urb;
539 }
540
541 /**
542 Submits bulk transfer to a bulk endpoint of a USB device.
543
544 @param Handle Debug port handle.
545 @param Direction The direction of data transfer.
546 @param Data Array of pointers to the buffers of data to transmit
547 from or receive into.
548 @param DataLength The lenght of the data buffer.
549 @param Timeout Indicates the maximum time, in microsecond, which
550 the transfer is allowed to complete.
551
552 @retval EFI_SUCCESS The transfer was completed successfully.
553 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
554 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
555 @retval EFI_TIMEOUT The transfer failed due to timeout.
556 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
557
558 **/
559 EFI_STATUS
560 EFIAPI
561 XhcDataTransfer (
562 IN USB3_DEBUG_PORT_HANDLE *Handle,
563 IN EFI_USB_DATA_DIRECTION Direction,
564 IN OUT VOID *Data,
565 IN OUT UINTN *DataLength,
566 IN UINTN Timeout
567 )
568 {
569 URB *Urb;
570 EFI_STATUS Status;
571
572 //
573 // Validate the parameters
574 //
575 if ((DataLength == NULL) || (*DataLength == 0) || (Data == NULL)) {
576 return EFI_INVALID_PARAMETER;
577 }
578
579 //
580 // Create a new URB, insert it into the asynchronous
581 // schedule list, then poll the execution status.
582 //
583 Urb = XhcCreateUrb (Handle, Direction, Data, *DataLength);
584 ASSERT (Urb != NULL);
585
586 XhcExecTransfer (Handle, Urb, Timeout);
587
588 *DataLength = Urb->Completed;
589
590 Status = EFI_TIMEOUT;
591 if (Urb->Result == EFI_USB_NOERROR) {
592 Status = EFI_SUCCESS;
593 }
594
595 if (Direction == EfiUsbDataIn) {
596 //
597 // Move data from internal buffer to outside buffer (outside buffer may be in SMRAM...)
598 // SMRAM does not allow to do DMA, so we create an internal buffer.
599 //
600 CopyMem (Data, (VOID *)(UINTN)Urb->Data, *DataLength);
601 }
602
603 return Status;
604 }
605