]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/Ehci/Dxe/EhciSched.c
Remove two global variable: mUsbCapabilityLen and mDeviceSpeed and integrate them...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Ehci / Dxe / EhciSched.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 EhciSched.c
15
16 Abstract:
17
18
19 Revision History
20 --*/
21
22 #include "Ehci.h"
23
24 EFI_STATUS
25 InitialPeriodicFrameList (
26 IN USB2_HC_DEV *HcDev,
27 IN UINTN Length
28 )
29 /*++
30
31 Routine Description:
32
33 Initialize Periodic Schedule Frame List
34
35 Arguments:
36
37 HcDev - USB2_HC_DEV
38 Length - Frame List Length
39
40 Returns:
41
42 EFI_SUCCESS Success
43 EFI_DEVICE_ERROR Fail
44
45 --*/
46 {
47 EFI_STATUS Status;
48 VOID *CommonBuffer;
49 EFI_PHYSICAL_ADDRESS FrameBuffer;
50 VOID *Map;
51 UINTN BufferSizeInPages;
52 UINTN BufferSizeInBytes;
53 UINTN FrameIndex;
54 FRAME_LIST_ENTRY *FrameEntryPtr;
55
56 //
57 // The Frame List is a common buffer that will be
58 // accessed by both the cpu and the usb bus master
59 // at the same time.
60 // The Frame List ocupies 4K bytes,
61 // and must be aligned on 4-Kbyte boundaries.
62 //
63 if (EHCI_MAX_FRAME_LIST_LENGTH != Length && IsFrameListProgrammable (HcDev)) {
64 Status = SetFrameListLen (HcDev, Length);
65 if (EFI_ERROR (Status)) {
66 Status = EFI_INVALID_PARAMETER;
67 goto exit;
68 }
69 }
70
71 BufferSizeInBytes = EFI_PAGE_SIZE;
72 BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);
73 Status = HcDev->PciIo->AllocateBuffer (
74 HcDev->PciIo,
75 AllocateAnyPages,
76 EfiBootServicesData,
77 BufferSizeInPages,
78 &CommonBuffer,
79 0
80 );
81 if (EFI_ERROR (Status)) {
82 DEBUG ((gEHCErrorLevel, "EHCI: PciIo->AllocateBuffer Failed\n"));
83 Status = EFI_OUT_OF_RESOURCES;
84 goto exit;
85 }
86
87 Status = HcDev->PciIo->Map (
88 HcDev->PciIo,
89 EfiPciIoOperationBusMasterCommonBuffer,
90 CommonBuffer,
91 &BufferSizeInBytes,
92 &FrameBuffer,
93 &Map
94 );
95 if (EFI_ERROR (Status) || (BufferSizeInBytes != EFI_PAGE_SIZE)) {
96 DEBUG ((gEHCErrorLevel, "EHCI: PciIo->MapBuffer Failed\n"));
97 Status = EFI_OUT_OF_RESOURCES;
98 goto free_buffer;
99 }
100
101 //
102 // Put high 32bit into CtrlDataStructSeg reg
103 // when 64bit addressing range capability
104 //
105 if (HcDev->Is64BitCapable != 0) {
106 HcDev->High32BitAddr = (UINT32) GET_32B_TO_63B (FrameBuffer);
107
108 Status = SetCtrlDataStructSeg (HcDev);
109 if (EFI_ERROR (Status)) {
110 DEBUG ((gEHCErrorLevel, "EHCI: SetCtrlDataStructSeg Failed\n"));
111 Status = EFI_DEVICE_ERROR;
112 goto unmap_buffer;
113 }
114 }
115
116 //
117 // Tell the Host Controller where the Frame List lies,
118 // by set the Frame List Base Address Register.
119 //
120 Status = SetFrameListBaseAddr (HcDev, (UINT32) FrameBuffer);
121 if (EFI_ERROR (Status)) {
122 Status = EFI_DEVICE_ERROR;
123 goto unmap_buffer;
124 }
125
126 HcDev->PeriodicFrameListLength = Length;
127 HcDev->PeriodicFrameListBuffer = (VOID *) ((UINTN) FrameBuffer);
128 HcDev->PeriodicFrameListMap = Map;
129
130 //
131 // Init Frame List Array fields
132 //
133 FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
134 for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {
135 FrameEntryPtr->LinkPointer = 0;
136 FrameEntryPtr->Rsvd = 0;
137 FrameEntryPtr->SelectType = 0;
138 FrameEntryPtr->LinkTerminate = TRUE;
139 FrameEntryPtr++;
140 }
141
142 goto exit;
143
144 unmap_buffer:
145 HcDev->PciIo->Unmap (HcDev->PciIo, Map);
146 free_buffer:
147 HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);
148 exit:
149 return Status;
150 }
151
152 VOID
153 DeinitialPeriodicFrameList (
154 IN USB2_HC_DEV *HcDev
155 )
156 /*++
157
158 Routine Description:
159
160 Deinitialize Periodic Schedule Frame List
161
162 Arguments:
163
164 HcDev - USB2_HC_DEV
165
166 Returns:
167
168 VOID
169
170 --*/
171 {
172 HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->PeriodicFrameListMap);
173 HcDev->PciIo->FreeBuffer (HcDev->PciIo, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE), HcDev->PeriodicFrameListBuffer);
174 return ;
175 }
176
177 EFI_STATUS
178 CreatePollingTimer (
179 IN USB2_HC_DEV *HcDev,
180 IN EFI_EVENT_NOTIFY NotifyFunction
181 )
182 /*++
183
184 Routine Description:
185
186 Create Async Request Polling Timer
187
188 Arguments:
189
190 HcDev - USB2_HC_DEV
191 NotifyFunction - Timer Notify Function
192
193 Returns:
194
195 EFI_SUCCESS Success
196 EFI_DEVICE_ERROR Fail
197
198 --*/
199 {
200 return gBS->CreateEvent (
201 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
202 EFI_TPL_NOTIFY,
203 NotifyFunction,
204 HcDev,
205 &HcDev->AsyncRequestEvent
206 );
207 }
208
209 EFI_STATUS
210 DestoryPollingTimer (
211 IN USB2_HC_DEV *HcDev
212 )
213 /*++
214
215 Routine Description:
216
217 Destory Async Request Polling Timer
218
219 Arguments:
220
221 HcDev - USB2_HC_DEV
222
223 Returns:
224
225 EFI_SUCCESS Success
226 EFI_DEVICE_ERROR Fail
227
228 --*/
229 {
230 return gBS->CloseEvent (HcDev->AsyncRequestEvent);
231 }
232
233 EFI_STATUS
234 StartPollingTimer (
235 IN USB2_HC_DEV *HcDev
236 )
237 /*++
238
239 Routine Description:
240
241 Start Async Request Polling Timer
242
243 Arguments:
244
245 HcDev - USB2_HC_DEV
246
247 Returns:
248
249 EFI_SUCCESS Success
250 EFI_DEVICE_ERROR Fail
251
252 --*/
253 {
254 return gBS->SetTimer (
255 HcDev->AsyncRequestEvent,
256 TimerPeriodic,
257 EHCI_ASYNC_REQUEST_POLLING_TIME
258 );
259 }
260
261 EFI_STATUS
262 StopPollingTimer (
263 IN USB2_HC_DEV *HcDev
264 )
265 /*++
266
267 Routine Description:
268
269 Stop Async Request Polling Timer
270
271 Arguments:
272
273 HcDev - USB2_HC_DEV
274
275 Returns:
276
277 EFI_SUCCESS Success
278 EFI_DEVICE_ERROR Fail
279
280 --*/
281 {
282 return gBS->SetTimer (
283 HcDev->AsyncRequestEvent,
284 TimerCancel,
285 EHCI_ASYNC_REQUEST_POLLING_TIME
286 );
287 }
288
289 EFI_STATUS
290 CreateQh (
291 IN USB2_HC_DEV *HcDev,
292 IN UINT8 DeviceAddr,
293 IN UINT8 Endpoint,
294 IN UINT8 DeviceSpeed,
295 IN UINTN MaxPacketLen,
296 OUT EHCI_QH_ENTITY **QhPtrPtr
297 )
298 /*++
299
300 Routine Description:
301
302 Create Qh Structure and Pre-Initialize
303
304 Arguments:
305
306 HcDev - USB2_HC_DEV
307 DeviceAddr - Address of Device
308 Endpoint - Endpoint Number
309 DeviceSpeed - Device Speed
310 MaxPacketLen - Max Length of one Packet
311 QhPtrPtr - A pointer of pointer to Qh for return
312
313 Returns:
314
315 EFI_SUCCESS Success
316 EFI_OUT_OF_RESOURCES Cannot allocate resources
317
318 --*/
319 {
320 EFI_STATUS Status;
321 EHCI_QH_HW *QhHwPtr;
322
323 ASSERT (HcDev);
324 ASSERT (QhPtrPtr);
325
326 *QhPtrPtr = NULL;
327
328 //
329 // Allocate memory for Qh structure
330 //
331 Status = EhciAllocatePool (
332 HcDev,
333 (UINT8 **) QhPtrPtr,
334 sizeof (EHCI_QH_ENTITY)
335 );
336 if (EFI_ERROR (Status)) {
337 Status = EFI_OUT_OF_RESOURCES;
338 goto exit;
339 }
340 //
341 // Init fields in Qh
342 //
343 ZeroMem (*QhPtrPtr, sizeof (EHCI_QH_ENTITY));
344
345 //
346 // Software field
347 //
348 (*QhPtrPtr)->Next = NULL;
349 (*QhPtrPtr)->Prev = NULL;
350 (*QhPtrPtr)->FirstQtdPtr = NULL;
351 (*QhPtrPtr)->AltQtdPtr = NULL;
352 (*QhPtrPtr)->LastQtdPtr = NULL;
353
354 //
355 // Hardware field
356 //
357 QhHwPtr = &((*QhPtrPtr)->Qh);
358 QhHwPtr->QhHorizontalPointer = 0;
359 QhHwPtr->SelectType = 0;
360 QhHwPtr->MaxPacketLen = (UINT32) MaxPacketLen;
361 QhHwPtr->EndpointSpeed = (DeviceSpeed & 0x3);
362 QhHwPtr->EndpointNum = (Endpoint & 0x0f);
363 QhHwPtr->DeviceAddr = (DeviceAddr & 0x7f);
364 QhHwPtr->Multiplier = HIGH_BANDWIDTH_PIPE_MULTIPLIER;
365 QhHwPtr->Rsvd1 = 0;
366 QhHwPtr->Rsvd2 = 0;
367 QhHwPtr->Rsvd3 = 0;
368 QhHwPtr->Rsvd4 = 0;
369 QhHwPtr->Rsvd5 = 0;
370 QhHwPtr->Rsvd6 = 0;
371
372 exit:
373 return Status;
374 }
375
376 VOID
377 DestoryQh (
378 IN USB2_HC_DEV *HcDev,
379 IN EHCI_QH_ENTITY *QhPtr
380 )
381 /*++
382
383 Routine Description:
384
385 Destory Qh Structure
386
387 Arguments:
388
389 HcDev - USB2_HC_DEV
390 QhPtr - A pointer to Qh
391
392 Returns:
393
394 EFI_SUCCESS Success
395 EFI_DEVICE_ERROR Fail
396
397 --*/
398 {
399 ASSERT (HcDev);
400 ASSERT (QhPtr);
401
402 EhciFreePool (HcDev, (UINT8 *) QhPtr, sizeof (EHCI_QH_ENTITY));
403 return ;
404 }
405
406 EFI_STATUS
407 CreateControlQh (
408 IN USB2_HC_DEV *HcDev,
409 IN UINT8 DeviceAddr,
410 IN UINT8 DeviceSpeed,
411 IN UINTN MaxPacketLen,
412 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
413 OUT EHCI_QH_ENTITY **QhPtrPtr
414 )
415 /*++
416
417 Routine Description:
418
419 Create Qh for Control Transfer
420
421 Arguments:
422
423 HcDev - USB2_HC_DEV
424 DeviceAddr - Address of Device
425 DeviceSpeed - Device Speed
426 MaxPacketLen - Max Length of one Packet
427 Translator - Translator Transaction for SplitX
428 QhPtrPtr - A pointer of pointer to Qh for return
429
430 Returns:
431
432 EFI_SUCCESS Success
433 EFI_OUT_OF_RESOURCES Cannot allocate resources
434
435 --*/
436 {
437 EFI_STATUS Status;
438
439 //
440 // Create and init Control Qh
441 //
442 Status = CreateQh (
443 HcDev,
444 DeviceAddr,
445 0,
446 DeviceSpeed,
447 MaxPacketLen,
448 QhPtrPtr
449 );
450 if (EFI_ERROR (Status)) {
451 Status = EFI_OUT_OF_RESOURCES;
452 goto exit;
453 }
454 //
455 // Software field
456 //
457 (*QhPtrPtr)->Next = (*QhPtrPtr);
458 (*QhPtrPtr)->Prev = (*QhPtrPtr);
459 (*QhPtrPtr)->TransferType = CONTROL_TRANSFER;
460
461 //
462 // Hardware field
463 //
464 // Control Transfer use DataToggleControl
465 //
466 (*QhPtrPtr)->Qh.DataToggleControl = TRUE;
467 (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);
468 (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE;
469 (*QhPtrPtr)->Qh.QhTerminate = FALSE;
470 (*QhPtrPtr)->Qh.ControlEndpointFlag = TRUE;
471 (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD;
472 if (NULL != Translator) {
473 (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
474 (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
475 (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
476 }
477
478 exit:
479 return Status;
480 }
481
482 EFI_STATUS
483 CreateBulkQh (
484 IN USB2_HC_DEV *HcDev,
485 IN UINT8 DeviceAddr,
486 IN UINT8 EndPointAddr,
487 IN UINT8 DeviceSpeed,
488 IN UINT8 DataToggle,
489 IN UINTN MaxPacketLen,
490 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
491 OUT EHCI_QH_ENTITY **QhPtrPtr
492 )
493 /*++
494
495 Routine Description:
496
497 Create Qh for Bulk Transfer
498
499 Arguments:
500
501 HcDev - USB2_HC_DEV
502 DeviceAddr - Address of Device
503 EndPointAddr - Address of Endpoint
504 DeviceSpeed - Device Speed
505 MaxPacketLen - Max Length of one Packet
506 Translator - Translator Transaction for SplitX
507 QhPtrPtr - A pointer of pointer to Qh for return
508
509 Returns:
510
511 EFI_SUCCESS Success
512 EFI_OUT_OF_RESOURCES Cannot allocate resources
513
514 --*/
515 {
516 EFI_STATUS Status;
517
518 //
519 // Create and init Bulk Qh
520 //
521 Status = CreateQh (
522 HcDev,
523 DeviceAddr,
524 EndPointAddr,
525 DeviceSpeed,
526 MaxPacketLen,
527 QhPtrPtr
528 );
529 if (EFI_ERROR (Status)) {
530 Status = EFI_OUT_OF_RESOURCES;
531 goto exit;
532 }
533
534 //
535 // Software fields
536 //
537 (*QhPtrPtr)->Next = (*QhPtrPtr);
538 (*QhPtrPtr)->Prev = (*QhPtrPtr);
539 (*QhPtrPtr)->TransferType = BULK_TRANSFER;
540
541 //
542 // Hardware fields
543 //
544 // BulkTransfer don't use DataToggleControl
545 //
546 (*QhPtrPtr)->Qh.DataToggleControl = FALSE;
547 (*QhPtrPtr)->Qh.QhHorizontalPointer = (UINT32) (GET_0B_TO_31B (&((*QhPtrPtr)->Qh)) >> 5);
548 (*QhPtrPtr)->Qh.SelectType = QH_SELECT_TYPE;
549 (*QhPtrPtr)->Qh.QhTerminate = FALSE;
550 (*QhPtrPtr)->Qh.NakCountReload = NAK_COUNT_RELOAD;
551 (*QhPtrPtr)->Qh.DataToggle = DataToggle;
552 if (NULL != Translator) {
553 (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
554 (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
555 (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
556 }
557
558 exit:
559 return Status;
560 }
561
562 EFI_STATUS
563 CreateInterruptQh (
564 IN USB2_HC_DEV *HcDev,
565 IN UINT8 DeviceAddr,
566 IN UINT8 EndPointAddr,
567 IN UINT8 DeviceSpeed,
568 IN UINT8 DataToggle,
569 IN UINTN MaxPacketLen,
570 IN UINTN Interval,
571 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
572 OUT EHCI_QH_ENTITY **QhPtrPtr
573 )
574 /*++
575
576 Routine Description:
577
578 Create Qh for Control Transfer
579
580 Arguments:
581
582 HcDev - USB2_HC_DEV
583 DeviceAddr - Address of Device
584 EndPointAddr - Address of Endpoint
585 DeviceSpeed - Device Speed
586 MaxPacketLen - Max Length of one Packet
587 Interval - value of interval
588 Translator - Translator Transaction for SplitX
589 QhPtrPtr - A pointer of pointer to Qh for return
590
591 Returns:
592
593 EFI_SUCCESS Success
594 EFI_OUT_OF_RESOURCES Cannot allocate resources
595
596 --*/
597 {
598 EFI_STATUS Status;
599
600 //
601 // Create and init InterruptQh
602 //
603 Status = CreateQh (
604 HcDev,
605 DeviceAddr,
606 EndPointAddr,
607 DeviceSpeed,
608 MaxPacketLen,
609 QhPtrPtr
610 );
611 if (EFI_ERROR (Status)) {
612 Status = EFI_OUT_OF_RESOURCES;
613 goto exit;
614 }
615
616 //
617 // Software fields
618 //
619 if (Interval == 0) {
620 (*QhPtrPtr)->TransferType = SYNC_INTERRUPT_TRANSFER;
621 } else {
622 (*QhPtrPtr)->TransferType = ASYNC_INTERRUPT_TRANSFER;
623 }
624 (*QhPtrPtr)->Interval = GetApproxiOfInterval (Interval);
625
626 //
627 // Hardware fields
628 //
629 // InterruptTranfer don't use DataToggleControl
630 //
631 (*QhPtrPtr)->Qh.DataToggleControl = FALSE;
632 (*QhPtrPtr)->Qh.QhHorizontalPointer = 0;
633 (*QhPtrPtr)->Qh.QhTerminate = TRUE;
634 (*QhPtrPtr)->Qh.NakCountReload = 0;
635 (*QhPtrPtr)->Qh.InerruptScheduleMask = MICRO_FRAME_0_CHANNEL;
636 (*QhPtrPtr)->Qh.SplitComletionMask = (MICRO_FRAME_2_CHANNEL | MICRO_FRAME_3_CHANNEL | MICRO_FRAME_4_CHANNEL);
637 (*QhPtrPtr)->Qh.DataToggle = DataToggle;
638 if (NULL != Translator) {
639 (*QhPtrPtr)->Qh.PortNum = Translator->TranslatorPortNumber;
640 (*QhPtrPtr)->Qh.HubAddr = Translator->TranslatorHubAddress;
641 (*QhPtrPtr)->Qh.Status |= QTD_STATUS_DO_START_SPLIT;
642 }
643
644 exit:
645 return Status;
646 }
647
648 EFI_STATUS
649 CreateQtd (
650 IN USB2_HC_DEV *HcDev,
651 IN UINT8 *DataPtr,
652 IN UINTN DataLen,
653 IN UINT8 PktId,
654 IN UINT8 Toggle,
655 IN UINT8 QtdStatus,
656 OUT EHCI_QTD_ENTITY **QtdPtrPtr
657 )
658 /*++
659
660 Routine Description:
661
662 Create Qtd Structure and Pre-Initialize it
663
664 Arguments:
665
666 HcDev - USB2_HC_DEV
667 DataPtr - A pointer to user data buffer to transfer
668 DataLen - Length of user data to transfer
669 PktId - Packet Identification of this Qtd
670 Toggle - Data Toggle of this Qtd
671 QtdStatus - Default value of status of this Qtd
672 QtdPtrPtr - A pointer of pointer to Qtd for return
673
674 Returns:
675
676 EFI_SUCCESS Success
677 EFI_OUT_OF_RESOURCES Cannot allocate resources
678
679 --*/
680 {
681 EFI_STATUS Status;
682 EHCI_QTD_HW *QtdHwPtr;
683
684 ASSERT (HcDev);
685 ASSERT (QtdPtrPtr);
686
687 //
688 // Create memory for Qtd structure
689 //
690 Status = EhciAllocatePool (
691 HcDev,
692 (UINT8 **) QtdPtrPtr,
693 sizeof (EHCI_QTD_ENTITY)
694 );
695 if (EFI_ERROR (Status)) {
696 Status = EFI_OUT_OF_RESOURCES;
697 goto exit;
698 }
699 //
700 // Init fields in Qtd
701 //
702
703 ZeroMem (*QtdPtrPtr, sizeof (EHCI_QTD_ENTITY));
704
705 //
706 // Software field
707 //
708 (*QtdPtrPtr)->TotalBytes = (UINT32) DataLen;
709 (*QtdPtrPtr)->StaticTotalBytes = (UINT32) DataLen;
710 (*QtdPtrPtr)->Prev = NULL;
711 (*QtdPtrPtr)->Next = NULL;
712
713 //
714 // Hardware field
715 //
716 QtdHwPtr = &((*QtdPtrPtr)->Qtd);
717 QtdHwPtr->NextQtdPointer = 0;
718 QtdHwPtr->NextQtdTerminate = TRUE;
719 QtdHwPtr->AltNextQtdPointer = 0;
720 QtdHwPtr->AltNextQtdTerminate = TRUE;
721 QtdHwPtr->DataToggle = Toggle;
722 QtdHwPtr->TotalBytes = (UINT32) DataLen;
723 QtdHwPtr->CurrentPage = 0;
724 QtdHwPtr->ErrorCount = QTD_ERROR_COUNTER;
725 QtdHwPtr->Status = QtdStatus;
726 QtdHwPtr->Rsvd1 = 0;
727 QtdHwPtr->Rsvd2 = 0;
728 QtdHwPtr->Rsvd3 = 0;
729 QtdHwPtr->Rsvd4 = 0;
730 QtdHwPtr->Rsvd5 = 0;
731 QtdHwPtr->Rsvd6 = 0;
732
733 //
734 // Set PacketID [Setup/Data/Status]
735 //
736 switch (PktId) {
737 case SETUP_PACKET_ID:
738 QtdHwPtr->PidCode = SETUP_PACKET_PID_CODE;
739 break;
740
741 case INPUT_PACKET_ID:
742 QtdHwPtr->PidCode = INPUT_PACKET_PID_CODE;
743 break;
744
745 case OUTPUT_PACKET_ID:
746 QtdHwPtr->PidCode = OUTPUT_PACKET_PID_CODE;
747 break;
748
749 default:
750 Status = EFI_INVALID_PARAMETER;
751 goto exit;
752 }
753
754 //
755 // Set Data Buffer Pointers
756 //
757 if (NULL != DataPtr) {
758 SetQtdBufferPointer (
759 QtdHwPtr,
760 DataPtr,
761 DataLen
762 );
763 (*QtdPtrPtr)->StaticCurrentOffset = QtdHwPtr->CurrentOffset;
764 }
765
766 exit:
767 return Status;
768 }
769
770 EFI_STATUS
771 CreateSetupQtd (
772 IN USB2_HC_DEV *HcDev,
773 IN UINT8 *DevReqPtr,
774 OUT EHCI_QTD_ENTITY **QtdPtrPtr
775 )
776 /*++
777
778 Routine Description:
779
780 Create Qtd Structure for Setup
781
782 Arguments:
783
784 HcDev - USB2_HC_DEV
785 DevReqPtr - A pointer to Device Request Data
786 QtdPtrPtr - A pointer of pointer to Qtd for return
787
788 Returns:
789
790 EFI_SUCCESS Success
791 EFI_OUT_OF_RESOURCES Cannot allocate resources
792
793 --*/
794 {
795 return CreateQtd (
796 HcDev,
797 DevReqPtr,
798 sizeof (EFI_USB_DEVICE_REQUEST),
799 SETUP_PACKET_ID,
800 DATA0,
801 QTD_STATUS_ACTIVE,
802 QtdPtrPtr
803 );
804 }
805
806 EFI_STATUS
807 CreateDataQtd (
808 IN USB2_HC_DEV *HcDev,
809 IN UINT8 *DataPtr,
810 IN UINTN DataLen,
811 IN UINT8 PktId,
812 IN UINT8 Toggle,
813 OUT EHCI_QTD_ENTITY **QtdPtrPtr
814 )
815 /*++
816
817 Routine Description:
818
819 Create Qtd Structure for data
820
821 Arguments:
822
823 HcDev - USB2_HC_DEV
824 DataPtr - A pointer to user data buffer to transfer
825 DataLen - Length of user data to transfer
826 PktId - Packet Identification of this Qtd
827 Toggle - Data Toggle of this Qtd
828 QtdPtrPtr - A pointer of pointer to Qtd for return
829
830 Returns:
831
832 EFI_SUCCESS Success
833 EFI_OUT_OF_RESOURCES Cannot allocate resources
834
835 --*/
836 {
837 return CreateQtd (
838 HcDev,
839 DataPtr,
840 DataLen,
841 PktId,
842 Toggle,
843 QTD_STATUS_ACTIVE,
844 QtdPtrPtr
845 );
846 }
847
848 EFI_STATUS
849 CreateAltQtd (
850 IN USB2_HC_DEV *HcDev,
851 IN UINT8 PktId,
852 OUT EHCI_QTD_ENTITY **QtdPtrPtr
853 )
854 /*++
855
856 Routine Description:
857
858 Create Qtd Structure for Alternative
859
860 Arguments:
861
862 HcDev - USB2_HC_DEV
863 PktId - Packet Identification of this Qtd
864 QtdPtrPtr - A pointer of pointer to Qtd for return
865
866 Returns:
867
868 EFI_SUCCESS Success
869 EFI_OUT_OF_RESOURCES Cannot allocate resources
870
871 --*/
872 {
873 return CreateQtd (
874 HcDev,
875 NULL,
876 0,
877 PktId,
878 0,
879 QTD_STATUS_ACTIVE,
880 QtdPtrPtr
881 );
882 }
883
884 EFI_STATUS
885 CreateStatusQtd (
886 IN USB2_HC_DEV *HcDev,
887 IN UINT8 PktId,
888 OUT EHCI_QTD_ENTITY **QtdPtrPtr
889 )
890 /*++
891
892 Routine Description:
893
894 Create Qtd Structure for status
895
896 Arguments:
897
898 HcDev - USB2_HC_DEV
899 PktId - Packet Identification of this Qtd
900 QtdPtrPtr - A pointer of pointer to Qtd for return
901
902 Returns:
903
904 EFI_SUCCESS Success
905 EFI_OUT_OF_RESOURCES Cannot allocate resources
906
907 --*/
908 {
909 return CreateQtd (
910 HcDev,
911 NULL,
912 0,
913 PktId,
914 DATA1,
915 QTD_STATUS_ACTIVE,
916 QtdPtrPtr
917 );
918 }
919
920 EFI_STATUS
921 CreateControlQtds (
922 IN USB2_HC_DEV *HcDev,
923 IN UINT8 DataPktId,
924 IN UINT8 *RequestCursor,
925 IN UINT8 *DataCursor,
926 IN UINTN DataLen,
927 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
928 OUT EHCI_QTD_ENTITY **ControlQtdsHead
929 )
930 /*++
931
932 Routine Description:
933
934 Create Qtds list for Control Transfer
935
936 Arguments:
937
938 HcDev - USB2_HC_DEV
939 DataPktId - Packet Identification of Data Qtds
940 RequestCursor - A pointer to request structure buffer to transfer
941 DataCursor - A pointer to user data buffer to transfer
942 DataLen - Length of user data to transfer
943 ControlQtdsHead - A pointer of pointer to first Qtd for control tranfer for return
944
945 Returns:
946
947 EFI_SUCCESS Success
948 EFI_OUT_OF_RESOURCES Cannot allocate resources
949
950 --*/
951 {
952 EFI_STATUS Status;
953 EHCI_QTD_ENTITY *QtdPtr;
954 EHCI_QTD_ENTITY *PreQtdPtr;
955 EHCI_QTD_ENTITY *SetupQtdPtr;
956 EHCI_QTD_ENTITY *FirstDataQtdPtr;
957 EHCI_QTD_ENTITY *LastDataQtdPtr;
958 EHCI_QTD_ENTITY *StatusQtdPtr;
959 UINT8 DataToggle;
960 UINT8 StatusPktId;
961 UINTN CapacityOfQtd;
962 UINTN SizePerQtd;
963 UINTN DataCount;
964 UINTN Xnum;
965
966 QtdPtr = NULL;
967 PreQtdPtr = NULL;
968 SetupQtdPtr = NULL;
969 FirstDataQtdPtr = NULL;
970 LastDataQtdPtr = NULL;
971 StatusQtdPtr = NULL;
972 CapacityOfQtd = 0;
973
974 //
975 // Setup Stage of Control Transfer
976 //
977 Status = CreateSetupQtd (
978 HcDev,
979 RequestCursor,
980 &SetupQtdPtr
981 );
982 if (EFI_ERROR (Status)) {
983 Status = EFI_OUT_OF_RESOURCES;
984 goto exit;
985 }
986
987 //
988 // Data Stage of Control Transfer
989 //
990 DataToggle = 1;
991 DataCount = DataLen;
992
993 //
994 // Create Qtd structure and link together
995 //
996 while (DataCount > 0) {
997 //
998 // PktSize is the data load size that each Qtd.
999 //
1000 CapacityOfQtd = GetCapacityOfQtd (DataCursor);
1001 SizePerQtd = DataCount;
1002 if (DataCount > CapacityOfQtd) {
1003 SizePerQtd = CapacityOfQtd;
1004 }
1005
1006 Status = CreateDataQtd (
1007 HcDev,
1008 DataCursor,
1009 SizePerQtd,
1010 DataPktId,
1011 DataToggle,
1012 &QtdPtr
1013 );
1014 if (EFI_ERROR (Status)) {
1015 Status = EFI_OUT_OF_RESOURCES;
1016 if (NULL == FirstDataQtdPtr) {
1017 goto destory_setup_qtd;
1018 } else {
1019 goto destory_qtds;
1020 }
1021 }
1022
1023 if (NULL == FirstDataQtdPtr) {
1024 FirstDataQtdPtr = QtdPtr;
1025 } else {
1026 LinkQtdToQtd (PreQtdPtr, QtdPtr);
1027 }
1028
1029 //
1030 // Reverse Data Toggle or not determined by parity of transactions of one qtd
1031 //
1032 Xnum = Translator ? GetNumberOfTransaction (SizePerQtd, EHCI_BLOCK_SIZE_WITH_TT) : GetNumberOfTransaction (SizePerQtd, EHCI_BLOCK_SIZE);
1033 if (Xnum % 2 != 0) {
1034 DataToggle ^= 1;
1035 }
1036
1037 PreQtdPtr = QtdPtr;
1038 DataCursor += SizePerQtd;
1039 DataCount -= SizePerQtd;
1040 }
1041
1042 LastDataQtdPtr = QtdPtr;
1043
1044 //
1045 // Status Stage of Control Transfer
1046 //
1047 if (OUTPUT_PACKET_ID == DataPktId) {
1048 StatusPktId = INPUT_PACKET_ID;
1049 } else {
1050 StatusPktId = OUTPUT_PACKET_ID;
1051 }
1052
1053 Status = CreateStatusQtd (
1054 HcDev,
1055 StatusPktId,
1056 &StatusQtdPtr
1057 );
1058 if (EFI_ERROR (Status)) {
1059 Status = EFI_OUT_OF_RESOURCES;
1060 goto destory_qtds;
1061 }
1062
1063 //
1064 // Link setup Qtd -> data Qtds -> status Qtd
1065 //
1066 if (FirstDataQtdPtr != NULL) {
1067 LinkQtdToQtd (SetupQtdPtr, FirstDataQtdPtr);
1068 LinkQtdToQtd (LastDataQtdPtr, StatusQtdPtr);
1069 } else {
1070 LinkQtdToQtd (SetupQtdPtr, StatusQtdPtr);
1071 }
1072
1073 *ControlQtdsHead = SetupQtdPtr;
1074
1075 goto exit;
1076
1077 destory_qtds:
1078 DestoryQtds (HcDev, FirstDataQtdPtr);
1079 destory_setup_qtd:
1080 DestoryQtds (HcDev, SetupQtdPtr);
1081 exit:
1082 return Status;
1083 }
1084
1085 EFI_STATUS
1086 CreateBulkOrInterruptQtds (
1087 IN USB2_HC_DEV *HcDev,
1088 IN UINT8 PktId,
1089 IN UINT8 *DataCursor,
1090 IN UINTN DataLen,
1091 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
1092 OUT EHCI_QTD_ENTITY **QtdsHead
1093 )
1094 /*++
1095
1096 Routine Description:
1097
1098 Create Qtds list for Bulk or Interrupt Transfer
1099
1100 Arguments:
1101
1102 HcDev - USB2_HC_DEV
1103 PktId - Packet Identification of Qtds
1104 DataCursor - A pointer to user data buffer to transfer
1105 DataLen - Length of user data to transfer
1106 DataToggle - Data Toggle to start
1107 Translator - Translator Transaction for SplitX
1108 QtdsHead - A pointer of pointer to first Qtd for control tranfer for return
1109
1110 Returns:
1111
1112 EFI_SUCCESS Success
1113 EFI_OUT_OF_RESOURCES Cannot allocate resources
1114
1115 --*/
1116 {
1117 EFI_STATUS Status;
1118 EHCI_QTD_ENTITY *QtdPtr;
1119 EHCI_QTD_ENTITY *PreQtdPtr;
1120 EHCI_QTD_ENTITY *FirstQtdPtr;
1121 EHCI_QTD_ENTITY *AltQtdPtr;
1122 UINTN DataCount;
1123 UINTN CapacityOfQtd;
1124 UINTN SizePerQtd;
1125
1126 Status = EFI_SUCCESS;
1127 QtdPtr = NULL;
1128 PreQtdPtr = NULL;
1129 FirstQtdPtr = NULL;
1130 AltQtdPtr = NULL;
1131 CapacityOfQtd = 0;
1132
1133 DataCount = DataLen;
1134 while (DataCount > 0) {
1135
1136 CapacityOfQtd = GetCapacityOfQtd (DataCursor);
1137 SizePerQtd = DataCount;
1138 if (DataCount > CapacityOfQtd) {
1139 SizePerQtd = CapacityOfQtd;
1140 }
1141
1142 Status = CreateDataQtd (
1143 HcDev,
1144 DataCursor,
1145 SizePerQtd,
1146 PktId,
1147 0,
1148 &QtdPtr
1149 );
1150 if (EFI_ERROR (Status)) {
1151 Status = EFI_OUT_OF_RESOURCES;
1152 if (NULL == FirstQtdPtr) {
1153 goto exit;
1154 } else {
1155 goto destory_qtds;
1156 }
1157 }
1158
1159 if (NULL == FirstQtdPtr) {
1160 FirstQtdPtr = QtdPtr;
1161 } else {
1162 LinkQtdToQtd (PreQtdPtr, QtdPtr);
1163 }
1164
1165 PreQtdPtr = QtdPtr;
1166 DataCursor += SizePerQtd;
1167 DataCount -= SizePerQtd;
1168 }
1169
1170 //
1171 // Set Alternate Qtd
1172 //
1173 if (INPUT_PACKET_ID == PktId && 1 < GetNumberOfQtd (FirstQtdPtr)) {
1174 Status = CreateAltQtd (
1175 HcDev,
1176 PktId,
1177 &AltQtdPtr
1178 );
1179 if (EFI_ERROR (Status)) {
1180 Status = EFI_OUT_OF_RESOURCES;
1181 goto destory_qtds;
1182 }
1183
1184 LinkQtdsToAltQtd (FirstQtdPtr, AltQtdPtr);
1185 }
1186
1187 *QtdsHead = FirstQtdPtr;
1188 goto exit;
1189
1190 destory_qtds:
1191 DestoryQtds (HcDev, FirstQtdPtr);
1192 exit:
1193 return Status;
1194 }
1195
1196 VOID
1197 DestoryQtds (
1198 IN USB2_HC_DEV *HcDev,
1199 IN EHCI_QTD_ENTITY *FirstQtdPtr
1200 )
1201 /*++
1202
1203 Routine Description:
1204
1205 Destory all Qtds in the list
1206
1207 Arguments:
1208
1209 HcDev - USB2_HC_DEV
1210 FirstQtdPtr - A pointer to first Qtd in the list
1211
1212 Returns:
1213
1214 VOID
1215
1216 --*/
1217 {
1218 EHCI_QTD_ENTITY *PrevQtd;
1219 EHCI_QTD_ENTITY *NextQtd;
1220
1221 if (!FirstQtdPtr) {
1222 goto exit;
1223 }
1224
1225 PrevQtd = FirstQtdPtr;
1226
1227 //
1228 // Delete all the Qtds.
1229 //
1230 do {
1231 NextQtd = PrevQtd->Next;
1232 EhciFreePool (HcDev, (UINT8 *) PrevQtd, sizeof (EHCI_QTD_ENTITY));
1233 PrevQtd = NextQtd;
1234 } while (NULL != PrevQtd);
1235
1236 exit:
1237 return ;
1238 }
1239
1240 UINTN
1241 GetNumberOfQtd (
1242 IN EHCI_QTD_ENTITY *FirstQtdPtr
1243 )
1244 /*++
1245
1246 Routine Description:
1247
1248 Number of Qtds in the list
1249
1250 Arguments:
1251
1252 FirstQtdPtr - A pointer to first Qtd in the list
1253
1254 Returns:
1255
1256 Number of Qtds in the list
1257
1258 --*/
1259 {
1260 UINTN Count;
1261 EHCI_QTD_ENTITY *QtdPtr;
1262 Count = 0;
1263 QtdPtr = FirstQtdPtr;
1264
1265 ;
1266
1267 while (NULL != QtdPtr) {
1268 Count++;
1269 QtdPtr = QtdPtr->Next;
1270 }
1271
1272 return Count;
1273 }
1274
1275 UINTN
1276 GetNumberOfTransaction (
1277 IN UINTN SizeOfData,
1278 IN UINTN SizeOfTransaction
1279 )
1280 /*++
1281
1282 Routine Description:
1283
1284 Number of Transactions in one Qtd
1285
1286 Arguments:
1287
1288 SizeOfData - Size of one Qtd
1289 SizeOfTransaction - Size of one Transaction
1290
1291 Returns:
1292
1293 Number of Transactions in this Qtd
1294
1295 --*/
1296 {
1297
1298 return ((SizeOfData & (SizeOfTransaction - 1)) ? SizeOfData / SizeOfTransaction + 1 : SizeOfData / SizeOfTransaction);
1299
1300 }
1301
1302 UINTN
1303 GetCapacityOfQtd (
1304 IN UINT8 *BufferCursor
1305 )
1306 /*++
1307
1308 Routine Description:
1309
1310 Get Size of First Qtd
1311
1312 Arguments:
1313
1314 BufferCursor - BufferCursor of the Qtd
1315
1316 Returns:
1317
1318 Size of First Qtd
1319
1320 --*/
1321 {
1322
1323 return (EHCI_MAX_QTD_CAPACITY - (EHCI_BLOCK_SIZE * GetNumberOfTransaction (EFI_PAGE_MASK & GET_0B_TO_31B (BufferCursor), EHCI_BLOCK_SIZE)));
1324
1325 }
1326
1327 UINTN
1328 GetApproxiOfInterval (
1329 IN UINTN Interval
1330 )
1331 /*++
1332
1333 Routine Description:
1334
1335 Get the approximate value in the 2 index sequence
1336
1337 Arguments:
1338
1339 Interval - the value of interval
1340
1341 Returns:
1342
1343 approximate value of interval in the 2 index sequence
1344
1345 --*/
1346 {
1347 UINTN Orignate;
1348 UINTN Approxi;
1349
1350 Orignate = Interval;
1351 Approxi = 1;
1352
1353 while (Orignate != 1 && Orignate != 0) {
1354 Orignate = Orignate >> 1;
1355 Approxi = Approxi << 1;
1356 }
1357
1358 if (Interval & (Approxi >> 1)) {
1359 Approxi = Approxi << 1;
1360 }
1361
1362 return Approxi;
1363 }
1364
1365 EHCI_QTD_HW *
1366 GetQtdAlternateNextPointer (
1367 IN EHCI_QTD_HW *HwQtdPtr
1368 )
1369 /*++
1370
1371 Routine Description:
1372
1373 Get Qtd alternate next pointer field
1374
1375 Arguments:
1376
1377 HwQtdPtr - A pointer to hardware Qtd structure
1378
1379 Returns:
1380
1381 A pointer to hardware alternate Qtd
1382
1383 --*/
1384 {
1385 EHCI_QTD_HW *Value;
1386
1387 Value = NULL;
1388
1389 if (!HwQtdPtr->AltNextQtdTerminate) {
1390 Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->AltNextQtdPointer << 5);
1391 }
1392
1393 return Value;
1394 }
1395
1396 EHCI_QTD_HW *
1397 GetQtdNextPointer (
1398 IN EHCI_QTD_HW *HwQtdPtr
1399 )
1400 /*++
1401
1402 Routine Description:
1403
1404 Get Qtd next pointer field
1405
1406 Arguments:
1407
1408 HwQtdPtr - A pointer to hardware Qtd structure
1409
1410 Returns:
1411
1412 A pointer to next hardware Qtd structure
1413
1414 --*/
1415 {
1416 EHCI_QTD_HW *Value;
1417
1418 Value = NULL;
1419
1420 if (!HwQtdPtr->NextQtdTerminate) {
1421 Value = (EHCI_QTD_HW *) GET_0B_TO_31B (HwQtdPtr->NextQtdPointer << 5);
1422 }
1423
1424 return Value;
1425 }
1426
1427 VOID LinkQtdToQtd (
1428 IN EHCI_QTD_ENTITY * PreQtdPtr,
1429 IN EHCI_QTD_ENTITY * QtdPtr
1430 )
1431 /*++
1432
1433 Routine Description:
1434
1435 Link Qtds together
1436
1437 Arguments:
1438
1439 PreQtdPtr - A pointer to pre Qtd
1440 QtdPtr - A pointer to next Qtd
1441
1442 Returns:
1443
1444 VOID
1445
1446 --*/
1447 {
1448 EHCI_QTD_HW *QtdHwPtr;
1449
1450 ASSERT(PreQtdPtr);
1451 ASSERT(QtdPtr);
1452
1453 //
1454 // Software link
1455 //
1456 PreQtdPtr->Next = QtdPtr;
1457 QtdPtr->Prev = PreQtdPtr;
1458
1459 //
1460 // Hardware link
1461 //
1462 QtdHwPtr = &(QtdPtr->Qtd);
1463 PreQtdPtr->Qtd.NextQtdPointer = (UINT32) (GET_0B_TO_31B(QtdHwPtr) >> 5);
1464 PreQtdPtr->Qtd.NextQtdTerminate = FALSE;
1465
1466 return ;
1467 }
1468
1469
1470 VOID LinkQtdsToAltQtd (
1471 IN EHCI_QTD_ENTITY * FirstQtdPtr,
1472 IN EHCI_QTD_ENTITY * AltQtdPtr
1473 )
1474 /*++
1475
1476 Routine Description:
1477
1478 Link AlterQtds together
1479
1480 Arguments:
1481
1482 FirstQtdPtr - A pointer to first Qtd in the list
1483 AltQtdPtr - A pointer to alternative Qtd
1484
1485 Returns:
1486
1487 VOID
1488
1489 --*/
1490 {
1491 EHCI_QTD_ENTITY *QtdPtr;
1492 EHCI_QTD_HW *AltQtdHwPtr;
1493
1494 ASSERT(FirstQtdPtr);
1495 ASSERT(AltQtdPtr);
1496
1497 AltQtdHwPtr = &(AltQtdPtr->Qtd);
1498 QtdPtr = FirstQtdPtr;
1499
1500 while (NULL != QtdPtr) {
1501 //
1502 // Software link
1503 //
1504 QtdPtr->AltNext = AltQtdPtr;
1505 //
1506 // Hardware link
1507 //
1508 QtdPtr->Qtd.AltNextQtdPointer = (UINT32) (GET_0B_TO_31B(AltQtdHwPtr) >> 5);
1509 QtdPtr->Qtd.AltNextQtdTerminate = FALSE;
1510 QtdPtr = QtdPtr->Next;
1511 }
1512
1513 return ;
1514 }
1515
1516 VOID
1517 LinkQtdToQh (
1518 IN EHCI_QH_ENTITY *QhPtr,
1519 IN EHCI_QTD_ENTITY *QtdPtr
1520 )
1521 /*++
1522
1523 Routine Description:
1524
1525 Link Qtds list to Qh
1526
1527 Arguments:
1528
1529 QhPtr - A pointer to Qh
1530 QtdPtr - A pointer to first Qtd in the list
1531
1532 Returns:
1533
1534 VOID
1535
1536 --*/
1537 {
1538 EHCI_QTD_ENTITY *Cursor;
1539 EHCI_QTD_HW *QtdHwPtr;
1540
1541 ASSERT (QhPtr);
1542 ASSERT (QtdPtr);
1543
1544 QhPtr->FirstQtdPtr = QtdPtr;
1545 if (NULL != QtdPtr->AltNext) {
1546 QhPtr->AltQtdPtr = QtdPtr->AltNext;
1547 }
1548
1549 Cursor = QtdPtr;
1550 while (NULL != Cursor) {
1551 Cursor->SelfQh = QhPtr;
1552 if (NULL == Cursor->Next) {
1553 QhPtr->LastQtdPtr = Cursor;
1554 }
1555
1556 Cursor = Cursor->Next;
1557 }
1558
1559 QtdHwPtr = &(QtdPtr->Qtd);
1560 QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (QtdHwPtr) >> 5);
1561 QhPtr->Qh.NextQtdTerminate = FALSE;
1562
1563 return ;
1564 }
1565
1566 EFI_STATUS
1567 LinkQhToAsyncList (
1568 IN USB2_HC_DEV *HcDev,
1569 IN EHCI_QH_ENTITY *QhPtr
1570 )
1571 /*++
1572
1573 Routine Description:
1574
1575 Link Qh to Async Schedule List
1576
1577 Arguments:
1578
1579 HcDev - USB2_HC_DEV
1580 QhPtr - A pointer to Qh
1581
1582 Returns:
1583
1584 EFI_SUCCESS Success
1585 EFI_DEVICE_ERROR Fail
1586
1587 --*/
1588 {
1589 EFI_STATUS Status;
1590
1591 ASSERT (HcDev);
1592 ASSERT (QhPtr);
1593
1594 QhPtr->Qh.HeadReclamationFlag = TRUE;
1595
1596 Status = SetAsyncListAddr (HcDev, QhPtr);
1597 if (EFI_ERROR (Status)) {
1598 Status = EFI_DEVICE_ERROR;
1599 goto exit;
1600 }
1601
1602 if (!IsAsyncScheduleEnabled (HcDev)) {
1603
1604 Status = EnableAsynchronousSchedule (HcDev);
1605 if (EFI_ERROR (Status)) {
1606 Status = EFI_DEVICE_ERROR;
1607 goto exit;
1608 }
1609
1610 Status = WaitForAsyncScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
1611 if (EFI_ERROR (Status)) {
1612 DEBUG ((gEHCDebugLevel, "WaitForAsyncScheduleEnable TimeOut"));
1613 Status = EFI_TIMEOUT;
1614 goto exit;
1615 }
1616
1617 if (IsEhcHalted (HcDev)) {
1618 Status = StartScheduleExecution (HcDev);
1619 if (EFI_ERROR (Status)) {
1620 Status = EFI_DEVICE_ERROR;
1621 }
1622 }
1623
1624 }
1625
1626 exit:
1627 return Status;
1628 }
1629
1630 EFI_STATUS
1631 UnlinkQhFromAsyncList (
1632 IN USB2_HC_DEV *HcDev,
1633 IN EHCI_QH_ENTITY *QhPtr
1634 )
1635 /*++
1636
1637 Routine Description:
1638
1639 Unlink Qh from Async Schedule List
1640
1641 Arguments:
1642
1643 HcDev - USB2_HC_DEV
1644 QhPtr - A pointer to Qh
1645
1646 Returns:
1647
1648 EFI_SUCCESS Success
1649 EFI_DEVICE_ERROR Fail
1650
1651 --*/
1652 {
1653 EFI_STATUS Status;
1654
1655 Status = EFI_SUCCESS;
1656
1657 ASSERT (HcDev);
1658 ASSERT (QhPtr);
1659
1660 if (QhPtr == QhPtr->Next) {
1661
1662 Status = DisableAsynchronousSchedule (HcDev);
1663 if (EFI_ERROR (Status)) {
1664 Status = EFI_DEVICE_ERROR;
1665 goto exit;
1666 }
1667
1668 Status = WaitForAsyncScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
1669 if (EFI_ERROR (Status)) {
1670 DEBUG ((gEHCErrorLevel, "WaitForAsyncScheduleDisable TimeOut\n"));
1671 Status = EFI_TIMEOUT;
1672 goto exit;
1673 }
1674
1675 }
1676
1677 exit:
1678 return Status;
1679 }
1680
1681 VOID
1682 LinkQhToPeriodicList (
1683 IN USB2_HC_DEV *HcDev,
1684 IN EHCI_QH_ENTITY *QhPtr
1685 )
1686 /*++
1687
1688 Routine Description:
1689
1690 Link Qh to Periodic Schedule List
1691
1692 Arguments:
1693
1694 HcDev - USB2_HC_DEV
1695 QhPtr - A pointer to Qh
1696
1697 Returns:
1698
1699 VOID
1700
1701 --*/
1702 {
1703 FRAME_LIST_ENTRY *FrameEntryPtr;
1704 EHCI_QH_ENTITY *FindQhPtr;
1705 EHCI_QH_HW *FindQhHwPtr;
1706 UINTN FrameIndex;
1707
1708 ASSERT (HcDev);
1709 ASSERT (QhPtr);
1710
1711 FindQhPtr = NULL;
1712 FindQhHwPtr = NULL;
1713 FrameIndex = 0;
1714 FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
1715
1716 QhPtr->Qh.HeadReclamationFlag = FALSE;
1717
1718 if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {
1719
1720 //
1721 // AsyncInterruptTransfer Qh
1722 //
1723
1724 //
1725 // Link to Frame[0] List
1726 //
1727 if (!FrameEntryPtr->LinkTerminate) {
1728 //
1729 // Not Null FrameList
1730 //
1731 FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
1732 FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
1733 //
1734 // FindQh is Left/Right to Qh
1735 //
1736 while ((NULL != FindQhPtr->Next) && (FindQhPtr->Interval > QhPtr->Interval)) {
1737 FindQhPtr = FindQhPtr->Next;
1738 }
1739
1740 if (FindQhPtr->Interval == QhPtr->Interval) {
1741 //
1742 // Link Qh after FindQh
1743 //
1744 if (NULL != FindQhPtr->Next) {
1745 FindQhPtr->Next->Prev = QhPtr;
1746 QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Next->Qh) >> 5);
1747 QhPtr->Qh.SelectType = QH_SELECT_TYPE;
1748 QhPtr->Qh.QhTerminate = FALSE;
1749 }
1750
1751 FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1752 FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;
1753 FindQhPtr->Qh.QhTerminate = FALSE;
1754
1755 QhPtr->Prev = FindQhPtr;
1756 QhPtr->Next = FindQhPtr->Next;
1757 FindQhPtr->Next = QhPtr;
1758 } else if (FindQhPtr->Interval < QhPtr->Interval) {
1759 //
1760 // Link Qh before FindQh
1761 //
1762 if (NULL == FindQhPtr->Prev) {
1763 //
1764 // Qh is the First one in Frame[0] List
1765 //
1766 FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1767 FrameEntryPtr->SelectType = QH_SELECT_TYPE;
1768 FrameEntryPtr->LinkTerminate = FALSE;
1769 } else {
1770 //
1771 // Qh is not the First one in Frame[0] List
1772 //
1773 FindQhPtr->Prev->Next = QhPtr;
1774 FindQhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1775 FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
1776 FindQhPtr->Prev->Qh.QhTerminate = FALSE;
1777 }
1778
1779 QhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(FindQhPtr->Qh) >> 5);
1780 QhPtr->Qh.SelectType = QH_SELECT_TYPE;
1781 QhPtr->Qh.QhTerminate = FALSE;
1782
1783 QhPtr->Next = FindQhPtr;
1784 QhPtr->Prev = FindQhPtr->Prev;
1785 FindQhPtr->Prev = QhPtr;
1786 } else {
1787 //
1788 // Link Qh after FindQh, Qh is the Last one
1789 //
1790 FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1791 FindQhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
1792 FindQhPtr->Qh.QhTerminate = FALSE;
1793
1794 QhPtr->Prev = FindQhPtr;
1795 QhPtr->Next = NULL;
1796 FindQhPtr->Next = QhPtr;
1797 }
1798 } else {
1799 //
1800 // Null FrameList
1801 //
1802 FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1803 FrameEntryPtr->SelectType = QH_SELECT_TYPE;
1804 FrameEntryPtr->LinkTerminate = FALSE;
1805 }
1806 //
1807 // Other Frame[X]
1808 //
1809 if (NULL == QhPtr->Prev) {
1810 //
1811 // Qh is the First one in Frame[0] List
1812 //
1813 FrameIndex += QhPtr->Interval;
1814 while (FrameIndex < HcDev->PeriodicFrameListLength) {
1815 FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
1816 FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1817 FrameEntryPtr->SelectType = QH_SELECT_TYPE;
1818 FrameEntryPtr->LinkTerminate = FALSE;
1819 FrameIndex += QhPtr->Interval;
1820 }
1821 } else if (QhPtr->Interval < QhPtr->Prev->Interval) {
1822 //
1823 // Qh is not the First one in Frame[0] List, and Prev.interval > Qh.interval
1824 //
1825 FrameIndex += QhPtr->Interval;
1826 while (FrameIndex < HcDev->PeriodicFrameListLength) {
1827 FrameEntryPtr = (FRAME_LIST_ENTRY *) (FrameEntryPtr + QhPtr->Interval);
1828 if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
1829 FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1830 FrameEntryPtr->SelectType = QH_SELECT_TYPE;
1831 FrameEntryPtr->LinkTerminate = FALSE;
1832 }
1833
1834 FrameIndex += QhPtr->Interval;
1835 }
1836 }
1837 } else {
1838
1839 //
1840 // SyncInterruptTransfer Qh
1841 //
1842
1843 if (!FrameEntryPtr->LinkTerminate) {
1844 //
1845 // Not Null FrameList
1846 //
1847 FindQhHwPtr = (EHCI_QH_HW *) GET_0B_TO_31B (FrameEntryPtr->LinkPointer << 5);
1848 FindQhPtr = (EHCI_QH_ENTITY *) GET_QH_ENTITY_ADDR (FindQhHwPtr);
1849 //
1850 // FindQh is Last Qh in the Asynchronous List, Link Qh after FindQh
1851 //
1852 while (NULL != FindQhPtr->Next) {
1853 FindQhPtr = FindQhPtr->Next;
1854 }
1855
1856 FindQhPtr->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1857 FindQhPtr->Qh.SelectType = QH_SELECT_TYPE;
1858 FindQhPtr->Qh.QhTerminate = FALSE;
1859
1860 FindQhPtr->Next = QhPtr;
1861 QhPtr->Prev = FindQhPtr;
1862 } else {
1863 //
1864 // Null FrameList
1865 //
1866 FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Qh) >> 5);
1867 FrameEntryPtr->SelectType = QH_SELECT_TYPE;
1868 FrameEntryPtr->LinkTerminate = FALSE;
1869 }
1870 }
1871
1872 return ;
1873 }
1874
1875 VOID
1876 UnlinkQhFromPeriodicList (
1877 IN USB2_HC_DEV *HcDev,
1878 IN EHCI_QH_ENTITY *QhPtr,
1879 IN UINTN Interval
1880 )
1881 /*++
1882
1883 Routine Description:
1884
1885 Unlink Qh from Periodic Schedule List
1886
1887 Arguments:
1888
1889 HcDev - USB2_HC_DEV
1890 QhPtr - A pointer to Qh
1891 Interval - Interval of this periodic transfer
1892
1893 Returns:
1894
1895 VOID
1896
1897 --*/
1898 {
1899 FRAME_LIST_ENTRY *FrameEntryPtr;
1900 UINTN FrameIndex;
1901
1902 FrameIndex = 0;
1903
1904 ASSERT (HcDev);
1905 ASSERT (QhPtr);
1906
1907 FrameIndex = 0;
1908 FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;
1909
1910 if (QhPtr->TransferType == ASYNC_INTERRUPT_TRANSFER) {
1911
1912 //
1913 // AsyncInterruptTransfer Qh
1914 //
1915
1916 if (NULL == QhPtr->Prev) {
1917 //
1918 // Qh is the First one on Frame[0] List
1919 //
1920 if (NULL == QhPtr->Next) {
1921 //
1922 // Only one on Frame[0] List
1923 //
1924 while (FrameIndex < HcDev->PeriodicFrameListLength) {
1925 FrameEntryPtr->LinkPointer = 0;
1926 FrameEntryPtr->SelectType = 0;
1927 FrameEntryPtr->LinkTerminate = TRUE;
1928 FrameEntryPtr += Interval;
1929 FrameIndex += Interval;
1930 }
1931 } else {
1932 while (FrameIndex < HcDev->PeriodicFrameListLength) {
1933 FrameEntryPtr->LinkPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
1934 FrameEntryPtr->SelectType = QH_SELECT_TYPE;
1935 FrameEntryPtr->LinkTerminate = FALSE;
1936 FrameEntryPtr += Interval;
1937 FrameIndex += Interval;
1938 }
1939 }
1940 } else {
1941
1942 //
1943 // Not First one on Frame[0] List
1944 //
1945 if (NULL == QhPtr->Next) {
1946 //
1947 // Qh is the Last one on Frame[0] List
1948 //
1949 QhPtr->Prev->Qh.QhHorizontalPointer = 0;
1950 QhPtr->Prev->Qh.SelectType = 0;
1951 QhPtr->Prev->Qh.QhTerminate = TRUE;
1952 } else {
1953 QhPtr->Prev->Qh.QhHorizontalPointer = (UINT32) GET_0B_TO_31B (&(QhPtr->Next->Qh) >> 5);
1954 QhPtr->Prev->Qh.SelectType = QH_SELECT_TYPE;
1955 QhPtr->Prev->Qh.QhTerminate = FALSE;
1956 }
1957
1958 if (Interval == QhPtr->Prev->Interval) {
1959 //
1960 // Interval is the same as Prev
1961 // Not involed Frame[X]
1962 //
1963 } else {
1964 //
1965 // Other Frame[X]
1966 //
1967 while (FrameIndex < HcDev->PeriodicFrameListLength) {
1968 if ((FrameIndex % QhPtr->Prev->Interval) != 0) {
1969 FrameEntryPtr->LinkPointer = QhPtr->Prev->Qh.QhHorizontalPointer;
1970 FrameEntryPtr->SelectType = QhPtr->Prev->Qh.SelectType;
1971 FrameEntryPtr->LinkTerminate = QhPtr->Prev->Qh.QhTerminate;
1972 }
1973 FrameEntryPtr += Interval;
1974 FrameIndex += Interval;
1975 }
1976 }
1977 }
1978
1979 if (NULL != QhPtr->Next) {
1980 QhPtr->Next->Prev = QhPtr->Prev;
1981 }
1982
1983 if (NULL != QhPtr->Prev) {
1984 QhPtr->Prev->Next = QhPtr->Next;
1985 }
1986 } else {
1987 //
1988 // SyncInterruptTransfer Qh
1989 //
1990 if (NULL == QhPtr->Prev) {
1991 //
1992 // Qh is the only one Qh on Frame[0] List
1993 //
1994 FrameEntryPtr->LinkPointer = 0;
1995 FrameEntryPtr->SelectType = 0;
1996 FrameEntryPtr->LinkTerminate = TRUE;
1997 } else {
1998 QhPtr->Prev->Qh.QhHorizontalPointer = 0;
1999 QhPtr->Prev->Qh.SelectType = 0;
2000 QhPtr->Prev->Qh.QhTerminate = TRUE;
2001 }
2002
2003 if (NULL != QhPtr->Prev) {
2004 QhPtr->Prev->Next = NULL;
2005 }
2006 }
2007
2008 return ;
2009 }
2010
2011 VOID
2012 LinkToAsyncReqeust (
2013 IN USB2_HC_DEV *HcDev,
2014 IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
2015 )
2016 /*++
2017
2018 Routine Description:
2019
2020 Llink AsyncRequest Entry to Async Request List
2021
2022 Arguments:
2023
2024 HcDev - USB2_HC_DEV
2025 AsyncRequestPtr - A pointer to Async Request Entry
2026
2027 Returns:
2028
2029 VOID
2030
2031 --*/
2032 {
2033 EHCI_ASYNC_REQUEST *CurrentPtr;
2034
2035 CurrentPtr = HcDev->AsyncRequestList;
2036 HcDev->AsyncRequestList = AsyncRequestPtr;
2037 AsyncRequestPtr->Prev = NULL;
2038 AsyncRequestPtr->Next = CurrentPtr;
2039
2040 if (NULL != CurrentPtr) {
2041 CurrentPtr->Prev = AsyncRequestPtr;
2042 }
2043
2044 return ;
2045 }
2046
2047 VOID
2048 UnlinkFromAsyncReqeust (
2049 IN USB2_HC_DEV *HcDev,
2050 IN EHCI_ASYNC_REQUEST *AsyncRequestPtr
2051 )
2052 /*++
2053
2054 Routine Description:
2055
2056 Unlink AsyncRequest Entry from Async Request List
2057
2058 Arguments:
2059
2060 HcDev - USB2_HC_DEV
2061 AsyncRequestPtr - A pointer to Async Request Entry
2062
2063 Returns:
2064
2065 VOID
2066
2067 --*/
2068 {
2069 if (NULL == AsyncRequestPtr->Prev) {
2070 HcDev->AsyncRequestList = AsyncRequestPtr->Next;
2071 if (NULL != AsyncRequestPtr->Next) {
2072 AsyncRequestPtr->Next->Prev = NULL;
2073 }
2074 } else {
2075 AsyncRequestPtr->Prev->Next = AsyncRequestPtr->Next;
2076 if (NULL != AsyncRequestPtr->Next) {
2077 AsyncRequestPtr->Next->Prev = AsyncRequestPtr->Prev;
2078 }
2079 }
2080
2081 return ;
2082 }
2083
2084 VOID
2085 SetQtdBufferPointer (
2086 IN EHCI_QTD_HW *QtdHwPtr,
2087 IN VOID *DataPtr,
2088 IN UINTN DataLen
2089 )
2090 /*++
2091
2092 Routine Description:
2093
2094 Set data buffer pointers in Qtd
2095
2096 Arguments:
2097
2098 QtdHwPtr - A pointer to Qtd hardware structure
2099 DataPtr - A pointer to user data buffer
2100 DataLen - Length of the user data buffer
2101
2102 Returns:
2103
2104 VOID
2105
2106 --*/
2107 {
2108 UINTN RemainLen;
2109
2110 RemainLen = DataLen;
2111 ASSERT (QtdHwPtr);
2112
2113 //
2114 // Allow buffer address range across 4G.
2115 // But EFI_USB_MAX_BULK_BUFFER_NUM = 1, so don't allow
2116 // seperate buffer array.
2117 //
2118
2119 //
2120 // Set BufferPointer0, ExtBufferPointer0 and Offset
2121 //
2122 QtdHwPtr->BufferPointer0 = (UINT32) (GET_0B_TO_31B (DataPtr) >> 12);
2123 QtdHwPtr->CurrentOffset = (UINT32) (GET_0B_TO_31B (DataPtr) & EFI_PAGE_MASK);
2124 QtdHwPtr->ExtBufferPointer0 = (UINT32) GET_32B_TO_63B (DataPtr);
2125
2126 //
2127 // Set BufferPointer1 and ExtBufferPointer1
2128 //
2129 RemainLen = RemainLen > (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset) ? (RemainLen - (EFI_PAGE_SIZE - QtdHwPtr->CurrentOffset)) : 0;
2130 if (RemainLen == 0) {
2131 goto exit;
2132 }
2133
2134 QtdHwPtr->BufferPointer1 = QtdHwPtr->BufferPointer0 + 1;
2135 QtdHwPtr->ExtBufferPointer1 = (QtdHwPtr->BufferPointer1 == 0) ? (QtdHwPtr->ExtBufferPointer0 + 1) : QtdHwPtr->ExtBufferPointer0;
2136
2137 //
2138 // Set BufferPointer2 and ExtBufferPointer2
2139 //
2140 RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
2141 if (RemainLen == 0) {
2142 goto exit;
2143 }
2144
2145 QtdHwPtr->BufferPointer2 = QtdHwPtr->BufferPointer1 + 1;
2146 QtdHwPtr->ExtBufferPointer2 = (QtdHwPtr->BufferPointer2 == 0) ? (QtdHwPtr->ExtBufferPointer1 + 1) : QtdHwPtr->ExtBufferPointer1;
2147
2148 //
2149 // Set BufferPointer3 and ExtBufferPointer3
2150 //
2151 RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
2152 if (RemainLen == 0) {
2153 goto exit;
2154 }
2155
2156 QtdHwPtr->BufferPointer3 = QtdHwPtr->BufferPointer2 + 1;
2157 QtdHwPtr->ExtBufferPointer3 = (QtdHwPtr->BufferPointer2 == 0) ? (QtdHwPtr->ExtBufferPointer2 + 1) : QtdHwPtr->ExtBufferPointer2;
2158
2159 //
2160 // Set BufferPointer4 and ExtBufferPointer4
2161 //
2162 RemainLen = RemainLen > EFI_PAGE_SIZE ? (RemainLen - EFI_PAGE_SIZE) : 0;
2163 if (RemainLen == 0) {
2164 goto exit;
2165 }
2166
2167 QtdHwPtr->BufferPointer4 = QtdHwPtr->BufferPointer3 + 1;
2168 QtdHwPtr->ExtBufferPointer4 = (QtdHwPtr->BufferPointer3 == 0) ? (QtdHwPtr->ExtBufferPointer3 + 1) : QtdHwPtr->ExtBufferPointer3;
2169
2170 exit:
2171 return ;
2172 }
2173
2174 BOOLEAN
2175 IsQtdStatusActive (
2176 IN EHCI_QTD_HW *HwQtdPtr
2177 )
2178 /*++
2179
2180 Routine Description:
2181
2182 Whether Qtd status is active or not
2183
2184 Arguments:
2185
2186 HwQtdPtr - A pointer to hardware Qtd structure
2187
2188 Returns:
2189
2190 TRUE Active
2191 FALSE Inactive
2192
2193 --*/
2194 {
2195 UINT8 QtdStatus;
2196 BOOLEAN Value;
2197
2198 QtdStatus = (UINT8) (HwQtdPtr->Status);
2199 Value = (BOOLEAN) (QtdStatus & QTD_STATUS_ACTIVE);
2200
2201 return Value;
2202 }
2203
2204 BOOLEAN
2205 IsQtdStatusHalted (
2206 IN EHCI_QTD_HW *HwQtdPtr
2207 )
2208 /*++
2209
2210 Routine Description:
2211
2212 Whether Qtd status is halted or not
2213
2214 Arguments:
2215
2216 HwQtdPtr - A pointer to hardware Qtd structure
2217
2218 Returns:
2219
2220 TRUE Halted
2221 FALSE Not halted
2222
2223 --*/
2224 {
2225 UINT8 QtdStatus;
2226 BOOLEAN Value;
2227
2228 QtdStatus = (UINT8) (HwQtdPtr->Status);
2229 Value = (BOOLEAN) (QtdStatus & QTD_STATUS_HALTED);
2230
2231 return Value;
2232 }
2233
2234 BOOLEAN
2235 IsQtdStatusBufferError (
2236 IN EHCI_QTD_HW *HwQtdPtr
2237 )
2238 /*++
2239
2240 Routine Description:
2241
2242 Whether Qtd status is buffer error or not
2243
2244 Arguments:
2245
2246 HwQtdPtr - A pointer to hardware Qtd structure
2247
2248 Returns:
2249
2250 TRUE Buffer error
2251 FALSE No buffer error
2252
2253 --*/
2254 {
2255 UINT8 QtdStatus;
2256 BOOLEAN Value;
2257
2258 QtdStatus = (UINT8) (HwQtdPtr->Status);
2259 Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BUFFER_ERR);
2260
2261 return Value;
2262 }
2263
2264 BOOLEAN
2265 IsQtdStatusBabbleError (
2266 IN EHCI_QTD_HW *HwQtdPtr
2267 )
2268 /*++
2269
2270 Routine Description:
2271
2272 Whether Qtd status is babble error or not
2273
2274 Arguments:
2275
2276 HwQtdPtr - A pointer to hardware Qtd structure
2277
2278 Returns:
2279
2280 TRUE Babble error
2281 FALSE No babble error
2282
2283 --*/
2284 {
2285 UINT8 QtdStatus;
2286 BOOLEAN Value;
2287
2288 QtdStatus = (UINT8) (HwQtdPtr->Status);
2289 Value = (BOOLEAN) (QtdStatus & QTD_STATUS_BABBLE_ERR);
2290
2291 return Value;
2292 }
2293
2294 BOOLEAN
2295 IsQtdStatusTransactionError (
2296 IN EHCI_QTD_HW *HwQtdPtr
2297 )
2298 /*++
2299
2300 Routine Description:
2301
2302 Whether Qtd status is transaction error or not
2303
2304 Arguments:
2305
2306 HwQtdPtr - A pointer to hardware Qtd structure
2307
2308 Returns:
2309
2310 TRUE Transaction error
2311 FALSE No transaction error
2312
2313 --*/
2314 {
2315 UINT8 QtdStatus;
2316 BOOLEAN Value;
2317
2318 QtdStatus = (UINT8) (HwQtdPtr->Status);
2319 Value = (BOOLEAN) (QtdStatus & QTD_STATUS_TRANSACTION_ERR);
2320
2321 return Value;
2322 }
2323
2324 BOOLEAN
2325 IsDataInTransfer (
2326 IN UINT8 EndPointAddress
2327 )
2328 /*++
2329
2330 Routine Description:
2331
2332 Whether is a DataIn direction transfer
2333
2334 Arguments:
2335
2336 EndPointAddress - address of the endpoint
2337
2338 Returns:
2339
2340 TRUE DataIn
2341 FALSE DataOut
2342
2343 --*/
2344 {
2345 BOOLEAN Value;
2346
2347 if (EndPointAddress & 0x80) {
2348 Value = TRUE;
2349 } else {
2350 Value = FALSE;
2351 }
2352
2353 return Value;
2354 }
2355
2356 EFI_STATUS
2357 MapDataBuffer (
2358 IN USB2_HC_DEV *HcDev,
2359 IN EFI_USB_DATA_DIRECTION TransferDirection,
2360 IN VOID *Data,
2361 IN OUT UINTN *DataLength,
2362 OUT UINT8 *PktId,
2363 OUT UINT8 **DataCursor,
2364 OUT VOID **DataMap
2365 )
2366 /*++
2367
2368 Routine Description:
2369
2370 Map address of user data buffer
2371
2372 Arguments:
2373
2374 HcDev - USB2_HC_DEV
2375 TransferDirection - direction of transfer
2376 Data - A pointer to user data buffer
2377 DataLength - length of user data
2378 PktId - Packte Identificaion
2379 DataCursor - mapped address to return
2380 DataMap - identificaion of this mapping to return
2381
2382 Returns:
2383
2384 EFI_SUCCESS Success
2385 EFI_DEVICE_ERROR Fail
2386
2387 --*/
2388 {
2389 EFI_STATUS Status;
2390 EFI_PHYSICAL_ADDRESS TempPhysicalAddr;
2391
2392 Status = EFI_SUCCESS;
2393
2394 switch (TransferDirection) {
2395
2396 case EfiUsbDataIn:
2397
2398 *PktId = INPUT_PACKET_ID;
2399 //
2400 // BusMasterWrite means cpu read
2401 //
2402 Status = HcDev->PciIo->Map (
2403 HcDev->PciIo,
2404 EfiPciIoOperationBusMasterWrite,
2405 Data,
2406 DataLength,
2407 &TempPhysicalAddr,
2408 DataMap
2409 );
2410 if (EFI_ERROR (Status)) {
2411 DEBUG ((gEHCDebugLevel, "MapDataBuffer Failed\n"));
2412 Status = EFI_DEVICE_ERROR;
2413 goto exit;
2414 }
2415
2416 *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
2417 break;
2418
2419 case EfiUsbDataOut:
2420
2421 *PktId = OUTPUT_PACKET_ID;
2422 //
2423 // BusMasterRead means cpu write
2424 //
2425 Status = HcDev->PciIo->Map (
2426 HcDev->PciIo,
2427 EfiPciIoOperationBusMasterRead,
2428 Data,
2429 DataLength,
2430 &TempPhysicalAddr,
2431 DataMap
2432 );
2433 if (EFI_ERROR (Status)) {
2434 Status = EFI_DEVICE_ERROR;
2435 goto exit;
2436 }
2437
2438 *DataCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
2439 break;
2440
2441 case EfiUsbNoData:
2442
2443 *PktId = OUTPUT_PACKET_ID;
2444 Data = NULL;
2445 *DataLength = 0;
2446 *DataCursor = NULL;
2447 *DataMap = NULL;
2448 break;
2449
2450 default:
2451
2452 Status = EFI_INVALID_PARAMETER;
2453 }
2454
2455 exit:
2456 return Status;
2457 }
2458
2459 EFI_STATUS
2460 MapRequestBuffer (
2461 IN USB2_HC_DEV *HcDev,
2462 IN OUT VOID *Request,
2463 OUT UINT8 **RequestCursor,
2464 OUT VOID **RequestMap
2465 )
2466 /*++
2467
2468 Routine Description:
2469
2470 Map address of request structure buffer
2471
2472 Arguments:
2473
2474 HcDev - USB2_HC_DEV
2475 Request - A pointer to request structure
2476 RequestCursor - Mapped address of request structure to return
2477 RequestMap - Identificaion of this mapping to return
2478
2479 Returns:
2480
2481 EFI_SUCCESS Success
2482 EFI_DEVICE_ERROR Fail
2483
2484 --*/
2485 {
2486 EFI_STATUS Status;
2487 UINTN RequestLen;
2488 EFI_PHYSICAL_ADDRESS TempPhysicalAddr;
2489
2490 RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
2491 Status = HcDev->PciIo->Map (
2492 HcDev->PciIo,
2493 EfiPciIoOperationBusMasterRead,
2494 (UINT8 *) Request,
2495 (UINTN *) &RequestLen,
2496 &TempPhysicalAddr,
2497 RequestMap
2498 );
2499 if (EFI_ERROR (Status)) {
2500 Status = EFI_DEVICE_ERROR;
2501 goto exit;
2502 }
2503
2504 *RequestCursor = (UINT8 *) ((UINTN) TempPhysicalAddr);
2505
2506 exit:
2507 return Status;
2508 }
2509
2510 EFI_STATUS
2511 DeleteAsyncRequestTransfer (
2512 IN USB2_HC_DEV *HcDev,
2513 IN UINT8 DeviceAddress,
2514 IN UINT8 EndPointAddress,
2515 OUT UINT8 *DataToggle
2516 )
2517 /*++
2518
2519 Routine Description:
2520
2521 Delete all asynchronous request transfer
2522
2523 Arguments:
2524
2525 HcDev - USB2_HC_DEV
2526 DeviceAddress - address of usb device
2527 EndPointAddress - address of endpoint
2528 DataToggle - stored data toggle
2529
2530 Returns:
2531
2532 EFI_SUCCESS Success
2533 EFI_DEVICE_ERROR Fail
2534
2535 --*/
2536 {
2537 EFI_STATUS Status;
2538 EHCI_ASYNC_REQUEST *AsyncRequestPtr;
2539 EHCI_ASYNC_REQUEST *MatchPtr;
2540 EHCI_QH_HW *QhHwPtr;
2541 UINT8 EndPointNum;
2542
2543 if (NULL == HcDev->AsyncRequestList) {
2544 Status = EFI_INVALID_PARAMETER;
2545 goto exit;
2546 }
2547
2548 MatchPtr = NULL;
2549 QhHwPtr = NULL;
2550 EndPointNum = EndPointAddress & 0x0f;
2551 AsyncRequestPtr = HcDev->AsyncRequestList;
2552
2553 //
2554 // Find QH of AsyncRequest by DeviceAddress and EndPointNum
2555 //
2556 do {
2557
2558 QhHwPtr = &(AsyncRequestPtr->QhPtr->Qh);
2559 if (QhHwPtr->DeviceAddr == DeviceAddress && QhHwPtr->EndpointNum == EndPointNum) {
2560 MatchPtr = AsyncRequestPtr;
2561 break;
2562 }
2563
2564 AsyncRequestPtr = AsyncRequestPtr->Next;
2565
2566 } while (NULL != AsyncRequestPtr);
2567
2568 if (NULL == MatchPtr) {
2569 Status = EFI_INVALID_PARAMETER;
2570 goto exit;
2571 }
2572
2573 Status = DisablePeriodicSchedule (HcDev);
2574 if (EFI_ERROR (Status)) {
2575 Status = EFI_DEVICE_ERROR;
2576 goto exit;
2577 }
2578
2579 Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);
2580 if (EFI_ERROR (Status)) {
2581 DEBUG ((gEHCErrorLevel, "WaitForPeriodicScheduleDisable TimeOut\n"));
2582 Status = EFI_TIMEOUT;
2583 goto exit;
2584 }
2585
2586 *DataToggle = (UINT8) MatchPtr->QhPtr->Qh.DataToggle;
2587 UnlinkQhFromPeriodicList (HcDev, MatchPtr->QhPtr, MatchPtr->QhPtr->Interval);
2588 UnlinkFromAsyncReqeust (HcDev, MatchPtr);
2589
2590 if (NULL == HcDev->AsyncRequestList) {
2591
2592 Status = StopPollingTimer (HcDev);
2593 if (EFI_ERROR (Status)) {
2594 Status = EFI_DEVICE_ERROR;
2595 goto exit;
2596 }
2597
2598 } else {
2599
2600 Status = EnablePeriodicSchedule (HcDev);
2601 if (EFI_ERROR (Status)) {
2602 Status = EFI_DEVICE_ERROR;
2603 goto exit;
2604 }
2605
2606 Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);
2607 if (EFI_ERROR (Status)) {
2608 DEBUG ((gEHCErrorLevel, "WaitForPeriodicScheduleEnable TimeOut\n"));
2609 Status = EFI_TIMEOUT;
2610 goto exit;
2611 }
2612
2613 if (IsEhcHalted (HcDev)) {
2614 Status = StartScheduleExecution (HcDev);
2615 if (EFI_ERROR (Status)) {
2616 Status = EFI_DEVICE_ERROR;
2617 goto exit;
2618 }
2619 }
2620
2621 }
2622
2623 DestoryQtds (HcDev, MatchPtr->QhPtr->FirstQtdPtr);
2624 DestoryQh (HcDev, MatchPtr->QhPtr);
2625 EhciFreePool (HcDev, (UINT8 *) MatchPtr, sizeof (EHCI_ASYNC_REQUEST));
2626
2627 exit:
2628 return Status;
2629 }
2630
2631 VOID
2632 CleanUpAllAsyncRequestTransfer (
2633 IN USB2_HC_DEV *HcDev
2634 )
2635 /*++
2636
2637 Routine Description:
2638
2639 Clean up all asynchronous request transfer
2640
2641 Arguments:
2642
2643 HcDev - USB2_HC_DEV
2644
2645 Returns:
2646
2647 VOID
2648
2649 --*/
2650 {
2651 EHCI_ASYNC_REQUEST *AsyncRequestPtr;
2652 EHCI_ASYNC_REQUEST *FreePtr;
2653
2654 AsyncRequestPtr = NULL;
2655 FreePtr = NULL;
2656
2657 StopPollingTimer (HcDev);
2658
2659 AsyncRequestPtr = HcDev->AsyncRequestList;
2660 while (NULL != AsyncRequestPtr) {
2661
2662 FreePtr = AsyncRequestPtr;
2663 AsyncRequestPtr = AsyncRequestPtr->Next;
2664 UnlinkFromAsyncReqeust (HcDev, FreePtr);
2665 UnlinkQhFromPeriodicList (HcDev, FreePtr->QhPtr, FreePtr->QhPtr->Interval);
2666 DestoryQtds (HcDev, FreePtr->QhPtr->FirstQtdPtr);
2667 DestoryQh (HcDev, FreePtr->QhPtr);
2668 EhciFreePool (HcDev, (UINT8 *) FreePtr, sizeof (EHCI_ASYNC_REQUEST));
2669
2670 }
2671
2672 return ;
2673 }
2674
2675 VOID
2676 ZeroOutQhOverlay (
2677 IN EHCI_QH_ENTITY *QhPtr
2678 )
2679 /*++
2680
2681 Routine Description:
2682
2683 Zero out the fields in Qh structure
2684
2685 Arguments:
2686
2687 QhPtr - A pointer to Qh structure
2688
2689 Returns:
2690
2691 VOID
2692
2693 --*/
2694 {
2695 QhPtr->Qh.CurrentQtdPointer = 0;
2696 QhPtr->Qh.AltNextQtdPointer = 0;
2697 QhPtr->Qh.NakCount = 0;
2698 QhPtr->Qh.AltNextQtdTerminate = 0;
2699 QhPtr->Qh.TotalBytes = 0;
2700 QhPtr->Qh.InterruptOnComplete = 0;
2701 QhPtr->Qh.CurrentPage = 0;
2702 QhPtr->Qh.ErrorCount = 0;
2703 QhPtr->Qh.PidCode = 0;
2704 QhPtr->Qh.Status = 0;
2705 QhPtr->Qh.BufferPointer0 = 0;
2706 QhPtr->Qh.CurrentOffset = 0;
2707 QhPtr->Qh.BufferPointer1 = 0;
2708 QhPtr->Qh.CompleteSplitMask = 0;
2709 QhPtr->Qh.BufferPointer2 = 0;
2710 QhPtr->Qh.SplitBytes = 0;
2711 QhPtr->Qh.FrameTag = 0;
2712 QhPtr->Qh.BufferPointer3 = 0;
2713 QhPtr->Qh.BufferPointer4 = 0;
2714 QhPtr->Qh.ExtBufferPointer0 = 0;
2715 QhPtr->Qh.ExtBufferPointer1 = 0;
2716 QhPtr->Qh.ExtBufferPointer2 = 0;
2717 QhPtr->Qh.ExtBufferPointer3 = 0;
2718 QhPtr->Qh.ExtBufferPointer4 = 0;
2719 }
2720
2721 VOID
2722 UpdateAsyncRequestTransfer (
2723 IN EHCI_ASYNC_REQUEST *AsyncRequestPtr,
2724 IN UINT32 TransferResult,
2725 IN UINTN ErrQtdPos
2726 )
2727 /*++
2728
2729 Routine Description:
2730
2731 Update asynchronous request transfer
2732
2733 Arguments:
2734
2735 AsyncRequestPtr - A pointer to async request
2736 TransferResult - transfer result
2737 ErrQtdPos - postion of error Qtd
2738
2739 Returns:
2740
2741 VOID
2742
2743 --*/
2744 {
2745 EHCI_QTD_ENTITY *QtdPtr;
2746
2747 QtdPtr = NULL;
2748
2749 if (EFI_USB_NOERROR == TransferResult) {
2750
2751 //
2752 // Update Qh for next trigger
2753 //
2754
2755 QtdPtr = AsyncRequestPtr->QhPtr->FirstQtdPtr;
2756
2757 //
2758 // Update fields in Qh
2759 //
2760
2761 //
2762 // Get DataToggle from Overlay in Qh
2763 //
2764 // ZeroOut Overlay in Qh except DataToggle, HostController will update this field
2765 //
2766 ZeroOutQhOverlay (AsyncRequestPtr->QhPtr);
2767 AsyncRequestPtr->QhPtr->Qh.NextQtdPointer = (UINT32) (GET_0B_TO_31B (&(QtdPtr->Qtd)) >> 5);
2768 AsyncRequestPtr->QhPtr->Qh.NextQtdTerminate = FALSE;
2769
2770 //
2771 // Update fields in Qtd
2772 //
2773 while (NULL != QtdPtr) {
2774 QtdPtr->Qtd.TotalBytes = QtdPtr->StaticTotalBytes;
2775 QtdPtr->Qtd.CurrentOffset = QtdPtr->StaticCurrentOffset;
2776 QtdPtr->Qtd.CurrentPage = 0;
2777 QtdPtr->Qtd.ErrorCount = QTD_ERROR_COUNTER;
2778 QtdPtr->Qtd.Status = QTD_STATUS_ACTIVE;
2779
2780 QtdPtr->TotalBytes = QtdPtr->StaticTotalBytes;
2781 QtdPtr = QtdPtr->Next;
2782 }
2783 }
2784
2785 return ;
2786 }
2787
2788 BOOLEAN
2789 CheckQtdsTransferResult (
2790 IN BOOLEAN IsControl,
2791 IN EHCI_QH_ENTITY *QhPtr,
2792 OUT UINT32 *Result,
2793 OUT UINTN *ErrQtdPos,
2794 OUT UINTN *ActualLen
2795 )
2796 /*++
2797
2798 Routine Description:
2799
2800 Check transfer result of Qtds
2801
2802 Arguments:
2803
2804 IsControl - Is control transfer or not
2805 QhPtr - A pointer to Qh
2806 Result - Transfer result
2807 ErrQtdPos - Error TD Position
2808 ActualLen - Actual Transfer Size
2809
2810 Returns:
2811
2812 TRUE Qtds finished
2813 FALSE Not finish
2814
2815 --*/
2816 {
2817 UINTN ActualLenPerQtd;
2818 EHCI_QTD_ENTITY *QtdPtr;
2819 EHCI_QTD_HW *QtdHwPtr;
2820 BOOLEAN Value;
2821
2822 ASSERT (QhPtr);
2823 ASSERT (Result);
2824 ASSERT (ErrQtdPos);
2825 ASSERT (ActualLen);
2826
2827 Value = TRUE;
2828 QtdPtr = QhPtr->FirstQtdPtr;
2829 QtdHwPtr = &(QtdPtr->Qtd);
2830
2831 while (NULL != QtdHwPtr) {
2832
2833 if (IsQtdStatusActive (QtdHwPtr)) {
2834 *Result |= EFI_USB_ERR_NOTEXECUTE;
2835 }
2836
2837 if (IsQtdStatusHalted (QtdHwPtr)) {
2838 *Result |= EFI_USB_ERR_STALL;
2839 }
2840
2841 if (IsQtdStatusBufferError (QtdHwPtr)) {
2842 *Result |= EFI_USB_ERR_BUFFER;
2843 }
2844
2845 if (IsQtdStatusBabbleError (QtdHwPtr)) {
2846 *Result |= EFI_USB_ERR_BABBLE;
2847 }
2848
2849 if (IsQtdStatusTransactionError (QtdHwPtr)) {
2850 *Result |= EFI_USB_ERR_TIMEOUT;
2851 }
2852
2853 ActualLenPerQtd = QtdPtr->TotalBytes - QtdHwPtr->TotalBytes;
2854 QtdPtr->TotalBytes = QtdHwPtr->TotalBytes;
2855 //
2856 // Accumulate actual transferred data length in each DataQtd.
2857 //
2858 if (SETUP_PACKET_PID_CODE != QtdHwPtr->PidCode) {
2859 *ActualLen += ActualLenPerQtd;
2860 }
2861
2862 if (*Result) {
2863 Value = FALSE;
2864 break;
2865 }
2866
2867 if ((!IsControl) && (QtdPtr->TotalBytes > 0)) {
2868 //
2869 // Did something, but isn't full workload
2870 //
2871 break;
2872 }
2873
2874 (*ErrQtdPos)++;
2875 QtdPtr = QtdPtr->Next;
2876 QtdHwPtr = &(QtdPtr->Qtd);
2877
2878 }
2879
2880 return Value;
2881 }
2882
2883 EFI_STATUS
2884 ExecuteTransfer (
2885 IN USB2_HC_DEV *HcDev,
2886 IN BOOLEAN IsControl,
2887 IN EHCI_QH_ENTITY *QhPtr,
2888 IN OUT UINTN *ActualLen,
2889 OUT UINT8 *DataToggle,
2890 IN UINTN TimeOut,
2891 OUT UINT32 *TransferResult
2892 )
2893 /*++
2894
2895 Routine Description:
2896
2897 Execute Bulk or SyncInterrupt Transfer
2898
2899 Arguments:
2900
2901 HcDev - USB2_HC_DEV
2902 IsControl - Is control transfer or not
2903 QhPtr - A pointer to Qh
2904 ActualLen - Actual transfered Len
2905 DataToggle - Data Toggle
2906 TimeOut - TimeOut threshold
2907 TransferResult - Transfer result
2908
2909 Returns:
2910
2911 EFI_SUCCESS Sucess
2912 EFI_DEVICE_ERROR Fail
2913
2914 --*/
2915 {
2916 EFI_STATUS Status;
2917 UINTN ErrQtdPos;
2918 UINTN Delay;
2919 UINTN RequireLen;
2920 BOOLEAN Finished;
2921
2922 Status = EFI_SUCCESS;
2923 ErrQtdPos = 0;
2924 *TransferResult = EFI_USB_NOERROR;
2925 RequireLen = *ActualLen;
2926 *ActualLen = 0;
2927 Finished = FALSE;
2928
2929 Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
2930
2931 do {
2932 *TransferResult = 0;
2933 Finished = CheckQtdsTransferResult (
2934 IsControl,
2935 QhPtr,
2936 TransferResult,
2937 &ErrQtdPos,
2938 ActualLen
2939 );
2940 if (Finished) {
2941 break;
2942 }
2943 //
2944 // Qtd is inactive, which means bulk or interrupt transfer's end.
2945 //
2946 if (!(*TransferResult & EFI_USB_ERR_NOTEXECUTE)) {
2947 break;
2948 }
2949
2950 gBS->Stall (EHCI_SYNC_REQUEST_POLLING_TIME);
2951
2952 } while (--Delay);
2953
2954 if (EFI_USB_NOERROR != *TransferResult) {
2955 if (0 == Delay) {
2956 Status = EFI_TIMEOUT;
2957 } else {
2958 Status = EFI_DEVICE_ERROR;
2959 }
2960 }
2961
2962 //
2963 // Special for Bulk and Interrupt Transfer
2964 //
2965 *DataToggle = (UINT8) QhPtr->Qh.DataToggle;
2966
2967 return Status;
2968 }
2969
2970 EFI_STATUS
2971 AsyncRequestMoniter (
2972 IN EFI_EVENT Event,
2973 IN VOID *Context
2974 )
2975 /*++
2976 Routine Description:
2977
2978 Interrupt transfer periodic check handler
2979
2980 Arguments:
2981 Event - Interrupt event
2982 Context - Pointer to USB2_HC_DEV
2983
2984 Returns:
2985
2986 EFI_SUCCESS Success
2987 EFI_DEVICE_ERROR Fail
2988
2989 --*/
2990 {
2991 EFI_STATUS Status;
2992 USB2_HC_DEV *HcDev;
2993 EHCI_ASYNC_REQUEST *AsyncRequestPtr;
2994 EHCI_QTD_HW *QtdHwPtr;
2995 UINTN ErrQtdPos;
2996 UINTN ActualLen;
2997 UINT32 TransferResult;
2998 UINT8 *ReceiveBuffer;
2999 UINT8 *ProcessBuffer;
3000 EHCI_ASYNC_REQUEST *NextPtr;
3001
3002 Status = EFI_SUCCESS;
3003 QtdHwPtr = NULL;
3004 ReceiveBuffer = NULL;
3005 ProcessBuffer = NULL;
3006 HcDev = (USB2_HC_DEV *) Context;
3007 AsyncRequestPtr = HcDev->AsyncRequestList;
3008
3009 while (NULL != AsyncRequestPtr) {
3010
3011 TransferResult = 0;
3012 ErrQtdPos = 0;
3013 ActualLen = 0;
3014
3015 CheckQtdsTransferResult (
3016 FALSE,
3017 AsyncRequestPtr->QhPtr,
3018 &TransferResult,
3019 &ErrQtdPos,
3020 &ActualLen
3021 );
3022
3023 if ((TransferResult & EFI_USB_ERR_NAK) || (TransferResult & EFI_USB_ERR_NOTEXECUTE)) {
3024 AsyncRequestPtr = AsyncRequestPtr->Next;
3025 continue;
3026 }
3027 //
3028 // Allocate memory for EHC private data structure
3029 //
3030 ProcessBuffer = AllocateZeroPool (ActualLen);
3031 if (NULL == ProcessBuffer) {
3032 Status = EFI_OUT_OF_RESOURCES;
3033 goto exit;
3034 }
3035
3036 QtdHwPtr = &(AsyncRequestPtr->QhPtr->FirstQtdPtr->Qtd);
3037 ReceiveBuffer = (UINT8 *) GET_0B_TO_31B ((QtdHwPtr->BufferPointer0 << 12) | AsyncRequestPtr->QhPtr->FirstQtdPtr->StaticCurrentOffset);
3038 CopyMem (
3039 ProcessBuffer,
3040 ReceiveBuffer,
3041 ActualLen
3042 );
3043
3044 UpdateAsyncRequestTransfer (AsyncRequestPtr, TransferResult, ErrQtdPos);
3045
3046 NextPtr = AsyncRequestPtr->Next;
3047
3048 if (EFI_USB_NOERROR == TransferResult) {
3049
3050 if (AsyncRequestPtr->CallBackFunc != NULL) {
3051 (AsyncRequestPtr->CallBackFunc) (ProcessBuffer, ActualLen, AsyncRequestPtr->Context, TransferResult);
3052 }
3053
3054 } else {
3055
3056 //
3057 // leave error recovery to its related device driver. A common case of
3058 // the error recovery is to re-submit the interrupt transfer.
3059 // When an interrupt transfer is re-submitted, its position in the linked
3060 // list is changed. It is inserted to the head of the linked list, while
3061 // this function scans the whole list from head to tail. Thus, the
3062 // re-submitted interrupt transfer's callback function will not be called
3063 // again in this round.
3064 //
3065 if (AsyncRequestPtr->CallBackFunc != NULL) {
3066 (AsyncRequestPtr->CallBackFunc) (NULL, 0, AsyncRequestPtr->Context, TransferResult);
3067 }
3068
3069 }
3070
3071 if (NULL != ProcessBuffer) {
3072 gBS->FreePool (ProcessBuffer);
3073 }
3074
3075 AsyncRequestPtr = NextPtr;
3076 }
3077
3078 exit:
3079 return Status;
3080 }
3081