]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c
Remove some unused internal functions.
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Uhci / Dxe / uhchlp.c
CommitLineData
878ddf1f 1/*++\r
2\r
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
11\r
12Module Name:\r
13\r
14 UhcHlp.c\r
15 \r
16Abstract: \r
17 \r
18\r
19Revision History\r
20--*/\r
21\r
22#include "uhci.h"\r
23\r
1cc8ee78 24STATIC\r
878ddf1f 25EFI_STATUS\r
26USBReadPortW (\r
27 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
28 IN UINT32 PortOffset,\r
29 IN OUT UINT16 *Data\r
30 )\r
31/*++\r
32\r
33Routine Description:\r
34\r
35 USBReadPort Word\r
36\r
37Arguments:\r
38\r
39 PciIo - EFI_PCI_IO_PROTOCOL\r
40 PortOffset - Port offset\r
41 Data - Data to reutrn\r
42\r
43Returns:\r
44\r
45 EFI_SUCCESS\r
46\r
47--*/\r
48{\r
49 //\r
50 // Perform 16bit Read in PCI IO Space\r
51 //\r
52 return PciIo->Io.Read (\r
562d2849 53 PciIo,\r
54 EfiPciIoWidthUint16,\r
55 USB_BAR_INDEX,\r
56 (UINT64) PortOffset,\r
57 1,\r
58 Data\r
59 );\r
878ddf1f 60}\r
61\r
1cc8ee78 62STATIC\r
878ddf1f 63EFI_STATUS\r
64USBWritePortW (\r
65 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
66 IN UINT32 PortOffset,\r
67 IN UINT16 Data\r
68 )\r
69/*++\r
70\r
71Routine Description:\r
72\r
73 USB Write Port Word\r
74\r
75Arguments:\r
76\r
77 PciIo - EFI_PCI_IO_PROTOCOL\r
78 PortOffset - Port offset\r
79 Data - Data to write\r
80\r
81Returns:\r
82\r
83 EFI_SUCCESS\r
84\r
85--*/\r
86{\r
87 //\r
88 // Perform 16bit Write in PCI IO Space\r
89 //\r
90 return PciIo->Io.Write (\r
562d2849 91 PciIo,\r
92 EfiPciIoWidthUint16,\r
93 USB_BAR_INDEX,\r
94 (UINT64) PortOffset,\r
95 1,\r
96 &Data\r
97 );\r
878ddf1f 98}\r
99\r
1cc8ee78 100STATIC\r
878ddf1f 101EFI_STATUS\r
102USBWritePortDW (\r
103 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
104 IN UINT32 PortOffset,\r
105 IN UINT32 Data\r
106 )\r
107/*++\r
108\r
109Routine Description:\r
110\r
111 USB Write Port DWord\r
112\r
113Arguments:\r
114\r
115 PciIo - EFI_PCI_IO_PROTOCOL\r
116 PortOffset - Port offset\r
117 Data - Data to write\r
118\r
119Returns:\r
120\r
121 EFI_SUCCESS\r
122\r
123--*/\r
124{\r
125 //\r
126 // Perform 32bit Write in PCI IO Space\r
127 //\r
128 return PciIo->Io.Write (\r
562d2849 129 PciIo,\r
130 EfiPciIoWidthUint32,\r
131 USB_BAR_INDEX,\r
132 (UINT64) PortOffset,\r
133 1,\r
134 &Data\r
135 );\r
878ddf1f 136}\r
137//\r
138// USB register-base helper functions\r
139//\r
140EFI_STATUS\r
141WriteUHCCommandReg (\r
142 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
143 IN UINT32 CmdAddrOffset,\r
144 IN UINT16 UsbCmd\r
145 )\r
146/*++\r
147\r
148Routine Description:\r
149\r
150 Write UHCI Command Register\r
151\r
152Arguments:\r
153\r
154 PciIo - EFI_PCI_IO_PROTOCOL\r
155 CmdAddrOffset - Command address offset\r
156 UsbCmd - Data to write\r
157\r
158Returns:\r
159\r
160 EFI_SUCCESS\r
161\r
162--*/\r
163{\r
164 //\r
165 // Write to UHC's Command Register\r
166 //\r
167 return USBWritePortW (PciIo, CmdAddrOffset, UsbCmd);\r
168}\r
169\r
170EFI_STATUS\r
171ReadUHCCommandReg (\r
172 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
173 IN UINT32 CmdAddrOffset,\r
174 IN OUT UINT16 *Data\r
175 )\r
176/*++\r
177\r
178Routine Description:\r
179\r
180 Read UHCI Command Register\r
181\r
182Arguments:\r
183\r
184 PciIo - EFI_PCI_IO_PROTOCOL\r
185 CmdAddrOffset - Command address offset\r
186 Data - Data to return\r
187\r
188Returns:\r
189\r
190 EFI_SUCCESS\r
191\r
192--*/\r
193{\r
194 //\r
195 // Read from UHC's Command Register\r
196 //\r
197 return USBReadPortW (PciIo, CmdAddrOffset, Data);\r
198}\r
199\r
200EFI_STATUS\r
201WriteUHCStatusReg (\r
202 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
203 IN UINT32 StatusAddrOffset,\r
204 IN UINT16 UsbSts\r
205 )\r
206/*++\r
207\r
208Routine Description:\r
209\r
210 Write UHCI Staus Register\r
211\r
212Arguments:\r
213\r
214 PciIo - EFI_PCI_IO_PROTOCOL\r
215 StatusAddrOffset - Status address offset\r
216 UsbSts - Data to write\r
217\r
218Returns:\r
219\r
220 EFI_SUCCESS\r
221\r
222--*/\r
223{\r
224 //\r
225 // Write to UHC's Status Register\r
226 //\r
227 return USBWritePortW (PciIo, StatusAddrOffset, UsbSts);\r
228}\r
229\r
230EFI_STATUS\r
231ReadUHCStatusReg (\r
232 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
233 IN UINT32 StatusAddrOffset,\r
234 IN OUT UINT16 *Data\r
235 )\r
236/*++\r
237\r
238Routine Description:\r
239\r
240 Read UHCI Staus Register\r
241\r
242Arguments:\r
243\r
244 PciIo - EFI_PCI_IO_PROTOCOL\r
245 StatusAddrOffset - Status address offset\r
246 UsbSts - Data to return\r
247\r
248Returns:\r
249\r
250 EFI_SUCCESS\r
251\r
252--*/\r
253{\r
254 //\r
255 // Read from UHC's Status Register\r
256 //\r
257 return USBReadPortW (PciIo, StatusAddrOffset, Data);\r
258}\r
259\r
260\r
261EFI_STATUS\r
262ClearStatusReg (\r
263 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
264 IN UINT32 StatusAddrOffset\r
265 )\r
266/*++\r
267\r
268Routine Description:\r
269\r
270 Clear the content of UHC's Status Register\r
271\r
272Arguments:\r
273\r
274 PciIo - EFI_PCI_IO_PROTOCOL\r
275 StatusAddrOffset - Status address offset\r
276 \r
277Returns:\r
278\r
279 EFI_SUCCESS\r
280\r
281--*/\r
282{\r
283 \r
284 return WriteUHCStatusReg (PciIo, StatusAddrOffset, 0x003F);\r
285}\r
286\r
287EFI_STATUS\r
288ReadUHCFrameNumberReg (\r
289 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
290 IN UINT32 FrameNumAddrOffset,\r
291 IN OUT UINT16 *Data\r
292 )\r
293/*++\r
294\r
295Routine Description:\r
296\r
297 Read from UHC's Frame Number Register\r
298\r
299Arguments:\r
300\r
301 PciIo - EFI_PCI_IO_PROTOCOL\r
302 FrameNumAddrOffset - Frame number register offset\r
303 Data - Data to return \r
304Returns:\r
305\r
306 EFI_SUCCESS\r
307\r
308--*/\r
309{\r
310 \r
311 return USBReadPortW (PciIo, FrameNumAddrOffset, Data);\r
312}\r
313\r
314EFI_STATUS\r
315WriteUHCFrameListBaseReg (\r
316 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
317 IN UINT32 FlBaseAddrOffset,\r
318 IN UINT32 UsbFrameListBaseAddr\r
319 )\r
320/*++\r
321\r
322Routine Description:\r
323\r
324 Write to UHC's Frame List Base Register\r
325\r
326Arguments:\r
327\r
328 PciIo - EFI_PCI_IO_PROTOCOL\r
329 FlBaseAddrOffset - Frame Base address register\r
330 UsbFrameListBaseAddr - Address to write\r
331\r
332Returns:\r
333\r
334 EFI_SUCCESS\r
335\r
336--*/\r
337{\r
338 \r
339 return USBWritePortDW (PciIo, FlBaseAddrOffset, UsbFrameListBaseAddr);\r
340}\r
341\r
342EFI_STATUS\r
343ReadRootPortReg (\r
344 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
345 IN UINT32 PortAddrOffset,\r
346 IN OUT UINT16 *Data\r
347 )\r
348/*++\r
349\r
350Routine Description:\r
351\r
352 Read from UHC's Root Port Register\r
353\r
354Arguments:\r
355\r
356 PciIo - EFI_PCI_IO_PROTOCOL\r
357 PortAddrOffset - Port Addrress Offset,\r
358 Data - Data to return\r
359Returns:\r
360\r
361 EFI_SUCCESS\r
362\r
363--*/\r
364{\r
365 \r
366 return USBReadPortW (PciIo, PortAddrOffset, Data);\r
367}\r
368\r
369EFI_STATUS\r
370WriteRootPortReg (\r
371 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
372 IN UINT32 PortAddrOffset,\r
373 IN UINT16 ControlBits\r
374 )\r
375/*++\r
376\r
377Routine Description:\r
378\r
379 Write to UHC's Root Port Register\r
380\r
381Arguments:\r
382\r
383 PciIo - EFI_PCI_IO_PROTOCOL\r
384 PortAddrOffset - Port Addrress Offset,\r
385 ControlBits - Data to write\r
386Returns:\r
387\r
388 EFI_SUCCESS\r
389\r
390--*/\r
391{\r
392 \r
393 return USBWritePortW (PciIo, PortAddrOffset, ControlBits);\r
394}\r
395\r
396\r
397\r
398EFI_STATUS\r
399WaitForUHCHalt (\r
400 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
401 IN UINT32 StatusRegAddr,\r
402 IN UINTN Timeout\r
403 )\r
404/*++\r
405\r
406Routine Description:\r
407\r
408 Wait until UHCI halt or timeout\r
409\r
410Arguments:\r
411\r
412 PciIo - EFI_PCI_IO_PROTOCOL\r
413 StatusRegAddr - Status Register Address\r
414 Timeout - Time out value in us\r
415\r
416Returns:\r
417\r
418 EFI_DEVICE_ERROR - Unable to read the status register\r
419 EFI_TIMEOUT - Time out\r
420 EFI_SUCCESS - Success\r
421\r
422--*/\r
423{\r
424 UINTN Delay;\r
425 EFI_STATUS Status;\r
426 UINT16 HcStatus;\r
427\r
428 //\r
429 // Timeout is in us unit\r
430 //\r
431 Delay = (Timeout / 50) + 1;\r
432 do {\r
433 Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);\r
434 if (EFI_ERROR (Status)) {\r
435 return EFI_DEVICE_ERROR;\r
436 }\r
437\r
438 if ((HcStatus & USBSTS_HCH) == USBSTS_HCH) {\r
439 break;\r
440 }\r
441 //\r
442 // Stall for 50 us\r
443 //\r
444 gBS->Stall (50);\r
445\r
446 } while (Delay--);\r
447\r
448 if (Delay == 0) {\r
449 return EFI_TIMEOUT;\r
450 }\r
451\r
452 return EFI_SUCCESS;\r
453}\r
454\r
455BOOLEAN\r
456IsStatusOK (\r
457 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
458 IN UINT32 StatusRegAddr\r
459 )\r
460/*++\r
461\r
462Routine Description:\r
463\r
464 Judge whether the host controller operates well\r
465\r
466Arguments:\r
467\r
468 PciIo - EFI_PCI_IO_PROTOCOL\r
469 StatusRegAddr - Status register address\r
470\r
471Returns:\r
472\r
473 TRUE - Status is good\r
474 FALSE - Status is bad\r
475\r
476--*/\r
477{\r
478 EFI_STATUS Status;\r
479 UINT16 HcStatus;\r
480 //\r
481 // Detect whether the interrupt is caused by fatal error.\r
482 // see "UHCI Design Guid".\r
483 //\r
484 Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);\r
485 if (EFI_ERROR (Status)) {\r
486 return FALSE;\r
487 }\r
488\r
489 if (HcStatus & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) {\r
490 return FALSE;\r
491 } else {\r
492 return TRUE;\r
493 }\r
494\r
495}\r
496\r
497\r
498BOOLEAN \r
499IsHostSysOrProcessErr (\r
500 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
501 IN UINT32 StatusRegAddr\r
502 )\r
503/*++\r
504\r
505Routine Description:\r
506\r
507 Judge the status is HostSys,ProcessErr error or good\r
508\r
509Arguments:\r
510\r
511 PciIo - EFI_PCI_IO_PROTOCOL\r
512 StatusRegAddr - Status register address\r
513\r
514Returns:\r
515\r
516 TRUE - Status is good\r
517 FALSE - Status is bad\r
518\r
519--*/\r
520{\r
521 EFI_STATUS Status;\r
522 UINT16 HcStatus;\r
523 //\r
524 // Detect whether the interrupt is caused by serious error.\r
525 // see "UHCI Design Guid".\r
526 //\r
527 Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);\r
528 if (EFI_ERROR (Status)) {\r
529 return FALSE;\r
530 }\r
531\r
532 if (HcStatus & (USBSTS_HSE | USBSTS_HCPE)) {\r
533 return TRUE;\r
534 } else {\r
535 return FALSE;\r
536 }\r
537}\r
538\r
539\r
540UINT16\r
541GetCurrentFrameNumber (\r
542 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
543 IN UINT32 FrameNumAddrOffset\r
544 )\r
545/*++\r
546\r
547Routine Description:\r
548\r
549 Get Current Frame Number\r
550\r
551Arguments:\r
552\r
553 PciIo - EFI_PCI_IO_PROTOCOL\r
554 FrameNumAddrOffset - FrameNum register AddrOffset\r
555\r
556Returns:\r
557\r
558 Frame number \r
559\r
560--*/\r
561{\r
562 //\r
563 // Gets value in the USB frame number register.\r
564 //\r
565 UINT16 FrameNumber;\r
566\r
567 ReadUHCFrameNumberReg (PciIo, FrameNumAddrOffset, &FrameNumber);\r
568\r
569 return (UINT16) (FrameNumber & 0x03FF);\r
570}\r
571\r
572EFI_STATUS\r
573SetFrameListBaseAddress (\r
574 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
575 IN UINT32 FlBaseAddrReg,\r
576 IN UINT32 Addr\r
577 )\r
578/*++\r
579\r
580Routine Description:\r
581\r
582 Set FrameListBase Address\r
583\r
584Arguments:\r
585\r
586 PciIo - EFI_PCI_IO_PROTOCOL\r
587 FlBaseAddrReg - FrameListBase register\r
588 Addr - Address to set\r
589\r
590Returns:\r
591\r
592 EFI_SUCCESS\r
593\r
594--*/\r
595{\r
596 //\r
597 // Sets value in the USB Frame List Base Address register.\r
598 //\r
599 return WriteUHCFrameListBaseReg (PciIo, FlBaseAddrReg, (UINT32) (Addr & 0xFFFFF000));\r
600}\r
601\r
602VOID\r
603EnableMaxPacketSize (\r
604 IN USB_HC_DEV *HcDev\r
605 )\r
606/*++\r
607\r
608Routine Description:\r
609\r
610 Enable Max Packet Size\r
611\r
612Arguments:\r
613\r
614 HcDev - USB_HC_DEV\r
615\r
616Returns:\r
617\r
618 VOID\r
619\r
620--*/\r
621{\r
622 UINT16 CommandContent;\r
878ddf1f 623\r
1cc8ee78 624 ReadUHCCommandReg (\r
625 HcDev->PciIo,\r
626 (UINT32) (USBCMD),\r
627 &CommandContent\r
628 );\r
878ddf1f 629\r
630 if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) {\r
631 CommandContent |= USBCMD_MAXP;\r
632 WriteUHCCommandReg (\r
633 HcDev->PciIo,\r
634 (UINT32) (USBCMD),\r
635 CommandContent\r
636 );\r
637 }\r
638\r
639 return ;\r
640}\r
641\r
642EFI_STATUS\r
643CreateFrameList (\r
644 IN USB_HC_DEV *HcDev,\r
645 IN UINT32 FlBaseAddrReg\r
646 )\r
647/*++\r
648\r
649Routine Description:\r
650\r
651 CreateFrameList\r
652\r
653Arguments:\r
654\r
655 HcDev - USB_HC_DEV\r
656 FlBaseAddrReg - Frame List register\r
657\r
658Returns:\r
659\r
660 EFI_OUT_OF_RESOURCES - Can't allocate memory resources\r
661 EFI_UNSUPPORTED - Map memory fail\r
662 EFI_SUCCESS - Success\r
663\r
664--*/\r
665{\r
666 EFI_STATUS Status;\r
667 VOID *CommonBuffer;\r
668 EFI_PHYSICAL_ADDRESS MappedAddress;\r
669 VOID *Mapping;\r
670 UINTN BufferSizeInPages;\r
671 UINTN BufferSizeInBytes;\r
672\r
673 //\r
674 // The Frame List is a common buffer that will be\r
675 // accessed by both the cpu and the usb bus master\r
676 // at the same time.\r
677 // The Frame List ocupies 4K bytes,\r
678 // and must be aligned on 4-Kbyte boundaries.\r
679 //\r
680 BufferSizeInBytes = 4096;\r
681 BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);\r
682 Status = HcDev->PciIo->AllocateBuffer (\r
562d2849 683 HcDev->PciIo,\r
684 AllocateAnyPages,\r
685 EfiBootServicesData,\r
686 BufferSizeInPages,\r
687 &CommonBuffer,\r
688 0\r
689 );\r
878ddf1f 690 if (EFI_ERROR (Status)) {\r
691 return EFI_OUT_OF_RESOURCES;\r
692 }\r
693\r
694 Status = HcDev->PciIo->Map (\r
562d2849 695 HcDev->PciIo,\r
696 EfiPciIoOperationBusMasterCommonBuffer,\r
697 CommonBuffer,\r
698 &BufferSizeInBytes,\r
699 &MappedAddress,\r
700 &Mapping\r
701 );\r
878ddf1f 702 if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) {\r
703 HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);\r
704 return EFI_UNSUPPORTED;\r
705 }\r
706\r
707 HcDev->FrameListEntry = (FRAMELIST_ENTRY *) ((UINTN) MappedAddress);\r
708\r
709 HcDev->FrameListMapping = Mapping;\r
710\r
711 InitFrameList (HcDev);\r
712\r
713 //\r
714 // Tell the Host Controller where the Frame List lies,\r
715 // by set the Frame List Base Address Register.\r
716 //\r
717 SetFrameListBaseAddress (\r
718 HcDev->PciIo,\r
719 FlBaseAddrReg,\r
720 (UINT32) ((UINTN) HcDev->FrameListEntry)\r
721 );\r
722\r
723 return EFI_SUCCESS;\r
724}\r
725\r
726EFI_STATUS\r
727FreeFrameListEntry (\r
728 IN USB_HC_DEV *HcDev\r
729 )\r
730/*++\r
731\r
732Routine Description:\r
733\r
734 Free FrameList buffer\r
735\r
736Arguments:\r
737\r
738 HcDev - USB_HC_DEV\r
739\r
740Returns:\r
741\r
742 EFI_SUCCESS - success\r
743\r
744--*/\r
745{\r
746 //\r
747 // Unmap the common buffer for framelist entry,\r
748 // and free the common buffer.\r
749 // Uhci's frame list occupy 4k memory.\r
750 //\r
751 HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->FrameListMapping);\r
752 HcDev->PciIo->FreeBuffer (\r
753 HcDev->PciIo,\r
754 EFI_SIZE_TO_PAGES (4096),\r
755 (VOID *) (HcDev->FrameListEntry)\r
756 );\r
757 return EFI_SUCCESS;\r
758}\r
759\r
760VOID\r
761InitFrameList (\r
762 IN USB_HC_DEV *HcDev\r
763 )\r
764/*++\r
765\r
766Routine Description:\r
767\r
768 Initialize FrameList\r
769\r
770Arguments:\r
771\r
772 HcDev - USB_HC_DEV\r
773\r
774Returns:\r
775 VOID\r
776\r
777--*/ \r
778{\r
779 FRAMELIST_ENTRY *FrameListPtr;\r
780 UINTN Index;\r
781\r
782 //\r
783 // Validate each Frame List Entry\r
784 //\r
785 FrameListPtr = HcDev->FrameListEntry;\r
786 for (Index = 0; Index < 1024; Index++) {\r
787 FrameListPtr->FrameListPtrTerminate = 1;\r
788 FrameListPtr->FrameListPtr = 0;\r
789 FrameListPtr->FrameListPtrQSelect = 0;\r
790 FrameListPtr->FrameListRsvd = 0;\r
791 FrameListPtr++;\r
792 }\r
793}\r
794//\r
795// //////////////////////////////////////////////////////////////\r
796//\r
797// QH TD related Helper Functions\r
798//\r
799////////////////////////////////////////////////////////////////\r
800//\r
801// functions for QH\r
802//\r
1cc8ee78 803STATIC\r
878ddf1f 804EFI_STATUS\r
805AllocateQHStruct (\r
806 IN USB_HC_DEV *HcDev,\r
807 OUT QH_STRUCT **ppQHStruct\r
808 )\r
809/*++\r
810\r
811Routine Description:\r
812\r
813 Allocate QH Struct\r
814\r
815Arguments:\r
816\r
817 HcDev - USB_HC_DEV\r
818 ppQHStruct - QH_STRUCT content to return\r
819Returns:\r
820\r
821 EFI_SUCCESS\r
822\r
823--*/\r
824{\r
825 *ppQHStruct = NULL;\r
826\r
827 //\r
828 // QH must align on 16 bytes alignment,\r
829 // since the memory allocated by UhciAllocatePool ()\r
830 // is aligned on 32 bytes, it is no need to adjust\r
831 // the allocated memory returned.\r
832 //\r
833 return UhciAllocatePool (HcDev, (UINT8 **) ppQHStruct, sizeof (QH_STRUCT));\r
834}\r
835\r
836\r
837EFI_STATUS\r
838CreateQH (\r
839 IN USB_HC_DEV *HcDev,\r
840 OUT QH_STRUCT **pptrQH\r
841 )\r
842/*++\r
843\r
844Routine Description:\r
845\r
846 CreateQH\r
847\r
848Arguments:\r
849\r
850 HcDev - USB_HC_DEV\r
851 ppQHStruct - QH_STRUCT content to return\r
852Returns:\r
853\r
854 EFI_SUCCESS - Success\r
855 EFI_OUT_OF_RESOURCES - Can't allocate memory\r
856--*/\r
857{\r
858 EFI_STATUS Status;\r
859\r
860 //\r
861 // allocate align memory for QH_STRUCT\r
862 //\r
863 Status = AllocateQHStruct (HcDev, pptrQH);\r
864 if (EFI_ERROR (Status)) {\r
865 return EFI_OUT_OF_RESOURCES;\r
866 }\r
867 //\r
868 // init each field of the QH_STRUCT\r
869 //\r
870 //\r
871 // Make QH ready\r
872 //\r
873 SetQHHorizontalValidorInvalid (*pptrQH, FALSE);\r
874 SetQHVerticalValidorInvalid (*pptrQH, FALSE);\r
875\r
876 return EFI_SUCCESS;\r
877}\r
878\r
879VOID\r
880SetQHHorizontalLinkPtr (\r
881 IN QH_STRUCT *PtrQH,\r
882 IN VOID *ptrNext\r
883 )\r
884/*++\r
885\r
886Routine Description:\r
887\r
888 Set QH Horizontal Link Pointer\r
889\r
890Arguments:\r
891\r
892 PtrQH - QH_STRUCT\r
893 ptrNext - Data to write \r
894\r
895Returns:\r
896\r
897 VOID\r
898\r
899--*/\r
900{\r
901 //\r
902 // Since the QH_STRUCT is aligned on 16-byte boundaries,\r
903 // Only the highest 28bit of the address is valid\r
904 // (take 32bit address as an example).\r
905 //\r
906 PtrQH->QH.QHHorizontalPtr = (UINT32) ((UINTN) ptrNext >> 4);\r
907}\r
908\r
909VOID *\r
910GetQHHorizontalLinkPtr (\r
911 IN QH_STRUCT *PtrQH\r
912 )\r
913/*++\r
914\r
915Routine Description:\r
916\r
917 Get QH Horizontal Link Pointer\r
918\r
919Arguments:\r
920\r
921 PtrQH - QH_STRUCT\r
922 \r
923\r
924Returns:\r
925\r
926 Data to return \r
927\r
928--*/\r
929{\r
930 //\r
931 // Restore the 28bit address to 32bit address\r
932 // (take 32bit address as an example)\r
933 //\r
934 return (VOID *) ((UINTN) (PtrQH->QH.QHHorizontalPtr << 4));\r
935}\r
936\r
937VOID\r
938SetQHHorizontalQHorTDSelect (\r
939 IN QH_STRUCT *PtrQH,\r
940 IN BOOLEAN bQH\r
941 )\r
942/*++\r
943\r
944Routine Description:\r
945\r
946 Set QH Horizontal QH or TD \r
947\r
948Arguments:\r
949\r
950 PtrQH - QH_STRUCT\r
951 bQH - TRUE is QH FALSE is TD\r
952\r
953Returns:\r
954 VOID\r
955\r
956--*/\r
957{\r
958 //\r
959 // if QH is connected, the specified bit is set,\r
960 // if TD is connected, the specified bit is cleared.\r
961 //\r
962 PtrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0;\r
963}\r
964\r
965\r
966VOID\r
967SetQHHorizontalValidorInvalid (\r
968 IN QH_STRUCT *PtrQH,\r
969 IN BOOLEAN bValid\r
970 )\r
971/*++\r
972\r
973Routine Description:\r
974\r
975 Set QH Horizontal Valid or Invalid\r
976\r
977Arguments:\r
978\r
979 PtrQH - QH_STRUCT\r
980 bValid - TRUE is Valid FALSE is Invalid\r
981\r
982Returns:\r
983 VOID\r
984\r
985--*/\r
986{\r
987 //\r
988 // Valid means the horizontal link pointer is valid,\r
989 // else, it's invalid.\r
990 //\r
991 PtrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1;\r
992}\r
993\r
994VOID\r
995SetQHVerticalLinkPtr (\r
996 IN QH_STRUCT *PtrQH,\r
997 IN VOID *ptrNext\r
998 )\r
999/*++\r
1000\r
1001Routine Description:\r
1002\r
1003 Set QH Vertical Link Pointer\r
1004 \r
1005Arguments:\r
1006\r
1007 PtrQH - QH_STRUCT\r
1008 ptrNext - Data to write\r
1009Returns:\r
1010\r
1011 VOID\r
1012\r
1013--*/\r
1014{\r
1015 //\r
1016 // Since the QH_STRUCT is aligned on 16-byte boundaries,\r
1017 // Only the highest 28bit of the address is valid\r
1018 // (take 32bit address as an example).\r
1019 //\r
1020 PtrQH->QH.QHVerticalPtr = (UINT32) ((UINTN) ptrNext >> 4);\r
1021}\r
1022\r
1023VOID *\r
1024GetQHVerticalLinkPtr (\r
1025 IN QH_STRUCT *PtrQH\r
1026 )\r
1027/*++\r
1028\r
1029Routine Description:\r
1030\r
1031 Get QH Vertical Link Pointer\r
1032 \r
1033Arguments:\r
1034\r
1035 PtrQH - QH_STRUCT\r
1036 \r
1037Returns:\r
1038\r
1039 Data to return\r
1040\r
1041--*/\r
1042{\r
1043 //\r
1044 // Restore the 28bit address to 32bit address\r
1045 // (take 32bit address as an example)\r
1046 //\r
1047 return (VOID *) ((UINTN) (PtrQH->QH.QHVerticalPtr << 4));\r
1048}\r
1049\r
1050VOID\r
1051SetQHVerticalQHorTDSelect (\r
1052 IN QH_STRUCT *PtrQH,\r
1053 IN BOOLEAN bQH\r
1054 )\r
1055/*++\r
1056\r
1057Routine Description:\r
1058\r
1059 Set QH Vertical QH or TD\r
1060\r
1061Arguments:\r
1062\r
1063 PtrQH - QH_STRUCT\r
1064 bQH - TRUE is QH FALSE is TD\r
1065\r
1066Returns:\r
1067\r
1068 VOID\r
1069\r
1070--*/\r
1071{\r
1072 //\r
1073 // Set the specified bit if the Vertical Link Pointer pointing to a QH,\r
1074 // Clear the specified bit if the Vertical Link Pointer pointing to a TD.\r
1075 //\r
1076 PtrQH->QH.QHVerticalQSelect = bQH ? 1 : 0;\r
1077}\r
1078\r
1079BOOLEAN\r
1080IsQHHorizontalQHSelect (\r
1081 IN QH_STRUCT *PtrQH\r
1082 )\r
1083/*++\r
1084\r
1085Routine Description:\r
1086\r
1087 Is QH Horizontal QH Select\r
1088\r
1089Arguments:\r
1090\r
1091 PtrQH - QH_STRUCT\r
1092 \r
1093Returns:\r
1094\r
1095 TRUE - QH\r
1096 FALSE - TD\r
1097\r
1098--*/\r
1099{\r
1100 //\r
1101 // Retrieve the information about whether the Horizontal Link Pointer\r
1102 // pointing to a QH or TD.\r
1103 //\r
1104 return (BOOLEAN) (PtrQH->QH.QHHorizontalQSelect ? TRUE : FALSE);\r
1105}\r
1106\r
1107VOID\r
1108SetQHVerticalValidorInvalid (\r
1109 IN QH_STRUCT *PtrQH,\r
1110 IN BOOLEAN IsValid\r
1111 )\r
1112/*++\r
1113\r
1114Routine Description:\r
1115\r
1116 Set QH Vertical Valid or Invalid\r
1117\r
1118Arguments:\r
1119\r
1120 PtrQH - QH_STRUCT\r
1121 IsValid - TRUE is valid FALSE is invalid\r
1122\r
1123Returns:\r
1124\r
1125 VOID\r
1126\r
1127--*/\r
1128{\r
1129 //\r
1130 // If TRUE, indicates the Vertical Link Pointer field is valid,\r
1131 // else, the field is invalid.\r
1132 //\r
1133 PtrQH->QH.QHVerticalTerminate = IsValid ? 0 : 1;\r
1134}\r
1135\r
1136\r
1137BOOLEAN\r
1138GetQHVerticalValidorInvalid (\r
1139 IN QH_STRUCT *PtrQH\r
1140 )\r
1141/*++\r
1142\r
1143Routine Description:\r
1144\r
1145 Get QH Vertical Valid or Invalid\r
1146\r
1147Arguments:\r
1148\r
1149 PtrQH - QH_STRUCT\r
1150\r
1151Returns:\r
1152\r
1153 TRUE - Valid\r
1154 FALSE - Invalid\r
1155\r
1156--*/\r
1157{\r
1158 //\r
1159 // If TRUE, indicates the Vertical Link Pointer field is valid,\r
1160 // else, the field is invalid.\r
1161 //\r
1162 return (BOOLEAN) (!(PtrQH->QH.QHVerticalTerminate));\r
1163}\r
1164\r
1cc8ee78 1165STATIC\r
878ddf1f 1166BOOLEAN\r
1167GetQHHorizontalValidorInvalid (\r
1168 IN QH_STRUCT *PtrQH\r
1169 )\r
1170/*++\r
1171\r
1172Routine Description:\r
1173\r
1174 Get QH Horizontal Valid or Invalid\r
1175\r
1176Arguments:\r
1177\r
1178 PtrQH - QH_STRUCT\r
1179\r
1180Returns:\r
1181\r
1182 TRUE - Valid\r
1183 FALSE - Invalid\r
1184\r
1185--*/\r
1186{\r
1187 //\r
1188 // If TRUE, meaning the Horizontal Link Pointer field is valid,\r
1189 // else, the field is invalid.\r
1190 //\r
1191 return (BOOLEAN) (!(PtrQH->QH.QHHorizontalTerminate));\r
1192}\r
1193//\r
1194// functions for TD\r
1195//\r
1196EFI_STATUS\r
1197AllocateTDStruct (\r
1198 IN USB_HC_DEV *HcDev,\r
1199 OUT TD_STRUCT **ppTDStruct\r
1200 )\r
1201/*++\r
1202\r
1203Routine Description:\r
1204\r
1205 Allocate TD Struct\r
1206\r
1207Arguments:\r
1208\r
1209 HcDev - USB_HC_DEV\r
1210 ppTDStruct - place to store TD_STRUCT pointer\r
1211Returns:\r
1212\r
1213 EFI_SUCCESS\r
1214\r
1215--*/\r
1216{\r
1217 *ppTDStruct = NULL;\r
1218\r
1219 //\r
1220 // TD must align on 16 bytes alignment,\r
1221 // since the memory allocated by UhciAllocatePool ()\r
1222 // is aligned on 32 bytes, it is no need to adjust\r
1223 // the allocated memory returned.\r
1224 //\r
1225 return UhciAllocatePool (\r
1226 HcDev,\r
1227 (UINT8 **) ppTDStruct,\r
1228 sizeof (TD_STRUCT)\r
1229 );\r
1230}\r
1231\r
1232EFI_STATUS\r
1233CreateTD (\r
1234 IN USB_HC_DEV *HcDev,\r
1235 OUT TD_STRUCT **pptrTD\r
1236 )\r
1237/*++\r
1238\r
1239Routine Description:\r
1240\r
1241 Create TD\r
1242\r
1243Arguments:\r
1244\r
1245 HcDev - USB_HC_DEV\r
1246 pptrTD - TD_STRUCT pointer to store\r
1247\r
1248Returns:\r
1249\r
1250 EFI_OUT_OF_RESOURCES - Can't allocate resources\r
1251 EFI_SUCCESS - Success\r
1252\r
1253--*/\r
1254{\r
1255 EFI_STATUS Status;\r
1256 //\r
1257 // create memory for TD_STRUCT, and align the memory.\r
1258 //\r
1259 Status = AllocateTDStruct (HcDev, pptrTD);\r
1260 if (EFI_ERROR (Status)) {\r
1261 return EFI_OUT_OF_RESOURCES;\r
1262 }\r
1263\r
1264 //\r
1265 // Make TD ready.\r
1266 //\r
1267 SetTDLinkPtrValidorInvalid (*pptrTD, FALSE);\r
1268\r
1269\r
1270 return EFI_SUCCESS;\r
1271}\r
1272\r
1273EFI_STATUS\r
1274GenSetupStageTD (\r
1275 IN USB_HC_DEV *HcDev,\r
1276 IN UINT8 DevAddr,\r
1277 IN UINT8 Endpoint,\r
1278 IN BOOLEAN bSlow,\r
1279 IN UINT8 *pDevReq,\r
1280 IN UINT8 RequestLen,\r
1281 OUT TD_STRUCT **ppTD\r
1282 )\r
1283/*++\r
1284\r
1285Routine Description:\r
1286\r
1287 Generate Setup Stage TD\r
1288\r
1289Arguments:\r
1290\r
1291 HcDev - USB_HC_DEV\r
1292 DevAddr - Device address\r
1293 Endpoint - Endpoint number \r
1294 bSlow - Full speed or low speed\r
1295 pDevReq - Device request\r
1296 RequestLen - Request length\r
1297 ppTD - TD_STRUCT to return\r
1298Returns:\r
1299\r
1300 EFI_OUT_OF_RESOURCES - Can't allocate memory\r
1301 EFI_SUCCESS - Success\r
1302\r
1303--*/\r
1304{\r
1305 EFI_STATUS Status;\r
1306 TD_STRUCT *pTDStruct;\r
1307\r
1308 Status = CreateTD (HcDev, &pTDStruct);\r
1309 if (EFI_ERROR (Status)) {\r
1310 return EFI_OUT_OF_RESOURCES;\r
1311 }\r
1312\r
1313 SetTDLinkPtr (pTDStruct, NULL);\r
1314\r
1315 //\r
1316 // Depth first fashion\r
1317 //\r
1318 SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE);\r
1319\r
1320 //\r
1321 // initialize as the last TD in the QH context,\r
1322 // this field will be updated in the TD linkage process.\r
1323 //\r
1324 SetTDLinkPtrValidorInvalid (pTDStruct, FALSE);\r
1325\r
1326 //\r
1327 // Disable Short Packet Detection by default\r
1328 //\r
1329 EnableorDisableTDShortPacket (pTDStruct, FALSE);\r
1330\r
1331 //\r
1332 // Max error counter is 3, retry 3 times when error encountered.\r
1333 //\r
1334 SetTDControlErrorCounter (pTDStruct, 3);\r
1335\r
1336 //\r
1337 // set device speed attribute\r
1338 // (TRUE - Slow Device; FALSE - Full Speed Device)\r
1339 //\r
1340 SetTDLoworFullSpeedDevice (pTDStruct, bSlow);\r
1341\r
1342 //\r
1343 // Non isochronous transfer TD\r
1344 //\r
1345 SetTDControlIsochronousorNot (pTDStruct, FALSE);\r
1346\r
1347 //\r
1348 // Interrupt On Complete bit be set to zero,\r
1349 // Disable IOC interrupt.\r
1350 //\r
1351 SetorClearTDControlIOC (pTDStruct, FALSE);\r
1352\r
1353 //\r
1354 // Set TD Active bit\r
1355 //\r
1356 SetTDStatusActiveorInactive (pTDStruct, TRUE);\r
1357\r
1358 SetTDTokenMaxLength (pTDStruct, RequestLen);\r
1359\r
1360 SetTDTokenDataToggle0 (pTDStruct);\r
1361\r
1362 SetTDTokenEndPoint (pTDStruct, Endpoint);\r
1363\r
1364 SetTDTokenDeviceAddress (pTDStruct, DevAddr);\r
1365\r
1366 SetTDTokenPacketID (pTDStruct, SETUP_PACKET_ID);\r
1367\r
1368 pTDStruct->pTDBuffer = (UINT8 *) pDevReq;\r
1369 pTDStruct->TDBufferLength = RequestLen;\r
1370 SetTDDataBuffer (pTDStruct);\r
1371\r
1372 *ppTD = pTDStruct;\r
1373\r
1374 return EFI_SUCCESS;\r
1375}\r
1376\r
1377EFI_STATUS\r
1378GenDataTD (\r
1379 IN USB_HC_DEV *HcDev,\r
1380 IN UINT8 DevAddr,\r
1381 IN UINT8 Endpoint,\r
1382 IN UINT8 *pData,\r
1383 IN UINT8 Len,\r
1384 IN UINT8 PktID,\r
1385 IN UINT8 Toggle,\r
1386 IN BOOLEAN bSlow,\r
1387 OUT TD_STRUCT **ppTD\r
1388 )\r
1389/*++\r
1390\r
1391Routine Description:\r
1392\r
1393 Generate Data Stage TD\r
1394\r
1395Arguments:\r
1396\r
1397 HcDev - USB_HC_DEV\r
1398 DevAddr - Device address\r
1399 Endpoint - Endpoint number \r
1400 pData - Data buffer \r
1401 Len - Data length\r
1402 PktID - Packet ID\r
1403 Toggle - Data toggle value\r
1404 bSlow - Full speed or low speed\r
1405 ppTD - TD_STRUCT to return\r
1406Returns:\r
1407\r
1408 EFI_OUT_OF_RESOURCES - Can't allocate memory\r
1409 EFI_SUCCESS - Success\r
1410\r
1411--*/\r
1412{\r
1413 TD_STRUCT *pTDStruct;\r
1414 EFI_STATUS Status;\r
1415\r
1416 Status = CreateTD (HcDev, &pTDStruct);\r
1417 if (EFI_ERROR (Status)) {\r
1418 return EFI_OUT_OF_RESOURCES;\r
1419 }\r
1420\r
1421 SetTDLinkPtr (pTDStruct, NULL);\r
1422\r
1423 //\r
1424 // Depth first fashion\r
1425 //\r
1426 SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE);\r
1427\r
1428 //\r
1429 // Link pointer pointing to TD struct\r
1430 //\r
1431 SetTDLinkPtrQHorTDSelect (pTDStruct, FALSE);\r
1432\r
1433 //\r
1434 // initialize as the last TD in the QH context,\r
1435 // this field will be updated in the TD linkage process.\r
1436 //\r
1437 SetTDLinkPtrValidorInvalid (pTDStruct, FALSE);\r
1438\r
1439 //\r
1440 // Disable short packet detect\r
1441 //\r
1442 EnableorDisableTDShortPacket (pTDStruct, FALSE);\r
1443 //\r
1444 // Max error counter is 3\r
1445 //\r
1446 SetTDControlErrorCounter (pTDStruct, 3);\r
1447\r
1448 //\r
1449 // set device speed attribute\r
1450 // (TRUE - Slow Device; FALSE - Full Speed Device)\r
1451 //\r
1452 SetTDLoworFullSpeedDevice (pTDStruct, bSlow);\r
1453\r
1454 //\r
1455 // Non isochronous transfer TD\r
1456 //\r
1457 SetTDControlIsochronousorNot (pTDStruct, FALSE);\r
1458\r
1459 //\r
1460 // Disable Interrupt On Complete\r
1461 // Disable IOC interrupt.\r
1462 //\r
1463 SetorClearTDControlIOC (pTDStruct, FALSE);\r
1464\r
1465 //\r
1466 // Set Active bit\r
1467 //\r
1468 SetTDStatusActiveorInactive (pTDStruct, TRUE);\r
1469\r
1470 SetTDTokenMaxLength (pTDStruct, Len);\r
1471\r
1472 if (Toggle) {\r
1473 SetTDTokenDataToggle1 (pTDStruct);\r
1474 } else {\r
1475 SetTDTokenDataToggle0 (pTDStruct);\r
1476 }\r
1477\r
1478 SetTDTokenEndPoint (pTDStruct, Endpoint);\r
1479\r
1480 SetTDTokenDeviceAddress (pTDStruct, DevAddr);\r
1481\r
1482 SetTDTokenPacketID (pTDStruct, PktID);\r
1483\r
1484 pTDStruct->pTDBuffer = (UINT8 *) pData;\r
1485 pTDStruct->TDBufferLength = Len;\r
1486 SetTDDataBuffer (pTDStruct);\r
1487 *ppTD = pTDStruct;\r
1488\r
1489 return EFI_SUCCESS;\r
1490}\r
1491\r
1492\r
1493EFI_STATUS\r
1494CreateStatusTD (\r
1495 IN USB_HC_DEV *HcDev,\r
1496 IN UINT8 DevAddr,\r
1497 IN UINT8 Endpoint,\r
1498 IN UINT8 PktID,\r
1499 IN BOOLEAN bSlow,\r
1500 OUT TD_STRUCT **ppTD\r
1501 )\r
1502/*++\r
1503\r
1504Routine Description:\r
1505\r
1506 Generate Status Stage TD\r
1507\r
1508Arguments:\r
1509\r
1510 HcDev - USB_HC_DEV\r
1511 DevAddr - Device address\r
1512 Endpoint - Endpoint number \r
1513 PktID - Packet ID\r
1514 bSlow - Full speed or low speed\r
1515 ppTD - TD_STRUCT to return\r
1516Returns:\r
1517\r
1518 EFI_OUT_OF_RESOURCES - Can't allocate memory\r
1519 EFI_SUCCESS - Success\r
1520\r
1521--*/\r
1522{\r
1523 TD_STRUCT *ptrTDStruct;\r
1524 EFI_STATUS Status;\r
1525\r
1526 Status = CreateTD (HcDev, &ptrTDStruct);\r
1527 if (EFI_ERROR (Status)) {\r
1528 return EFI_OUT_OF_RESOURCES;\r
1529 }\r
1530\r
1531 SetTDLinkPtr (ptrTDStruct, NULL);\r
1532\r
1533 //\r
1534 // Depth first fashion\r
1535 //\r
1536 SetTDLinkPtrDepthorBreadth (ptrTDStruct, TRUE);\r
1537\r
1538 //\r
1539 // initialize as the last TD in the QH context,\r
1540 // this field will be updated in the TD linkage process.\r
1541 //\r
1542 SetTDLinkPtrValidorInvalid (ptrTDStruct, FALSE);\r
1543\r
1544 //\r
1545 // Disable short packet detect\r
1546 //\r
1547 EnableorDisableTDShortPacket (ptrTDStruct, FALSE);\r
1548\r
1549 //\r
1550 // Max error counter is 3\r
1551 //\r
1552 SetTDControlErrorCounter (ptrTDStruct, 3);\r
1553\r
1554 //\r
1555 // set device speed attribute\r
1556 // (TRUE - Slow Device; FALSE - Full Speed Device)\r
1557 //\r
1558 SetTDLoworFullSpeedDevice (ptrTDStruct, bSlow);\r
1559\r
1560 //\r
1561 // Non isochronous transfer TD\r
1562 //\r
1563 SetTDControlIsochronousorNot (ptrTDStruct, FALSE);\r
1564\r
1565 //\r
1566 // Disable Interrupt On Complete\r
1567 // Disable IOC interrupt.\r
1568 //\r
1569 SetorClearTDControlIOC (ptrTDStruct, FALSE);\r
1570\r
1571 //\r
1572 // Set TD Active bit\r
1573 //\r
1574 SetTDStatusActiveorInactive (ptrTDStruct, TRUE);\r
1575\r
1576 SetTDTokenMaxLength (ptrTDStruct, 0);\r
1577\r
1578 SetTDTokenDataToggle1 (ptrTDStruct);\r
1579\r
1580 SetTDTokenEndPoint (ptrTDStruct, Endpoint);\r
1581\r
1582 SetTDTokenDeviceAddress (ptrTDStruct, DevAddr);\r
1583\r
1584 SetTDTokenPacketID (ptrTDStruct, PktID);\r
1585\r
1586 ptrTDStruct->pTDBuffer = NULL;\r
1587 ptrTDStruct->TDBufferLength = 0;\r
1588 SetTDDataBuffer (ptrTDStruct);\r
1589\r
1590 *ppTD = ptrTDStruct;\r
1591\r
1592 return EFI_SUCCESS;\r
1593}\r
1594\r
1595\r
1596VOID\r
1597SetTDLinkPtrValidorInvalid (\r
1598 IN TD_STRUCT *ptrTDStruct,\r
1599 IN BOOLEAN bValid\r
1600 )\r
1601/*++\r
1602\r
1603Routine Description:\r
1604\r
1605 Set TD Link Pointer Valid or Invalid\r
1606\r
1607Arguments:\r
1608\r
1609 ptrTDStruct - TD_STRUCT\r
1610 bValid - TRUE is valid FALSE is invalid\r
1611\r
1612Returns:\r
1613\r
1614 VOID\r
1615\r
1616--*/\r
1617{\r
1618 //\r
1619 // Valid means the link pointer is valid,\r
1620 // else, it's invalid.\r
1621 //\r
1622 ptrTDStruct->TDData.TDLinkPtrTerminate = (bValid ? 0 : 1);\r
1623}\r
1624\r
1625VOID\r
1626SetTDLinkPtrQHorTDSelect (\r
1627 IN TD_STRUCT *ptrTDStruct,\r
1628 IN BOOLEAN bQH\r
1629 )\r
1630/*++\r
1631\r
1632Routine Description:\r
1633\r
1634 Set TD Link Pointer QH or TD Select\r
1635\r
1636Arguments:\r
1637\r
1638 ptrTDStruct - TD_STRUCT\r
1639 bQH - TRUE is QH FALSE is TD\r
1640 \r
1641Returns:\r
1642\r
1643 VOID\r
1644\r
1645--*/\r
1646{\r
1647 //\r
1648 // Indicate whether the Link Pointer pointing to a QH or TD\r
1649 //\r
1650 ptrTDStruct->TDData.TDLinkPtrQSelect = (bQH ? 1 : 0);\r
1651}\r
1652\r
1653VOID\r
1654SetTDLinkPtrDepthorBreadth (\r
1655 IN TD_STRUCT *ptrTDStruct,\r
1656 IN BOOLEAN bDepth\r
1657 )\r
1658/*++\r
1659\r
1660Routine Description:\r
1661\r
1662 Set TD Link Pointer depth or bread priority\r
1663\r
1664Arguments:\r
1665\r
1666 ptrTDStruct - TD_STRUCT\r
1667 bDepth - TRUE is Depth FALSE is Breadth\r
1668 \r
1669Returns:\r
1670\r
1671 VOID\r
1672\r
1673--*/\r
1674{\r
1675 //\r
1676 // If TRUE, indicating the host controller should process in depth first\r
1677 // fashion,\r
1678 // else, the host controller should process in breadth first fashion\r
1679 //\r
1680 ptrTDStruct->TDData.TDLinkPtrDepthSelect = (bDepth ? 1 : 0);\r
1681}\r
1682\r
1683VOID\r
1684SetTDLinkPtr (\r
1685 IN TD_STRUCT *ptrTDStruct,\r
1686 IN VOID *ptrNext\r
1687 )\r
1688/*++\r
1689\r
1690Routine Description:\r
1691\r
1692 Set TD Link Pointer\r
1693\r
1694Arguments:\r
1695\r
1696 ptrTDStruct - TD_STRUCT\r
1697 ptrNext - Pointer to set\r
1698 \r
1699Returns:\r
1700\r
1701 VOID\r
1702\r
1703--*/\r
1704{\r
1705 //\r
1706 // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,\r
1707 // only the highest 28 bits are valid. (if take 32bit address as an example)\r
1708 //\r
1709 ptrTDStruct->TDData.TDLinkPtr = (UINT32) ((UINTN) ptrNext >> 4);\r
1710}\r
1711\r
1712VOID *\r
1713GetTDLinkPtr (\r
1714 IN TD_STRUCT *ptrTDStruct\r
1715 )\r
1716/*++\r
1717\r
1718Routine Description:\r
1719\r
1720 Get TD Link Pointer\r
1721\r
1722Arguments:\r
1723\r
1724 ptrTDStruct - TD_STRUCT\r
1725 \r
1726Returns:\r
1727\r
1728 Pointer to get\r
1729\r
1730--*/\r
1731{\r
1732 //\r
1733 // Get TD Link Pointer. Restore it back to 32bit\r
1734 // (if take 32bit address as an example)\r
1735 //\r
1736 return (VOID *) ((UINTN) (ptrTDStruct->TDData.TDLinkPtr << 4));\r
1737}\r
1738\r
1cc8ee78 1739STATIC\r
878ddf1f 1740BOOLEAN\r
1741IsTDLinkPtrQHOrTD (\r
1742 IN TD_STRUCT *ptrTDStruct\r
1743 )\r
1744/*++\r
1745\r
1746Routine Description:\r
1747\r
1748 Is TD Link Pointer is QH Or TD\r
1749\r
1750Arguments:\r
1751\r
1752 ptrTDStruct - TODO: add argument description\r
1753\r
1754Returns:\r
1755\r
1756 TRUE - QH\r
1757 FALSE - TD \r
1758\r
1759--*/\r
1760{\r
1761 //\r
1762 // Get the information about whether the Link Pointer field pointing to\r
1763 // a QH or a TD.\r
1764 //\r
1765 return (BOOLEAN) (ptrTDStruct->TDData.TDLinkPtrQSelect);\r
1766}\r
1767\r
1768VOID\r
1769EnableorDisableTDShortPacket (\r
1770 IN TD_STRUCT *ptrTDStruct,\r
1771 IN BOOLEAN bEnable\r
1772 )\r
1773/*++\r
1774\r
1775Routine Description:\r
1776\r
1777 Enable or Disable TD ShortPacket\r
1778\r
1779Arguments:\r
1780\r
1781 ptrTDStruct - TD_STRUCT\r
1782 bEnable - TRUE is Enanble FALSE is Disable\r
1783\r
1784Returns:\r
1785\r
1786 VOID\r
1787\r
1788--*/\r
1789{\r
1790 //\r
1791 // TRUE means enable short packet detection mechanism.\r
1792 //\r
1793 ptrTDStruct->TDData.TDStatusSPD = (bEnable ? 1 : 0);\r
1794}\r
1795\r
1796VOID\r
1797SetTDControlErrorCounter (\r
1798 IN TD_STRUCT *ptrTDStruct,\r
1799 IN UINT8 nMaxErrors\r
1800 )\r
1801/*++\r
1802\r
1803Routine Description:\r
1804\r
1805 Set TD Control ErrorCounter\r
1806\r
1807Arguments:\r
1808\r
1809 ptrTDStruct - TD_STRUCT\r
1810 nMaxErrors - Error counter number\r
1811 \r
1812Returns:\r
1813\r
1814 VOID\r
1815\r
1816--*/\r
1817{\r
1818 //\r
1819 // valid value of nMaxErrors is 0,1,2,3\r
1820 //\r
1821 if (nMaxErrors > 3) {\r
1822 nMaxErrors = 3;\r
1823 }\r
1824\r
1825 ptrTDStruct->TDData.TDStatusErr = nMaxErrors;\r
1826}\r
1827\r
1828\r
1829VOID\r
1830SetTDLoworFullSpeedDevice (\r
1831 IN TD_STRUCT *ptrTDStruct,\r
1832 IN BOOLEAN bLowSpeedDevice\r
1833 )\r
1834{\r
1835 //\r
1836 // TRUE means the TD is targeting at a Low-speed device\r
1837 //\r
1838 ptrTDStruct->TDData.TDStatusLS = (bLowSpeedDevice ? 1 : 0);\r
1839}\r
1840\r
1841VOID\r
1842SetTDControlIsochronousorNot (\r
1843 IN TD_STRUCT *ptrTDStruct,\r
1844 IN BOOLEAN IsIsochronous\r
1845 )\r
1846{\r
1847 //\r
1848 // TRUE means the TD belongs to Isochronous transfer type.\r
1849 //\r
1850 ptrTDStruct->TDData.TDStatusIOS = (IsIsochronous ? 1 : 0);\r
1851}\r
1852\r
1853VOID\r
1854SetorClearTDControlIOC (\r
1855 IN TD_STRUCT *ptrTDStruct,\r
1856 IN BOOLEAN IsSet\r
1857 )\r
1858{\r
1859 //\r
1860 // If this bit is set, it indicates that the host controller should issue\r
1861 // an interrupt on completion of the frame in which this TD is executed.\r
1862 //\r
1863 ptrTDStruct->TDData.TDStatusIOC = IsSet ? 1 : 0;\r
1864}\r
1865\r
1866VOID\r
1867SetTDStatusActiveorInactive (\r
1868 IN TD_STRUCT *ptrTDStruct,\r
1869 IN BOOLEAN IsActive\r
1870 )\r
1871{\r
1872 //\r
1873 // If this bit is set, it indicates that the TD is active and can be\r
1874 // executed.\r
1875 //\r
1876 if (IsActive) {\r
1877 ptrTDStruct->TDData.TDStatus |= 0x80;\r
1878 } else {\r
1879 ptrTDStruct->TDData.TDStatus &= 0x7F;\r
1880 }\r
1881}\r
1882\r
1883UINT16\r
1884SetTDTokenMaxLength (\r
1885 IN TD_STRUCT *ptrTDStruct,\r
1886 IN UINT16 MaximumLength\r
1887 )\r
1888{\r
1889 //\r
1890 // Specifies the maximum number of data bytes allowed for the transfer.\r
1891 // the legal value extent is 0 ~ 0x500.\r
1892 //\r
1893 if (MaximumLength > 0x500) {\r
1894 MaximumLength = 0x500;\r
1895 }\r
1896 ptrTDStruct->TDData.TDTokenMaxLen = MaximumLength - 1;\r
1897\r
1898 return MaximumLength;\r
1899}\r
1900\r
1901VOID\r
1902SetTDTokenDataToggle1 (\r
1903 IN TD_STRUCT *ptrTDStruct\r
1904 )\r
1905{\r
1906 //\r
1907 // Set the data toggle bit to DATA1\r
1908 //\r
1909 ptrTDStruct->TDData.TDTokenDataToggle = 1;\r
1910}\r
1911\r
1912VOID\r
1913SetTDTokenDataToggle0 (\r
1914 IN TD_STRUCT *ptrTDStruct\r
1915 )\r
1916{\r
1917 //\r
1918 // Set the data toggle bit to DATA0\r
1919 //\r
1920 ptrTDStruct->TDData.TDTokenDataToggle = 0;\r
1921}\r
1922\r
1923UINT8\r
1924GetTDTokenDataToggle (\r
1925 IN TD_STRUCT *ptrTDStruct\r
1926 )\r
1927{\r
1928 //\r
1929 // Get the data toggle value.\r
1930 //\r
1931 return (UINT8) (ptrTDStruct->TDData.TDTokenDataToggle);\r
1932}\r
1933\r
1934VOID\r
1935SetTDTokenEndPoint (\r
1936 IN TD_STRUCT *ptrTDStruct,\r
1937 IN UINTN EndPoint\r
1938 )\r
1939{\r
1940 //\r
1941 // Set EndPoint Number the TD is targeting at.\r
1942 //\r
1943 ptrTDStruct->TDData.TDTokenEndPt = (UINT8) EndPoint;\r
1944}\r
1945\r
1946VOID\r
1947SetTDTokenDeviceAddress (\r
1948 IN TD_STRUCT *ptrTDStruct,\r
1949 IN UINTN DeviceAddress\r
1950 )\r
1951{\r
1952 //\r
1953 // Set Device Address the TD is targeting at.\r
1954 //\r
1955 ptrTDStruct->TDData.TDTokenDevAddr = (UINT8) DeviceAddress;\r
1956}\r
1957\r
1958VOID\r
1959SetTDTokenPacketID (\r
1960 IN TD_STRUCT *ptrTDStruct,\r
1961 IN UINT8 PID\r
1962 )\r
1963{\r
1964 //\r
1965 // Set the Packet Identification to be used for this transaction.\r
1966 //\r
1967 ptrTDStruct->TDData.TDTokenPID = PID;\r
1968}\r
1969\r
1970VOID\r
1971SetTDDataBuffer (\r
1972 IN TD_STRUCT *ptrTDStruct\r
1973 )\r
1974{\r
1975 //\r
1976 // Set the beginning address of the data buffer that will be used\r
1977 // during the transaction.\r
1978 //\r
1979 ptrTDStruct->TDData.TDBufferPtr = (UINT32) ((UINTN) (ptrTDStruct->pTDBuffer));\r
1980}\r
1981\r
1982BOOLEAN\r
1983IsTDStatusActive (\r
1984 IN TD_STRUCT *ptrTDStruct\r
1985 )\r
1986{\r
1987 UINT8 TDStatus;\r
1988\r
1989 //\r
1990 // Detect whether the TD is active.\r
1991 //\r
1992 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
1993 return (BOOLEAN) (TDStatus & 0x80);\r
1994}\r
1995\r
1996BOOLEAN\r
1997IsTDStatusStalled (\r
1998 IN TD_STRUCT *ptrTDStruct\r
1999 )\r
2000{\r
2001 UINT8 TDStatus;\r
2002\r
2003 //\r
2004 // Detect whether the device/endpoint addressed by this TD is stalled.\r
2005 //\r
2006 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
2007 return (BOOLEAN) (TDStatus & 0x40);\r
2008}\r
2009\r
2010BOOLEAN\r
2011IsTDStatusBufferError (\r
2012 IN TD_STRUCT *ptrTDStruct\r
2013 )\r
2014{\r
2015 UINT8 TDStatus;\r
2016 //\r
2017 // Detect whether Data Buffer Error is happened.\r
2018 //\r
2019 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
2020 return (BOOLEAN) (TDStatus & 0x20);\r
2021}\r
2022\r
2023BOOLEAN\r
2024IsTDStatusBabbleError (\r
2025 IN TD_STRUCT *ptrTDStruct\r
2026 )\r
2027{\r
2028 UINT8 TDStatus;\r
2029\r
2030 //\r
2031 // Detect whether Babble Error is happened.\r
2032 //\r
2033 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
2034 return (BOOLEAN) (TDStatus & 0x10);\r
2035}\r
2036\r
2037BOOLEAN\r
2038IsTDStatusNAKReceived (\r
2039 IN TD_STRUCT *ptrTDStruct\r
2040 )\r
2041{\r
2042 UINT8 TDStatus;\r
2043\r
2044 //\r
2045 // Detect whether NAK is received.\r
2046 //\r
2047 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
2048 return (BOOLEAN) (TDStatus & 0x08);\r
2049}\r
2050\r
2051BOOLEAN\r
2052IsTDStatusCRCTimeOutError (\r
2053 IN TD_STRUCT *ptrTDStruct\r
2054 )\r
2055{\r
2056 UINT8 TDStatus;\r
2057\r
2058 //\r
2059 // Detect whether CRC/Time Out Error is encountered.\r
2060 //\r
2061 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
2062 return (BOOLEAN) (TDStatus & 0x04);\r
2063}\r
2064\r
2065BOOLEAN\r
2066IsTDStatusBitStuffError (\r
2067 IN TD_STRUCT *ptrTDStruct\r
2068 )\r
2069{\r
2070 UINT8 TDStatus;\r
2071\r
2072 //\r
2073 // Detect whether Bitstuff Error is received.\r
2074 //\r
2075 TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);\r
2076 return (BOOLEAN) (TDStatus & 0x02);\r
2077}\r
2078\r
2079UINT16\r
2080GetTDStatusActualLength (\r
2081 IN TD_STRUCT *ptrTDStruct\r
2082 )\r
2083{\r
2084 //\r
2085 // Retrieve the actual number of bytes that were tansferred.\r
2086 // the value is encoded as n-1. so return the decoded value.\r
2087 //\r
2088 return (UINT16) ((ptrTDStruct->TDData.TDStatusActualLength) + 1);\r
2089}\r
2090\r
2091UINT16\r
2092GetTDTokenMaxLength (\r
2093 IN TD_STRUCT *ptrTDStruct\r
2094 )\r
2095{\r
2096 //\r
2097 // Retrieve the maximum number of data bytes allowed for the trnasfer.\r
2098 //\r
2099 return (UINT16) ((ptrTDStruct->TDData.TDTokenMaxLen) + 1);\r
2100}\r
2101\r
2102UINT8\r
2103GetTDTokenEndPoint (\r
2104 IN TD_STRUCT *ptrTDStruct\r
2105 )\r
2106{\r
2107 //\r
2108 // Retrieve the endpoint number the transaction is targeting at.\r
2109 //\r
2110 return (UINT8) (ptrTDStruct->TDData.TDTokenEndPt);\r
2111}\r
2112\r
2113UINT8\r
2114GetTDTokenDeviceAddress (\r
2115 IN TD_STRUCT *ptrTDStruct\r
2116 )\r
2117{\r
2118 //\r
2119 // Retrieve the device address the transaction is targeting at.\r
2120 //\r
2121 return (UINT8) (ptrTDStruct->TDData.TDTokenDevAddr);\r
2122}\r
2123\r
2124UINT8\r
2125GetTDTokenPacketID (\r
2126 IN TD_STRUCT *ptrTDStruct\r
2127 )\r
2128{\r
2129 //\r
2130 // Retrieve the Packet Identification information.\r
2131 //\r
2132 return (UINT8) (ptrTDStruct->TDData.TDTokenPID);\r
2133}\r
2134\r
2135UINT8 *\r
2136GetTDDataBuffer (\r
2137 IN TD_STRUCT *ptrTDStruct\r
2138 )\r
2139{\r
2140 //\r
2141 // Retrieve the beginning address of the data buffer\r
2142 // that involved in this transaction.\r
2143 //\r
2144 return ptrTDStruct->pTDBuffer;\r
2145}\r
2146\r
2147BOOLEAN\r
2148GetTDLinkPtrValidorInvalid (\r
2149 IN TD_STRUCT *ptrTDStruct\r
2150 )\r
2151{\r
2152 //\r
2153 // Retrieve the information of whether the Link Pointer field\r
2154 // is valid or not.\r
2155 //\r
2156 if (ptrTDStruct->TDData.TDLinkPtrTerminate) {\r
2157 return FALSE;\r
2158 } else {\r
2159 return TRUE;\r
2160 }\r
2161\r
2162}\r
2163\r
2164UINTN\r
2165CountTDsNumber (\r
2166 IN TD_STRUCT *PtrFirstTD\r
2167 )\r
2168{\r
2169 UINTN Number;\r
2170 TD_STRUCT *ptr;\r
2171 //\r
2172 // Count the queued TDs number.\r
2173 //\r
2174 Number = 0;\r
2175 ptr = PtrFirstTD;\r
2176 while (ptr) {\r
2177 ptr = (TD_STRUCT *) ptr->ptrNextTD;\r
2178 Number++;\r
2179 }\r
2180\r
2181 return Number;\r
2182}\r
2183\r
2184\r
2185\r
2186VOID\r
2187LinkTDToQH (\r
2188 IN QH_STRUCT *PtrQH,\r
2189 IN TD_STRUCT *PtrTD\r
2190 )\r
2191/*++\r
2192\r
2193Routine Description:\r
2194\r
2195 Link TD To QH\r
2196\r
2197Arguments:\r
2198\r
2199 PtrQH - QH_STRUCT\r
2200 PtrTD - TD_STRUCT\r
2201Returns:\r
2202\r
2203 VOID\r
2204\r
2205--*/\r
2206{\r
2207 if (PtrQH == NULL || PtrTD == NULL) {\r
2208 return ;\r
2209 }\r
2210 //\r
2211 // Validate QH Vertical Ptr field\r
2212 //\r
2213 SetQHVerticalValidorInvalid (PtrQH, TRUE);\r
2214\r
2215 //\r
2216 // Vertical Ptr pointing to TD structure\r
2217 //\r
2218 SetQHVerticalQHorTDSelect (PtrQH, FALSE);\r
2219\r
2220 SetQHVerticalLinkPtr (PtrQH, (VOID *) PtrTD);\r
2221\r
2222 PtrQH->ptrDown = (VOID *) PtrTD;\r
2223}\r
2224\r
2225VOID\r
2226LinkTDToTD (\r
2227 IN TD_STRUCT *ptrPreTD,\r
2228 IN TD_STRUCT *PtrTD\r
2229 )\r
2230/*++\r
2231\r
2232Routine Description:\r
2233\r
2234 Link TD To TD\r
2235\r
2236Arguments:\r
2237\r
2238 ptrPreTD - Previous TD_STRUCT to be linked\r
2239 PtrTD - TD_STRUCT to link\r
2240Returns:\r
2241\r
2242 VOID\r
2243\r
2244--*/\r
2245{\r
2246 if (ptrPreTD == NULL || PtrTD == NULL) {\r
2247 return ;\r
2248 }\r
2249 //\r
2250 // Depth first fashion\r
2251 //\r
2252 SetTDLinkPtrDepthorBreadth (ptrPreTD, TRUE);\r
2253\r
2254 //\r
2255 // Link pointer pointing to TD struct\r
2256 //\r
2257 SetTDLinkPtrQHorTDSelect (ptrPreTD, FALSE);\r
2258\r
2259 //\r
2260 // Validate the link pointer valid bit\r
2261 //\r
2262 SetTDLinkPtrValidorInvalid (ptrPreTD, TRUE);\r
2263\r
2264 SetTDLinkPtr (ptrPreTD, PtrTD);\r
2265\r
2266 ptrPreTD->ptrNextTD = (VOID *) PtrTD;\r
2267}\r
2268//\r
2269// Transfer Schedule related Helper Functions\r
2270//\r
2271VOID\r
2272SetorClearCurFrameListTerminate (\r
2273 IN FRAMELIST_ENTRY *pCurEntry,\r
2274 IN BOOLEAN IsSet\r
2275 )\r
2276{\r
2277 //\r
2278 // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.\r
2279 //\r
2280 pCurEntry->FrameListPtrTerminate = (IsSet ? 1 : 0);\r
2281}\r
2282\r
2283VOID\r
2284SetCurFrameListQHorTD (\r
2285 IN FRAMELIST_ENTRY *pCurEntry,\r
2286 IN BOOLEAN IsQH\r
2287 )\r
2288{\r
2289 //\r
2290 // This bit indicates to the hardware whether the item referenced by the\r
2291 // link pointer is a TD or a QH.\r
2292 //\r
2293 pCurEntry->FrameListPtrQSelect = (IsQH ? 1 : 0);\r
2294}\r
2295\r
1cc8ee78 2296STATIC\r
878ddf1f 2297BOOLEAN\r
2298IsCurFrameListQHorTD (\r
2299 IN FRAMELIST_ENTRY *pCurEntry\r
2300 )\r
2301{\r
2302 //\r
2303 // TRUE is QH\r
2304 // FALSE is TD\r
2305 //\r
2306 return (BOOLEAN) (pCurEntry->FrameListPtrQSelect);\r
2307}\r
2308\r
2309BOOLEAN\r
2310GetCurFrameListTerminate (\r
2311 IN FRAMELIST_ENTRY *pCurEntry\r
2312 )\r
2313{\r
2314 //\r
2315 // TRUE means the frame is empty,\r
2316 // FALSE means the link pointer field is valid.\r
2317 //\r
2318 return (BOOLEAN) (pCurEntry->FrameListPtrTerminate);\r
2319}\r
2320\r
2321VOID\r
2322SetCurFrameListPointer (\r
2323 IN FRAMELIST_ENTRY *pCurEntry,\r
2324 IN UINT8 *ptr\r
2325 )\r
2326{\r
2327 //\r
2328 // Set the pointer field of the frame.\r
2329 //\r
2330 pCurEntry->FrameListPtr = (UINT32) ((UINTN) ptr >> 4);\r
2331}\r
2332\r
2333VOID *\r
2334GetCurFrameListPointer (\r
2335 IN FRAMELIST_ENTRY *pCurEntry\r
2336 )\r
2337{\r
2338 //\r
2339 // Get the link pointer of the frame.\r
2340 //\r
2341 return (VOID *) ((UINTN) (pCurEntry->FrameListPtr << 4));\r
2342\r
2343}\r
2344\r
2345VOID\r
2346LinkQHToFrameList (\r
2347 IN FRAMELIST_ENTRY *pEntry,\r
2348 IN UINT16 FrameListIndex,\r
2349 IN QH_STRUCT *PtrQH\r
2350 )\r
2351/*++\r
2352\r
2353Routine Description:\r
2354\r
2355 Link QH To Frame List\r
2356\r
2357Arguments:\r
2358\r
2359 pEntry - FRAMELIST_ENTRY\r
2360 FrameListIndex - Frame List Index\r
2361 PtrQH - QH to link \r
2362Returns:\r
2363\r
2364 VOID\r
2365\r
2366--*/\r
2367{\r
2368 FRAMELIST_ENTRY *pCurFrame;\r
2369 QH_STRUCT *TempQH;\r
2370 QH_STRUCT *NextTempQH;\r
2371 TD_STRUCT *TempTD;\r
2372 BOOLEAN LINK;\r
2373\r
2374 //\r
2375 // Get frame list entry that the link process will begin from.\r
2376 //\r
2377 pCurFrame = pEntry + FrameListIndex;\r
2378\r
2379 //\r
2380 // if current frame is empty\r
2381 // then link the specified QH directly to the Frame List.\r
2382 //\r
2383 if (GetCurFrameListTerminate (pCurFrame)) {\r
2384 \r
2385 //\r
2386 // Link new QH to the frame list entry.\r
2387 //\r
2388 SetCurFrameListQHorTD (pCurFrame, TRUE);\r
2389\r
2390 SetCurFrameListPointer (pCurFrame, (UINT8 *) PtrQH);\r
2391\r
2392 //\r
2393 // clear T bit in the Frame List, indicating that the frame list entry\r
2394 // is no longer empty.\r
2395 //\r
2396 SetorClearCurFrameListTerminate (pCurFrame, FALSE);\r
2397\r
2398 return ;\r
2399\r
2400 } else {\r
2401 //\r
2402 // current frame list has link pointer\r
2403 //\r
2404 if (!IsCurFrameListQHorTD (pCurFrame)) {\r
2405 //\r
2406 // a TD is linked to the framelist entry\r
2407 //\r
2408 TempTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
2409\r
2410 while (GetTDLinkPtrValidorInvalid (TempTD)) {\r
2411\r
2412 if (IsTDLinkPtrQHOrTD (TempTD)) {\r
2413 //\r
2414 // QH linked next to the TD\r
2415 //\r
2416 break;\r
2417 }\r
2418\r
2419 TempTD = (TD_STRUCT *) GetTDLinkPtr (TempTD);\r
2420 }\r
2421 \r
2422 //\r
2423 // either no ptr linked next to the TD or QH is linked next to the TD\r
2424 //\r
2425 if (!GetTDLinkPtrValidorInvalid (TempTD)) {\r
2426 \r
2427 //\r
2428 // no ptr linked next to the TD\r
2429 //\r
2430 TempTD->ptrNextQH = PtrQH;\r
2431 SetTDLinkPtrQHorTDSelect (TempTD, TRUE);\r
2432 SetTDLinkPtr (TempTD, PtrQH);\r
2433 SetTDLinkPtrValidorInvalid (TempTD, TRUE);\r
2434 return ;\r
2435\r
2436 } else {\r
2437 //\r
2438 // QH is linked next to the TD\r
2439 //\r
2440 TempQH = (QH_STRUCT *) GetTDLinkPtr (TempTD);\r
2441 }\r
2442 } else {\r
2443 //\r
2444 // a QH is linked to the framelist entry\r
2445 //\r
2446 TempQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
2447 }\r
2448 \r
2449 //\r
2450 // Set up Flag\r
2451 //\r
2452 LINK = TRUE;\r
2453\r
2454 //\r
2455 // Avoid the same qh repeated linking in one frame entry\r
2456 //\r
2457 if (TempQH == PtrQH) {\r
2458 LINK = FALSE;\r
2459 return ;\r
2460 }\r
2461 //\r
2462 // if current QH has next QH connected\r
2463 //\r
2464 while (GetQHHorizontalValidorInvalid (TempQH)) {\r
2465 //\r
2466 // Get next QH pointer\r
2467 //\r
2468 NextTempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (TempQH);\r
2469\r
2470 //\r
2471 // Bulk transfer qh may be self-linked,\r
2472 // so, the code below is to aVOID dead-loop when meeting self-linked qh\r
2473 //\r
2474 if (NextTempQH == TempQH) {\r
2475 LINK = FALSE;\r
2476 break;\r
2477 }\r
2478\r
2479 TempQH = NextTempQH;\r
2480\r
2481 //\r
2482 // Avoid the same qh repeated linking in one frame entry\r
2483 //\r
2484 if (TempQH == PtrQH) {\r
2485 LINK = FALSE;\r
2486 }\r
2487 }\r
2488\r
2489 if (LINK) {\r
2490 TempQH->ptrNext = PtrQH;\r
2491 SetQHHorizontalQHorTDSelect (TempQH, TRUE);\r
2492 SetQHHorizontalLinkPtr (TempQH, PtrQH);\r
2493 SetQHHorizontalValidorInvalid (TempQH, TRUE);\r
2494 }\r
2495\r
2496 return ;\r
2497 }\r
2498}\r
2499\r
2500EFI_STATUS\r
2501ExecuteControlTransfer (\r
2502 IN USB_HC_DEV *HcDev,\r
2503 IN TD_STRUCT *PtrTD,\r
2504 IN UINT32 wIndex,\r
2505 OUT UINTN *ActualLen,\r
2506 IN UINTN TimeOut,\r
2507 OUT UINT32 *TransferResult\r
2508 )\r
2509/*++\r
2510\r
2511Routine Description:\r
2512\r
2513 Execute Control Transfer\r
2514\r
2515Arguments:\r
2516\r
2517 HcDev - USB_HC_DEV\r
2518 PtrTD - TD_STRUCT\r
2519 wIndex - No use\r
2520 ActualLen - Actual transfered Len \r
2521 TimeOut - TimeOut value in milliseconds\r
2522 TransferResult - Transfer result\r
2523Returns:\r
2524\r
2525 EFI_SUCCESS - Sucess\r
2526 EFI_DEVICE_ERROR - Error\r
2527 \r
2528\r
2529--*/\r
2530{\r
2531 UINTN ErrTDPos;\r
2532 UINTN Delay;\r
2533 UINTN RequiredLen;\r
2534 BOOLEAN TransferFinished;\r
2535\r
2536 ErrTDPos = 0;\r
2537 *TransferResult = EFI_USB_NOERROR;\r
2538 RequiredLen = *ActualLen;\r
2539 *ActualLen = 0;\r
2540\r
2541 Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;\r
2542\r
2543 do {\r
2544 TransferFinished = CheckTDsResults (\r
2545 PtrTD,\r
2546 RequiredLen,\r
2547 TransferResult,\r
2548 &ErrTDPos,\r
2549 ActualLen\r
2550 );\r
2551\r
2552 if (TransferFinished) {\r
2553 break;\r
2554 }\r
2555 \r
2556 //\r
2557 // TD is inactive, which means the control transfer is end.\r
2558 //\r
2559 if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {\r
2560 break;\r
2561 } \r
2562\r
2563 gBS->Stall (50);\r
2564\r
2565 } while (Delay--);\r
2566\r
2567 if (*TransferResult != EFI_USB_NOERROR) {\r
2568 return EFI_DEVICE_ERROR;\r
2569 }\r
2570\r
2571 return EFI_SUCCESS;\r
2572}\r
2573\r
2574EFI_STATUS\r
2575ExecBulkorSyncInterruptTransfer (\r
2576 IN USB_HC_DEV *HcDev,\r
2577 IN TD_STRUCT *PtrTD,\r
2578 IN UINT32 wIndex,\r
2579 OUT UINTN *ActualLen,\r
2580 OUT UINT8 *DataToggle,\r
2581 IN UINTN TimeOut,\r
2582 OUT UINT32 *TransferResult\r
2583 )\r
2584/*++\r
2585\r
2586Routine Description:\r
2587\r
2588 Execute Bulk or SyncInterrupt Transfer\r
2589\r
2590Arguments:\r
2591\r
2592 HcDev - USB_HC_DEV\r
2593 PtrTD - TD_STRUCT\r
2594 wIndex - No use\r
2595 ActualLen - Actual transfered Len \r
2596 DataToggle - Data Toggle\r
2597 TimeOut - TimeOut value in milliseconds\r
2598 TransferResult - Transfer result\r
2599Returns:\r
2600\r
2601 EFI_SUCCESS - Sucess\r
2602 EFI_DEVICE_ERROR - Error\r
2603--*/\r
2604{\r
2605 UINTN ErrTDPos;\r
2606 UINTN ScrollNum;\r
2607 UINTN Delay;\r
2608 UINTN RequiredLen;\r
2609 BOOLEAN TransferFinished;\r
2610\r
2611 ErrTDPos = 0;\r
2612 *TransferResult = EFI_USB_NOERROR;\r
2613 RequiredLen = *ActualLen;\r
2614 *ActualLen = 0;\r
2615\r
2616 Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;\r
2617\r
2618 do {\r
2619\r
2620 TransferFinished = CheckTDsResults (\r
2621 PtrTD,\r
2622 RequiredLen,\r
2623 TransferResult,\r
2624 &ErrTDPos,\r
2625 ActualLen\r
2626 );\r
2627 \r
2628 if (TransferFinished) {\r
2629 break;\r
2630 }\r
2631 \r
2632 //\r
2633 // TD is inactive, which means bulk or interrupt transfer's end.\r
2634 // \r
2635 if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {\r
2636 break;\r
2637 }\r
2638\r
2639 gBS->Stall (50);\r
2640\r
2641 } while (Delay--);\r
2642\r
2643 //\r
2644 // has error\r
2645 //\r
2646 if (*TransferResult != EFI_USB_NOERROR) {\r
2647 \r
2648 //\r
2649 // scroll the Data Toggle back to the last success TD\r
2650 //\r
2651 ScrollNum = CountTDsNumber (PtrTD) - ErrTDPos;\r
2652 if (ScrollNum & 0x1) {\r
2653 *DataToggle ^= 1;\r
2654 }\r
2655\r
2656 return EFI_DEVICE_ERROR;\r
2657 }\r
2658\r
2659 return EFI_SUCCESS;\r
2660}\r
2661\r
2662VOID\r
2663DelLinkSingleQH (\r
2664 IN USB_HC_DEV *HcDev,\r
2665 IN QH_STRUCT *PtrQH,\r
2666 IN UINT16 FrameListIndex,\r
2667 IN BOOLEAN SearchOther,\r
2668 IN BOOLEAN Delete\r
2669 )\r
2670/*++\r
2671\r
2672Routine Description:\r
2673\r
2674 Unlink from frame list and delete single QH\r
2675Arguments:\r
2676\r
2677 HcDev - USB_HC_DEV\r
2678 PtrQH - QH_STRUCT\r
2679 FrameListIndex - Frame List Index\r
2680 SearchOther - Search Other QH\r
2681 Delete - TRUE is to delete the QH\r
2682Returns:\r
2683 VOID\r
2684--*/\r
2685{\r
2686 FRAMELIST_ENTRY *pCurFrame;\r
2687 UINTN Index;\r
2688 UINTN BeginFrame;\r
2689 UINTN EndFrame;\r
2690 QH_STRUCT *CurrentQH;\r
2691 QH_STRUCT *NextQH;\r
2692 TD_STRUCT *CurrentTD;\r
2693 VOID *PtrPreQH;\r
2694 BOOLEAN Found;\r
2695\r
2696 NextQH = NULL;\r
2697 PtrPreQH = NULL;\r
2698 Found = FALSE;\r
2699\r
2700 if (PtrQH == NULL) {\r
2701 return ;\r
2702 }\r
2703\r
2704 if (SearchOther) {\r
2705 BeginFrame = 0;\r
2706 EndFrame = 1024;\r
2707 } else {\r
2708 BeginFrame = FrameListIndex;\r
2709 EndFrame = FrameListIndex + 1;\r
2710 }\r
2711\r
2712 for (Index = BeginFrame; Index < EndFrame; Index++) {\r
2713\r
2714 pCurFrame = HcDev->FrameListEntry + (Index & 0x3FF);\r
2715\r
2716 if (GetCurFrameListTerminate (pCurFrame)) {\r
2717 //\r
2718 // current frame list is empty,search next frame list entry\r
2719 //\r
2720 continue;\r
2721 }\r
2722\r
2723 if (!IsCurFrameListQHorTD (pCurFrame)) {\r
2724 //\r
2725 // TD linked to current framelist\r
2726 //\r
2727 CurrentTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
2728\r
2729 while (GetTDLinkPtrValidorInvalid (CurrentTD)) {\r
2730\r
2731 if (IsTDLinkPtrQHOrTD (CurrentTD)) {\r
2732 //\r
2733 // QH linked next to the TD,break while ()\r
2734 //\r
2735 break;\r
2736 }\r
2737\r
2738 CurrentTD = (TD_STRUCT *) GetTDLinkPtr (CurrentTD);\r
2739 }\r
2740\r
2741 if (!GetTDLinkPtrValidorInvalid (CurrentTD)) {\r
2742 //\r
2743 // no QH linked next to the last TD,\r
2744 // search next frame list\r
2745 //\r
2746 continue;\r
2747 }\r
2748 \r
2749 //\r
2750 // a QH linked next to the last TD\r
2751 //\r
2752 CurrentQH = (QH_STRUCT *) GetTDLinkPtr (CurrentTD);\r
2753\r
2754 PtrPreQH = CurrentTD;\r
2755\r
2756 } else {\r
2757 //\r
2758 // a QH linked to current framelist\r
2759 //\r
2760 CurrentQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);\r
2761\r
2762 PtrPreQH = NULL;\r
2763 }\r
2764\r
2765 if (CurrentQH == PtrQH) {\r
2766\r
2767 if (GetQHHorizontalValidorInvalid (PtrQH)) {\r
2768 //\r
2769 // there is QH connected after the QH found\r
2770 //\r
2771 //\r
2772 // retrieve nex qh pointer of the qh found.\r
2773 //\r
2774 NextQH = GetQHHorizontalLinkPtr (PtrQH);\r
2775 } else {\r
2776 NextQH = NULL;\r
2777 }\r
2778\r
2779 if (PtrPreQH) {\r
2780 //\r
2781 // QH linked to a TD struct\r
2782 //\r
2783 CurrentTD = (TD_STRUCT *) PtrPreQH;\r
2784\r
2785 SetTDLinkPtrValidorInvalid (CurrentTD, (BOOLEAN) ((NextQH == NULL) ? FALSE : TRUE));\r
2786 SetTDLinkPtr (CurrentTD, NextQH);\r
2787 CurrentTD->ptrNextQH = NextQH;\r
2788\r
2789 } else {\r
2790 //\r
2791 // QH linked directly to current framelist entry\r
2792 //\r
2793 SetorClearCurFrameListTerminate (pCurFrame, (BOOLEAN) ((NextQH == NULL) ? TRUE : FALSE));\r
2794 SetCurFrameListPointer (pCurFrame, (UINT8 *) NextQH);\r
2795 }\r
2796\r
2797 Found = TRUE;\r
2798 //\r
2799 // search next framelist entry\r
2800 //\r
2801 continue;\r
2802 }\r
2803\r
2804 while (GetQHHorizontalValidorInvalid (CurrentQH)) {\r
2805\r
2806 PtrPreQH = CurrentQH;\r
2807 //\r
2808 // Get next horizontal linked QH\r
2809 //\r
2810 CurrentQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (CurrentQH);\r
2811 //\r
2812 // the qh is found\r
2813 //\r
2814 if (CurrentQH == PtrQH) {\r
2815 break;\r
2816 }\r
2817 }\r
2818 \r
2819 //\r
2820 // search next frame list entry\r
2821 //\r
2822 if (CurrentQH != PtrQH) {\r
2823 //\r
2824 // Not find the QH\r
2825 //\r
2826 continue;\r
2827 }\r
2828 //\r
2829 // find the specified qh, then delink it from\r
2830 // the horizontal QH list in the frame entry.\r
2831 //\r
2832 \r
2833 if (GetQHHorizontalValidorInvalid (PtrQH)) {\r
2834 //\r
2835 // there is QH connected after the QH found\r
2836 //\r
2837 //\r
2838 // retrieve nex qh pointer of the qh found.\r
2839 //\r
2840 NextQH = GetQHHorizontalLinkPtr (PtrQH);\r
2841\r
2842 } else {\r
2843 //\r
2844 // NO QH connected after the QH found\r
2845 //\r
2846 NextQH = NULL;\r
2847 //\r
2848 // NULL the previous QH's link ptr and set Terminate field.\r
2849 //\r
2850 SetQHHorizontalValidorInvalid ((QH_STRUCT *) PtrPreQH, FALSE);\r
2851 }\r
2852\r
2853 SetQHHorizontalLinkPtr ((QH_STRUCT *) PtrPreQH, NextQH);\r
2854 ((QH_STRUCT *) PtrPreQH)->ptrNext = NextQH;\r
2855\r
2856 Found = TRUE;\r
2857 }\r
2858\r
2859 if (Found && Delete) {\r
2860 //\r
2861 // free memory once used by the specific QH\r
2862 //\r
2863 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
2864 }\r
2865\r
2866 return ;\r
2867}\r
2868\r
2869\r
2870VOID\r
2871DeleteQueuedTDs (\r
2872 IN USB_HC_DEV *HcDev,\r
2873 IN TD_STRUCT *PtrFirstTD\r
2874 )\r
2875/*++\r
2876Routine Description:\r
2877\r
2878 Delete Queued TDs\r
2879Arguments:\r
2880\r
2881 HcDev - USB_HC_DEV\r
2882 PtrFirstTD - TD link list head\r
2883\r
2884Returns:\r
2885 VOID\r
2886\r
2887--*/\r
2888{\r
2889 TD_STRUCT *Tptr1;\r
2890 TD_STRUCT *Tptr2;\r
2891\r
2892 Tptr1 = PtrFirstTD;\r
2893 //\r
2894 // Delete all the TDs in a queue.\r
2895 //\r
2896 while (Tptr1) {\r
2897\r
2898 Tptr2 = Tptr1;\r
2899\r
2900 if (!GetTDLinkPtrValidorInvalid (Tptr2)) {\r
2901 Tptr1 = NULL;\r
2902 } else {\r
2903\r
2904 Tptr1 = GetTDLinkPtr (Tptr2);\r
2905\r
2906 //\r
2907 // TD link to itself\r
2908 //\r
2909 if (Tptr1 == Tptr2) {\r
2910 Tptr1 = NULL;\r
2911 }\r
2912 }\r
2913\r
2914 UhciFreePool (HcDev, (UINT8 *) Tptr2, sizeof (TD_STRUCT));\r
2915 }\r
2916\r
2917 return ;\r
2918}\r
2919\r
2920VOID\r
2921InsertQHTDToINTList (\r
2922 IN USB_HC_DEV *HcDev,\r
2923 IN QH_STRUCT *PtrQH,\r
2924 IN TD_STRUCT *PtrFirstTD,\r
2925 IN UINT8 DeviceAddress,\r
2926 IN UINT8 EndPointAddress,\r
2927 IN UINT8 DataToggle,\r
2928 IN UINTN DataLength,\r
2929 IN UINTN PollingInterval,\r
2930 IN VOID *Mapping,\r
2931 IN UINT8 *DataBuffer,\r
2932 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
2933 IN VOID *Context\r
2934 )\r
2935/*++\r
2936Routine Description:\r
2937 Insert QH and TD To Interrupt List\r
2938Arguments:\r
2939\r
2940 HcDev - USB_HC_DEV\r
2941 PtrQH - QH_STRUCT\r
2942 PtrFirstTD - First TD_STRUCT\r
2943 DeviceAddress - Device Address\r
2944 EndPointAddress - EndPoint Address\r
2945 DataToggle - Data Toggle\r
2946 DataLength - Data length \r
2947 PollingInterval - Polling Interval when inserted to frame list\r
2948 Mapping - Mapping alue \r
2949 DataBuffer - Data buffer\r
2950 CallBackFunction- CallBackFunction after interrupt transfeer\r
2951 Context - CallBackFunction Context passed as function parameter\r
2952Returns:\r
2953 EFI_SUCCESS - Sucess\r
2954 EFI_INVALID_PARAMETER - Paremeter is error \r
2955\r
2956--*/\r
2957{\r
2958 INTERRUPT_LIST *Node;\r
2959\r
2960 Node = AllocatePool (sizeof (INTERRUPT_LIST));\r
2961 if (Node == NULL) {\r
2962 return ;\r
2963 }\r
2964 \r
2965 //\r
2966 // Fill Node field\r
2967 //\r
2968 Node->Signature = INTERRUPT_LIST_SIGNATURE;\r
2969 Node->DevAddr = DeviceAddress;\r
2970 Node->EndPoint = EndPointAddress;\r
2971 Node->PtrQH = PtrQH;\r
2972 Node->PtrFirstTD = PtrFirstTD;\r
2973 Node->DataToggle = DataToggle;\r
2974 Node->DataLen = DataLength;\r
2975 Node->PollInterval = PollingInterval;\r
2976 Node->Mapping = Mapping;\r
2977 //\r
2978 // DataBuffer is allocated host memory, not mapped memory\r
2979 //\r
2980 Node->DataBuffer = DataBuffer;\r
2981 Node->InterruptCallBack = CallBackFunction;\r
2982 Node->InterruptContext = Context;\r
2983\r
2984 //\r
2985 // insert the new interrupt transfer to the head of the list.\r
2986 // The interrupt transfer's monitor function scans the whole list from head\r
2987 // to tail. The new interrupt transfer MUST be added to the head of the list\r
2988 // for the sake of error recovery.\r
2989 //\r
2990 InsertHeadList (&(HcDev->InterruptListHead), &(Node->Link));\r
2991\r
2992 return ;\r
2993}\r
2994\r
2995\r
2996EFI_STATUS\r
2997DeleteAsyncINTQHTDs (\r
2998 IN USB_HC_DEV *HcDev,\r
2999 IN UINT8 DeviceAddress,\r
3000 IN UINT8 EndPointAddress,\r
3001 OUT UINT8 *DataToggle\r
3002 )\r
3003/*++\r
3004Routine Description:\r
3005\r
3006 Delete Async INT QH and TDs\r
3007Arguments:\r
3008\r
3009 HcDev - USB_HC_DEV\r
3010 DeviceAddress - Device Address\r
3011 EndPointAddress - EndPoint Address\r
3012 DataToggle - Data Toggle\r
3013\r
3014Returns:\r
3015 EFI_SUCCESS - Sucess\r
3016 EFI_INVALID_PARAMETER - Paremeter is error \r
3017\r
3018--*/\r
3019{\r
3020 QH_STRUCT *MatchQH;\r
3021 QH_STRUCT *ptrNextQH;\r
3022 TD_STRUCT *MatchTD;\r
3023 LIST_ENTRY *Link;\r
3024 INTERRUPT_LIST *MatchList;\r
3025 INTERRUPT_LIST *PtrList;\r
3026 BOOLEAN Found;\r
3027\r
3028 UINT32 Result;\r
3029 UINTN ErrTDPos;\r
3030 UINTN ActualLen;\r
3031\r
3032 MatchQH = NULL;\r
3033 MatchTD = NULL;\r
3034 MatchList = NULL;\r
3035\r
3036 //\r
3037 // no interrupt transaction exists\r
3038 //\r
3039 if (IsListEmpty (&(HcDev->InterruptListHead))) {\r
3040 return EFI_INVALID_PARAMETER;\r
3041 }\r
3042 //\r
3043 // find the correct QH-TD that need to delete\r
3044 // (by matching Device address and EndPoint number to match QH-TD )\r
3045 //\r
3046 Found = FALSE;\r
3047 Link = &(HcDev->InterruptListHead);\r
3048 do {\r
3049\r
3050 Link = Link->ForwardLink;\r
3051 PtrList = INTERRUPT_LIST_FROM_LINK (Link);\r
3052\r
3053 if ((PtrList->DevAddr == DeviceAddress) && ((PtrList->EndPoint & 0x0f) == (EndPointAddress & 0x0f))) {\r
3054 MatchList = PtrList;\r
3055\r
3056 Found = TRUE;\r
3057 break;\r
3058 }\r
3059\r
3060 } while (Link->ForwardLink != &(HcDev->InterruptListHead));\r
3061\r
3062 if (!Found) {\r
3063 return EFI_INVALID_PARAMETER;\r
3064 }\r
3065 //\r
3066 // get current endpoint's data toggle bit and save.\r
3067 //\r
3068 ExecuteAsyncINTTDs (HcDev, MatchList, &Result, &ErrTDPos, &ActualLen);\r
3069 UpdateAsyncINTQHTDs (MatchList, Result, (UINT32) ErrTDPos);\r
3070 *DataToggle = MatchList->DataToggle;\r
3071\r
3072 MatchTD = MatchList->PtrFirstTD;\r
3073 MatchQH = MatchList->PtrQH;\r
3074 //\r
3075 // find the first matching QH position in the FrameList\r
3076 //\r
3077 while (MatchQH) {\r
3078\r
3079 ptrNextQH = MatchQH->ptrNextIntQH;\r
3080\r
3081 //\r
3082 // Search all the entries\r
3083 //\r
3084 DelLinkSingleQH (HcDev, MatchQH, 0, TRUE, TRUE);\r
3085\r
3086 MatchQH = ptrNextQH;\r
3087 }\r
3088 \r
3089 //\r
3090 // Call PciIo->Unmap() to unmap the busmaster read/write\r
3091 //\r
3092 HcDev->PciIo->Unmap (HcDev->PciIo, MatchList->Mapping);\r
3093\r
3094 //\r
3095 // free host data buffer allocated,\r
3096 // mapped data buffer is freed by Unmap\r
3097 //\r
3098 if (MatchList->DataBuffer != NULL) {\r
3099 gBS->FreePool (MatchList->DataBuffer);\r
3100 }\r
3101 \r
3102 //\r
3103 // at last delete the TDs, to aVOID problems\r
3104 //\r
3105 DeleteQueuedTDs (HcDev, MatchTD);\r
3106\r
3107 //\r
3108 // remove Match node from interrupt list\r
3109 //\r
3110 RemoveEntryList (&(MatchList->Link));\r
3111 gBS->FreePool (MatchList);\r
3112 return EFI_SUCCESS;\r
3113}\r
3114\r
3115BOOLEAN\r
3116CheckTDsResults (\r
3117 IN TD_STRUCT *PtrTD,\r
3118 IN UINTN RequiredLen,\r
3119 OUT UINT32 *Result,\r
3120 OUT UINTN *ErrTDPos,\r
3121 OUT UINTN *ActualTransferSize\r
3122 )\r
3123/*++\r
3124\r
3125Routine Description:\r
3126\r
3127 Check TDs Results\r
3128\r
3129Arguments:\r
3130\r
3131 PtrTD - TD_STRUCT to check\r
3132 RequiredLen - Required Len\r
3133 Result - Transfer result\r
3134 ErrTDPos - Error TD Position\r
3135 ActualTransferSize - Actual Transfer Size\r
3136\r
3137Returns:\r
3138\r
3139 TRUE - Sucess\r
3140 FALSE - Fail\r
3141\r
3142--*/\r
3143{\r
3144 UINTN Len;\r
3145\r
3146 *Result = EFI_USB_NOERROR;\r
3147 *ErrTDPos = 0;\r
3148\r
3149 //\r
3150 // Init to zero.\r
3151 //\r
3152 *ActualTransferSize = 0;\r
3153\r
3154 while (PtrTD) {\r
3155\r
3156 if (IsTDStatusActive (PtrTD)) {\r
3157 *Result |= EFI_USB_ERR_NOTEXECUTE;\r
3158 }\r
3159\r
3160 if (IsTDStatusStalled (PtrTD)) {\r
3161 *Result |= EFI_USB_ERR_STALL;\r
3162 }\r
3163\r
3164 if (IsTDStatusBufferError (PtrTD)) {\r
3165 *Result |= EFI_USB_ERR_BUFFER;\r
3166 }\r
3167\r
3168 if (IsTDStatusBabbleError (PtrTD)) {\r
3169 *Result |= EFI_USB_ERR_BABBLE;\r
3170 }\r
3171\r
3172 if (IsTDStatusNAKReceived (PtrTD)) {\r
3173 *Result |= EFI_USB_ERR_NAK;\r
3174 }\r
3175\r
3176 if (IsTDStatusCRCTimeOutError (PtrTD)) {\r
3177 *Result |= EFI_USB_ERR_TIMEOUT;\r
3178 }\r
3179\r
3180 if (IsTDStatusBitStuffError (PtrTD)) {\r
3181 *Result |= EFI_USB_ERR_BITSTUFF;\r
3182 }\r
3183 \r
3184 //\r
3185 // if any error encountered, stop processing the left TDs.\r
3186 //\r
3187 if (*Result) {\r
3188 return FALSE;\r
3189 }\r
3190\r
3191 Len = GetTDStatusActualLength (PtrTD) & 0x7FF;\r
3192 *ActualTransferSize += Len;\r
3193\r
3194 if (*ActualTransferSize <= RequiredLen && Len < PtrTD->TDData.TDTokenMaxLen) {\r
3195 //\r
3196 // transter finished and actural length less than required length\r
3197 //\r
3198 goto Done;\r
3199 }\r
3200 //\r
3201 // Accumulate actual transferred data length in each TD.\r
3202 //\r
3203 PtrTD = (TD_STRUCT *) (PtrTD->ptrNextTD);\r
3204 //\r
3205 // Record the first Error TD's position in the queue,\r
3206 // this value is zero-based.\r
3207 //\r
3208 (*ErrTDPos)++;\r
3209 }\r
3210\r
3211Done:\r
3212 return TRUE;\r
3213}\r
3214\r
3215\r
3216VOID\r
3217ExecuteAsyncINTTDs (\r
3218 IN USB_HC_DEV *HcDev,\r
3219 IN INTERRUPT_LIST *PtrList,\r
3220 OUT UINT32 *Result,\r
3221 OUT UINTN *ErrTDPos,\r
3222 OUT UINTN *ActualLen\r
3223 )\r
3224/*++\r
3225\r
3226Routine Description:\r
3227\r
3228 Execute Async Interrupt TDs\r
3229\r
3230Arguments:\r
3231\r
3232 HcDev - USB_HC_DEV\r
3233 PtrList - INTERRUPT_LIST\r
3234 Result - Transfer result\r
3235 ErrTDPos - Error TD Position\r
3236 ActualTransferSize - Actual Transfer Size\r
3237 \r
3238Returns:\r
3239\r
3240 VOID\r
3241\r
3242--*/\r
3243{\r
3244 //\r
3245 // *ErrTDPos is zero-based value, indicating the first error TD's position\r
3246 // in the TDs' sequence.\r
3247 // *ErrTDPos value is only valid when *Result is not equal NOERROR.\r
3248 //\r
3249 UINTN RequiredLen;\r
3250\r
3251 RequiredLen = *ActualLen;\r
3252 CheckTDsResults (PtrList->PtrFirstTD, RequiredLen, Result, ErrTDPos, ActualLen);\r
3253\r
3254 return ;\r
3255}\r
3256\r
3257\r
3258VOID\r
3259UpdateAsyncINTQHTDs (\r
3260 IN INTERRUPT_LIST *PtrList,\r
3261 IN UINT32 Result,\r
3262 IN UINT32 ErrTDPos\r
3263 )\r
3264/*++\r
3265\r
3266Routine Description:\r
3267\r
3268 Update Async Interrupt QH and TDs\r
3269\r
3270Arguments:\r
3271\r
3272 PtrList - INTERRUPT_LIST\r
3273 Result - Transfer reslut\r
3274 ErrTDPos - Error TD Position\r
3275\r
3276Returns:\r
3277\r
3278 VOID\r
3279\r
3280--*/\r
3281{\r
3282 QH_STRUCT *PtrFirstQH;\r
3283 QH_STRUCT *PtrQH;\r
3284 TD_STRUCT *PtrFirstTD;\r
3285 TD_STRUCT *PtrTD;\r
3286 UINT8 DataToggle;\r
3287 UINT32 Index;\r
3288\r
3289 PtrFirstQH = PtrList->PtrQH;\r
3290 PtrFirstTD = PtrList->PtrFirstTD;\r
3291\r
3292 DataToggle = 0;\r
3293\r
3294 if (Result == EFI_USB_NOERROR) {\r
3295\r
3296 PtrTD = PtrFirstTD;\r
3297 while (PtrTD) {\r
3298 DataToggle = GetTDTokenDataToggle (PtrTD);\r
3299 PtrTD = PtrTD->ptrNextTD;\r
3300 }\r
3301 \r
3302 //\r
3303 // save current DataToggle value to interrupt list.\r
3304 // this value is used for tracing the interrupt endpoint DataToggle.\r
3305 // when this interrupt transfer is deleted, the last DataToggle is saved\r
3306 //\r
3307 PtrList->DataToggle = DataToggle;\r
3308\r
3309 PtrTD = PtrFirstTD;\r
3310\r
3311 //\r
3312 // Since DataToggle bit should toggle after each success transaction,\r
3313 // the First TD's DataToggle bit will be updated to XOR of Last TD's\r
3314 // DataToggle bit. If the First TD's DataToggle bit is not equal Last\r
3315 // TD's DataToggle bit, that means it already be the XOR of Last TD's,\r
3316 // so no update is needed.\r
3317 //\r
3318 if (DataToggle == GetTDTokenDataToggle (PtrFirstTD)) {\r
3319 PtrTD = PtrFirstTD;\r
3320 while (PtrTD) {\r
3321\r
3322 DataToggle ^= 1;\r
3323 if (DataToggle) {\r
3324 SetTDTokenDataToggle1 (PtrTD);\r
3325 } else {\r
3326 SetTDTokenDataToggle0 (PtrTD);\r
3327 }\r
3328\r
3329 PtrTD = PtrTD->ptrNextTD;\r
3330 }\r
3331 }\r
3332 //\r
3333 // restore Link Pointer of QH to First TD\r
3334 // (because QH's Link Pointer will change during TD execution)\r
3335 //\r
3336 PtrQH = PtrFirstQH;\r
3337 while (PtrQH) {\r
3338\r
3339 LinkTDToQH (PtrQH, PtrFirstTD);\r
3340 PtrQH = PtrQH->ptrNextIntQH;\r
3341 }\r
3342 \r
3343 //\r
3344 // set all the TDs active\r
3345 //\r
3346 PtrTD = PtrFirstTD;\r
3347 while (PtrTD) {\r
3348 SetTDStatusActiveorInactive (PtrTD, TRUE);\r
3349 PtrTD = PtrTD->ptrNextTD;\r
3350 }\r
3351\r
3352 } else if (((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE) ||\r
3353 ((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK)\r
3354 ) {\r
3355 //\r
3356 // no update\r
3357 //\r
3358 } else {\r
3359 //\r
3360 // Have Errors\r
3361 //\r
3362 PtrTD = PtrFirstTD;\r
3363 //\r
3364 // not first TD error\r
3365 //\r
3366 if (ErrTDPos != 0) {\r
3367 //\r
3368 // get the last success TD\r
3369 //\r
3370 for (Index = 1; Index < ErrTDPos; Index++) {\r
3371 PtrTD = PtrTD->ptrNextTD;\r
3372 }\r
3373 //\r
3374 // update Data Toggle in the interrupt list node\r
3375 //\r
3376 PtrList->DataToggle = GetTDTokenDataToggle (PtrTD);\r
3377\r
3378 //\r
3379 // get the error TD\r
3380 //\r
3381 PtrTD = PtrTD->ptrNextTD;\r
3382\r
3383 } else {\r
3384 PtrList->DataToggle = GetTDTokenDataToggle (PtrTD);\r
3385 }\r
3386 //\r
3387 // do not restore the QH's vertical link pointer,\r
3388 // let the callback function do the rest of error handling.\r
3389 //\r
3390 }\r
3391\r
3392 return ;\r
3393}\r
3394\r
3395VOID\r
3396ReleaseInterruptList (\r
3397 IN USB_HC_DEV *HcDev,\r
3398 IN LIST_ENTRY *ListHead\r
3399 )\r
3400/*++\r
3401\r
3402Routine Description:\r
3403\r
3404 Release Interrupt List\r
3405Arguments:\r
3406\r
3407 HcDev - USB_HC_DEV\r
3408 ListHead - List head\r
3409\r
3410Returns:\r
3411\r
3412 VOID\r
3413\r
3414--*/\r
3415{\r
3416 LIST_ENTRY *Link;\r
3417 LIST_ENTRY *SavedLink;\r
3418 INTERRUPT_LIST *pNode;\r
3419 TD_STRUCT *PtrTD;\r
3420 TD_STRUCT *ptrNextTD;\r
3421 QH_STRUCT *PtrQH;\r
3422 QH_STRUCT *SavedQH;\r
3423\r
3424 if (ListHead == NULL) {\r
3425 return ;\r
3426 }\r
3427\r
3428 Link = ListHead;\r
3429\r
3430 //\r
3431 // Free all the resources in the interrupt list\r
3432 //\r
3433 SavedLink = Link->ForwardLink;\r
3434 while (!IsListEmpty (ListHead)) {\r
3435\r
3436 Link = SavedLink;\r
3437\r
3438 SavedLink = Link->ForwardLink;\r
3439\r
3440 pNode = INTERRUPT_LIST_FROM_LINK (Link);\r
3441\r
3442 RemoveEntryList (&pNode->Link);\r
3443\r
3444 SavedQH = pNode->PtrQH;\r
3445 for (PtrQH = SavedQH; PtrQH != NULL; PtrQH = SavedQH) {\r
3446 SavedQH = PtrQH->ptrNextIntQH;\r
3447 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));\r
3448 }\r
3449\r
3450 PtrTD = pNode->PtrFirstTD;\r
3451 while (PtrTD != NULL) {\r
3452\r
3453 ptrNextTD = PtrTD->ptrNextTD;\r
3454 UhciFreePool (HcDev, (UINT8 *) PtrTD, sizeof (TD_STRUCT));\r
3455 PtrTD = ptrNextTD;\r
3456 }\r
3457\r
3458 gBS->FreePool (pNode);\r
3459 }\r
3460}\r
3461\r
3462\r
3463EFI_STATUS\r
3464InitializeMemoryManagement (\r
3465 IN USB_HC_DEV *HcDev\r
3466 )\r
3467/*++\r
3468\r
3469Routine Description:\r
3470\r
3471 Initialize Memory Management\r
3472\r
3473Arguments:\r
3474\r
3475 HcDev - USB_HC_DEV\r
3476\r
3477Returns:\r
3478\r
3479 EFI_SUCCESS - Success\r
3480--*/\r
3481{\r
3482 MEMORY_MANAGE_HEADER *MemoryHeader;\r
3483 EFI_STATUS Status;\r
3484 UINTN MemPages;\r
3485\r
3486 MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
3487 Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);\r
3488 if (EFI_ERROR (Status)) {\r
3489 return Status;\r
3490 }\r
3491\r
3492 HcDev->MemoryHeader = MemoryHeader;\r
3493\r
3494 return EFI_SUCCESS;\r
3495}\r
3496\r
3497EFI_STATUS\r
3498CreateMemoryBlock (\r
3499 IN USB_HC_DEV *HcDev,\r
3500 OUT MEMORY_MANAGE_HEADER **MemoryHeader,\r
3501 IN UINTN MemoryBlockSizeInPages\r
3502 )\r
3503/*++\r
3504\r
3505Routine Description:\r
3506\r
3507 Use PciIo->AllocateBuffer to allocate common buffer for the memory block,\r
3508 and use PciIo->Map to map the common buffer for Bus Master Read/Write.\r
3509\r
3510\r
3511Arguments:\r
3512\r
3513 HcDev - USB_HC_DEV\r
3514 MemoryHeader - MEMORY_MANAGE_HEADER to output\r
3515 MemoryBlockSizeInPages - MemoryBlockSizeInPages\r
3516Returns:\r
3517\r
3518 EFI_SUCCESS - Success\r
3519--*/\r
3520{\r
3521 EFI_STATUS Status;\r
3522 VOID *CommonBuffer;\r
3523 EFI_PHYSICAL_ADDRESS MappedAddress;\r
3524 UINTN MemoryBlockSizeInBytes;\r
3525 VOID *Mapping;\r
3526\r
3527 //\r
3528 // Allocate memory for MemoryHeader\r
3529 //\r
3530 *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));\r
3531 if (*MemoryHeader == NULL) {\r
3532 return EFI_OUT_OF_RESOURCES;\r
3533 }\r
3534\r
3535 (*MemoryHeader)->Next = NULL;\r
3536\r
3537 //\r
3538 // set Memory block size\r
3539 //\r
3540 (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
3541\r
3542 //\r
3543 // each bit in Bit Array will manage 32 bytes memory in memory block\r
3544 //\r
3545 (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8;\r
3546\r
3547 //\r
3548 // Allocate memory for BitArray\r
3549 //\r
3550 (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);\r
3551 if ((*MemoryHeader)->BitArrayPtr == NULL) {\r
3552 gBS->FreePool (*MemoryHeader);\r
3553 return EFI_OUT_OF_RESOURCES;\r
3554 }\r
3555 \r
3556 //\r
3557 // Memory Block uses MemoryBlockSizeInPages pages,\r
3558 // and it is allocated as common buffer use.\r
3559 //\r
3560 Status = HcDev->PciIo->AllocateBuffer (\r
562d2849 3561 HcDev->PciIo,\r
3562 AllocateAnyPages,\r
3563 EfiBootServicesData,\r
3564 MemoryBlockSizeInPages,\r
3565 &CommonBuffer,\r
3566 0\r
3567 );\r
878ddf1f 3568 if (EFI_ERROR (Status)) {\r
3569 gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
3570 gBS->FreePool (*MemoryHeader);\r
3571 return Status;\r
3572 }\r
3573\r
3574 MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);\r
3575 Status = HcDev->PciIo->Map (\r
562d2849 3576 HcDev->PciIo,\r
3577 EfiPciIoOperationBusMasterCommonBuffer,\r
3578 CommonBuffer,\r
3579 &MemoryBlockSizeInBytes,\r
3580 &MappedAddress,\r
3581 &Mapping\r
3582 );\r
878ddf1f 3583 //\r
3584 // if returned Mapped size is less than the size we request,do not support.\r
3585 //\r
3586 if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {\r
3587 HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);\r
3588 gBS->FreePool ((*MemoryHeader)->BitArrayPtr);\r
3589 gBS->FreePool (*MemoryHeader);\r
3590 return EFI_UNSUPPORTED;\r
3591 }\r
3592 //\r
3593 // Set Memory block initial address\r
3594 //\r
3595 (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);\r
3596 (*MemoryHeader)->Mapping = Mapping;\r
3597\r
3598 ZeroMem (\r
3599 (*MemoryHeader)->MemoryBlockPtr,\r
3600 EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)\r
3601 );\r
3602\r
3603 return EFI_SUCCESS;\r
3604}\r
3605\r
3606EFI_STATUS\r
3607FreeMemoryHeader (\r
3608 IN USB_HC_DEV *HcDev,\r
3609 IN MEMORY_MANAGE_HEADER *MemoryHeader\r
3610 )\r
3611/*++\r
3612\r
3613Routine Description:\r
3614\r
3615 Free Memory Header\r
3616\r
3617Arguments:\r
3618\r
3619 HcDev - USB_HC_DEV\r
3620 MemoryHeader - MemoryHeader to be freed\r
3621\r
3622Returns:\r
3623\r
3624 EFI_INVALID_PARAMETER - Parameter is error\r
3625 EFI_SUCCESS - Success\r
3626\r
3627--*/\r
3628{\r
3629 if ((MemoryHeader == NULL) || (HcDev == NULL)) {\r
3630 return EFI_INVALID_PARAMETER;\r
3631 }\r
3632 //\r
3633 // unmap the common buffer used by the memory block\r
3634 //\r
3635 HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);\r
3636\r
3637 //\r
3638 // free common buffer\r
3639 //\r
3640 HcDev->PciIo->FreeBuffer (\r
3641 HcDev->PciIo,\r
3642 EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),\r
3643 MemoryHeader->MemoryBlockPtr\r
3644 );\r
3645 //\r
3646 // free bit array\r
3647 //\r
3648 gBS->FreePool (MemoryHeader->BitArrayPtr);\r
3649 //\r
3650 // free memory header\r
3651 //\r
3652 gBS->FreePool (MemoryHeader);\r
3653\r
3654 return EFI_SUCCESS;\r
3655}\r
3656\r
3657EFI_STATUS\r
3658UhciAllocatePool (\r
3659 IN USB_HC_DEV *HcDev,\r
3660 OUT UINT8 **Pool,\r
3661 IN UINTN AllocSize\r
3662 )\r
3663/*++\r
3664\r
3665Routine Description:\r
3666\r
3667 Uhci Allocate Pool\r
3668\r
3669Arguments:\r
3670\r
3671 HcDev - USB_HC_DEV\r
3672 Pool - Place to store pointer to the memory buffer\r
3673 AllocSize - Alloc Size\r
3674\r
3675Returns:\r
3676\r
3677 EFI_SUCCESS - Success\r
3678\r
3679--*/\r
3680{\r
3681 MEMORY_MANAGE_HEADER *MemoryHeader;\r
3682 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
3683 MEMORY_MANAGE_HEADER *NewMemoryHeader;\r
3684 UINTN RealAllocSize;\r
3685 UINTN MemoryBlockSizeInPages;\r
3686 EFI_STATUS Status;\r
3687\r
3688 *Pool = NULL;\r
3689\r
3690 MemoryHeader = HcDev->MemoryHeader;\r
3691 ASSERT (MemoryHeader != NULL);\r
3692\r
3693 //\r
3694 // allocate unit is 32 bytes (align on 32 byte)\r
3695 //\r
3696 if (AllocSize & 0x1F) {\r
3697 RealAllocSize = (AllocSize / 32 + 1) * 32;\r
3698 } else {\r
3699 RealAllocSize = AllocSize;\r
3700 }\r
3701 \r
3702 //\r
3703 // There may be linked MemoryHeaders.\r
3704 // To allocate a free pool in Memory blocks,\r
3705 // must search in the MemoryHeader link list\r
3706 // until enough free pool is found.\r
3707 //\r
3708 Status = EFI_NOT_FOUND;\r
3709 for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;\r
3710 TempHeaderPtr = TempHeaderPtr->Next) {\r
3711\r
3712 Status = AllocMemInMemoryBlock (\r
562d2849 3713 TempHeaderPtr,\r
3714 (VOID **) Pool,\r
3715 RealAllocSize / 32\r
3716 );\r
878ddf1f 3717 if (!EFI_ERROR (Status)) {\r
3718 ZeroMem (*Pool, AllocSize);\r
3719 return EFI_SUCCESS;\r
3720 }\r
3721 }\r
3722 \r
3723 //\r
3724 // There is no enough memory,\r
3725 // Create a new Memory Block\r
3726 //\r
3727 \r
3728 //\r
3729 // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,\r
3730 // just allocate a large enough memory block.\r
3731 //\r
3732 if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {\r
3733 MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;\r
3734 } else {\r
3735 MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;\r
3736 }\r
3737\r
3738 Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);\r
3739 if (EFI_ERROR (Status)) {\r
3740 return Status;\r
3741 }\r
3742 \r
3743 //\r
3744 // Link the new Memory Block to the Memory Header list\r
3745 //\r
3746 InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);\r
3747\r
3748 Status = AllocMemInMemoryBlock (\r
562d2849 3749 NewMemoryHeader,\r
3750 (VOID **) Pool,\r
3751 RealAllocSize / 32\r
3752 );\r
878ddf1f 3753\r
3754 if (!EFI_ERROR (Status)) {\r
3755 ZeroMem (*Pool, AllocSize);\r
3756 }\r
3757\r
3758 return Status;\r
3759}\r
3760\r
3761VOID\r
3762UhciFreePool (\r
3763 IN USB_HC_DEV *HcDev,\r
3764 IN UINT8 *Pool,\r
3765 IN UINTN AllocSize\r
3766 )\r
3767/*++\r
3768\r
3769Routine Description:\r
3770\r
3771 Uhci Free Pool\r
3772\r
3773Arguments:\r
3774\r
3775 HcDev - USB_HC_DEV\r
3776 Pool - Pool to free\r
3777 AllocSize - Pool size\r
3778\r
3779Returns:\r
3780\r
3781 VOID\r
3782\r
3783--*/\r
3784{\r
3785 MEMORY_MANAGE_HEADER *MemoryHeader;\r
3786 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
3787 UINTN StartBytePos;\r
3788 UINTN Index;\r
3789 UINT8 StartBitPos;\r
3790 UINT8 Index2;\r
3791 UINTN Count;\r
3792 UINTN RealAllocSize;\r
3793\r
3794 MemoryHeader = HcDev->MemoryHeader;\r
3795\r
3796 //\r
3797 // allocate unit is 32 byte (align on 32 byte)\r
3798 //\r
3799 if (AllocSize & 0x1F) {\r
3800 RealAllocSize = (AllocSize / 32 + 1) * 32;\r
3801 } else {\r
3802 RealAllocSize = AllocSize;\r
3803 }\r
3804 //\r
3805 // scan the memory header linked list for\r
3806 // the asigned memory to free.\r
3807 //\r
3808 for (TempHeaderPtr = MemoryHeader;TempHeaderPtr != NULL;\r
3809 TempHeaderPtr = TempHeaderPtr->Next) {\r
3810\r
3811 if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&\r
3812 ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))\r
3813 ) {\r
3814 //\r
3815 // Pool is in the Memory Block area,\r
3816 // find the start byte and bit in the bit array\r
3817 //\r
3818 StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8;\r
3819 StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7);\r
3820\r
3821 //\r
3822 // reset associated bits in bit arry\r
3823 //\r
3824 for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {\r
3825\r
1cc8ee78 3826 TempHeaderPtr->BitArrayPtr[Index] = (UINT8) (TempHeaderPtr->BitArrayPtr[Index] ^ bit (Index2));\r
878ddf1f 3827 Index2++;\r
3828 if (Index2 == 8) {\r
3829 Index += 1;\r
3830 Index2 = 0;\r
3831 }\r
3832 }\r
3833 //\r
3834 // break the loop\r
3835 //\r
3836 break;\r
3837 }\r
3838 }\r
3839 \r
3840 //\r
3841 // Release emptied memory blocks (only if the memory block is not\r
3842 // the first one in the memory header list\r
3843 //\r
3844 for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
3845 //\r
3846 // Debug\r
3847 //\r
3848 ASSERT (MemoryHeader->Next != NULL);\r
3849\r
3850 if (IsMemoryBlockEmptied (TempHeaderPtr)) {\r
3851\r
3852 DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);\r
3853 //\r
3854 // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
3855 // the TempHeaderPtr is pointing to nonsense content.\r
3856 //\r
3857 FreeMemoryHeader (HcDev, TempHeaderPtr);\r
3858 //\r
3859 // reset the TempHeaderPtr, continue search for\r
3860 // another empty memory block.\r
3861 //\r
3862 TempHeaderPtr = MemoryHeader->Next;\r
3863 continue;\r
3864 }\r
3865\r
3866 TempHeaderPtr = TempHeaderPtr->Next;\r
3867 }\r
3868}\r
3869\r
3870VOID\r
3871InsertMemoryHeaderToList (\r
3872 IN MEMORY_MANAGE_HEADER *MemoryHeader,\r
3873 IN MEMORY_MANAGE_HEADER *NewMemoryHeader\r
3874 )\r
3875/*++\r
3876\r
3877Routine Description:\r
3878\r
3879 Insert Memory Header To List\r
3880\r
3881Arguments:\r
3882\r
3883 MemoryHeader - MEMORY_MANAGE_HEADER\r
3884 NewMemoryHeader - MEMORY_MANAGE_HEADER\r
3885\r
3886Returns:\r
3887\r
3888 VOID\r
3889\r
3890--*/\r
3891{\r
3892 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
3893\r
3894 for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;\r
3895 TempHeaderPtr = TempHeaderPtr->Next) {\r
3896 if (TempHeaderPtr->Next == NULL) {\r
3897 TempHeaderPtr->Next = NewMemoryHeader;\r
3898 break;\r
3899 }\r
3900 }\r
3901}\r
3902\r
3903EFI_STATUS\r
3904AllocMemInMemoryBlock (\r
3905 IN MEMORY_MANAGE_HEADER *MemoryHeader,\r
3906 OUT VOID **Pool,\r
3907 IN UINTN NumberOfMemoryUnit\r
3908 )\r
3909/*++\r
3910\r
3911Routine Description:\r
3912\r
3913 Alloc Memory In MemoryBlock\r
3914\r
3915Arguments:\r
3916\r
3917 MemoryHeader - MEMORY_MANAGE_HEADER\r
3918 Pool - Place to store pointer to memory\r
3919 NumberOfMemoryUnit - Number Of Memory Unit\r
3920\r
3921Returns:\r
3922\r
3923 EFI_NOT_FOUND - Can't find the free memory \r
3924 EFI_SUCCESS - Success\r
3925\r
3926--*/\r
3927{\r
3928 UINTN TempBytePos;\r
3929 UINTN FoundBytePos;\r
3930 UINT8 Index;\r
3931 UINT8 FoundBitPos;\r
3932 UINT8 ByteValue;\r
3933 UINT8 BitValue;\r
3934 UINTN NumberOfZeros;\r
3935 UINTN Count;\r
3936\r
3937 FoundBytePos = 0;\r
3938 FoundBitPos = 0;\r
3939 ByteValue = MemoryHeader->BitArrayPtr[0];\r
3940 NumberOfZeros = 0;\r
3941 Index = 0;\r
3942\r
3943 for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {\r
3944 \r
3945 //\r
3946 // Pop out BitValue from a byte in TempBytePos.\r
3947 //\r
3948 BitValue = (UINT8) (ByteValue & 0x1);\r
3949 //\r
3950 // right shift the byte\r
3951 //\r
3952 ByteValue /= 2;\r
3953\r
3954 if (BitValue == 0) {\r
3955 //\r
3956 // Found a free bit, the NumberOfZeros only record the number\r
3957 // of those consecutive zeros\r
3958 //\r
3959 NumberOfZeros++;\r
3960 //\r
3961 // Found enough consecutive free space, break the loop\r
3962 //\r
3963 if (NumberOfZeros >= NumberOfMemoryUnit) {\r
3964 break;\r
3965 }\r
3966 } else {\r
3967 //\r
3968 // Encountering a '1', meant the bit is ocupied.\r
3969 //\r
3970 if (NumberOfZeros >= NumberOfMemoryUnit) {\r
3971 //\r
3972 // Found enough consecutive free space,break the loop\r
3973 //\r
3974 break;\r
3975 } else {\r
3976 //\r
3977 // the NumberOfZeros only record the number of those consecutive zeros,\r
3978 // so reset the NumberOfZeros to 0 when encountering '1' before finding\r
3979 // enough consecutive '0's\r
3980 //\r
3981 NumberOfZeros = 0;\r
3982 //\r
3983 // reset the (FoundBytePos,FoundBitPos) to the position of '1'\r
3984 //\r
3985 FoundBytePos = TempBytePos;\r
3986 FoundBitPos = Index;\r
3987 }\r
3988 }\r
3989 //\r
3990 // step forward a bit\r
3991 //\r
3992 Index++;\r
3993 if (Index == 8) {\r
3994 //\r
3995 // step forward a byte, getting the byte value,\r
3996 // and reset the bit pos.\r
3997 //\r
3998 TempBytePos += 1;\r
3999 ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];\r
4000 Index = 0;\r
4001 }\r
4002 }\r
4003\r
4004 if (NumberOfZeros < NumberOfMemoryUnit) {\r
4005 return EFI_NOT_FOUND;\r
4006 }\r
4007 \r
4008 //\r
4009 // Found enough free space.\r
4010 //\r
4011 \r
4012 //\r
4013 // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:\r
4014 // 1)(FoundBytePos,FoundBitPos) record the position\r
4015 // of the last '1' before the consecutive '0's, it must\r
4016 // be adjusted to the start position of the consecutive '0's.\r
4017 // 2)the start address of the consecutive '0's is just the start of\r
4018 // the bitarray. so no need to adjust the values of\r
4019 // (FoundBytePos,FoundBitPos).\r
4020 //\r
4021 if ((MemoryHeader->BitArrayPtr[0] & bit (0)) != 0) {\r
4022 FoundBitPos += 1;\r
4023 }\r
4024 \r
4025 //\r
4026 // Have the (FoundBytePos,FoundBitPos) make sense.\r
4027 //\r
4028 if (FoundBitPos > 7) {\r
4029 FoundBytePos += 1;\r
4030 FoundBitPos -= 8;\r
4031 }\r
4032 \r
4033 //\r
4034 // Set the memory as allocated\r
4035 //\r
4036 for (TempBytePos = FoundBytePos, Index = FoundBitPos,Count = 0;\r
4037 Count < NumberOfMemoryUnit; Count ++) {\r
4038\r
1cc8ee78 4039 MemoryHeader->BitArrayPtr[TempBytePos] = (UINT8) (MemoryHeader->BitArrayPtr[TempBytePos] | bit (Index));\r
878ddf1f 4040 Index++;\r
4041 if (Index == 8) {\r
4042 TempBytePos += 1;\r
4043 Index = 0;\r
4044 }\r
4045 }\r
4046\r
4047 *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32;\r
4048\r
4049 return EFI_SUCCESS;\r
4050}\r
4051\r
4052BOOLEAN\r
4053IsMemoryBlockEmptied (\r
4054 IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr\r
4055 )\r
4056/*++\r
4057\r
4058Routine Description:\r
4059\r
4060 Is Memory Block Emptied\r
4061\r
4062Arguments:\r
4063\r
4064 MemoryHeaderPtr - MEMORY_MANAGE_HEADER\r
4065\r
4066Returns:\r
4067\r
4068 TRUE - Empty\r
4069 FALSE - Not Empty \r
4070\r
4071--*/\r
4072{\r
4073 UINTN Index;\r
4074\r
4075 for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {\r
4076 if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {\r
4077 return FALSE;\r
4078 }\r
4079 }\r
4080\r
4081 return TRUE;\r
4082}\r
4083\r
4084VOID\r
4085DelinkMemoryBlock (\r
4086 IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,\r
4087 IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader\r
4088 )\r
4089/*++\r
4090\r
4091Routine Description:\r
4092\r
4093 Delink Memory Block\r
4094\r
4095Arguments:\r
4096\r
4097 FirstMemoryHeader - MEMORY_MANAGE_HEADER\r
4098 NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER\r
4099\r
4100Returns:\r
4101\r
4102 VOID\r
4103\r
4104--*/\r
4105{\r
4106 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
4107\r
4108 if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {\r
4109 return ;\r
4110 }\r
4111 for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL;\r
4112 TempHeaderPtr = TempHeaderPtr->Next) {\r
4113\r
4114 if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {\r
4115 //\r
4116 // Link the before and after\r
4117 //\r
4118 TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;\r
4119 break;\r
4120 }\r
4121 }\r
4122}\r
4123\r
4124EFI_STATUS\r
4125DelMemoryManagement (\r
4126 IN USB_HC_DEV *HcDev\r
4127 )\r
4128/*++\r
4129\r
4130Routine Description:\r
4131\r
4132 Delete Memory Management\r
4133\r
4134Arguments:\r
4135\r
4136 HcDev - USB_HC_DEV\r
4137\r
4138Returns:\r
4139\r
4140 EFI_SUCCESS - Success\r
4141\r
4142--*/\r
4143{\r
4144 MEMORY_MANAGE_HEADER *TempHeaderPtr;\r
4145\r
4146 for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {\r
4147\r
4148 DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);\r
4149 //\r
4150 // when the TempHeaderPtr is freed in FreeMemoryHeader(),\r
4151 // the TempHeaderPtr is pointing to nonsense content.\r
4152 //\r
4153 FreeMemoryHeader (HcDev, TempHeaderPtr);\r
4154 //\r
4155 // reset the TempHeaderPtr,continue free another memory block.\r
4156 //\r
4157 TempHeaderPtr = HcDev->MemoryHeader->Next;\r
4158 }\r
4159\r
4160 FreeMemoryHeader (HcDev, HcDev->MemoryHeader);\r
4161\r
4162 return EFI_SUCCESS;\r
4163}\r
4164\r
4165\r
4166VOID\r
4167CleanUsbTransactions (\r
4168 IN USB_HC_DEV *HcDev\r
4169 )\r
4170{\r
4171 //\r
4172 // only asynchronous interrupt transfers are always alive on the bus\r
4173 //\r
4174 ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));\r
4175}\r
4176\r
4177VOID\r
4178TurnOffUSBEmulation (\r
4179 IN EFI_PCI_IO_PROTOCOL *PciIo\r
4180 )\r
4181/*++\r
4182 \r
4183 Routine Description:\r
4184 Disable USB Emulation\r
4185 Arguments:\r
4186 PciIo - EFI_PCI_IO_PROTOCOL\r
4187 Returns:\r
4188 VOID\r
4189--*/\r
4190{\r
4191 UINT16 Command;\r
4192\r
4193 //\r
4194 // Disable USB Emulation\r
4195 //\r
4196 Command = 0;\r
4197 PciIo->Pci.Write (\r
562d2849 4198 PciIo,\r
4199 EfiPciIoWidthUint16,\r
4200 USB_EMULATION,\r
4201 1,\r
4202 &Command\r
4203 );\r
878ddf1f 4204\r
4205 return ;\r
4206}\r