]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UhciDxe/UhciQueue.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / UhciQueue.c
CommitLineData
913cb9dc 1/** @file\r
2\r
ab6495ea 3 The UHCI register operation routines.\r
4\r
cd5ebaa0 5Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
913cb9dc 7\r
913cb9dc 8**/\r
9\r
10#include "Uhci.h"\r
11\r
913cb9dc 12/**\r
ab6495ea 13 Map address of request structure buffer.\r
913cb9dc 14\r
ab6495ea 15 @param Uhc The UHCI device.\r
16 @param Request The user request buffer.\r
17 @param MappedAddr Mapped address of request.\r
18 @param Map Identificaion of this mapping to return.\r
913cb9dc 19\r
ab6495ea 20 @return EFI_SUCCESS Success.\r
21 @return EFI_DEVICE_ERROR Fail to map the user request.\r
913cb9dc 22\r
23**/\r
24EFI_STATUS\r
25UhciMapUserRequest (\r
1436aea4
MK
26 IN USB_HC_DEV *Uhc,\r
27 IN OUT VOID *Request,\r
28 OUT UINT8 **MappedAddr,\r
29 OUT VOID **Map\r
913cb9dc 30 )\r
31{\r
32 EFI_STATUS Status;\r
33 UINTN Len;\r
34 EFI_PHYSICAL_ADDRESS PhyAddr;\r
35\r
36 Len = sizeof (EFI_USB_DEVICE_REQUEST);\r
37 Status = Uhc->PciIo->Map (\r
38 Uhc->PciIo,\r
39 EfiPciIoOperationBusMasterRead,\r
40 Request,\r
41 &Len,\r
42 &PhyAddr,\r
43 Map\r
44 );\r
45\r
46 if (!EFI_ERROR (Status)) {\r
1436aea4 47 *MappedAddr = (UINT8 *)(UINTN)PhyAddr;\r
913cb9dc 48 }\r
49\r
50 return Status;\r
51}\r
52\r
913cb9dc 53/**\r
ab6495ea 54 Map address of user data buffer.\r
913cb9dc 55\r
ab6495ea 56 @param Uhc The UHCI device.\r
57 @param Direction Direction of the data transfer.\r
58 @param Data The user data buffer.\r
59 @param Len Length of the user data.\r
60 @param PktId Packet identificaion.\r
61 @param MappedAddr Mapped address to return.\r
62 @param Map Identificaion of this mapping to return.\r
913cb9dc 63\r
ab6495ea 64 @return EFI_SUCCESS Success.\r
65 @return EFI_DEVICE_ERROR Fail to map the user data.\r
913cb9dc 66\r
67**/\r
68EFI_STATUS\r
69UhciMapUserData (\r
70 IN USB_HC_DEV *Uhc,\r
71 IN EFI_USB_DATA_DIRECTION Direction,\r
72 IN VOID *Data,\r
73 IN OUT UINTN *Len,\r
74 OUT UINT8 *PktId,\r
75 OUT UINT8 **MappedAddr,\r
76 OUT VOID **Map\r
77 )\r
78{\r
79 EFI_STATUS Status;\r
80 EFI_PHYSICAL_ADDRESS PhyAddr;\r
81\r
82 Status = EFI_SUCCESS;\r
83\r
84 switch (Direction) {\r
1436aea4
MK
85 case EfiUsbDataIn:\r
86 //\r
87 // BusMasterWrite means cpu read\r
88 //\r
89 *PktId = INPUT_PACKET_ID;\r
90 Status = Uhc->PciIo->Map (\r
91 Uhc->PciIo,\r
92 EfiPciIoOperationBusMasterWrite,\r
93 Data,\r
94 Len,\r
95 &PhyAddr,\r
96 Map\r
97 );\r
98\r
99 if (EFI_ERROR (Status)) {\r
100 goto EXIT;\r
101 }\r
102\r
103 *MappedAddr = (UINT8 *)(UINTN)PhyAddr;\r
104 break;\r
105\r
106 case EfiUsbDataOut:\r
107 *PktId = OUTPUT_PACKET_ID;\r
108 Status = Uhc->PciIo->Map (\r
109 Uhc->PciIo,\r
110 EfiPciIoOperationBusMasterRead,\r
111 Data,\r
112 Len,\r
113 &PhyAddr,\r
114 Map\r
115 );\r
116\r
117 if (EFI_ERROR (Status)) {\r
118 goto EXIT;\r
119 }\r
120\r
121 *MappedAddr = (UINT8 *)(UINTN)PhyAddr;\r
122 break;\r
123\r
124 case EfiUsbNoData:\r
125 if ((Len != NULL) && (*Len != 0)) {\r
126 Status = EFI_INVALID_PARAMETER;\r
127 goto EXIT;\r
128 }\r
129\r
130 *PktId = OUTPUT_PACKET_ID;\r
131 *MappedAddr = NULL;\r
132 *Map = NULL;\r
133 break;\r
134\r
135 default:\r
136 Status = EFI_INVALID_PARAMETER;\r
913cb9dc 137 }\r
138\r
139EXIT:\r
140 return Status;\r
141}\r
142\r
913cb9dc 143/**\r
ab6495ea 144 Link the TD To QH.\r
913cb9dc 145\r
3af875e2 146 @param Uhc The UHCI device.\r
ab6495ea 147 @param Qh The queue head for the TD to link to.\r
148 @param Td The TD to link.\r
913cb9dc 149\r
913cb9dc 150**/\r
151VOID\r
152UhciLinkTdToQh (\r
1436aea4
MK
153 IN USB_HC_DEV *Uhc,\r
154 IN UHCI_QH_SW *Qh,\r
155 IN UHCI_TD_SW *Td\r
913cb9dc 156 )\r
157{\r
3af875e2 158 EFI_PHYSICAL_ADDRESS PhyAddr;\r
3af875e2 159\r
aa91de05 160 PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Td, sizeof (UHCI_TD_HW));\r
3af875e2 161\r
aa91de05 162 ASSERT ((Qh != NULL) && (Td != NULL));\r
913cb9dc 163\r
3af875e2 164 Qh->QhHw.VerticalLink = QH_VLINK (PhyAddr, FALSE);\r
1436aea4 165 Qh->TDs = (VOID *)Td;\r
913cb9dc 166}\r
167\r
913cb9dc 168/**\r
ab6495ea 169 Unlink TD from the QH.\r
913cb9dc 170\r
ab6495ea 171 @param Qh The queue head to unlink from.\r
172 @param Td The TD to unlink.\r
913cb9dc 173\r
913cb9dc 174**/\r
175VOID\r
176UhciUnlinkTdFromQh (\r
1436aea4
MK
177 IN UHCI_QH_SW *Qh,\r
178 IN UHCI_TD_SW *Td\r
913cb9dc 179 )\r
180{\r
181 ASSERT ((Qh != NULL) && (Td != NULL));\r
182\r
183 Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);\r
184 Qh->TDs = NULL;\r
185}\r
186\r
913cb9dc 187/**\r
ab6495ea 188 Append a new TD To the previous TD.\r
913cb9dc 189\r
3af875e2 190 @param Uhc The UHCI device.\r
ab6495ea 191 @param PrevTd Previous UHCI_TD_SW to be linked to.\r
192 @param ThisTd TD to link.\r
913cb9dc 193\r
913cb9dc 194**/\r
913cb9dc 195VOID\r
196UhciAppendTd (\r
1436aea4
MK
197 IN USB_HC_DEV *Uhc,\r
198 IN UHCI_TD_SW *PrevTd,\r
199 IN UHCI_TD_SW *ThisTd\r
913cb9dc 200 )\r
201{\r
3af875e2 202 EFI_PHYSICAL_ADDRESS PhyAddr;\r
913cb9dc 203\r
aa91de05 204 PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, ThisTd, sizeof (UHCI_TD_HW));\r
3af875e2 205\r
aa91de05 206 ASSERT ((PrevTd != NULL) && (ThisTd != NULL));\r
3af875e2 207\r
208 PrevTd->TdHw.NextLink = TD_LINK (PhyAddr, TRUE, FALSE);\r
1436aea4 209 PrevTd->NextTd = (VOID *)ThisTd;\r
913cb9dc 210}\r
211\r
913cb9dc 212/**\r
ab6495ea 213 Delete a list of TDs.\r
913cb9dc 214\r
ab6495ea 215 @param Uhc The UHCI device.\r
216 @param FirstTd TD link list head.\r
913cb9dc 217\r
ab6495ea 218 @return None.\r
913cb9dc 219\r
220**/\r
221VOID\r
222UhciDestoryTds (\r
1436aea4
MK
223 IN USB_HC_DEV *Uhc,\r
224 IN UHCI_TD_SW *FirstTd\r
913cb9dc 225 )\r
226{\r
1436aea4
MK
227 UHCI_TD_SW *NextTd;\r
228 UHCI_TD_SW *ThisTd;\r
913cb9dc 229\r
230 NextTd = FirstTd;\r
231\r
232 while (NextTd != NULL) {\r
1436aea4
MK
233 ThisTd = NextTd;\r
234 NextTd = ThisTd->NextTd;\r
913cb9dc 235 UsbHcFreeMem (Uhc->MemPool, ThisTd, sizeof (UHCI_TD_SW));\r
236 }\r
237}\r
238\r
913cb9dc 239/**\r
ab6495ea 240 Create an initialize a new queue head.\r
913cb9dc 241\r
ab6495ea 242 @param Uhc The UHCI device.\r
243 @param Interval The polling interval for the queue.\r
913cb9dc 244\r
ab6495ea 245 @return The newly created queue header.\r
913cb9dc 246\r
247**/\r
248UHCI_QH_SW *\r
249UhciCreateQh (\r
1436aea4
MK
250 IN USB_HC_DEV *Uhc,\r
251 IN UINTN Interval\r
913cb9dc 252 )\r
253{\r
1436aea4 254 UHCI_QH_SW *Qh;\r
913cb9dc 255\r
256 Qh = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_QH_SW));\r
257\r
258 if (Qh == NULL) {\r
259 return NULL;\r
260 }\r
261\r
262 Qh->QhHw.HorizonLink = QH_HLINK (NULL, TRUE);\r
263 Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);\r
1436aea4 264 Qh->Interval = UhciConvertPollRate (Interval);\r
913cb9dc 265 Qh->TDs = NULL;\r
266 Qh->NextQh = NULL;\r
267\r
268 return Qh;\r
269}\r
270\r
913cb9dc 271/**\r
ab6495ea 272 Create and intialize a TD.\r
913cb9dc 273\r
ab6495ea 274 @param Uhc The UHCI device.\r
913cb9dc 275\r
ab6495ea 276 @return The newly allocated and initialized TD.\r
913cb9dc 277\r
278**/\r
913cb9dc 279UHCI_TD_SW *\r
280UhciCreateTd (\r
1436aea4 281 IN USB_HC_DEV *Uhc\r
913cb9dc 282 )\r
283{\r
1436aea4 284 UHCI_TD_SW *Td;\r
913cb9dc 285\r
1436aea4 286 Td = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_TD_SW));\r
913cb9dc 287 if (Td == NULL) {\r
288 return NULL;\r
289 }\r
290\r
aa91de05 291 Td->TdHw.NextLink = TD_LINK (NULL, FALSE, TRUE);\r
913cb9dc 292 Td->NextTd = NULL;\r
293 Td->Data = NULL;\r
294 Td->DataLen = 0;\r
295\r
296 return Td;\r
297}\r
298\r
913cb9dc 299/**\r
ab6495ea 300 Create and initialize a TD for Setup Stage of a control transfer.\r
913cb9dc 301\r
ab6495ea 302 @param Uhc The UHCI device.\r
303 @param DevAddr Device address.\r
3af875e2 304 @param Request A pointer to cpu memory address of Device request.\r
305 @param RequestPhy A pointer to pci memory address of Device request.\r
ab6495ea 306 @param IsLow Full speed or low speed.\r
913cb9dc 307\r
ab6495ea 308 @return The created setup Td Pointer.\r
913cb9dc 309\r
310**/\r
913cb9dc 311UHCI_TD_SW *\r
312UhciCreateSetupTd (\r
1436aea4
MK
313 IN USB_HC_DEV *Uhc,\r
314 IN UINT8 DevAddr,\r
315 IN UINT8 *Request,\r
316 IN UINT8 *RequestPhy,\r
317 IN BOOLEAN IsLow\r
913cb9dc 318 )\r
319{\r
1436aea4 320 UHCI_TD_SW *Td;\r
913cb9dc 321\r
322 Td = UhciCreateTd (Uhc);\r
323\r
324 if (Td == NULL) {\r
325 return NULL;\r
326 }\r
327\r
328 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);\r
329 Td->TdHw.ShortPacket = FALSE;\r
330 Td->TdHw.IsIsoch = FALSE;\r
331 Td->TdHw.IntOnCpl = FALSE;\r
332 Td->TdHw.ErrorCount = 0x03;\r
333 Td->TdHw.Status |= USBTD_ACTIVE;\r
334 Td->TdHw.DataToggle = 0;\r
335 Td->TdHw.EndPoint = 0;\r
336 Td->TdHw.LowSpeed = IsLow ? 1 : 0;\r
337 Td->TdHw.DeviceAddr = DevAddr & 0x7F;\r
1436aea4 338 Td->TdHw.MaxPacketLen = (UINT32)(sizeof (EFI_USB_DEVICE_REQUEST) - 1);\r
913cb9dc 339 Td->TdHw.PidCode = SETUP_PACKET_ID;\r
1436aea4 340 Td->TdHw.DataBuffer = (UINT32)(UINTN)RequestPhy;\r
913cb9dc 341\r
1436aea4
MK
342 Td->Data = Request;\r
343 Td->DataLen = (UINT16)sizeof (EFI_USB_DEVICE_REQUEST);\r
913cb9dc 344\r
345 return Td;\r
346}\r
347\r
913cb9dc 348/**\r
ab6495ea 349 Create a TD for data.\r
913cb9dc 350\r
ab6495ea 351 @param Uhc The UHCI device.\r
352 @param DevAddr Device address.\r
353 @param Endpoint Endpoint number.\r
3af875e2 354 @param DataPtr A pointer to cpu memory address of Data buffer.\r
355 @param DataPhyPtr A pointer to pci memory address of Data buffer.\r
ab6495ea 356 @param Len Data length.\r
357 @param PktId Packet ID.\r
358 @param Toggle Data toggle value.\r
359 @param IsLow Full speed or low speed.\r
913cb9dc 360\r
ab6495ea 361 @return Data Td pointer if success, otherwise NULL.\r
913cb9dc 362\r
363**/\r
913cb9dc 364UHCI_TD_SW *\r
365UhciCreateDataTd (\r
1436aea4
MK
366 IN USB_HC_DEV *Uhc,\r
367 IN UINT8 DevAddr,\r
368 IN UINT8 Endpoint,\r
369 IN UINT8 *DataPtr,\r
370 IN UINT8 *DataPhyPtr,\r
371 IN UINTN Len,\r
372 IN UINT8 PktId,\r
373 IN UINT8 Toggle,\r
374 IN BOOLEAN IsLow\r
913cb9dc 375 )\r
376{\r
377 UHCI_TD_SW *Td;\r
378\r
379 //\r
380 // Code as length - 1, and the max valid length is 0x500\r
381 //\r
382 ASSERT (Len <= 0x500);\r
383\r
1436aea4 384 Td = UhciCreateTd (Uhc);\r
913cb9dc 385\r
386 if (Td == NULL) {\r
387 return NULL;\r
388 }\r
389\r
390 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);\r
391 Td->TdHw.ShortPacket = FALSE;\r
392 Td->TdHw.IsIsoch = FALSE;\r
393 Td->TdHw.IntOnCpl = FALSE;\r
aa91de05 394 Td->TdHw.ErrorCount = 0x03;\r
913cb9dc 395 Td->TdHw.Status = USBTD_ACTIVE;\r
396 Td->TdHw.LowSpeed = IsLow ? 1 : 0;\r
397 Td->TdHw.DataToggle = Toggle & 0x01;\r
398 Td->TdHw.EndPoint = Endpoint & 0x0F;\r
399 Td->TdHw.DeviceAddr = DevAddr & 0x7F;\r
1436aea4
MK
400 Td->TdHw.MaxPacketLen = (UINT32)(Len - 1);\r
401 Td->TdHw.PidCode = (UINT8)PktId;\r
402 Td->TdHw.DataBuffer = (UINT32)(UINTN)DataPhyPtr;\r
913cb9dc 403\r
1436aea4
MK
404 Td->Data = DataPtr;\r
405 Td->DataLen = (UINT16)Len;\r
913cb9dc 406\r
407 return Td;\r
408}\r
409\r
913cb9dc 410/**\r
ab6495ea 411 Create TD for the Status Stage of control transfer.\r
913cb9dc 412\r
ab6495ea 413 @param Uhc The UHCI device.\r
414 @param DevAddr Device address.\r
415 @param PktId Packet ID.\r
416 @param IsLow Full speed or low speed.\r
913cb9dc 417\r
ab6495ea 418 @return Status Td Pointer.\r
913cb9dc 419\r
420**/\r
913cb9dc 421UHCI_TD_SW *\r
422UhciCreateStatusTd (\r
1436aea4
MK
423 IN USB_HC_DEV *Uhc,\r
424 IN UINT8 DevAddr,\r
425 IN UINT8 PktId,\r
426 IN BOOLEAN IsLow\r
913cb9dc 427 )\r
428{\r
1436aea4 429 UHCI_TD_SW *Td;\r
913cb9dc 430\r
431 Td = UhciCreateTd (Uhc);\r
432\r
433 if (Td == NULL) {\r
434 return NULL;\r
435 }\r
436\r
437 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);\r
438 Td->TdHw.ShortPacket = FALSE;\r
439 Td->TdHw.IsIsoch = FALSE;\r
440 Td->TdHw.IntOnCpl = FALSE;\r
441 Td->TdHw.ErrorCount = 0x03;\r
442 Td->TdHw.Status |= USBTD_ACTIVE;\r
1436aea4 443 Td->TdHw.MaxPacketLen = 0x7FF; // 0x7FF: there is no data (refer to UHCI spec)\r
913cb9dc 444 Td->TdHw.DataToggle = 1;\r
445 Td->TdHw.EndPoint = 0;\r
446 Td->TdHw.LowSpeed = IsLow ? 1 : 0;\r
447 Td->TdHw.DeviceAddr = DevAddr & 0x7F;\r
1436aea4
MK
448 Td->TdHw.PidCode = (UINT8)PktId;\r
449 Td->TdHw.DataBuffer = (UINT32)(UINTN)NULL;\r
913cb9dc 450\r
1436aea4
MK
451 Td->Data = NULL;\r
452 Td->DataLen = 0;\r
913cb9dc 453\r
454 return Td;\r
455}\r
456\r
913cb9dc 457/**\r
ab6495ea 458 Create Tds list for Control Transfer.\r
913cb9dc 459\r
ab6495ea 460 @param Uhc The UHCI device.\r
461 @param DeviceAddr The device address.\r
462 @param DataPktId Packet Identification of Data Tds.\r
3af875e2 463 @param Request A pointer to cpu memory address of request structure buffer to transfer.\r
464 @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.\r
465 @param Data A pointer to cpu memory address of user data buffer to transfer.\r
466 @param DataPhy A pointer to pci memory address of user data buffer to transfer.\r
ab6495ea 467 @param DataLen Length of user data to transfer.\r
468 @param MaxPacket Maximum packet size for control transfer.\r
469 @param IsLow Full speed or low speed.\r
913cb9dc 470\r
ab6495ea 471 @return The Td list head for the control transfer.\r
913cb9dc 472\r
473**/\r
474UHCI_TD_SW *\r
475UhciCreateCtrlTds (\r
1436aea4
MK
476 IN USB_HC_DEV *Uhc,\r
477 IN UINT8 DeviceAddr,\r
478 IN UINT8 DataPktId,\r
479 IN UINT8 *Request,\r
480 IN UINT8 *RequestPhy,\r
481 IN UINT8 *Data,\r
482 IN UINT8 *DataPhy,\r
483 IN UINTN DataLen,\r
484 IN UINT8 MaxPacket,\r
485 IN BOOLEAN IsLow\r
913cb9dc 486 )\r
487{\r
1436aea4
MK
488 UHCI_TD_SW *SetupTd;\r
489 UHCI_TD_SW *FirstDataTd;\r
490 UHCI_TD_SW *DataTd;\r
491 UHCI_TD_SW *PrevDataTd;\r
492 UHCI_TD_SW *StatusTd;\r
493 UINT8 DataToggle;\r
494 UINT8 StatusPktId;\r
495 UINTN ThisTdLen;\r
913cb9dc 496\r
497 DataTd = NULL;\r
498 SetupTd = NULL;\r
499 FirstDataTd = NULL;\r
500 PrevDataTd = NULL;\r
501 StatusTd = NULL;\r
502\r
503 //\r
504 // Create setup packets for the transfer\r
505 //\r
3af875e2 506 SetupTd = UhciCreateSetupTd (Uhc, DeviceAddr, Request, RequestPhy, IsLow);\r
913cb9dc 507\r
508 if (SetupTd == NULL) {\r
509 return NULL;\r
510 }\r
511\r
512 //\r
513 // Create data packets for the transfer\r
514 //\r
515 DataToggle = 1;\r
516\r
517 while (DataLen > 0) {\r
518 //\r
519 // PktSize is the data load size in each Td.\r
520 //\r
521 ThisTdLen = (DataLen > MaxPacket ? MaxPacket : DataLen);\r
522\r
523 DataTd = UhciCreateDataTd (\r
524 Uhc,\r
525 DeviceAddr,\r
526 0,\r
1436aea4
MK
527 Data, // cpu memory address\r
528 DataPhy, // Pci memory address\r
913cb9dc 529 ThisTdLen,\r
530 DataPktId,\r
531 DataToggle,\r
532 IsLow\r
533 );\r
534\r
535 if (DataTd == NULL) {\r
536 goto FREE_TD;\r
537 }\r
538\r
539 if (FirstDataTd == NULL) {\r
540 FirstDataTd = DataTd;\r
541 FirstDataTd->NextTd = NULL;\r
542 } else {\r
3af875e2 543 UhciAppendTd (Uhc, PrevDataTd, DataTd);\r
913cb9dc 544 }\r
545\r
546 DataToggle ^= 1;\r
1436aea4
MK
547 PrevDataTd = DataTd;\r
548 Data += ThisTdLen;\r
549 DataPhy += ThisTdLen;\r
550 DataLen -= ThisTdLen;\r
913cb9dc 551 }\r
552\r
553 //\r
554 // Status packet is on the opposite direction to data packets\r
555 //\r
556 if (OUTPUT_PACKET_ID == DataPktId) {\r
557 StatusPktId = INPUT_PACKET_ID;\r
558 } else {\r
559 StatusPktId = OUTPUT_PACKET_ID;\r
560 }\r
561\r
562 StatusTd = UhciCreateStatusTd (Uhc, DeviceAddr, StatusPktId, IsLow);\r
563\r
564 if (StatusTd == NULL) {\r
565 goto FREE_TD;\r
566 }\r
567\r
568 //\r
569 // Link setup Td -> data Tds -> status Td together\r
570 //\r
571 if (FirstDataTd != NULL) {\r
3af875e2 572 UhciAppendTd (Uhc, SetupTd, FirstDataTd);\r
573 UhciAppendTd (Uhc, PrevDataTd, StatusTd);\r
913cb9dc 574 } else {\r
3af875e2 575 UhciAppendTd (Uhc, SetupTd, StatusTd);\r
913cb9dc 576 }\r
577\r
578 return SetupTd;\r
579\r
580FREE_TD:\r
581 if (SetupTd != NULL) {\r
582 UhciDestoryTds (Uhc, SetupTd);\r
583 }\r
584\r
585 if (FirstDataTd != NULL) {\r
586 UhciDestoryTds (Uhc, FirstDataTd);\r
587 }\r
588\r
589 return NULL;\r
590}\r
591\r
913cb9dc 592/**\r
ab6495ea 593 Create Tds list for Bulk/Interrupt Transfer.\r
594\r
595 @param Uhc USB_HC_DEV.\r
596 @param DevAddr Address of Device.\r
597 @param EndPoint Endpoint Number.\r
598 @param PktId Packet Identification of Data Tds.\r
3af875e2 599 @param Data A pointer to cpu memory address of user data buffer to transfer.\r
600 @param DataPhy A pointer to pci memory address of user data buffer to transfer.\r
ab6495ea 601 @param DataLen Length of user data to transfer.\r
602 @param DataToggle Data Toggle Pointer.\r
603 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.\r
604 @param IsLow Is Low Speed Device.\r
605\r
606 @return The Tds list head for the bulk transfer.\r
913cb9dc 607\r
608**/\r
609UHCI_TD_SW *\r
610UhciCreateBulkOrIntTds (\r
1436aea4
MK
611 IN USB_HC_DEV *Uhc,\r
612 IN UINT8 DevAddr,\r
613 IN UINT8 EndPoint,\r
614 IN UINT8 PktId,\r
615 IN UINT8 *Data,\r
616 IN UINT8 *DataPhy,\r
617 IN UINTN DataLen,\r
618 IN OUT UINT8 *DataToggle,\r
619 IN UINT8 MaxPacket,\r
620 IN BOOLEAN IsLow\r
913cb9dc 621 )\r
622{\r
1436aea4
MK
623 UHCI_TD_SW *DataTd;\r
624 UHCI_TD_SW *FirstDataTd;\r
625 UHCI_TD_SW *PrevDataTd;\r
626 UINTN ThisTdLen;\r
913cb9dc 627\r
628 DataTd = NULL;\r
629 FirstDataTd = NULL;\r
630 PrevDataTd = NULL;\r
631\r
632 //\r
633 // Create data packets for the transfer\r
634 //\r
635 while (DataLen > 0) {\r
636 //\r
637 // PktSize is the data load size that each Td.\r
638 //\r
639 ThisTdLen = DataLen;\r
640\r
641 if (DataLen > MaxPacket) {\r
642 ThisTdLen = MaxPacket;\r
643 }\r
644\r
645 DataTd = UhciCreateDataTd (\r
646 Uhc,\r
647 DevAddr,\r
648 EndPoint,\r
649 Data,\r
3af875e2 650 DataPhy,\r
913cb9dc 651 ThisTdLen,\r
652 PktId,\r
653 *DataToggle,\r
654 IsLow\r
655 );\r
656\r
657 if (DataTd == NULL) {\r
658 goto FREE_TD;\r
659 }\r
660\r
661 if (PktId == INPUT_PACKET_ID) {\r
662 DataTd->TdHw.ShortPacket = TRUE;\r
663 }\r
664\r
665 if (FirstDataTd == NULL) {\r
666 FirstDataTd = DataTd;\r
667 FirstDataTd->NextTd = NULL;\r
668 } else {\r
3af875e2 669 UhciAppendTd (Uhc, PrevDataTd, DataTd);\r
913cb9dc 670 }\r
671\r
672 *DataToggle ^= 1;\r
673 PrevDataTd = DataTd;\r
674 Data += ThisTdLen;\r
3af875e2 675 DataPhy += ThisTdLen;\r
913cb9dc 676 DataLen -= ThisTdLen;\r
677 }\r
678\r
679 return FirstDataTd;\r
680\r
681FREE_TD:\r
682 if (FirstDataTd != NULL) {\r
683 UhciDestoryTds (Uhc, FirstDataTd);\r
684 }\r
685\r
686 return NULL;\r
687}\r