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.
26 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
38 PciIo - EFI_PCI_IO_PROTOCOL
39 PortOffset - Port offset
49 // Perform 16bit Read in PCI IO Space
51 return PciIo
->Io
.Read (
63 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
75 PciIo - EFI_PCI_IO_PROTOCOL
76 PortOffset - Port offset
86 // Perform 32bit Read in PCI IO Space
88 return PciIo
->Io
.Read (
100 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
101 IN UINT32 PortOffset
,
112 PciIo - EFI_PCI_IO_PROTOCOL
113 PortOffset - Port offset
123 // Perform 16bit Write in PCI IO Space
125 return PciIo
->Io
.Write (
137 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
138 IN UINT32 PortOffset
,
149 PciIo - EFI_PCI_IO_PROTOCOL
150 PortOffset - Port offset
160 // Perform 32bit Write in PCI IO Space
162 return PciIo
->Io
.Write (
172 // USB register-base helper functions
176 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
177 IN UINT32 CmdAddrOffset
,
184 Write UHCI Command Register
188 PciIo - EFI_PCI_IO_PROTOCOL
189 CmdAddrOffset - Command address offset
190 UsbCmd - Data to write
199 // Write to UHC's Command Register
201 return USBWritePortW (PciIo
, CmdAddrOffset
, UsbCmd
);
206 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
207 IN UINT32 CmdAddrOffset
,
214 Read UHCI Command Register
218 PciIo - EFI_PCI_IO_PROTOCOL
219 CmdAddrOffset - Command address offset
220 Data - Data to return
229 // Read from UHC's Command Register
231 return USBReadPortW (PciIo
, CmdAddrOffset
, Data
);
236 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
237 IN UINT32 StatusAddrOffset
,
244 Write UHCI Staus Register
248 PciIo - EFI_PCI_IO_PROTOCOL
249 StatusAddrOffset - Status address offset
250 UsbSts - Data to write
259 // Write to UHC's Status Register
261 return USBWritePortW (PciIo
, StatusAddrOffset
, UsbSts
);
266 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
267 IN UINT32 StatusAddrOffset
,
274 Read UHCI Staus Register
278 PciIo - EFI_PCI_IO_PROTOCOL
279 StatusAddrOffset - Status address offset
280 UsbSts - Data to return
289 // Read from UHC's Status Register
291 return USBReadPortW (PciIo
, StatusAddrOffset
, Data
);
297 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
298 IN UINT32 StatusAddrOffset
304 Clear the content of UHC's Status Register
308 PciIo - EFI_PCI_IO_PROTOCOL
309 StatusAddrOffset - Status address offset
318 return WriteUHCStatusReg (PciIo
, StatusAddrOffset
, 0x003F);
322 ReadUHCFrameNumberReg (
323 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
324 IN UINT32 FrameNumAddrOffset
,
331 Read from UHC's Frame Number Register
335 PciIo - EFI_PCI_IO_PROTOCOL
336 FrameNumAddrOffset - Frame number register offset
337 Data - Data to return
345 return USBReadPortW (PciIo
, FrameNumAddrOffset
, Data
);
349 WriteUHCFrameListBaseReg (
350 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
351 IN UINT32 FlBaseAddrOffset
,
352 IN UINT32 UsbFrameListBaseAddr
358 Write to UHC's Frame List Base Register
362 PciIo - EFI_PCI_IO_PROTOCOL
363 FlBaseAddrOffset - Frame Base address register
364 UsbFrameListBaseAddr - Address to write
373 return USBWritePortDW (PciIo
, FlBaseAddrOffset
, UsbFrameListBaseAddr
);
378 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
379 IN UINT32 PortAddrOffset
,
386 Read from UHC's Root Port Register
390 PciIo - EFI_PCI_IO_PROTOCOL
391 PortAddrOffset - Port Addrress Offset,
392 Data - Data to return
400 return USBReadPortW (PciIo
, PortAddrOffset
, Data
);
405 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
406 IN UINT32 PortAddrOffset
,
407 IN UINT16 ControlBits
413 Write to UHC's Root Port Register
417 PciIo - EFI_PCI_IO_PROTOCOL
418 PortAddrOffset - Port Addrress Offset,
419 ControlBits - Data to write
427 return USBWritePortW (PciIo
, PortAddrOffset
, ControlBits
);
434 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
435 IN UINT32 StatusRegAddr
,
442 Wait until UHCI halt or timeout
446 PciIo - EFI_PCI_IO_PROTOCOL
447 StatusRegAddr - Status Register Address
448 Timeout - Time out value in us
452 EFI_DEVICE_ERROR - Unable to read the status register
453 EFI_TIMEOUT - Time out
454 EFI_SUCCESS - Success
463 // Timeout is in us unit
465 Delay
= (Timeout
/ 50) + 1;
467 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
468 if (EFI_ERROR (Status
)) {
469 return EFI_DEVICE_ERROR
;
472 if ((HcStatus
& USBSTS_HCH
) == USBSTS_HCH
) {
491 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
492 IN UINT32 StatusRegAddr
498 Judge whether the host controller operates well
502 PciIo - EFI_PCI_IO_PROTOCOL
503 StatusRegAddr - Status register address
507 TRUE - Status is good
508 FALSE - Status is bad
515 // Detect whether the interrupt is caused by fatal error.
516 // see "UHCI Design Guid".
518 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
519 if (EFI_ERROR (Status
)) {
523 if (HcStatus
& (USBSTS_HCPE
| USBSTS_HSE
| USBSTS_HCH
)) {
533 IsHostSysOrProcessErr (
534 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
535 IN UINT32 StatusRegAddr
541 Judge the status is HostSys,ProcessErr error or good
545 PciIo - EFI_PCI_IO_PROTOCOL
546 StatusRegAddr - Status register address
550 TRUE - Status is good
551 FALSE - Status is bad
558 // Detect whether the interrupt is caused by serious error.
559 // see "UHCI Design Guid".
561 Status
= ReadUHCStatusReg (PciIo
, StatusRegAddr
, &HcStatus
);
562 if (EFI_ERROR (Status
)) {
566 if (HcStatus
& (USBSTS_HSE
| USBSTS_HCPE
)) {
575 GetCurrentFrameNumber (
576 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
577 IN UINT32 FrameNumAddrOffset
583 Get Current Frame Number
587 PciIo - EFI_PCI_IO_PROTOCOL
588 FrameNumAddrOffset - FrameNum register AddrOffset
597 // Gets value in the USB frame number register.
601 ReadUHCFrameNumberReg (PciIo
, FrameNumAddrOffset
, &FrameNumber
);
603 return (UINT16
) (FrameNumber
& 0x03FF);
607 SetFrameListBaseAddress (
608 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
609 IN UINT32 FlBaseAddrReg
,
616 Set FrameListBase Address
620 PciIo - EFI_PCI_IO_PROTOCOL
621 FlBaseAddrReg - FrameListBase register
622 Addr - Address to set
631 // Sets value in the USB Frame List Base Address register.
633 return WriteUHCFrameListBaseReg (PciIo
, FlBaseAddrReg
, (UINT32
) (Addr
& 0xFFFFF000));
637 EnableMaxPacketSize (
644 Enable Max Packet Size
656 UINT16 CommandContent
;
659 Status
= ReadUHCCommandReg (
665 if ((CommandContent
& USBCMD_MAXP
) != USBCMD_MAXP
) {
666 CommandContent
|= USBCMD_MAXP
;
679 IN USB_HC_DEV
*HcDev
,
680 IN UINT32 FlBaseAddrReg
691 FlBaseAddrReg - Frame List register
695 EFI_OUT_OF_RESOURCES - Can't allocate memory resources
696 EFI_UNSUPPORTED - Map memory fail
697 EFI_SUCCESS - Success
703 EFI_PHYSICAL_ADDRESS MappedAddress
;
705 UINTN BufferSizeInPages
;
706 UINTN BufferSizeInBytes
;
709 // The Frame List is a common buffer that will be
710 // accessed by both the cpu and the usb bus master
712 // The Frame List ocupies 4K bytes,
713 // and must be aligned on 4-Kbyte boundaries.
715 BufferSizeInBytes
= 4096;
716 BufferSizeInPages
= EFI_SIZE_TO_PAGES (BufferSizeInBytes
);
717 Status
= HcDev
->PciIo
->AllocateBuffer (
725 if (EFI_ERROR (Status
)) {
726 return EFI_OUT_OF_RESOURCES
;
729 Status
= HcDev
->PciIo
->Map (
731 EfiPciIoOperationBusMasterCommonBuffer
,
737 if (EFI_ERROR (Status
) || (BufferSizeInBytes
!= 4096)) {
738 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, BufferSizeInPages
, CommonBuffer
);
739 return EFI_UNSUPPORTED
;
742 HcDev
->FrameListEntry
= (FRAMELIST_ENTRY
*) ((UINTN
) MappedAddress
);
744 HcDev
->FrameListMapping
= Mapping
;
746 InitFrameList (HcDev
);
749 // Tell the Host Controller where the Frame List lies,
750 // by set the Frame List Base Address Register.
752 SetFrameListBaseAddress (
755 (UINT32
) ((UINTN
) HcDev
->FrameListEntry
)
769 Free FrameList buffer
777 EFI_SUCCESS - success
782 // Unmap the common buffer for framelist entry,
783 // and free the common buffer.
784 // Uhci's frame list occupy 4k memory.
786 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, HcDev
->FrameListMapping
);
787 HcDev
->PciIo
->FreeBuffer (
789 EFI_SIZE_TO_PAGES (4096),
790 (VOID
*) (HcDev
->FrameListEntry
)
814 FRAMELIST_ENTRY
*FrameListPtr
;
818 // Validate each Frame List Entry
820 FrameListPtr
= HcDev
->FrameListEntry
;
821 for (Index
= 0; Index
< 1024; Index
++) {
822 FrameListPtr
->FrameListPtrTerminate
= 1;
823 FrameListPtr
->FrameListPtr
= 0;
824 FrameListPtr
->FrameListPtrQSelect
= 0;
825 FrameListPtr
->FrameListRsvd
= 0;
830 // //////////////////////////////////////////////////////////////
832 // QH TD related Helper Functions
834 ////////////////////////////////////////////////////////////////
840 IN USB_HC_DEV
*HcDev
,
841 OUT QH_STRUCT
**ppQHStruct
852 ppQHStruct - QH_STRUCT content to return
862 // QH must align on 16 bytes alignment,
863 // since the memory allocated by UhciAllocatePool ()
864 // is aligned on 32 bytes, it is no need to adjust
865 // the allocated memory returned.
867 return UhciAllocatePool (HcDev
, (UINT8
**) ppQHStruct
, sizeof (QH_STRUCT
));
873 IN USB_HC_DEV
*HcDev
,
874 OUT QH_STRUCT
**pptrQH
885 ppQHStruct - QH_STRUCT content to return
888 EFI_SUCCESS - Success
889 EFI_OUT_OF_RESOURCES - Can't allocate memory
895 // allocate align memory for QH_STRUCT
897 Status
= AllocateQHStruct (HcDev
, pptrQH
);
898 if (EFI_ERROR (Status
)) {
899 return EFI_OUT_OF_RESOURCES
;
902 // init each field of the QH_STRUCT
907 SetQHHorizontalValidorInvalid (*pptrQH
, FALSE
);
908 SetQHVerticalValidorInvalid (*pptrQH
, FALSE
);
914 SetQHHorizontalLinkPtr (
922 Set QH Horizontal Link Pointer
927 ptrNext - Data to write
936 // Since the QH_STRUCT is aligned on 16-byte boundaries,
937 // Only the highest 28bit of the address is valid
938 // (take 32bit address as an example).
940 PtrQH
->QH
.QHHorizontalPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
944 GetQHHorizontalLinkPtr (
951 Get QH Horizontal Link Pointer
965 // Restore the 28bit address to 32bit address
966 // (take 32bit address as an example)
968 return (VOID
*) ((UINTN
) (PtrQH
->QH
.QHHorizontalPtr
<< 4));
972 SetQHHorizontalQHorTDSelect (
980 Set QH Horizontal QH or TD
985 bQH - TRUE is QH FALSE is TD
993 // if QH is connected, the specified bit is set,
994 // if TD is connected, the specified bit is cleared.
996 PtrQH
->QH
.QHHorizontalQSelect
= bQH
? 1 : 0;
1001 SetQHHorizontalValidorInvalid (
1002 IN QH_STRUCT
*PtrQH
,
1007 Routine Description:
1009 Set QH Horizontal Valid or Invalid
1014 bValid - TRUE is Valid FALSE is Invalid
1022 // Valid means the horizontal link pointer is valid,
1023 // else, it's invalid.
1025 PtrQH
->QH
.QHHorizontalTerminate
= bValid
? 0 : 1;
1029 SetQHVerticalLinkPtr (
1030 IN QH_STRUCT
*PtrQH
,
1035 Routine Description:
1037 Set QH Vertical Link Pointer
1042 ptrNext - Data to write
1050 // Since the QH_STRUCT is aligned on 16-byte boundaries,
1051 // Only the highest 28bit of the address is valid
1052 // (take 32bit address as an example).
1054 PtrQH
->QH
.QHVerticalPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
1058 GetQHVerticalLinkPtr (
1063 Routine Description:
1065 Get QH Vertical Link Pointer
1078 // Restore the 28bit address to 32bit address
1079 // (take 32bit address as an example)
1081 return (VOID
*) ((UINTN
) (PtrQH
->QH
.QHVerticalPtr
<< 4));
1085 SetQHVerticalQHorTDSelect (
1086 IN QH_STRUCT
*PtrQH
,
1091 Routine Description:
1093 Set QH Vertical QH or TD
1098 bQH - TRUE is QH FALSE is TD
1107 // Set the specified bit if the Vertical Link Pointer pointing to a QH,
1108 // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
1110 PtrQH
->QH
.QHVerticalQSelect
= bQH
? 1 : 0;
1114 IsQHHorizontalQHSelect (
1119 Routine Description:
1121 Is QH Horizontal QH Select
1135 // Retrieve the information about whether the Horizontal Link Pointer
1136 // pointing to a QH or TD.
1138 return (BOOLEAN
) (PtrQH
->QH
.QHHorizontalQSelect
? TRUE
: FALSE
);
1142 SetQHVerticalValidorInvalid (
1143 IN QH_STRUCT
*PtrQH
,
1148 Routine Description:
1150 Set QH Vertical Valid or Invalid
1155 IsValid - TRUE is valid FALSE is invalid
1164 // If TRUE, indicates the Vertical Link Pointer field is valid,
1165 // else, the field is invalid.
1167 PtrQH
->QH
.QHVerticalTerminate
= IsValid
? 0 : 1;
1172 GetQHVerticalValidorInvalid (
1177 Routine Description:
1179 Get QH Vertical Valid or Invalid
1193 // If TRUE, indicates the Vertical Link Pointer field is valid,
1194 // else, the field is invalid.
1196 return (BOOLEAN
) (!(PtrQH
->QH
.QHVerticalTerminate
));
1200 GetQHHorizontalValidorInvalid (
1205 Routine Description:
1207 Get QH Horizontal Valid or Invalid
1221 // If TRUE, meaning the Horizontal Link Pointer field is valid,
1222 // else, the field is invalid.
1224 return (BOOLEAN
) (!(PtrQH
->QH
.QHHorizontalTerminate
));
1231 IN USB_HC_DEV
*HcDev
,
1232 OUT TD_STRUCT
**ppTDStruct
1236 Routine Description:
1243 ppTDStruct - place to store TD_STRUCT pointer
1253 // TD must align on 16 bytes alignment,
1254 // since the memory allocated by UhciAllocatePool ()
1255 // is aligned on 32 bytes, it is no need to adjust
1256 // the allocated memory returned.
1258 return UhciAllocatePool (
1260 (UINT8
**) ppTDStruct
,
1267 IN USB_HC_DEV
*HcDev
,
1268 OUT TD_STRUCT
**pptrTD
1272 Routine Description:
1279 pptrTD - TD_STRUCT pointer to store
1283 EFI_OUT_OF_RESOURCES - Can't allocate resources
1284 EFI_SUCCESS - Success
1290 // create memory for TD_STRUCT, and align the memory.
1292 Status
= AllocateTDStruct (HcDev
, pptrTD
);
1293 if (EFI_ERROR (Status
)) {
1294 return EFI_OUT_OF_RESOURCES
;
1300 SetTDLinkPtrValidorInvalid (*pptrTD
, FALSE
);
1308 IN USB_HC_DEV
*HcDev
,
1313 IN UINT8 RequestLen
,
1314 OUT TD_STRUCT
**ppTD
1318 Routine Description:
1320 Generate Setup Stage TD
1325 DevAddr - Device address
1326 Endpoint - Endpoint number
1327 bSlow - Full speed or low speed
1328 pDevReq - Device request
1329 RequestLen - Request length
1330 ppTD - TD_STRUCT to return
1333 EFI_OUT_OF_RESOURCES - Can't allocate memory
1334 EFI_SUCCESS - Success
1339 TD_STRUCT
*pTDStruct
;
1341 Status
= CreateTD (HcDev
, &pTDStruct
);
1342 if (EFI_ERROR (Status
)) {
1343 return EFI_OUT_OF_RESOURCES
;
1346 SetTDLinkPtr (pTDStruct
, NULL
);
1349 // Depth first fashion
1351 SetTDLinkPtrDepthorBreadth (pTDStruct
, TRUE
);
1354 // initialize as the last TD in the QH context,
1355 // this field will be updated in the TD linkage process.
1357 SetTDLinkPtrValidorInvalid (pTDStruct
, FALSE
);
1360 // Disable Short Packet Detection by default
1362 EnableorDisableTDShortPacket (pTDStruct
, FALSE
);
1365 // Max error counter is 3, retry 3 times when error encountered.
1367 SetTDControlErrorCounter (pTDStruct
, 3);
1370 // set device speed attribute
1371 // (TRUE - Slow Device; FALSE - Full Speed Device)
1373 SetTDLoworFullSpeedDevice (pTDStruct
, bSlow
);
1376 // Non isochronous transfer TD
1378 SetTDControlIsochronousorNot (pTDStruct
, FALSE
);
1381 // Interrupt On Complete bit be set to zero,
1382 // Disable IOC interrupt.
1384 SetorClearTDControlIOC (pTDStruct
, FALSE
);
1387 // Set TD Active bit
1389 SetTDStatusActiveorInactive (pTDStruct
, TRUE
);
1391 SetTDTokenMaxLength (pTDStruct
, RequestLen
);
1393 SetTDTokenDataToggle0 (pTDStruct
);
1395 SetTDTokenEndPoint (pTDStruct
, Endpoint
);
1397 SetTDTokenDeviceAddress (pTDStruct
, DevAddr
);
1399 SetTDTokenPacketID (pTDStruct
, SETUP_PACKET_ID
);
1401 pTDStruct
->pTDBuffer
= (UINT8
*) pDevReq
;
1402 pTDStruct
->TDBufferLength
= RequestLen
;
1403 SetTDDataBuffer (pTDStruct
);
1412 IN USB_HC_DEV
*HcDev
,
1420 OUT TD_STRUCT
**ppTD
1424 Routine Description:
1426 Generate Data Stage TD
1431 DevAddr - Device address
1432 Endpoint - Endpoint number
1436 Toggle - Data toggle value
1437 bSlow - Full speed or low speed
1438 ppTD - TD_STRUCT to return
1441 EFI_OUT_OF_RESOURCES - Can't allocate memory
1442 EFI_SUCCESS - Success
1446 TD_STRUCT
*pTDStruct
;
1449 Status
= CreateTD (HcDev
, &pTDStruct
);
1450 if (EFI_ERROR (Status
)) {
1451 return EFI_OUT_OF_RESOURCES
;
1454 SetTDLinkPtr (pTDStruct
, NULL
);
1457 // Depth first fashion
1459 SetTDLinkPtrDepthorBreadth (pTDStruct
, TRUE
);
1462 // Link pointer pointing to TD struct
1464 SetTDLinkPtrQHorTDSelect (pTDStruct
, FALSE
);
1467 // initialize as the last TD in the QH context,
1468 // this field will be updated in the TD linkage process.
1470 SetTDLinkPtrValidorInvalid (pTDStruct
, FALSE
);
1473 // Disable short packet detect
1475 EnableorDisableTDShortPacket (pTDStruct
, FALSE
);
1477 // Max error counter is 3
1479 SetTDControlErrorCounter (pTDStruct
, 3);
1482 // set device speed attribute
1483 // (TRUE - Slow Device; FALSE - Full Speed Device)
1485 SetTDLoworFullSpeedDevice (pTDStruct
, bSlow
);
1488 // Non isochronous transfer TD
1490 SetTDControlIsochronousorNot (pTDStruct
, FALSE
);
1493 // Disable Interrupt On Complete
1494 // Disable IOC interrupt.
1496 SetorClearTDControlIOC (pTDStruct
, FALSE
);
1501 SetTDStatusActiveorInactive (pTDStruct
, TRUE
);
1503 SetTDTokenMaxLength (pTDStruct
, Len
);
1506 SetTDTokenDataToggle1 (pTDStruct
);
1508 SetTDTokenDataToggle0 (pTDStruct
);
1511 SetTDTokenEndPoint (pTDStruct
, Endpoint
);
1513 SetTDTokenDeviceAddress (pTDStruct
, DevAddr
);
1515 SetTDTokenPacketID (pTDStruct
, PktID
);
1517 pTDStruct
->pTDBuffer
= (UINT8
*) pData
;
1518 pTDStruct
->TDBufferLength
= Len
;
1519 SetTDDataBuffer (pTDStruct
);
1528 IN USB_HC_DEV
*HcDev
,
1533 OUT TD_STRUCT
**ppTD
1537 Routine Description:
1539 Generate Status Stage TD
1544 DevAddr - Device address
1545 Endpoint - Endpoint number
1547 bSlow - Full speed or low speed
1548 ppTD - TD_STRUCT to return
1551 EFI_OUT_OF_RESOURCES - Can't allocate memory
1552 EFI_SUCCESS - Success
1556 TD_STRUCT
*ptrTDStruct
;
1559 Status
= CreateTD (HcDev
, &ptrTDStruct
);
1560 if (EFI_ERROR (Status
)) {
1561 return EFI_OUT_OF_RESOURCES
;
1564 SetTDLinkPtr (ptrTDStruct
, NULL
);
1567 // Depth first fashion
1569 SetTDLinkPtrDepthorBreadth (ptrTDStruct
, TRUE
);
1572 // initialize as the last TD in the QH context,
1573 // this field will be updated in the TD linkage process.
1575 SetTDLinkPtrValidorInvalid (ptrTDStruct
, FALSE
);
1578 // Disable short packet detect
1580 EnableorDisableTDShortPacket (ptrTDStruct
, FALSE
);
1583 // Max error counter is 3
1585 SetTDControlErrorCounter (ptrTDStruct
, 3);
1588 // set device speed attribute
1589 // (TRUE - Slow Device; FALSE - Full Speed Device)
1591 SetTDLoworFullSpeedDevice (ptrTDStruct
, bSlow
);
1594 // Non isochronous transfer TD
1596 SetTDControlIsochronousorNot (ptrTDStruct
, FALSE
);
1599 // Disable Interrupt On Complete
1600 // Disable IOC interrupt.
1602 SetorClearTDControlIOC (ptrTDStruct
, FALSE
);
1605 // Set TD Active bit
1607 SetTDStatusActiveorInactive (ptrTDStruct
, TRUE
);
1609 SetTDTokenMaxLength (ptrTDStruct
, 0);
1611 SetTDTokenDataToggle1 (ptrTDStruct
);
1613 SetTDTokenEndPoint (ptrTDStruct
, Endpoint
);
1615 SetTDTokenDeviceAddress (ptrTDStruct
, DevAddr
);
1617 SetTDTokenPacketID (ptrTDStruct
, PktID
);
1619 ptrTDStruct
->pTDBuffer
= NULL
;
1620 ptrTDStruct
->TDBufferLength
= 0;
1621 SetTDDataBuffer (ptrTDStruct
);
1623 *ppTD
= ptrTDStruct
;
1630 SetTDLinkPtrValidorInvalid (
1631 IN TD_STRUCT
*ptrTDStruct
,
1636 Routine Description:
1638 Set TD Link Pointer Valid or Invalid
1642 ptrTDStruct - TD_STRUCT
1643 bValid - TRUE is valid FALSE is invalid
1652 // Valid means the link pointer is valid,
1653 // else, it's invalid.
1655 ptrTDStruct
->TDData
.TDLinkPtrTerminate
= (bValid
? 0 : 1);
1659 SetTDLinkPtrQHorTDSelect (
1660 IN TD_STRUCT
*ptrTDStruct
,
1665 Routine Description:
1667 Set TD Link Pointer QH or TD Select
1671 ptrTDStruct - TD_STRUCT
1672 bQH - TRUE is QH FALSE is TD
1681 // Indicate whether the Link Pointer pointing to a QH or TD
1683 ptrTDStruct
->TDData
.TDLinkPtrQSelect
= (bQH
? 1 : 0);
1687 SetTDLinkPtrDepthorBreadth (
1688 IN TD_STRUCT
*ptrTDStruct
,
1693 Routine Description:
1695 Set TD Link Pointer depth or bread priority
1699 ptrTDStruct - TD_STRUCT
1700 bDepth - TRUE is Depth FALSE is Breadth
1709 // If TRUE, indicating the host controller should process in depth first
1711 // else, the host controller should process in breadth first fashion
1713 ptrTDStruct
->TDData
.TDLinkPtrDepthSelect
= (bDepth
? 1 : 0);
1718 IN TD_STRUCT
*ptrTDStruct
,
1723 Routine Description:
1729 ptrTDStruct - TD_STRUCT
1730 ptrNext - Pointer to set
1739 // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,
1740 // only the highest 28 bits are valid. (if take 32bit address as an example)
1742 ptrTDStruct
->TDData
.TDLinkPtr
= (UINT32
) ((UINTN
) ptrNext
>> 4);
1747 IN TD_STRUCT
*ptrTDStruct
1751 Routine Description:
1757 ptrTDStruct - TD_STRUCT
1766 // Get TD Link Pointer. Restore it back to 32bit
1767 // (if take 32bit address as an example)
1769 return (VOID
*) ((UINTN
) (ptrTDStruct
->TDData
.TDLinkPtr
<< 4));
1774 IN TD_STRUCT
*ptrTDStruct
1778 Routine Description:
1780 Is TD Link Pointer is QH Or TD
1784 ptrTDStruct - TODO: add argument description
1794 // Get the information about whether the Link Pointer field pointing to
1797 return (BOOLEAN
) (ptrTDStruct
->TDData
.TDLinkPtrQSelect
);
1801 EnableorDisableTDShortPacket (
1802 IN TD_STRUCT
*ptrTDStruct
,
1807 Routine Description:
1809 Enable or Disable TD ShortPacket
1813 ptrTDStruct - TD_STRUCT
1814 bEnable - TRUE is Enanble FALSE is Disable
1823 // TRUE means enable short packet detection mechanism.
1825 ptrTDStruct
->TDData
.TDStatusSPD
= (bEnable
? 1 : 0);
1829 SetTDControlErrorCounter (
1830 IN TD_STRUCT
*ptrTDStruct
,
1835 Routine Description:
1837 Set TD Control ErrorCounter
1841 ptrTDStruct - TD_STRUCT
1842 nMaxErrors - Error counter number
1851 // valid value of nMaxErrors is 0,1,2,3
1853 if (nMaxErrors
> 3) {
1857 ptrTDStruct
->TDData
.TDStatusErr
= nMaxErrors
;
1862 SetTDLoworFullSpeedDevice (
1863 IN TD_STRUCT
*ptrTDStruct
,
1864 IN BOOLEAN bLowSpeedDevice
1868 // TRUE means the TD is targeting at a Low-speed device
1870 ptrTDStruct
->TDData
.TDStatusLS
= (bLowSpeedDevice
? 1 : 0);
1874 SetTDControlIsochronousorNot (
1875 IN TD_STRUCT
*ptrTDStruct
,
1876 IN BOOLEAN IsIsochronous
1880 // TRUE means the TD belongs to Isochronous transfer type.
1882 ptrTDStruct
->TDData
.TDStatusIOS
= (IsIsochronous
? 1 : 0);
1886 SetorClearTDControlIOC (
1887 IN TD_STRUCT
*ptrTDStruct
,
1892 // If this bit is set, it indicates that the host controller should issue
1893 // an interrupt on completion of the frame in which this TD is executed.
1895 ptrTDStruct
->TDData
.TDStatusIOC
= IsSet
? 1 : 0;
1899 SetTDStatusActiveorInactive (
1900 IN TD_STRUCT
*ptrTDStruct
,
1905 // If this bit is set, it indicates that the TD is active and can be
1909 ptrTDStruct
->TDData
.TDStatus
|= 0x80;
1911 ptrTDStruct
->TDData
.TDStatus
&= 0x7F;
1916 SetTDTokenMaxLength (
1917 IN TD_STRUCT
*ptrTDStruct
,
1918 IN UINT16 MaximumLength
1922 // Specifies the maximum number of data bytes allowed for the transfer.
1923 // the legal value extent is 0 ~ 0x500.
1925 if (MaximumLength
> 0x500) {
1926 MaximumLength
= 0x500;
1928 ptrTDStruct
->TDData
.TDTokenMaxLen
= MaximumLength
- 1;
1930 return MaximumLength
;
1934 SetTDTokenDataToggle1 (
1935 IN TD_STRUCT
*ptrTDStruct
1939 // Set the data toggle bit to DATA1
1941 ptrTDStruct
->TDData
.TDTokenDataToggle
= 1;
1945 SetTDTokenDataToggle0 (
1946 IN TD_STRUCT
*ptrTDStruct
1950 // Set the data toggle bit to DATA0
1952 ptrTDStruct
->TDData
.TDTokenDataToggle
= 0;
1956 GetTDTokenDataToggle (
1957 IN TD_STRUCT
*ptrTDStruct
1961 // Get the data toggle value.
1963 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenDataToggle
);
1967 SetTDTokenEndPoint (
1968 IN TD_STRUCT
*ptrTDStruct
,
1973 // Set EndPoint Number the TD is targeting at.
1975 ptrTDStruct
->TDData
.TDTokenEndPt
= (UINT8
) EndPoint
;
1979 SetTDTokenDeviceAddress (
1980 IN TD_STRUCT
*ptrTDStruct
,
1981 IN UINTN DeviceAddress
1985 // Set Device Address the TD is targeting at.
1987 ptrTDStruct
->TDData
.TDTokenDevAddr
= (UINT8
) DeviceAddress
;
1991 SetTDTokenPacketID (
1992 IN TD_STRUCT
*ptrTDStruct
,
1997 // Set the Packet Identification to be used for this transaction.
1999 ptrTDStruct
->TDData
.TDTokenPID
= PID
;
2004 IN TD_STRUCT
*ptrTDStruct
2008 // Set the beginning address of the data buffer that will be used
2009 // during the transaction.
2011 ptrTDStruct
->TDData
.TDBufferPtr
= (UINT32
) ((UINTN
) (ptrTDStruct
->pTDBuffer
));
2016 IN TD_STRUCT
*ptrTDStruct
2022 // Detect whether the TD is active.
2024 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2025 return (BOOLEAN
) (TDStatus
& 0x80);
2030 IN TD_STRUCT
*ptrTDStruct
2036 // Detect whether the device/endpoint addressed by this TD is stalled.
2038 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2039 return (BOOLEAN
) (TDStatus
& 0x40);
2043 IsTDStatusBufferError (
2044 IN TD_STRUCT
*ptrTDStruct
2049 // Detect whether Data Buffer Error is happened.
2051 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2052 return (BOOLEAN
) (TDStatus
& 0x20);
2056 IsTDStatusBabbleError (
2057 IN TD_STRUCT
*ptrTDStruct
2063 // Detect whether Babble Error is happened.
2065 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2066 return (BOOLEAN
) (TDStatus
& 0x10);
2070 IsTDStatusNAKReceived (
2071 IN TD_STRUCT
*ptrTDStruct
2077 // Detect whether NAK is received.
2079 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2080 return (BOOLEAN
) (TDStatus
& 0x08);
2084 IsTDStatusCRCTimeOutError (
2085 IN TD_STRUCT
*ptrTDStruct
2091 // Detect whether CRC/Time Out Error is encountered.
2093 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2094 return (BOOLEAN
) (TDStatus
& 0x04);
2098 IsTDStatusBitStuffError (
2099 IN TD_STRUCT
*ptrTDStruct
2105 // Detect whether Bitstuff Error is received.
2107 TDStatus
= (UINT8
) (ptrTDStruct
->TDData
.TDStatus
);
2108 return (BOOLEAN
) (TDStatus
& 0x02);
2112 GetTDStatusActualLength (
2113 IN TD_STRUCT
*ptrTDStruct
2117 // Retrieve the actual number of bytes that were tansferred.
2118 // the value is encoded as n-1. so return the decoded value.
2120 return (UINT16
) ((ptrTDStruct
->TDData
.TDStatusActualLength
) + 1);
2124 GetTDTokenMaxLength (
2125 IN TD_STRUCT
*ptrTDStruct
2129 // Retrieve the maximum number of data bytes allowed for the trnasfer.
2131 return (UINT16
) ((ptrTDStruct
->TDData
.TDTokenMaxLen
) + 1);
2135 GetTDTokenEndPoint (
2136 IN TD_STRUCT
*ptrTDStruct
2140 // Retrieve the endpoint number the transaction is targeting at.
2142 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenEndPt
);
2146 GetTDTokenDeviceAddress (
2147 IN TD_STRUCT
*ptrTDStruct
2151 // Retrieve the device address the transaction is targeting at.
2153 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenDevAddr
);
2157 GetTDTokenPacketID (
2158 IN TD_STRUCT
*ptrTDStruct
2162 // Retrieve the Packet Identification information.
2164 return (UINT8
) (ptrTDStruct
->TDData
.TDTokenPID
);
2169 IN TD_STRUCT
*ptrTDStruct
2173 // Retrieve the beginning address of the data buffer
2174 // that involved in this transaction.
2176 return ptrTDStruct
->pTDBuffer
;
2180 GetTDLinkPtrValidorInvalid (
2181 IN TD_STRUCT
*ptrTDStruct
2185 // Retrieve the information of whether the Link Pointer field
2188 if (ptrTDStruct
->TDData
.TDLinkPtrTerminate
) {
2198 IN TD_STRUCT
*PtrFirstTD
2204 // Count the queued TDs number.
2209 ptr
= (TD_STRUCT
*) ptr
->ptrNextTD
;
2220 IN QH_STRUCT
*PtrQH
,
2225 Routine Description:
2239 if (PtrQH
== NULL
|| PtrTD
== NULL
) {
2243 // Validate QH Vertical Ptr field
2245 SetQHVerticalValidorInvalid (PtrQH
, TRUE
);
2248 // Vertical Ptr pointing to TD structure
2250 SetQHVerticalQHorTDSelect (PtrQH
, FALSE
);
2252 SetQHVerticalLinkPtr (PtrQH
, (VOID
*) PtrTD
);
2254 PtrQH
->ptrDown
= (VOID
*) PtrTD
;
2259 IN TD_STRUCT
*ptrPreTD
,
2264 Routine Description:
2270 ptrPreTD - Previous TD_STRUCT to be linked
2271 PtrTD - TD_STRUCT to link
2278 if (ptrPreTD
== NULL
|| PtrTD
== NULL
) {
2282 // Depth first fashion
2284 SetTDLinkPtrDepthorBreadth (ptrPreTD
, TRUE
);
2287 // Link pointer pointing to TD struct
2289 SetTDLinkPtrQHorTDSelect (ptrPreTD
, FALSE
);
2292 // Validate the link pointer valid bit
2294 SetTDLinkPtrValidorInvalid (ptrPreTD
, TRUE
);
2296 SetTDLinkPtr (ptrPreTD
, PtrTD
);
2298 ptrPreTD
->ptrNextTD
= (VOID
*) PtrTD
;
2301 // Transfer Schedule related Helper Functions
2304 SetorClearCurFrameListTerminate (
2305 IN FRAMELIST_ENTRY
*pCurEntry
,
2310 // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.
2312 pCurEntry
->FrameListPtrTerminate
= (IsSet
? 1 : 0);
2316 SetCurFrameListQHorTD (
2317 IN FRAMELIST_ENTRY
*pCurEntry
,
2322 // This bit indicates to the hardware whether the item referenced by the
2323 // link pointer is a TD or a QH.
2325 pCurEntry
->FrameListPtrQSelect
= (IsQH
? 1 : 0);
2329 IsCurFrameListQHorTD (
2330 IN FRAMELIST_ENTRY
*pCurEntry
2337 return (BOOLEAN
) (pCurEntry
->FrameListPtrQSelect
);
2341 GetCurFrameListTerminate (
2342 IN FRAMELIST_ENTRY
*pCurEntry
2346 // TRUE means the frame is empty,
2347 // FALSE means the link pointer field is valid.
2349 return (BOOLEAN
) (pCurEntry
->FrameListPtrTerminate
);
2353 SetCurFrameListPointer (
2354 IN FRAMELIST_ENTRY
*pCurEntry
,
2359 // Set the pointer field of the frame.
2361 pCurEntry
->FrameListPtr
= (UINT32
) ((UINTN
) ptr
>> 4);
2365 GetCurFrameListPointer (
2366 IN FRAMELIST_ENTRY
*pCurEntry
2370 // Get the link pointer of the frame.
2372 return (VOID
*) ((UINTN
) (pCurEntry
->FrameListPtr
<< 4));
2378 IN FRAMELIST_ENTRY
*pEntry
,
2379 IN UINT16 FrameListIndex
,
2384 Routine Description:
2386 Link QH To Frame List
2390 pEntry - FRAMELIST_ENTRY
2391 FrameListIndex - Frame List Index
2399 FRAMELIST_ENTRY
*pCurFrame
;
2401 QH_STRUCT
*NextTempQH
;
2406 // Get frame list entry that the link process will begin from.
2408 pCurFrame
= pEntry
+ FrameListIndex
;
2411 // if current frame is empty
2412 // then link the specified QH directly to the Frame List.
2414 if (GetCurFrameListTerminate (pCurFrame
)) {
2417 // Link new QH to the frame list entry.
2419 SetCurFrameListQHorTD (pCurFrame
, TRUE
);
2421 SetCurFrameListPointer (pCurFrame
, (UINT8
*) PtrQH
);
2424 // clear T bit in the Frame List, indicating that the frame list entry
2425 // is no longer empty.
2427 SetorClearCurFrameListTerminate (pCurFrame
, FALSE
);
2433 // current frame list has link pointer
2435 if (!IsCurFrameListQHorTD (pCurFrame
)) {
2437 // a TD is linked to the framelist entry
2439 TempTD
= (TD_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2441 while (GetTDLinkPtrValidorInvalid (TempTD
)) {
2443 if (IsTDLinkPtrQHOrTD (TempTD
)) {
2445 // QH linked next to the TD
2450 TempTD
= (TD_STRUCT
*) GetTDLinkPtr (TempTD
);
2454 // either no ptr linked next to the TD or QH is linked next to the TD
2456 if (!GetTDLinkPtrValidorInvalid (TempTD
)) {
2459 // no ptr linked next to the TD
2461 TempTD
->ptrNextQH
= PtrQH
;
2462 SetTDLinkPtrQHorTDSelect (TempTD
, TRUE
);
2463 SetTDLinkPtr (TempTD
, PtrQH
);
2464 SetTDLinkPtrValidorInvalid (TempTD
, TRUE
);
2469 // QH is linked next to the TD
2471 TempQH
= (QH_STRUCT
*) GetTDLinkPtr (TempTD
);
2475 // a QH is linked to the framelist entry
2477 TempQH
= (QH_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2486 // Avoid the same qh repeated linking in one frame entry
2488 if (TempQH
== PtrQH
) {
2493 // if current QH has next QH connected
2495 while (GetQHHorizontalValidorInvalid (TempQH
)) {
2497 // Get next QH pointer
2499 NextTempQH
= (QH_STRUCT
*) GetQHHorizontalLinkPtr (TempQH
);
2502 // Bulk transfer qh may be self-linked,
2503 // so, the code below is to aVOID dead-loop when meeting self-linked qh
2505 if (NextTempQH
== TempQH
) {
2510 TempQH
= NextTempQH
;
2513 // Avoid the same qh repeated linking in one frame entry
2515 if (TempQH
== PtrQH
) {
2521 TempQH
->ptrNext
= PtrQH
;
2522 SetQHHorizontalQHorTDSelect (TempQH
, TRUE
);
2523 SetQHHorizontalLinkPtr (TempQH
, PtrQH
);
2524 SetQHHorizontalValidorInvalid (TempQH
, TRUE
);
2532 ExecuteControlTransfer (
2533 IN USB_HC_DEV
*HcDev
,
2534 IN TD_STRUCT
*PtrTD
,
2536 OUT UINTN
*ActualLen
,
2538 OUT UINT32
*TransferResult
2542 Routine Description:
2544 Execute Control Transfer
2551 ActualLen - Actual transfered Len
2552 TimeOut - TimeOut value in milliseconds
2553 TransferResult - Transfer result
2556 EFI_SUCCESS - Sucess
2557 EFI_DEVICE_ERROR - Error
2565 BOOLEAN TransferFinished
;
2568 *TransferResult
= EFI_USB_NOERROR
;
2569 RequiredLen
= *ActualLen
;
2572 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2575 TransferFinished
= CheckTDsResults (
2583 if (TransferFinished
) {
2588 // TD is inactive, which means the control transfer is end.
2590 if ((*TransferResult
& EFI_USB_ERR_NOTEXECUTE
) != EFI_USB_ERR_NOTEXECUTE
) {
2598 if (*TransferResult
!= EFI_USB_NOERROR
) {
2599 return EFI_DEVICE_ERROR
;
2606 ExecBulkorSyncInterruptTransfer (
2607 IN USB_HC_DEV
*HcDev
,
2608 IN TD_STRUCT
*PtrTD
,
2610 OUT UINTN
*ActualLen
,
2611 OUT UINT8
*DataToggle
,
2613 OUT UINT32
*TransferResult
2617 Routine Description:
2619 Execute Bulk or SyncInterrupt Transfer
2626 ActualLen - Actual transfered Len
2627 DataToggle - Data Toggle
2628 TimeOut - TimeOut value in milliseconds
2629 TransferResult - Transfer result
2632 EFI_SUCCESS - Sucess
2633 EFI_DEVICE_ERROR - Error
2640 BOOLEAN TransferFinished
;
2643 *TransferResult
= EFI_USB_NOERROR
;
2644 RequiredLen
= *ActualLen
;
2647 Delay
= (TimeOut
* STALL_1_MILLI_SECOND
/ 50) + 1;
2651 TransferFinished
= CheckTDsResults (
2659 if (TransferFinished
) {
2664 // TD is inactive, which means bulk or interrupt transfer's end.
2666 if ((*TransferResult
& EFI_USB_ERR_NOTEXECUTE
) != EFI_USB_ERR_NOTEXECUTE
) {
2677 if (*TransferResult
!= EFI_USB_NOERROR
) {
2680 // scroll the Data Toggle back to the last success TD
2682 ScrollNum
= CountTDsNumber (PtrTD
) - ErrTDPos
;
2683 if (ScrollNum
& 0x1) {
2687 return EFI_DEVICE_ERROR
;
2695 IN USB_HC_DEV
*HcDev
,
2696 IN QH_STRUCT
*PtrQH
,
2697 IN UINT16 FrameListIndex
,
2698 IN BOOLEAN SearchOther
,
2703 Routine Description:
2705 Unlink from frame list and delete single QH
2710 FrameListIndex - Frame List Index
2711 SearchOther - Search Other QH
2712 Delete - TRUE is to delete the QH
2717 FRAMELIST_ENTRY
*pCurFrame
;
2721 QH_STRUCT
*CurrentQH
;
2723 TD_STRUCT
*CurrentTD
;
2731 if (PtrQH
== NULL
) {
2739 BeginFrame
= FrameListIndex
;
2740 EndFrame
= FrameListIndex
+ 1;
2743 for (Index
= BeginFrame
; Index
< EndFrame
; Index
++) {
2745 pCurFrame
= HcDev
->FrameListEntry
+ (Index
& 0x3FF);
2747 if (GetCurFrameListTerminate (pCurFrame
)) {
2749 // current frame list is empty,search next frame list entry
2754 if (!IsCurFrameListQHorTD (pCurFrame
)) {
2756 // TD linked to current framelist
2758 CurrentTD
= (TD_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2760 while (GetTDLinkPtrValidorInvalid (CurrentTD
)) {
2762 if (IsTDLinkPtrQHOrTD (CurrentTD
)) {
2764 // QH linked next to the TD,break while ()
2769 CurrentTD
= (TD_STRUCT
*) GetTDLinkPtr (CurrentTD
);
2772 if (!GetTDLinkPtrValidorInvalid (CurrentTD
)) {
2774 // no QH linked next to the last TD,
2775 // search next frame list
2781 // a QH linked next to the last TD
2783 CurrentQH
= (QH_STRUCT
*) GetTDLinkPtr (CurrentTD
);
2785 PtrPreQH
= CurrentTD
;
2789 // a QH linked to current framelist
2791 CurrentQH
= (QH_STRUCT
*) GetCurFrameListPointer (pCurFrame
);
2796 if (CurrentQH
== PtrQH
) {
2798 if (GetQHHorizontalValidorInvalid (PtrQH
)) {
2800 // there is QH connected after the QH found
2803 // retrieve nex qh pointer of the qh found.
2805 NextQH
= GetQHHorizontalLinkPtr (PtrQH
);
2812 // QH linked to a TD struct
2814 CurrentTD
= (TD_STRUCT
*) PtrPreQH
;
2816 SetTDLinkPtrValidorInvalid (CurrentTD
, (BOOLEAN
) ((NextQH
== NULL
) ? FALSE
: TRUE
));
2817 SetTDLinkPtr (CurrentTD
, NextQH
);
2818 CurrentTD
->ptrNextQH
= NextQH
;
2822 // QH linked directly to current framelist entry
2824 SetorClearCurFrameListTerminate (pCurFrame
, (BOOLEAN
) ((NextQH
== NULL
) ? TRUE
: FALSE
));
2825 SetCurFrameListPointer (pCurFrame
, (UINT8
*) NextQH
);
2830 // search next framelist entry
2835 while (GetQHHorizontalValidorInvalid (CurrentQH
)) {
2837 PtrPreQH
= CurrentQH
;
2839 // Get next horizontal linked QH
2841 CurrentQH
= (QH_STRUCT
*) GetQHHorizontalLinkPtr (CurrentQH
);
2845 if (CurrentQH
== PtrQH
) {
2851 // search next frame list entry
2853 if (CurrentQH
!= PtrQH
) {
2860 // find the specified qh, then delink it from
2861 // the horizontal QH list in the frame entry.
2864 if (GetQHHorizontalValidorInvalid (PtrQH
)) {
2866 // there is QH connected after the QH found
2869 // retrieve nex qh pointer of the qh found.
2871 NextQH
= GetQHHorizontalLinkPtr (PtrQH
);
2875 // NO QH connected after the QH found
2879 // NULL the previous QH's link ptr and set Terminate field.
2881 SetQHHorizontalValidorInvalid ((QH_STRUCT
*) PtrPreQH
, FALSE
);
2884 SetQHHorizontalLinkPtr ((QH_STRUCT
*) PtrPreQH
, NextQH
);
2885 ((QH_STRUCT
*) PtrPreQH
)->ptrNext
= NextQH
;
2890 if (Found
&& Delete
) {
2892 // free memory once used by the specific QH
2894 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
2903 IN USB_HC_DEV
*HcDev
,
2904 IN TD_STRUCT
*PtrFirstTD
2907 Routine Description:
2913 PtrFirstTD - TD link list head
2925 // Delete all the TDs in a queue.
2931 if (!GetTDLinkPtrValidorInvalid (Tptr2
)) {
2935 Tptr1
= GetTDLinkPtr (Tptr2
);
2938 // TD link to itself
2940 if (Tptr1
== Tptr2
) {
2945 UhciFreePool (HcDev
, (UINT8
*) Tptr2
, sizeof (TD_STRUCT
));
2952 InsertQHTDToINTList (
2953 IN USB_HC_DEV
*HcDev
,
2954 IN QH_STRUCT
*PtrQH
,
2955 IN TD_STRUCT
*PtrFirstTD
,
2956 IN UINT8 DeviceAddress
,
2957 IN UINT8 EndPointAddress
,
2958 IN UINT8 DataToggle
,
2959 IN UINTN DataLength
,
2960 IN UINTN PollingInterval
,
2962 IN UINT8
*DataBuffer
,
2963 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction
,
2967 Routine Description:
2968 Insert QH and TD To Interrupt List
2973 PtrFirstTD - First TD_STRUCT
2974 DeviceAddress - Device Address
2975 EndPointAddress - EndPoint Address
2976 DataToggle - Data Toggle
2977 DataLength - Data length
2978 PollingInterval - Polling Interval when inserted to frame list
2979 Mapping - Mapping alue
2980 DataBuffer - Data buffer
2981 CallBackFunction- CallBackFunction after interrupt transfeer
2982 Context - CallBackFunction Context passed as function parameter
2984 EFI_SUCCESS - Sucess
2985 EFI_INVALID_PARAMETER - Paremeter is error
2989 INTERRUPT_LIST
*Node
;
2991 Node
= AllocatePool (sizeof (INTERRUPT_LIST
));
2999 Node
->Signature
= INTERRUPT_LIST_SIGNATURE
;
3000 Node
->DevAddr
= DeviceAddress
;
3001 Node
->EndPoint
= EndPointAddress
;
3002 Node
->PtrQH
= PtrQH
;
3003 Node
->PtrFirstTD
= PtrFirstTD
;
3004 Node
->DataToggle
= DataToggle
;
3005 Node
->DataLen
= DataLength
;
3006 Node
->PollInterval
= PollingInterval
;
3007 Node
->Mapping
= Mapping
;
3009 // DataBuffer is allocated host memory, not mapped memory
3011 Node
->DataBuffer
= DataBuffer
;
3012 Node
->InterruptCallBack
= CallBackFunction
;
3013 Node
->InterruptContext
= Context
;
3016 // insert the new interrupt transfer to the head of the list.
3017 // The interrupt transfer's monitor function scans the whole list from head
3018 // to tail. The new interrupt transfer MUST be added to the head of the list
3019 // for the sake of error recovery.
3021 InsertHeadList (&(HcDev
->InterruptListHead
), &(Node
->Link
));
3028 DeleteAsyncINTQHTDs (
3029 IN USB_HC_DEV
*HcDev
,
3030 IN UINT8 DeviceAddress
,
3031 IN UINT8 EndPointAddress
,
3032 OUT UINT8
*DataToggle
3035 Routine Description:
3037 Delete Async INT QH and TDs
3041 DeviceAddress - Device Address
3042 EndPointAddress - EndPoint Address
3043 DataToggle - Data Toggle
3046 EFI_SUCCESS - Sucess
3047 EFI_INVALID_PARAMETER - Paremeter is error
3052 QH_STRUCT
*ptrNextQH
;
3055 INTERRUPT_LIST
*MatchList
;
3056 INTERRUPT_LIST
*PtrList
;
3068 // no interrupt transaction exists
3070 if (IsListEmpty (&(HcDev
->InterruptListHead
))) {
3071 return EFI_INVALID_PARAMETER
;
3074 // find the correct QH-TD that need to delete
3075 // (by matching Device address and EndPoint number to match QH-TD )
3078 Link
= &(HcDev
->InterruptListHead
);
3081 Link
= Link
->ForwardLink
;
3082 PtrList
= INTERRUPT_LIST_FROM_LINK (Link
);
3084 if ((PtrList
->DevAddr
== DeviceAddress
) && ((PtrList
->EndPoint
& 0x0f) == (EndPointAddress
& 0x0f))) {
3085 MatchList
= PtrList
;
3091 } while (Link
->ForwardLink
!= &(HcDev
->InterruptListHead
));
3094 return EFI_INVALID_PARAMETER
;
3097 // get current endpoint's data toggle bit and save.
3099 ExecuteAsyncINTTDs (HcDev
, MatchList
, &Result
, &ErrTDPos
, &ActualLen
);
3100 UpdateAsyncINTQHTDs (MatchList
, Result
, (UINT32
) ErrTDPos
);
3101 *DataToggle
= MatchList
->DataToggle
;
3103 MatchTD
= MatchList
->PtrFirstTD
;
3104 MatchQH
= MatchList
->PtrQH
;
3106 // find the first matching QH position in the FrameList
3110 ptrNextQH
= MatchQH
->ptrNextIntQH
;
3113 // Search all the entries
3115 DelLinkSingleQH (HcDev
, MatchQH
, 0, TRUE
, TRUE
);
3117 MatchQH
= ptrNextQH
;
3121 // Call PciIo->Unmap() to unmap the busmaster read/write
3123 HcDev
->PciIo
->Unmap (HcDev
->PciIo
, MatchList
->Mapping
);
3126 // free host data buffer allocated,
3127 // mapped data buffer is freed by Unmap
3129 if (MatchList
->DataBuffer
!= NULL
) {
3130 gBS
->FreePool (MatchList
->DataBuffer
);
3134 // at last delete the TDs, to aVOID problems
3136 DeleteQueuedTDs (HcDev
, MatchTD
);
3139 // remove Match node from interrupt list
3141 RemoveEntryList (&(MatchList
->Link
));
3142 gBS
->FreePool (MatchList
);
3148 IN TD_STRUCT
*PtrTD
,
3149 IN UINTN RequiredLen
,
3151 OUT UINTN
*ErrTDPos
,
3152 OUT UINTN
*ActualTransferSize
3156 Routine Description:
3162 PtrTD - TD_STRUCT to check
3163 RequiredLen - Required Len
3164 Result - Transfer result
3165 ErrTDPos - Error TD Position
3166 ActualTransferSize - Actual Transfer Size
3177 *Result
= EFI_USB_NOERROR
;
3183 *ActualTransferSize
= 0;
3187 if (IsTDStatusActive (PtrTD
)) {
3188 *Result
|= EFI_USB_ERR_NOTEXECUTE
;
3191 if (IsTDStatusStalled (PtrTD
)) {
3192 *Result
|= EFI_USB_ERR_STALL
;
3195 if (IsTDStatusBufferError (PtrTD
)) {
3196 *Result
|= EFI_USB_ERR_BUFFER
;
3199 if (IsTDStatusBabbleError (PtrTD
)) {
3200 *Result
|= EFI_USB_ERR_BABBLE
;
3203 if (IsTDStatusNAKReceived (PtrTD
)) {
3204 *Result
|= EFI_USB_ERR_NAK
;
3207 if (IsTDStatusCRCTimeOutError (PtrTD
)) {
3208 *Result
|= EFI_USB_ERR_TIMEOUT
;
3211 if (IsTDStatusBitStuffError (PtrTD
)) {
3212 *Result
|= EFI_USB_ERR_BITSTUFF
;
3216 // if any error encountered, stop processing the left TDs.
3222 Len
= GetTDStatusActualLength (PtrTD
) & 0x7FF;
3223 *ActualTransferSize
+= Len
;
3225 if (*ActualTransferSize
<= RequiredLen
&& Len
< PtrTD
->TDData
.TDTokenMaxLen
) {
3227 // transter finished and actural length less than required length
3232 // Accumulate actual transferred data length in each TD.
3234 PtrTD
= (TD_STRUCT
*) (PtrTD
->ptrNextTD
);
3236 // Record the first Error TD's position in the queue,
3237 // this value is zero-based.
3248 ExecuteAsyncINTTDs (
3249 IN USB_HC_DEV
*HcDev
,
3250 IN INTERRUPT_LIST
*PtrList
,
3252 OUT UINTN
*ErrTDPos
,
3253 OUT UINTN
*ActualLen
3257 Routine Description:
3259 Execute Async Interrupt TDs
3264 PtrList - INTERRUPT_LIST
3265 Result - Transfer result
3266 ErrTDPos - Error TD Position
3267 ActualTransferSize - Actual Transfer Size
3276 // *ErrTDPos is zero-based value, indicating the first error TD's position
3277 // in the TDs' sequence.
3278 // *ErrTDPos value is only valid when *Result is not equal NOERROR.
3282 RequiredLen
= *ActualLen
;
3283 CheckTDsResults (PtrList
->PtrFirstTD
, RequiredLen
, Result
, ErrTDPos
, ActualLen
);
3290 UpdateAsyncINTQHTDs (
3291 IN INTERRUPT_LIST
*PtrList
,
3297 Routine Description:
3299 Update Async Interrupt QH and TDs
3303 PtrList - INTERRUPT_LIST
3304 Result - Transfer reslut
3305 ErrTDPos - Error TD Position
3313 QH_STRUCT
*PtrFirstQH
;
3315 TD_STRUCT
*PtrFirstTD
;
3320 PtrFirstQH
= PtrList
->PtrQH
;
3321 PtrFirstTD
= PtrList
->PtrFirstTD
;
3325 if (Result
== EFI_USB_NOERROR
) {
3329 DataToggle
= GetTDTokenDataToggle (PtrTD
);
3330 PtrTD
= PtrTD
->ptrNextTD
;
3334 // save current DataToggle value to interrupt list.
3335 // this value is used for tracing the interrupt endpoint DataToggle.
3336 // when this interrupt transfer is deleted, the last DataToggle is saved
3338 PtrList
->DataToggle
= DataToggle
;
3343 // Since DataToggle bit should toggle after each success transaction,
3344 // the First TD's DataToggle bit will be updated to XOR of Last TD's
3345 // DataToggle bit. If the First TD's DataToggle bit is not equal Last
3346 // TD's DataToggle bit, that means it already be the XOR of Last TD's,
3347 // so no update is needed.
3349 if (DataToggle
== GetTDTokenDataToggle (PtrFirstTD
)) {
3355 SetTDTokenDataToggle1 (PtrTD
);
3357 SetTDTokenDataToggle0 (PtrTD
);
3360 PtrTD
= PtrTD
->ptrNextTD
;
3364 // restore Link Pointer of QH to First TD
3365 // (because QH's Link Pointer will change during TD execution)
3370 LinkTDToQH (PtrQH
, PtrFirstTD
);
3371 PtrQH
= PtrQH
->ptrNextIntQH
;
3375 // set all the TDs active
3379 SetTDStatusActiveorInactive (PtrTD
, TRUE
);
3380 PtrTD
= PtrTD
->ptrNextTD
;
3383 } else if (((Result
& EFI_USB_ERR_NOTEXECUTE
) == EFI_USB_ERR_NOTEXECUTE
) ||
3384 ((Result
& EFI_USB_ERR_NAK
) == EFI_USB_ERR_NAK
)
3395 // not first TD error
3397 if (ErrTDPos
!= 0) {
3399 // get the last success TD
3401 for (Index
= 1; Index
< ErrTDPos
; Index
++) {
3402 PtrTD
= PtrTD
->ptrNextTD
;
3405 // update Data Toggle in the interrupt list node
3407 PtrList
->DataToggle
= GetTDTokenDataToggle (PtrTD
);
3412 PtrTD
= PtrTD
->ptrNextTD
;
3415 PtrList
->DataToggle
= GetTDTokenDataToggle (PtrTD
);
3418 // do not restore the QH's vertical link pointer,
3419 // let the callback function do the rest of error handling.
3427 ReleaseInterruptList (
3428 IN USB_HC_DEV
*HcDev
,
3429 IN LIST_ENTRY
*ListHead
3433 Routine Description:
3435 Release Interrupt List
3439 ListHead - List head
3448 LIST_ENTRY
*SavedLink
;
3449 INTERRUPT_LIST
*pNode
;
3451 TD_STRUCT
*ptrNextTD
;
3455 if (ListHead
== NULL
) {
3462 // Free all the resources in the interrupt list
3464 SavedLink
= Link
->ForwardLink
;
3465 while (!IsListEmpty (ListHead
)) {
3469 SavedLink
= Link
->ForwardLink
;
3471 pNode
= INTERRUPT_LIST_FROM_LINK (Link
);
3473 RemoveEntryList (&pNode
->Link
);
3475 SavedQH
= pNode
->PtrQH
;
3476 for (PtrQH
= SavedQH
; PtrQH
!= NULL
; PtrQH
= SavedQH
) {
3477 SavedQH
= PtrQH
->ptrNextIntQH
;
3478 UhciFreePool (HcDev
, (UINT8
*) PtrQH
, sizeof (QH_STRUCT
));
3481 PtrTD
= pNode
->PtrFirstTD
;
3482 while (PtrTD
!= NULL
) {
3484 ptrNextTD
= PtrTD
->ptrNextTD
;
3485 UhciFreePool (HcDev
, (UINT8
*) PtrTD
, sizeof (TD_STRUCT
));
3489 gBS
->FreePool (pNode
);
3495 InitializeMemoryManagement (
3496 IN USB_HC_DEV
*HcDev
3500 Routine Description:
3502 Initialize Memory Management
3510 EFI_SUCCESS - Success
3513 MEMORY_MANAGE_HEADER
*MemoryHeader
;
3517 MemPages
= NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES
;
3518 Status
= CreateMemoryBlock (HcDev
, &MemoryHeader
, MemPages
);
3519 if (EFI_ERROR (Status
)) {
3523 HcDev
->MemoryHeader
= MemoryHeader
;
3530 IN USB_HC_DEV
*HcDev
,
3531 OUT MEMORY_MANAGE_HEADER
**MemoryHeader
,
3532 IN UINTN MemoryBlockSizeInPages
3536 Routine Description:
3538 Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
3539 and use PciIo->Map to map the common buffer for Bus Master Read/Write.
3545 MemoryHeader - MEMORY_MANAGE_HEADER to output
3546 MemoryBlockSizeInPages - MemoryBlockSizeInPages
3549 EFI_SUCCESS - Success
3554 EFI_PHYSICAL_ADDRESS MappedAddress
;
3555 UINTN MemoryBlockSizeInBytes
;
3559 // Allocate memory for MemoryHeader
3561 *MemoryHeader
= AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER
));
3562 if (*MemoryHeader
== NULL
) {
3563 return EFI_OUT_OF_RESOURCES
;
3566 (*MemoryHeader
)->Next
= NULL
;
3569 // set Memory block size
3571 (*MemoryHeader
)->MemoryBlockSizeInBytes
= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
);
3574 // each bit in Bit Array will manage 32 bytes memory in memory block
3576 (*MemoryHeader
)->BitArraySizeInBytes
= ((*MemoryHeader
)->MemoryBlockSizeInBytes
/ 32) / 8;
3579 // Allocate memory for BitArray
3581 (*MemoryHeader
)->BitArrayPtr
= AllocateZeroPool ((*MemoryHeader
)->BitArraySizeInBytes
);
3582 if ((*MemoryHeader
)->BitArrayPtr
== NULL
) {
3583 gBS
->FreePool (*MemoryHeader
);
3584 return EFI_OUT_OF_RESOURCES
;
3588 // Memory Block uses MemoryBlockSizeInPages pages,
3589 // and it is allocated as common buffer use.
3591 Status
= HcDev
->PciIo
->AllocateBuffer (
3594 EfiBootServicesData
,
3595 MemoryBlockSizeInPages
,
3599 if (EFI_ERROR (Status
)) {
3600 gBS
->FreePool ((*MemoryHeader
)->BitArrayPtr
);
3601 gBS
->FreePool (*MemoryHeader
);
3605 MemoryBlockSizeInBytes
= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
);
3606 Status
= HcDev
->PciIo
->Map (
3608 EfiPciIoOperationBusMasterCommonBuffer
,
3610 &MemoryBlockSizeInBytes
,
3615 // if returned Mapped size is less than the size we request,do not support.
3617 if (EFI_ERROR (Status
) || (MemoryBlockSizeInBytes
!= EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
))) {
3618 HcDev
->PciIo
->FreeBuffer (HcDev
->PciIo
, MemoryBlockSizeInPages
, CommonBuffer
);
3619 gBS
->FreePool ((*MemoryHeader
)->BitArrayPtr
);
3620 gBS
->FreePool (*MemoryHeader
);
3621 return EFI_UNSUPPORTED
;
3624 // Set Memory block initial address
3626 (*MemoryHeader
)->MemoryBlockPtr
= (UINT8
*) ((UINTN
) MappedAddress
);
3627 (*MemoryHeader
)->Mapping
= Mapping
;
3630 (*MemoryHeader
)->MemoryBlockPtr
,
3631 EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages
)