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