1 /** @file
2 
3     This file contains URB request, each request is warpped in a
4     URB (Usb Request Block).
5 
6 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #include "Ehci.h"
12 
13 
14 /**
15   Create a single QTD to hold the data.
16 
17   @param  Ehc                   The EHCI device.
18   @param  Data                  The cpu memory address of current data not associated with a QTD.
19   @param  DataPhy               The pci bus address of current data not associated with a QTD.
20   @param  DataLen               The length of the data.
21   @param  PktId                 Packet ID to use in the QTD.
22   @param  Toggle                Data toggle to use in the QTD.
23   @param  MaxPacket             Maximu packet length of the endpoint.
24 
25   @return Created QTD or NULL if failed to create one.
26 
27 **/
28 EHC_QTD *
EhcCreateQtd(IN USB2_HC_DEV * Ehc,IN UINT8 * Data,IN UINT8 * DataPhy,IN UINTN DataLen,IN UINT8 PktId,IN UINT8 Toggle,IN UINTN MaxPacket)29 EhcCreateQtd (
30   IN USB2_HC_DEV          *Ehc,
31   IN UINT8                *Data,
32   IN UINT8                *DataPhy,
33   IN UINTN                DataLen,
34   IN UINT8                PktId,
35   IN UINT8                Toggle,
36   IN UINTN                MaxPacket
37   )
38 {
39   EHC_QTD                 *Qtd;
40   QTD_HW                  *QtdHw;
41   UINTN                   Index;
42   UINTN                   Len;
43   UINTN                   ThisBufLen;
44 
45   ASSERT (Ehc != NULL);
46 
47   Qtd = UsbHcAllocateMem (Ehc->MemPool, sizeof (EHC_QTD));
48 
49   if (Qtd == NULL) {
50     return NULL;
51   }
52 
53   Qtd->Signature    = EHC_QTD_SIG;
54   Qtd->Data         = Data;
55   Qtd->DataLen      = 0;
56 
57   InitializeListHead (&Qtd->QtdList);
58 
59   QtdHw             = &Qtd->QtdHw;
60   QtdHw->NextQtd    = QTD_LINK (NULL, TRUE);
61   QtdHw->AltNext    = QTD_LINK (NULL, TRUE);
62   QtdHw->Status     = QTD_STAT_ACTIVE;
63   QtdHw->Pid        = PktId;
64   QtdHw->ErrCnt     = QTD_MAX_ERR;
65   QtdHw->Ioc        = 0;
66   QtdHw->TotalBytes = 0;
67   QtdHw->DataToggle = Toggle;
68 
69   //
70   // Fill in the buffer points
71   //
72   if (Data != NULL) {
73     Len = 0;
74 
75     for (Index = 0; Index <= QTD_MAX_BUFFER; Index++) {
76       //
77       // Set the buffer point (Check page 41 EHCI Spec 1.0). No need to
78       // compute the offset and clear Reserved fields. This is already
79       // done in the data point.
80       //
81       QtdHw->Page[Index]      = EHC_LOW_32BIT (DataPhy);
82       QtdHw->PageHigh[Index]  = EHC_HIGH_32BIT (DataPhy);
83 
84       ThisBufLen              = QTD_BUF_LEN - (EHC_LOW_32BIT (DataPhy) & QTD_BUF_MASK);
85 
86       if (Len + ThisBufLen >= DataLen) {
87         Len = DataLen;
88         break;
89       }
90 
91       Len += ThisBufLen;
92       Data += ThisBufLen;
93       DataPhy += ThisBufLen;
94     }
95 
96     //
97     // Need to fix the last pointer if the Qtd can't hold all the
98     // user's data to make sure that the length is in the unit of
99     // max packets. If it can hold all the data, there is no such
100     // need.
101     //
102     if (Len < DataLen) {
103       Len = Len - Len % MaxPacket;
104     }
105 
106     QtdHw->TotalBytes = (UINT32) Len;
107     Qtd->DataLen      = Len;
108   }
109 
110   return Qtd;
111 }
112 
113 
114 
115 /**
116   Initialize the queue head for interrupt transfer,
117   that is, initialize the following three fields:
118   1. SplitXState in the Status field
119   2. Microframe S-mask
120   3. Microframe C-mask
121 
122   @param  Ep                    The queue head's related endpoint.
123   @param  QhHw                  The queue head to initialize.
124 
125 **/
126 VOID
EhcInitIntQh(IN USB_ENDPOINT * Ep,IN QH_HW * QhHw)127 EhcInitIntQh (
128   IN USB_ENDPOINT         *Ep,
129   IN QH_HW                *QhHw
130   )
131 {
132   //
133   // Because UEFI interface can't utilitize an endpoint with
134   // poll rate faster than 1ms, only need to set one bit in
135   // the queue head. simple. But it may be changed later. If
136   // sub-1ms interrupt is supported, need to update the S-Mask
137   // here
138   //
139   if (Ep->DevSpeed == EFI_USB_SPEED_HIGH) {
140     QhHw->SMask = QH_MICROFRAME_0;
141     return ;
142   }
143 
144   //
145   // For low/full speed device, the transfer must go through
146   // the split transaction. Need to update three fields
147   // 1. SplitXState in the status
148   // 2. Microframe S-Mask
149   // 3. Microframe C-Mask
150   // UEFI USB doesn't exercise admission control. It simplely
151   // schedule the high speed transactions in microframe 0, and
152   // full/low speed transactions at microframe 1. This also
153   // avoid the use of FSTN.
154   //
155   QhHw->SMask = QH_MICROFRAME_1;
156   QhHw->CMask = QH_MICROFRAME_3 | QH_MICROFRAME_4 | QH_MICROFRAME_5;
157 }
158 
159 
160 
161 /**
162   Allocate and initialize a EHCI queue head.
163 
164   @param  Ehci                  The EHCI device.
165   @param  Ep                    The endpoint to create queue head for.
166 
167   @return Created queue head or NULL if failed to create one.
168 
169 **/
170 EHC_QH *
EhcCreateQh(IN USB2_HC_DEV * Ehci,IN USB_ENDPOINT * Ep)171 EhcCreateQh (
172   IN USB2_HC_DEV          *Ehci,
173   IN USB_ENDPOINT         *Ep
174   )
175 {
176   EHC_QH                  *Qh;
177   QH_HW                   *QhHw;
178 
179   Qh = UsbHcAllocateMem (Ehci->MemPool, sizeof (EHC_QH));
180 
181   if (Qh == NULL) {
182     return NULL;
183   }
184 
185   Qh->Signature       = EHC_QH_SIG;
186   Qh->NextQh          = NULL;
187   Qh->Interval        = Ep->PollRate;
188 
189   InitializeListHead (&Qh->Qtds);
190 
191   QhHw                = &Qh->QhHw;
192   QhHw->HorizonLink   = QH_LINK (NULL, 0, TRUE);
193   QhHw->DeviceAddr    = Ep->DevAddr;
194   QhHw->Inactive      = 0;
195   QhHw->EpNum         = Ep->EpAddr;
196   QhHw->EpSpeed       = Ep->DevSpeed;
197   QhHw->DtCtrl        = 0;
198   QhHw->ReclaimHead   = 0;
199   QhHw->MaxPacketLen  = (UINT32) Ep->MaxPacket;
200   QhHw->CtrlEp        = 0;
201   QhHw->NakReload     = QH_NAK_RELOAD;
202   QhHw->HubAddr       = Ep->HubAddr;
203   QhHw->PortNum       = Ep->HubPort;
204   QhHw->Multiplier    = 1;
205   QhHw->DataToggle    = Ep->Toggle;
206 
207   if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) {
208     QhHw->Status |= QTD_STAT_DO_SS;
209   }
210 
211   switch (Ep->Type) {
212   case EHC_CTRL_TRANSFER:
213     //
214     // Special initialization for the control transfer:
215     // 1. Control transfer initialize data toggle from each QTD
216     // 2. Set the Control Endpoint Flag (C) for low/full speed endpoint.
217     //
218     QhHw->DtCtrl = 1;
219 
220     if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) {
221       QhHw->CtrlEp = 1;
222     }
223     break;
224 
225   case EHC_INT_TRANSFER_ASYNC:
226   case EHC_INT_TRANSFER_SYNC:
227     //
228     // Special initialization for the interrupt transfer
229     // to set the S-Mask and C-Mask
230     //
231     QhHw->NakReload = 0;
232     EhcInitIntQh (Ep, QhHw);
233     break;
234 
235   case EHC_BULK_TRANSFER:
236     if ((Ep->DevSpeed == EFI_USB_SPEED_HIGH) && (Ep->Direction == EfiUsbDataOut)) {
237       QhHw->Status |= QTD_STAT_DO_PING;
238     }
239 
240     break;
241   }
242 
243   return Qh;
244 }
245 
246 
247 /**
248   Convert the poll interval from application to that
249   be used by EHCI interface data structure. Only need
250   to get the max 2^n that is less than interval. UEFI
251   can't support high speed endpoint with a interval less
252   than 8 microframe because interval is specified in
253   the unit of ms (millisecond).
254 
255   @param  Interval              The interval to convert.
256 
257   @return The converted interval.
258 
259 **/
260 UINTN
EhcConvertPollRate(IN UINTN Interval)261 EhcConvertPollRate (
262   IN  UINTN               Interval
263   )
264 {
265   UINTN                   BitCount;
266 
267   if (Interval == 0) {
268     return 1;
269   }
270 
271   //
272   // Find the index (1 based) of the highest non-zero bit
273   //
274   BitCount = 0;
275 
276   while (Interval != 0) {
277     Interval >>= 1;
278     BitCount++;
279   }
280 
281   return (UINTN)1 << (BitCount - 1);
282 }
283 
284 
285 /**
286   Free a list of QTDs.
287 
288   @param  Ehc                   The EHCI device.
289   @param  Qtds                  The list head of the QTD.
290 
291 **/
292 VOID
EhcFreeQtds(IN USB2_HC_DEV * Ehc,IN LIST_ENTRY * Qtds)293 EhcFreeQtds (
294   IN USB2_HC_DEV          *Ehc,
295   IN LIST_ENTRY           *Qtds
296   )
297 {
298   LIST_ENTRY              *Entry;
299   LIST_ENTRY              *Next;
300   EHC_QTD                 *Qtd;
301 
302   EFI_LIST_FOR_EACH_SAFE (Entry, Next, Qtds) {
303     Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList);
304 
305     RemoveEntryList (&Qtd->QtdList);
306     UsbHcFreeMem (Ehc->MemPool, Qtd, sizeof (EHC_QTD));
307   }
308 }
309 
310 
311 /**
312   Free an allocated URB. It is possible for it to be partially inited.
313 
314   @param  Ehc                   The EHCI device.
315   @param  Urb                   The URB to free.
316 
317 **/
318 VOID
EhcFreeUrb(IN USB2_HC_DEV * Ehc,IN URB * Urb)319 EhcFreeUrb (
320   IN USB2_HC_DEV          *Ehc,
321   IN URB                  *Urb
322   )
323 {
324   EFI_PCI_IO_PROTOCOL       *PciIo;
325 
326   PciIo = Ehc->PciIo;
327 
328   if (Urb->RequestPhy != NULL) {
329     PciIo->Unmap (PciIo, Urb->RequestMap);
330   }
331 
332   if (Urb->DataMap != NULL) {
333     PciIo->Unmap (PciIo, Urb->DataMap);
334   }
335 
336   if (Urb->Qh != NULL) {
337     //
338     // Ensure that this queue head has been unlinked from the
339     // schedule data structures. Free all the associated QTDs
340     //
341     EhcFreeQtds (Ehc, &Urb->Qh->Qtds);
342     UsbHcFreeMem (Ehc->MemPool, Urb->Qh, sizeof (EHC_QH));
343   }
344 
345   gBS->FreePool (Urb);
346 }
347 
348 
349 /**
350   Create a list of QTDs for the URB.
351 
352   @param  Ehc                   The EHCI device.
353   @param  Urb                   The URB to create QTDs for.
354 
355   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource for QTD.
356   @retval EFI_SUCCESS           The QTDs are allocated for the URB.
357 
358 **/
359 EFI_STATUS
EhcCreateQtds(IN USB2_HC_DEV * Ehc,IN URB * Urb)360 EhcCreateQtds (
361   IN USB2_HC_DEV          *Ehc,
362   IN URB                  *Urb
363   )
364 {
365   USB_ENDPOINT            *Ep;
366   EHC_QH                  *Qh;
367   EHC_QTD                 *Qtd;
368   EHC_QTD                 *StatusQtd;
369   EHC_QTD                 *NextQtd;
370   LIST_ENTRY              *Entry;
371   UINT32                  AlterNext;
372   UINT8                   Toggle;
373   UINTN                   Len;
374   UINT8                   Pid;
375   EFI_PHYSICAL_ADDRESS    PhyAddr;
376 
377   ASSERT ((Urb != NULL) && (Urb->Qh != NULL));
378 
379   //
380   // EHCI follows the alternet next QTD pointer if it meets
381   // a short read and the AlterNext pointer is valid. UEFI
382   // EHCI driver should terminate the transfer except the
383   // control transfer.
384   //
385   Toggle    = 0;
386   Qh        = Urb->Qh;
387   Ep        = &Urb->Ep;
388   StatusQtd = NULL;
389   AlterNext = QTD_LINK (NULL, TRUE);
390 
391   PhyAddr   = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));
392   if (Ep->Direction == EfiUsbDataIn) {
393     AlterNext = QTD_LINK (PhyAddr, FALSE);
394   }
395 
396   //
397   // Build the Setup and status packets for control transfer
398   //
399   if (Urb->Ep.Type == EHC_CTRL_TRANSFER) {
400     Len = sizeof (EFI_USB_DEVICE_REQUEST);
401     Qtd = EhcCreateQtd (Ehc, (UINT8 *)Urb->Request, (UINT8 *)Urb->RequestPhy, Len, QTD_PID_SETUP, 0, Ep->MaxPacket);
402 
403     if (Qtd == NULL) {
404       return EFI_OUT_OF_RESOURCES;
405     }
406 
407     InsertTailList (&Qh->Qtds, &Qtd->QtdList);
408 
409     //
410     // Create the status packet now. Set the AlterNext to it. So, when
411     // EHCI meets a short control read, it can resume at the status stage.
412     // Use the opposite direction of the data stage, or IN if there is
413     // no data stage.
414     //
415     if (Ep->Direction == EfiUsbDataIn) {
416       Pid = QTD_PID_OUTPUT;
417     } else {
418       Pid = QTD_PID_INPUT;
419     }
420 
421     StatusQtd = EhcCreateQtd (Ehc, NULL, NULL, 0, Pid, 1, Ep->MaxPacket);
422 
423     if (StatusQtd == NULL) {
424       goto ON_ERROR;
425     }
426 
427     if (Ep->Direction == EfiUsbDataIn) {
428       PhyAddr   = UsbHcGetPciAddressForHostMem (Ehc->MemPool, StatusQtd, sizeof (EHC_QTD));
429       AlterNext = QTD_LINK (PhyAddr, FALSE);
430     }
431 
432     Toggle = 1;
433   }
434 
435   //
436   // Build the data packets for all the transfers
437   //
438   if (Ep->Direction == EfiUsbDataIn) {
439     Pid = QTD_PID_INPUT;
440   } else {
441     Pid = QTD_PID_OUTPUT;
442   }
443 
444   Qtd = NULL;
445   Len = 0;
446 
447   while (Len < Urb->DataLen) {
448     Qtd = EhcCreateQtd (
449             Ehc,
450             (UINT8 *) Urb->Data + Len,
451             (UINT8 *) Urb->DataPhy + Len,
452             Urb->DataLen - Len,
453             Pid,
454             Toggle,
455             Ep->MaxPacket
456             );
457 
458     if (Qtd == NULL) {
459       goto ON_ERROR;
460     }
461 
462     Qtd->QtdHw.AltNext = AlterNext;
463     InsertTailList (&Qh->Qtds, &Qtd->QtdList);
464 
465     //
466     // Switch the Toggle bit if odd number of packets are included in the QTD.
467     //
468     if (((Qtd->DataLen + Ep->MaxPacket - 1) / Ep->MaxPacket) % 2) {
469       Toggle = (UINT8) (1 - Toggle);
470     }
471 
472     Len += Qtd->DataLen;
473   }
474 
475   //
476   // Insert the status packet for control transfer
477   //
478   if (Ep->Type == EHC_CTRL_TRANSFER) {
479     InsertTailList (&Qh->Qtds, &StatusQtd->QtdList);
480   }
481 
482   //
483   // OK, all the QTDs needed are created. Now, fix the NextQtd point
484   //
485   EFI_LIST_FOR_EACH (Entry, &Qh->Qtds) {
486     Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList);
487 
488     //
489     // break if it is the last entry on the list
490     //
491     if (Entry->ForwardLink == &Qh->Qtds) {
492       break;
493     }
494 
495     NextQtd             = EFI_LIST_CONTAINER (Entry->ForwardLink, EHC_QTD, QtdList);
496     PhyAddr             = UsbHcGetPciAddressForHostMem (Ehc->MemPool, NextQtd, sizeof (EHC_QTD));
497     Qtd->QtdHw.NextQtd  = QTD_LINK (PhyAddr, FALSE);
498   }
499 
500   //
501   // Link the QTDs to the queue head
502   //
503   NextQtd           = EFI_LIST_CONTAINER (Qh->Qtds.ForwardLink, EHC_QTD, QtdList);
504   PhyAddr           = UsbHcGetPciAddressForHostMem (Ehc->MemPool, NextQtd, sizeof (EHC_QTD));
505   Qh->QhHw.NextQtd  = QTD_LINK (PhyAddr, FALSE);
506   return EFI_SUCCESS;
507 
508 ON_ERROR:
509   EhcFreeQtds (Ehc, &Qh->Qtds);
510   return EFI_OUT_OF_RESOURCES;
511 }
512 
513 
514 /**
515   Create a new URB and its associated QTD.
516 
517   @param  Ehc                   The EHCI device.
518   @param  DevAddr               The device address.
519   @param  EpAddr                Endpoint addrress & its direction.
520   @param  DevSpeed              The device speed.
521   @param  Toggle                Initial data toggle to use.
522   @param  MaxPacket             The max packet length of the endpoint.
523   @param  Hub                   The transaction translator to use.
524   @param  Type                  The transaction type.
525   @param  Request               The standard USB request for control transfer.
526   @param  Data                  The user data to transfer.
527   @param  DataLen               The length of data buffer.
528   @param  Callback              The function to call when data is transferred.
529   @param  Context               The context to the callback.
530   @param  Interval              The interval for interrupt transfer.
531 
532   @return Created URB or NULL.
533 
534 **/
535 URB *
EhcCreateUrb(IN USB2_HC_DEV * Ehc,IN UINT8 DevAddr,IN UINT8 EpAddr,IN UINT8 DevSpeed,IN UINT8 Toggle,IN UINTN MaxPacket,IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Hub,IN UINTN Type,IN EFI_USB_DEVICE_REQUEST * Request,IN VOID * Data,IN UINTN DataLen,IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,IN VOID * Context,IN UINTN Interval)536 EhcCreateUrb (
537   IN USB2_HC_DEV                        *Ehc,
538   IN UINT8                              DevAddr,
539   IN UINT8                              EpAddr,
540   IN UINT8                              DevSpeed,
541   IN UINT8                              Toggle,
542   IN UINTN                              MaxPacket,
543   IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub,
544   IN UINTN                              Type,
545   IN EFI_USB_DEVICE_REQUEST             *Request,
546   IN VOID                               *Data,
547   IN UINTN                              DataLen,
548   IN EFI_ASYNC_USB_TRANSFER_CALLBACK    Callback,
549   IN VOID                               *Context,
550   IN UINTN                              Interval
551   )
552 {
553   USB_ENDPOINT                  *Ep;
554   EFI_PHYSICAL_ADDRESS          PhyAddr;
555   EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
556   EFI_PCI_IO_PROTOCOL           *PciIo;
557   EFI_STATUS                    Status;
558   UINTN                         Len;
559   URB                           *Urb;
560   VOID                          *Map;
561 
562   Urb = AllocateZeroPool (sizeof (URB));
563 
564   if (Urb == NULL) {
565     return NULL;
566   }
567 
568   Urb->Signature  = EHC_URB_SIG;
569   InitializeListHead (&Urb->UrbList);
570 
571   Ep              = &Urb->Ep;
572   Ep->DevAddr     = DevAddr;
573   Ep->EpAddr      = (UINT8) (EpAddr & 0x0F);
574   Ep->Direction   = (((EpAddr & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut);
575   Ep->DevSpeed    = DevSpeed;
576   Ep->MaxPacket   = MaxPacket;
577 
578   Ep->HubAddr     = 0;
579   Ep->HubPort     = 0;
580 
581   if (DevSpeed != EFI_USB_SPEED_HIGH) {
582     ASSERT (Hub != NULL);
583 
584     Ep->HubAddr   = Hub->TranslatorHubAddress;
585     Ep->HubPort   = Hub->TranslatorPortNumber;
586   }
587 
588   Ep->Toggle      = Toggle;
589   Ep->Type        = Type;
590   Ep->PollRate    = EhcConvertPollRate (Interval);
591 
592   Urb->Request    = Request;
593   Urb->Data       = Data;
594   Urb->DataLen    = DataLen;
595   Urb->Callback   = Callback;
596   Urb->Context    = Context;
597 
598   PciIo           = Ehc->PciIo;
599   Urb->Qh         = EhcCreateQh (Ehc, &Urb->Ep);
600 
601   if (Urb->Qh == NULL) {
602     goto ON_ERROR;
603   }
604 
605   //
606   // Map the request and user data
607   //
608   if (Request != NULL) {
609     Len     = sizeof (EFI_USB_DEVICE_REQUEST);
610     MapOp   = EfiPciIoOperationBusMasterRead;
611     Status  = PciIo->Map (PciIo, MapOp, Request, &Len, &PhyAddr, &Map);
612 
613     if (EFI_ERROR (Status) || (Len != sizeof (EFI_USB_DEVICE_REQUEST))) {
614       goto ON_ERROR;
615     }
616 
617     Urb->RequestPhy = (VOID *) ((UINTN) PhyAddr);
618     Urb->RequestMap = Map;
619   }
620 
621   if (Data != NULL) {
622     Len     = DataLen;
623 
624     if (Ep->Direction == EfiUsbDataIn) {
625       MapOp = EfiPciIoOperationBusMasterWrite;
626     } else {
627       MapOp = EfiPciIoOperationBusMasterRead;
628     }
629 
630     Status  = PciIo->Map (PciIo, MapOp, Data, &Len, &PhyAddr, &Map);
631 
632     if (EFI_ERROR (Status) || (Len != DataLen)) {
633       goto ON_ERROR;
634     }
635 
636     Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);
637     Urb->DataMap  = Map;
638   }
639 
640   Status = EhcCreateQtds (Ehc, Urb);
641 
642   if (EFI_ERROR (Status)) {
643     goto ON_ERROR;
644   }
645 
646   return Urb;
647 
648 ON_ERROR:
649   EhcFreeUrb (Ehc, Urb);
650   return NULL;
651 }
652