1. Sync Tcp4 protocol definitions to match UEFI 2.1
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Bus / Pci / UhciDxe / Uhci.c
1 /** @file\r
2 \r
3 Copyright (c) 2004 - 2007, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   Uhci.c\r
15 \r
16 Abstract:\r
17 \r
18   The UHCI driver model and HC protocol routines.\r
19 \r
20 Revision History\r
21 \r
22 \r
23 **/\r
24 \r
25 #include "Uhci.h"\r
26 \r
27 \r
28 /**\r
29   Provides software reset for the USB host controller.\r
30 \r
31   This      : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
32   Attributes: A bit mask of the reset operation to perform.\r
33 \r
34   @return EFI_SUCCESS           : The reset operation succeeded.\r
35   @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
36   @return EFI_DEVICE_ERROR      : An error was encountered while attempting\r
37   @return to perform the reset operation.\r
38 \r
39 **/\r
40 STATIC\r
41 EFI_STATUS\r
42 EFIAPI\r
43 UhciReset (\r
44   IN EFI_USB_HC_PROTOCOL     *This,\r
45   IN UINT16                  Attributes\r
46   )\r
47 {\r
48   USB_HC_DEV          *Uhc;\r
49   EFI_TPL             OldTpl;\r
50 \r
51   OldTpl  = gBS->RaiseTPL (UHCI_TPL);\r
52   Uhc     = UHC_FROM_USB_HC_PROTO (This);\r
53 \r
54   switch (Attributes) {\r
55   case EFI_USB_HC_RESET_GLOBAL:\r
56     //\r
57     // Stop schedule and set the Global Reset bit in the command register\r
58     //\r
59     UhciStopHc (Uhc, STALL_1_SECOND);\r
60     UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
61 \r
62     //\r
63     // Wait 50ms for root port to let reset complete\r
64     // See UHCI spec page122 Reset signaling\r
65     //\r
66     gBS->Stall (ROOT_PORT_REST_TIME);\r
67 \r
68     //\r
69     // Clear the Global Reset bit to zero.\r
70     //\r
71     UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
72 \r
73     //\r
74     // UHCI spec page120 reset recovery time\r
75     //\r
76     gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
77     break;\r
78 \r
79   case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
80     //\r
81     // Stop schedule and set Host Controller Reset bit to 1\r
82     //\r
83     UhciStopHc (Uhc, STALL_1_SECOND);\r
84     UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);\r
85 \r
86     //\r
87     // this bit will be reset by Host Controller when reset is completed.\r
88     // wait 10ms to let reset complete\r
89     //\r
90     gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
91     break;\r
92 \r
93   default:\r
94     goto ON_INVAILD_PARAMETER;\r
95   }\r
96 \r
97   //\r
98   // Delete all old transactions on the USB bus, then\r
99   // reinitialize the frame list\r
100   //\r
101   UhciFreeAllAsyncReq (Uhc);\r
102   UhciDestoryFrameList (Uhc);\r
103   UhciInitFrameList (Uhc);\r
104 \r
105   gBS->RestoreTPL (OldTpl);\r
106 \r
107   return EFI_SUCCESS;\r
108 \r
109 ON_INVAILD_PARAMETER:\r
110 \r
111   gBS->RestoreTPL (OldTpl);\r
112 \r
113   return EFI_INVALID_PARAMETER;\r
114 }\r
115 \r
116 \r
117 /**\r
118   Retrieves current state of the USB host controller.\r
119 \r
120   This    :  A pointer to the EFI_USB_HC_PROTOCOL instance.\r
121   State   :  A pointer to the EFI_USB_HC_STATE data structure that\r
122   indicates current state of the USB host controller.\r
123 \r
124   @return EFI_SUCCESS           : State was returned\r
125   @return EFI_INVALID_PARAMETER : State is NULL.\r
126   @return EFI_DEVICE_ERROR      : An error was encountered\r
127 \r
128 **/\r
129 STATIC\r
130 EFI_STATUS\r
131 EFIAPI\r
132 UhciGetState (\r
133   IN  EFI_USB_HC_PROTOCOL     *This,\r
134   OUT EFI_USB_HC_STATE        *State\r
135   )\r
136 {\r
137   USB_HC_DEV          *Uhc;\r
138   UINT16              UsbSts;\r
139   UINT16              UsbCmd;\r
140 \r
141   if (State == NULL) {\r
142     return EFI_INVALID_PARAMETER;\r
143   }\r
144 \r
145   Uhc     = UHC_FROM_USB_HC_PROTO (This);\r
146 \r
147   UsbCmd  = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
148   UsbSts  = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);\r
149 \r
150   if (UsbCmd & USBCMD_EGSM) {\r
151     *State = EfiUsbHcStateSuspend;\r
152 \r
153   } else if ((UsbSts & USBSTS_HCH) != 0) {\r
154     *State = EfiUsbHcStateHalt;\r
155 \r
156   } else {\r
157     *State = EfiUsbHcStateOperational;\r
158   }\r
159 \r
160   return EFI_SUCCESS;\r
161 }\r
162 \r
163 \r
164 /**\r
165   Sets the USB host controller to a specific state.\r
166 \r
167   This     : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
168   State    : Indicates the state of the host controller that will be set.\r
169 \r
170   @return EFI_SUCCESS           : The USB host controller was successfully set\r
171   @return EFI_INVALID_PARAMETER : State is invalid.\r
172   @return EFI_DEVICE_ERROR      : Failed to set the state specified\r
173 \r
174 **/\r
175 STATIC\r
176 EFI_STATUS\r
177 EFIAPI\r
178 UhciSetState (\r
179   IN EFI_USB_HC_PROTOCOL     *This,\r
180   IN EFI_USB_HC_STATE        State\r
181   )\r
182 {\r
183   EFI_USB_HC_STATE    CurState;\r
184   USB_HC_DEV          *Uhc;\r
185   EFI_TPL             OldTpl;\r
186   EFI_STATUS          Status;\r
187   UINT16              UsbCmd;\r
188 \r
189   Uhc     = UHC_FROM_USB_HC_PROTO (This);\r
190   Status  = UhciGetState (This, &CurState);\r
191 \r
192   if (EFI_ERROR (Status)) {\r
193     return EFI_DEVICE_ERROR;\r
194   }\r
195 \r
196   if (CurState == State) {\r
197     return EFI_SUCCESS;\r
198   }\r
199 \r
200   Status  = EFI_SUCCESS;\r
201   OldTpl  = gBS->RaiseTPL (UHCI_TPL);\r
202 \r
203   switch (State) {\r
204   case EfiUsbHcStateHalt:\r
205     Status = UhciStopHc (Uhc, STALL_1_SECOND);\r
206     break;\r
207 \r
208   case EfiUsbHcStateOperational:\r
209     UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
210 \r
211     if (CurState == EfiUsbHcStateHalt) {\r
212       //\r
213       // Set Run/Stop bit to 1, also set the bandwidht reclamation\r
214       // point to 64 bytes\r
215       //\r
216       UsbCmd |= USBCMD_RS | USBCMD_MAXP;\r
217       UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
218 \r
219     } else if (CurState == EfiUsbHcStateSuspend) {\r
220       //\r
221       // If FGR(Force Global Resume) bit is 0, set it\r
222       //\r
223       if ((UsbCmd & USBCMD_FGR) == 0) {\r
224         UsbCmd |= USBCMD_FGR;\r
225         UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
226       }\r
227 \r
228       //\r
229       // wait 20ms to let resume complete (20ms is specified by UHCI spec)\r
230       //\r
231       gBS->Stall (FORCE_GLOBAL_RESUME_TIME);\r
232 \r
233       //\r
234       // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
235       //\r
236       UsbCmd &= ~USBCMD_FGR;\r
237       UsbCmd &= ~USBCMD_EGSM;\r
238       UsbCmd |= USBCMD_RS;\r
239       UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
240     }\r
241 \r
242     break;\r
243 \r
244   case EfiUsbHcStateSuspend:\r
245     Status = UhciSetState (This, EfiUsbHcStateHalt);\r
246 \r
247     if (EFI_ERROR (Status)) {\r
248       Status = EFI_DEVICE_ERROR;\r
249       goto ON_EXIT;\r
250     }\r
251 \r
252     //\r
253     // Set Enter Global Suspend Mode bit to 1.\r
254     //\r
255     UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
256     UsbCmd |= USBCMD_EGSM;\r
257     UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
258     break;\r
259 \r
260   default:\r
261     Status = EFI_INVALID_PARAMETER;\r
262     break;\r
263   }\r
264 \r
265 ON_EXIT:\r
266   gBS->RestoreTPL (OldTpl);\r
267   return Status;\r
268 }\r
269 \r
270 \r
271 /**\r
272   Retrieves the number of root hub ports.\r
273 \r
274   This       : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
275   PortNumber : A pointer to the number of the root hub ports.\r
276 \r
277   @return EFI_SUCCESS           : The port number was retrieved successfully.\r
278   @return EFI_INVALID_PARAMETER : PortNumber is NULL.\r
279   @return EFI_DEVICE_ERROR      : An error was encountered\r
280 \r
281 **/\r
282 STATIC\r
283 EFI_STATUS\r
284 EFIAPI\r
285 UhciGetRootHubPortNumber (\r
286   IN  EFI_USB_HC_PROTOCOL     *This,\r
287   OUT UINT8                   *PortNumber\r
288   )\r
289 {\r
290   USB_HC_DEV          *Uhc;\r
291   UINT32              Offset;\r
292   UINT16              PortSC;\r
293   UINT32              Index;\r
294 \r
295   Uhc = UHC_FROM_USB_HC_PROTO (This);\r
296 \r
297   if (PortNumber == NULL) {\r
298     return EFI_INVALID_PARAMETER;\r
299   }\r
300 \r
301   *PortNumber = 0;\r
302 \r
303   for (Index = 0; Index < USB_MAX_ROOTHUB_PORT; Index++) {\r
304     Offset  = USBPORTSC_OFFSET + Index * 2;\r
305     PortSC  = UhciReadReg (Uhc->PciIo, Offset);\r
306 \r
307     //\r
308     // Port status's bit 7 is reserved and always returns 1 if\r
309     // the port number is valid. Intel's UHCI (in EHCI controller)\r
310     // returns 0 in this bit if port number is invalid. Also, if\r
311     // PciIo IoRead returns error, 0xFFFF is returned to caller.\r
312     //\r
313     if (((PortSC & 0x80) != 0) && (PortSC != 0xFFFF)) {\r
314       (*PortNumber)++;\r
315     }\r
316   }\r
317 \r
318   Uhc->RootPorts = *PortNumber;\r
319 \r
320   UHCI_DEBUG (("UhciGetRootHubPortNumber: %d ports\n", Uhc->RootPorts));\r
321   return EFI_SUCCESS;\r
322 }\r
323 \r
324 \r
325 /**\r
326   Retrieves the current status of a USB root hub port.\r
327 \r
328   This        : A pointer to the EFI_USB_HC_PROTOCOL.\r
329   PortNumber  : Specifies the root hub port. This value is zero-based.\r
330   PortStatus  : A pointer to the current port status bits and port status change bits.\r
331 \r
332   @return EFI_SUCCESS           : The port status was returned in PortStatus.\r
333   @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
334   @return EFI_DEVICE_ERROR      : Can't read register\r
335 \r
336 **/\r
337 EFI_STATUS\r
338 EFIAPI\r
339 UhciGetRootHubPortStatus (\r
340   IN  EFI_USB_HC_PROTOCOL     *This,\r
341   IN  UINT8                   PortNumber,\r
342   OUT EFI_USB_PORT_STATUS     *PortStatus\r
343   )\r
344 {\r
345   USB_HC_DEV          *Uhc;\r
346   UINT32              Offset;\r
347   UINT16              PortSC;\r
348 \r
349   Uhc = UHC_FROM_USB_HC_PROTO (This);\r
350 \r
351   if (PortStatus == NULL) {\r
352     return EFI_INVALID_PARAMETER;\r
353   }\r
354 \r
355   if (PortNumber >= Uhc->RootPorts) {\r
356     return EFI_INVALID_PARAMETER;\r
357   }\r
358 \r
359   Offset                        = USBPORTSC_OFFSET + PortNumber * 2;\r
360   PortStatus->PortStatus        = 0;\r
361   PortStatus->PortChangeStatus  = 0;\r
362 \r
363   PortSC                        = UhciReadReg (Uhc->PciIo, Offset);\r
364 \r
365   if (PortSC & USBPORTSC_CCS) {\r
366     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
367   }\r
368 \r
369   if (PortSC & USBPORTSC_PED) {\r
370     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
371   }\r
372 \r
373   if (PortSC & USBPORTSC_SUSP) {\r
374     UHCI_DEBUG (("UhciGetRootHubPortStatus: port %d is suspended\n", PortNumber));\r
375     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
376   }\r
377 \r
378   if (PortSC & USBPORTSC_PR) {\r
379     PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
380   }\r
381 \r
382   if (PortSC & USBPORTSC_LSDA) {\r
383     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
384   }\r
385 \r
386   //\r
387   // CHC will always return one in port owner bit\r
388   //\r
389   PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
390 \r
391   if (PortSC & USBPORTSC_CSC) {\r
392     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
393   }\r
394 \r
395   if (PortSC & USBPORTSC_PEDC) {\r
396     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
397   }\r
398 \r
399   return EFI_SUCCESS;\r
400 }\r
401 \r
402 \r
403 /**\r
404   Sets a feature for the specified root hub port.\r
405 \r
406   This        : A pointer to the EFI_USB_HC_PROTOCOL.\r
407   PortNumber  : Specifies the root hub port whose feature\r
408   is requested to be set.\r
409   PortFeature : Indicates the feature selector associated\r
410   with the feature set request.\r
411 \r
412   @return EFI_SUCCESS           : The feature was set for the port.\r
413   @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
414   @return EFI_DEVICE_ERROR      : Can't read register\r
415 \r
416 **/\r
417 STATIC\r
418 EFI_STATUS\r
419 EFIAPI\r
420 UhciSetRootHubPortFeature (\r
421   IN  EFI_USB_HC_PROTOCOL     *This,\r
422   IN  UINT8                   PortNumber,\r
423   IN  EFI_USB_PORT_FEATURE    PortFeature\r
424   )\r
425 {\r
426   USB_HC_DEV          *Uhc;\r
427   EFI_TPL             OldTpl;\r
428   UINT32              Offset;\r
429   UINT16              PortSC;\r
430   UINT16              Command;\r
431 \r
432   Uhc = UHC_FROM_USB_HC_PROTO (This);\r
433 \r
434   if (PortNumber >= Uhc->RootPorts) {\r
435     return EFI_INVALID_PARAMETER;\r
436   }\r
437 \r
438   Offset  = USBPORTSC_OFFSET + PortNumber * 2;\r
439 \r
440   OldTpl  = gBS->RaiseTPL (UHCI_TPL);\r
441   PortSC  = UhciReadReg (Uhc->PciIo, Offset);\r
442 \r
443   switch (PortFeature) {\r
444   case EfiUsbPortSuspend:\r
445     Command = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
446     if (!(Command & USBCMD_EGSM)) {\r
447       //\r
448       // if global suspend is not active, can set port suspend\r
449       //\r
450       PortSC &= 0xfff5;\r
451       PortSC |= USBPORTSC_SUSP;\r
452     }\r
453     break;\r
454 \r
455   case EfiUsbPortReset:\r
456     PortSC &= 0xfff5;\r
457     PortSC |= USBPORTSC_PR;\r
458     break;\r
459 \r
460   case EfiUsbPortPower:\r
461     //\r
462     // No action\r
463     //\r
464     break;\r
465 \r
466   case EfiUsbPortEnable:\r
467     PortSC &= 0xfff5;\r
468     PortSC |= USBPORTSC_PED;\r
469     break;\r
470 \r
471   default:\r
472     gBS->RestoreTPL (OldTpl);\r
473     return EFI_INVALID_PARAMETER;\r
474   }\r
475 \r
476   UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
477   gBS->RestoreTPL (OldTpl);\r
478 \r
479   return EFI_SUCCESS;\r
480 }\r
481 \r
482 \r
483 /**\r
484   Clears a feature for the specified root hub port.\r
485 \r
486   This        : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
487   PortNumber  : Specifies the root hub port whose feature\r
488   is requested to be cleared.\r
489   PortFeature : Indicates the feature selector associated with the\r
490   feature clear request.\r
491 \r
492   @return EFI_SUCCESS           : The feature was cleared for the port.\r
493   @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
494   @return EFI_DEVICE_ERROR      : Can't read register\r
495 \r
496 **/\r
497 STATIC\r
498 EFI_STATUS\r
499 EFIAPI\r
500 UhciClearRootHubPortFeature (\r
501   IN  EFI_USB_HC_PROTOCOL     *This,\r
502   IN  UINT8                   PortNumber,\r
503   IN  EFI_USB_PORT_FEATURE    PortFeature\r
504   )\r
505 {\r
506   USB_HC_DEV          *Uhc;\r
507   EFI_TPL             OldTpl;\r
508   UINT32              Offset;\r
509   UINT16              PortSC;\r
510 \r
511   Uhc = UHC_FROM_USB_HC_PROTO (This);\r
512 \r
513   if (PortNumber >= Uhc->RootPorts) {\r
514     return EFI_INVALID_PARAMETER;\r
515   }\r
516 \r
517   Offset  = USBPORTSC_OFFSET + PortNumber * 2;\r
518 \r
519   OldTpl  = gBS->RaiseTPL (UHCI_TPL);\r
520   PortSC  = UhciReadReg (Uhc->PciIo, Offset);\r
521 \r
522   switch (PortFeature) {\r
523   case EfiUsbPortEnable:\r
524     PortSC &= 0xfff5;\r
525     PortSC &= ~USBPORTSC_PED;\r
526     break;\r
527 \r
528   case EfiUsbPortSuspend:\r
529     //\r
530     // Cause a resume on the specified port if in suspend mode.\r
531     //\r
532     PortSC &= 0xfff5;\r
533     PortSC &= ~USBPORTSC_SUSP;\r
534     break;\r
535 \r
536   case EfiUsbPortPower:\r
537     //\r
538     // No action\r
539     //\r
540     break;\r
541 \r
542   case EfiUsbPortReset:\r
543     PortSC &= 0xfff5;\r
544     PortSC &= ~USBPORTSC_PR;\r
545     break;\r
546 \r
547   case EfiUsbPortConnectChange:\r
548     PortSC &= 0xfff5;\r
549     PortSC |= USBPORTSC_CSC;\r
550     break;\r
551 \r
552   case EfiUsbPortEnableChange:\r
553     PortSC &= 0xfff5;\r
554     PortSC |= USBPORTSC_PEDC;\r
555     break;\r
556 \r
557   case EfiUsbPortSuspendChange:\r
558     //\r
559     // Root hub does not support this\r
560     //\r
561     break;\r
562 \r
563   case EfiUsbPortOverCurrentChange:\r
564     //\r
565     // Root hub does not support this\r
566     //\r
567     break;\r
568 \r
569   case EfiUsbPortResetChange:\r
570     //\r
571     // Root hub does not support this\r
572     //\r
573     break;\r
574 \r
575   default:\r
576     gBS->RestoreTPL (OldTpl);\r
577     return EFI_INVALID_PARAMETER;\r
578   }\r
579 \r
580   UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
581   gBS->RestoreTPL (OldTpl);\r
582 \r
583   return EFI_SUCCESS;\r
584 }\r
585 \r
586 \r
587 /**\r
588   Submits control transfer to a target USB device.\r
589 \r
590   This                : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
591   DeviceAddress       : Usb device address\r
592   IsSlowDevice        : Whether the device is of slow speed or full speed\r
593   MaximumPacketLength : maximum packet size of the default control endpoint\r
594   Request             : USB device request to send\r
595   TransferDirection   : Specifies the data direction for the transfer.\r
596   Data                : Data buffer to transmit from or receive into\r
597   DataLength          : Number of bytes of the data\r
598   TimeOut             : Maximum time, in microseconds\r
599   TransferResult      : Return result in this\r
600 \r
601   @return EFI_SUCCESS           : Transfer was completed successfully.\r
602   @return EFI_OUT_OF_RESOURCES  : Failed due to a lack of resources.\r
603   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
604   @return EFI_TIMEOUT           : Failed due to timeout.\r
605   @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
606 \r
607 **/\r
608 STATIC\r
609 EFI_STATUS\r
610 EFIAPI\r
611 UhciControlTransfer (\r
612   IN       EFI_USB_HC_PROTOCOL        *This,\r
613   IN       UINT8                      DeviceAddress,\r
614   IN       BOOLEAN                    IsSlowDevice,\r
615   IN       UINT8                      MaximumPacketLength,\r
616   IN       EFI_USB_DEVICE_REQUEST     *Request,\r
617   IN       EFI_USB_DATA_DIRECTION     TransferDirection,\r
618   IN OUT   VOID                       *Data,              OPTIONAL\r
619   IN OUT   UINTN                      *DataLength,        OPTIONAL\r
620   IN       UINTN                      TimeOut,\r
621   OUT      UINT32                     *TransferResult\r
622   )\r
623 {\r
624   USB_HC_DEV              *Uhc;\r
625   UHCI_TD_SW              *TDs;\r
626   EFI_TPL                 OldTpl;\r
627   EFI_STATUS              Status;\r
628   UHCI_QH_RESULT          QhResult;\r
629   UINT8                   PktId;\r
630   UINT8                   *RequestPhy;\r
631   VOID                    *RequestMap;\r
632   UINT8                   *DataPhy;\r
633   VOID                    *DataMap;\r
634 \r
635   Uhc         = UHC_FROM_USB_HC_PROTO (This);\r
636   TDs         = NULL;\r
637   DataPhy     = NULL;\r
638   DataMap     = NULL;\r
639   RequestPhy  = NULL;\r
640   RequestMap  = NULL;\r
641 \r
642   //\r
643   // Parameters Checking\r
644   //\r
645   if (Request == NULL || TransferResult == NULL) {\r
646     return EFI_INVALID_PARAMETER;\r
647   }\r
648 \r
649   if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
650     return EFI_INVALID_PARAMETER;\r
651   }\r
652 \r
653   if ((MaximumPacketLength != 8) &&  (MaximumPacketLength != 16) &&\r
654       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
655 \r
656     return EFI_INVALID_PARAMETER;\r
657   }\r
658 \r
659   if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
660     return EFI_INVALID_PARAMETER;\r
661   }\r
662 \r
663   *TransferResult = EFI_USB_ERR_SYSTEM;\r
664   Status          = EFI_DEVICE_ERROR;\r
665 \r
666   //\r
667   // If errors exist that cause host controller halt,\r
668   // clear status then return EFI_DEVICE_ERROR.\r
669   //\r
670   UhciAckAllInterrupt (Uhc);\r
671 \r
672   if (!UhciIsHcWorking (Uhc->PciIo)) {\r
673     return EFI_DEVICE_ERROR;\r
674   }\r
675 \r
676   OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
677 \r
678   //\r
679   // Map the Request and data for bus master access,\r
680   // then create a list of TD for this transfer\r
681   //\r
682   Status = UhciMapUserRequest (Uhc, Request, &RequestPhy, &RequestMap);\r
683 \r
684   if (EFI_ERROR (Status)) {\r
685     goto ON_EXIT;\r
686   }\r
687 \r
688   Status = UhciMapUserData (Uhc, TransferDirection, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
689 \r
690   if (EFI_ERROR (Status)) {\r
691     Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
692     goto ON_EXIT;\r
693   }\r
694 \r
695   TDs = UhciCreateCtrlTds (\r
696           Uhc,\r
697           DeviceAddress,\r
698           PktId,\r
699           RequestPhy,\r
700           DataPhy,\r
701           *DataLength,\r
702           MaximumPacketLength,\r
703           IsSlowDevice\r
704           );\r
705 \r
706   if (TDs == NULL) {\r
707     Status = EFI_OUT_OF_RESOURCES;\r
708     goto UNMAP_DATA;\r
709   }\r
710 \r
711   //\r
712   // According to the speed of the end point, link\r
713   // the TD to corrosponding queue head, then check\r
714   // the execution result\r
715   //\r
716   UhciLinkTdToQh (Uhc->CtrlQh, TDs);\r
717   Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
718   UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);\r
719 \r
720   Uhc->PciIo->Flush (Uhc->PciIo);\r
721 \r
722   *TransferResult = QhResult.Result;\r
723 \r
724   if (DataLength != NULL) {\r
725     *DataLength = QhResult.Complete;\r
726   }\r
727 \r
728   UhciDestoryTds (Uhc, TDs);\r
729 \r
730 UNMAP_DATA:\r
731   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
732   Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
733 \r
734 ON_EXIT:\r
735   gBS->RestoreTPL (OldTpl);\r
736   return Status;\r
737 }\r
738 \r
739 \r
740 /**\r
741   Submits bulk transfer to a bulk endpoint of a USB device.\r
742 \r
743   This                :A pointer to the EFI_USB_HC_PROTOCOL instance.\r
744   DeviceAddress       : Usb device address\r
745   EndPointAddress     : Endpoint number and endpoint direction\r
746   MaximumPacketLength : Maximum packet size of the target endpoint\r
747   Data                : Data buffer to transmit from or receive into\r
748   DataLength          : Length of the data buffer\r
749   DataToggle          : On input, data toggle to use, on output, the next toggle\r
750   TimeOut             : Indicates the maximum time\r
751   TransferResult      : Variable to receive the transfer result\r
752 \r
753   @return EFI_SUCCESS           : The bulk transfer was completed successfully.\r
754   @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
755   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
756   @return EFI_TIMEOUT           : Failed due to timeout.\r
757   @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
758 \r
759 **/\r
760 STATIC\r
761 EFI_STATUS\r
762 EFIAPI\r
763 UhciBulkTransfer (\r
764   IN       EFI_USB_HC_PROTOCOL     *This,\r
765   IN       UINT8                   DeviceAddress,\r
766   IN       UINT8                   EndPointAddress,\r
767   IN       UINT8                   MaximumPacketLength,\r
768   IN OUT   VOID                    *Data,\r
769   IN OUT   UINTN                   *DataLength,\r
770   IN OUT   UINT8                   *DataToggle,\r
771   IN       UINTN                   TimeOut,\r
772   OUT      UINT32                  *TransferResult\r
773   )\r
774 {\r
775   EFI_USB_DATA_DIRECTION  Direction;\r
776   EFI_TPL                 OldTpl;\r
777   USB_HC_DEV              *Uhc;\r
778   UHCI_TD_SW              *TDs;\r
779   UHCI_QH_SW              *BulkQh;\r
780   UHCI_QH_RESULT          QhResult;\r
781   EFI_STATUS              Status;\r
782   UINT8                   PktId;\r
783   UINT8                   *DataPhy;\r
784   VOID                    *DataMap;\r
785 \r
786   Uhc     = UHC_FROM_USB_HC_PROTO (This);\r
787   DataPhy = NULL;\r
788   DataMap = NULL;\r
789 \r
790   if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
791     return EFI_INVALID_PARAMETER;\r
792   }\r
793 \r
794   if (*DataLength == 0) {\r
795     return EFI_INVALID_PARAMETER;\r
796   }\r
797 \r
798   if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
799     return EFI_INVALID_PARAMETER;\r
800   }\r
801 \r
802   if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
803       (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
804     return EFI_INVALID_PARAMETER;\r
805   }\r
806 \r
807   *TransferResult = EFI_USB_ERR_SYSTEM;\r
808   Status          = EFI_OUT_OF_RESOURCES;\r
809 \r
810   //\r
811   // If has errors that cause host controller halt,\r
812   // then return EFI_DEVICE_ERROR directly.\r
813   //\r
814   UhciAckAllInterrupt (Uhc);\r
815 \r
816   if (!UhciIsHcWorking (Uhc->PciIo)) {\r
817     return EFI_DEVICE_ERROR;\r
818   }\r
819 \r
820   OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
821 \r
822   //\r
823   // Map the source data buffer for bus master access,\r
824   // then create a list of TDs\r
825   //\r
826   if (EndPointAddress & 0x80) {\r
827     Direction = EfiUsbDataIn;\r
828   } else {\r
829     Direction = EfiUsbDataOut;\r
830   }\r
831 \r
832   Status = UhciMapUserData (Uhc, Direction, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
833 \r
834   if (EFI_ERROR (Status)) {\r
835     goto ON_EXIT;\r
836   }\r
837 \r
838   Status = EFI_OUT_OF_RESOURCES;\r
839   TDs    = UhciCreateBulkOrIntTds (\r
840              Uhc,\r
841              DeviceAddress,\r
842              EndPointAddress,\r
843              PktId,\r
844              DataPhy,\r
845              *DataLength,\r
846              DataToggle,\r
847              MaximumPacketLength,\r
848              FALSE\r
849              );\r
850 \r
851   if (TDs == NULL) {\r
852     Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
853     goto ON_EXIT;\r
854   }\r
855 \r
856 \r
857   //\r
858   // Link the TDs to bulk queue head. According to the platfore\r
859   // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured\r
860   // to do full speed bandwidth reclamation or not.\r
861   //\r
862   BulkQh = Uhc->BulkQh;\r
863 \r
864   UhciLinkTdToQh (BulkQh, TDs);\r
865   Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);\r
866   UhciUnlinkTdFromQh (BulkQh, TDs);\r
867 \r
868   Uhc->PciIo->Flush (Uhc->PciIo);\r
869 \r
870   *TransferResult = QhResult.Result;\r
871   *DataToggle     = QhResult.NextToggle;\r
872   *DataLength     = QhResult.Complete;\r
873 \r
874   UhciDestoryTds (Uhc, TDs);\r
875   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
876 \r
877 ON_EXIT:\r
878   gBS->RestoreTPL (OldTpl);\r
879   return Status;\r
880 }\r
881 \r
882 \r
883 /**\r
884   Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.\r
885 \r
886   This                : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
887   DeviceAddress       : Target device address\r
888   EndPointAddress     : Endpoint number with direction\r
889   IsSlowDevice        : Whether the target device is slow device or full-speed device.\r
890   MaximumPacketLength : Maximum packet size of the target endpoint\r
891   IsNewTransfer       : If TRUE, submit a new async interrupt transfer, otherwise\r
892   cancel an existed one\r
893   DataToggle          : On input, the data toggle to use; On output, next data toggle\r
894   PollingInterval     : Interrupt poll rate in milliseconds\r
895   DataLength          : Length of data to receive\r
896   CallBackFunction    : Function to call periodically\r
897   Context             : User context\r
898 \r
899   @return EFI_SUCCESS           : Request is submitted or cancelled\r
900   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
901   @return EFI_OUT_OF_RESOURCES  : Failed due to a lack of resources.\r
902   @return EFI_DEVICE_ERROR      : Failed to due to device error\r
903 \r
904 **/\r
905 STATIC\r
906 EFI_STATUS\r
907 EFIAPI\r
908 UhciAsyncInterruptTransfer (\r
909   IN     EFI_USB_HC_PROTOCOL                * This,\r
910   IN     UINT8                              DeviceAddress,\r
911   IN     UINT8                              EndPointAddress,\r
912   IN     BOOLEAN                            IsSlowDevice,\r
913   IN     UINT8                              MaximumPacketLength,\r
914   IN     BOOLEAN                            IsNewTransfer,\r
915   IN OUT UINT8                              *DataToggle,\r
916   IN     UINTN                              PollingInterval,    OPTIONAL\r
917   IN     UINTN                              DataLength,         OPTIONAL\r
918   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    CallBackFunction,   OPTIONAL\r
919   IN     VOID                               *Context OPTIONAL\r
920   )\r
921 {\r
922   USB_HC_DEV          *Uhc;\r
923   UHCI_QH_SW          *Qh;\r
924   UHCI_TD_SW          *IntTds;\r
925   EFI_TPL             OldTpl;\r
926   EFI_STATUS          Status;\r
927   UINT8               *DataPtr;\r
928   UINT8               *DataPhy;\r
929   VOID                *DataMap;\r
930   UINT8               PktId;\r
931 \r
932   Uhc       = UHC_FROM_USB_HC_PROTO (This);\r
933   Qh        = NULL;\r
934   IntTds    = NULL;\r
935   DataPtr   = NULL;\r
936   DataPhy   = NULL;\r
937   DataMap   = NULL;\r
938 \r
939   if ((EndPointAddress & 0x80) == 0) {\r
940     return EFI_INVALID_PARAMETER;\r
941   }\r
942 \r
943   //\r
944   // Delete Async interrupt transfer request\r
945   //\r
946   if (!IsNewTransfer) {\r
947     OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
948     Status = UhciRemoveAsyncReq (Uhc, DeviceAddress, EndPointAddress, DataToggle);\r
949 \r
950     gBS->RestoreTPL (OldTpl);\r
951     return Status;\r
952   }\r
953 \r
954   if (PollingInterval < 1 || PollingInterval > 255) {\r
955     return EFI_INVALID_PARAMETER;\r
956   }\r
957 \r
958   if (DataLength == 0) {\r
959     return EFI_INVALID_PARAMETER;\r
960   }\r
961 \r
962   if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
963     return EFI_INVALID_PARAMETER;\r
964   }\r
965 \r
966   //\r
967   // If has errors that cause host controller halt,\r
968   // then return EFI_DEVICE_ERROR directly.\r
969   //\r
970   UhciAckAllInterrupt (Uhc);\r
971 \r
972   if (!UhciIsHcWorking (Uhc->PciIo)) {\r
973     return EFI_DEVICE_ERROR;\r
974   }\r
975 \r
976   //\r
977   // Allocate and map source data buffer for bus master access.\r
978   //\r
979   DataPtr = AllocatePool (DataLength);\r
980 \r
981   if (DataPtr == NULL) {\r
982     return EFI_OUT_OF_RESOURCES;\r
983   }\r
984 \r
985   OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
986 \r
987   //\r
988   // Map the user data then create a queue head and\r
989   // list of TD for it.\r
990   //\r
991   Status = UhciMapUserData (\r
992              Uhc,\r
993              EfiUsbDataIn,\r
994              DataPtr,\r
995              &DataLength,\r
996              &PktId,\r
997              &DataPhy,\r
998              &DataMap\r
999              );\r
1000 \r
1001   if (EFI_ERROR (Status)) {\r
1002     goto FREE_DATA;\r
1003   }\r
1004 \r
1005   Qh = UhciCreateQh (Uhc, PollingInterval);\r
1006 \r
1007   if (Qh == NULL) {\r
1008     Status = EFI_OUT_OF_RESOURCES;\r
1009     goto UNMAP_DATA;\r
1010   }\r
1011 \r
1012   IntTds = UhciCreateBulkOrIntTds (\r
1013              Uhc,\r
1014              DeviceAddress,\r
1015              EndPointAddress,\r
1016              PktId,\r
1017              DataPhy,\r
1018              DataLength,\r
1019              DataToggle,\r
1020              MaximumPacketLength,\r
1021              IsSlowDevice\r
1022              );\r
1023 \r
1024   if (IntTds == NULL) {\r
1025     Status = EFI_OUT_OF_RESOURCES;\r
1026     goto DESTORY_QH;\r
1027   }\r
1028 \r
1029   UhciLinkTdToQh (Qh, IntTds);\r
1030 \r
1031   //\r
1032   // Save QH-TD structures to async Interrupt transfer list,\r
1033   // for monitor interrupt transfer execution routine use.\r
1034   //\r
1035   Status = UhciCreateAsyncReq (\r
1036              Uhc,\r
1037              Qh,\r
1038              IntTds,\r
1039              DeviceAddress,\r
1040              EndPointAddress,\r
1041              DataLength,\r
1042              PollingInterval,\r
1043              DataMap,\r
1044              DataPtr,\r
1045              CallBackFunction,\r
1046              Context,\r
1047              IsSlowDevice\r
1048              );\r
1049 \r
1050   if (EFI_ERROR (Status)) {\r
1051     goto DESTORY_QH;\r
1052   }\r
1053 \r
1054   UhciLinkQhToFrameList (Uhc->FrameBase, Qh);\r
1055 \r
1056   gBS->RestoreTPL (OldTpl);\r
1057   return EFI_SUCCESS;\r
1058 \r
1059 DESTORY_QH:\r
1060   UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));\r
1061 \r
1062 UNMAP_DATA:\r
1063   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1064 \r
1065 FREE_DATA:\r
1066   gBS->FreePool (DataPtr);\r
1067   Uhc->PciIo->Flush (Uhc->PciIo);\r
1068 \r
1069   gBS->RestoreTPL (OldTpl);\r
1070   return Status;\r
1071 }\r
1072 \r
1073 \r
1074 /**\r
1075   Submits synchronous interrupt transfer to an interrupt endpoint of a USB device.\r
1076 \r
1077   This                : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1078   DeviceAddress       : Device address of the target USB device\r
1079   EndPointAddress     : Endpoint number and direction\r
1080   IsSlowDevice        : Whether the target device is of slow speed or full speed\r
1081   MaximumPacketLength : Maximum packet size of target endpoint\r
1082   Data                : Data to transmit or receive\r
1083   DataLength          : On input, data length to transmit or buffer size.\r
1084   On output, the number of bytes transferred.\r
1085   DataToggle          : On input, data toggle to use; On output, next data toggle\r
1086   TimeOut             : Maximum time, in microseconds, transfer is allowed to complete.\r
1087   TransferResult      : Variable to receive transfer result\r
1088 \r
1089   @return EFI_SUCCESS           : Transfer was completed successfully.\r
1090   @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
1091   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1092   @return EFI_TIMEOUT           : Failed due to timeout.\r
1093   @return EFI_DEVICE_ERROR      : Failed due to host controller or device error\r
1094 \r
1095 **/\r
1096 STATIC\r
1097 EFI_STATUS\r
1098 EFIAPI\r
1099 UhciSyncInterruptTransfer (\r
1100   IN       EFI_USB_HC_PROTOCOL     *This,\r
1101   IN       UINT8                   DeviceAddress,\r
1102   IN       UINT8                   EndPointAddress,\r
1103   IN       BOOLEAN                 IsSlowDevice,\r
1104   IN       UINT8                   MaximumPacketLength,\r
1105   IN OUT   VOID                    *Data,\r
1106   IN OUT   UINTN                   *DataLength,\r
1107   IN OUT   UINT8                   *DataToggle,\r
1108   IN       UINTN                   TimeOut,\r
1109   OUT      UINT32                  *TransferResult\r
1110   )\r
1111 {\r
1112   EFI_STATUS          Status;\r
1113   USB_HC_DEV          *Uhc;\r
1114   UHCI_TD_SW          *TDs;\r
1115   UHCI_QH_RESULT      QhResult;\r
1116   EFI_TPL             OldTpl;\r
1117   UINT8               *DataPhy;\r
1118   VOID                *DataMap;\r
1119   UINT8               PktId;\r
1120 \r
1121   Uhc     = UHC_FROM_USB_HC_PROTO (This);\r
1122   DataPhy = NULL;\r
1123   DataMap = NULL;\r
1124   TDs     = NULL;\r
1125 \r
1126   if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
1127     return EFI_INVALID_PARAMETER;\r
1128   }\r
1129 \r
1130   if ((EndPointAddress & 0x80) == 0) {\r
1131     return EFI_INVALID_PARAMETER;\r
1132   }\r
1133 \r
1134   if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1135     return EFI_INVALID_PARAMETER;\r
1136   }\r
1137 \r
1138   if ((*DataLength == 0) || (MaximumPacketLength > 64)) {\r
1139     return EFI_INVALID_PARAMETER;\r
1140   }\r
1141 \r
1142   if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
1143     return EFI_INVALID_PARAMETER;\r
1144   }\r
1145 \r
1146   *TransferResult = EFI_USB_ERR_SYSTEM;\r
1147   Status          = EFI_DEVICE_ERROR;\r
1148 \r
1149 \r
1150   UhciAckAllInterrupt (Uhc);\r
1151 \r
1152   if (!UhciIsHcWorking (Uhc->PciIo)) {\r
1153     return Status;\r
1154   }\r
1155 \r
1156   OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1157 \r
1158   //\r
1159   // Map the source data buffer for bus master access.\r
1160   // Create Tds list, then link it to the UHC's interrupt list\r
1161   //\r
1162   Status = UhciMapUserData (\r
1163              Uhc,\r
1164              EfiUsbDataIn,\r
1165              Data,\r
1166              DataLength,\r
1167              &PktId,\r
1168              &DataPhy,\r
1169              &DataMap\r
1170              );\r
1171 \r
1172   if (EFI_ERROR (Status)) {\r
1173     goto ON_EXIT;\r
1174   }\r
1175 \r
1176   TDs = UhciCreateBulkOrIntTds (\r
1177           Uhc,\r
1178           DeviceAddress,\r
1179           EndPointAddress,\r
1180           PktId,\r
1181           DataPhy,\r
1182           *DataLength,\r
1183           DataToggle,\r
1184           MaximumPacketLength,\r
1185           IsSlowDevice\r
1186           );\r
1187 \r
1188   if (TDs == NULL) {\r
1189     Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1190 \r
1191     Status = EFI_OUT_OF_RESOURCES;\r
1192     goto ON_EXIT;\r
1193   }\r
1194 \r
1195 \r
1196   UhciLinkTdToQh (Uhc->SyncIntQh, TDs);\r
1197 \r
1198   Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
1199 \r
1200   UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);\r
1201   Uhc->PciIo->Flush (Uhc->PciIo);\r
1202 \r
1203   *TransferResult = QhResult.Result;\r
1204   *DataToggle     = QhResult.NextToggle;\r
1205   *DataLength     = QhResult.Complete;\r
1206 \r
1207   UhciDestoryTds (Uhc, TDs);\r
1208   Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1209 \r
1210 ON_EXIT:\r
1211   gBS->RestoreTPL (OldTpl);\r
1212   return Status;\r
1213 }\r
1214 \r
1215 \r
1216 /**\r
1217   Submits isochronous transfer to a target USB device.\r
1218 \r
1219   This                : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1220   DeviceAddress       : Target device address\r
1221   EndPointAddress     : End point address withdirection\r
1222   MaximumPacketLength : Maximum packet size of the endpoint\r
1223   Data                : Data to transmit or receive\r
1224   DataLength          : Bytes of the data\r
1225   TransferResult      : Variable to receive the result\r
1226 \r
1227   @return EFI_UNSUPPORTED\r
1228 \r
1229 **/\r
1230 STATIC\r
1231 EFI_STATUS\r
1232 EFIAPI\r
1233 UhciIsochronousTransfer (\r
1234   IN       EFI_USB_HC_PROTOCOL     *This,\r
1235   IN       UINT8                   DeviceAddress,\r
1236   IN       UINT8                   EndPointAddress,\r
1237   IN       UINT8                   MaximumPacketLength,\r
1238   IN OUT   VOID                    *Data,\r
1239   IN       UINTN                   DataLength,\r
1240   OUT      UINT32                  *TransferResult\r
1241   )\r
1242 {\r
1243   return EFI_UNSUPPORTED;\r
1244 }\r
1245 \r
1246 \r
1247 /**\r
1248   Submits Async isochronous transfer to a target USB device.\r
1249 \r
1250   This                : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1251   DeviceAddress       : Target device address\r
1252   EndPointAddress     : End point address withdirection\r
1253   MaximumPacketLength : Maximum packet size of the endpoint\r
1254   Data                : Data to transmit or receive\r
1255   IsochronousCallBack : Function to call when the transfer completes\r
1256   Context             : User context\r
1257 \r
1258   @return EFI_UNSUPPORTED\r
1259 \r
1260 **/\r
1261 STATIC\r
1262 EFI_STATUS\r
1263 EFIAPI\r
1264 UhciAsyncIsochronousTransfer (\r
1265   IN       EFI_USB_HC_PROTOCOL                 * This,\r
1266   IN       UINT8                               DeviceAddress,\r
1267   IN       UINT8                               EndPointAddress,\r
1268   IN       UINT8                               MaximumPacketLength,\r
1269   IN OUT   VOID                                *Data,\r
1270   IN       UINTN                               DataLength,\r
1271   IN       EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,\r
1272   IN       VOID                                *Context OPTIONAL\r
1273   )\r
1274 {\r
1275   return EFI_UNSUPPORTED;\r
1276 }\r
1277 \r
1278 \r
1279 \r
1280 /**\r
1281   Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
1282 \r
1283   @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1284   @param  Attributes           A bit mask of the reset operation to perform.  See\r
1285                                below for a list of the supported bit mask values.\r
1286 \r
1287   @return EFI_SUCCESS           : The reset operation succeeded.\r
1288   @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
1289   @return EFI_UNSUPPORTED       : This type of reset is not currently supported\r
1290   @return EFI_DEVICE_ERROR      : Other errors\r
1291 \r
1292 **/\r
1293 STATIC\r
1294 EFI_STATUS\r
1295 EFIAPI\r
1296 Uhci2Reset (\r
1297   IN EFI_USB2_HC_PROTOCOL   *This,\r
1298   IN UINT16                 Attributes\r
1299   )\r
1300 {\r
1301   USB_HC_DEV          *UhciDev;\r
1302 \r
1303   UhciDev = UHC_FROM_USB2_HC_PROTO (This);\r
1304 \r
1305   if ((Attributes == EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG) ||\r
1306       (Attributes == EFI_USB_HC_RESET_HOST_WITH_DEBUG)) {\r
1307     return EFI_UNSUPPORTED;\r
1308   }\r
1309 \r
1310   return UhciReset (&UhciDev->UsbHc, Attributes);\r
1311 }\r
1312 \r
1313 \r
1314 /**\r
1315   Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
1316 \r
1317   @param  This                 A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1318   @param  State                Variable to receive current device state\r
1319 \r
1320   @return EFI_SUCCESS           : The state is returned\r
1321   @return EFI_INVALID_PARAMETER : State is not valid.\r
1322   @return EFI_DEVICE_ERROR      : Other errors2006\r
1323 \r
1324 **/\r
1325 STATIC\r
1326 EFI_STATUS\r
1327 EFIAPI\r
1328 Uhci2GetState (\r
1329   IN CONST EFI_USB2_HC_PROTOCOL   *This,\r
1330   OUT      EFI_USB_HC_STATE       *State\r
1331   )\r
1332 {\r
1333   USB_HC_DEV          *Uhc;\r
1334 \r
1335   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1336   return UhciGetState (&Uhc->UsbHc, State);\r
1337 }\r
1338 \r
1339 \r
1340 /**\r
1341   Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
1342 \r
1343   @param  This                 A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1344   @param  State                Indicates the state of the host controller that will\r
1345                                be set.\r
1346 \r
1347   @return EFI_SUCCESS           : Host controller was successfully placed in the state\r
1348   @return EFI_INVALID_PARAMETER : State is invalid.\r
1349   @return EFI_DEVICE_ERROR      : Failed to set the state\r
1350 \r
1351 **/\r
1352 STATIC\r
1353 EFI_STATUS\r
1354 EFIAPI\r
1355 Uhci2SetState (\r
1356   IN EFI_USB2_HC_PROTOCOL    *This,\r
1357   IN EFI_USB_HC_STATE        State\r
1358   )\r
1359 {\r
1360   USB_HC_DEV          *Uhc;\r
1361 \r
1362   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1363   return UhciSetState (&Uhc->UsbHc, State);\r
1364 }\r
1365 \r
1366 \r
1367 /**\r
1368   Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
1369 \r
1370   @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance\r
1371   @param  MaxSpeed             A pointer to the max speed USB host controller\r
1372                                supports.\r
1373   @param  PortNumber           A pointer to the number of root hub ports.\r
1374   @param  Is64BitCapable       A pointer to an integer to show whether USB host\r
1375                                controller supports 64-bit memory addressing.\r
1376 \r
1377   @return EFI_SUCCESS           : capabilities were retrieved successfully.\r
1378   @return EFI_INVALID_PARAMETER : MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
1379   @return EFI_DEVICE_ERROR      : An error was encountered\r
1380 \r
1381 **/\r
1382 STATIC\r
1383 EFI_STATUS\r
1384 EFIAPI\r
1385 Uhci2GetCapability (\r
1386   IN  EFI_USB2_HC_PROTOCOL  *This,\r
1387   OUT UINT8                 *MaxSpeed,\r
1388   OUT UINT8                 *PortNumber,\r
1389   OUT UINT8                 *Is64BitCapable\r
1390   )\r
1391 {\r
1392   USB_HC_DEV          *Uhc;\r
1393 \r
1394   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1395 \r
1396   if ((NULL == MaxSpeed) || (NULL == PortNumber) || (NULL == Is64BitCapable)) {\r
1397     return EFI_INVALID_PARAMETER;\r
1398   }\r
1399 \r
1400   *MaxSpeed       = EFI_USB_SPEED_FULL;\r
1401   *Is64BitCapable = (UINT8) FALSE;\r
1402 \r
1403   return UhciGetRootHubPortNumber (&Uhc->UsbHc, PortNumber);\r
1404 }\r
1405 \r
1406 \r
1407 /**\r
1408   Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
1409 \r
1410   @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL.\r
1411   @param  PortNumber           The port to get status\r
1412   @param  PortStatus           A pointer to the current port status bits and  port\r
1413                                status change bits.\r
1414 \r
1415   @return EFI_SUCCESS           : status of the USB root hub port was returned in PortStatus.\r
1416   @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
1417   @return EFI_DEVICE_ERROR      : Can't read register\r
1418 \r
1419 **/\r
1420 STATIC\r
1421 EFI_STATUS\r
1422 EFIAPI\r
1423 Uhci2GetRootHubPortStatus (\r
1424   IN  CONST EFI_USB2_HC_PROTOCOL   *This,\r
1425   IN  CONST UINT8                  PortNumber,\r
1426   OUT       EFI_USB_PORT_STATUS    *PortStatus\r
1427   )\r
1428 {\r
1429   USB_HC_DEV          *Uhc;\r
1430 \r
1431   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1432 \r
1433   return UhciGetRootHubPortStatus (&Uhc->UsbHc, PortNumber, PortStatus);\r
1434 }\r
1435 \r
1436 \r
1437 /**\r
1438   Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
1439 \r
1440   @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL.\r
1441   @param  PortNumber           Specifies the root hub port whose feature  is\r
1442                                requested to be set.\r
1443   @param  PortFeature          Indicates the feature selector associated  with the\r
1444                                feature set request.\r
1445 \r
1446   @return EFI_SUCCESS           : PortFeature was set for the root port\r
1447   @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
1448   @return EFI_DEVICE_ERROR      : Can't read register\r
1449 \r
1450 **/\r
1451 STATIC\r
1452 EFI_STATUS\r
1453 EFIAPI\r
1454 Uhci2SetRootHubPortFeature (\r
1455   IN EFI_USB2_HC_PROTOCOL    *This,\r
1456   IN UINT8                   PortNumber,\r
1457   IN EFI_USB_PORT_FEATURE    PortFeature\r
1458   )\r
1459 {\r
1460   USB_HC_DEV          *Uhc;\r
1461 \r
1462   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1463 \r
1464   return UhciSetRootHubPortFeature (&Uhc->UsbHc, PortNumber, PortFeature);\r
1465 }\r
1466 \r
1467 \r
1468 /**\r
1469   Clears a feature for the specified root hub port according to Uefi 2.0 spec.\r
1470 \r
1471   @param  This                 A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1472   @param  PortNumber           Specifies the root hub port whose feature  is\r
1473                                requested to be cleared.\r
1474   @param  PortFeature          Indicates the feature selector associated with the\r
1475                                feature clear request.\r
1476 \r
1477   @return EFI_SUCCESS           : PortFeature was cleared for the USB root hub port\r
1478   @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
1479   @return EFI_DEVICE_ERROR      : Can't read register\r
1480 \r
1481 **/\r
1482 STATIC\r
1483 EFI_STATUS\r
1484 EFIAPI\r
1485 Uhci2ClearRootHubPortFeature (\r
1486   IN EFI_USB2_HC_PROTOCOL    *This,\r
1487   IN UINT8                   PortNumber,\r
1488   IN EFI_USB_PORT_FEATURE    PortFeature\r
1489   )\r
1490 {\r
1491   USB_HC_DEV          *Uhc;\r
1492 \r
1493   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1494 \r
1495   return UhciClearRootHubPortFeature (&Uhc->UsbHc, PortNumber, PortFeature);\r
1496 }\r
1497 \r
1498 \r
1499 /**\r
1500   Submits control transfer to a target USB device accroding to UEFI 2.0 spec..\r
1501 \r
1502   This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1503   DeviceAddress       : Target device address\r
1504   DeviceSpeed         : Device speed\r
1505   MaximumPacketLength : Maximum packet size of the target endpoint\r
1506   Request             : USB device request to send\r
1507   TransferDirection   : Data direction of the Data stage in control transfer\r
1508   Data                : Data to transmit/receive in data stage\r
1509   DataLength          : Length of the data\r
1510   TimeOut             : Maximum time, in microseconds, for transfer to complete.\r
1511   TransferResult      : Variable to receive the transfer result\r
1512 \r
1513   @return EFI_SUCCESS           : The control transfer was completed successfully.\r
1514   @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
1515   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1516   @return EFI_TIMEOUT           : Failed due to timeout.\r
1517   @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
1518 \r
1519 **/\r
1520 STATIC\r
1521 EFI_STATUS\r
1522 EFIAPI\r
1523 Uhci2ControlTransfer (\r
1524   IN     EFI_USB2_HC_PROTOCOL                 *This,\r
1525   IN     UINT8                                DeviceAddress,\r
1526   IN     UINT8                                DeviceSpeed,\r
1527   IN     UINTN                                MaximumPacketLength,\r
1528   IN     EFI_USB_DEVICE_REQUEST               *Request,\r
1529   IN     EFI_USB_DATA_DIRECTION               TransferDirection,\r
1530   IN OUT VOID                                 *Data,\r
1531   IN OUT UINTN                                *DataLength,\r
1532   IN     UINTN                                TimeOut,\r
1533   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,\r
1534   OUT    UINT32                               *TransferResult\r
1535   )\r
1536 {\r
1537   USB_HC_DEV          *Uhc;\r
1538   BOOLEAN             IsSlow;\r
1539 \r
1540   Uhc     = UHC_FROM_USB2_HC_PROTO (This);\r
1541   IsSlow  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
1542 \r
1543   return UhciControlTransfer (\r
1544            &Uhc->UsbHc,\r
1545            DeviceAddress,\r
1546            IsSlow,\r
1547            (UINT8) MaximumPacketLength,\r
1548            Request,\r
1549            TransferDirection,\r
1550            Data,\r
1551            DataLength,\r
1552            TimeOut,\r
1553            TransferResult\r
1554            );\r
1555 }\r
1556 \r
1557 \r
1558 /**\r
1559   Submits bulk transfer to a bulk endpoint of a USB device\r
1560 \r
1561   This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1562   DeviceAddress       : Target device address\r
1563   EndPointAddress     : Endpoint number and direction\r
1564   DeviceSpeed         : Device speed\r
1565   MaximumPacketLength : Maximum packet size of the target endpoint\r
1566   DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
1567   Data                : Array of pointers to the buffers of data\r
1568   DataLength          : On input, size of the data buffer, On output,\r
1569   actually transferred data size.\r
1570   DataToggle          : On input, data toggle to use; On output, next data toggle\r
1571   Translator          : A pointr to the transaction translator data.\r
1572   TimeOut             : Maximum time out, in microseconds\r
1573   TransferResult      : Variable to receive transfer result\r
1574 \r
1575   @return EFI_SUCCESS           : The bulk transfer was completed successfully.\r
1576   @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
1577   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1578   @return EFI_TIMEOUT           : Failed due to timeout.\r
1579   @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
1580 \r
1581 **/\r
1582 STATIC\r
1583 EFI_STATUS\r
1584 EFIAPI\r
1585 Uhci2BulkTransfer (\r
1586   IN     EFI_USB2_HC_PROTOCOL               *This,\r
1587   IN     UINT8                              DeviceAddress,\r
1588   IN     UINT8                              EndPointAddress,\r
1589   IN     UINT8                              DeviceSpeed,\r
1590   IN     UINTN                              MaximumPacketLength,\r
1591   IN     UINT8                              DataBuffersNumber,\r
1592   IN OUT VOID                               *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
1593   IN OUT UINTN                              *DataLength,\r
1594   IN OUT UINT8                              *DataToggle,\r
1595   IN     UINTN                              TimeOut,\r
1596   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1597   OUT    UINT32                             *TransferResult\r
1598   )\r
1599 {\r
1600   USB_HC_DEV          *Uhc;\r
1601 \r
1602   Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1603 \r
1604   if (Data == NULL || DeviceSpeed == EFI_USB_SPEED_LOW) {\r
1605     return EFI_INVALID_PARAMETER;\r
1606   }\r
1607 \r
1608   //\r
1609   // For full-speed bulk transfers only the data pointed by Data[0] shall be used\r
1610   //\r
1611   return UhciBulkTransfer (\r
1612            &Uhc->UsbHc,\r
1613            DeviceAddress,\r
1614            EndPointAddress,\r
1615            (UINT8) MaximumPacketLength,\r
1616            *Data,\r
1617            DataLength,\r
1618            DataToggle,\r
1619            TimeOut,\r
1620            TransferResult\r
1621            );\r
1622 }\r
1623 \r
1624 \r
1625 /**\r
1626   Submits an asynchronous interrupt transfer to an\r
1627   interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
1628 \r
1629   This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1630   DeviceAddress       : Target device address\r
1631   EndPointAddress     : Endpoint number and direction\r
1632   DeviceSpeed         : Device speed\r
1633   MaximumPacketLength : Maximum packet size of the target endpoint\r
1634   IsNewTransfer       : If TRUE, submit a new transfer, if FALSE cancel old transfer\r
1635   DataToggle          : On input, data toggle to use; On output, next data toggle\r
1636   PollingInterval     : Interrupt poll rate in milliseconds\r
1637   DataLength          : On input, size of the data buffer, On output,\r
1638   actually transferred data size.\r
1639   Translator          : A pointr to the transaction translator data.\r
1640   CallBackFunction    : Function to call periodically\r
1641   Context             : User context\r
1642 \r
1643   @return EFI_SUCCESS           : Transfer was submitted\r
1644   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1645   @return EFI_OUT_OF_RESOURCES  : Failed due to a lack of resources.\r
1646   @return EFI_DEVICE_ERROR      : Can't read register\r
1647 \r
1648 **/\r
1649 STATIC\r
1650 EFI_STATUS\r
1651 EFIAPI\r
1652 Uhci2AsyncInterruptTransfer (\r
1653   IN     EFI_USB2_HC_PROTOCOL               *This,\r
1654   IN     UINT8                              DeviceAddress,\r
1655   IN     UINT8                              EndPointAddress,\r
1656   IN     UINT8                              DeviceSpeed,\r
1657   IN     UINTN                              MaximumPacketLength,\r
1658   IN     BOOLEAN                            IsNewTransfer,\r
1659   IN OUT UINT8                              *DataToggle,\r
1660   IN     UINTN                              PollingInterval,\r
1661   IN     UINTN                              DataLength,\r
1662   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1663   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    CallBackFunction,\r
1664   IN     VOID                               *Context\r
1665   )\r
1666 {\r
1667   USB_HC_DEV          *Uhc;\r
1668   BOOLEAN             IsSlow;\r
1669 \r
1670   Uhc     = UHC_FROM_USB2_HC_PROTO (This);\r
1671   IsSlow  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
1672 \r
1673   return UhciAsyncInterruptTransfer (\r
1674            &Uhc->UsbHc,\r
1675            DeviceAddress,\r
1676            EndPointAddress,\r
1677            IsSlow,\r
1678            (UINT8) MaximumPacketLength,\r
1679            IsNewTransfer,\r
1680            DataToggle,\r
1681            PollingInterval,\r
1682            DataLength,\r
1683            CallBackFunction,\r
1684            Context\r
1685            );\r
1686 }\r
1687 \r
1688 \r
1689 /**\r
1690   Submits synchronous interrupt transfer to an interrupt endpoint\r
1691   of a USB device according to UEFI 2.0 spec.\r
1692 \r
1693   This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1694   DeviceAddress       : Target device address\r
1695   EndPointAddress     : Endpoint number and direction\r
1696   DeviceSpeed         : Device speed\r
1697   MaximumPacketLength : Maximum packet size of the target endpoint\r
1698   DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
1699   Data                : Array of pointers to the buffers of data\r
1700   DataLength          : On input, size of the data buffer, On output,\r
1701   actually transferred data size.\r
1702   DataToggle          : On input, data toggle to use; On output, next data toggle\r
1703   TimeOut             : Maximum time out, in microseconds\r
1704   Translator          : A pointr to the transaction translator data.\r
1705   TransferResult      : Variable to receive transfer result\r
1706 \r
1707   @return EFI_SUCCESS           : The transfer was completed successfully.\r
1708   @return EFI_OUT_OF_RESOURCES  : Failed due to lack of resource.\r
1709   @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1710   @return EFI_TIMEOUT           : Failed due to timeout.\r
1711   @return EFI_DEVICE_ERROR      : Failed due to host controller or device error.\r
1712 \r
1713 **/\r
1714 STATIC\r
1715 EFI_STATUS\r
1716 EFIAPI\r
1717 Uhci2SyncInterruptTransfer (\r
1718   IN     EFI_USB2_HC_PROTOCOL                      *This,\r
1719   IN     UINT8                                     DeviceAddress,\r
1720   IN     UINT8                                     EndPointAddress,\r
1721   IN     UINT8                                     DeviceSpeed,\r
1722   IN     UINTN                                     MaximumPacketLength,\r
1723   IN OUT VOID                                      *Data,\r
1724   IN OUT UINTN                                     *DataLength,\r
1725   IN OUT UINT8                                     *DataToggle,\r
1726   IN     UINTN                                     TimeOut,\r
1727   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR        *Translator,\r
1728   OUT    UINT32                                    *TransferResult\r
1729   )\r
1730 {\r
1731   USB_HC_DEV          *Uhc;\r
1732   BOOLEAN             IsSlow;\r
1733 \r
1734   if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
1735     return EFI_INVALID_PARAMETER;\r
1736   }\r
1737 \r
1738   Uhc     = UHC_FROM_USB2_HC_PROTO (This);\r
1739   IsSlow  = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
1740 \r
1741   return UhciSyncInterruptTransfer (\r
1742            &Uhc->UsbHc,\r
1743            DeviceAddress,\r
1744            EndPointAddress,\r
1745            IsSlow,\r
1746            (UINT8) MaximumPacketLength,\r
1747            Data,\r
1748            DataLength,\r
1749            DataToggle,\r
1750            TimeOut,\r
1751            TransferResult\r
1752            );\r
1753 }\r
1754 \r
1755 \r
1756 /**\r
1757   Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1758 \r
1759   This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1760   DeviceAddress       : Target device address\r
1761   EndPointAddress     : Endpoint number and direction\r
1762   DeviceSpeed         : Device speed\r
1763   MaximumPacketLength : Maximum packet size of the target endpoint\r
1764   DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
1765   Data                : Array of pointers to the buffers of data\r
1766   DataLength          : On input, size of the data buffer, On output,\r
1767   actually transferred data size.\r
1768   Translator          : A pointr to the transaction translator data.\r
1769   TransferResult      : Variable to receive transfer result\r
1770 \r
1771   @return EFI_UNSUPPORTED\r
1772 \r
1773 **/\r
1774 STATIC\r
1775 EFI_STATUS\r
1776 EFIAPI\r
1777 Uhci2IsochronousTransfer (\r
1778   IN     EFI_USB2_HC_PROTOCOL               *This,\r
1779   IN     UINT8                              DeviceAddress,\r
1780   IN     UINT8                              EndPointAddress,\r
1781   IN     UINT8                              DeviceSpeed,\r
1782   IN     UINTN                              MaximumPacketLength,\r
1783   IN     UINT8                              DataBuffersNumber,\r
1784   IN OUT VOID                               *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1785   IN     UINTN                              DataLength,\r
1786   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1787   OUT    UINT32                             *TransferResult\r
1788   )\r
1789 {\r
1790   return EFI_UNSUPPORTED;\r
1791 }\r
1792 \r
1793 \r
1794 /**\r
1795   Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1796 \r
1797   This                : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1798   DeviceAddress       : Target device address\r
1799   EndPointAddress     : Endpoint number and direction\r
1800   DeviceSpeed         : Device speed\r
1801   MaximumPacketLength : Maximum packet size of the target endpoint\r
1802   DataBuffersNumber   : Number of data buffers prepared for the transfer.\r
1803   Data                : Array of pointers to the buffers of data\r
1804   Translator          : A pointr to the transaction translator data.\r
1805   IsochronousCallBack : Function to call when the transfer complete\r
1806   Context             : Pass to the call back function as parameter\r
1807 \r
1808   @return EFI_UNSUPPORTED\r
1809 \r
1810 **/\r
1811 STATIC\r
1812 EFI_STATUS\r
1813 EFIAPI\r
1814 Uhci2AsyncIsochronousTransfer (\r
1815   IN     EFI_USB2_HC_PROTOCOL                *This,\r
1816   IN     UINT8                               DeviceAddress,\r
1817   IN     UINT8                               EndPointAddress,\r
1818   IN     UINT8                               DeviceSpeed,\r
1819   IN     UINTN                               MaximumPacketLength,\r
1820   IN     UINT8                               DataBuffersNumber,\r
1821   IN OUT VOID                                *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1822   IN     UINTN                               DataLength,\r
1823   IN     EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
1824   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,\r
1825   IN     VOID                                *Context\r
1826   )\r
1827 {\r
1828   return EFI_UNSUPPORTED;\r
1829 }\r
1830 \r
1831 EFI_STATUS\r
1832 EFIAPI\r
1833 UhciDriverEntryPoint (\r
1834   IN EFI_HANDLE           ImageHandle,\r
1835   IN EFI_SYSTEM_TABLE     *SystemTable\r
1836   )\r
1837 /*++\r
1838 \r
1839   Routine Description:\r
1840 \r
1841     Entry point for EFI drivers.\r
1842 \r
1843   Arguments:\r
1844 \r
1845     ImageHandle - EFI_HANDLE\r
1846     SystemTable - EFI_SYSTEM_TABLE\r
1847 \r
1848   Returns:\r
1849 \r
1850     EFI_SUCCESS : Driver is successfully loaded\r
1851     Others      : Failed\r
1852 \r
1853 --*/\r
1854 {\r
1855   return EfiLibInstallAllDriverProtocols (\r
1856            ImageHandle,\r
1857            SystemTable,\r
1858            &gUhciDriverBinding,\r
1859            ImageHandle,\r
1860            &gUhciComponentName,\r
1861            NULL,\r
1862            NULL\r
1863            );\r
1864 }\r
1865 \r
1866 \r
1867 /**\r
1868   Test to see if this driver supports ControllerHandle. Any\r
1869   ControllerHandle that has UsbHcProtocol installed will be supported.\r
1870 \r
1871   @param  This                 Protocol instance pointer.\r
1872   @param  Controller           Handle of device to test\r
1873   @param  RemainingDevicePath  Not used\r
1874 \r
1875   @return EFI_SUCCESS         : This driver supports this device.\r
1876   @return EFI_UNSUPPORTED     : This driver does not support this device.\r
1877 \r
1878 **/\r
1879 EFI_STATUS\r
1880 EFIAPI\r
1881 UhciDriverBindingSupported (\r
1882   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
1883   IN EFI_HANDLE                      Controller,\r
1884   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
1885   )\r
1886 {\r
1887   EFI_STATUS            OpenStatus;\r
1888   EFI_STATUS            Status;\r
1889   EFI_PCI_IO_PROTOCOL   *PciIo;\r
1890   USB_CLASSC            UsbClassCReg;\r
1891 \r
1892   //\r
1893   // Test whether there is PCI IO Protocol attached on the controller handle.\r
1894   //\r
1895   OpenStatus = gBS->OpenProtocol (\r
1896                       Controller,\r
1897                       &gEfiPciIoProtocolGuid,\r
1898                       (VOID **) &PciIo,\r
1899                       This->DriverBindingHandle,\r
1900                       Controller,\r
1901                       EFI_OPEN_PROTOCOL_BY_DRIVER\r
1902                       );\r
1903 \r
1904   if (EFI_ERROR (OpenStatus)) {\r
1905     return OpenStatus;\r
1906   }\r
1907 \r
1908   Status = PciIo->Pci.Read (\r
1909                         PciIo,\r
1910                         EfiPciIoWidthUint8,\r
1911                         CLASSC_OFFSET,\r
1912                         sizeof (USB_CLASSC) / sizeof (UINT8),\r
1913                         &UsbClassCReg\r
1914                         );\r
1915 \r
1916   if (EFI_ERROR (Status)) {\r
1917     Status = EFI_UNSUPPORTED;\r
1918     goto ON_EXIT;\r
1919   }\r
1920 \r
1921   //\r
1922   // Test whether the controller belongs to UHCI type\r
1923   //\r
1924   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1925       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1926       (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)\r
1927       ) {\r
1928 \r
1929     Status = EFI_UNSUPPORTED;\r
1930   }\r
1931 \r
1932 ON_EXIT:\r
1933   gBS->CloseProtocol (\r
1934          Controller,\r
1935          &gEfiPciIoProtocolGuid,\r
1936          This->DriverBindingHandle,\r
1937          Controller\r
1938          );\r
1939 \r
1940   return Status;\r
1941 \r
1942 }\r
1943 \r
1944 \r
1945 /**\r
1946   Allocate and initialize the empty UHCI device\r
1947 \r
1948   @param  PciIo                The PCIIO to use\r
1949 \r
1950   @return Allocated UHCI device\r
1951 \r
1952 **/\r
1953 STATIC\r
1954 USB_HC_DEV *\r
1955 UhciAllocateDev (\r
1956   IN EFI_PCI_IO_PROTOCOL    *PciIo\r
1957   )\r
1958 {\r
1959   USB_HC_DEV  *Uhc;\r
1960   EFI_STATUS  Status;\r
1961 \r
1962   Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));\r
1963 \r
1964   if (Uhc == NULL) {\r
1965     return NULL;\r
1966   }\r
1967 \r
1968   //\r
1969   // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.\r
1970   // USB_HC_PROTOCOL is for EFI 1.1 backward compability.\r
1971   //\r
1972   Uhc->Signature                        = USB_HC_DEV_SIGNATURE;\r
1973   Uhc->UsbHc.Reset                      = UhciReset;\r
1974   Uhc->UsbHc.GetState                   = UhciGetState;\r
1975   Uhc->UsbHc.SetState                   = UhciSetState;\r
1976   Uhc->UsbHc.ControlTransfer            = UhciControlTransfer;\r
1977   Uhc->UsbHc.BulkTransfer               = UhciBulkTransfer;\r
1978   Uhc->UsbHc.AsyncInterruptTransfer     = UhciAsyncInterruptTransfer;\r
1979   Uhc->UsbHc.SyncInterruptTransfer      = UhciSyncInterruptTransfer;\r
1980   Uhc->UsbHc.IsochronousTransfer        = UhciIsochronousTransfer;\r
1981   Uhc->UsbHc.AsyncIsochronousTransfer   = UhciAsyncIsochronousTransfer;\r
1982   Uhc->UsbHc.GetRootHubPortNumber       = UhciGetRootHubPortNumber;\r
1983   Uhc->UsbHc.GetRootHubPortStatus       = UhciGetRootHubPortStatus;\r
1984   Uhc->UsbHc.SetRootHubPortFeature      = UhciSetRootHubPortFeature;\r
1985   Uhc->UsbHc.ClearRootHubPortFeature    = UhciClearRootHubPortFeature;\r
1986   Uhc->UsbHc.MajorRevision              = 0x1;\r
1987   Uhc->UsbHc.MinorRevision              = 0x1;\r
1988 \r
1989   Uhc->Usb2Hc.GetCapability             = Uhci2GetCapability;\r
1990   Uhc->Usb2Hc.Reset                     = Uhci2Reset;\r
1991   Uhc->Usb2Hc.GetState                  = Uhci2GetState;\r
1992   Uhc->Usb2Hc.SetState                  = Uhci2SetState;\r
1993   Uhc->Usb2Hc.ControlTransfer           = Uhci2ControlTransfer;\r
1994   Uhc->Usb2Hc.BulkTransfer              = Uhci2BulkTransfer;\r
1995   Uhc->Usb2Hc.AsyncInterruptTransfer    = Uhci2AsyncInterruptTransfer;\r
1996   Uhc->Usb2Hc.SyncInterruptTransfer     = Uhci2SyncInterruptTransfer;\r
1997   Uhc->Usb2Hc.IsochronousTransfer       = Uhci2IsochronousTransfer;\r
1998   Uhc->Usb2Hc.AsyncIsochronousTransfer  = Uhci2AsyncIsochronousTransfer;\r
1999   Uhc->Usb2Hc.GetRootHubPortStatus      = Uhci2GetRootHubPortStatus;\r
2000   Uhc->Usb2Hc.SetRootHubPortFeature     = Uhci2SetRootHubPortFeature;\r
2001   Uhc->Usb2Hc.ClearRootHubPortFeature   = Uhci2ClearRootHubPortFeature;\r
2002   Uhc->Usb2Hc.MajorRevision             = 0x1;\r
2003   Uhc->Usb2Hc.MinorRevision             = 0x1;\r
2004 \r
2005   Uhc->PciIo   = PciIo;\r
2006   Uhc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);\r
2007 \r
2008   if (Uhc->MemPool == NULL) {\r
2009     Status = EFI_OUT_OF_RESOURCES;\r
2010     goto ON_ERROR;\r
2011   }\r
2012 \r
2013   InitializeListHead (&Uhc->AsyncIntList);\r
2014 \r
2015   Status = gBS->CreateEvent (\r
2016                   EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
2017                   TPL_CALLBACK,\r
2018                   UhciMonitorAsyncReqList,\r
2019                   Uhc,\r
2020                   &Uhc->AsyncIntMonitor\r
2021                   );\r
2022 \r
2023   if (EFI_ERROR (Status)) {\r
2024     UsbHcFreeMemPool (Uhc->MemPool);\r
2025     goto ON_ERROR;\r
2026   }\r
2027 \r
2028   return Uhc;\r
2029 \r
2030 ON_ERROR:\r
2031   gBS->FreePool (Uhc);\r
2032   return NULL;\r
2033 }\r
2034 \r
2035 \r
2036 /**\r
2037   Free the UHCI device and release its associated resources\r
2038 \r
2039   @param  Uhc                  The UHCI device to release\r
2040 \r
2041   @return None\r
2042 \r
2043 **/\r
2044 STATIC\r
2045 VOID\r
2046 UhciFreeDev (\r
2047   IN USB_HC_DEV           *Uhc\r
2048   )\r
2049 {\r
2050   if (Uhc->AsyncIntMonitor != NULL) {\r
2051     gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
2052   }\r
2053 \r
2054   if (Uhc->MemPool != NULL) {\r
2055     UsbHcFreeMemPool (Uhc->MemPool);\r
2056   }\r
2057 \r
2058   if (Uhc->CtrlNameTable) {\r
2059     FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
2060   }\r
2061 \r
2062   gBS->FreePool (Uhc);\r
2063 }\r
2064 \r
2065 \r
2066 /**\r
2067   Uninstall all Uhci Interface\r
2068 \r
2069   @param  Controller           Controller handle\r
2070   @param  This                 Protocol instance pointer.\r
2071 \r
2072   @return VOID\r
2073 \r
2074 **/\r
2075 STATIC\r
2076 VOID\r
2077 UhciCleanDevUp (\r
2078   IN  EFI_HANDLE          Controller,\r
2079   IN  EFI_USB_HC_PROTOCOL *This\r
2080   )\r
2081 {\r
2082   USB_HC_DEV          *Uhc;\r
2083 \r
2084   //\r
2085   // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
2086   //\r
2087   Uhc = UHC_FROM_USB_HC_PROTO (This);\r
2088   UhciStopHc (Uhc, STALL_1_SECOND);\r
2089 \r
2090   gBS->UninstallProtocolInterface (\r
2091         Controller,\r
2092         &gEfiUsbHcProtocolGuid,\r
2093         &Uhc->UsbHc\r
2094         );\r
2095 \r
2096   gBS->UninstallProtocolInterface (\r
2097         Controller,\r
2098         &gEfiUsb2HcProtocolGuid,\r
2099         &Uhc->Usb2Hc\r
2100         );\r
2101 \r
2102   UhciFreeAllAsyncReq (Uhc);\r
2103   UhciDestoryFrameList (Uhc);\r
2104 \r
2105   Uhc->PciIo->Attributes (\r
2106                 Uhc->PciIo,\r
2107                 EfiPciIoAttributeOperationDisable,\r
2108                 EFI_PCI_DEVICE_ENABLE,\r
2109                 NULL\r
2110                 );\r
2111 \r
2112   UhciFreeDev (Uhc);\r
2113 }\r
2114 \r
2115 \r
2116 /**\r
2117   Starting the Usb UHCI Driver\r
2118 \r
2119   @param  This                 Protocol instance pointer.\r
2120   @param  Controller           Handle of device to test\r
2121   @param  RemainingDevicePath  Not used\r
2122 \r
2123   @retval EFI_SUCCESS          This driver supports this device.\r
2124   @retval EFI_UNSUPPORTED      This driver does not support this device.\r
2125   @retval EFI_DEVICE_ERROR     This driver cannot be started due to device Error\r
2126                                EFI_OUT_OF_RESOURCES- Failed due to resource\r
2127                                shortage\r
2128 \r
2129 **/\r
2130 EFI_STATUS\r
2131 EFIAPI\r
2132 UhciDriverBindingStart (\r
2133   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
2134   IN EFI_HANDLE                      Controller,\r
2135   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
2136   )\r
2137 {\r
2138   EFI_STATUS          Status;\r
2139   EFI_PCI_IO_PROTOCOL *PciIo;\r
2140   USB_HC_DEV          *Uhc;\r
2141 \r
2142   //\r
2143   // Open PCIIO, then enable the EHC device and turn off emulation\r
2144   //\r
2145   Uhc = NULL;\r
2146   Status = gBS->OpenProtocol (\r
2147                   Controller,\r
2148                   &gEfiPciIoProtocolGuid,\r
2149                   (VOID **) &PciIo,\r
2150                   This->DriverBindingHandle,\r
2151                   Controller,\r
2152                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
2153                   );\r
2154 \r
2155   if (EFI_ERROR (Status)) {\r
2156     return Status;\r
2157   }\r
2158 \r
2159   UhciTurnOffUsbEmulation (PciIo);\r
2160 \r
2161   Status = PciIo->Attributes (\r
2162                     PciIo,\r
2163                     EfiPciIoAttributeOperationEnable,\r
2164                     EFI_PCI_DEVICE_ENABLE,\r
2165                     NULL\r
2166                     );\r
2167 \r
2168   if (EFI_ERROR (Status)) {\r
2169     goto CLOSE_PCIIO;\r
2170   }\r
2171 \r
2172   Uhc = UhciAllocateDev (PciIo);\r
2173 \r
2174   if (Uhc == NULL) {\r
2175     Status = EFI_OUT_OF_RESOURCES;\r
2176     goto CLOSE_PCIIO;\r
2177   }\r
2178 \r
2179   //\r
2180   // Allocate and Init Host Controller's Frame List Entry\r
2181   //\r
2182   Status = UhciInitFrameList (Uhc);\r
2183 \r
2184   if (EFI_ERROR (Status)) {\r
2185     Status = EFI_OUT_OF_RESOURCES;\r
2186     goto FREE_UHC;\r
2187   }\r
2188 \r
2189   Status = gBS->SetTimer (\r
2190                   Uhc->AsyncIntMonitor,\r
2191                   TimerPeriodic,\r
2192                   INTERRUPT_POLLING_TIME\r
2193                   );\r
2194 \r
2195   if (EFI_ERROR (Status)) {\r
2196     goto FREE_UHC;\r
2197   }\r
2198 \r
2199   //\r
2200   // Install both USB_HC_PROTOCOL and USB2_HC_PROTOCOL\r
2201   //\r
2202   Status = gBS->InstallMultipleProtocolInterfaces (\r
2203                   &Controller,\r
2204                   &gEfiUsbHcProtocolGuid,\r
2205                   &Uhc->UsbHc,\r
2206                   &gEfiUsb2HcProtocolGuid,\r
2207                   &Uhc->Usb2Hc,\r
2208                   NULL\r
2209                   );\r
2210 \r
2211   if (EFI_ERROR (Status)) {\r
2212     goto FREE_UHC;\r
2213   }\r
2214 \r
2215   //\r
2216   // Install the component name protocol\r
2217   //\r
2218   Uhc->CtrlNameTable = NULL;\r
2219 \r
2220   AddUnicodeString (\r
2221     "eng",\r
2222     gUhciComponentName.SupportedLanguages,\r
2223     &Uhc->CtrlNameTable,\r
2224     L"Usb Universal Host Controller"\r
2225     );\r
2226 \r
2227   //\r
2228   // Start the UHCI hardware, also set its reclamation point to 64 bytes\r
2229   //\r
2230   UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);\r
2231 \r
2232   return EFI_SUCCESS;\r
2233 \r
2234 FREE_UHC:\r
2235   UhciFreeDev (Uhc);\r
2236 \r
2237 CLOSE_PCIIO:\r
2238   gBS->CloseProtocol (\r
2239         Controller,\r
2240         &gEfiPciIoProtocolGuid,\r
2241         This->DriverBindingHandle,\r
2242         Controller\r
2243         );\r
2244 \r
2245   return Status;\r
2246 }\r
2247 \r
2248 \r
2249 /**\r
2250   Stop this driver on ControllerHandle. Support stoping any child handles\r
2251   created by this driver.\r
2252 \r
2253   @param  This                 Protocol instance pointer.\r
2254   @param  Controller           Handle of device to stop driver on\r
2255   @param  NumberOfChildren     Number of Children in the ChildHandleBuffer\r
2256   @param  ChildHandleBuffer    List of handles for the children we need to stop.\r
2257 \r
2258   @return EFI_SUCCESS\r
2259   @return others\r
2260 \r
2261 **/\r
2262 EFI_STATUS\r
2263 EFIAPI\r
2264 UhciDriverBindingStop (\r
2265   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
2266   IN EFI_HANDLE                      Controller,\r
2267   IN UINTN                           NumberOfChildren,\r
2268   IN EFI_HANDLE                      *ChildHandleBuffer\r
2269   )\r
2270 {\r
2271   EFI_USB_HC_PROTOCOL   *UsbHc;\r
2272   EFI_USB2_HC_PROTOCOL  *Usb2Hc;\r
2273   EFI_STATUS            Status;\r
2274 \r
2275   Status = gBS->OpenProtocol (\r
2276                   Controller,\r
2277                   &gEfiUsbHcProtocolGuid,\r
2278                   (VOID **) &UsbHc,\r
2279                   This->DriverBindingHandle,\r
2280                   Controller,\r
2281                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2282                   );\r
2283   //\r
2284   // Test whether the Controller handler passed in is a valid\r
2285   // Usb controller handle that should be supported, if not,\r
2286   // return the error status directly\r
2287   //\r
2288   if (EFI_ERROR (Status)) {\r
2289     return Status;\r
2290   }\r
2291 \r
2292   Status = gBS->OpenProtocol (\r
2293                   Controller,\r
2294                   &gEfiUsb2HcProtocolGuid,\r
2295                   (VOID **) &Usb2Hc,\r
2296                   This->DriverBindingHandle,\r
2297                   Controller,\r
2298                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2299                   );\r
2300 \r
2301   //\r
2302   // Test whether the Controller handler passed in is a valid\r
2303   // Usb controller handle that should be supported, if not,\r
2304   // return the error status directly\r
2305   //\r
2306   if (EFI_ERROR (Status)) {\r
2307     return Status;\r
2308   }\r
2309 \r
2310   UhciCleanDevUp (Controller, UsbHc);\r
2311 \r
2312   gBS->CloseProtocol (\r
2313         Controller,\r
2314         &gEfiPciIoProtocolGuid,\r
2315         This->DriverBindingHandle,\r
2316         Controller\r
2317         );\r
2318 \r
2319   return EFI_SUCCESS;\r
2320 }\r
2321 \r
2322 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
2323   UhciDriverBindingSupported,\r
2324   UhciDriverBindingStart,\r
2325   UhciDriverBindingStop,\r
2326   0x20,\r
2327   NULL,\r
2328   NULL\r
2329 };\r