3 Copyright (c) 2007, 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.
18 The UHCI register operation routines.
29 Map address of request structure buffer
31 @param Uhc The UHCI device
32 @param Request The user request buffer
33 @param MappedAddr Mapped address of request
34 @param Map Identificaion of this mapping to return
36 @return EFI_SUCCESS : Success
37 @return EFI_DEVICE_ERROR : Fail to map the user request
44 OUT UINT8
**MappedAddr
,
50 EFI_PHYSICAL_ADDRESS PhyAddr
;
52 Len
= sizeof (EFI_USB_DEVICE_REQUEST
);
53 Status
= Uhc
->PciIo
->Map (
55 EfiPciIoOperationBusMasterRead
,
62 if (!EFI_ERROR (Status
)) {
63 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
71 Map address of user data buffer
73 @param Uhc The UHCI device
74 @param Direction direction of the data transfer
75 @param Data The user data buffer
76 @param Len Length of the user data
77 @param PktId Packet identificaion
78 @param MappedAddr mapped address to return
79 @param Map identificaion of this mapping to return
81 @return EFI_SUCCESS : Success
82 @return EFI_DEVICE_ERROR : Fail to map the user data
88 IN EFI_USB_DATA_DIRECTION Direction
,
92 OUT UINT8
**MappedAddr
,
97 EFI_PHYSICAL_ADDRESS PhyAddr
;
104 // BusMasterWrite means cpu read
106 *PktId
= INPUT_PACKET_ID
;
107 Status
= Uhc
->PciIo
->Map (
109 EfiPciIoOperationBusMasterWrite
,
116 if (EFI_ERROR (Status
)) {
120 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
124 *PktId
= OUTPUT_PACKET_ID
;
125 Status
= Uhc
->PciIo
->Map (
127 EfiPciIoOperationBusMasterRead
,
134 if (EFI_ERROR (Status
)) {
138 *MappedAddr
= (UINT8
*) (UINTN
) PhyAddr
;
142 if ((Len
!= NULL
) && (*Len
!= 0)) {
143 Status
= EFI_INVALID_PARAMETER
;
147 *PktId
= OUTPUT_PACKET_ID
;
154 Status
= EFI_INVALID_PARAMETER
;
166 @param Qh The queue head for the TD to link to
167 @param Td The TD to link
178 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
180 Qh
->QhHw
.VerticalLink
= QH_VLINK (Td
, FALSE
);
181 Qh
->TDs
= (VOID
*) Td
;
186 Unlink TD from the QH
188 @param Qh The queue head to unlink from
189 @param Td The TD to unlink
200 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
202 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
208 Append a new TD To the previous TD
210 @param PrevTd Previous UHCI_TD_SW to be linked to
211 @param ThisTd TD to link
219 IN UHCI_TD_SW
*PrevTd
,
220 IN UHCI_TD_SW
*ThisTd
223 ASSERT ((PrevTd
!= NULL
) && (ThisTd
!= NULL
));
225 PrevTd
->TdHw
.NextLink
= TD_LINK (ThisTd
, TRUE
, FALSE
);
226 PrevTd
->NextTd
= (VOID
*) ThisTd
;
233 @param Uhc The UHCI device
234 @param FirstTd TD link list head
242 IN UHCI_TD_SW
*FirstTd
250 while (NextTd
!= NULL
) {
252 NextTd
= ThisTd
->NextTd
;
253 UsbHcFreeMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_SW
));
259 Create an initialize a new queue head
261 @param Uhc The UHCI device
262 @param Interval The polling interval for the queue
264 @return The newly created queue header
275 Qh
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_QH_SW
));
281 Qh
->QhHw
.HorizonLink
= QH_HLINK (NULL
, TRUE
);
282 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
283 Qh
->Interval
= Interval
;
292 Create and intialize a TD
294 @param Uhc The UHCI device
296 @return The newly allocated and initialized TD
307 Td
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_TD_SW
));
312 Td
->TdHw
.NextLink
= TD_LINK (NULL
, FALSE
, TRUE
);
322 Create and initialize a TD for Setup Stage of a control transfer
324 @param Uhc The UHCI device
325 @param DevAddr Device address
326 @param Request Device request
327 @param IsLow Full speed or low speed
329 @return The created setup Td Pointer
343 Td
= UhciCreateTd (Uhc
);
349 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
350 Td
->TdHw
.ShortPacket
= FALSE
;
351 Td
->TdHw
.IsIsoch
= FALSE
;
352 Td
->TdHw
.IntOnCpl
= FALSE
;
353 Td
->TdHw
.ErrorCount
= 0x03;
354 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
355 Td
->TdHw
.DataToggle
= 0;
356 Td
->TdHw
.EndPoint
= 0;
357 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
358 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
359 Td
->TdHw
.MaxPacketLen
= (UINT32
) (sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
360 Td
->TdHw
.PidCode
= SETUP_PACKET_ID
;
361 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) Request
;
364 Td
->DataLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
373 @param Uhc The UHCI device
374 @param DevAddr Device address
375 @param Endpoint Endpoint number
376 @param DataPtr Data buffer
377 @param Len Data length
378 @param PktId Packet ID
379 @param Toggle Data toggle value
380 @param IsLow Full speed or low speed
382 @return Data Td pointer if success, otherwise NUL
401 // Code as length - 1, and the max valid length is 0x500
403 ASSERT (Len
<= 0x500);
405 Td
= UhciCreateTd (Uhc
);
411 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
412 Td
->TdHw
.ShortPacket
= FALSE
;
413 Td
->TdHw
.IsIsoch
= FALSE
;
414 Td
->TdHw
.IntOnCpl
= FALSE
;
415 Td
->TdHw
.ErrorCount
= 0X03;
416 Td
->TdHw
.Status
= USBTD_ACTIVE
;
417 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
418 Td
->TdHw
.DataToggle
= Toggle
& 0x01;
419 Td
->TdHw
.EndPoint
= Endpoint
& 0x0F;
420 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
421 Td
->TdHw
.MaxPacketLen
= (UINT32
) (Len
- 1);
422 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
423 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) DataPtr
;
426 Td
->DataLen
= (UINT16
) Len
;
433 Create TD for the Status Stage of control transfer
435 @param Uhc The UHCI device
436 @param DevAddr Device address
437 @param PktId Packet ID
438 @param IsLow Full speed or low speed
440 @return Status Td Pointer
454 Td
= UhciCreateTd (Uhc
);
460 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
461 Td
->TdHw
.ShortPacket
= FALSE
;
462 Td
->TdHw
.IsIsoch
= FALSE
;
463 Td
->TdHw
.IntOnCpl
= FALSE
;
464 Td
->TdHw
.ErrorCount
= 0x03;
465 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
466 Td
->TdHw
.MaxPacketLen
= 0x7FF; //0x7FF: there is no data (refer to UHCI spec)
467 Td
->TdHw
.DataToggle
= 1;
468 Td
->TdHw
.EndPoint
= 0;
469 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
470 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
471 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
472 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) NULL
;
482 Create Tds list for Control Transfer
484 @param Uhc The UHCI device
485 @param DeviceAddr The device address
486 @param DataPktId Packet Identification of Data Tds
487 @param Request A pointer to request structure buffer to transfer
488 @param Data A pointer to user data buffer to transfer
489 @param DataLen Length of user data to transfer
490 @param MaxPacket Maximum packet size for control transfer
491 @param IsLow Full speed or low speed
493 @return The Td list head for the control transfer
509 UHCI_TD_SW
*FirstDataTd
;
511 UHCI_TD_SW
*PrevDataTd
;
512 UHCI_TD_SW
*StatusTd
;
525 // Create setup packets for the transfer
527 SetupTd
= UhciCreateSetupTd (Uhc
, DeviceAddr
, Request
, IsLow
);
529 if (SetupTd
== NULL
) {
534 // Create data packets for the transfer
538 while (DataLen
> 0) {
540 // PktSize is the data load size in each Td.
542 ThisTdLen
= (DataLen
> MaxPacket
? MaxPacket
: DataLen
);
544 DataTd
= UhciCreateDataTd (
555 if (DataTd
== NULL
) {
559 if (FirstDataTd
== NULL
) {
560 FirstDataTd
= DataTd
;
561 FirstDataTd
->NextTd
= NULL
;
563 UhciAppendTd (PrevDataTd
, DataTd
);
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 (SetupTd
, FirstDataTd
);
592 UhciAppendTd (PrevDataTd
, StatusTd
);
594 UhciAppendTd (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 user data buffer to transfer
620 @param DataLen Length of user data to transfer
621 @param DataToggle Data Toggle Pointer
622 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer
623 @param IsLow Is Low Speed Device
625 @return The Tds list head for the bulk transfer
629 UhciCreateBulkOrIntTds (
636 IN OUT UINT8
*DataToggle
,
642 UHCI_TD_SW
*FirstDataTd
;
643 UHCI_TD_SW
*PrevDataTd
;
651 // Create data packets for the transfer
653 while (DataLen
> 0) {
655 // PktSize is the data load size that each Td.
659 if (DataLen
> MaxPacket
) {
660 ThisTdLen
= MaxPacket
;
663 DataTd
= UhciCreateDataTd (
674 if (DataTd
== NULL
) {
678 if (PktId
== INPUT_PACKET_ID
) {
679 DataTd
->TdHw
.ShortPacket
= TRUE
;
682 if (FirstDataTd
== NULL
) {
683 FirstDataTd
= DataTd
;
684 FirstDataTd
->NextTd
= NULL
;
686 UhciAppendTd (PrevDataTd
, DataTd
);
692 DataLen
-= ThisTdLen
;
698 if (FirstDataTd
!= NULL
) {
699 UhciDestoryTds (Uhc
, FirstDataTd
);