3 The UHCI register operation routines.
5 Copyright (c) 2007 - 2008, Intel Corporation
6 All rights reserved. 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.
169 EFI_PHYSICAL_ADDRESS PhyAddr
;
172 Len
= sizeof (UHCI_TD_HW
);
173 Status
= Uhc
->PciIo
->Map (
175 EfiPciIoOperationBusMasterRead
,
182 ASSERT (!EFI_ERROR (Status
) && (Qh
!= NULL
) && (Td
!= NULL
));
184 Qh
->QhHw
.VerticalLink
= QH_VLINK (PhyAddr
, FALSE
);
185 Qh
->TDs
= (VOID
*) Td
;
190 Unlink TD from the QH.
192 @param Qh The queue head to unlink from.
193 @param Td The TD to unlink.
202 ASSERT ((Qh
!= NULL
) && (Td
!= NULL
));
204 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
210 Append a new TD To the previous TD.
212 @param Uhc The UHCI device.
213 @param PrevTd Previous UHCI_TD_SW to be linked to.
214 @param ThisTd TD to link.
220 IN UHCI_TD_SW
*PrevTd
,
221 IN UHCI_TD_SW
*ThisTd
226 EFI_PHYSICAL_ADDRESS PhyAddr
;
229 Len
= sizeof (UHCI_TD_HW
);
230 Status
= Uhc
->PciIo
->Map (
232 EfiPciIoOperationBusMasterRead
,
239 ASSERT (!EFI_ERROR (Status
) && (PrevTd
!= NULL
) && (ThisTd
!= NULL
));
241 PrevTd
->TdHw
.NextLink
= TD_LINK (PhyAddr
, TRUE
, FALSE
);
242 PrevTd
->NextTd
= (VOID
*) ThisTd
;
247 Delete a list of TDs.
249 @param Uhc The UHCI device.
250 @param FirstTd TD link list head.
258 IN UHCI_TD_SW
*FirstTd
266 while (NextTd
!= NULL
) {
268 NextTd
= ThisTd
->NextTd
;
269 UsbHcFreeMem (Uhc
->MemPool
, ThisTd
, sizeof (UHCI_TD_SW
));
275 Create an initialize a new queue head.
277 @param Uhc The UHCI device.
278 @param Interval The polling interval for the queue.
280 @return The newly created queue header.
291 Qh
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_QH_SW
));
297 Qh
->QhHw
.HorizonLink
= QH_HLINK (NULL
, TRUE
);
298 Qh
->QhHw
.VerticalLink
= QH_VLINK (NULL
, TRUE
);
299 Qh
->Interval
= UhciConvertPollRate(Interval
);
308 Create and intialize a TD.
310 @param Uhc The UHCI device.
312 @return The newly allocated and initialized TD.
322 Td
= UsbHcAllocateMem (Uhc
->MemPool
, sizeof (UHCI_TD_SW
));
336 Create and initialize a TD for Setup Stage of a control transfer.
338 @param Uhc The UHCI device.
339 @param DevAddr Device address.
340 @param Request A pointer to cpu memory address of Device request.
341 @param RequestPhy A pointer to pci memory address of Device request.
342 @param IsLow Full speed or low speed.
344 @return The created setup Td Pointer.
352 IN UINT8
*RequestPhy
,
358 Td
= UhciCreateTd (Uhc
);
364 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
365 Td
->TdHw
.ShortPacket
= FALSE
;
366 Td
->TdHw
.IsIsoch
= FALSE
;
367 Td
->TdHw
.IntOnCpl
= FALSE
;
368 Td
->TdHw
.ErrorCount
= 0x03;
369 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
370 Td
->TdHw
.DataToggle
= 0;
371 Td
->TdHw
.EndPoint
= 0;
372 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
373 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
374 Td
->TdHw
.MaxPacketLen
= (UINT32
) (sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
375 Td
->TdHw
.PidCode
= SETUP_PACKET_ID
;
376 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) RequestPhy
;
379 Td
->DataLen
= sizeof (EFI_USB_DEVICE_REQUEST
);
386 Create a TD for data.
388 @param Uhc The UHCI device.
389 @param DevAddr Device address.
390 @param Endpoint Endpoint number.
391 @param DataPtr A pointer to cpu memory address of Data buffer.
392 @param DataPhyPtr A pointer to pci memory address of Data buffer.
393 @param Len Data length.
394 @param PktId Packet ID.
395 @param Toggle Data toggle value.
396 @param IsLow Full speed or low speed.
398 @return Data Td pointer if success, otherwise NULL.
407 IN UINT8
*DataPhyPtr
,
417 // Code as length - 1, and the max valid length is 0x500
419 ASSERT (Len
<= 0x500);
421 Td
= UhciCreateTd (Uhc
);
427 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
428 Td
->TdHw
.ShortPacket
= FALSE
;
429 Td
->TdHw
.IsIsoch
= FALSE
;
430 Td
->TdHw
.IntOnCpl
= FALSE
;
431 Td
->TdHw
.ErrorCount
= 0X03;
432 Td
->TdHw
.Status
= USBTD_ACTIVE
;
433 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
434 Td
->TdHw
.DataToggle
= Toggle
& 0x01;
435 Td
->TdHw
.EndPoint
= Endpoint
& 0x0F;
436 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
437 Td
->TdHw
.MaxPacketLen
= (UINT32
) (Len
- 1);
438 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
439 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) DataPhyPtr
;
442 Td
->DataLen
= (UINT16
) Len
;
449 Create TD for the Status Stage of control transfer.
451 @param Uhc The UHCI device.
452 @param DevAddr Device address.
453 @param PktId Packet ID.
454 @param IsLow Full speed or low speed.
456 @return Status Td Pointer.
469 Td
= UhciCreateTd (Uhc
);
475 Td
->TdHw
.NextLink
= TD_LINK (NULL
, TRUE
, TRUE
);
476 Td
->TdHw
.ShortPacket
= FALSE
;
477 Td
->TdHw
.IsIsoch
= FALSE
;
478 Td
->TdHw
.IntOnCpl
= FALSE
;
479 Td
->TdHw
.ErrorCount
= 0x03;
480 Td
->TdHw
.Status
|= USBTD_ACTIVE
;
481 Td
->TdHw
.MaxPacketLen
= 0x7FF; //0x7FF: there is no data (refer to UHCI spec)
482 Td
->TdHw
.DataToggle
= 1;
483 Td
->TdHw
.EndPoint
= 0;
484 Td
->TdHw
.LowSpeed
= IsLow
? 1 : 0;
485 Td
->TdHw
.DeviceAddr
= DevAddr
& 0x7F;
486 Td
->TdHw
.PidCode
= (UINT8
) PktId
;
487 Td
->TdHw
.DataBuffer
= (UINT32
) (UINTN
) NULL
;
497 Create Tds list for Control Transfer.
499 @param Uhc The UHCI device.
500 @param DeviceAddr The device address.
501 @param DataPktId Packet Identification of Data Tds.
502 @param Request A pointer to cpu memory address of request structure buffer to transfer.
503 @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.
504 @param Data A pointer to cpu memory address of user data buffer to transfer.
505 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
506 @param DataLen Length of user data to transfer.
507 @param MaxPacket Maximum packet size for control transfer.
508 @param IsLow Full speed or low speed.
510 @return The Td list head for the control transfer.
519 IN UINT8
*RequestPhy
,
528 UHCI_TD_SW
*FirstDataTd
;
530 UHCI_TD_SW
*PrevDataTd
;
531 UHCI_TD_SW
*StatusTd
;
544 // Create setup packets for the transfer
546 SetupTd
= UhciCreateSetupTd (Uhc
, DeviceAddr
, Request
, RequestPhy
, IsLow
);
548 if (SetupTd
== NULL
) {
553 // Create data packets for the transfer
557 while (DataLen
> 0) {
559 // PktSize is the data load size in each Td.
561 ThisTdLen
= (DataLen
> MaxPacket
? MaxPacket
: DataLen
);
563 DataTd
= UhciCreateDataTd (
567 Data
, //cpu memory address
568 DataPhy
, //Pci memory address
575 if (DataTd
== NULL
) {
579 if (FirstDataTd
== NULL
) {
580 FirstDataTd
= DataTd
;
581 FirstDataTd
->NextTd
= NULL
;
583 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
589 DataPhy
+= ThisTdLen
;
590 DataLen
-= ThisTdLen
;
594 // Status packet is on the opposite direction to data packets
596 if (OUTPUT_PACKET_ID
== DataPktId
) {
597 StatusPktId
= INPUT_PACKET_ID
;
599 StatusPktId
= OUTPUT_PACKET_ID
;
602 StatusTd
= UhciCreateStatusTd (Uhc
, DeviceAddr
, StatusPktId
, IsLow
);
604 if (StatusTd
== NULL
) {
609 // Link setup Td -> data Tds -> status Td together
611 if (FirstDataTd
!= NULL
) {
612 UhciAppendTd (Uhc
, SetupTd
, FirstDataTd
);
613 UhciAppendTd (Uhc
, PrevDataTd
, StatusTd
);
615 UhciAppendTd (Uhc
, SetupTd
, StatusTd
);
621 if (SetupTd
!= NULL
) {
622 UhciDestoryTds (Uhc
, SetupTd
);
625 if (FirstDataTd
!= NULL
) {
626 UhciDestoryTds (Uhc
, FirstDataTd
);
634 Create Tds list for Bulk/Interrupt Transfer.
636 @param Uhc USB_HC_DEV.
637 @param DevAddr Address of Device.
638 @param EndPoint Endpoint Number.
639 @param PktId Packet Identification of Data Tds.
640 @param Data A pointer to cpu memory address of user data buffer to transfer.
641 @param DataPhy A pointer to pci memory address of user data buffer to transfer.
642 @param DataLen Length of user data to transfer.
643 @param DataToggle Data Toggle Pointer.
644 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.
645 @param IsLow Is Low Speed Device.
647 @return The Tds list head for the bulk transfer.
651 UhciCreateBulkOrIntTds (
659 IN OUT UINT8
*DataToggle
,
665 UHCI_TD_SW
*FirstDataTd
;
666 UHCI_TD_SW
*PrevDataTd
;
674 // Create data packets for the transfer
676 while (DataLen
> 0) {
678 // PktSize is the data load size that each Td.
682 if (DataLen
> MaxPacket
) {
683 ThisTdLen
= MaxPacket
;
686 DataTd
= UhciCreateDataTd (
698 if (DataTd
== NULL
) {
702 if (PktId
== INPUT_PACKET_ID
) {
703 DataTd
->TdHw
.ShortPacket
= TRUE
;
706 if (FirstDataTd
== NULL
) {
707 FirstDataTd
= DataTd
;
708 FirstDataTd
->NextTd
= NULL
;
710 UhciAppendTd (Uhc
, PrevDataTd
, DataTd
);
716 DataPhy
+= ThisTdLen
;
717 DataLen
-= ThisTdLen
;
723 if (FirstDataTd
!= NULL
) {
724 UhciDestoryTds (Uhc
, FirstDataTd
);