]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UhciDxe/UhciQueue.c
NumberOfCpus and SmmStartupThisAp field in Framework SMST should be updated per PI...
[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
b4c24e2d 5Copyright (c) 2007 - 2008, Intel Corporation\r
913cb9dc 6All rights reserved. This program and the accompanying materials\r
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_STATUS Status;\r
168 UINTN Len;\r
169 EFI_PHYSICAL_ADDRESS PhyAddr;\r
170 VOID* Map;\r
171\r
172 Len = sizeof (UHCI_TD_HW);\r
173 Status = Uhc->PciIo->Map (\r
174 Uhc->PciIo,\r
175 EfiPciIoOperationBusMasterRead,\r
176 Td,\r
177 &Len,\r
178 &PhyAddr,\r
179 &Map\r
180 );\r
181\r
182 ASSERT (!EFI_ERROR (Status) && (Qh != NULL) && (Td != NULL));\r
913cb9dc 183\r
3af875e2 184 Qh->QhHw.VerticalLink = QH_VLINK (PhyAddr, FALSE);\r
913cb9dc 185 Qh->TDs = (VOID *) Td;\r
186}\r
187\r
188\r
189/**\r
ab6495ea 190 Unlink TD from the QH.\r
913cb9dc 191\r
ab6495ea 192 @param Qh The queue head to unlink from.\r
193 @param Td The TD to unlink.\r
913cb9dc 194\r
913cb9dc 195**/\r
196VOID\r
197UhciUnlinkTdFromQh (\r
198 IN UHCI_QH_SW *Qh,\r
199 IN UHCI_TD_SW *Td\r
200 )\r
201{\r
202 ASSERT ((Qh != NULL) && (Td != NULL));\r
203\r
204 Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);\r
205 Qh->TDs = NULL;\r
206}\r
207\r
208\r
209/**\r
ab6495ea 210 Append a new TD To the previous TD.\r
913cb9dc 211\r
3af875e2 212 @param Uhc The UHCI device.\r
ab6495ea 213 @param PrevTd Previous UHCI_TD_SW to be linked to.\r
214 @param ThisTd TD to link.\r
913cb9dc 215\r
913cb9dc 216**/\r
913cb9dc 217VOID\r
218UhciAppendTd (\r
3af875e2 219 IN USB_HC_DEV *Uhc,\r
913cb9dc 220 IN UHCI_TD_SW *PrevTd,\r
221 IN UHCI_TD_SW *ThisTd\r
222 )\r
223{\r
3af875e2 224 EFI_STATUS Status;\r
225 UINTN Len;\r
226 EFI_PHYSICAL_ADDRESS PhyAddr;\r
227 VOID* Map;\r
913cb9dc 228\r
3af875e2 229 Len = sizeof (UHCI_TD_HW);\r
230 Status = Uhc->PciIo->Map (\r
231 Uhc->PciIo,\r
232 EfiPciIoOperationBusMasterRead,\r
233 ThisTd,\r
234 &Len,\r
235 &PhyAddr,\r
236 &Map\r
237 );\r
238\r
239 ASSERT (!EFI_ERROR (Status) && (PrevTd != NULL) && (ThisTd != NULL));\r
240\r
241 PrevTd->TdHw.NextLink = TD_LINK (PhyAddr, TRUE, FALSE);\r
913cb9dc 242 PrevTd->NextTd = (VOID *) ThisTd;\r
243}\r
244\r
245\r
246/**\r
ab6495ea 247 Delete a list of TDs.\r
913cb9dc 248\r
ab6495ea 249 @param Uhc The UHCI device.\r
250 @param FirstTd TD link list head.\r
913cb9dc 251\r
ab6495ea 252 @return None.\r
913cb9dc 253\r
254**/\r
255VOID\r
256UhciDestoryTds (\r
257 IN USB_HC_DEV *Uhc,\r
258 IN UHCI_TD_SW *FirstTd\r
259 )\r
260{\r
261 UHCI_TD_SW *NextTd;\r
262 UHCI_TD_SW *ThisTd;\r
263\r
264 NextTd = FirstTd;\r
265\r
266 while (NextTd != NULL) {\r
267 ThisTd = NextTd;\r
268 NextTd = ThisTd->NextTd;\r
269 UsbHcFreeMem (Uhc->MemPool, ThisTd, sizeof (UHCI_TD_SW));\r
270 }\r
271}\r
272\r
273\r
274/**\r
ab6495ea 275 Create an initialize a new queue head.\r
913cb9dc 276\r
ab6495ea 277 @param Uhc The UHCI device.\r
278 @param Interval The polling interval for the queue.\r
913cb9dc 279\r
ab6495ea 280 @return The newly created queue header.\r
913cb9dc 281\r
282**/\r
283UHCI_QH_SW *\r
284UhciCreateQh (\r
285 IN USB_HC_DEV *Uhc,\r
286 IN UINTN Interval\r
287 )\r
288{\r
289 UHCI_QH_SW *Qh;\r
290\r
291 Qh = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_QH_SW));\r
292\r
293 if (Qh == NULL) {\r
294 return NULL;\r
295 }\r
296\r
297 Qh->QhHw.HorizonLink = QH_HLINK (NULL, TRUE);\r
298 Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);\r
b4c24e2d 299 Qh->Interval = UhciConvertPollRate(Interval);\r
913cb9dc 300 Qh->TDs = NULL;\r
301 Qh->NextQh = NULL;\r
302\r
303 return Qh;\r
304}\r
305\r
306\r
307/**\r
ab6495ea 308 Create and intialize a TD.\r
913cb9dc 309\r
ab6495ea 310 @param Uhc The UHCI device.\r
913cb9dc 311\r
ab6495ea 312 @return The newly allocated and initialized TD.\r
913cb9dc 313\r
314**/\r
913cb9dc 315UHCI_TD_SW *\r
316UhciCreateTd (\r
317 IN USB_HC_DEV *Uhc\r
318 )\r
319{\r
320 UHCI_TD_SW *Td;\r
321\r
322 Td = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_TD_SW));\r
323 if (Td == NULL) {\r
324 return NULL;\r
325 }\r
326\r
913cb9dc 327 Td->NextTd = NULL;\r
328 Td->Data = NULL;\r
329 Td->DataLen = 0;\r
330\r
331 return Td;\r
332}\r
333\r
334\r
335/**\r
ab6495ea 336 Create and initialize a TD for Setup Stage of a control transfer.\r
913cb9dc 337\r
ab6495ea 338 @param Uhc The UHCI device.\r
339 @param DevAddr Device address.\r
3af875e2 340 @param Request A pointer to cpu memory address of Device request.\r
341 @param RequestPhy A pointer to pci memory address of Device request.\r
ab6495ea 342 @param IsLow Full speed or low speed.\r
913cb9dc 343\r
ab6495ea 344 @return The created setup Td Pointer.\r
913cb9dc 345\r
346**/\r
913cb9dc 347UHCI_TD_SW *\r
348UhciCreateSetupTd (\r
349 IN USB_HC_DEV *Uhc,\r
350 IN UINT8 DevAddr,\r
351 IN UINT8 *Request,\r
3af875e2 352 IN UINT8 *RequestPhy,\r
913cb9dc 353 IN BOOLEAN IsLow\r
354 )\r
355{\r
356 UHCI_TD_SW *Td;\r
357\r
358 Td = UhciCreateTd (Uhc);\r
359\r
360 if (Td == NULL) {\r
361 return NULL;\r
362 }\r
363\r
364 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);\r
365 Td->TdHw.ShortPacket = FALSE;\r
366 Td->TdHw.IsIsoch = FALSE;\r
367 Td->TdHw.IntOnCpl = FALSE;\r
368 Td->TdHw.ErrorCount = 0x03;\r
369 Td->TdHw.Status |= USBTD_ACTIVE;\r
370 Td->TdHw.DataToggle = 0;\r
371 Td->TdHw.EndPoint = 0;\r
372 Td->TdHw.LowSpeed = IsLow ? 1 : 0;\r
373 Td->TdHw.DeviceAddr = DevAddr & 0x7F;\r
374 Td->TdHw.MaxPacketLen = (UINT32) (sizeof (EFI_USB_DEVICE_REQUEST) - 1);\r
375 Td->TdHw.PidCode = SETUP_PACKET_ID;\r
3af875e2 376 Td->TdHw.DataBuffer = (UINT32) (UINTN) RequestPhy;\r
913cb9dc 377\r
378 Td->Data = Request;\r
379 Td->DataLen = sizeof (EFI_USB_DEVICE_REQUEST);\r
380\r
381 return Td;\r
382}\r
383\r
384\r
385/**\r
ab6495ea 386 Create a TD for data.\r
913cb9dc 387\r
ab6495ea 388 @param Uhc The UHCI device.\r
389 @param DevAddr Device address.\r
390 @param Endpoint Endpoint number.\r
3af875e2 391 @param DataPtr A pointer to cpu memory address of Data buffer.\r
392 @param DataPhyPtr A pointer to pci memory address of Data buffer.\r
ab6495ea 393 @param Len Data length.\r
394 @param PktId Packet ID.\r
395 @param Toggle Data toggle value.\r
396 @param IsLow Full speed or low speed.\r
913cb9dc 397\r
ab6495ea 398 @return Data Td pointer if success, otherwise NULL.\r
913cb9dc 399\r
400**/\r
913cb9dc 401UHCI_TD_SW *\r
402UhciCreateDataTd (\r
403 IN USB_HC_DEV *Uhc,\r
404 IN UINT8 DevAddr,\r
405 IN UINT8 Endpoint,\r
406 IN UINT8 *DataPtr,\r
3af875e2 407 IN UINT8 *DataPhyPtr,\r
913cb9dc 408 IN UINTN Len,\r
409 IN UINT8 PktId,\r
410 IN UINT8 Toggle,\r
411 IN BOOLEAN IsLow\r
412 )\r
413{\r
414 UHCI_TD_SW *Td;\r
415\r
416 //\r
417 // Code as length - 1, and the max valid length is 0x500\r
418 //\r
419 ASSERT (Len <= 0x500);\r
420\r
421 Td = UhciCreateTd (Uhc);\r
422\r
423 if (Td == NULL) {\r
424 return NULL;\r
425 }\r
426\r
427 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);\r
428 Td->TdHw.ShortPacket = FALSE;\r
429 Td->TdHw.IsIsoch = FALSE;\r
430 Td->TdHw.IntOnCpl = FALSE;\r
431 Td->TdHw.ErrorCount = 0X03;\r
432 Td->TdHw.Status = USBTD_ACTIVE;\r
433 Td->TdHw.LowSpeed = IsLow ? 1 : 0;\r
434 Td->TdHw.DataToggle = Toggle & 0x01;\r
435 Td->TdHw.EndPoint = Endpoint & 0x0F;\r
436 Td->TdHw.DeviceAddr = DevAddr & 0x7F;\r
437 Td->TdHw.MaxPacketLen = (UINT32) (Len - 1);\r
438 Td->TdHw.PidCode = (UINT8) PktId;\r
3af875e2 439 Td->TdHw.DataBuffer = (UINT32) (UINTN) DataPhyPtr;\r
913cb9dc 440\r
441 Td->Data = DataPtr;\r
442 Td->DataLen = (UINT16) Len;\r
443\r
444 return Td;\r
445}\r
446\r
447\r
448/**\r
ab6495ea 449 Create TD for the Status Stage of control transfer.\r
913cb9dc 450\r
ab6495ea 451 @param Uhc The UHCI device.\r
452 @param DevAddr Device address.\r
453 @param PktId Packet ID.\r
454 @param IsLow Full speed or low speed.\r
913cb9dc 455\r
ab6495ea 456 @return Status Td Pointer.\r
913cb9dc 457\r
458**/\r
913cb9dc 459UHCI_TD_SW *\r
460UhciCreateStatusTd (\r
461 IN USB_HC_DEV *Uhc,\r
462 IN UINT8 DevAddr,\r
463 IN UINT8 PktId,\r
464 IN BOOLEAN IsLow\r
465 )\r
466{\r
467 UHCI_TD_SW *Td;\r
468\r
469 Td = UhciCreateTd (Uhc);\r
470\r
471 if (Td == NULL) {\r
472 return NULL;\r
473 }\r
474\r
475 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);\r
476 Td->TdHw.ShortPacket = FALSE;\r
477 Td->TdHw.IsIsoch = FALSE;\r
478 Td->TdHw.IntOnCpl = FALSE;\r
479 Td->TdHw.ErrorCount = 0x03;\r
480 Td->TdHw.Status |= USBTD_ACTIVE;\r
481 Td->TdHw.MaxPacketLen = 0x7FF; //0x7FF: there is no data (refer to UHCI spec)\r
482 Td->TdHw.DataToggle = 1;\r
483 Td->TdHw.EndPoint = 0;\r
484 Td->TdHw.LowSpeed = IsLow ? 1 : 0;\r
485 Td->TdHw.DeviceAddr = DevAddr & 0x7F;\r
486 Td->TdHw.PidCode = (UINT8) PktId;\r
487 Td->TdHw.DataBuffer = (UINT32) (UINTN) NULL;\r
488\r
489 Td->Data = NULL;\r
490 Td->DataLen = 0;\r
491\r
492 return Td;\r
493}\r
494\r
495\r
496/**\r
ab6495ea 497 Create Tds list for Control Transfer.\r
913cb9dc 498\r
ab6495ea 499 @param Uhc The UHCI device.\r
500 @param DeviceAddr The device address.\r
501 @param DataPktId Packet Identification of Data Tds.\r
3af875e2 502 @param Request A pointer to cpu memory address of request structure buffer to transfer.\r
503 @param RequestPhy A pointer to pci memory address of request structure buffer to transfer.\r
504 @param Data A pointer to cpu memory address of user data buffer to transfer.\r
505 @param DataPhy A pointer to pci memory address of user data buffer to transfer.\r
ab6495ea 506 @param DataLen Length of user data to transfer.\r
507 @param MaxPacket Maximum packet size for control transfer.\r
508 @param IsLow Full speed or low speed.\r
913cb9dc 509\r
ab6495ea 510 @return The Td list head for the control transfer.\r
913cb9dc 511\r
512**/\r
513UHCI_TD_SW *\r
514UhciCreateCtrlTds (\r
515 IN USB_HC_DEV *Uhc,\r
516 IN UINT8 DeviceAddr,\r
517 IN UINT8 DataPktId,\r
518 IN UINT8 *Request,\r
3af875e2 519 IN UINT8 *RequestPhy,\r
913cb9dc 520 IN UINT8 *Data,\r
3af875e2 521 IN UINT8 *DataPhy,\r
913cb9dc 522 IN UINTN DataLen,\r
523 IN UINT8 MaxPacket,\r
524 IN BOOLEAN IsLow\r
525 )\r
526{\r
527 UHCI_TD_SW *SetupTd;\r
528 UHCI_TD_SW *FirstDataTd;\r
529 UHCI_TD_SW *DataTd;\r
530 UHCI_TD_SW *PrevDataTd;\r
531 UHCI_TD_SW *StatusTd;\r
532 UINT8 DataToggle;\r
533 UINT8 StatusPktId;\r
534 UINTN ThisTdLen;\r
535\r
536\r
537 DataTd = NULL;\r
538 SetupTd = NULL;\r
539 FirstDataTd = NULL;\r
540 PrevDataTd = NULL;\r
541 StatusTd = NULL;\r
542\r
543 //\r
544 // Create setup packets for the transfer\r
545 //\r
3af875e2 546 SetupTd = UhciCreateSetupTd (Uhc, DeviceAddr, Request, RequestPhy, IsLow);\r
913cb9dc 547\r
548 if (SetupTd == NULL) {\r
549 return NULL;\r
550 }\r
551\r
552 //\r
553 // Create data packets for the transfer\r
554 //\r
555 DataToggle = 1;\r
556\r
557 while (DataLen > 0) {\r
558 //\r
559 // PktSize is the data load size in each Td.\r
560 //\r
561 ThisTdLen = (DataLen > MaxPacket ? MaxPacket : DataLen);\r
562\r
563 DataTd = UhciCreateDataTd (\r
564 Uhc,\r
565 DeviceAddr,\r
566 0,\r
3af875e2 567 Data, //cpu memory address\r
568 DataPhy, //Pci memory address\r
913cb9dc 569 ThisTdLen,\r
570 DataPktId,\r
571 DataToggle,\r
572 IsLow\r
573 );\r
574\r
575 if (DataTd == NULL) {\r
576 goto FREE_TD;\r
577 }\r
578\r
579 if (FirstDataTd == NULL) {\r
580 FirstDataTd = DataTd;\r
581 FirstDataTd->NextTd = NULL;\r
582 } else {\r
3af875e2 583 UhciAppendTd (Uhc, PrevDataTd, DataTd);\r
913cb9dc 584 }\r
585\r
586 DataToggle ^= 1;\r
587 PrevDataTd = DataTd;\r
588 Data += ThisTdLen;\r
3af875e2 589 DataPhy += ThisTdLen;\r
913cb9dc 590 DataLen -= ThisTdLen;\r
591 }\r
592\r
593 //\r
594 // Status packet is on the opposite direction to data packets\r
595 //\r
596 if (OUTPUT_PACKET_ID == DataPktId) {\r
597 StatusPktId = INPUT_PACKET_ID;\r
598 } else {\r
599 StatusPktId = OUTPUT_PACKET_ID;\r
600 }\r
601\r
602 StatusTd = UhciCreateStatusTd (Uhc, DeviceAddr, StatusPktId, IsLow);\r
603\r
604 if (StatusTd == NULL) {\r
605 goto FREE_TD;\r
606 }\r
607\r
608 //\r
609 // Link setup Td -> data Tds -> status Td together\r
610 //\r
611 if (FirstDataTd != NULL) {\r
3af875e2 612 UhciAppendTd (Uhc, SetupTd, FirstDataTd);\r
613 UhciAppendTd (Uhc, PrevDataTd, StatusTd);\r
913cb9dc 614 } else {\r
3af875e2 615 UhciAppendTd (Uhc, SetupTd, StatusTd);\r
913cb9dc 616 }\r
617\r
618 return SetupTd;\r
619\r
620FREE_TD:\r
621 if (SetupTd != NULL) {\r
622 UhciDestoryTds (Uhc, SetupTd);\r
623 }\r
624\r
625 if (FirstDataTd != NULL) {\r
626 UhciDestoryTds (Uhc, FirstDataTd);\r
627 }\r
628\r
629 return NULL;\r
630}\r
631\r
632\r
633/**\r
ab6495ea 634 Create Tds list for Bulk/Interrupt Transfer.\r
635\r
636 @param Uhc USB_HC_DEV.\r
637 @param DevAddr Address of Device.\r
638 @param EndPoint Endpoint Number.\r
639 @param PktId Packet Identification of Data Tds.\r
3af875e2 640 @param Data A pointer to cpu memory address of user data buffer to transfer.\r
641 @param DataPhy A pointer to pci memory address of user data buffer to transfer.\r
ab6495ea 642 @param DataLen Length of user data to transfer.\r
643 @param DataToggle Data Toggle Pointer.\r
644 @param MaxPacket Maximum packet size for Bulk/Interrupt transfer.\r
645 @param IsLow Is Low Speed Device.\r
646\r
647 @return The Tds list head for the bulk transfer.\r
913cb9dc 648\r
649**/\r
650UHCI_TD_SW *\r
651UhciCreateBulkOrIntTds (\r
652 IN USB_HC_DEV *Uhc,\r
653 IN UINT8 DevAddr,\r
654 IN UINT8 EndPoint,\r
655 IN UINT8 PktId,\r
656 IN UINT8 *Data,\r
3af875e2 657 IN UINT8 *DataPhy,\r
913cb9dc 658 IN UINTN DataLen,\r
659 IN OUT UINT8 *DataToggle,\r
660 IN UINT8 MaxPacket,\r
661 IN BOOLEAN IsLow\r
662 )\r
663{\r
664 UHCI_TD_SW *DataTd;\r
665 UHCI_TD_SW *FirstDataTd;\r
666 UHCI_TD_SW *PrevDataTd;\r
667 UINTN ThisTdLen;\r
668\r
669 DataTd = NULL;\r
670 FirstDataTd = NULL;\r
671 PrevDataTd = NULL;\r
672\r
673 //\r
674 // Create data packets for the transfer\r
675 //\r
676 while (DataLen > 0) {\r
677 //\r
678 // PktSize is the data load size that each Td.\r
679 //\r
680 ThisTdLen = DataLen;\r
681\r
682 if (DataLen > MaxPacket) {\r
683 ThisTdLen = MaxPacket;\r
684 }\r
685\r
686 DataTd = UhciCreateDataTd (\r
687 Uhc,\r
688 DevAddr,\r
689 EndPoint,\r
690 Data,\r
3af875e2 691 DataPhy,\r
913cb9dc 692 ThisTdLen,\r
693 PktId,\r
694 *DataToggle,\r
695 IsLow\r
696 );\r
697\r
698 if (DataTd == NULL) {\r
699 goto FREE_TD;\r
700 }\r
701\r
702 if (PktId == INPUT_PACKET_ID) {\r
703 DataTd->TdHw.ShortPacket = TRUE;\r
704 }\r
705\r
706 if (FirstDataTd == NULL) {\r
707 FirstDataTd = DataTd;\r
708 FirstDataTd->NextTd = NULL;\r
709 } else {\r
3af875e2 710 UhciAppendTd (Uhc, PrevDataTd, DataTd);\r
913cb9dc 711 }\r
712\r
713 *DataToggle ^= 1;\r
714 PrevDataTd = DataTd;\r
715 Data += ThisTdLen;\r
3af875e2 716 DataPhy += ThisTdLen;\r
913cb9dc 717 DataLen -= ThisTdLen;\r
718 }\r
719\r
720 return FirstDataTd;\r
721\r
722FREE_TD:\r
723 if (FirstDataTd != NULL) {\r
724 UhciDestoryTds (Uhc, FirstDataTd);\r
725 }\r
726\r
727 return NULL;\r
728}\r