3 The UHCI register operation routines.
5 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Map address of request structure buffer.
15 @param Uhc The UHCI device.
16 @param Request The user request buffer.
17 @param MappedAddr Mapped address of request.
18 @param Map Identificaion of this mapping to return.
20 @return EFI_SUCCESS Success.
21 @return EFI_DEVICE_ERROR Fail to map the user request.
28 OUT UINT8
**MappedAddr
,
34 EFI_PHYSICAL_ADDRESS PhyAddr
;
36 Len
= sizeof (EFI_USB_DEVICE_REQUEST
);
37 Status
= Uhc
->PciIo
->Map (
39 EfiPciIoOperationBusMasterRead
,
46 if (!EFI_ERROR (Status
)) {
47 *MappedAddr
= (UINT8
*)(UINTN
)PhyAddr
;
54 Map address of user data buffer.
56 @param Uhc The UHCI device.
57 @param Direction Direction of the data transfer.
58 @param Data The user data buffer.
59 @param Len Length of the user data.
60 @param PktId Packet identificaion.
61 @param MappedAddr Mapped address to return.
62 @param Map Identificaion of this mapping to return.
64 @return EFI_SUCCESS Success.
65 @return EFI_DEVICE_ERROR Fail to map the user data.
71 IN EFI_USB_DATA_DIRECTION Direction
,
75 OUT UINT8
**MappedAddr
,
80 EFI_PHYSICAL_ADDRESS PhyAddr
;
87 // BusMasterWrite means cpu read
89 *PktId
= INPUT_PACKET_ID
;
90 Status
= Uhc
->PciIo
->Map (
92 EfiPciIoOperationBusMasterWrite
,
99 if (EFI_ERROR (Status
)) {
103 *MappedAddr
= (UINT8
*)(UINTN
)PhyAddr
;
107 *PktId
= OUTPUT_PACKET_ID
;
108 Status
= Uhc
->PciIo
->Map (
110 EfiPciIoOperationBusMasterRead
,
117 if (EFI_ERROR (Status
)) {
121 *MappedAddr
= (UINT8
*)(UINTN
)PhyAddr
;
125 if ((Len
!= NULL
) && (*Len
!= 0)) {
126 Status
= EFI_INVALID_PARAMETER
;
130 *PktId
= OUTPUT_PACKET_ID
;
136 Status
= EFI_INVALID_PARAMETER
;
146 @param Uhc The UHCI device.
147 @param Qh The queue head for the TD to link to.
148 @param Td The TD to link.
158 EFI_PHYSICAL_ADDRESS PhyAddr
;
160 PhyAddr
= UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, Td
, sizeof (UHCI_TD_HW
));
162 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
164 Qh
->QhHw
.VerticalLink
= QH_VLINK (PhyAddr
, FALSE
);
165 Qh
->TDs
= (VOID
*)Td
;
169 Unlink TD from the QH.
171 @param Qh The queue head to unlink from.
172 @param Td The TD to unlink.
181 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
183 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
188 Append a new TD To the previous TD.
190 @param Uhc The UHCI device.
191 @param PrevTd Previous UHCI_TD_SW to be linked to.
192 @param ThisTd TD to link.
198 IN UHCI_TD_SW
*PrevTd
,
199 IN UHCI_TD_SW
*ThisTd
202 EFI_PHYSICAL_ADDRESS PhyAddr
;
204 PhyAddr
= UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_HW
));
206 ASSERT ((PrevTd
!= NULL
) && (ThisTd
!= NULL
));
208 PrevTd
->TdHw
.NextLink
= TD_LINK (PhyAddr
, TRUE
, FALSE
);
209 PrevTd
->NextTd
= (VOID
*)ThisTd
;
213 Delete a list of TDs.
215 @param Uhc The UHCI device.
216 @param FirstTd TD link list head.
224 IN UHCI_TD_SW
*FirstTd
232 while (NextTd
!= NULL
) {
234 NextTd
= ThisTd
->NextTd
;
235 UsbHcFreeMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_SW
));
240 Create an initialize a new queue head.
242 @param Uhc The UHCI device.
243 @param Interval The polling interval for the queue.
245 @return The newly created queue header.
256 Qh
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_QH_SW
));
262 Qh
->QhHw
.HorizonLink
= QH_HLINK (NULL
, TRUE
);
263 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
264 Qh
->Interval
= UhciConvertPollRate (Interval
);
272 Create and intialize a TD.
274 @param Uhc The UHCI device.
276 @return The newly allocated and initialized TD.
286 Td
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_TD_SW
));
291 Td
->TdHw
.NextLink
= TD_LINK (NULL
, FALSE
, TRUE
);
300 Create and initialize a TD for Setup Stage of a control transfer.
302 @param Uhc The UHCI device.
303 @param DevAddr Device address.
304 @param Request A pointer to cpu memory address of Device request.
305 @param RequestPhy A pointer to pci memory address of Device request.
306 @param IsLow Full speed or low speed.
308 @return The created setup Td Pointer.
316 IN UINT8
*RequestPhy
,
322 Td
= UhciCreateTd (Uhc
);
328 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
329 Td
->TdHw
.ShortPacket
= FALSE
;
330 Td
->TdHw
.IsIsoch
= FALSE
;
331 Td
->TdHw
.IntOnCpl
= FALSE
;
332 Td
->TdHw
.ErrorCount
= 0x03;
333 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
334 Td
->TdHw
.DataToggle
= 0;
335 Td
->TdHw
.EndPoint
= 0;
336 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
337 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
338 Td
->TdHw
.MaxPacketLen
= (UINT32
)(sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
339 Td
->TdHw
.PidCode
= SETUP_PACKET_ID
;
340 Td
->TdHw
.DataBuffer
= (UINT32
)(UINTN
)RequestPhy
;
343 Td
->DataLen
= (UINT16
)sizeof (EFI_USB_DEVICE_REQUEST
);
349 Create a TD for data.
351 @param Uhc The UHCI device.
352 @param DevAddr Device address.
353 @param Endpoint Endpoint number.
354 @param DataPtr A pointer to cpu memory address of Data buffer.
355 @param DataPhyPtr A pointer to pci memory address of Data buffer.
356 @param Len Data length.
357 @param PktId Packet ID.
358 @param Toggle Data toggle value.
359 @param IsLow Full speed or low speed.
361 @return Data Td pointer if success, otherwise NULL.
370 IN UINT8
*DataPhyPtr
,
380 // Code as length - 1, and the max valid length is 0x500
382 ASSERT (Len
<= 0x500);
384 Td
= UhciCreateTd (Uhc
);
390 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
391 Td
->TdHw
.ShortPacket
= FALSE
;
392 Td
->TdHw
.IsIsoch
= FALSE
;
393 Td
->TdHw
.IntOnCpl
= FALSE
;
394 Td
->TdHw
.ErrorCount
= 0x03;
395 Td
->TdHw
.Status
= USBTD_ACTIVE
;
396 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
397 Td
->TdHw
.DataToggle
= Toggle
& 0x01;
398 Td
->TdHw
.EndPoint
= Endpoint
& 0x0F;
399 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
400 Td
->TdHw
.MaxPacketLen
= (UINT32
)(Len
- 1);
401 Td
->TdHw
.PidCode
= (UINT8
)PktId
;
402 Td
->TdHw
.DataBuffer
= (UINT32
)(UINTN
)DataPhyPtr
;
405 Td
->DataLen
= (UINT16
)Len
;
411 Create TD for the Status Stage of control transfer.
413 @param Uhc The UHCI device.
414 @param DevAddr Device address.
415 @param PktId Packet ID.
416 @param IsLow Full speed or low speed.
418 @return Status Td Pointer.
431 Td
= UhciCreateTd (Uhc
);
437 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
438 Td
->TdHw
.ShortPacket
= FALSE
;
439 Td
->TdHw
.IsIsoch
= FALSE
;
440 Td
->TdHw
.IntOnCpl
= FALSE
;
441 Td
->TdHw
.ErrorCount
= 0x03;
442 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
443 Td
->TdHw
.MaxPacketLen
= 0x7FF; // 0x7FF: there is no data (refer to UHCI spec)
444 Td
->TdHw
.DataToggle
= 1;
445 Td
->TdHw
.EndPoint
= 0;
446 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
447 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
448 Td
->TdHw
.PidCode
= (UINT8
)PktId
;
449 Td
->TdHw
.DataBuffer
= (UINT32
)(UINTN
)NULL
;
458 Create Tds list for Control Transfer.
460 @param Uhc The UHCI device.
461 @param DeviceAddr The device address.
462 @param DataPktId Packet Identification of Data Tds.
463 @param Request A pointer to cpu memory address of request structure buffer to transfer.
464 @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.
465 @param Data A pointer to cpu memory address of user data buffer to transfer.
466 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
467 @param DataLen Length of user data to transfer.
468 @param MaxPacket Maximum packet size for control transfer.
469 @param IsLow Full speed or low speed.
471 @return The Td list head for the control transfer.
480 IN UINT8
*RequestPhy
,
489 UHCI_TD_SW
*FirstDataTd
;
491 UHCI_TD_SW
*PrevDataTd
;
492 UHCI_TD_SW
*StatusTd
;
504 // Create setup packets for the transfer
506 SetupTd
= UhciCreateSetupTd (Uhc
, DeviceAddr
, Request
, RequestPhy
, IsLow
);
508 if (SetupTd
== NULL
) {
513 // Create data packets for the transfer
517 while (DataLen
> 0) {
519 // PktSize is the data load size in each Td.
521 ThisTdLen
= (DataLen
> MaxPacket
? MaxPacket
: DataLen
);
523 DataTd
= UhciCreateDataTd (
527 Data
, // cpu memory address
528 DataPhy
, // Pci memory address
535 if (DataTd
== NULL
) {
539 if (FirstDataTd
== NULL
) {
540 FirstDataTd
= DataTd
;
541 FirstDataTd
->NextTd
= NULL
;
543 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
549 DataPhy
+= ThisTdLen
;
550 DataLen
-= ThisTdLen
;
554 // Status packet is on the opposite direction to data packets
556 if (OUTPUT_PACKET_ID
== DataPktId
) {
557 StatusPktId
= INPUT_PACKET_ID
;
559 StatusPktId
= OUTPUT_PACKET_ID
;
562 StatusTd
= UhciCreateStatusTd (Uhc
, DeviceAddr
, StatusPktId
, IsLow
);
564 if (StatusTd
== NULL
) {
569 // Link setup Td -> data Tds -> status Td together
571 if (FirstDataTd
!= NULL
) {
572 UhciAppendTd (Uhc
, SetupTd
, FirstDataTd
);
573 UhciAppendTd (Uhc
, PrevDataTd
, StatusTd
);
575 UhciAppendTd (Uhc
, SetupTd
, StatusTd
);
581 if (SetupTd
!= NULL
) {
582 UhciDestoryTds (Uhc
, SetupTd
);
585 if (FirstDataTd
!= NULL
) {
586 UhciDestoryTds (Uhc
, FirstDataTd
);
593 Create Tds list for Bulk/Interrupt Transfer.
595 @param Uhc USB_HC_DEV.
596 @param DevAddr Address of Device.
597 @param EndPoint Endpoint Number.
598 @param PktId Packet Identification of Data Tds.
599 @param Data A pointer to cpu memory address of user data buffer to transfer.
600 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
601 @param DataLen Length of user data to transfer.
602 @param DataToggle Data Toggle Pointer.
603 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.
604 @param IsLow Is Low Speed Device.
606 @return The Tds list head for the bulk transfer.
610 UhciCreateBulkOrIntTds (
618 IN OUT UINT8
*DataToggle
,
624 UHCI_TD_SW
*FirstDataTd
;
625 UHCI_TD_SW
*PrevDataTd
;
633 // Create data packets for the transfer
635 while (DataLen
> 0) {
637 // PktSize is the data load size that each Td.
641 if (DataLen
> MaxPacket
) {
642 ThisTdLen
= MaxPacket
;
645 DataTd
= UhciCreateDataTd (
657 if (DataTd
== NULL
) {
661 if (PktId
== INPUT_PACKET_ID
) {
662 DataTd
->TdHw
.ShortPacket
= TRUE
;
665 if (FirstDataTd
== NULL
) {
666 FirstDataTd
= DataTd
;
667 FirstDataTd
->NextTd
= NULL
;
669 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
675 DataPhy
+= ThisTdLen
;
676 DataLen
-= ThisTdLen
;
682 if (FirstDataTd
!= NULL
) {
683 UhciDestoryTds (Uhc
, FirstDataTd
);