TianoCore EDK2 master
Loading...
Searching...
No Matches
UhciQueue.c
Go to the documentation of this file.
1
10#include "Uhci.h"
11
26 IN USB_HC_DEV *Uhc,
27 IN OUT VOID *Request,
28 OUT UINT8 **MappedAddr,
29 OUT VOID **Map
30 )
31{
32 EFI_STATUS Status;
33 UINTN Len;
35
36 Len = sizeof (EFI_USB_DEVICE_REQUEST);
37 Status = Uhc->PciIo->Map (
38 Uhc->PciIo,
40 Request,
41 &Len,
42 &PhyAddr,
43 Map
44 );
45
46 if (!EFI_ERROR (Status)) {
47 *MappedAddr = (UINT8 *)(UINTN)PhyAddr;
48 }
49
50 return Status;
51}
52
70 IN USB_HC_DEV *Uhc,
71 IN EFI_USB_DATA_DIRECTION Direction,
72 IN VOID *Data,
73 IN OUT UINTN *Len,
74 OUT UINT8 *PktId,
75 OUT UINT8 **MappedAddr,
76 OUT VOID **Map
77 )
78{
79 EFI_STATUS Status;
81
82 Status = EFI_SUCCESS;
83
84 switch (Direction) {
85 case EfiUsbDataIn:
86 //
87 // BusMasterWrite means cpu read
88 //
89 *PktId = INPUT_PACKET_ID;
90 Status = Uhc->PciIo->Map (
91 Uhc->PciIo,
93 Data,
94 Len,
95 &PhyAddr,
96 Map
97 );
98
99 if (EFI_ERROR (Status)) {
100 goto EXIT;
101 }
102
103 *MappedAddr = (UINT8 *)(UINTN)PhyAddr;
104 break;
105
106 case EfiUsbDataOut:
107 *PktId = OUTPUT_PACKET_ID;
108 Status = Uhc->PciIo->Map (
109 Uhc->PciIo,
111 Data,
112 Len,
113 &PhyAddr,
114 Map
115 );
116
117 if (EFI_ERROR (Status)) {
118 goto EXIT;
119 }
120
121 *MappedAddr = (UINT8 *)(UINTN)PhyAddr;
122 break;
123
124 case EfiUsbNoData:
125 if ((Len != NULL) && (*Len != 0)) {
126 Status = EFI_INVALID_PARAMETER;
127 goto EXIT;
128 }
129
130 *PktId = OUTPUT_PACKET_ID;
131 *MappedAddr = NULL;
132 *Map = NULL;
133 break;
134
135 default:
136 Status = EFI_INVALID_PARAMETER;
137 }
138
139EXIT:
140 return Status;
141}
142
151VOID
153 IN USB_HC_DEV *Uhc,
154 IN UHCI_QH_SW *Qh,
155 IN UHCI_TD_SW *Td
156 )
157{
158 EFI_PHYSICAL_ADDRESS PhyAddr;
159
160 PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Td, sizeof (UHCI_TD_HW));
161
162 ASSERT ((Qh != NULL) && (Td != NULL));
163
164 Qh->QhHw.VerticalLink = QH_VLINK (PhyAddr, FALSE);
165 Qh->TDs = (VOID *)Td;
166}
167
175VOID
177 IN UHCI_QH_SW *Qh,
178 IN UHCI_TD_SW *Td
179 )
180{
181 ASSERT ((Qh != NULL) && (Td != NULL));
182
183 Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);
184 Qh->TDs = NULL;
185}
186
195VOID
197 IN USB_HC_DEV *Uhc,
198 IN UHCI_TD_SW *PrevTd,
199 IN UHCI_TD_SW *ThisTd
200 )
201{
202 EFI_PHYSICAL_ADDRESS PhyAddr;
203
204 PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, ThisTd, sizeof (UHCI_TD_HW));
205
206 ASSERT ((PrevTd != NULL) && (ThisTd != NULL));
207
208 PrevTd->TdHw.NextLink = TD_LINK (PhyAddr, TRUE, FALSE);
209 PrevTd->NextTd = (VOID *)ThisTd;
210}
211
221VOID
223 IN USB_HC_DEV *Uhc,
224 IN UHCI_TD_SW *FirstTd
225 )
226{
227 UHCI_TD_SW *NextTd;
228 UHCI_TD_SW *ThisTd;
229
230 NextTd = FirstTd;
231
232 while (NextTd != NULL) {
233 ThisTd = NextTd;
234 NextTd = ThisTd->NextTd;
235 UsbHcFreeMem (Uhc->MemPool, ThisTd, sizeof (UHCI_TD_SW));
236 }
237}
238
250 IN USB_HC_DEV *Uhc,
251 IN UINTN Interval
252 )
253{
254 UHCI_QH_SW *Qh;
255
256 Qh = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_QH_SW));
257
258 if (Qh == NULL) {
259 return NULL;
260 }
261
262 Qh->QhHw.HorizonLink = QH_HLINK (NULL, TRUE);
263 Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE);
264 Qh->Interval = UhciConvertPollRate (Interval);
265 Qh->TDs = NULL;
266 Qh->NextQh = NULL;
267
268 return Qh;
269}
270
281 IN USB_HC_DEV *Uhc
282 )
283{
284 UHCI_TD_SW *Td;
285
286 Td = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_TD_SW));
287 if (Td == NULL) {
288 return NULL;
289 }
290
291 Td->TdHw.NextLink = TD_LINK (NULL, FALSE, TRUE);
292 Td->NextTd = NULL;
293 Td->Data = NULL;
294 Td->DataLen = 0;
295
296 return Td;
297}
298
313 IN USB_HC_DEV *Uhc,
314 IN UINT8 DevAddr,
315 IN UINT8 *Request,
316 IN UINT8 *RequestPhy,
317 IN BOOLEAN IsLow
318 )
319{
320 UHCI_TD_SW *Td;
321
322 Td = UhciCreateTd (Uhc);
323
324 if (Td == NULL) {
325 return NULL;
326 }
327
328 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);
329 Td->TdHw.ShortPacket = FALSE;
330 Td->TdHw.IsIsoch = FALSE;
331 Td->TdHw.IntOnCpl = FALSE;
332 Td->TdHw.ErrorCount = 0x03;
333 Td->TdHw.Status |= USBTD_ACTIVE;
334 Td->TdHw.DataToggle = 0;
335 Td->TdHw.EndPoint = 0;
336 Td->TdHw.LowSpeed = IsLow ? 1 : 0;
337 Td->TdHw.DeviceAddr = DevAddr & 0x7F;
338 Td->TdHw.MaxPacketLen = (UINT32)(sizeof (EFI_USB_DEVICE_REQUEST) - 1);
339 Td->TdHw.PidCode = SETUP_PACKET_ID;
340 Td->TdHw.DataBuffer = (UINT32)(UINTN)RequestPhy;
341
342 Td->Data = Request;
343 Td->DataLen = (UINT16)sizeof (EFI_USB_DEVICE_REQUEST);
344
345 return Td;
346}
347
366 IN USB_HC_DEV *Uhc,
367 IN UINT8 DevAddr,
368 IN UINT8 Endpoint,
369 IN UINT8 *DataPtr,
370 IN UINT8 *DataPhyPtr,
371 IN UINTN Len,
372 IN UINT8 PktId,
373 IN UINT8 Toggle,
374 IN BOOLEAN IsLow
375 )
376{
377 UHCI_TD_SW *Td;
378
379 //
380 // Code as length - 1, and the max valid length is 0x500
381 //
382 ASSERT (Len <= 0x500);
383
384 Td = UhciCreateTd (Uhc);
385
386 if (Td == NULL) {
387 return NULL;
388 }
389
390 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);
391 Td->TdHw.ShortPacket = FALSE;
392 Td->TdHw.IsIsoch = FALSE;
393 Td->TdHw.IntOnCpl = FALSE;
394 Td->TdHw.ErrorCount = 0x03;
395 Td->TdHw.Status = USBTD_ACTIVE;
396 Td->TdHw.LowSpeed = IsLow ? 1 : 0;
397 Td->TdHw.DataToggle = Toggle & 0x01;
398 Td->TdHw.EndPoint = Endpoint & 0x0F;
399 Td->TdHw.DeviceAddr = DevAddr & 0x7F;
400 Td->TdHw.MaxPacketLen = (UINT32)(Len - 1);
401 Td->TdHw.PidCode = (UINT8)PktId;
402 Td->TdHw.DataBuffer = (UINT32)(UINTN)DataPhyPtr;
403
404 Td->Data = DataPtr;
405 Td->DataLen = (UINT16)Len;
406
407 return Td;
408}
409
423 IN USB_HC_DEV *Uhc,
424 IN UINT8 DevAddr,
425 IN UINT8 PktId,
426 IN BOOLEAN IsLow
427 )
428{
429 UHCI_TD_SW *Td;
430
431 Td = UhciCreateTd (Uhc);
432
433 if (Td == NULL) {
434 return NULL;
435 }
436
437 Td->TdHw.NextLink = TD_LINK (NULL, TRUE, TRUE);
438 Td->TdHw.ShortPacket = FALSE;
439 Td->TdHw.IsIsoch = FALSE;
440 Td->TdHw.IntOnCpl = FALSE;
441 Td->TdHw.ErrorCount = 0x03;
442 Td->TdHw.Status |= USBTD_ACTIVE;
443 Td->TdHw.MaxPacketLen = 0x7FF; // 0x7FF: there is no data (refer to UHCI spec)
444 Td->TdHw.DataToggle = 1;
445 Td->TdHw.EndPoint = 0;
446 Td->TdHw.LowSpeed = IsLow ? 1 : 0;
447 Td->TdHw.DeviceAddr = DevAddr & 0x7F;
448 Td->TdHw.PidCode = (UINT8)PktId;
449 Td->TdHw.DataBuffer = (UINT32)(UINTN)NULL;
450
451 Td->Data = NULL;
452 Td->DataLen = 0;
453
454 return Td;
455}
456
476 IN USB_HC_DEV *Uhc,
477 IN UINT8 DeviceAddr,
478 IN UINT8 DataPktId,
479 IN UINT8 *Request,
480 IN UINT8 *RequestPhy,
481 IN UINT8 *Data,
482 IN UINT8 *DataPhy,
483 IN UINTN DataLen,
484 IN UINT8 MaxPacket,
485 IN BOOLEAN IsLow
486 )
487{
488 UHCI_TD_SW *SetupTd;
489 UHCI_TD_SW *FirstDataTd;
490 UHCI_TD_SW *DataTd;
491 UHCI_TD_SW *PrevDataTd;
492 UHCI_TD_SW *StatusTd;
493 UINT8 DataToggle;
494 UINT8 StatusPktId;
495 UINTN ThisTdLen;
496
497 DataTd = NULL;
498 SetupTd = NULL;
499 FirstDataTd = NULL;
500 PrevDataTd = NULL;
501 StatusTd = NULL;
502
503 //
504 // Create setup packets for the transfer
505 //
506 SetupTd = UhciCreateSetupTd (Uhc, DeviceAddr, Request, RequestPhy, IsLow);
507
508 if (SetupTd == NULL) {
509 return NULL;
510 }
511
512 //
513 // Create data packets for the transfer
514 //
515 DataToggle = 1;
516
517 while (DataLen > 0) {
518 //
519 // PktSize is the data load size in each Td.
520 //
521 ThisTdLen = (DataLen > MaxPacket ? MaxPacket : DataLen);
522
523 DataTd = UhciCreateDataTd (
524 Uhc,
525 DeviceAddr,
526 0,
527 Data, // cpu memory address
528 DataPhy, // Pci memory address
529 ThisTdLen,
530 DataPktId,
531 DataToggle,
532 IsLow
533 );
534
535 if (DataTd == NULL) {
536 goto FREE_TD;
537 }
538
539 if (FirstDataTd == NULL) {
540 FirstDataTd = DataTd;
541 FirstDataTd->NextTd = NULL;
542 } else {
543 UhciAppendTd (Uhc, PrevDataTd, DataTd);
544 }
545
546 DataToggle ^= 1;
547 PrevDataTd = DataTd;
548 Data += ThisTdLen;
549 DataPhy += ThisTdLen;
550 DataLen -= ThisTdLen;
551 }
552
553 //
554 // Status packet is on the opposite direction to data packets
555 //
556 if (OUTPUT_PACKET_ID == DataPktId) {
557 StatusPktId = INPUT_PACKET_ID;
558 } else {
559 StatusPktId = OUTPUT_PACKET_ID;
560 }
561
562 StatusTd = UhciCreateStatusTd (Uhc, DeviceAddr, StatusPktId, IsLow);
563
564 if (StatusTd == NULL) {
565 goto FREE_TD;
566 }
567
568 //
569 // Link setup Td -> data Tds -> status Td together
570 //
571 if (FirstDataTd != NULL) {
572 UhciAppendTd (Uhc, SetupTd, FirstDataTd);
573 UhciAppendTd (Uhc, PrevDataTd, StatusTd);
574 } else {
575 UhciAppendTd (Uhc, SetupTd, StatusTd);
576 }
577
578 return SetupTd;
579
580FREE_TD:
581 if (SetupTd != NULL) {
582 UhciDestoryTds (Uhc, SetupTd);
583 }
584
585 if (FirstDataTd != NULL) {
586 UhciDestoryTds (Uhc, FirstDataTd);
587 }
588
589 return NULL;
590}
591
611 IN USB_HC_DEV *Uhc,
612 IN UINT8 DevAddr,
613 IN UINT8 EndPoint,
614 IN UINT8 PktId,
615 IN UINT8 *Data,
616 IN UINT8 *DataPhy,
617 IN UINTN DataLen,
618 IN OUT UINT8 *DataToggle,
619 IN UINT8 MaxPacket,
620 IN BOOLEAN IsLow
621 )
622{
623 UHCI_TD_SW *DataTd;
624 UHCI_TD_SW *FirstDataTd;
625 UHCI_TD_SW *PrevDataTd;
626 UINTN ThisTdLen;
627
628 DataTd = NULL;
629 FirstDataTd = NULL;
630 PrevDataTd = NULL;
631
632 //
633 // Create data packets for the transfer
634 //
635 while (DataLen > 0) {
636 //
637 // PktSize is the data load size that each Td.
638 //
639 ThisTdLen = DataLen;
640
641 if (DataLen > MaxPacket) {
642 ThisTdLen = MaxPacket;
643 }
644
645 DataTd = UhciCreateDataTd (
646 Uhc,
647 DevAddr,
648 EndPoint,
649 Data,
650 DataPhy,
651 ThisTdLen,
652 PktId,
653 *DataToggle,
654 IsLow
655 );
656
657 if (DataTd == NULL) {
658 goto FREE_TD;
659 }
660
661 if (PktId == INPUT_PACKET_ID) {
662 DataTd->TdHw.ShortPacket = TRUE;
663 }
664
665 if (FirstDataTd == NULL) {
666 FirstDataTd = DataTd;
667 FirstDataTd->NextTd = NULL;
668 } else {
669 UhciAppendTd (Uhc, PrevDataTd, DataTd);
670 }
671
672 *DataToggle ^= 1;
673 PrevDataTd = DataTd;
674 Data += ThisTdLen;
675 DataPhy += ThisTdLen;
676 DataLen -= ThisTdLen;
677 }
678
679 return FirstDataTd;
680
681FREE_TD:
682 if (FirstDataTd != NULL) {
683 UhciDestoryTds (Uhc, FirstDataTd);
684 }
685
686 return NULL;
687}
UINT64 UINTN
EFI_PHYSICAL_ADDRESS UsbHcGetPciAddressForHostMem(IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
Definition: UsbHcMem.c:223
VOID UsbHcFreeMem(IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
Definition: UsbHcMem.c:493
VOID * UsbHcAllocateMem(IN USBHC_MEM_POOL *Pool, IN UINTN Size)
Definition: UsbHcMem.c:419
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
@ EfiPciIoOperationBusMasterWrite
Definition: PciIo.h:85
@ EfiPciIoOperationBusMasterRead
Definition: PciIo.h:81
EFI_USB_DATA_DIRECTION
Definition: UsbIo.h:44
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
VOID UhciDestoryTds(IN USB_HC_DEV *Uhc, IN UHCI_TD_SW *FirstTd)
Definition: UhciQueue.c:222
EFI_STATUS UhciMapUserRequest(IN USB_HC_DEV *Uhc, IN OUT VOID *Request, OUT UINT8 **MappedAddr, OUT VOID **Map)
Definition: UhciQueue.c:25
VOID UhciLinkTdToQh(IN USB_HC_DEV *Uhc, IN UHCI_QH_SW *Qh, IN UHCI_TD_SW *Td)
Definition: UhciQueue.c:152
UHCI_QH_SW * UhciCreateQh(IN USB_HC_DEV *Uhc, IN UINTN Interval)
Definition: UhciQueue.c:249
VOID UhciAppendTd(IN USB_HC_DEV *Uhc, IN UHCI_TD_SW *PrevTd, IN UHCI_TD_SW *ThisTd)
Definition: UhciQueue.c:196
UHCI_TD_SW * UhciCreateDataTd(IN USB_HC_DEV *Uhc, IN UINT8 DevAddr, IN UINT8 Endpoint, IN UINT8 *DataPtr, IN UINT8 *DataPhyPtr, IN UINTN Len, IN UINT8 PktId, IN UINT8 Toggle, IN BOOLEAN IsLow)
Definition: UhciQueue.c:365
UHCI_TD_SW * UhciCreateSetupTd(IN USB_HC_DEV *Uhc, IN UINT8 DevAddr, IN UINT8 *Request, IN UINT8 *RequestPhy, IN BOOLEAN IsLow)
Definition: UhciQueue.c:312
EFI_STATUS UhciMapUserData(IN USB_HC_DEV *Uhc, IN EFI_USB_DATA_DIRECTION Direction, IN VOID *Data, IN OUT UINTN *Len, OUT UINT8 *PktId, OUT UINT8 **MappedAddr, OUT VOID **Map)
Definition: UhciQueue.c:69
UHCI_TD_SW * UhciCreateStatusTd(IN USB_HC_DEV *Uhc, IN UINT8 DevAddr, IN UINT8 PktId, IN BOOLEAN IsLow)
Definition: UhciQueue.c:422
UHCI_TD_SW * UhciCreateBulkOrIntTds(IN USB_HC_DEV *Uhc, IN UINT8 DevAddr, IN UINT8 EndPoint, IN UINT8 PktId, IN UINT8 *Data, IN UINT8 *DataPhy, IN UINTN DataLen, IN OUT UINT8 *DataToggle, IN UINT8 MaxPacket, IN BOOLEAN IsLow)
Definition: UhciQueue.c:610
UHCI_TD_SW * UhciCreateCtrlTds(IN USB_HC_DEV *Uhc, IN UINT8 DeviceAddr, IN UINT8 DataPktId, IN UINT8 *Request, IN UINT8 *RequestPhy, IN UINT8 *Data, IN UINT8 *DataPhy, IN UINTN DataLen, IN UINT8 MaxPacket, IN BOOLEAN IsLow)
Definition: UhciQueue.c:475
UHCI_TD_SW * UhciCreateTd(IN USB_HC_DEV *Uhc)
Definition: UhciQueue.c:280
VOID UhciUnlinkTdFromQh(IN UHCI_QH_SW *Qh, IN UHCI_TD_SW *Td)
Definition: UhciQueue.c:176
UINTN UhciConvertPollRate(IN UINTN Interval)
Definition: UhciSched.c:209