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
14 Map address of request structure buffer.
16 @param Uhc The UHCI device.
17 @param Request The user request buffer.
18 @param MappedAddr Mapped address of request.
19 @param Map Identificaion of this mapping to return.
21 @return EFI_SUCCESS Success.
22 @return EFI_DEVICE_ERROR Fail to map the user request.
29 OUT UINT8
**MappedAddr
,
35 EFI_PHYSICAL_ADDRESS PhyAddr
;
37 Len
= sizeof (EFI_USB_DEVICE_REQUEST
);
38 Status
= Uhc
->PciIo
->Map (
40 EfiPciIoOperationBusMasterRead
,
47 if (!EFI_ERROR (Status
)) {
48 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
56 Map address of user data buffer.
58 @param Uhc The UHCI device.
59 @param Direction Direction of the data transfer.
60 @param Data The user data buffer.
61 @param Len Length of the user data.
62 @param PktId Packet identificaion.
63 @param MappedAddr Mapped address to return.
64 @param Map Identificaion of this mapping to return.
66 @return EFI_SUCCESS Success.
67 @return EFI_DEVICE_ERROR Fail to map the user data.
73 IN EFI_USB_DATA_DIRECTION Direction
,
77 OUT UINT8
**MappedAddr
,
82 EFI_PHYSICAL_ADDRESS PhyAddr
;
89 // BusMasterWrite means cpu read
91 *PktId
= INPUT_PACKET_ID
;
92 Status
= Uhc
->PciIo
->Map (
94 EfiPciIoOperationBusMasterWrite
,
101 if (EFI_ERROR (Status
)) {
105 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
109 *PktId
= OUTPUT_PACKET_ID
;
110 Status
= Uhc
->PciIo
->Map (
112 EfiPciIoOperationBusMasterRead
,
119 if (EFI_ERROR (Status
)) {
123 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
127 if ((Len
!= NULL
) && (*Len
!= 0)) {
128 Status
= EFI_INVALID_PARAMETER
;
132 *PktId
= OUTPUT_PACKET_ID
;
138 Status
= EFI_INVALID_PARAMETER
;
149 @param Uhc The UHCI device.
150 @param Qh The queue head for the TD to link to.
151 @param Td The TD to link.
161 EFI_PHYSICAL_ADDRESS PhyAddr
;
163 PhyAddr
= UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, Td
, sizeof (UHCI_TD_HW
));
165 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
167 Qh
->QhHw
.VerticalLink
= QH_VLINK (PhyAddr
, FALSE
);
168 Qh
->TDs
= (VOID
*) Td
;
173 Unlink TD from the QH.
175 @param Qh The queue head to unlink from.
176 @param Td The TD to unlink.
185 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
187 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
193 Append a new TD To the previous TD.
195 @param Uhc The UHCI device.
196 @param PrevTd Previous UHCI_TD_SW to be linked to.
197 @param ThisTd TD to link.
203 IN UHCI_TD_SW
*PrevTd
,
204 IN UHCI_TD_SW
*ThisTd
207 EFI_PHYSICAL_ADDRESS PhyAddr
;
209 PhyAddr
= UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_HW
));
211 ASSERT ((PrevTd
!= NULL
) && (ThisTd
!= NULL
));
213 PrevTd
->TdHw
.NextLink
= TD_LINK (PhyAddr
, TRUE
, FALSE
);
214 PrevTd
->NextTd
= (VOID
*) ThisTd
;
219 Delete a list of TDs.
221 @param Uhc The UHCI device.
222 @param FirstTd TD link list head.
230 IN UHCI_TD_SW
*FirstTd
238 while (NextTd
!= NULL
) {
240 NextTd
= ThisTd
->NextTd
;
241 UsbHcFreeMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_SW
));
247 Create an initialize a new queue head.
249 @param Uhc The UHCI device.
250 @param Interval The polling interval for the queue.
252 @return The newly created queue header.
263 Qh
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_QH_SW
));
269 Qh
->QhHw
.HorizonLink
= QH_HLINK (NULL
, TRUE
);
270 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
271 Qh
->Interval
= UhciConvertPollRate(Interval
);
280 Create and intialize a TD.
282 @param Uhc The UHCI device.
284 @return The newly allocated and initialized TD.
294 Td
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_TD_SW
));
299 Td
->TdHw
.NextLink
= TD_LINK (NULL
, FALSE
, TRUE
);
309 Create and initialize a TD for Setup Stage of a control transfer.
311 @param Uhc The UHCI device.
312 @param DevAddr Device address.
313 @param Request A pointer to cpu memory address of Device request.
314 @param RequestPhy A pointer to pci memory address of Device request.
315 @param IsLow Full speed or low speed.
317 @return The created setup Td Pointer.
325 IN UINT8
*RequestPhy
,
331 Td
= UhciCreateTd (Uhc
);
337 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
338 Td
->TdHw
.ShortPacket
= FALSE
;
339 Td
->TdHw
.IsIsoch
= FALSE
;
340 Td
->TdHw
.IntOnCpl
= FALSE
;
341 Td
->TdHw
.ErrorCount
= 0x03;
342 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
343 Td
->TdHw
.DataToggle
= 0;
344 Td
->TdHw
.EndPoint
= 0;
345 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
346 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
347 Td
->TdHw
.MaxPacketLen
= (UINT32
) (sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
348 Td
->TdHw
.PidCode
= SETUP_PACKET_ID
;
349 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) RequestPhy
;
352 Td
->DataLen
= (UINT16
) sizeof (EFI_USB_DEVICE_REQUEST
);
359 Create a TD for data.
361 @param Uhc The UHCI device.
362 @param DevAddr Device address.
363 @param Endpoint Endpoint number.
364 @param DataPtr A pointer to cpu memory address of Data buffer.
365 @param DataPhyPtr A pointer to pci memory address of Data buffer.
366 @param Len Data length.
367 @param PktId Packet ID.
368 @param Toggle Data toggle value.
369 @param IsLow Full speed or low speed.
371 @return Data Td pointer if success, otherwise NULL.
380 IN UINT8
*DataPhyPtr
,
390 // Code as length - 1, and the max valid length is 0x500
392 ASSERT (Len
<= 0x500);
394 Td
= UhciCreateTd (Uhc
);
400 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
401 Td
->TdHw
.ShortPacket
= FALSE
;
402 Td
->TdHw
.IsIsoch
= FALSE
;
403 Td
->TdHw
.IntOnCpl
= FALSE
;
404 Td
->TdHw
.ErrorCount
= 0x03;
405 Td
->TdHw
.Status
= USBTD_ACTIVE
;
406 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
407 Td
->TdHw
.DataToggle
= Toggle
& 0x01;
408 Td
->TdHw
.EndPoint
= Endpoint
& 0x0F;
409 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
410 Td
->TdHw
.MaxPacketLen
= (UINT32
) (Len
- 1);
411 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
412 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) DataPhyPtr
;
415 Td
->DataLen
= (UINT16
) Len
;
422 Create TD for the Status Stage of control transfer.
424 @param Uhc The UHCI device.
425 @param DevAddr Device address.
426 @param PktId Packet ID.
427 @param IsLow Full speed or low speed.
429 @return Status Td Pointer.
442 Td
= UhciCreateTd (Uhc
);
448 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
449 Td
->TdHw
.ShortPacket
= FALSE
;
450 Td
->TdHw
.IsIsoch
= FALSE
;
451 Td
->TdHw
.IntOnCpl
= FALSE
;
452 Td
->TdHw
.ErrorCount
= 0x03;
453 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
454 Td
->TdHw
.MaxPacketLen
= 0x7FF; //0x7FF: there is no data (refer to UHCI spec)
455 Td
->TdHw
.DataToggle
= 1;
456 Td
->TdHw
.EndPoint
= 0;
457 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
458 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
459 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
460 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) NULL
;
470 Create Tds list for Control Transfer.
472 @param Uhc The UHCI device.
473 @param DeviceAddr The device address.
474 @param DataPktId Packet Identification of Data Tds.
475 @param Request A pointer to cpu memory address of request structure buffer to transfer.
476 @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.
477 @param Data A pointer to cpu memory address of user data buffer to transfer.
478 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
479 @param DataLen Length of user data to transfer.
480 @param MaxPacket Maximum packet size for control transfer.
481 @param IsLow Full speed or low speed.
483 @return The Td list head for the control transfer.
492 IN UINT8
*RequestPhy
,
501 UHCI_TD_SW
*FirstDataTd
;
503 UHCI_TD_SW
*PrevDataTd
;
504 UHCI_TD_SW
*StatusTd
;
517 // Create setup packets for the transfer
519 SetupTd
= UhciCreateSetupTd (Uhc
, DeviceAddr
, Request
, RequestPhy
, IsLow
);
521 if (SetupTd
== NULL
) {
526 // Create data packets for the transfer
530 while (DataLen
> 0) {
532 // PktSize is the data load size in each Td.
534 ThisTdLen
= (DataLen
> MaxPacket
? MaxPacket
: DataLen
);
536 DataTd
= UhciCreateDataTd (
540 Data
, //cpu memory address
541 DataPhy
, //Pci memory address
548 if (DataTd
== NULL
) {
552 if (FirstDataTd
== NULL
) {
553 FirstDataTd
= DataTd
;
554 FirstDataTd
->NextTd
= NULL
;
556 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
562 DataPhy
+= ThisTdLen
;
563 DataLen
-= ThisTdLen
;
567 // Status packet is on the opposite direction to data packets
569 if (OUTPUT_PACKET_ID
== DataPktId
) {
570 StatusPktId
= INPUT_PACKET_ID
;
572 StatusPktId
= OUTPUT_PACKET_ID
;
575 StatusTd
= UhciCreateStatusTd (Uhc
, DeviceAddr
, StatusPktId
, IsLow
);
577 if (StatusTd
== NULL
) {
582 // Link setup Td -> data Tds -> status Td together
584 if (FirstDataTd
!= NULL
) {
585 UhciAppendTd (Uhc
, SetupTd
, FirstDataTd
);
586 UhciAppendTd (Uhc
, PrevDataTd
, StatusTd
);
588 UhciAppendTd (Uhc
, SetupTd
, StatusTd
);
594 if (SetupTd
!= NULL
) {
595 UhciDestoryTds (Uhc
, SetupTd
);
598 if (FirstDataTd
!= NULL
) {
599 UhciDestoryTds (Uhc
, FirstDataTd
);
607 Create Tds list for Bulk/Interrupt Transfer.
609 @param Uhc USB_HC_DEV.
610 @param DevAddr Address of Device.
611 @param EndPoint Endpoint Number.
612 @param PktId Packet Identification of Data Tds.
613 @param Data A pointer to cpu memory address of user data buffer to transfer.
614 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
615 @param DataLen Length of user data to transfer.
616 @param DataToggle Data Toggle Pointer.
617 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.
618 @param IsLow Is Low Speed Device.
620 @return The Tds list head for the bulk transfer.
624 UhciCreateBulkOrIntTds (
632 IN OUT UINT8
*DataToggle
,
638 UHCI_TD_SW
*FirstDataTd
;
639 UHCI_TD_SW
*PrevDataTd
;
647 // Create data packets for the transfer
649 while (DataLen
> 0) {
651 // PktSize is the data load size that each Td.
655 if (DataLen
> MaxPacket
) {
656 ThisTdLen
= MaxPacket
;
659 DataTd
= UhciCreateDataTd (
671 if (DataTd
== NULL
) {
675 if (PktId
== INPUT_PACKET_ID
) {
676 DataTd
->TdHw
.ShortPacket
= TRUE
;
679 if (FirstDataTd
== NULL
) {
680 FirstDataTd
= DataTd
;
681 FirstDataTd
->NextTd
= NULL
;
683 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
689 DataPhy
+= ThisTdLen
;
690 DataLen
-= ThisTdLen
;
696 if (FirstDataTd
!= NULL
) {
697 UhciDestoryTds (Uhc
, FirstDataTd
);