3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
39 PciIo - EFI_PCI_IO_PROTOCOL
40 PortOffset - Port offset
50 // Perform 16bit Read in PCI IO Space
52 return PciIo
->Io
.Read (
65 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
77 PciIo - EFI_PCI_IO_PROTOCOL
78 PortOffset - Port offset
88 // Perform 32bit Read in PCI IO Space
90 return PciIo
->Io
.Read (
103 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
104 IN UINT32 PortOffset
,
115 PciIo - EFI_PCI_IO_PROTOCOL
116 PortOffset - Port offset
126 // Perform 16bit Write in PCI IO Space
128 return PciIo
->Io
.Write (
141 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
142 IN UINT32 PortOffset
,
153 PciIo - EFI_PCI_IO_PROTOCOL
154 PortOffset - Port offset
164 // Perform 32bit Write in PCI IO Space
166 return PciIo
->Io
.Write (
176 // USB register-base helper functions
180 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
181 IN UINT32 CmdAddrOffset
,
188 Write UHCI Command Register
192 PciIo - EFI_PCI_IO_PROTOCOL
193 CmdAddrOffset - Command address offset
194 UsbCmd - Data to write
203 // Write to UHC's Command Register
205 return USBWritePortW (PciIo
, CmdAddrOffset
, UsbCmd
);
210 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
211 IN UINT32 CmdAddrOffset
,
218 Read UHCI Command Register
222 PciIo - EFI_PCI_IO_PROTOCOL
223 CmdAddrOffset - Command address offset
224 Data - Data to return
233 // Read from UHC's Command Register
235 return USBReadPortW (PciIo
, CmdAddrOffset
, Data
);
240 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
241 IN UINT32 StatusAddrOffset
,
248 Write UHCI Staus Register
252 PciIo - EFI_PCI_IO_PROTOCOL
253 StatusAddrOffset - Status address offset
254 UsbSts - Data to write
263 // Write to UHC's Status Register
265 return USBWritePortW (PciIo
, StatusAddrOffset
, UsbSts
);
270 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
271 IN UINT32 StatusAddrOffset
,
278 Read UHCI Staus Register
282 PciIo - EFI_PCI_IO_PROTOCOL
283 StatusAddrOffset - Status address offset
284 UsbSts - Data to return
293 // Read from UHC's Status Register
295 return USBReadPortW (PciIo
, StatusAddrOffset
, Data
);
301 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
302 IN UINT32 StatusAddrOffset
308 Clear the content of UHC's Status Register
312 PciIo - EFI_PCI_IO_PROTOCOL
313 StatusAddrOffset - Status address offset
322 return WriteUHCStatusReg (PciIo
, StatusAddrOffset
, 0x003F);
326 ReadUHCFrameNumberReg (
327 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
328 IN UINT32 FrameNumAddrOffset
,
335 Read from UHC's Frame Number Register
339 PciIo - EFI_PCI_IO_PROTOCOL
340 FrameNumAddrOffset - Frame number register offset
341 Data - Data to return
349 return USBReadPortW (PciIo
, FrameNumAddrOffset
, Data
);
353 WriteUHCFrameListBaseReg (
354 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
355 IN UINT32 FlBaseAddrOffset
,
356 IN UINT32 UsbFrameListBaseAddr
362 Write to UHC's Frame List Base Register
366 PciIo - EFI_PCI_IO_PROTOCOL
367 FlBaseAddrOffset - Frame Base address register
368 UsbFrameListBaseAddr - Address to write
377 return USBWritePortDW (PciIo
, FlBaseAddrOffset
, UsbFrameListBaseAddr
);
382 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
383 IN UINT32 PortAddrOffset
,
390 Read from UHC's Root Port Register
394 PciIo - EFI_PCI_IO_PROTOCOL
395 PortAddrOffset - Port Addrress Offset,
396 Data - Data to return
404 return USBReadPortW (PciIo
, PortAddrOffset
, Data
);
409 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
410 IN UINT32 PortAddrOffset
,
411 IN UINT16 ControlBits
417 Write to UHC's Root Port Register
421 PciIo - EFI_PCI_IO_PROTOCOL
422 PortAddrOffset - Port Addrress Offset,
423 ControlBits - Data to write
431 return USBWritePortW (PciIo
, PortAddrOffset
, ControlBits
);
438 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
439 IN UINT32 StatusRegAddr
,
446 Wait until UHCI halt or timeout
450 PciIo - EFI_PCI_IO_PROTOCOL
451 StatusRegAddr - Status Register Address
452 Timeout - Time out value in us
456 EFI_DEVICE_ERROR - Unable to read the status register
457 EFI_TIMEOUT - Time out
458 EFI_SUCCESS - Success
467 // Timeout is in us unit
469 Delay
= (Timeout
/ 50) + 1;
471 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
472 if (EFI_ERROR (Status
)) {
473 return EFI_DEVICE_ERROR
;
476 if ((HcStatus
& USBSTS_HCH
) == USBSTS_HCH
) {
495 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
496 IN UINT32 StatusRegAddr
502 Judge whether the host controller operates well
506 PciIo - EFI_PCI_IO_PROTOCOL
507 StatusRegAddr - Status register address
511 TRUE - Status is good
512 FALSE - Status is bad
519 // Detect whether the interrupt is caused by fatal error.
520 // see "UHCI Design Guid".
522 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
523 if (EFI_ERROR (Status
)) {
527 if (HcStatus
& (USBSTS_HCPE
| USBSTS_HSE
| USBSTS_HCH
)) {
537 IsHostSysOrProcessErr (
538 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
539 IN UINT32 StatusRegAddr
545 Judge the status is HostSys,ProcessErr error or good
549 PciIo - EFI_PCI_IO_PROTOCOL
550 StatusRegAddr - Status register address
554 TRUE - Status is good
555 FALSE - Status is bad
562 // Detect whether the interrupt is caused by serious error.
563 // see "UHCI Design Guid".
565 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
566 if (EFI_ERROR (Status
)) {
570 if (HcStatus
& (USBSTS_HSE
| USBSTS_HCPE
)) {
579 GetCurrentFrameNumber (
580 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
581 IN UINT32 FrameNumAddrOffset
587 Get Current Frame Number
591 PciIo - EFI_PCI_IO_PROTOCOL
592 FrameNumAddrOffset - FrameNum register AddrOffset
601 // Gets value in the USB frame number register.
605 ReadUHCFrameNumberReg (PciIo
, FrameNumAddrOffset
, &FrameNumber
);
607 return (UINT16
) (FrameNumber
& 0x03FF);
611 SetFrameListBaseAddress (
612 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
613 IN UINT32 FlBaseAddrReg
,
620 Set FrameListBase Address
624 PciIo - EFI_PCI_IO_PROTOCOL
625 FlBaseAddrReg - FrameListBase register
626 Addr - Address to set
635 // Sets value in the USB Frame List Base Address register.
637 return WriteUHCFrameListBaseReg (PciIo
, FlBaseAddrReg
, (UINT32
) (Addr
& 0xFFFFF000));
641 EnableMaxPacketSize (
648 Enable Max Packet Size
660 UINT16 CommandContent
;
668 if ((CommandContent
& USBCMD_MAXP
) != USBCMD_MAXP
) {
669 CommandContent
|= USBCMD_MAXP
;
682 IN USB_HC_DEV
*HcDev
,
683 IN UINT32 FlBaseAddrReg
694 FlBaseAddrReg - Frame List register
698 EFI_OUT_OF_RESOURCES - Can't allocate memory resources
699 EFI_UNSUPPORTED - Map memory fail
700 EFI_SUCCESS - Success
706 EFI_PHYSICAL_ADDRESS MappedAddress
;
708 UINTN BufferSizeInPages
;
709 UINTN BufferSizeInBytes
;
712 // The Frame List is a common buffer that will be
713 // accessed by both the cpu and the usb bus master
715 // The Frame List ocupies 4K bytes,
716 // and must be aligned on 4-Kbyte boundaries.
718 BufferSizeInBytes
= 4096;
719 BufferSizeInPages
= EFI_SIZE_TO_PAGES (BufferSizeInBytes
);
720 Status
= HcDev
->PciIo
->AllocateBuffer (
728 if (EFI_ERROR (Status
)) {
729 return EFI_OUT_OF_RESOURCES
;
732 Status
= HcDev
->PciIo
->Map (
734 EfiPciIoOperationBusMasterCommonBuffer
,
740 if (EFI_ERROR (Status
) || (BufferSizeInBytes
!= 4096)) {
741 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, BufferSizeInPages
, CommonBuffer
);
742 return EFI_UNSUPPORTED
;
745 HcDev
->FrameListEntry
= (FRAMELIST_ENTRY
*) ((UINTN
) MappedAddress
);
747 HcDev
->FrameListMapping
= Mapping
;
749 InitFrameList (HcDev
);
752 // Tell the Host Controller where the Frame List lies,
753 // by set the Frame List Base Address Register.
755 SetFrameListBaseAddress (
758 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
772 Free FrameList buffer
780 EFI_SUCCESS - success
785 // Unmap the common buffer for framelist entry,
786 // and free the common buffer.
787 // Uhci's frame list occupy 4k memory.
789 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, HcDev
->FrameListMapping
);
790 HcDev
->PciIo
->FreeBuffer (
792 EFI_SIZE_TO_PAGES (4096),
793 (VOID
*) (HcDev
->FrameListEntry
)
817 FRAMELIST_ENTRY
*FrameListPtr
;
821 // Validate each Frame List Entry
823 FrameListPtr
= HcDev
->FrameListEntry
;
824 for (Index
= 0; Index
< 1024; Index
++) {
825 FrameListPtr
->FrameListPtrTerminate
= 1;
826 FrameListPtr
->FrameListPtr
= 0;
827 FrameListPtr
->FrameListPtrQSelect
= 0;
828 FrameListPtr
->FrameListRsvd
= 0;
833 // //////////////////////////////////////////////////////////////
835 // QH TD related Helper Functions
837 ////////////////////////////////////////////////////////////////
844 IN USB_HC_DEV
*HcDev
,
845 OUT QH_STRUCT
**ppQHStruct
856 ppQHStruct - QH_STRUCT content to return
866 // QH must align on 16 bytes alignment,
867 // since the memory allocated by UhciAllocatePool ()
868 // is aligned on 32 bytes, it is no need to adjust
869 // the allocated memory returned.
871 return UhciAllocatePool (HcDev
, (UINT8
**) ppQHStruct
, sizeof (QH_STRUCT
));
877 IN USB_HC_DEV
*HcDev
,
878 OUT QH_STRUCT
**pptrQH
889 ppQHStruct - QH_STRUCT content to return
892 EFI_SUCCESS - Success
893 EFI_OUT_OF_RESOURCES - Can't allocate memory
899 // allocate align memory for QH_STRUCT
901 Status
= AllocateQHStruct (HcDev
, pptrQH
);
902 if (EFI_ERROR (Status
)) {
903 return EFI_OUT_OF_RESOURCES
;
906 // init each field of the QH_STRUCT
911 SetQHHorizontalValidorInvalid (*pptrQH
, FALSE
);
912 SetQHVerticalValidorInvalid (*pptrQH
, FALSE
);
918 SetQHHorizontalLinkPtr (
926 Set QH Horizontal Link Pointer
931 ptrNext - Data to write
940 // Since the QH_STRUCT is aligned on 16-byte boundaries,
941 // Only the highest 28bit of the address is valid
942 // (take 32bit address as an example).
944 PtrQH
->QH
.QHHorizontalPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
948 GetQHHorizontalLinkPtr (
955 Get QH Horizontal Link Pointer
969 // Restore the 28bit address to 32bit address
970 // (take 32bit address as an example)
972 return (VOID
*) ((UINTN
) (PtrQH
->QH
.QHHorizontalPtr
<< 4));
976 SetQHHorizontalQHorTDSelect (
984 Set QH Horizontal QH or TD
989 bQH - TRUE is QH FALSE is TD
997 // if QH is connected, the specified bit is set,
998 // if TD is connected, the specified bit is cleared.
1000 PtrQH
->QH
.QHHorizontalQSelect
= bQH
? 1 : 0;
1005 SetQHHorizontalValidorInvalid (
1006 IN QH_STRUCT
*PtrQH
,
1011 Routine Description:
1013 Set QH Horizontal Valid or Invalid
1018 bValid - TRUE is Valid FALSE is Invalid
1026 // Valid means the horizontal link pointer is valid,
1027 // else, it's invalid.
1029 PtrQH
->QH
.QHHorizontalTerminate
= bValid
? 0 : 1;
1033 SetQHVerticalLinkPtr (
1034 IN QH_STRUCT
*PtrQH
,
1039 Routine Description:
1041 Set QH Vertical Link Pointer
1046 ptrNext - Data to write
1054 // Since the QH_STRUCT is aligned on 16-byte boundaries,
1055 // Only the highest 28bit of the address is valid
1056 // (take 32bit address as an example).
1058 PtrQH
->QH
.QHVerticalPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
1062 GetQHVerticalLinkPtr (
1067 Routine Description:
1069 Get QH Vertical Link Pointer
1082 // Restore the 28bit address to 32bit address
1083 // (take 32bit address as an example)
1085 return (VOID
*) ((UINTN
) (PtrQH
->QH
.QHVerticalPtr
<< 4));
1089 SetQHVerticalQHorTDSelect (
1090 IN QH_STRUCT
*PtrQH
,
1095 Routine Description:
1097 Set QH Vertical QH or TD
1102 bQH - TRUE is QH FALSE is TD
1111 // Set the specified bit if the Vertical Link Pointer pointing to a QH,
1112 // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
1114 PtrQH
->QH
.QHVerticalQSelect
= bQH
? 1 : 0;
1118 IsQHHorizontalQHSelect (
1123 Routine Description:
1125 Is QH Horizontal QH Select
1139 // Retrieve the information about whether the Horizontal Link Pointer
1140 // pointing to a QH or TD.
1142 return (BOOLEAN
) (PtrQH
->QH
.QHHorizontalQSelect
? TRUE
: FALSE
);
1146 SetQHVerticalValidorInvalid (
1147 IN QH_STRUCT
*PtrQH
,
1152 Routine Description:
1154 Set QH Vertical Valid or Invalid
1159 IsValid - TRUE is valid FALSE is invalid
1168 // If TRUE, indicates the Vertical Link Pointer field is valid,
1169 // else, the field is invalid.
1171 PtrQH
->QH
.QHVerticalTerminate
= IsValid
? 0 : 1;
1176 GetQHVerticalValidorInvalid (
1181 Routine Description:
1183 Get QH Vertical Valid or Invalid
1197 // If TRUE, indicates the Vertical Link Pointer field is valid,
1198 // else, the field is invalid.
1200 return (BOOLEAN
) (!(PtrQH
->QH
.QHVerticalTerminate
));
1205 GetQHHorizontalValidorInvalid (
1210 Routine Description:
1212 Get QH Horizontal Valid or Invalid
1226 // If TRUE, meaning the Horizontal Link Pointer field is valid,
1227 // else, the field is invalid.
1229 return (BOOLEAN
) (!(PtrQH
->QH
.QHHorizontalTerminate
));
1236 IN USB_HC_DEV
*HcDev
,
1237 OUT TD_STRUCT
**ppTDStruct
1241 Routine Description:
1248 ppTDStruct - place to store TD_STRUCT pointer
1258 // TD must align on 16 bytes alignment,
1259 // since the memory allocated by UhciAllocatePool ()
1260 // is aligned on 32 bytes, it is no need to adjust
1261 // the allocated memory returned.
1263 return UhciAllocatePool (
1265 (UINT8
**) ppTDStruct
,
1272 IN USB_HC_DEV
*HcDev
,
1273 OUT TD_STRUCT
**pptrTD
1277 Routine Description:
1284 pptrTD - TD_STRUCT pointer to store
1288 EFI_OUT_OF_RESOURCES - Can't allocate resources
1289 EFI_SUCCESS - Success
1295 // create memory for TD_STRUCT, and align the memory.
1297 Status
= AllocateTDStruct (HcDev
, pptrTD
);
1298 if (EFI_ERROR (Status
)) {
1299 return EFI_OUT_OF_RESOURCES
;
1305 SetTDLinkPtrValidorInvalid (*pptrTD
, FALSE
);
1313 IN USB_HC_DEV
*HcDev
,
1318 IN UINT8 RequestLen
,
1319 OUT TD_STRUCT
**ppTD
1323 Routine Description:
1325 Generate Setup Stage TD
1330 DevAddr - Device address
1331 Endpoint - Endpoint number
1332 bSlow - Full speed or low speed
1333 pDevReq - Device request
1334 RequestLen - Request length
1335 ppTD - TD_STRUCT to return
1338 EFI_OUT_OF_RESOURCES - Can't allocate memory
1339 EFI_SUCCESS - Success
1344 TD_STRUCT
*pTDStruct
;
1346 Status
= CreateTD (HcDev
, &pTDStruct
);
1347 if (EFI_ERROR (Status
)) {
1348 return EFI_OUT_OF_RESOURCES
;
1351 SetTDLinkPtr (pTDStruct
, NULL
);
1354 // Depth first fashion
1356 SetTDLinkPtrDepthorBreadth (pTDStruct
, TRUE
);
1359 // initialize as the last TD in the QH context,
1360 // this field will be updated in the TD linkage process.
1362 SetTDLinkPtrValidorInvalid (pTDStruct
, FALSE
);
1365 // Disable Short Packet Detection by default
1367 EnableorDisableTDShortPacket (pTDStruct
, FALSE
);
1370 // Max error counter is 3, retry 3 times when error encountered.
1372 SetTDControlErrorCounter (pTDStruct
, 3);
1375 // set device speed attribute
1376 // (TRUE - Slow Device; FALSE - Full Speed Device)
1378 SetTDLoworFullSpeedDevice (pTDStruct
, bSlow
);
1381 // Non isochronous transfer TD
1383 SetTDControlIsochronousorNot (pTDStruct
, FALSE
);
1386 // Interrupt On Complete bit be set to zero,
1387 // Disable IOC interrupt.
1389 SetorClearTDControlIOC (pTDStruct
, FALSE
);
1392 // Set TD Active bit
1394 SetTDStatusActiveorInactive (pTDStruct
, TRUE
);
1396 SetTDTokenMaxLength (pTDStruct
, RequestLen
);
1398 SetTDTokenDataToggle0 (pTDStruct
);
1400 SetTDTokenEndPoint (pTDStruct
, Endpoint
);
1402 SetTDTokenDeviceAddress (pTDStruct
, DevAddr
);
1404 SetTDTokenPacketID (pTDStruct
, SETUP_PACKET_ID
);
1406 pTDStruct
->pTDBuffer
= (UINT8
*) pDevReq
;
1407 pTDStruct
->TDBufferLength
= RequestLen
;
1408 SetTDDataBuffer (pTDStruct
);
1417 IN USB_HC_DEV
*HcDev
,
1425 OUT TD_STRUCT
**ppTD
1429 Routine Description:
1431 Generate Data Stage TD
1436 DevAddr - Device address
1437 Endpoint - Endpoint number
1441 Toggle - Data toggle value
1442 bSlow - Full speed or low speed
1443 ppTD - TD_STRUCT to return
1446 EFI_OUT_OF_RESOURCES - Can't allocate memory
1447 EFI_SUCCESS - Success
1451 TD_STRUCT
*pTDStruct
;
1454 Status
= CreateTD (HcDev
, &pTDStruct
);
1455 if (EFI_ERROR (Status
)) {
1456 return EFI_OUT_OF_RESOURCES
;
1459 SetTDLinkPtr (pTDStruct
, NULL
);
1462 // Depth first fashion
1464 SetTDLinkPtrDepthorBreadth (pTDStruct
, TRUE
);
1467 // Link pointer pointing to TD struct
1469 SetTDLinkPtrQHorTDSelect (pTDStruct
, FALSE
);
1472 // initialize as the last TD in the QH context,
1473 // this field will be updated in the TD linkage process.
1475 SetTDLinkPtrValidorInvalid (pTDStruct
, FALSE
);
1478 // Disable short packet detect
1480 EnableorDisableTDShortPacket (pTDStruct
, FALSE
);
1482 // Max error counter is 3
1484 SetTDControlErrorCounter (pTDStruct
, 3);
1487 // set device speed attribute
1488 // (TRUE - Slow Device; FALSE - Full Speed Device)
1490 SetTDLoworFullSpeedDevice (pTDStruct
, bSlow
);
1493 // Non isochronous transfer TD
1495 SetTDControlIsochronousorNot (pTDStruct
, FALSE
);
1498 // Disable Interrupt On Complete
1499 // Disable IOC interrupt.
1501 SetorClearTDControlIOC (pTDStruct
, FALSE
);
1506 SetTDStatusActiveorInactive (pTDStruct
, TRUE
);
1508 SetTDTokenMaxLength (pTDStruct
, Len
);
1511 SetTDTokenDataToggle1 (pTDStruct
);
1513 SetTDTokenDataToggle0 (pTDStruct
);
1516 SetTDTokenEndPoint (pTDStruct
, Endpoint
);
1518 SetTDTokenDeviceAddress (pTDStruct
, DevAddr
);
1520 SetTDTokenPacketID (pTDStruct
, PktID
);
1522 pTDStruct
->pTDBuffer
= (UINT8
*) pData
;
1523 pTDStruct
->TDBufferLength
= Len
;
1524 SetTDDataBuffer (pTDStruct
);
1533 IN USB_HC_DEV
*HcDev
,
1538 OUT TD_STRUCT
**ppTD
1542 Routine Description:
1544 Generate Status Stage TD
1549 DevAddr - Device address
1550 Endpoint - Endpoint number
1552 bSlow - Full speed or low speed
1553 ppTD - TD_STRUCT to return
1556 EFI_OUT_OF_RESOURCES - Can't allocate memory
1557 EFI_SUCCESS - Success
1561 TD_STRUCT
*ptrTDStruct
;
1564 Status
= CreateTD (HcDev
, &ptrTDStruct
);
1565 if (EFI_ERROR (Status
)) {
1566 return EFI_OUT_OF_RESOURCES
;
1569 SetTDLinkPtr (ptrTDStruct
, NULL
);
1572 // Depth first fashion
1574 SetTDLinkPtrDepthorBreadth (ptrTDStruct
, TRUE
);
1577 // initialize as the last TD in the QH context,
1578 // this field will be updated in the TD linkage process.
1580 SetTDLinkPtrValidorInvalid (ptrTDStruct
, FALSE
);
1583 // Disable short packet detect
1585 EnableorDisableTDShortPacket (ptrTDStruct
, FALSE
);
1588 // Max error counter is 3
1590 SetTDControlErrorCounter (ptrTDStruct
, 3);
1593 // set device speed attribute
1594 // (TRUE - Slow Device; FALSE - Full Speed Device)
1596 SetTDLoworFullSpeedDevice (ptrTDStruct
, bSlow
);
1599 // Non isochronous transfer TD
1601 SetTDControlIsochronousorNot (ptrTDStruct
, FALSE
);
1604 // Disable Interrupt On Complete
1605 // Disable IOC interrupt.
1607 SetorClearTDControlIOC (ptrTDStruct
, FALSE
);
1610 // Set TD Active bit
1612 SetTDStatusActiveorInactive (ptrTDStruct
, TRUE
);
1614 SetTDTokenMaxLength (ptrTDStruct
, 0);
1616 SetTDTokenDataToggle1 (ptrTDStruct
);
1618 SetTDTokenEndPoint (ptrTDStruct
, Endpoint
);
1620 SetTDTokenDeviceAddress (ptrTDStruct
, DevAddr
);
1622 SetTDTokenPacketID (ptrTDStruct
, PktID
);
1624 ptrTDStruct
->pTDBuffer
= NULL
;
1625 ptrTDStruct
->TDBufferLength
= 0;
1626 SetTDDataBuffer (ptrTDStruct
);
1628 *ppTD
= ptrTDStruct
;
1635 SetTDLinkPtrValidorInvalid (
1636 IN TD_STRUCT
*ptrTDStruct
,
1641 Routine Description:
1643 Set TD Link Pointer Valid or Invalid
1647 ptrTDStruct - TD_STRUCT
1648 bValid - TRUE is valid FALSE is invalid
1657 // Valid means the link pointer is valid,
1658 // else, it's invalid.
1660 ptrTDStruct
->TDData
.TDLinkPtrTerminate
= (bValid
? 0 : 1);
1664 SetTDLinkPtrQHorTDSelect (
1665 IN TD_STRUCT
*ptrTDStruct
,
1670 Routine Description:
1672 Set TD Link Pointer QH or TD Select
1676 ptrTDStruct - TD_STRUCT
1677 bQH - TRUE is QH FALSE is TD
1686 // Indicate whether the Link Pointer pointing to a QH or TD
1688 ptrTDStruct
->TDData
.TDLinkPtrQSelect
= (bQH
? 1 : 0);
1692 SetTDLinkPtrDepthorBreadth (
1693 IN TD_STRUCT
*ptrTDStruct
,
1698 Routine Description:
1700 Set TD Link Pointer depth or bread priority
1704 ptrTDStruct - TD_STRUCT
1705 bDepth - TRUE is Depth FALSE is Breadth
1714 // If TRUE, indicating the host controller should process in depth first
1716 // else, the host controller should process in breadth first fashion
1718 ptrTDStruct
->TDData
.TDLinkPtrDepthSelect
= (bDepth
? 1 : 0);
1723 IN TD_STRUCT
*ptrTDStruct
,
1728 Routine Description:
1734 ptrTDStruct - TD_STRUCT
1735 ptrNext - Pointer to set
1744 // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,
1745 // only the highest 28 bits are valid. (if take 32bit address as an example)
1747 ptrTDStruct
->TDData
.TDLinkPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
1752 IN TD_STRUCT
*ptrTDStruct
1756 Routine Description:
1762 ptrTDStruct - TD_STRUCT
1771 // Get TD Link Pointer. Restore it back to 32bit
1772 // (if take 32bit address as an example)
1774 return (VOID
*) ((UINTN
) (ptrTDStruct
->TDData
.TDLinkPtr
<< 4));
1780 IN TD_STRUCT
*ptrTDStruct
1784 Routine Description:
1786 Is TD Link Pointer is QH Or TD
1790 ptrTDStruct - TODO: add argument description
1800 // Get the information about whether the Link Pointer field pointing to
1803 return (BOOLEAN
) (ptrTDStruct
->TDData
.TDLinkPtrQSelect
);
1807 EnableorDisableTDShortPacket (
1808 IN TD_STRUCT
*ptrTDStruct
,
1813 Routine Description:
1815 Enable or Disable TD ShortPacket
1819 ptrTDStruct - TD_STRUCT
1820 bEnable - TRUE is Enanble FALSE is Disable
1829 // TRUE means enable short packet detection mechanism.
1831 ptrTDStruct
->TDData
.TDStatusSPD
= (bEnable
? 1 : 0);
1835 SetTDControlErrorCounter (
1836 IN TD_STRUCT
*ptrTDStruct
,
1841 Routine Description:
1843 Set TD Control ErrorCounter
1847 ptrTDStruct - TD_STRUCT
1848 nMaxErrors - Error counter number
1857 // valid value of nMaxErrors is 0,1,2,3
1859 if (nMaxErrors
> 3) {
1863 ptrTDStruct
->TDData
.TDStatusErr
= nMaxErrors
;
1868 SetTDLoworFullSpeedDevice (
1869 IN TD_STRUCT
*ptrTDStruct
,
1870 IN BOOLEAN bLowSpeedDevice
1874 // TRUE means the TD is targeting at a Low-speed device
1876 ptrTDStruct
->TDData
.TDStatusLS
= (bLowSpeedDevice
? 1 : 0);
1880 SetTDControlIsochronousorNot (
1881 IN TD_STRUCT
*ptrTDStruct
,
1882 IN BOOLEAN IsIsochronous
1886 // TRUE means the TD belongs to Isochronous transfer type.
1888 ptrTDStruct
->TDData
.TDStatusIOS
= (IsIsochronous
? 1 : 0);
1892 SetorClearTDControlIOC (
1893 IN TD_STRUCT
*ptrTDStruct
,
1898 // If this bit is set, it indicates that the host controller should issue
1899 // an interrupt on completion of the frame in which this TD is executed.
1901 ptrTDStruct
->TDData
.TDStatusIOC
= IsSet
? 1 : 0;
1905 SetTDStatusActiveorInactive (
1906 IN TD_STRUCT
*ptrTDStruct
,
1911 // If this bit is set, it indicates that the TD is active and can be
1915 ptrTDStruct
->TDData
.TDStatus
|= 0x80;
1917 ptrTDStruct
->TDData
.TDStatus
&= 0x7F;
1922 SetTDTokenMaxLength (
1923 IN TD_STRUCT
*ptrTDStruct
,
1924 IN UINT16 MaximumLength
1928 // Specifies the maximum number of data bytes allowed for the transfer.
1929 // the legal value extent is 0 ~ 0x500.
1931 if (MaximumLength
> 0x500) {
1932 MaximumLength
= 0x500;
1934 ptrTDStruct
->TDData
.TDTokenMaxLen
= MaximumLength
- 1;
1936 return MaximumLength
;
1940 SetTDTokenDataToggle1 (
1941 IN TD_STRUCT
*ptrTDStruct
1945 // Set the data toggle bit to DATA1
1947 ptrTDStruct
->TDData
.TDTokenDataToggle
= 1;
1951 SetTDTokenDataToggle0 (
1952 IN TD_STRUCT
*ptrTDStruct
1956 // Set the data toggle bit to DATA0
1958 ptrTDStruct
->TDData
.TDTokenDataToggle
= 0;
1962 GetTDTokenDataToggle (
1963 IN TD_STRUCT
*ptrTDStruct
1967 // Get the data toggle value.
1969 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenDataToggle
);
1973 SetTDTokenEndPoint (
1974 IN TD_STRUCT
*ptrTDStruct
,
1979 // Set EndPoint Number the TD is targeting at.
1981 ptrTDStruct
->TDData
.TDTokenEndPt
= (UINT8
) EndPoint
;
1985 SetTDTokenDeviceAddress (
1986 IN TD_STRUCT
*ptrTDStruct
,
1987 IN UINTN DeviceAddress
1991 // Set Device Address the TD is targeting at.
1993 ptrTDStruct
->TDData
.TDTokenDevAddr
= (UINT8
) DeviceAddress
;
1997 SetTDTokenPacketID (
1998 IN TD_STRUCT
*ptrTDStruct
,
2003 // Set the Packet Identification to be used for this transaction.
2005 ptrTDStruct
->TDData
.TDTokenPID
= PID
;
2010 IN TD_STRUCT
*ptrTDStruct
2014 // Set the beginning address of the data buffer that will be used
2015 // during the transaction.
2017 ptrTDStruct
->TDData
.TDBufferPtr
= (UINT32
) ((UINTN
) (ptrTDStruct
->pTDBuffer
));
2022 IN TD_STRUCT
*ptrTDStruct
2028 // Detect whether the TD is active.
2030 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2031 return (BOOLEAN
) (TDStatus
& 0x80);
2036 IN TD_STRUCT
*ptrTDStruct
2042 // Detect whether the device/endpoint addressed by this TD is stalled.
2044 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2045 return (BOOLEAN
) (TDStatus
& 0x40);
2049 IsTDStatusBufferError (
2050 IN TD_STRUCT
*ptrTDStruct
2055 // Detect whether Data Buffer Error is happened.
2057 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2058 return (BOOLEAN
) (TDStatus
& 0x20);
2062 IsTDStatusBabbleError (
2063 IN TD_STRUCT
*ptrTDStruct
2069 // Detect whether Babble Error is happened.
2071 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2072 return (BOOLEAN
) (TDStatus
& 0x10);
2076 IsTDStatusNAKReceived (
2077 IN TD_STRUCT
*ptrTDStruct
2083 // Detect whether NAK is received.
2085 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2086 return (BOOLEAN
) (TDStatus
& 0x08);
2090 IsTDStatusCRCTimeOutError (
2091 IN TD_STRUCT
*ptrTDStruct
2097 // Detect whether CRC/Time Out Error is encountered.
2099 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2100 return (BOOLEAN
) (TDStatus
& 0x04);
2104 IsTDStatusBitStuffError (
2105 IN TD_STRUCT
*ptrTDStruct
2111 // Detect whether Bitstuff Error is received.
2113 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2114 return (BOOLEAN
) (TDStatus
& 0x02);
2118 GetTDStatusActualLength (
2119 IN TD_STRUCT
*ptrTDStruct
2123 // Retrieve the actual number of bytes that were tansferred.
2124 // the value is encoded as n-1. so return the decoded value.
2126 return (UINT16
) ((ptrTDStruct
->TDData
.TDStatusActualLength
) + 1);
2130 GetTDTokenMaxLength (
2131 IN TD_STRUCT
*ptrTDStruct
2135 // Retrieve the maximum number of data bytes allowed for the trnasfer.
2137 return (UINT16
) ((ptrTDStruct
->TDData
.TDTokenMaxLen
) + 1);
2141 GetTDTokenEndPoint (
2142 IN TD_STRUCT
*ptrTDStruct
2146 // Retrieve the endpoint number the transaction is targeting at.
2148 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenEndPt
);
2152 GetTDTokenDeviceAddress (
2153 IN TD_STRUCT
*ptrTDStruct
2157 // Retrieve the device address the transaction is targeting at.
2159 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenDevAddr
);
2163 GetTDTokenPacketID (
2164 IN TD_STRUCT
*ptrTDStruct
2168 // Retrieve the Packet Identification information.
2170 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenPID
);
2175 IN TD_STRUCT
*ptrTDStruct
2179 // Retrieve the beginning address of the data buffer
2180 // that involved in this transaction.
2182 return ptrTDStruct
->pTDBuffer
;
2186 GetTDLinkPtrValidorInvalid (
2187 IN TD_STRUCT
*ptrTDStruct
2191 // Retrieve the information of whether the Link Pointer field
2194 if (ptrTDStruct
->TDData
.TDLinkPtrTerminate
) {
2204 IN TD_STRUCT
*PtrFirstTD
2210 // Count the queued TDs number.
2215 ptr
= (TD_STRUCT
*) ptr
->ptrNextTD
;
2226 IN QH_STRUCT
*PtrQH
,
2231 Routine Description:
2245 if (PtrQH
== NULL
|| PtrTD
== NULL
) {
2249 // Validate QH Vertical Ptr field
2251 SetQHVerticalValidorInvalid (PtrQH
, TRUE
);
2254 // Vertical Ptr pointing to TD structure
2256 SetQHVerticalQHorTDSelect (PtrQH
, FALSE
);
2258 SetQHVerticalLinkPtr (PtrQH
, (VOID
*) PtrTD
);
2260 PtrQH
->ptrDown
= (VOID
*) PtrTD
;
2265 IN TD_STRUCT
*ptrPreTD
,
2270 Routine Description:
2276 ptrPreTD - Previous TD_STRUCT to be linked
2277 PtrTD - TD_STRUCT to link
2284 if (ptrPreTD
== NULL
|| PtrTD
== NULL
) {
2288 // Depth first fashion
2290 SetTDLinkPtrDepthorBreadth (ptrPreTD
, TRUE
);
2293 // Link pointer pointing to TD struct
2295 SetTDLinkPtrQHorTDSelect (ptrPreTD
, FALSE
);
2298 // Validate the link pointer valid bit
2300 SetTDLinkPtrValidorInvalid (ptrPreTD
, TRUE
);
2302 SetTDLinkPtr (ptrPreTD
, PtrTD
);
2304 ptrPreTD
->ptrNextTD
= (VOID
*) PtrTD
;
2307 // Transfer Schedule related Helper Functions
2310 SetorClearCurFrameListTerminate (
2311 IN FRAMELIST_ENTRY
*pCurEntry
,
2316 // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.
2318 pCurEntry
->FrameListPtrTerminate
= (IsSet
? 1 : 0);
2322 SetCurFrameListQHorTD (
2323 IN FRAMELIST_ENTRY
*pCurEntry
,
2328 // This bit indicates to the hardware whether the item referenced by the
2329 // link pointer is a TD or a QH.
2331 pCurEntry
->FrameListPtrQSelect
= (IsQH
? 1 : 0);
2336 IsCurFrameListQHorTD (
2337 IN FRAMELIST_ENTRY
*pCurEntry
2344 return (BOOLEAN
) (pCurEntry
->FrameListPtrQSelect
);
2348 GetCurFrameListTerminate (
2349 IN FRAMELIST_ENTRY
*pCurEntry
2353 // TRUE means the frame is empty,
2354 // FALSE means the link pointer field is valid.
2356 return (BOOLEAN
) (pCurEntry
->FrameListPtrTerminate
);
2360 SetCurFrameListPointer (
2361 IN FRAMELIST_ENTRY
*pCurEntry
,
2366 // Set the pointer field of the frame.
2368 pCurEntry
->FrameListPtr
= (UINT32
) ((UINTN
) ptr
>> 4);
2372 GetCurFrameListPointer (
2373 IN FRAMELIST_ENTRY
*pCurEntry
2377 // Get the link pointer of the frame.
2379 return (VOID
*) ((UINTN
) (pCurEntry
->FrameListPtr
<< 4));
2385 IN FRAMELIST_ENTRY
*pEntry
,
2386 IN UINT16 FrameListIndex
,
2391 Routine Description:
2393 Link QH To Frame List
2397 pEntry - FRAMELIST_ENTRY
2398 FrameListIndex - Frame List Index
2406 FRAMELIST_ENTRY
*pCurFrame
;
2408 QH_STRUCT
*NextTempQH
;
2413 // Get frame list entry that the link process will begin from.
2415 pCurFrame
= pEntry
+ FrameListIndex
;
2418 // if current frame is empty
2419 // then link the specified QH directly to the Frame List.
2421 if (GetCurFrameListTerminate (pCurFrame
)) {
2424 // Link new QH to the frame list entry.
2426 SetCurFrameListQHorTD (pCurFrame
, TRUE
);
2428 SetCurFrameListPointer (pCurFrame
, (UINT8
*) PtrQH
);
2431 // clear T bit in the Frame List, indicating that the frame list entry
2432 // is no longer empty.
2434 SetorClearCurFrameListTerminate (pCurFrame
, FALSE
);
2440 // current frame list has link pointer
2442 if (!IsCurFrameListQHorTD (pCurFrame
)) {
2444 // a TD is linked to the framelist entry
2446 TempTD
= (TD_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2448 while (GetTDLinkPtrValidorInvalid (TempTD
)) {
2450 if (IsTDLinkPtrQHOrTD (TempTD
)) {
2452 // QH linked next to the TD
2457 TempTD
= (TD_STRUCT
*) GetTDLinkPtr (TempTD
);
2461 // either no ptr linked next to the TD or QH is linked next to the TD
2463 if (!GetTDLinkPtrValidorInvalid (TempTD
)) {
2466 // no ptr linked next to the TD
2468 TempTD
->ptrNextQH
= PtrQH
;
2469 SetTDLinkPtrQHorTDSelect (TempTD
, TRUE
);
2470 SetTDLinkPtr (TempTD
, PtrQH
);
2471 SetTDLinkPtrValidorInvalid (TempTD
, TRUE
);
2476 // QH is linked next to the TD
2478 TempQH
= (QH_STRUCT
*) GetTDLinkPtr (TempTD
);
2482 // a QH is linked to the framelist entry
2484 TempQH
= (QH_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2493 // Avoid the same qh repeated linking in one frame entry
2495 if (TempQH
== PtrQH
) {
2500 // if current QH has next QH connected
2502 while (GetQHHorizontalValidorInvalid (TempQH
)) {
2504 // Get next QH pointer
2506 NextTempQH
= (QH_STRUCT
*) GetQHHorizontalLinkPtr (TempQH
);
2509 // Bulk transfer qh may be self-linked,
2510 // so, the code below is to aVOID dead-loop when meeting self-linked qh
2512 if (NextTempQH
== TempQH
) {
2517 TempQH
= NextTempQH
;
2520 // Avoid the same qh repeated linking in one frame entry
2522 if (TempQH
== PtrQH
) {
2528 TempQH
->ptrNext
= PtrQH
;
2529 SetQHHorizontalQHorTDSelect (TempQH
, TRUE
);
2530 SetQHHorizontalLinkPtr (TempQH
, PtrQH
);
2531 SetQHHorizontalValidorInvalid (TempQH
, TRUE
);
2539 ExecuteControlTransfer (
2540 IN USB_HC_DEV
*HcDev
,
2541 IN TD_STRUCT
*PtrTD
,
2543 OUT UINTN
*ActualLen
,
2545 OUT UINT32
*TransferResult
2549 Routine Description:
2551 Execute Control Transfer
2558 ActualLen - Actual transfered Len
2559 TimeOut - TimeOut value in milliseconds
2560 TransferResult - Transfer result
2563 EFI_SUCCESS - Sucess
2564 EFI_DEVICE_ERROR - Error
2572 BOOLEAN TransferFinished
;
2575 *TransferResult
= EFI_USB_NOERROR
;
2576 RequiredLen
= *ActualLen
;
2579 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2582 TransferFinished
= CheckTDsResults (
2590 if (TransferFinished
) {
2595 // TD is inactive, which means the control transfer is end.
2597 if ((*TransferResult
& EFI_USB_ERR_NOTEXECUTE
) != EFI_USB_ERR_NOTEXECUTE
) {
2605 if (*TransferResult
!= EFI_USB_NOERROR
) {
2606 return EFI_DEVICE_ERROR
;
2613 ExecBulkorSyncInterruptTransfer (
2614 IN USB_HC_DEV
*HcDev
,
2615 IN TD_STRUCT
*PtrTD
,
2617 OUT UINTN
*ActualLen
,
2618 OUT UINT8
*DataToggle
,
2620 OUT UINT32
*TransferResult
2624 Routine Description:
2626 Execute Bulk or SyncInterrupt Transfer
2633 ActualLen - Actual transfered Len
2634 DataToggle - Data Toggle
2635 TimeOut - TimeOut value in milliseconds
2636 TransferResult - Transfer result
2639 EFI_SUCCESS - Sucess
2640 EFI_DEVICE_ERROR - Error
2647 BOOLEAN TransferFinished
;
2650 *TransferResult
= EFI_USB_NOERROR
;
2651 RequiredLen
= *ActualLen
;
2654 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2658 TransferFinished
= CheckTDsResults (
2666 if (TransferFinished
) {
2671 // TD is inactive, which means bulk or interrupt transfer's end.
2673 if ((*TransferResult
& EFI_USB_ERR_NOTEXECUTE
) != EFI_USB_ERR_NOTEXECUTE
) {
2684 if (*TransferResult
!= EFI_USB_NOERROR
) {
2687 // scroll the Data Toggle back to the last success TD
2689 ScrollNum
= CountTDsNumber (PtrTD
) - ErrTDPos
;
2690 if (ScrollNum
& 0x1) {
2694 return EFI_DEVICE_ERROR
;
2702 IN USB_HC_DEV
*HcDev
,
2703 IN QH_STRUCT
*PtrQH
,
2704 IN UINT16 FrameListIndex
,
2705 IN BOOLEAN SearchOther
,
2710 Routine Description:
2712 Unlink from frame list and delete single QH
2717 FrameListIndex - Frame List Index
2718 SearchOther - Search Other QH
2719 Delete - TRUE is to delete the QH
2724 FRAMELIST_ENTRY
*pCurFrame
;
2728 QH_STRUCT
*CurrentQH
;
2730 TD_STRUCT
*CurrentTD
;
2738 if (PtrQH
== NULL
) {
2746 BeginFrame
= FrameListIndex
;
2747 EndFrame
= FrameListIndex
+ 1;
2750 for (Index
= BeginFrame
; Index
< EndFrame
; Index
++) {
2752 pCurFrame
= HcDev
->FrameListEntry
+ (Index
& 0x3FF);
2754 if (GetCurFrameListTerminate (pCurFrame
)) {
2756 // current frame list is empty,search next frame list entry
2761 if (!IsCurFrameListQHorTD (pCurFrame
)) {
2763 // TD linked to current framelist
2765 CurrentTD
= (TD_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2767 while (GetTDLinkPtrValidorInvalid (CurrentTD
)) {
2769 if (IsTDLinkPtrQHOrTD (CurrentTD
)) {
2771 // QH linked next to the TD,break while ()
2776 CurrentTD
= (TD_STRUCT
*) GetTDLinkPtr (CurrentTD
);
2779 if (!GetTDLinkPtrValidorInvalid (CurrentTD
)) {
2781 // no QH linked next to the last TD,
2782 // search next frame list
2788 // a QH linked next to the last TD
2790 CurrentQH
= (QH_STRUCT
*) GetTDLinkPtr (CurrentTD
);
2792 PtrPreQH
= CurrentTD
;
2796 // a QH linked to current framelist
2798 CurrentQH
= (QH_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2803 if (CurrentQH
== PtrQH
) {
2805 if (GetQHHorizontalValidorInvalid (PtrQH
)) {
2807 // there is QH connected after the QH found
2810 // retrieve nex qh pointer of the qh found.
2812 NextQH
= GetQHHorizontalLinkPtr (PtrQH
);
2819 // QH linked to a TD struct
2821 CurrentTD
= (TD_STRUCT
*) PtrPreQH
;
2823 SetTDLinkPtrValidorInvalid (CurrentTD
, (BOOLEAN
) ((NextQH
== NULL
) ? FALSE
: TRUE
));
2824 SetTDLinkPtr (CurrentTD
, NextQH
);
2825 CurrentTD
->ptrNextQH
= NextQH
;
2829 // QH linked directly to current framelist entry
2831 SetorClearCurFrameListTerminate (pCurFrame
, (BOOLEAN
) ((NextQH
== NULL
) ? TRUE
: FALSE
));
2832 SetCurFrameListPointer (pCurFrame
, (UINT8
*) NextQH
);
2837 // search next framelist entry
2842 while (GetQHHorizontalValidorInvalid (CurrentQH
)) {
2844 PtrPreQH
= CurrentQH
;
2846 // Get next horizontal linked QH
2848 CurrentQH
= (QH_STRUCT
*) GetQHHorizontalLinkPtr (CurrentQH
);
2852 if (CurrentQH
== PtrQH
) {
2858 // search next frame list entry
2860 if (CurrentQH
!= PtrQH
) {
2867 // find the specified qh, then delink it from
2868 // the horizontal QH list in the frame entry.
2871 if (GetQHHorizontalValidorInvalid (PtrQH
)) {
2873 // there is QH connected after the QH found
2876 // retrieve nex qh pointer of the qh found.
2878 NextQH
= GetQHHorizontalLinkPtr (PtrQH
);
2882 // NO QH connected after the QH found
2886 // NULL the previous QH's link ptr and set Terminate field.
2888 SetQHHorizontalValidorInvalid ((QH_STRUCT
*) PtrPreQH
, FALSE
);
2891 SetQHHorizontalLinkPtr ((QH_STRUCT
*) PtrPreQH
, NextQH
);
2892 ((QH_STRUCT
*) PtrPreQH
)->ptrNext
= NextQH
;
2897 if (Found
&& Delete
) {
2899 // free memory once used by the specific QH
2901 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2910 IN USB_HC_DEV
*HcDev
,
2911 IN TD_STRUCT
*PtrFirstTD
2914 Routine Description:
2920 PtrFirstTD - TD link list head
2932 // Delete all the TDs in a queue.
2938 if (!GetTDLinkPtrValidorInvalid (Tptr2
)) {
2942 Tptr1
= GetTDLinkPtr (Tptr2
);
2945 // TD link to itself
2947 if (Tptr1
== Tptr2
) {
2952 UhciFreePool (HcDev
, (UINT8
*) Tptr2
, sizeof (TD_STRUCT
));
2959 InsertQHTDToINTList (
2960 IN USB_HC_DEV
*HcDev
,
2961 IN QH_STRUCT
*PtrQH
,
2962 IN TD_STRUCT
*PtrFirstTD
,
2963 IN UINT8 DeviceAddress
,
2964 IN UINT8 EndPointAddress
,
2965 IN UINT8 DataToggle
,
2966 IN UINTN DataLength
,
2967 IN UINTN PollingInterval
,
2969 IN UINT8
*DataBuffer
,
2970 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
2974 Routine Description:
2975 Insert QH and TD To Interrupt List
2980 PtrFirstTD - First TD_STRUCT
2981 DeviceAddress - Device Address
2982 EndPointAddress - EndPoint Address
2983 DataToggle - Data Toggle
2984 DataLength - Data length
2985 PollingInterval - Polling Interval when inserted to frame list
2986 Mapping - Mapping alue
2987 DataBuffer - Data buffer
2988 CallBackFunction- CallBackFunction after interrupt transfeer
2989 Context - CallBackFunction Context passed as function parameter
2991 EFI_SUCCESS - Sucess
2992 EFI_INVALID_PARAMETER - Paremeter is error
2996 INTERRUPT_LIST
*Node
;
2998 Node
= AllocatePool (sizeof (INTERRUPT_LIST
));
3006 Node
->Signature
= INTERRUPT_LIST_SIGNATURE
;
3007 Node
->DevAddr
= DeviceAddress
;
3008 Node
->EndPoint
= EndPointAddress
;
3009 Node
->PtrQH
= PtrQH
;
3010 Node
->PtrFirstTD
= PtrFirstTD
;
3011 Node
->DataToggle
= DataToggle
;
3012 Node
->DataLen
= DataLength
;
3013 Node
->PollInterval
= PollingInterval
;
3014 Node
->Mapping
= Mapping
;
3016 // DataBuffer is allocated host memory, not mapped memory
3018 Node
->DataBuffer
= DataBuffer
;
3019 Node
->InterruptCallBack
= CallBackFunction
;
3020 Node
->InterruptContext
= Context
;
3023 // insert the new interrupt transfer to the head of the list.
3024 // The interrupt transfer's monitor function scans the whole list from head
3025 // to tail. The new interrupt transfer MUST be added to the head of the list
3026 // for the sake of error recovery.
3028 InsertHeadList (&(HcDev
->InterruptListHead
), &(Node
->Link
));
3035 DeleteAsyncINTQHTDs (
3036 IN USB_HC_DEV
*HcDev
,
3037 IN UINT8 DeviceAddress
,
3038 IN UINT8 EndPointAddress
,
3039 OUT UINT8
*DataToggle
3042 Routine Description:
3044 Delete Async INT QH and TDs
3048 DeviceAddress - Device Address
3049 EndPointAddress - EndPoint Address
3050 DataToggle - Data Toggle
3053 EFI_SUCCESS - Sucess
3054 EFI_INVALID_PARAMETER - Paremeter is error
3059 QH_STRUCT
*ptrNextQH
;
3062 INTERRUPT_LIST
*MatchList
;
3063 INTERRUPT_LIST
*PtrList
;
3075 // no interrupt transaction exists
3077 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
3078 return EFI_INVALID_PARAMETER
;
3081 // find the correct QH-TD that need to delete
3082 // (by matching Device address and EndPoint number to match QH-TD )
3085 Link
= &(HcDev
->InterruptListHead
);
3088 Link
= Link
->ForwardLink
;
3089 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
3091 if ((PtrList
->DevAddr
== DeviceAddress
) && ((PtrList
->EndPoint
& 0x0f) == (EndPointAddress
& 0x0f))) {
3092 MatchList
= PtrList
;
3098 } while (Link
->ForwardLink
!= &(HcDev
->InterruptListHead
));
3101 return EFI_INVALID_PARAMETER
;
3104 // get current endpoint's data toggle bit and save.
3106 ExecuteAsyncINTTDs (HcDev
, MatchList
, &Result
, &ErrTDPos
, &ActualLen
);
3107 UpdateAsyncINTQHTDs (MatchList
, Result
, (UINT32
) ErrTDPos
);
3108 *DataToggle
= MatchList
->DataToggle
;
3110 MatchTD
= MatchList
->PtrFirstTD
;
3111 MatchQH
= MatchList
->PtrQH
;
3113 // find the first matching QH position in the FrameList
3117 ptrNextQH
= MatchQH
->ptrNextIntQH
;
3120 // Search all the entries
3122 DelLinkSingleQH (HcDev
, MatchQH
, 0, TRUE
, TRUE
);
3124 MatchQH
= ptrNextQH
;
3128 // Call PciIo->Unmap() to unmap the busmaster read/write
3130 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, MatchList
->Mapping
);
3133 // free host data buffer allocated,
3134 // mapped data buffer is freed by Unmap
3136 if (MatchList
->DataBuffer
!= NULL
) {
3137 gBS
->FreePool (MatchList
->DataBuffer
);
3141 // at last delete the TDs, to aVOID problems
3143 DeleteQueuedTDs (HcDev
, MatchTD
);
3146 // remove Match node from interrupt list
3148 RemoveEntryList (&(MatchList
->Link
));
3149 gBS
->FreePool (MatchList
);
3155 IN TD_STRUCT
*PtrTD
,
3156 IN UINTN RequiredLen
,
3158 OUT UINTN
*ErrTDPos
,
3159 OUT UINTN
*ActualTransferSize
3163 Routine Description:
3169 PtrTD - TD_STRUCT to check
3170 RequiredLen - Required Len
3171 Result - Transfer result
3172 ErrTDPos - Error TD Position
3173 ActualTransferSize - Actual Transfer Size
3184 *Result
= EFI_USB_NOERROR
;
3190 *ActualTransferSize
= 0;
3194 if (IsTDStatusActive (PtrTD
)) {
3195 *Result
|= EFI_USB_ERR_NOTEXECUTE
;
3198 if (IsTDStatusStalled (PtrTD
)) {
3199 *Result
|= EFI_USB_ERR_STALL
;
3202 if (IsTDStatusBufferError (PtrTD
)) {
3203 *Result
|= EFI_USB_ERR_BUFFER
;
3206 if (IsTDStatusBabbleError (PtrTD
)) {
3207 *Result
|= EFI_USB_ERR_BABBLE
;
3210 if (IsTDStatusNAKReceived (PtrTD
)) {
3211 *Result
|= EFI_USB_ERR_NAK
;
3214 if (IsTDStatusCRCTimeOutError (PtrTD
)) {
3215 *Result
|= EFI_USB_ERR_TIMEOUT
;
3218 if (IsTDStatusBitStuffError (PtrTD
)) {
3219 *Result
|= EFI_USB_ERR_BITSTUFF
;
3223 // if any error encountered, stop processing the left TDs.
3229 Len
= GetTDStatusActualLength (PtrTD
) & 0x7FF;
3230 *ActualTransferSize
+= Len
;
3232 if (*ActualTransferSize
<= RequiredLen
&& Len
< PtrTD
->TDData
.TDTokenMaxLen
) {
3234 // transter finished and actural length less than required length
3239 // Accumulate actual transferred data length in each TD.
3241 PtrTD
= (TD_STRUCT
*) (PtrTD
->ptrNextTD
);
3243 // Record the first Error TD's position in the queue,
3244 // this value is zero-based.
3255 ExecuteAsyncINTTDs (
3256 IN USB_HC_DEV
*HcDev
,
3257 IN INTERRUPT_LIST
*PtrList
,
3259 OUT UINTN
*ErrTDPos
,
3260 OUT UINTN
*ActualLen
3264 Routine Description:
3266 Execute Async Interrupt TDs
3271 PtrList - INTERRUPT_LIST
3272 Result - Transfer result
3273 ErrTDPos - Error TD Position
3274 ActualTransferSize - Actual Transfer Size
3283 // *ErrTDPos is zero-based value, indicating the first error TD's position
3284 // in the TDs' sequence.
3285 // *ErrTDPos value is only valid when *Result is not equal NOERROR.
3289 RequiredLen
= *ActualLen
;
3290 CheckTDsResults (PtrList
->PtrFirstTD
, RequiredLen
, Result
, ErrTDPos
, ActualLen
);
3297 UpdateAsyncINTQHTDs (
3298 IN INTERRUPT_LIST
*PtrList
,
3304 Routine Description:
3306 Update Async Interrupt QH and TDs
3310 PtrList - INTERRUPT_LIST
3311 Result - Transfer reslut
3312 ErrTDPos - Error TD Position
3320 QH_STRUCT
*PtrFirstQH
;
3322 TD_STRUCT
*PtrFirstTD
;
3327 PtrFirstQH
= PtrList
->PtrQH
;
3328 PtrFirstTD
= PtrList
->PtrFirstTD
;
3332 if (Result
== EFI_USB_NOERROR
) {
3336 DataToggle
= GetTDTokenDataToggle (PtrTD
);
3337 PtrTD
= PtrTD
->ptrNextTD
;
3341 // save current DataToggle value to interrupt list.
3342 // this value is used for tracing the interrupt endpoint DataToggle.
3343 // when this interrupt transfer is deleted, the last DataToggle is saved
3345 PtrList
->DataToggle
= DataToggle
;
3350 // Since DataToggle bit should toggle after each success transaction,
3351 // the First TD's DataToggle bit will be updated to XOR of Last TD's
3352 // DataToggle bit. If the First TD's DataToggle bit is not equal Last
3353 // TD's DataToggle bit, that means it already be the XOR of Last TD's,
3354 // so no update is needed.
3356 if (DataToggle
== GetTDTokenDataToggle (PtrFirstTD
)) {
3362 SetTDTokenDataToggle1 (PtrTD
);
3364 SetTDTokenDataToggle0 (PtrTD
);
3367 PtrTD
= PtrTD
->ptrNextTD
;
3371 // restore Link Pointer of QH to First TD
3372 // (because QH's Link Pointer will change during TD execution)
3377 LinkTDToQH (PtrQH
, PtrFirstTD
);
3378 PtrQH
= PtrQH
->ptrNextIntQH
;
3382 // set all the TDs active
3386 SetTDStatusActiveorInactive (PtrTD
, TRUE
);
3387 PtrTD
= PtrTD
->ptrNextTD
;
3390 } else if (((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
) ||
3391 ((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
)
3402 // not first TD error
3404 if (ErrTDPos
!= 0) {
3406 // get the last success TD
3408 for (Index
= 1; Index
< ErrTDPos
; Index
++) {
3409 PtrTD
= PtrTD
->ptrNextTD
;
3412 // update Data Toggle in the interrupt list node
3414 PtrList
->DataToggle
= GetTDTokenDataToggle (PtrTD
);
3419 PtrTD
= PtrTD
->ptrNextTD
;
3422 PtrList
->DataToggle
= GetTDTokenDataToggle (PtrTD
);
3425 // do not restore the QH's vertical link pointer,
3426 // let the callback function do the rest of error handling.
3434 ReleaseInterruptList (
3435 IN USB_HC_DEV
*HcDev
,
3436 IN LIST_ENTRY
*ListHead
3440 Routine Description:
3442 Release Interrupt List
3446 ListHead - List head
3455 LIST_ENTRY
*SavedLink
;
3456 INTERRUPT_LIST
*pNode
;
3458 TD_STRUCT
*ptrNextTD
;
3462 if (ListHead
== NULL
) {
3469 // Free all the resources in the interrupt list
3471 SavedLink
= Link
->ForwardLink
;
3472 while (!IsListEmpty (ListHead
)) {
3476 SavedLink
= Link
->ForwardLink
;
3478 pNode
= INTERRUPT_LIST_FROM_LINK (Link
);
3480 RemoveEntryList (&pNode
->Link
);
3482 SavedQH
= pNode
->PtrQH
;
3483 for (PtrQH
= SavedQH
; PtrQH
!= NULL
; PtrQH
= SavedQH
) {
3484 SavedQH
= PtrQH
->ptrNextIntQH
;
3485 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3488 PtrTD
= pNode
->PtrFirstTD
;
3489 while (PtrTD
!= NULL
) {
3491 ptrNextTD
= PtrTD
->ptrNextTD
;
3492 UhciFreePool (HcDev
, (UINT8
*) PtrTD
, sizeof (TD_STRUCT
));
3496 gBS
->FreePool (pNode
);
3502 InitializeMemoryManagement (
3503 IN USB_HC_DEV
*HcDev
3507 Routine Description:
3509 Initialize Memory Management
3517 EFI_SUCCESS - Success
3520 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3524 MemPages
= NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
;
3525 Status
= CreateMemoryBlock (HcDev
, &MemoryHeader
, MemPages
);
3526 if (EFI_ERROR (Status
)) {
3530 HcDev
->MemoryHeader
= MemoryHeader
;
3537 IN USB_HC_DEV
*HcDev
,
3538 OUT MEMORY_MANAGE_HEADER
**MemoryHeader
,
3539 IN UINTN MemoryBlockSizeInPages
3543 Routine Description:
3545 Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
3546 and use PciIo->Map to map the common buffer for Bus Master Read/Write.
3552 MemoryHeader - MEMORY_MANAGE_HEADER to output
3553 MemoryBlockSizeInPages - MemoryBlockSizeInPages
3556 EFI_SUCCESS - Success
3561 EFI_PHYSICAL_ADDRESS MappedAddress
;
3562 UINTN MemoryBlockSizeInBytes
;
3566 // Allocate memory for MemoryHeader
3568 *MemoryHeader
= AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER
));
3569 if (*MemoryHeader
== NULL
) {
3570 return EFI_OUT_OF_RESOURCES
;
3573 (*MemoryHeader
)->Next
= NULL
;
3576 // set Memory block size
3578 (*MemoryHeader
)->MemoryBlockSizeInBytes
= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
);
3581 // each bit in Bit Array will manage 32 bytes memory in memory block
3583 (*MemoryHeader
)->BitArraySizeInBytes
= ((*MemoryHeader
)->MemoryBlockSizeInBytes
/ 32) / 8;
3586 // Allocate memory for BitArray
3588 (*MemoryHeader
)->BitArrayPtr
= AllocateZeroPool ((*MemoryHeader
)->BitArraySizeInBytes
);
3589 if ((*MemoryHeader
)->BitArrayPtr
== NULL
) {
3590 gBS
->FreePool (*MemoryHeader
);
3591 return EFI_OUT_OF_RESOURCES
;
3595 // Memory Block uses MemoryBlockSizeInPages pages,
3596 // and it is allocated as common buffer use.
3598 Status
= HcDev
->PciIo
->AllocateBuffer (
3601 EfiBootServicesData
,
3602 MemoryBlockSizeInPages
,
3606 if (EFI_ERROR (Status
)) {
3607 gBS
->FreePool ((*MemoryHeader
)->BitArrayPtr
);
3608 gBS
->FreePool (*MemoryHeader
);
3612 MemoryBlockSizeInBytes
= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
);
3613 Status
= HcDev
->PciIo
->Map (
3615 EfiPciIoOperationBusMasterCommonBuffer
,
3617 &MemoryBlockSizeInBytes
,
3622 // if returned Mapped size is less than the size we request,do not support.
3624 if (EFI_ERROR (Status
) || (MemoryBlockSizeInBytes
!= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
))) {
3625 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, MemoryBlockSizeInPages
, CommonBuffer
);
3626 gBS
->FreePool ((*MemoryHeader
)->BitArrayPtr
);
3627 gBS
->FreePool (*MemoryHeader
);
3628 return EFI_UNSUPPORTED
;
3631 // Set Memory block initial address
3633 (*MemoryHeader
)->MemoryBlockPtr
= (UINT8
*) ((UINTN
) MappedAddress
);
3634 (*MemoryHeader
)->Mapping
= Mapping
;
3637 (*MemoryHeader
)->MemoryBlockPtr
,
3638 EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
)
3646 IN USB_HC_DEV
*HcDev
,
3647 IN MEMORY_MANAGE_HEADER
*MemoryHeader
3651 Routine Description:
3658 MemoryHeader - MemoryHeader to be freed
3662 EFI_INVALID_PARAMETER - Parameter is error
3663 EFI_SUCCESS - Success
3667 if ((MemoryHeader
== NULL
) || (HcDev
== NULL
)) {
3668 return EFI_INVALID_PARAMETER
;
3671 // unmap the common buffer used by the memory block
3673 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, MemoryHeader
->Mapping
);
3676 // free common buffer
3678 HcDev
->PciIo
->FreeBuffer (
3680 EFI_SIZE_TO_PAGES (MemoryHeader
->MemoryBlockSizeInBytes
),
3681 MemoryHeader
->MemoryBlockPtr
3686 gBS
->FreePool (MemoryHeader
->BitArrayPtr
);
3688 // free memory header
3690 gBS
->FreePool (MemoryHeader
);
3697 IN USB_HC_DEV
*HcDev
,
3703 Routine Description:
3710 Pool - Place to store pointer to the memory buffer
3711 AllocSize - Alloc Size
3715 EFI_SUCCESS - Success
3719 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3720 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
3721 MEMORY_MANAGE_HEADER
*NewMemoryHeader
;
3722 UINTN RealAllocSize
;
3723 UINTN MemoryBlockSizeInPages
;
3728 MemoryHeader
= HcDev
->MemoryHeader
;
3729 ASSERT (MemoryHeader
!= NULL
);
3732 // allocate unit is 32 bytes (align on 32 byte)
3734 if (AllocSize
& 0x1F) {
3735 RealAllocSize
= (AllocSize
/ 32 + 1) * 32;
3737 RealAllocSize
= AllocSize
;
3741 // There may be linked MemoryHeaders.
3742 // To allocate a free pool in Memory blocks,
3743 // must search in the MemoryHeader link list
3744 // until enough free pool is found.
3746 Status
= EFI_NOT_FOUND
;
3747 for (TempHeaderPtr
= MemoryHeader
; TempHeaderPtr
!= NULL
;
3748 TempHeaderPtr
= TempHeaderPtr
->Next
) {
3750 Status
= AllocMemInMemoryBlock (
3755 if (!EFI_ERROR (Status
)) {
3756 ZeroMem (*Pool
, AllocSize
);
3762 // There is no enough memory,
3763 // Create a new Memory Block
3767 // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,
3768 // just allocate a large enough memory block.
3770 if (RealAllocSize
> EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
)) {
3771 MemoryBlockSizeInPages
= EFI_SIZE_TO_PAGES (RealAllocSize
) + 1;
3773 MemoryBlockSizeInPages
= NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
;
3776 Status
= CreateMemoryBlock (HcDev
, &NewMemoryHeader
, MemoryBlockSizeInPages
);
3777 if (EFI_ERROR (Status
)) {
3782 // Link the new Memory Block to the Memory Header list
3784 InsertMemoryHeaderToList (MemoryHeader
, NewMemoryHeader
);
3786 Status
= AllocMemInMemoryBlock (
3792 if (!EFI_ERROR (Status
)) {
3793 ZeroMem (*Pool
, AllocSize
);
3801 IN USB_HC_DEV
*HcDev
,
3807 Routine Description:
3815 AllocSize - Pool size
3823 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3824 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
3830 UINTN RealAllocSize
;
3832 MemoryHeader
= HcDev
->MemoryHeader
;
3835 // allocate unit is 32 byte (align on 32 byte)
3837 if (AllocSize
& 0x1F) {
3838 RealAllocSize
= (AllocSize
/ 32 + 1) * 32;
3840 RealAllocSize
= AllocSize
;
3843 // scan the memory header linked list for
3844 // the asigned memory to free.
3846 for (TempHeaderPtr
= MemoryHeader
;TempHeaderPtr
!= NULL
;
3847 TempHeaderPtr
= TempHeaderPtr
->Next
) {
3849 if ((Pool
>= TempHeaderPtr
->MemoryBlockPtr
) &&
3850 ((Pool
+ RealAllocSize
) <= (TempHeaderPtr
->MemoryBlockPtr
+ TempHeaderPtr
->MemoryBlockSizeInBytes
))
3853 // Pool is in the Memory Block area,
3854 // find the start byte and bit in the bit array
3856 StartBytePos
= ((Pool
- TempHeaderPtr
->MemoryBlockPtr
) / 32) / 8;
3857 StartBitPos
= (UINT8
) (((Pool
- TempHeaderPtr
->MemoryBlockPtr
) / 32) & 0x7);
3860 // reset associated bits in bit arry
3862 for (Index
= StartBytePos
, Index2
= StartBitPos
, Count
= 0; Count
< (RealAllocSize
/ 32); Count
++) {
3864 TempHeaderPtr
->BitArrayPtr
[Index
] = (UINT8
) (TempHeaderPtr
->BitArrayPtr
[Index
] ^ bit (Index2
));
3879 // Release emptied memory blocks (only if the memory block is not
3880 // the first one in the memory header list
3882 for (TempHeaderPtr
= MemoryHeader
->Next
; TempHeaderPtr
!= NULL
;) {
3886 ASSERT (MemoryHeader
->Next
!= NULL
);
3888 if (IsMemoryBlockEmptied (TempHeaderPtr
)) {
3890 DelinkMemoryBlock (MemoryHeader
, TempHeaderPtr
);
3892 // when the TempHeaderPtr is freed in FreeMemoryHeader(),
3893 // the TempHeaderPtr is pointing to nonsense content.
3895 FreeMemoryHeader (HcDev
, TempHeaderPtr
);
3897 // reset the TempHeaderPtr, continue search for
3898 // another empty memory block.
3900 TempHeaderPtr
= MemoryHeader
->Next
;
3904 TempHeaderPtr
= TempHeaderPtr
->Next
;
3909 InsertMemoryHeaderToList (
3910 IN MEMORY_MANAGE_HEADER
*MemoryHeader
,
3911 IN MEMORY_MANAGE_HEADER
*NewMemoryHeader
3915 Routine Description:
3917 Insert Memory Header To List
3921 MemoryHeader - MEMORY_MANAGE_HEADER
3922 NewMemoryHeader - MEMORY_MANAGE_HEADER
3930 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
3932 for (TempHeaderPtr
= MemoryHeader
; TempHeaderPtr
!= NULL
;
3933 TempHeaderPtr
= TempHeaderPtr
->Next
) {
3934 if (TempHeaderPtr
->Next
== NULL
) {
3935 TempHeaderPtr
->Next
= NewMemoryHeader
;
3942 AllocMemInMemoryBlock (
3943 IN MEMORY_MANAGE_HEADER
*MemoryHeader
,
3945 IN UINTN NumberOfMemoryUnit
3949 Routine Description:
3951 Alloc Memory In MemoryBlock
3955 MemoryHeader - MEMORY_MANAGE_HEADER
3956 Pool - Place to store pointer to memory
3957 NumberOfMemoryUnit - Number Of Memory Unit
3961 EFI_NOT_FOUND - Can't find the free memory
3962 EFI_SUCCESS - Success
3972 UINTN NumberOfZeros
;
3977 ByteValue
= MemoryHeader
->BitArrayPtr
[0];
3981 for (TempBytePos
= 0; TempBytePos
< MemoryHeader
->BitArraySizeInBytes
;) {
3984 // Pop out BitValue from a byte in TempBytePos.
3986 BitValue
= (UINT8
) (ByteValue
& 0x1);
3988 // right shift the byte
3992 if (BitValue
== 0) {
3994 // Found a free bit, the NumberOfZeros only record the number
3995 // of those consecutive zeros
3999 // Found enough consecutive free space, break the loop
4001 if (NumberOfZeros
>= NumberOfMemoryUnit
) {
4006 // Encountering a '1', meant the bit is ocupied.
4008 if (NumberOfZeros
>= NumberOfMemoryUnit
) {
4010 // Found enough consecutive free space,break the loop
4015 // the NumberOfZeros only record the number of those consecutive zeros,
4016 // so reset the NumberOfZeros to 0 when encountering '1' before finding
4017 // enough consecutive '0's
4021 // reset the (FoundBytePos,FoundBitPos) to the position of '1'
4023 FoundBytePos
= TempBytePos
;
4024 FoundBitPos
= Index
;
4028 // step forward a bit
4033 // step forward a byte, getting the byte value,
4034 // and reset the bit pos.
4037 ByteValue
= MemoryHeader
->BitArrayPtr
[TempBytePos
];
4042 if (NumberOfZeros
< NumberOfMemoryUnit
) {
4043 return EFI_NOT_FOUND
;
4047 // Found enough free space.
4051 // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:
4052 // 1)(FoundBytePos,FoundBitPos) record the position
4053 // of the last '1' before the consecutive '0's, it must
4054 // be adjusted to the start position of the consecutive '0's.
4055 // 2)the start address of the consecutive '0's is just the start of
4056 // the bitarray. so no need to adjust the values of
4057 // (FoundBytePos,FoundBitPos).
4059 if ((MemoryHeader
->BitArrayPtr
[0] & bit (0)) != 0) {
4064 // Have the (FoundBytePos,FoundBitPos) make sense.
4066 if (FoundBitPos
> 7) {
4072 // Set the memory as allocated
4074 for (TempBytePos
= FoundBytePos
, Index
= FoundBitPos
,Count
= 0;
4075 Count
< NumberOfMemoryUnit
; Count
++) {
4077 MemoryHeader
->BitArrayPtr
[TempBytePos
] = (UINT8
) (MemoryHeader
->BitArrayPtr
[TempBytePos
] | bit (Index
));
4085 *Pool
= MemoryHeader
->MemoryBlockPtr
+ (FoundBytePos
* 8 + FoundBitPos
) * 32;
4091 IsMemoryBlockEmptied (
4092 IN MEMORY_MANAGE_HEADER
*MemoryHeaderPtr
4096 Routine Description:
4098 Is Memory Block Emptied
4102 MemoryHeaderPtr - MEMORY_MANAGE_HEADER
4113 for (Index
= 0; Index
< MemoryHeaderPtr
->BitArraySizeInBytes
; Index
++) {
4114 if (MemoryHeaderPtr
->BitArrayPtr
[Index
] != 0) {
4124 IN MEMORY_MANAGE_HEADER
*FirstMemoryHeader
,
4125 IN MEMORY_MANAGE_HEADER
*NeedFreeMemoryHeader
4129 Routine Description:
4135 FirstMemoryHeader - MEMORY_MANAGE_HEADER
4136 NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER
4144 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
4146 if ((FirstMemoryHeader
== NULL
) || (NeedFreeMemoryHeader
== NULL
)) {
4149 for (TempHeaderPtr
= FirstMemoryHeader
; TempHeaderPtr
!= NULL
;
4150 TempHeaderPtr
= TempHeaderPtr
->Next
) {
4152 if (TempHeaderPtr
->Next
== NeedFreeMemoryHeader
) {
4154 // Link the before and after
4156 TempHeaderPtr
->Next
= NeedFreeMemoryHeader
->Next
;
4163 DelMemoryManagement (
4164 IN USB_HC_DEV
*HcDev
4168 Routine Description:
4170 Delete Memory Management
4178 EFI_SUCCESS - Success
4182 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
4184 for (TempHeaderPtr
= HcDev
->MemoryHeader
->Next
; TempHeaderPtr
!= NULL
;) {
4186 DelinkMemoryBlock (HcDev
->MemoryHeader
, TempHeaderPtr
);
4188 // when the TempHeaderPtr is freed in FreeMemoryHeader(),
4189 // the TempHeaderPtr is pointing to nonsense content.
4191 FreeMemoryHeader (HcDev
, TempHeaderPtr
);
4193 // reset the TempHeaderPtr,continue free another memory block.
4195 TempHeaderPtr
= HcDev
->MemoryHeader
->Next
;
4198 FreeMemoryHeader (HcDev
, HcDev
->MemoryHeader
);
4205 CleanUsbTransactions (
4206 IN USB_HC_DEV
*HcDev
4210 // only asynchronous interrupt transfers are always alive on the bus
4212 ReleaseInterruptList (HcDev
, &(HcDev
->InterruptListHead
));
4216 TurnOffUSBEmulation (
4217 IN EFI_PCI_IO_PROTOCOL
*PciIo
4221 Routine Description:
4222 Disable USB Emulation
4224 PciIo - EFI_PCI_IO_PROTOCOL
4232 // Disable USB Emulation
4237 EfiPciIoWidthUint16
,