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 16bit Write in PCI IO Space
90 return PciIo
->Io
.Write (
103 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
104 IN UINT32 PortOffset
,
115 PciIo - EFI_PCI_IO_PROTOCOL
116 PortOffset - Port offset
126 // Perform 32bit Write in PCI IO Space
128 return PciIo
->Io
.Write (
138 // USB register-base helper functions
142 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
143 IN UINT32 CmdAddrOffset
,
150 Write UHCI Command Register
154 PciIo - EFI_PCI_IO_PROTOCOL
155 CmdAddrOffset - Command address offset
156 UsbCmd - Data to write
165 // Write to UHC's Command Register
167 return USBWritePortW (PciIo
, CmdAddrOffset
, UsbCmd
);
172 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
173 IN UINT32 CmdAddrOffset
,
180 Read UHCI Command Register
184 PciIo - EFI_PCI_IO_PROTOCOL
185 CmdAddrOffset - Command address offset
186 Data - Data to return
195 // Read from UHC's Command Register
197 return USBReadPortW (PciIo
, CmdAddrOffset
, Data
);
202 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
203 IN UINT32 StatusAddrOffset
,
210 Write UHCI Staus Register
214 PciIo - EFI_PCI_IO_PROTOCOL
215 StatusAddrOffset - Status address offset
216 UsbSts - Data to write
225 // Write to UHC's Status Register
227 return USBWritePortW (PciIo
, StatusAddrOffset
, UsbSts
);
232 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
233 IN UINT32 StatusAddrOffset
,
240 Read UHCI Staus Register
244 PciIo - EFI_PCI_IO_PROTOCOL
245 StatusAddrOffset - Status address offset
246 UsbSts - Data to return
255 // Read from UHC's Status Register
257 return USBReadPortW (PciIo
, StatusAddrOffset
, Data
);
263 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
264 IN UINT32 StatusAddrOffset
270 Clear the content of UHC's Status Register
274 PciIo - EFI_PCI_IO_PROTOCOL
275 StatusAddrOffset - Status address offset
284 return WriteUHCStatusReg (PciIo
, StatusAddrOffset
, 0x003F);
288 ReadUHCFrameNumberReg (
289 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
290 IN UINT32 FrameNumAddrOffset
,
297 Read from UHC's Frame Number Register
301 PciIo - EFI_PCI_IO_PROTOCOL
302 FrameNumAddrOffset - Frame number register offset
303 Data - Data to return
311 return USBReadPortW (PciIo
, FrameNumAddrOffset
, Data
);
315 WriteUHCFrameListBaseReg (
316 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
317 IN UINT32 FlBaseAddrOffset
,
318 IN UINT32 UsbFrameListBaseAddr
324 Write to UHC's Frame List Base Register
328 PciIo - EFI_PCI_IO_PROTOCOL
329 FlBaseAddrOffset - Frame Base address register
330 UsbFrameListBaseAddr - Address to write
339 return USBWritePortDW (PciIo
, FlBaseAddrOffset
, UsbFrameListBaseAddr
);
344 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
345 IN UINT32 PortAddrOffset
,
352 Read from UHC's Root Port Register
356 PciIo - EFI_PCI_IO_PROTOCOL
357 PortAddrOffset - Port Addrress Offset,
358 Data - Data to return
366 return USBReadPortW (PciIo
, PortAddrOffset
, Data
);
371 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
372 IN UINT32 PortAddrOffset
,
373 IN UINT16 ControlBits
379 Write to UHC's Root Port Register
383 PciIo - EFI_PCI_IO_PROTOCOL
384 PortAddrOffset - Port Addrress Offset,
385 ControlBits - Data to write
393 return USBWritePortW (PciIo
, PortAddrOffset
, ControlBits
);
400 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
401 IN UINT32 StatusRegAddr
,
408 Wait until UHCI halt or timeout
412 PciIo - EFI_PCI_IO_PROTOCOL
413 StatusRegAddr - Status Register Address
414 Timeout - Time out value in us
418 EFI_DEVICE_ERROR - Unable to read the status register
419 EFI_TIMEOUT - Time out
420 EFI_SUCCESS - Success
429 // Timeout is in us unit
431 Delay
= (Timeout
/ 50) + 1;
433 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
434 if (EFI_ERROR (Status
)) {
435 return EFI_DEVICE_ERROR
;
438 if ((HcStatus
& USBSTS_HCH
) == USBSTS_HCH
) {
457 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
458 IN UINT32 StatusRegAddr
464 Judge whether the host controller operates well
468 PciIo - EFI_PCI_IO_PROTOCOL
469 StatusRegAddr - Status register address
473 TRUE - Status is good
474 FALSE - Status is bad
481 // Detect whether the interrupt is caused by fatal error.
482 // see "UHCI Design Guid".
484 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
485 if (EFI_ERROR (Status
)) {
489 if (HcStatus
& (USBSTS_HCPE
| USBSTS_HSE
| USBSTS_HCH
)) {
499 IsHostSysOrProcessErr (
500 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
501 IN UINT32 StatusRegAddr
507 Judge the status is HostSys,ProcessErr error or good
511 PciIo - EFI_PCI_IO_PROTOCOL
512 StatusRegAddr - Status register address
516 TRUE - Status is good
517 FALSE - Status is bad
524 // Detect whether the interrupt is caused by serious error.
525 // see "UHCI Design Guid".
527 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
528 if (EFI_ERROR (Status
)) {
532 if (HcStatus
& (USBSTS_HSE
| USBSTS_HCPE
)) {
541 GetCurrentFrameNumber (
542 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
543 IN UINT32 FrameNumAddrOffset
549 Get Current Frame Number
553 PciIo - EFI_PCI_IO_PROTOCOL
554 FrameNumAddrOffset - FrameNum register AddrOffset
563 // Gets value in the USB frame number register.
567 ReadUHCFrameNumberReg (PciIo
, FrameNumAddrOffset
, &FrameNumber
);
569 return (UINT16
) (FrameNumber
& 0x03FF);
573 SetFrameListBaseAddress (
574 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
575 IN UINT32 FlBaseAddrReg
,
582 Set FrameListBase Address
586 PciIo - EFI_PCI_IO_PROTOCOL
587 FlBaseAddrReg - FrameListBase register
588 Addr - Address to set
597 // Sets value in the USB Frame List Base Address register.
599 return WriteUHCFrameListBaseReg (PciIo
, FlBaseAddrReg
, (UINT32
) (Addr
& 0xFFFFF000));
603 EnableMaxPacketSize (
610 Enable Max Packet Size
622 UINT16 CommandContent
;
630 if ((CommandContent
& USBCMD_MAXP
) != USBCMD_MAXP
) {
631 CommandContent
|= USBCMD_MAXP
;
644 IN USB_HC_DEV
*HcDev
,
645 IN UINT32 FlBaseAddrReg
656 FlBaseAddrReg - Frame List register
660 EFI_OUT_OF_RESOURCES - Can't allocate memory resources
661 EFI_UNSUPPORTED - Map memory fail
662 EFI_SUCCESS - Success
668 EFI_PHYSICAL_ADDRESS MappedAddress
;
670 UINTN BufferSizeInPages
;
671 UINTN BufferSizeInBytes
;
674 // The Frame List is a common buffer that will be
675 // accessed by both the cpu and the usb bus master
677 // The Frame List ocupies 4K bytes,
678 // and must be aligned on 4-Kbyte boundaries.
680 BufferSizeInBytes
= 4096;
681 BufferSizeInPages
= EFI_SIZE_TO_PAGES (BufferSizeInBytes
);
682 Status
= HcDev
->PciIo
->AllocateBuffer (
690 if (EFI_ERROR (Status
)) {
691 return EFI_OUT_OF_RESOURCES
;
694 Status
= HcDev
->PciIo
->Map (
696 EfiPciIoOperationBusMasterCommonBuffer
,
702 if (EFI_ERROR (Status
) || (BufferSizeInBytes
!= 4096)) {
703 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, BufferSizeInPages
, CommonBuffer
);
704 return EFI_UNSUPPORTED
;
707 HcDev
->FrameListEntry
= (FRAMELIST_ENTRY
*) ((UINTN
) MappedAddress
);
709 HcDev
->FrameListMapping
= Mapping
;
711 InitFrameList (HcDev
);
714 // Tell the Host Controller where the Frame List lies,
715 // by set the Frame List Base Address Register.
717 SetFrameListBaseAddress (
720 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
734 Free FrameList buffer
742 EFI_SUCCESS - success
747 // Unmap the common buffer for framelist entry,
748 // and free the common buffer.
749 // Uhci's frame list occupy 4k memory.
751 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, HcDev
->FrameListMapping
);
752 HcDev
->PciIo
->FreeBuffer (
754 EFI_SIZE_TO_PAGES (4096),
755 (VOID
*) (HcDev
->FrameListEntry
)
779 FRAMELIST_ENTRY
*FrameListPtr
;
783 // Validate each Frame List Entry
785 FrameListPtr
= HcDev
->FrameListEntry
;
786 for (Index
= 0; Index
< 1024; Index
++) {
787 FrameListPtr
->FrameListPtrTerminate
= 1;
788 FrameListPtr
->FrameListPtr
= 0;
789 FrameListPtr
->FrameListPtrQSelect
= 0;
790 FrameListPtr
->FrameListRsvd
= 0;
795 // //////////////////////////////////////////////////////////////
797 // QH TD related Helper Functions
799 ////////////////////////////////////////////////////////////////
806 IN USB_HC_DEV
*HcDev
,
807 OUT QH_STRUCT
**ppQHStruct
818 ppQHStruct - QH_STRUCT content to return
828 // QH must align on 16 bytes alignment,
829 // since the memory allocated by UhciAllocatePool ()
830 // is aligned on 32 bytes, it is no need to adjust
831 // the allocated memory returned.
833 return UhciAllocatePool (HcDev
, (UINT8
**) ppQHStruct
, sizeof (QH_STRUCT
));
839 IN USB_HC_DEV
*HcDev
,
840 OUT QH_STRUCT
**pptrQH
851 ppQHStruct - QH_STRUCT content to return
854 EFI_SUCCESS - Success
855 EFI_OUT_OF_RESOURCES - Can't allocate memory
861 // allocate align memory for QH_STRUCT
863 Status
= AllocateQHStruct (HcDev
, pptrQH
);
864 if (EFI_ERROR (Status
)) {
865 return EFI_OUT_OF_RESOURCES
;
868 // init each field of the QH_STRUCT
873 SetQHHorizontalValidorInvalid (*pptrQH
, FALSE
);
874 SetQHVerticalValidorInvalid (*pptrQH
, FALSE
);
880 SetQHHorizontalLinkPtr (
888 Set QH Horizontal Link Pointer
893 ptrNext - Data to write
902 // Since the QH_STRUCT is aligned on 16-byte boundaries,
903 // Only the highest 28bit of the address is valid
904 // (take 32bit address as an example).
906 PtrQH
->QH
.QHHorizontalPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
910 GetQHHorizontalLinkPtr (
917 Get QH Horizontal Link Pointer
931 // Restore the 28bit address to 32bit address
932 // (take 32bit address as an example)
934 return (VOID
*) ((UINTN
) (PtrQH
->QH
.QHHorizontalPtr
<< 4));
938 SetQHHorizontalQHorTDSelect (
946 Set QH Horizontal QH or TD
951 bQH - TRUE is QH FALSE is TD
959 // if QH is connected, the specified bit is set,
960 // if TD is connected, the specified bit is cleared.
962 PtrQH
->QH
.QHHorizontalQSelect
= bQH
? 1 : 0;
967 SetQHHorizontalValidorInvalid (
975 Set QH Horizontal Valid or Invalid
980 bValid - TRUE is Valid FALSE is Invalid
988 // Valid means the horizontal link pointer is valid,
989 // else, it's invalid.
991 PtrQH
->QH
.QHHorizontalTerminate
= bValid
? 0 : 1;
995 SetQHVerticalLinkPtr (
1001 Routine Description:
1003 Set QH Vertical Link Pointer
1008 ptrNext - Data to write
1016 // Since the QH_STRUCT is aligned on 16-byte boundaries,
1017 // Only the highest 28bit of the address is valid
1018 // (take 32bit address as an example).
1020 PtrQH
->QH
.QHVerticalPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
1024 GetQHVerticalLinkPtr (
1029 Routine Description:
1031 Get QH Vertical Link Pointer
1044 // Restore the 28bit address to 32bit address
1045 // (take 32bit address as an example)
1047 return (VOID
*) ((UINTN
) (PtrQH
->QH
.QHVerticalPtr
<< 4));
1051 SetQHVerticalQHorTDSelect (
1052 IN QH_STRUCT
*PtrQH
,
1057 Routine Description:
1059 Set QH Vertical QH or TD
1064 bQH - TRUE is QH FALSE is TD
1073 // Set the specified bit if the Vertical Link Pointer pointing to a QH,
1074 // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
1076 PtrQH
->QH
.QHVerticalQSelect
= bQH
? 1 : 0;
1080 IsQHHorizontalQHSelect (
1085 Routine Description:
1087 Is QH Horizontal QH Select
1101 // Retrieve the information about whether the Horizontal Link Pointer
1102 // pointing to a QH or TD.
1104 return (BOOLEAN
) (PtrQH
->QH
.QHHorizontalQSelect
? TRUE
: FALSE
);
1108 SetQHVerticalValidorInvalid (
1109 IN QH_STRUCT
*PtrQH
,
1114 Routine Description:
1116 Set QH Vertical Valid or Invalid
1121 IsValid - TRUE is valid FALSE is invalid
1130 // If TRUE, indicates the Vertical Link Pointer field is valid,
1131 // else, the field is invalid.
1133 PtrQH
->QH
.QHVerticalTerminate
= IsValid
? 0 : 1;
1138 GetQHVerticalValidorInvalid (
1143 Routine Description:
1145 Get QH Vertical Valid or Invalid
1159 // If TRUE, indicates the Vertical Link Pointer field is valid,
1160 // else, the field is invalid.
1162 return (BOOLEAN
) (!(PtrQH
->QH
.QHVerticalTerminate
));
1167 GetQHHorizontalValidorInvalid (
1172 Routine Description:
1174 Get QH Horizontal Valid or Invalid
1188 // If TRUE, meaning the Horizontal Link Pointer field is valid,
1189 // else, the field is invalid.
1191 return (BOOLEAN
) (!(PtrQH
->QH
.QHHorizontalTerminate
));
1198 IN USB_HC_DEV
*HcDev
,
1199 OUT TD_STRUCT
**ppTDStruct
1203 Routine Description:
1210 ppTDStruct - place to store TD_STRUCT pointer
1220 // TD must align on 16 bytes alignment,
1221 // since the memory allocated by UhciAllocatePool ()
1222 // is aligned on 32 bytes, it is no need to adjust
1223 // the allocated memory returned.
1225 return UhciAllocatePool (
1227 (UINT8
**) ppTDStruct
,
1234 IN USB_HC_DEV
*HcDev
,
1235 OUT TD_STRUCT
**pptrTD
1239 Routine Description:
1246 pptrTD - TD_STRUCT pointer to store
1250 EFI_OUT_OF_RESOURCES - Can't allocate resources
1251 EFI_SUCCESS - Success
1257 // create memory for TD_STRUCT, and align the memory.
1259 Status
= AllocateTDStruct (HcDev
, pptrTD
);
1260 if (EFI_ERROR (Status
)) {
1261 return EFI_OUT_OF_RESOURCES
;
1267 SetTDLinkPtrValidorInvalid (*pptrTD
, FALSE
);
1275 IN USB_HC_DEV
*HcDev
,
1280 IN UINT8 RequestLen
,
1281 OUT TD_STRUCT
**ppTD
1285 Routine Description:
1287 Generate Setup Stage TD
1292 DevAddr - Device address
1293 Endpoint - Endpoint number
1294 bSlow - Full speed or low speed
1295 pDevReq - Device request
1296 RequestLen - Request length
1297 ppTD - TD_STRUCT to return
1300 EFI_OUT_OF_RESOURCES - Can't allocate memory
1301 EFI_SUCCESS - Success
1306 TD_STRUCT
*pTDStruct
;
1308 Status
= CreateTD (HcDev
, &pTDStruct
);
1309 if (EFI_ERROR (Status
)) {
1310 return EFI_OUT_OF_RESOURCES
;
1313 SetTDLinkPtr (pTDStruct
, NULL
);
1316 // Depth first fashion
1318 SetTDLinkPtrDepthorBreadth (pTDStruct
, TRUE
);
1321 // initialize as the last TD in the QH context,
1322 // this field will be updated in the TD linkage process.
1324 SetTDLinkPtrValidorInvalid (pTDStruct
, FALSE
);
1327 // Disable Short Packet Detection by default
1329 EnableorDisableTDShortPacket (pTDStruct
, FALSE
);
1332 // Max error counter is 3, retry 3 times when error encountered.
1334 SetTDControlErrorCounter (pTDStruct
, 3);
1337 // set device speed attribute
1338 // (TRUE - Slow Device; FALSE - Full Speed Device)
1340 SetTDLoworFullSpeedDevice (pTDStruct
, bSlow
);
1343 // Non isochronous transfer TD
1345 SetTDControlIsochronousorNot (pTDStruct
, FALSE
);
1348 // Interrupt On Complete bit be set to zero,
1349 // Disable IOC interrupt.
1351 SetorClearTDControlIOC (pTDStruct
, FALSE
);
1354 // Set TD Active bit
1356 SetTDStatusActiveorInactive (pTDStruct
, TRUE
);
1358 SetTDTokenMaxLength (pTDStruct
, RequestLen
);
1360 SetTDTokenDataToggle0 (pTDStruct
);
1362 SetTDTokenEndPoint (pTDStruct
, Endpoint
);
1364 SetTDTokenDeviceAddress (pTDStruct
, DevAddr
);
1366 SetTDTokenPacketID (pTDStruct
, SETUP_PACKET_ID
);
1368 pTDStruct
->pTDBuffer
= (UINT8
*) pDevReq
;
1369 pTDStruct
->TDBufferLength
= RequestLen
;
1370 SetTDDataBuffer (pTDStruct
);
1379 IN USB_HC_DEV
*HcDev
,
1387 OUT TD_STRUCT
**ppTD
1391 Routine Description:
1393 Generate Data Stage TD
1398 DevAddr - Device address
1399 Endpoint - Endpoint number
1403 Toggle - Data toggle value
1404 bSlow - Full speed or low speed
1405 ppTD - TD_STRUCT to return
1408 EFI_OUT_OF_RESOURCES - Can't allocate memory
1409 EFI_SUCCESS - Success
1413 TD_STRUCT
*pTDStruct
;
1416 Status
= CreateTD (HcDev
, &pTDStruct
);
1417 if (EFI_ERROR (Status
)) {
1418 return EFI_OUT_OF_RESOURCES
;
1421 SetTDLinkPtr (pTDStruct
, NULL
);
1424 // Depth first fashion
1426 SetTDLinkPtrDepthorBreadth (pTDStruct
, TRUE
);
1429 // Link pointer pointing to TD struct
1431 SetTDLinkPtrQHorTDSelect (pTDStruct
, FALSE
);
1434 // initialize as the last TD in the QH context,
1435 // this field will be updated in the TD linkage process.
1437 SetTDLinkPtrValidorInvalid (pTDStruct
, FALSE
);
1440 // Disable short packet detect
1442 EnableorDisableTDShortPacket (pTDStruct
, FALSE
);
1444 // Max error counter is 3
1446 SetTDControlErrorCounter (pTDStruct
, 3);
1449 // set device speed attribute
1450 // (TRUE - Slow Device; FALSE - Full Speed Device)
1452 SetTDLoworFullSpeedDevice (pTDStruct
, bSlow
);
1455 // Non isochronous transfer TD
1457 SetTDControlIsochronousorNot (pTDStruct
, FALSE
);
1460 // Disable Interrupt On Complete
1461 // Disable IOC interrupt.
1463 SetorClearTDControlIOC (pTDStruct
, FALSE
);
1468 SetTDStatusActiveorInactive (pTDStruct
, TRUE
);
1470 SetTDTokenMaxLength (pTDStruct
, Len
);
1473 SetTDTokenDataToggle1 (pTDStruct
);
1475 SetTDTokenDataToggle0 (pTDStruct
);
1478 SetTDTokenEndPoint (pTDStruct
, Endpoint
);
1480 SetTDTokenDeviceAddress (pTDStruct
, DevAddr
);
1482 SetTDTokenPacketID (pTDStruct
, PktID
);
1484 pTDStruct
->pTDBuffer
= (UINT8
*) pData
;
1485 pTDStruct
->TDBufferLength
= Len
;
1486 SetTDDataBuffer (pTDStruct
);
1495 IN USB_HC_DEV
*HcDev
,
1500 OUT TD_STRUCT
**ppTD
1504 Routine Description:
1506 Generate Status Stage TD
1511 DevAddr - Device address
1512 Endpoint - Endpoint number
1514 bSlow - Full speed or low speed
1515 ppTD - TD_STRUCT to return
1518 EFI_OUT_OF_RESOURCES - Can't allocate memory
1519 EFI_SUCCESS - Success
1523 TD_STRUCT
*ptrTDStruct
;
1526 Status
= CreateTD (HcDev
, &ptrTDStruct
);
1527 if (EFI_ERROR (Status
)) {
1528 return EFI_OUT_OF_RESOURCES
;
1531 SetTDLinkPtr (ptrTDStruct
, NULL
);
1534 // Depth first fashion
1536 SetTDLinkPtrDepthorBreadth (ptrTDStruct
, TRUE
);
1539 // initialize as the last TD in the QH context,
1540 // this field will be updated in the TD linkage process.
1542 SetTDLinkPtrValidorInvalid (ptrTDStruct
, FALSE
);
1545 // Disable short packet detect
1547 EnableorDisableTDShortPacket (ptrTDStruct
, FALSE
);
1550 // Max error counter is 3
1552 SetTDControlErrorCounter (ptrTDStruct
, 3);
1555 // set device speed attribute
1556 // (TRUE - Slow Device; FALSE - Full Speed Device)
1558 SetTDLoworFullSpeedDevice (ptrTDStruct
, bSlow
);
1561 // Non isochronous transfer TD
1563 SetTDControlIsochronousorNot (ptrTDStruct
, FALSE
);
1566 // Disable Interrupt On Complete
1567 // Disable IOC interrupt.
1569 SetorClearTDControlIOC (ptrTDStruct
, FALSE
);
1572 // Set TD Active bit
1574 SetTDStatusActiveorInactive (ptrTDStruct
, TRUE
);
1576 SetTDTokenMaxLength (ptrTDStruct
, 0);
1578 SetTDTokenDataToggle1 (ptrTDStruct
);
1580 SetTDTokenEndPoint (ptrTDStruct
, Endpoint
);
1582 SetTDTokenDeviceAddress (ptrTDStruct
, DevAddr
);
1584 SetTDTokenPacketID (ptrTDStruct
, PktID
);
1586 ptrTDStruct
->pTDBuffer
= NULL
;
1587 ptrTDStruct
->TDBufferLength
= 0;
1588 SetTDDataBuffer (ptrTDStruct
);
1590 *ppTD
= ptrTDStruct
;
1597 SetTDLinkPtrValidorInvalid (
1598 IN TD_STRUCT
*ptrTDStruct
,
1603 Routine Description:
1605 Set TD Link Pointer Valid or Invalid
1609 ptrTDStruct - TD_STRUCT
1610 bValid - TRUE is valid FALSE is invalid
1619 // Valid means the link pointer is valid,
1620 // else, it's invalid.
1622 ptrTDStruct
->TDData
.TDLinkPtrTerminate
= (bValid
? 0 : 1);
1626 SetTDLinkPtrQHorTDSelect (
1627 IN TD_STRUCT
*ptrTDStruct
,
1632 Routine Description:
1634 Set TD Link Pointer QH or TD Select
1638 ptrTDStruct - TD_STRUCT
1639 bQH - TRUE is QH FALSE is TD
1648 // Indicate whether the Link Pointer pointing to a QH or TD
1650 ptrTDStruct
->TDData
.TDLinkPtrQSelect
= (bQH
? 1 : 0);
1654 SetTDLinkPtrDepthorBreadth (
1655 IN TD_STRUCT
*ptrTDStruct
,
1660 Routine Description:
1662 Set TD Link Pointer depth or bread priority
1666 ptrTDStruct - TD_STRUCT
1667 bDepth - TRUE is Depth FALSE is Breadth
1676 // If TRUE, indicating the host controller should process in depth first
1678 // else, the host controller should process in breadth first fashion
1680 ptrTDStruct
->TDData
.TDLinkPtrDepthSelect
= (bDepth
? 1 : 0);
1685 IN TD_STRUCT
*ptrTDStruct
,
1690 Routine Description:
1696 ptrTDStruct - TD_STRUCT
1697 ptrNext - Pointer to set
1706 // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,
1707 // only the highest 28 bits are valid. (if take 32bit address as an example)
1709 ptrTDStruct
->TDData
.TDLinkPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
1714 IN TD_STRUCT
*ptrTDStruct
1718 Routine Description:
1724 ptrTDStruct - TD_STRUCT
1733 // Get TD Link Pointer. Restore it back to 32bit
1734 // (if take 32bit address as an example)
1736 return (VOID
*) ((UINTN
) (ptrTDStruct
->TDData
.TDLinkPtr
<< 4));
1742 IN TD_STRUCT
*ptrTDStruct
1746 Routine Description:
1748 Is TD Link Pointer is QH Or TD
1752 ptrTDStruct - TODO: add argument description
1762 // Get the information about whether the Link Pointer field pointing to
1765 return (BOOLEAN
) (ptrTDStruct
->TDData
.TDLinkPtrQSelect
);
1769 EnableorDisableTDShortPacket (
1770 IN TD_STRUCT
*ptrTDStruct
,
1775 Routine Description:
1777 Enable or Disable TD ShortPacket
1781 ptrTDStruct - TD_STRUCT
1782 bEnable - TRUE is Enanble FALSE is Disable
1791 // TRUE means enable short packet detection mechanism.
1793 ptrTDStruct
->TDData
.TDStatusSPD
= (bEnable
? 1 : 0);
1797 SetTDControlErrorCounter (
1798 IN TD_STRUCT
*ptrTDStruct
,
1803 Routine Description:
1805 Set TD Control ErrorCounter
1809 ptrTDStruct - TD_STRUCT
1810 nMaxErrors - Error counter number
1819 // valid value of nMaxErrors is 0,1,2,3
1821 if (nMaxErrors
> 3) {
1825 ptrTDStruct
->TDData
.TDStatusErr
= nMaxErrors
;
1830 SetTDLoworFullSpeedDevice (
1831 IN TD_STRUCT
*ptrTDStruct
,
1832 IN BOOLEAN bLowSpeedDevice
1836 // TRUE means the TD is targeting at a Low-speed device
1838 ptrTDStruct
->TDData
.TDStatusLS
= (bLowSpeedDevice
? 1 : 0);
1842 SetTDControlIsochronousorNot (
1843 IN TD_STRUCT
*ptrTDStruct
,
1844 IN BOOLEAN IsIsochronous
1848 // TRUE means the TD belongs to Isochronous transfer type.
1850 ptrTDStruct
->TDData
.TDStatusIOS
= (IsIsochronous
? 1 : 0);
1854 SetorClearTDControlIOC (
1855 IN TD_STRUCT
*ptrTDStruct
,
1860 // If this bit is set, it indicates that the host controller should issue
1861 // an interrupt on completion of the frame in which this TD is executed.
1863 ptrTDStruct
->TDData
.TDStatusIOC
= IsSet
? 1 : 0;
1867 SetTDStatusActiveorInactive (
1868 IN TD_STRUCT
*ptrTDStruct
,
1873 // If this bit is set, it indicates that the TD is active and can be
1877 ptrTDStruct
->TDData
.TDStatus
|= 0x80;
1879 ptrTDStruct
->TDData
.TDStatus
&= 0x7F;
1884 SetTDTokenMaxLength (
1885 IN TD_STRUCT
*ptrTDStruct
,
1886 IN UINT16 MaximumLength
1890 // Specifies the maximum number of data bytes allowed for the transfer.
1891 // the legal value extent is 0 ~ 0x500.
1893 if (MaximumLength
> 0x500) {
1894 MaximumLength
= 0x500;
1896 ptrTDStruct
->TDData
.TDTokenMaxLen
= MaximumLength
- 1;
1898 return MaximumLength
;
1902 SetTDTokenDataToggle1 (
1903 IN TD_STRUCT
*ptrTDStruct
1907 // Set the data toggle bit to DATA1
1909 ptrTDStruct
->TDData
.TDTokenDataToggle
= 1;
1913 SetTDTokenDataToggle0 (
1914 IN TD_STRUCT
*ptrTDStruct
1918 // Set the data toggle bit to DATA0
1920 ptrTDStruct
->TDData
.TDTokenDataToggle
= 0;
1924 GetTDTokenDataToggle (
1925 IN TD_STRUCT
*ptrTDStruct
1929 // Get the data toggle value.
1931 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenDataToggle
);
1935 SetTDTokenEndPoint (
1936 IN TD_STRUCT
*ptrTDStruct
,
1941 // Set EndPoint Number the TD is targeting at.
1943 ptrTDStruct
->TDData
.TDTokenEndPt
= (UINT8
) EndPoint
;
1947 SetTDTokenDeviceAddress (
1948 IN TD_STRUCT
*ptrTDStruct
,
1949 IN UINTN DeviceAddress
1953 // Set Device Address the TD is targeting at.
1955 ptrTDStruct
->TDData
.TDTokenDevAddr
= (UINT8
) DeviceAddress
;
1959 SetTDTokenPacketID (
1960 IN TD_STRUCT
*ptrTDStruct
,
1965 // Set the Packet Identification to be used for this transaction.
1967 ptrTDStruct
->TDData
.TDTokenPID
= PID
;
1972 IN TD_STRUCT
*ptrTDStruct
1976 // Set the beginning address of the data buffer that will be used
1977 // during the transaction.
1979 ptrTDStruct
->TDData
.TDBufferPtr
= (UINT32
) ((UINTN
) (ptrTDStruct
->pTDBuffer
));
1984 IN TD_STRUCT
*ptrTDStruct
1990 // Detect whether the TD is active.
1992 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
1993 return (BOOLEAN
) (TDStatus
& 0x80);
1998 IN TD_STRUCT
*ptrTDStruct
2004 // Detect whether the device/endpoint addressed by this TD is stalled.
2006 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2007 return (BOOLEAN
) (TDStatus
& 0x40);
2011 IsTDStatusBufferError (
2012 IN TD_STRUCT
*ptrTDStruct
2017 // Detect whether Data Buffer Error is happened.
2019 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2020 return (BOOLEAN
) (TDStatus
& 0x20);
2024 IsTDStatusBabbleError (
2025 IN TD_STRUCT
*ptrTDStruct
2031 // Detect whether Babble Error is happened.
2033 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2034 return (BOOLEAN
) (TDStatus
& 0x10);
2038 IsTDStatusNAKReceived (
2039 IN TD_STRUCT
*ptrTDStruct
2045 // Detect whether NAK is received.
2047 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2048 return (BOOLEAN
) (TDStatus
& 0x08);
2052 IsTDStatusCRCTimeOutError (
2053 IN TD_STRUCT
*ptrTDStruct
2059 // Detect whether CRC/Time Out Error is encountered.
2061 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2062 return (BOOLEAN
) (TDStatus
& 0x04);
2066 IsTDStatusBitStuffError (
2067 IN TD_STRUCT
*ptrTDStruct
2073 // Detect whether Bitstuff Error is received.
2075 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2076 return (BOOLEAN
) (TDStatus
& 0x02);
2080 GetTDStatusActualLength (
2081 IN TD_STRUCT
*ptrTDStruct
2085 // Retrieve the actual number of bytes that were tansferred.
2086 // the value is encoded as n-1. so return the decoded value.
2088 return (UINT16
) ((ptrTDStruct
->TDData
.TDStatusActualLength
) + 1);
2092 GetTDTokenMaxLength (
2093 IN TD_STRUCT
*ptrTDStruct
2097 // Retrieve the maximum number of data bytes allowed for the trnasfer.
2099 return (UINT16
) ((ptrTDStruct
->TDData
.TDTokenMaxLen
) + 1);
2103 GetTDTokenEndPoint (
2104 IN TD_STRUCT
*ptrTDStruct
2108 // Retrieve the endpoint number the transaction is targeting at.
2110 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenEndPt
);
2114 GetTDTokenDeviceAddress (
2115 IN TD_STRUCT
*ptrTDStruct
2119 // Retrieve the device address the transaction is targeting at.
2121 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenDevAddr
);
2125 GetTDTokenPacketID (
2126 IN TD_STRUCT
*ptrTDStruct
2130 // Retrieve the Packet Identification information.
2132 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenPID
);
2137 IN TD_STRUCT
*ptrTDStruct
2141 // Retrieve the beginning address of the data buffer
2142 // that involved in this transaction.
2144 return ptrTDStruct
->pTDBuffer
;
2148 GetTDLinkPtrValidorInvalid (
2149 IN TD_STRUCT
*ptrTDStruct
2153 // Retrieve the information of whether the Link Pointer field
2156 if (ptrTDStruct
->TDData
.TDLinkPtrTerminate
) {
2166 IN TD_STRUCT
*PtrFirstTD
2172 // Count the queued TDs number.
2177 ptr
= (TD_STRUCT
*) ptr
->ptrNextTD
;
2188 IN QH_STRUCT
*PtrQH
,
2193 Routine Description:
2207 if (PtrQH
== NULL
|| PtrTD
== NULL
) {
2211 // Validate QH Vertical Ptr field
2213 SetQHVerticalValidorInvalid (PtrQH
, TRUE
);
2216 // Vertical Ptr pointing to TD structure
2218 SetQHVerticalQHorTDSelect (PtrQH
, FALSE
);
2220 SetQHVerticalLinkPtr (PtrQH
, (VOID
*) PtrTD
);
2222 PtrQH
->ptrDown
= (VOID
*) PtrTD
;
2227 IN TD_STRUCT
*ptrPreTD
,
2232 Routine Description:
2238 ptrPreTD - Previous TD_STRUCT to be linked
2239 PtrTD - TD_STRUCT to link
2246 if (ptrPreTD
== NULL
|| PtrTD
== NULL
) {
2250 // Depth first fashion
2252 SetTDLinkPtrDepthorBreadth (ptrPreTD
, TRUE
);
2255 // Link pointer pointing to TD struct
2257 SetTDLinkPtrQHorTDSelect (ptrPreTD
, FALSE
);
2260 // Validate the link pointer valid bit
2262 SetTDLinkPtrValidorInvalid (ptrPreTD
, TRUE
);
2264 SetTDLinkPtr (ptrPreTD
, PtrTD
);
2266 ptrPreTD
->ptrNextTD
= (VOID
*) PtrTD
;
2269 // Transfer Schedule related Helper Functions
2272 SetorClearCurFrameListTerminate (
2273 IN FRAMELIST_ENTRY
*pCurEntry
,
2278 // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.
2280 pCurEntry
->FrameListPtrTerminate
= (IsSet
? 1 : 0);
2284 SetCurFrameListQHorTD (
2285 IN FRAMELIST_ENTRY
*pCurEntry
,
2290 // This bit indicates to the hardware whether the item referenced by the
2291 // link pointer is a TD or a QH.
2293 pCurEntry
->FrameListPtrQSelect
= (IsQH
? 1 : 0);
2298 IsCurFrameListQHorTD (
2299 IN FRAMELIST_ENTRY
*pCurEntry
2306 return (BOOLEAN
) (pCurEntry
->FrameListPtrQSelect
);
2310 GetCurFrameListTerminate (
2311 IN FRAMELIST_ENTRY
*pCurEntry
2315 // TRUE means the frame is empty,
2316 // FALSE means the link pointer field is valid.
2318 return (BOOLEAN
) (pCurEntry
->FrameListPtrTerminate
);
2322 SetCurFrameListPointer (
2323 IN FRAMELIST_ENTRY
*pCurEntry
,
2328 // Set the pointer field of the frame.
2330 pCurEntry
->FrameListPtr
= (UINT32
) ((UINTN
) ptr
>> 4);
2334 GetCurFrameListPointer (
2335 IN FRAMELIST_ENTRY
*pCurEntry
2339 // Get the link pointer of the frame.
2341 return (VOID
*) ((UINTN
) (pCurEntry
->FrameListPtr
<< 4));
2347 IN FRAMELIST_ENTRY
*pEntry
,
2348 IN UINT16 FrameListIndex
,
2353 Routine Description:
2355 Link QH To Frame List
2359 pEntry - FRAMELIST_ENTRY
2360 FrameListIndex - Frame List Index
2368 FRAMELIST_ENTRY
*pCurFrame
;
2370 QH_STRUCT
*NextTempQH
;
2375 // Get frame list entry that the link process will begin from.
2377 pCurFrame
= pEntry
+ FrameListIndex
;
2380 // if current frame is empty
2381 // then link the specified QH directly to the Frame List.
2383 if (GetCurFrameListTerminate (pCurFrame
)) {
2386 // Link new QH to the frame list entry.
2388 SetCurFrameListQHorTD (pCurFrame
, TRUE
);
2390 SetCurFrameListPointer (pCurFrame
, (UINT8
*) PtrQH
);
2393 // clear T bit in the Frame List, indicating that the frame list entry
2394 // is no longer empty.
2396 SetorClearCurFrameListTerminate (pCurFrame
, FALSE
);
2402 // current frame list has link pointer
2404 if (!IsCurFrameListQHorTD (pCurFrame
)) {
2406 // a TD is linked to the framelist entry
2408 TempTD
= (TD_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2410 while (GetTDLinkPtrValidorInvalid (TempTD
)) {
2412 if (IsTDLinkPtrQHOrTD (TempTD
)) {
2414 // QH linked next to the TD
2419 TempTD
= (TD_STRUCT
*) GetTDLinkPtr (TempTD
);
2423 // either no ptr linked next to the TD or QH is linked next to the TD
2425 if (!GetTDLinkPtrValidorInvalid (TempTD
)) {
2428 // no ptr linked next to the TD
2430 TempTD
->ptrNextQH
= PtrQH
;
2431 SetTDLinkPtrQHorTDSelect (TempTD
, TRUE
);
2432 SetTDLinkPtr (TempTD
, PtrQH
);
2433 SetTDLinkPtrValidorInvalid (TempTD
, TRUE
);
2438 // QH is linked next to the TD
2440 TempQH
= (QH_STRUCT
*) GetTDLinkPtr (TempTD
);
2444 // a QH is linked to the framelist entry
2446 TempQH
= (QH_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2455 // Avoid the same qh repeated linking in one frame entry
2457 if (TempQH
== PtrQH
) {
2462 // if current QH has next QH connected
2464 while (GetQHHorizontalValidorInvalid (TempQH
)) {
2466 // Get next QH pointer
2468 NextTempQH
= (QH_STRUCT
*) GetQHHorizontalLinkPtr (TempQH
);
2471 // Bulk transfer qh may be self-linked,
2472 // so, the code below is to aVOID dead-loop when meeting self-linked qh
2474 if (NextTempQH
== TempQH
) {
2479 TempQH
= NextTempQH
;
2482 // Avoid the same qh repeated linking in one frame entry
2484 if (TempQH
== PtrQH
) {
2490 TempQH
->ptrNext
= PtrQH
;
2491 SetQHHorizontalQHorTDSelect (TempQH
, TRUE
);
2492 SetQHHorizontalLinkPtr (TempQH
, PtrQH
);
2493 SetQHHorizontalValidorInvalid (TempQH
, TRUE
);
2501 ExecuteControlTransfer (
2502 IN USB_HC_DEV
*HcDev
,
2503 IN TD_STRUCT
*PtrTD
,
2505 OUT UINTN
*ActualLen
,
2507 OUT UINT32
*TransferResult
2511 Routine Description:
2513 Execute Control Transfer
2520 ActualLen - Actual transfered Len
2521 TimeOut - TimeOut value in milliseconds
2522 TransferResult - Transfer result
2525 EFI_SUCCESS - Sucess
2526 EFI_DEVICE_ERROR - Error
2534 BOOLEAN TransferFinished
;
2537 *TransferResult
= EFI_USB_NOERROR
;
2538 RequiredLen
= *ActualLen
;
2541 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2544 TransferFinished
= CheckTDsResults (
2552 if (TransferFinished
) {
2557 // TD is inactive, which means the control transfer is end.
2559 if ((*TransferResult
& EFI_USB_ERR_NOTEXECUTE
) != EFI_USB_ERR_NOTEXECUTE
) {
2567 if (*TransferResult
!= EFI_USB_NOERROR
) {
2568 return EFI_DEVICE_ERROR
;
2575 ExecBulkorSyncInterruptTransfer (
2576 IN USB_HC_DEV
*HcDev
,
2577 IN TD_STRUCT
*PtrTD
,
2579 OUT UINTN
*ActualLen
,
2580 OUT UINT8
*DataToggle
,
2582 OUT UINT32
*TransferResult
2586 Routine Description:
2588 Execute Bulk or SyncInterrupt Transfer
2595 ActualLen - Actual transfered Len
2596 DataToggle - Data Toggle
2597 TimeOut - TimeOut value in milliseconds
2598 TransferResult - Transfer result
2601 EFI_SUCCESS - Sucess
2602 EFI_DEVICE_ERROR - Error
2609 BOOLEAN TransferFinished
;
2612 *TransferResult
= EFI_USB_NOERROR
;
2613 RequiredLen
= *ActualLen
;
2616 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2620 TransferFinished
= CheckTDsResults (
2628 if (TransferFinished
) {
2633 // TD is inactive, which means bulk or interrupt transfer's end.
2635 if ((*TransferResult
& EFI_USB_ERR_NOTEXECUTE
) != EFI_USB_ERR_NOTEXECUTE
) {
2646 if (*TransferResult
!= EFI_USB_NOERROR
) {
2649 // scroll the Data Toggle back to the last success TD
2651 ScrollNum
= CountTDsNumber (PtrTD
) - ErrTDPos
;
2652 if (ScrollNum
& 0x1) {
2656 return EFI_DEVICE_ERROR
;
2664 IN USB_HC_DEV
*HcDev
,
2665 IN QH_STRUCT
*PtrQH
,
2666 IN UINT16 FrameListIndex
,
2667 IN BOOLEAN SearchOther
,
2672 Routine Description:
2674 Unlink from frame list and delete single QH
2679 FrameListIndex - Frame List Index
2680 SearchOther - Search Other QH
2681 Delete - TRUE is to delete the QH
2686 FRAMELIST_ENTRY
*pCurFrame
;
2690 QH_STRUCT
*CurrentQH
;
2692 TD_STRUCT
*CurrentTD
;
2700 if (PtrQH
== NULL
) {
2708 BeginFrame
= FrameListIndex
;
2709 EndFrame
= FrameListIndex
+ 1;
2712 for (Index
= BeginFrame
; Index
< EndFrame
; Index
++) {
2714 pCurFrame
= HcDev
->FrameListEntry
+ (Index
& 0x3FF);
2716 if (GetCurFrameListTerminate (pCurFrame
)) {
2718 // current frame list is empty,search next frame list entry
2723 if (!IsCurFrameListQHorTD (pCurFrame
)) {
2725 // TD linked to current framelist
2727 CurrentTD
= (TD_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2729 while (GetTDLinkPtrValidorInvalid (CurrentTD
)) {
2731 if (IsTDLinkPtrQHOrTD (CurrentTD
)) {
2733 // QH linked next to the TD,break while ()
2738 CurrentTD
= (TD_STRUCT
*) GetTDLinkPtr (CurrentTD
);
2741 if (!GetTDLinkPtrValidorInvalid (CurrentTD
)) {
2743 // no QH linked next to the last TD,
2744 // search next frame list
2750 // a QH linked next to the last TD
2752 CurrentQH
= (QH_STRUCT
*) GetTDLinkPtr (CurrentTD
);
2754 PtrPreQH
= CurrentTD
;
2758 // a QH linked to current framelist
2760 CurrentQH
= (QH_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2765 if (CurrentQH
== PtrQH
) {
2767 if (GetQHHorizontalValidorInvalid (PtrQH
)) {
2769 // there is QH connected after the QH found
2772 // retrieve nex qh pointer of the qh found.
2774 NextQH
= GetQHHorizontalLinkPtr (PtrQH
);
2781 // QH linked to a TD struct
2783 CurrentTD
= (TD_STRUCT
*) PtrPreQH
;
2785 SetTDLinkPtrValidorInvalid (CurrentTD
, (BOOLEAN
) ((NextQH
== NULL
) ? FALSE
: TRUE
));
2786 SetTDLinkPtr (CurrentTD
, NextQH
);
2787 CurrentTD
->ptrNextQH
= NextQH
;
2791 // QH linked directly to current framelist entry
2793 SetorClearCurFrameListTerminate (pCurFrame
, (BOOLEAN
) ((NextQH
== NULL
) ? TRUE
: FALSE
));
2794 SetCurFrameListPointer (pCurFrame
, (UINT8
*) NextQH
);
2799 // search next framelist entry
2804 while (GetQHHorizontalValidorInvalid (CurrentQH
)) {
2806 PtrPreQH
= CurrentQH
;
2808 // Get next horizontal linked QH
2810 CurrentQH
= (QH_STRUCT
*) GetQHHorizontalLinkPtr (CurrentQH
);
2814 if (CurrentQH
== PtrQH
) {
2820 // search next frame list entry
2822 if (CurrentQH
!= PtrQH
) {
2829 // find the specified qh, then delink it from
2830 // the horizontal QH list in the frame entry.
2833 if (GetQHHorizontalValidorInvalid (PtrQH
)) {
2835 // there is QH connected after the QH found
2838 // retrieve nex qh pointer of the qh found.
2840 NextQH
= GetQHHorizontalLinkPtr (PtrQH
);
2844 // NO QH connected after the QH found
2848 // NULL the previous QH's link ptr and set Terminate field.
2850 SetQHHorizontalValidorInvalid ((QH_STRUCT
*) PtrPreQH
, FALSE
);
2853 SetQHHorizontalLinkPtr ((QH_STRUCT
*) PtrPreQH
, NextQH
);
2854 ((QH_STRUCT
*) PtrPreQH
)->ptrNext
= NextQH
;
2859 if (Found
&& Delete
) {
2861 // free memory once used by the specific QH
2863 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2872 IN USB_HC_DEV
*HcDev
,
2873 IN TD_STRUCT
*PtrFirstTD
2876 Routine Description:
2882 PtrFirstTD - TD link list head
2894 // Delete all the TDs in a queue.
2900 if (!GetTDLinkPtrValidorInvalid (Tptr2
)) {
2904 Tptr1
= GetTDLinkPtr (Tptr2
);
2907 // TD link to itself
2909 if (Tptr1
== Tptr2
) {
2914 UhciFreePool (HcDev
, (UINT8
*) Tptr2
, sizeof (TD_STRUCT
));
2921 InsertQHTDToINTList (
2922 IN USB_HC_DEV
*HcDev
,
2923 IN QH_STRUCT
*PtrQH
,
2924 IN TD_STRUCT
*PtrFirstTD
,
2925 IN UINT8 DeviceAddress
,
2926 IN UINT8 EndPointAddress
,
2927 IN UINT8 DataToggle
,
2928 IN UINTN DataLength
,
2929 IN UINTN PollingInterval
,
2931 IN UINT8
*DataBuffer
,
2932 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
2936 Routine Description:
2937 Insert QH and TD To Interrupt List
2942 PtrFirstTD - First TD_STRUCT
2943 DeviceAddress - Device Address
2944 EndPointAddress - EndPoint Address
2945 DataToggle - Data Toggle
2946 DataLength - Data length
2947 PollingInterval - Polling Interval when inserted to frame list
2948 Mapping - Mapping alue
2949 DataBuffer - Data buffer
2950 CallBackFunction- CallBackFunction after interrupt transfeer
2951 Context - CallBackFunction Context passed as function parameter
2953 EFI_SUCCESS - Sucess
2954 EFI_INVALID_PARAMETER - Paremeter is error
2958 INTERRUPT_LIST
*Node
;
2960 Node
= AllocatePool (sizeof (INTERRUPT_LIST
));
2968 Node
->Signature
= INTERRUPT_LIST_SIGNATURE
;
2969 Node
->DevAddr
= DeviceAddress
;
2970 Node
->EndPoint
= EndPointAddress
;
2971 Node
->PtrQH
= PtrQH
;
2972 Node
->PtrFirstTD
= PtrFirstTD
;
2973 Node
->DataToggle
= DataToggle
;
2974 Node
->DataLen
= DataLength
;
2975 Node
->PollInterval
= PollingInterval
;
2976 Node
->Mapping
= Mapping
;
2978 // DataBuffer is allocated host memory, not mapped memory
2980 Node
->DataBuffer
= DataBuffer
;
2981 Node
->InterruptCallBack
= CallBackFunction
;
2982 Node
->InterruptContext
= Context
;
2985 // insert the new interrupt transfer to the head of the list.
2986 // The interrupt transfer's monitor function scans the whole list from head
2987 // to tail. The new interrupt transfer MUST be added to the head of the list
2988 // for the sake of error recovery.
2990 InsertHeadList (&(HcDev
->InterruptListHead
), &(Node
->Link
));
2997 DeleteAsyncINTQHTDs (
2998 IN USB_HC_DEV
*HcDev
,
2999 IN UINT8 DeviceAddress
,
3000 IN UINT8 EndPointAddress
,
3001 OUT UINT8
*DataToggle
3004 Routine Description:
3006 Delete Async INT QH and TDs
3010 DeviceAddress - Device Address
3011 EndPointAddress - EndPoint Address
3012 DataToggle - Data Toggle
3015 EFI_SUCCESS - Sucess
3016 EFI_INVALID_PARAMETER - Paremeter is error
3021 QH_STRUCT
*ptrNextQH
;
3024 INTERRUPT_LIST
*MatchList
;
3025 INTERRUPT_LIST
*PtrList
;
3037 // no interrupt transaction exists
3039 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
3040 return EFI_INVALID_PARAMETER
;
3043 // find the correct QH-TD that need to delete
3044 // (by matching Device address and EndPoint number to match QH-TD )
3047 Link
= &(HcDev
->InterruptListHead
);
3050 Link
= Link
->ForwardLink
;
3051 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
3053 if ((PtrList
->DevAddr
== DeviceAddress
) && ((PtrList
->EndPoint
& 0x0f) == (EndPointAddress
& 0x0f))) {
3054 MatchList
= PtrList
;
3060 } while (Link
->ForwardLink
!= &(HcDev
->InterruptListHead
));
3063 return EFI_INVALID_PARAMETER
;
3066 // get current endpoint's data toggle bit and save.
3068 ExecuteAsyncINTTDs (HcDev
, MatchList
, &Result
, &ErrTDPos
, &ActualLen
);
3069 UpdateAsyncINTQHTDs (MatchList
, Result
, (UINT32
) ErrTDPos
);
3070 *DataToggle
= MatchList
->DataToggle
;
3072 MatchTD
= MatchList
->PtrFirstTD
;
3073 MatchQH
= MatchList
->PtrQH
;
3075 // find the first matching QH position in the FrameList
3079 ptrNextQH
= MatchQH
->ptrNextIntQH
;
3082 // Search all the entries
3084 DelLinkSingleQH (HcDev
, MatchQH
, 0, TRUE
, TRUE
);
3086 MatchQH
= ptrNextQH
;
3090 // Call PciIo->Unmap() to unmap the busmaster read/write
3092 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, MatchList
->Mapping
);
3095 // free host data buffer allocated,
3096 // mapped data buffer is freed by Unmap
3098 if (MatchList
->DataBuffer
!= NULL
) {
3099 gBS
->FreePool (MatchList
->DataBuffer
);
3103 // at last delete the TDs, to aVOID problems
3105 DeleteQueuedTDs (HcDev
, MatchTD
);
3108 // remove Match node from interrupt list
3110 RemoveEntryList (&(MatchList
->Link
));
3111 gBS
->FreePool (MatchList
);
3117 IN TD_STRUCT
*PtrTD
,
3118 IN UINTN RequiredLen
,
3120 OUT UINTN
*ErrTDPos
,
3121 OUT UINTN
*ActualTransferSize
3125 Routine Description:
3131 PtrTD - TD_STRUCT to check
3132 RequiredLen - Required Len
3133 Result - Transfer result
3134 ErrTDPos - Error TD Position
3135 ActualTransferSize - Actual Transfer Size
3146 *Result
= EFI_USB_NOERROR
;
3152 *ActualTransferSize
= 0;
3156 if (IsTDStatusActive (PtrTD
)) {
3157 *Result
|= EFI_USB_ERR_NOTEXECUTE
;
3160 if (IsTDStatusStalled (PtrTD
)) {
3161 *Result
|= EFI_USB_ERR_STALL
;
3164 if (IsTDStatusBufferError (PtrTD
)) {
3165 *Result
|= EFI_USB_ERR_BUFFER
;
3168 if (IsTDStatusBabbleError (PtrTD
)) {
3169 *Result
|= EFI_USB_ERR_BABBLE
;
3172 if (IsTDStatusNAKReceived (PtrTD
)) {
3173 *Result
|= EFI_USB_ERR_NAK
;
3176 if (IsTDStatusCRCTimeOutError (PtrTD
)) {
3177 *Result
|= EFI_USB_ERR_TIMEOUT
;
3180 if (IsTDStatusBitStuffError (PtrTD
)) {
3181 *Result
|= EFI_USB_ERR_BITSTUFF
;
3185 // if any error encountered, stop processing the left TDs.
3191 Len
= GetTDStatusActualLength (PtrTD
) & 0x7FF;
3192 *ActualTransferSize
+= Len
;
3194 if (*ActualTransferSize
<= RequiredLen
&& Len
< PtrTD
->TDData
.TDTokenMaxLen
) {
3196 // transter finished and actural length less than required length
3201 // Accumulate actual transferred data length in each TD.
3203 PtrTD
= (TD_STRUCT
*) (PtrTD
->ptrNextTD
);
3205 // Record the first Error TD's position in the queue,
3206 // this value is zero-based.
3217 ExecuteAsyncINTTDs (
3218 IN USB_HC_DEV
*HcDev
,
3219 IN INTERRUPT_LIST
*PtrList
,
3221 OUT UINTN
*ErrTDPos
,
3222 OUT UINTN
*ActualLen
3226 Routine Description:
3228 Execute Async Interrupt TDs
3233 PtrList - INTERRUPT_LIST
3234 Result - Transfer result
3235 ErrTDPos - Error TD Position
3236 ActualTransferSize - Actual Transfer Size
3245 // *ErrTDPos is zero-based value, indicating the first error TD's position
3246 // in the TDs' sequence.
3247 // *ErrTDPos value is only valid when *Result is not equal NOERROR.
3251 RequiredLen
= *ActualLen
;
3252 CheckTDsResults (PtrList
->PtrFirstTD
, RequiredLen
, Result
, ErrTDPos
, ActualLen
);
3259 UpdateAsyncINTQHTDs (
3260 IN INTERRUPT_LIST
*PtrList
,
3266 Routine Description:
3268 Update Async Interrupt QH and TDs
3272 PtrList - INTERRUPT_LIST
3273 Result - Transfer reslut
3274 ErrTDPos - Error TD Position
3282 QH_STRUCT
*PtrFirstQH
;
3284 TD_STRUCT
*PtrFirstTD
;
3289 PtrFirstQH
= PtrList
->PtrQH
;
3290 PtrFirstTD
= PtrList
->PtrFirstTD
;
3294 if (Result
== EFI_USB_NOERROR
) {
3298 DataToggle
= GetTDTokenDataToggle (PtrTD
);
3299 PtrTD
= PtrTD
->ptrNextTD
;
3303 // save current DataToggle value to interrupt list.
3304 // this value is used for tracing the interrupt endpoint DataToggle.
3305 // when this interrupt transfer is deleted, the last DataToggle is saved
3307 PtrList
->DataToggle
= DataToggle
;
3312 // Since DataToggle bit should toggle after each success transaction,
3313 // the First TD's DataToggle bit will be updated to XOR of Last TD's
3314 // DataToggle bit. If the First TD's DataToggle bit is not equal Last
3315 // TD's DataToggle bit, that means it already be the XOR of Last TD's,
3316 // so no update is needed.
3318 if (DataToggle
== GetTDTokenDataToggle (PtrFirstTD
)) {
3324 SetTDTokenDataToggle1 (PtrTD
);
3326 SetTDTokenDataToggle0 (PtrTD
);
3329 PtrTD
= PtrTD
->ptrNextTD
;
3333 // restore Link Pointer of QH to First TD
3334 // (because QH's Link Pointer will change during TD execution)
3339 LinkTDToQH (PtrQH
, PtrFirstTD
);
3340 PtrQH
= PtrQH
->ptrNextIntQH
;
3344 // set all the TDs active
3348 SetTDStatusActiveorInactive (PtrTD
, TRUE
);
3349 PtrTD
= PtrTD
->ptrNextTD
;
3352 } else if (((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
) ||
3353 ((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
)
3364 // not first TD error
3366 if (ErrTDPos
!= 0) {
3368 // get the last success TD
3370 for (Index
= 1; Index
< ErrTDPos
; Index
++) {
3371 PtrTD
= PtrTD
->ptrNextTD
;
3374 // update Data Toggle in the interrupt list node
3376 PtrList
->DataToggle
= GetTDTokenDataToggle (PtrTD
);
3381 PtrTD
= PtrTD
->ptrNextTD
;
3384 PtrList
->DataToggle
= GetTDTokenDataToggle (PtrTD
);
3387 // do not restore the QH's vertical link pointer,
3388 // let the callback function do the rest of error handling.
3396 ReleaseInterruptList (
3397 IN USB_HC_DEV
*HcDev
,
3398 IN LIST_ENTRY
*ListHead
3402 Routine Description:
3404 Release Interrupt List
3408 ListHead - List head
3417 LIST_ENTRY
*SavedLink
;
3418 INTERRUPT_LIST
*pNode
;
3420 TD_STRUCT
*ptrNextTD
;
3424 if (ListHead
== NULL
) {
3431 // Free all the resources in the interrupt list
3433 SavedLink
= Link
->ForwardLink
;
3434 while (!IsListEmpty (ListHead
)) {
3438 SavedLink
= Link
->ForwardLink
;
3440 pNode
= INTERRUPT_LIST_FROM_LINK (Link
);
3442 RemoveEntryList (&pNode
->Link
);
3444 SavedQH
= pNode
->PtrQH
;
3445 for (PtrQH
= SavedQH
; PtrQH
!= NULL
; PtrQH
= SavedQH
) {
3446 SavedQH
= PtrQH
->ptrNextIntQH
;
3447 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3450 PtrTD
= pNode
->PtrFirstTD
;
3451 while (PtrTD
!= NULL
) {
3453 ptrNextTD
= PtrTD
->ptrNextTD
;
3454 UhciFreePool (HcDev
, (UINT8
*) PtrTD
, sizeof (TD_STRUCT
));
3458 gBS
->FreePool (pNode
);
3464 InitializeMemoryManagement (
3465 IN USB_HC_DEV
*HcDev
3469 Routine Description:
3471 Initialize Memory Management
3479 EFI_SUCCESS - Success
3482 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3486 MemPages
= NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
;
3487 Status
= CreateMemoryBlock (HcDev
, &MemoryHeader
, MemPages
);
3488 if (EFI_ERROR (Status
)) {
3492 HcDev
->MemoryHeader
= MemoryHeader
;
3499 IN USB_HC_DEV
*HcDev
,
3500 OUT MEMORY_MANAGE_HEADER
**MemoryHeader
,
3501 IN UINTN MemoryBlockSizeInPages
3505 Routine Description:
3507 Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
3508 and use PciIo->Map to map the common buffer for Bus Master Read/Write.
3514 MemoryHeader - MEMORY_MANAGE_HEADER to output
3515 MemoryBlockSizeInPages - MemoryBlockSizeInPages
3518 EFI_SUCCESS - Success
3523 EFI_PHYSICAL_ADDRESS MappedAddress
;
3524 UINTN MemoryBlockSizeInBytes
;
3528 // Allocate memory for MemoryHeader
3530 *MemoryHeader
= AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER
));
3531 if (*MemoryHeader
== NULL
) {
3532 return EFI_OUT_OF_RESOURCES
;
3535 (*MemoryHeader
)->Next
= NULL
;
3538 // set Memory block size
3540 (*MemoryHeader
)->MemoryBlockSizeInBytes
= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
);
3543 // each bit in Bit Array will manage 32 bytes memory in memory block
3545 (*MemoryHeader
)->BitArraySizeInBytes
= ((*MemoryHeader
)->MemoryBlockSizeInBytes
/ 32) / 8;
3548 // Allocate memory for BitArray
3550 (*MemoryHeader
)->BitArrayPtr
= AllocateZeroPool ((*MemoryHeader
)->BitArraySizeInBytes
);
3551 if ((*MemoryHeader
)->BitArrayPtr
== NULL
) {
3552 gBS
->FreePool (*MemoryHeader
);
3553 return EFI_OUT_OF_RESOURCES
;
3557 // Memory Block uses MemoryBlockSizeInPages pages,
3558 // and it is allocated as common buffer use.
3560 Status
= HcDev
->PciIo
->AllocateBuffer (
3563 EfiBootServicesData
,
3564 MemoryBlockSizeInPages
,
3568 if (EFI_ERROR (Status
)) {
3569 gBS
->FreePool ((*MemoryHeader
)->BitArrayPtr
);
3570 gBS
->FreePool (*MemoryHeader
);
3574 MemoryBlockSizeInBytes
= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
);
3575 Status
= HcDev
->PciIo
->Map (
3577 EfiPciIoOperationBusMasterCommonBuffer
,
3579 &MemoryBlockSizeInBytes
,
3584 // if returned Mapped size is less than the size we request,do not support.
3586 if (EFI_ERROR (Status
) || (MemoryBlockSizeInBytes
!= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
))) {
3587 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, MemoryBlockSizeInPages
, CommonBuffer
);
3588 gBS
->FreePool ((*MemoryHeader
)->BitArrayPtr
);
3589 gBS
->FreePool (*MemoryHeader
);
3590 return EFI_UNSUPPORTED
;
3593 // Set Memory block initial address
3595 (*MemoryHeader
)->MemoryBlockPtr
= (UINT8
*) ((UINTN
) MappedAddress
);
3596 (*MemoryHeader
)->Mapping
= Mapping
;
3599 (*MemoryHeader
)->MemoryBlockPtr
,
3600 EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
)
3608 IN USB_HC_DEV
*HcDev
,
3609 IN MEMORY_MANAGE_HEADER
*MemoryHeader
3613 Routine Description:
3620 MemoryHeader - MemoryHeader to be freed
3624 EFI_INVALID_PARAMETER - Parameter is error
3625 EFI_SUCCESS - Success
3629 if ((MemoryHeader
== NULL
) || (HcDev
== NULL
)) {
3630 return EFI_INVALID_PARAMETER
;
3633 // unmap the common buffer used by the memory block
3635 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, MemoryHeader
->Mapping
);
3638 // free common buffer
3640 HcDev
->PciIo
->FreeBuffer (
3642 EFI_SIZE_TO_PAGES (MemoryHeader
->MemoryBlockSizeInBytes
),
3643 MemoryHeader
->MemoryBlockPtr
3648 gBS
->FreePool (MemoryHeader
->BitArrayPtr
);
3650 // free memory header
3652 gBS
->FreePool (MemoryHeader
);
3659 IN USB_HC_DEV
*HcDev
,
3665 Routine Description:
3672 Pool - Place to store pointer to the memory buffer
3673 AllocSize - Alloc Size
3677 EFI_SUCCESS - Success
3681 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3682 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
3683 MEMORY_MANAGE_HEADER
*NewMemoryHeader
;
3684 UINTN RealAllocSize
;
3685 UINTN MemoryBlockSizeInPages
;
3690 MemoryHeader
= HcDev
->MemoryHeader
;
3691 ASSERT (MemoryHeader
!= NULL
);
3694 // allocate unit is 32 bytes (align on 32 byte)
3696 if (AllocSize
& 0x1F) {
3697 RealAllocSize
= (AllocSize
/ 32 + 1) * 32;
3699 RealAllocSize
= AllocSize
;
3703 // There may be linked MemoryHeaders.
3704 // To allocate a free pool in Memory blocks,
3705 // must search in the MemoryHeader link list
3706 // until enough free pool is found.
3708 Status
= EFI_NOT_FOUND
;
3709 for (TempHeaderPtr
= MemoryHeader
; TempHeaderPtr
!= NULL
;
3710 TempHeaderPtr
= TempHeaderPtr
->Next
) {
3712 Status
= AllocMemInMemoryBlock (
3717 if (!EFI_ERROR (Status
)) {
3718 ZeroMem (*Pool
, AllocSize
);
3724 // There is no enough memory,
3725 // Create a new Memory Block
3729 // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,
3730 // just allocate a large enough memory block.
3732 if (RealAllocSize
> EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
)) {
3733 MemoryBlockSizeInPages
= EFI_SIZE_TO_PAGES (RealAllocSize
) + 1;
3735 MemoryBlockSizeInPages
= NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
;
3738 Status
= CreateMemoryBlock (HcDev
, &NewMemoryHeader
, MemoryBlockSizeInPages
);
3739 if (EFI_ERROR (Status
)) {
3744 // Link the new Memory Block to the Memory Header list
3746 InsertMemoryHeaderToList (MemoryHeader
, NewMemoryHeader
);
3748 Status
= AllocMemInMemoryBlock (
3754 if (!EFI_ERROR (Status
)) {
3755 ZeroMem (*Pool
, AllocSize
);
3763 IN USB_HC_DEV
*HcDev
,
3769 Routine Description:
3777 AllocSize - Pool size
3785 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3786 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
3792 UINTN RealAllocSize
;
3794 MemoryHeader
= HcDev
->MemoryHeader
;
3797 // allocate unit is 32 byte (align on 32 byte)
3799 if (AllocSize
& 0x1F) {
3800 RealAllocSize
= (AllocSize
/ 32 + 1) * 32;
3802 RealAllocSize
= AllocSize
;
3805 // scan the memory header linked list for
3806 // the asigned memory to free.
3808 for (TempHeaderPtr
= MemoryHeader
;TempHeaderPtr
!= NULL
;
3809 TempHeaderPtr
= TempHeaderPtr
->Next
) {
3811 if ((Pool
>= TempHeaderPtr
->MemoryBlockPtr
) &&
3812 ((Pool
+ RealAllocSize
) <= (TempHeaderPtr
->MemoryBlockPtr
+ TempHeaderPtr
->MemoryBlockSizeInBytes
))
3815 // Pool is in the Memory Block area,
3816 // find the start byte and bit in the bit array
3818 StartBytePos
= ((Pool
- TempHeaderPtr
->MemoryBlockPtr
) / 32) / 8;
3819 StartBitPos
= (UINT8
) (((Pool
- TempHeaderPtr
->MemoryBlockPtr
) / 32) & 0x7);
3822 // reset associated bits in bit arry
3824 for (Index
= StartBytePos
, Index2
= StartBitPos
, Count
= 0; Count
< (RealAllocSize
/ 32); Count
++) {
3826 TempHeaderPtr
->BitArrayPtr
[Index
] = (UINT8
) (TempHeaderPtr
->BitArrayPtr
[Index
] ^ bit (Index2
));
3841 // Release emptied memory blocks (only if the memory block is not
3842 // the first one in the memory header list
3844 for (TempHeaderPtr
= MemoryHeader
->Next
; TempHeaderPtr
!= NULL
;) {
3848 ASSERT (MemoryHeader
->Next
!= NULL
);
3850 if (IsMemoryBlockEmptied (TempHeaderPtr
)) {
3852 DelinkMemoryBlock (MemoryHeader
, TempHeaderPtr
);
3854 // when the TempHeaderPtr is freed in FreeMemoryHeader(),
3855 // the TempHeaderPtr is pointing to nonsense content.
3857 FreeMemoryHeader (HcDev
, TempHeaderPtr
);
3859 // reset the TempHeaderPtr, continue search for
3860 // another empty memory block.
3862 TempHeaderPtr
= MemoryHeader
->Next
;
3866 TempHeaderPtr
= TempHeaderPtr
->Next
;
3871 InsertMemoryHeaderToList (
3872 IN MEMORY_MANAGE_HEADER
*MemoryHeader
,
3873 IN MEMORY_MANAGE_HEADER
*NewMemoryHeader
3877 Routine Description:
3879 Insert Memory Header To List
3883 MemoryHeader - MEMORY_MANAGE_HEADER
3884 NewMemoryHeader - MEMORY_MANAGE_HEADER
3892 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
3894 for (TempHeaderPtr
= MemoryHeader
; TempHeaderPtr
!= NULL
;
3895 TempHeaderPtr
= TempHeaderPtr
->Next
) {
3896 if (TempHeaderPtr
->Next
== NULL
) {
3897 TempHeaderPtr
->Next
= NewMemoryHeader
;
3904 AllocMemInMemoryBlock (
3905 IN MEMORY_MANAGE_HEADER
*MemoryHeader
,
3907 IN UINTN NumberOfMemoryUnit
3911 Routine Description:
3913 Alloc Memory In MemoryBlock
3917 MemoryHeader - MEMORY_MANAGE_HEADER
3918 Pool - Place to store pointer to memory
3919 NumberOfMemoryUnit - Number Of Memory Unit
3923 EFI_NOT_FOUND - Can't find the free memory
3924 EFI_SUCCESS - Success
3934 UINTN NumberOfZeros
;
3939 ByteValue
= MemoryHeader
->BitArrayPtr
[0];
3943 for (TempBytePos
= 0; TempBytePos
< MemoryHeader
->BitArraySizeInBytes
;) {
3946 // Pop out BitValue from a byte in TempBytePos.
3948 BitValue
= (UINT8
) (ByteValue
& 0x1);
3950 // right shift the byte
3954 if (BitValue
== 0) {
3956 // Found a free bit, the NumberOfZeros only record the number
3957 // of those consecutive zeros
3961 // Found enough consecutive free space, break the loop
3963 if (NumberOfZeros
>= NumberOfMemoryUnit
) {
3968 // Encountering a '1', meant the bit is ocupied.
3970 if (NumberOfZeros
>= NumberOfMemoryUnit
) {
3972 // Found enough consecutive free space,break the loop
3977 // the NumberOfZeros only record the number of those consecutive zeros,
3978 // so reset the NumberOfZeros to 0 when encountering '1' before finding
3979 // enough consecutive '0's
3983 // reset the (FoundBytePos,FoundBitPos) to the position of '1'
3985 FoundBytePos
= TempBytePos
;
3986 FoundBitPos
= Index
;
3990 // step forward a bit
3995 // step forward a byte, getting the byte value,
3996 // and reset the bit pos.
3999 ByteValue
= MemoryHeader
->BitArrayPtr
[TempBytePos
];
4004 if (NumberOfZeros
< NumberOfMemoryUnit
) {
4005 return EFI_NOT_FOUND
;
4009 // Found enough free space.
4013 // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:
4014 // 1)(FoundBytePos,FoundBitPos) record the position
4015 // of the last '1' before the consecutive '0's, it must
4016 // be adjusted to the start position of the consecutive '0's.
4017 // 2)the start address of the consecutive '0's is just the start of
4018 // the bitarray. so no need to adjust the values of
4019 // (FoundBytePos,FoundBitPos).
4021 if ((MemoryHeader
->BitArrayPtr
[0] & bit (0)) != 0) {
4026 // Have the (FoundBytePos,FoundBitPos) make sense.
4028 if (FoundBitPos
> 7) {
4034 // Set the memory as allocated
4036 for (TempBytePos
= FoundBytePos
, Index
= FoundBitPos
,Count
= 0;
4037 Count
< NumberOfMemoryUnit
; Count
++) {
4039 MemoryHeader
->BitArrayPtr
[TempBytePos
] = (UINT8
) (MemoryHeader
->BitArrayPtr
[TempBytePos
] | bit (Index
));
4047 *Pool
= MemoryHeader
->MemoryBlockPtr
+ (FoundBytePos
* 8 + FoundBitPos
) * 32;
4053 IsMemoryBlockEmptied (
4054 IN MEMORY_MANAGE_HEADER
*MemoryHeaderPtr
4058 Routine Description:
4060 Is Memory Block Emptied
4064 MemoryHeaderPtr - MEMORY_MANAGE_HEADER
4075 for (Index
= 0; Index
< MemoryHeaderPtr
->BitArraySizeInBytes
; Index
++) {
4076 if (MemoryHeaderPtr
->BitArrayPtr
[Index
] != 0) {
4086 IN MEMORY_MANAGE_HEADER
*FirstMemoryHeader
,
4087 IN MEMORY_MANAGE_HEADER
*NeedFreeMemoryHeader
4091 Routine Description:
4097 FirstMemoryHeader - MEMORY_MANAGE_HEADER
4098 NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER
4106 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
4108 if ((FirstMemoryHeader
== NULL
) || (NeedFreeMemoryHeader
== NULL
)) {
4111 for (TempHeaderPtr
= FirstMemoryHeader
; TempHeaderPtr
!= NULL
;
4112 TempHeaderPtr
= TempHeaderPtr
->Next
) {
4114 if (TempHeaderPtr
->Next
== NeedFreeMemoryHeader
) {
4116 // Link the before and after
4118 TempHeaderPtr
->Next
= NeedFreeMemoryHeader
->Next
;
4125 DelMemoryManagement (
4126 IN USB_HC_DEV
*HcDev
4130 Routine Description:
4132 Delete Memory Management
4140 EFI_SUCCESS - Success
4144 MEMORY_MANAGE_HEADER
*TempHeaderPtr
;
4146 for (TempHeaderPtr
= HcDev
->MemoryHeader
->Next
; TempHeaderPtr
!= NULL
;) {
4148 DelinkMemoryBlock (HcDev
->MemoryHeader
, TempHeaderPtr
);
4150 // when the TempHeaderPtr is freed in FreeMemoryHeader(),
4151 // the TempHeaderPtr is pointing to nonsense content.
4153 FreeMemoryHeader (HcDev
, TempHeaderPtr
);
4155 // reset the TempHeaderPtr,continue free another memory block.
4157 TempHeaderPtr
= HcDev
->MemoryHeader
->Next
;
4160 FreeMemoryHeader (HcDev
, HcDev
->MemoryHeader
);
4167 CleanUsbTransactions (
4168 IN USB_HC_DEV
*HcDev
4172 // only asynchronous interrupt transfers are always alive on the bus
4174 ReleaseInterruptList (HcDev
, &(HcDev
->InterruptListHead
));
4178 TurnOffUSBEmulation (
4179 IN EFI_PCI_IO_PROTOCOL
*PciIo
4183 Routine Description:
4184 Disable USB Emulation
4186 PciIo - EFI_PCI_IO_PROTOCOL
4194 // Disable USB Emulation
4199 EfiPciIoWidthUint16
,