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