3 The UHCI register operation routines.
5 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 Map address of request structure buffer.
22 @param Uhc The UHCI device.
23 @param Request The user request buffer.
24 @param MappedAddr Mapped address of request.
25 @param Map Identificaion of this mapping to return.
27 @return EFI_SUCCESS Success.
28 @return EFI_DEVICE_ERROR Fail to map the user request.
35 OUT UINT8
**MappedAddr
,
41 EFI_PHYSICAL_ADDRESS PhyAddr
;
43 Len
= sizeof (EFI_USB_DEVICE_REQUEST
);
44 Status
= Uhc
->PciIo
->Map (
46 EfiPciIoOperationBusMasterRead
,
53 if (!EFI_ERROR (Status
)) {
54 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
62 Map address of user data buffer.
64 @param Uhc The UHCI device.
65 @param Direction Direction of the data transfer.
66 @param Data The user data buffer.
67 @param Len Length of the user data.
68 @param PktId Packet identificaion.
69 @param MappedAddr Mapped address to return.
70 @param Map Identificaion of this mapping to return.
72 @return EFI_SUCCESS Success.
73 @return EFI_DEVICE_ERROR Fail to map the user data.
79 IN EFI_USB_DATA_DIRECTION Direction
,
83 OUT UINT8
**MappedAddr
,
88 EFI_PHYSICAL_ADDRESS PhyAddr
;
95 // BusMasterWrite means cpu read
97 *PktId
= INPUT_PACKET_ID
;
98 Status
= Uhc
->PciIo
->Map (
100 EfiPciIoOperationBusMasterWrite
,
107 if (EFI_ERROR (Status
)) {
111 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
115 *PktId
= OUTPUT_PACKET_ID
;
116 Status
= Uhc
->PciIo
->Map (
118 EfiPciIoOperationBusMasterRead
,
125 if (EFI_ERROR (Status
)) {
129 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
133 if ((Len
!= NULL
) && (*Len
!= 0)) {
134 Status
= EFI_INVALID_PARAMETER
;
138 *PktId
= OUTPUT_PACKET_ID
;
144 Status
= EFI_INVALID_PARAMETER
;
155 @param Uhc The UHCI device.
156 @param Qh The queue head for the TD to link to.
157 @param Td The TD to link.
167 EFI_PHYSICAL_ADDRESS PhyAddr
;
169 PhyAddr
= UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, Td
, sizeof (UHCI_TD_HW
));
171 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
173 Qh
->QhHw
.VerticalLink
= QH_VLINK (PhyAddr
, FALSE
);
174 Qh
->TDs
= (VOID
*) Td
;
179 Unlink TD from the QH.
181 @param Qh The queue head to unlink from.
182 @param Td The TD to unlink.
191 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
193 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
199 Append a new TD To the previous TD.
201 @param Uhc The UHCI device.
202 @param PrevTd Previous UHCI_TD_SW to be linked to.
203 @param ThisTd TD to link.
209 IN UHCI_TD_SW
*PrevTd
,
210 IN UHCI_TD_SW
*ThisTd
213 EFI_PHYSICAL_ADDRESS PhyAddr
;
215 PhyAddr
= UsbHcGetPciAddressForHostMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_HW
));
217 ASSERT ((PrevTd
!= NULL
) && (ThisTd
!= NULL
));
219 PrevTd
->TdHw
.NextLink
= TD_LINK (PhyAddr
, TRUE
, FALSE
);
220 PrevTd
->NextTd
= (VOID
*) ThisTd
;
225 Delete a list of TDs.
227 @param Uhc The UHCI device.
228 @param FirstTd TD link list head.
236 IN UHCI_TD_SW
*FirstTd
244 while (NextTd
!= NULL
) {
246 NextTd
= ThisTd
->NextTd
;
247 UsbHcFreeMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_SW
));
253 Create an initialize a new queue head.
255 @param Uhc The UHCI device.
256 @param Interval The polling interval for the queue.
258 @return The newly created queue header.
269 Qh
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_QH_SW
));
275 Qh
->QhHw
.HorizonLink
= QH_HLINK (NULL
, TRUE
);
276 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
277 Qh
->Interval
= UhciConvertPollRate(Interval
);
286 Create and intialize a TD.
288 @param Uhc The UHCI device.
290 @return The newly allocated and initialized TD.
300 Td
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_TD_SW
));
305 Td
->TdHw
.NextLink
= TD_LINK (NULL
, FALSE
, TRUE
);
315 Create and initialize a TD for Setup Stage of a control transfer.
317 @param Uhc The UHCI device.
318 @param DevAddr Device address.
319 @param Request A pointer to cpu memory address of Device request.
320 @param RequestPhy A pointer to pci memory address of Device request.
321 @param IsLow Full speed or low speed.
323 @return The created setup Td Pointer.
331 IN UINT8
*RequestPhy
,
337 Td
= UhciCreateTd (Uhc
);
343 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
344 Td
->TdHw
.ShortPacket
= FALSE
;
345 Td
->TdHw
.IsIsoch
= FALSE
;
346 Td
->TdHw
.IntOnCpl
= FALSE
;
347 Td
->TdHw
.ErrorCount
= 0x03;
348 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
349 Td
->TdHw
.DataToggle
= 0;
350 Td
->TdHw
.EndPoint
= 0;
351 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
352 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
353 Td
->TdHw
.MaxPacketLen
= (UINT32
) (sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
354 Td
->TdHw
.PidCode
= SETUP_PACKET_ID
;
355 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) RequestPhy
;
358 Td
->DataLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
365 Create a TD for data.
367 @param Uhc The UHCI device.
368 @param DevAddr Device address.
369 @param Endpoint Endpoint number.
370 @param DataPtr A pointer to cpu memory address of Data buffer.
371 @param DataPhyPtr A pointer to pci memory address of Data buffer.
372 @param Len Data length.
373 @param PktId Packet ID.
374 @param Toggle Data toggle value.
375 @param IsLow Full speed or low speed.
377 @return Data Td pointer if success, otherwise NULL.
386 IN UINT8
*DataPhyPtr
,
396 // Code as length - 1, and the max valid length is 0x500
398 ASSERT (Len
<= 0x500);
400 Td
= UhciCreateTd (Uhc
);
406 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
407 Td
->TdHw
.ShortPacket
= FALSE
;
408 Td
->TdHw
.IsIsoch
= FALSE
;
409 Td
->TdHw
.IntOnCpl
= FALSE
;
410 Td
->TdHw
.ErrorCount
= 0x03;
411 Td
->TdHw
.Status
= USBTD_ACTIVE
;
412 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
413 Td
->TdHw
.DataToggle
= Toggle
& 0x01;
414 Td
->TdHw
.EndPoint
= Endpoint
& 0x0F;
415 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
416 Td
->TdHw
.MaxPacketLen
= (UINT32
) (Len
- 1);
417 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
418 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) DataPhyPtr
;
421 Td
->DataLen
= (UINT16
) Len
;
428 Create TD for the Status Stage of control transfer.
430 @param Uhc The UHCI device.
431 @param DevAddr Device address.
432 @param PktId Packet ID.
433 @param IsLow Full speed or low speed.
435 @return Status Td Pointer.
448 Td
= UhciCreateTd (Uhc
);
454 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
455 Td
->TdHw
.ShortPacket
= FALSE
;
456 Td
->TdHw
.IsIsoch
= FALSE
;
457 Td
->TdHw
.IntOnCpl
= FALSE
;
458 Td
->TdHw
.ErrorCount
= 0x03;
459 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
460 Td
->TdHw
.MaxPacketLen
= 0x7FF; //0x7FF: there is no data (refer to UHCI spec)
461 Td
->TdHw
.DataToggle
= 1;
462 Td
->TdHw
.EndPoint
= 0;
463 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
464 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
465 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
466 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) NULL
;
476 Create Tds list for Control Transfer.
478 @param Uhc The UHCI device.
479 @param DeviceAddr The device address.
480 @param DataPktId Packet Identification of Data Tds.
481 @param Request A pointer to cpu memory address of request structure buffer to transfer.
482 @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.
483 @param Data A pointer to cpu memory address of user data buffer to transfer.
484 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
485 @param DataLen Length of user data to transfer.
486 @param MaxPacket Maximum packet size for control transfer.
487 @param IsLow Full speed or low speed.
489 @return The Td list head for the control transfer.
498 IN UINT8
*RequestPhy
,
507 UHCI_TD_SW
*FirstDataTd
;
509 UHCI_TD_SW
*PrevDataTd
;
510 UHCI_TD_SW
*StatusTd
;
523 // Create setup packets for the transfer
525 SetupTd
= UhciCreateSetupTd (Uhc
, DeviceAddr
, Request
, RequestPhy
, IsLow
);
527 if (SetupTd
== NULL
) {
532 // Create data packets for the transfer
536 while (DataLen
> 0) {
538 // PktSize is the data load size in each Td.
540 ThisTdLen
= (DataLen
> MaxPacket
? MaxPacket
: DataLen
);
542 DataTd
= UhciCreateDataTd (
546 Data
, //cpu memory address
547 DataPhy
, //Pci memory address
554 if (DataTd
== NULL
) {
558 if (FirstDataTd
== NULL
) {
559 FirstDataTd
= DataTd
;
560 FirstDataTd
->NextTd
= NULL
;
562 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
568 DataPhy
+= ThisTdLen
;
569 DataLen
-= ThisTdLen
;
573 // Status packet is on the opposite direction to data packets
575 if (OUTPUT_PACKET_ID
== DataPktId
) {
576 StatusPktId
= INPUT_PACKET_ID
;
578 StatusPktId
= OUTPUT_PACKET_ID
;
581 StatusTd
= UhciCreateStatusTd (Uhc
, DeviceAddr
, StatusPktId
, IsLow
);
583 if (StatusTd
== NULL
) {
588 // Link setup Td -> data Tds -> status Td together
590 if (FirstDataTd
!= NULL
) {
591 UhciAppendTd (Uhc
, SetupTd
, FirstDataTd
);
592 UhciAppendTd (Uhc
, PrevDataTd
, StatusTd
);
594 UhciAppendTd (Uhc
, SetupTd
, StatusTd
);
600 if (SetupTd
!= NULL
) {
601 UhciDestoryTds (Uhc
, SetupTd
);
604 if (FirstDataTd
!= NULL
) {
605 UhciDestoryTds (Uhc
, FirstDataTd
);
613 Create Tds list for Bulk/Interrupt Transfer.
615 @param Uhc USB_HC_DEV.
616 @param DevAddr Address of Device.
617 @param EndPoint Endpoint Number.
618 @param PktId Packet Identification of Data Tds.
619 @param Data A pointer to cpu memory address of user data buffer to transfer.
620 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
621 @param DataLen Length of user data to transfer.
622 @param DataToggle Data Toggle Pointer.
623 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.
624 @param IsLow Is Low Speed Device.
626 @return The Tds list head for the bulk transfer.
630 UhciCreateBulkOrIntTds (
638 IN OUT UINT8
*DataToggle
,
644 UHCI_TD_SW
*FirstDataTd
;
645 UHCI_TD_SW
*PrevDataTd
;
653 // Create data packets for the transfer
655 while (DataLen
> 0) {
657 // PktSize is the data load size that each Td.
661 if (DataLen
> MaxPacket
) {
662 ThisTdLen
= MaxPacket
;
665 DataTd
= UhciCreateDataTd (
677 if (DataTd
== NULL
) {
681 if (PktId
== INPUT_PACKET_ID
) {
682 DataTd
->TdHw
.ShortPacket
= TRUE
;
685 if (FirstDataTd
== NULL
) {
686 FirstDataTd
= DataTd
;
687 FirstDataTd
->NextTd
= NULL
;
689 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
695 DataPhy
+= ThisTdLen
;
696 DataLen
-= ThisTdLen
;
702 if (FirstDataTd
!= NULL
) {
703 UhciDestoryTds (Uhc
, FirstDataTd
);