c6105eb0b545952ea47fa3680337ea3579152aa3
[people/mcb30/edk2.git] / edk2 / EdkModulePkg / Bus / Pci / Ehci / Dxe / Ehci.c
1 /*++\r
2 \r
3 Copyright (c) 2006, 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     Ehci.c\r
15     \r
16 Abstract: \r
17     \r
18 \r
19 Revision History\r
20 --*/\r
21 \r
22 \r
23 #include "Ehci.h"\r
24 \r
25 \r
26 GLOBAL_REMOVE_IF_UNREFERENCED UINTN    gEHCDebugLevel  = EFI_D_INFO;\r
27 GLOBAL_REMOVE_IF_UNREFERENCED UINTN    gEHCErrorLevel  = EFI_D_ERROR;\r
28 \r
29 \r
30 //\r
31 // Prototypes\r
32 // Driver model protocol interface\r
33 //\r
34 \r
35 EFI_STATUS\r
36 EFIAPI\r
37 EhciDriverBindingSupported (\r
38   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
39   IN EFI_HANDLE                      Controller,\r
40   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
41   );\r
42 \r
43 EFI_STATUS\r
44 EFIAPI\r
45 EhciDriverBindingStart (\r
46   IN EFI_DRIVER_BINDING_PROTOCOL     *This,\r
47   IN EFI_HANDLE                      Controller,\r
48   IN EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath\r
49   );\r
50 \r
51 EFI_STATUS\r
52 EFIAPI\r
53 EhciDriverBindingStop (\r
54   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
55   IN  EFI_HANDLE                      Controller,\r
56   IN  UINTN                           NumberOfChildren,\r
57   IN  EFI_HANDLE                      *ChildHandleBuffer\r
58   );\r
59 \r
60 //\r
61 // Ehci protocol interface\r
62 //\r
63 EFI_STATUS\r
64 EFIAPI\r
65 EhciGetCapability (\r
66   IN  EFI_USB2_HC_PROTOCOL   *This,\r
67   OUT UINT8                  *MaxSpeed,\r
68   OUT UINT8                  *PortNumber,\r
69   OUT UINT8                  *Is64BitCapable\r
70   );\r
71 \r
72 EFI_STATUS\r
73 EFIAPI\r
74 EhciReset (\r
75   IN  EFI_USB2_HC_PROTOCOL     *This,\r
76   IN  UINT16                   Attributes\r
77   );\r
78 \r
79 EFI_STATUS\r
80 EFIAPI\r
81 EhciGetState (\r
82   IN  EFI_USB2_HC_PROTOCOL     *This,\r
83   OUT EFI_USB_HC_STATE         *State\r
84   );\r
85 \r
86 EFI_STATUS\r
87 EFIAPI\r
88 EhciSetState (\r
89   IN  EFI_USB2_HC_PROTOCOL     *This,\r
90   IN  EFI_USB_HC_STATE         State\r
91   );\r
92 \r
93 EFI_STATUS\r
94 EFIAPI\r
95 EhciControlTransfer (\r
96   IN  EFI_USB2_HC_PROTOCOL                 *This,\r
97   IN  UINT8                                DeviceAddress,\r
98   IN  UINT8                                DeviceSpeed,\r
99   IN  UINTN                                MaximumPacketLength,\r
100   IN  EFI_USB_DEVICE_REQUEST               *Request,\r
101   IN  EFI_USB_DATA_DIRECTION               TransferDirection,\r
102   IN  OUT VOID                             *Data,\r
103   IN  OUT UINTN                            *DataLength,\r
104   IN  UINTN                                TimeOut,\r
105   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,\r
106   OUT UINT32                               *TransferResult\r
107   );\r
108 \r
109 EFI_STATUS\r
110 EFIAPI\r
111 EhciBulkTransfer (\r
112   IN  EFI_USB2_HC_PROTOCOL                *This,\r
113   IN  UINT8                               DeviceAddress,\r
114   IN  UINT8                               EndPointAddress,\r
115   IN  UINT8                               DeviceSpeed,\r
116   IN  UINTN                               MaximumPacketLength,\r
117   IN  UINT8                               DataBuffersNumber,\r
118   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
119   IN  OUT UINTN                           *DataLength,\r
120   IN  OUT UINT8                           *DataToggle,\r
121   IN  UINTN                               TimeOut,\r
122   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
123   OUT UINT32                              *TransferResult\r
124   );\r
125 \r
126 EFI_STATUS\r
127 EFIAPI\r
128 EhciAsyncInterruptTransfer (\r
129   IN  EFI_USB2_HC_PROTOCOL                  * This,\r
130   IN  UINT8                                 DeviceAddress,\r
131   IN  UINT8                                 EndPointAddress,\r
132   IN  UINT8                                 DeviceSpeed,\r
133   IN  UINTN                                 MaxiumPacketLength,\r
134   IN  BOOLEAN                               IsNewTransfer,\r
135   IN  OUT UINT8                             *DataToggle,\r
136   IN  UINTN                                 PollingInterval,\r
137   IN  UINTN                                 DataLength,\r
138   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,\r
139   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,\r
140   IN  VOID                                  *Context OPTIONAL\r
141   );\r
142 \r
143 EFI_STATUS\r
144 EFIAPI\r
145 EhciSyncInterruptTransfer (\r
146   IN  EFI_USB2_HC_PROTOCOL                  *This,\r
147   IN  UINT8                                 DeviceAddress,\r
148   IN  UINT8                                 EndPointAddress,\r
149   IN  UINT8                                 DeviceSpeed,\r
150   IN  UINTN                                 MaximumPacketLength,\r
151   IN  OUT VOID                              *Data,\r
152   IN  OUT UINTN                             *DataLength,\r
153   IN  OUT UINT8                             *DataToggle,\r
154   IN  UINTN                                 TimeOut,\r
155   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,\r
156   OUT UINT32                                *TransferResult\r
157   );\r
158 \r
159 EFI_STATUS\r
160 EFIAPI\r
161 EhciIsochronousTransfer (\r
162   IN  EFI_USB2_HC_PROTOCOL                  *This,\r
163   IN  UINT8                                 DeviceAddress,\r
164   IN  UINT8                                 EndPointAddress,\r
165   IN  UINT8                                 DeviceSpeed,\r
166   IN  UINTN                                 MaximumPacketLength,\r
167   IN  UINT8                                 DataBuffersNumber,\r
168   IN  OUT VOID                              *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
169   IN  UINTN                                 DataLength,\r
170   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,\r
171   OUT UINT32                                *TransferResult\r
172   );\r
173 \r
174 EFI_STATUS\r
175 EFIAPI\r
176 EhciAsyncIsochronousTransfer (\r
177   IN  EFI_USB2_HC_PROTOCOL                *This,\r
178   IN  UINT8                               DeviceAddress,\r
179   IN  UINT8                               EndPointAddress,\r
180   IN  UINT8                               DeviceSpeed,\r
181   IN  UINTN                               MaximumPacketLength,\r
182   IN  UINT8                               DataBuffersNumber,\r
183   IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
184   IN  UINTN                               DataLength,\r
185   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
186   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,\r
187   IN  VOID                                *Context\r
188   );\r
189 \r
190 EFI_STATUS\r
191 EFIAPI\r
192 EhciGetRootHubPortStatus (\r
193   IN  EFI_USB2_HC_PROTOCOL     *This,\r
194   IN  UINT8                    PortNumber,\r
195   OUT EFI_USB_PORT_STATUS      *PortStatus\r
196   );\r
197 \r
198 EFI_STATUS\r
199 EFIAPI\r
200 EhciSetRootHubPortFeature (\r
201   IN  EFI_USB2_HC_PROTOCOL     *This,\r
202   IN  UINT8                    PortNumber,\r
203   IN  EFI_USB_PORT_FEATURE     PortFeature\r
204   );\r
205 \r
206 EFI_STATUS\r
207 EFIAPI\r
208 EhciClearRootHubPortFeature (\r
209   IN  EFI_USB2_HC_PROTOCOL     *This,\r
210   IN  UINT8                    PortNumber,\r
211   IN  EFI_USB_PORT_FEATURE     PortFeature\r
212   );\r
213 \r
214 //\r
215 // Ehci Driver Global Variables\r
216 //\r
217 EFI_DRIVER_BINDING_PROTOCOL gEhciDriverBinding = {\r
218   EhciDriverBindingSupported,\r
219   EhciDriverBindingStart,\r
220   EhciDriverBindingStop,\r
221   0x10,\r
222   NULL,\r
223   NULL\r
224 };\r
225 \r
226 UINT32                      mUsbCapabilityLen;\r
227 UINT32                      mDeviceSpeed[16];\r
228 \r
229 EFI_STATUS\r
230 EFIAPI\r
231 EhciDriverBindingSupported (\r
232   IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
233   IN EFI_HANDLE                  Controller,\r
234   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath\r
235   )\r
236 /*++\r
237 \r
238   Routine Description:\r
239   \r
240     Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
241     that has Usb2HcProtocol installed will be supported.\r
242 \r
243   Arguments:\r
244   \r
245     This                - Protocol instance pointer.\r
246     Controlle           - Handle of device to test\r
247     RemainingDevicePath - Not used\r
248 \r
249   Returns:\r
250   \r
251     EFI_SUCCESS       This driver supports this device.\r
252     EFI_UNSUPPORTED   This driver does not support this device.\r
253 \r
254 --*/\r
255 {\r
256   EFI_STATUS          Status;\r
257   EFI_PCI_IO_PROTOCOL *PciIo;\r
258   USB_CLASSC          UsbClassCReg;\r
259 \r
260   \r
261   //\r
262   // Test whether there is PCI IO Protocol attached on the controller handle.\r
263   //\r
264   Status = gBS->OpenProtocol (\r
265                   Controller,\r
266                   &gEfiPciIoProtocolGuid,\r
267                   (VOID **) &PciIo,\r
268                   This->DriverBindingHandle,\r
269                   Controller,\r
270                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
271                   );\r
272   if (EFI_ERROR (Status)) {\r
273     goto exit;\r
274   }\r
275 \r
276   Status = PciIo->Pci.Read (\r
277                         PciIo,\r
278                         EfiPciIoWidthUint8,\r
279                         CLASSC,\r
280                         sizeof (USB_CLASSC) / sizeof (UINT8),\r
281                         &UsbClassCReg\r
282                         );\r
283   if (EFI_ERROR (Status)) {\r
284     gBS->CloseProtocol (\r
285           Controller,\r
286           &gEfiPciIoProtocolGuid,\r
287           This->DriverBindingHandle,\r
288           Controller\r
289           );\r
290     Status = EFI_UNSUPPORTED;\r
291     goto exit;\r
292   }\r
293   \r
294   //\r
295   // Test whether the controller belongs to Ehci type\r
296   //\r
297   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
298       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
299       (UsbClassCReg.PI != PCI_CLASSC_PI_EHCI)\r
300       ) {\r
301 \r
302     gBS->CloseProtocol (\r
303            Controller,\r
304            &gEfiPciIoProtocolGuid,\r
305            This->DriverBindingHandle,\r
306            Controller\r
307            );\r
308 \r
309     Status = EFI_UNSUPPORTED;\r
310     goto exit;\r
311   }\r
312 \r
313   gBS->CloseProtocol (\r
314          Controller,\r
315          &gEfiPciIoProtocolGuid,\r
316          This->DriverBindingHandle,\r
317          Controller\r
318          );\r
319 \r
320 exit:\r
321   return Status;\r
322 }\r
323 \r
324 EFI_STATUS\r
325 EFIAPI\r
326 EhciDriverBindingStart (\r
327   IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
328   IN EFI_HANDLE                  Controller,\r
329   IN EFI_DEVICE_PATH_PROTOCOL    *RemainingDevicePath\r
330   )\r
331 /*++\r
332 \r
333   Routine Description:\r
334   \r
335     Starting the Usb EHCI Driver\r
336 \r
337   Arguments:\r
338   \r
339     This                - Protocol instance pointer.\r
340     Controller          - Handle of device to test\r
341     RemainingDevicePath - Not used\r
342 \r
343   Returns:\r
344   \r
345     EFI_SUCCESS           supports this device.\r
346     EFI_UNSUPPORTED       do not support this device.\r
347     EFI_DEVICE_ERROR      cannot be started due to device Error\r
348     EFI_OUT_OF_RESOURCES  cannot allocate resources\r
349 \r
350 --*/\r
351 {\r
352   EFI_STATUS            Status;\r
353   USB2_HC_DEV           *HcDev;\r
354   EFI_PCI_IO_PROTOCOL   *PciIo;\r
355   UINT8                 MaxSpeed;\r
356   UINT8                 PortNumber;\r
357   UINT8                 Is64BitCapable;\r
358   \r
359   //\r
360   // Open the PciIo Protocol\r
361   //\r
362   Status = gBS->OpenProtocol (\r
363                   Controller,\r
364                   &gEfiPciIoProtocolGuid,\r
365                   (VOID **) &PciIo,\r
366                   This->DriverBindingHandle,\r
367                   Controller,\r
368                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
369                   );\r
370   if (EFI_ERROR (Status)) {\r
371     Status = EFI_OUT_OF_RESOURCES;\r
372     goto exit;\r
373   }\r
374   \r
375   //\r
376   // Enable the USB Host Controller\r
377   //\r
378   Status = PciIo->Attributes (\r
379                     PciIo,\r
380                     EfiPciIoAttributeOperationEnable,\r
381                     EFI_PCI_DEVICE_ENABLE,\r
382                     NULL\r
383                     );\r
384   if (EFI_ERROR (Status)) {\r
385     Status = EFI_OUT_OF_RESOURCES;\r
386     goto close_pciio_protocol;\r
387   }\r
388   \r
389   //\r
390   // Allocate memory for EHC private data structure\r
391   //\r
392   HcDev = AllocateZeroPool (sizeof (USB2_HC_DEV));\r
393   if (NULL == HcDev) {\r
394     Status = EFI_OUT_OF_RESOURCES;\r
395     goto close_pciio_protocol;\r
396   }\r
397   \r
398   //\r
399   // Init EFI_USB2_HC_PROTOCOL interface and private data structure\r
400   //\r
401   HcDev->Usb2Hc.GetCapability             = EhciGetCapability;\r
402   HcDev->Usb2Hc.Reset                     = EhciReset;\r
403   HcDev->Usb2Hc.GetState                  = EhciGetState;\r
404   HcDev->Usb2Hc.SetState                  = EhciSetState;\r
405   HcDev->Usb2Hc.ControlTransfer           = EhciControlTransfer;\r
406   HcDev->Usb2Hc.BulkTransfer              = EhciBulkTransfer;\r
407   HcDev->Usb2Hc.AsyncInterruptTransfer    = EhciAsyncInterruptTransfer;\r
408   HcDev->Usb2Hc.SyncInterruptTransfer     = EhciSyncInterruptTransfer;\r
409   HcDev->Usb2Hc.IsochronousTransfer       = EhciIsochronousTransfer;\r
410   HcDev->Usb2Hc.AsyncIsochronousTransfer  = EhciAsyncIsochronousTransfer;\r
411   HcDev->Usb2Hc.GetRootHubPortStatus      = EhciGetRootHubPortStatus;\r
412   HcDev->Usb2Hc.SetRootHubPortFeature     = EhciSetRootHubPortFeature;\r
413   HcDev->Usb2Hc.ClearRootHubPortFeature   = EhciClearRootHubPortFeature;\r
414   HcDev->Usb2Hc.MajorRevision             = 0x1;\r
415   HcDev->Usb2Hc.MinorRevision             = 0x1;\r
416 \r
417   HcDev->AsyncRequestList                 = NULL;\r
418   HcDev->ControllerNameTable              = NULL;\r
419   HcDev->Signature                        = USB2_HC_DEV_SIGNATURE;\r
420   HcDev->PciIo = PciIo;\r
421 \r
422   //\r
423   // Install USB2_HC_PROTOCOL\r
424   //\r
425   Status = gBS->InstallProtocolInterface (\r
426                   &Controller,\r
427                   &gEfiUsb2HcProtocolGuid,\r
428                   EFI_NATIVE_INTERFACE,\r
429                   &HcDev->Usb2Hc\r
430                   );\r
431   if (EFI_ERROR (Status)) {\r
432     Status = EFI_OUT_OF_RESOURCES;\r
433     goto free_pool;\r
434   }\r
435   \r
436   //\r
437   // Get Capability Register Length\r
438   //\r
439   Status = GetCapabilityLen (HcDev);\r
440   if (EFI_ERROR (Status)) {\r
441     Status = EFI_DEVICE_ERROR;\r
442     goto uninstall_usb2hc_protocol;\r
443   }\r
444   \r
445   //\r
446   // Create and Init Perodic Frame List\r
447   //\r
448   Status = EhciGetCapability (\r
449              &HcDev->Usb2Hc, \r
450              &MaxSpeed, \r
451              &PortNumber, \r
452              &Is64BitCapable\r
453              );\r
454   if (EFI_ERROR (Status)) {\r
455     Status = EFI_OUT_OF_RESOURCES;\r
456     goto uninstall_usb2hc_protocol;\r
457   }\r
458   HcDev->Is64BitCapable = Is64BitCapable;\r
459   \r
460   //\r
461   // Create and Init Perodic Frame List\r
462   //\r
463   Status = InitialPeriodicFrameList (\r
464              HcDev, \r
465              EHCI_MAX_FRAME_LIST_LENGTH\r
466              );\r
467   if (EFI_ERROR (Status)) {\r
468     Status = EFI_OUT_OF_RESOURCES;\r
469     goto uninstall_usb2hc_protocol;\r
470   }\r
471   \r
472   //\r
473   // Init memory pool management\r
474   //\r
475   Status = InitialMemoryManagement (HcDev);\r
476   if (EFI_ERROR (Status)) {\r
477     Status = EFI_OUT_OF_RESOURCES;\r
478     goto deinit_perodic_frame_list;\r
479   }\r
480   \r
481   //\r
482   // Create AsyncRequest Polling Timer\r
483   //\r
484   Status = CreatePollingTimer (HcDev, (EFI_EVENT_NOTIFY) AsyncRequestMoniter);\r
485   if (EFI_ERROR (Status)) {\r
486     Status = EFI_OUT_OF_RESOURCES;\r
487     goto deinit_memory_management;\r
488   }\r
489   \r
490   //\r
491   // Default Maxximum Interrupt Interval is 8, \r
492   // it means that 8 micro frame = 1ms\r
493   //\r
494   \r
495   //\r
496   // Start the Host Controller\r
497   //\r
498   if (IsEhcHalted (HcDev)) {\r
499     Status = StartScheduleExecution (HcDev);\r
500     if (EFI_ERROR (Status)) {\r
501       Status = EFI_DEVICE_ERROR;\r
502       goto deinit_timer;\r
503     }\r
504   }\r
505   \r
506   //\r
507   // Set all ports routing to EHC\r
508   //\r
509   Status = SetPortRoutingEhc (HcDev);\r
510   if (EFI_ERROR (Status)) {\r
511     Status = EFI_DEVICE_ERROR;\r
512     goto deinit_timer;\r
513   }\r
514   \r
515   //\r
516   // Component name protocol\r
517   //\r
518   Status = AddUnicodeString (\r
519              "eng",\r
520              gEhciComponentName.SupportedLanguages,\r
521              &HcDev->ControllerNameTable,\r
522              L"Usb Enhanced Host Controller"\r
523              );\r
524   if (EFI_ERROR (Status)) {\r
525     Status = EFI_OUT_OF_RESOURCES;\r
526     goto deinit_timer;\r
527   }\r
528 \r
529   goto exit;\r
530 \r
531   //\r
532   // Error handle process\r
533   //\r
534 deinit_timer:\r
535   DestoryPollingTimer (HcDev);\r
536 deinit_memory_management:\r
537   DeinitialMemoryManagement (HcDev);\r
538 deinit_perodic_frame_list:\r
539   DeinitialPeriodicFrameList (HcDev);\r
540 uninstall_usb2hc_protocol:\r
541   gBS->UninstallProtocolInterface (\r
542          Controller,\r
543          &gEfiUsb2HcProtocolGuid,\r
544          &HcDev->Usb2Hc\r
545          );\r
546 free_pool:\r
547   gBS->FreePool (HcDev);\r
548 close_pciio_protocol:\r
549   gBS->CloseProtocol (\r
550          Controller,\r
551          &gEfiPciIoProtocolGuid,\r
552          This->DriverBindingHandle,\r
553          Controller\r
554          );\r
555 \r
556 exit:\r
557   return Status;\r
558 }\r
559 \r
560 EFI_STATUS\r
561 EFIAPI\r
562 EhciDriverBindingStop (\r
563   IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
564   IN EFI_HANDLE                  Controller,\r
565   IN UINTN                       NumberOfChildren,\r
566   IN EFI_HANDLE                  *ChildHandleBuffer\r
567   )\r
568 /*++\r
569 \r
570   Routine Description:\r
571   \r
572     Stop this driver on ControllerHandle. Support stoping any child handles\r
573     created by this driver.\r
574 \r
575   Arguments:\r
576   \r
577     This              - Protocol instance pointer.\r
578     Controller        - Handle of device to stop driver on\r
579     NumberOfChildren  - Number of Children in the ChildHandleBuffer\r
580     ChildHandleBuffer - List of handles for the children we need to stop.\r
581 \r
582   Returns:\r
583   \r
584     EFI_SUCCESS         Success\r
585     EFI_DEVICE_ERROR    Fail\r
586 --*/\r
587 {\r
588   EFI_STATUS            Status;\r
589   EFI_USB2_HC_PROTOCOL  *Usb2Hc;\r
590   USB2_HC_DEV           *HcDev;\r
591 \r
592   //\r
593   // Test whether the Controller handler passed in is a valid\r
594   // Usb controller handle that should be supported, if not,\r
595   // return the error status directly\r
596   //\r
597   Status = gBS->OpenProtocol (\r
598                   Controller,\r
599                   &gEfiUsb2HcProtocolGuid,\r
600                   (VOID **) &Usb2Hc,\r
601                   This->DriverBindingHandle,\r
602                   Controller,\r
603                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
604                   );\r
605   if (EFI_ERROR (Status)) {\r
606     Status = EFI_DEVICE_ERROR;\r
607     goto exit;\r
608   }\r
609 \r
610   HcDev = USB2_HC_DEV_FROM_THIS (Usb2Hc);\r
611 \r
612   //\r
613   // free all the controller related memory and uninstall UHCI Protocol.\r
614   //\r
615   Status = gBS->UninstallProtocolInterface (\r
616                   Controller,\r
617                   &gEfiUsb2HcProtocolGuid,\r
618                   Usb2Hc\r
619                   );\r
620   if (EFI_ERROR (Status)) {\r
621     Status = EFI_DEVICE_ERROR;\r
622     goto exit;\r
623   }\r
624   \r
625   //\r
626   // Set Host Controller state as halt\r
627   //\r
628   Status = Usb2Hc->SetState (\r
629                      Usb2Hc, \r
630                      EfiUsbHcStateHalt\r
631                      );\r
632   if (EFI_ERROR (Status)) {\r
633     Status = EFI_DEVICE_ERROR;\r
634     goto exit;\r
635   }\r
636   \r
637   //\r
638   // Stop AsyncRequest Polling Timer\r
639   //\r
640   Status = StopPollingTimer (HcDev);\r
641   if (EFI_ERROR (Status)) {\r
642     Status = EFI_DEVICE_ERROR;\r
643     goto exit;\r
644   }\r
645   \r
646   //\r
647   // Destroy Asynchronous Request Event\r
648   //\r
649   DestoryPollingTimer (HcDev);\r
650 \r
651   //\r
652   // Destroy Perodic Frame List\r
653   //\r
654   DeinitialPeriodicFrameList (HcDev);\r
655 \r
656   //\r
657   // Deinit Ehci pool memory management\r
658   //\r
659   DeinitialMemoryManagement (HcDev);\r
660 \r
661   //\r
662   // Denint Unicode String Table\r
663   //\r
664   FreeUnicodeStringTable (HcDev->ControllerNameTable);\r
665 \r
666   //\r
667   // Disable the USB Host Controller\r
668   //\r
669   Status = HcDev->PciIo->Attributes (\r
670                            HcDev->PciIo,\r
671                            EfiPciIoAttributeOperationDisable,\r
672                            EFI_PCI_DEVICE_ENABLE,\r
673                            NULL\r
674                            );\r
675   if (EFI_ERROR (Status)) {\r
676     Status = EFI_DEVICE_ERROR;\r
677     goto exit;\r
678   }\r
679 \r
680   gBS->FreePool (HcDev);\r
681 \r
682   gBS->CloseProtocol (\r
683         Controller,\r
684         &gEfiPciIoProtocolGuid,\r
685         This->DriverBindingHandle,\r
686         Controller\r
687         );\r
688 \r
689 exit:\r
690   return Status;\r
691 }\r
692 \r
693 EFI_STATUS\r
694 EFIAPI\r
695 EhciGetCapability (\r
696   IN  EFI_USB2_HC_PROTOCOL *This,\r
697   OUT UINT8                *MaxSpeed,\r
698   OUT UINT8                *PortNumber,\r
699   OUT UINT8                *Is64BitCapable\r
700   )\r
701 /*++\r
702   \r
703   Routine Description:\r
704   \r
705     Retrieves the capablility of root hub ports.\r
706     \r
707   Arguments:\r
708   \r
709     This            - A pointer to the EFI_USB_HC_PROTOCOL instance.\r
710     MaxSpeed        - A pointer to the number of the host controller.\r
711     PortNumber      - A pointer to the number of the root hub ports.\r
712     Is64BitCapable  - A pointer to the flag for whether controller supports \r
713                       64-bit memory addressing.\r
714     \r
715   Returns:\r
716   \r
717     EFI_SUCCESS            host controller capability were retrieved successfully.\r
718     EFI_INVALID_PARAMETER  MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
719     EFI_DEVICE_ERROR       An error was encountered while attempting to retrieve the capabilities.  \r
720           \r
721 --*/\r
722 {\r
723   EFI_STATUS  Status;\r
724   USB2_HC_DEV *HcDev;\r
725   UINT32      HcStructParamsAddr;\r
726   UINT32      HcStructParamsReg;\r
727   UINT32      HcCapParamsAddr;\r
728   UINT32      HcCapParamsReg;\r
729 \r
730   if (MaxSpeed == NULL || PortNumber == NULL || Is64BitCapable == NULL) {\r
731     Status = EFI_INVALID_PARAMETER;\r
732     goto exit;\r
733   }\r
734 \r
735   HcStructParamsAddr  = HCSPARAMS;\r
736   HcCapParamsAddr     = HCCPARAMS;\r
737   HcDev               = USB2_HC_DEV_FROM_THIS (This);\r
738 \r
739   Status = ReadEhcCapabiltiyReg (\r
740              HcDev,\r
741              HcStructParamsAddr,\r
742              &HcStructParamsReg\r
743              );\r
744   if (EFI_ERROR (Status)) {\r
745     Status = EFI_DEVICE_ERROR;\r
746     goto exit;\r
747   }\r
748 \r
749   Status = ReadEhcCapabiltiyReg (\r
750              HcDev,\r
751              HcCapParamsAddr,\r
752              &HcCapParamsReg\r
753              );\r
754   if (EFI_ERROR (Status)) {\r
755     Status = EFI_DEVICE_ERROR;\r
756     goto exit;\r
757   }\r
758 \r
759   *MaxSpeed       = EFI_USB_SPEED_HIGH;\r
760   *PortNumber     = (UINT8) (HcStructParamsReg & HCSP_NPORTS);\r
761   *Is64BitCapable = (UINT8) (HcCapParamsReg & HCCP_64BIT);\r
762 \r
763 exit:\r
764   return Status;\r
765 }\r
766 \r
767 EFI_STATUS\r
768 EFIAPI\r
769 EhciReset (\r
770   IN EFI_USB2_HC_PROTOCOL *This,\r
771   IN UINT16               Attributes\r
772   )\r
773 /*++\r
774   \r
775   Routine Description:\r
776   \r
777     Provides software reset for the USB host controller.\r
778   \r
779   Arguments:\r
780   \r
781   This        - A pointer to the EFI_USB2_HC_PROTOCOL instance.  \r
782   Attributes  - A bit mask of the reset operation to perform. \r
783                 See below for a list of the supported bit mask values.\r
784   \r
785   #define EFI_USB_HC_RESET_GLOBAL  0x0001\r
786   #define EFI_USB_HC_RESET_HOST_CONTROLLER  0x0002\r
787   #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG  0x0004\r
788   #define EFI_USB_HC_RESET_HOST_WITH_DEBUG  0x0008\r
789 \r
790   EFI_USB_HC_RESET_GLOBAL \r
791         If this bit is set, a global reset signal will be sent to the USB bus.\r
792         This resets all of the USB bus logic, including the USB host \r
793         controller hardware and all the devices attached on the USB bus.\r
794   EFI_USB_HC_RESET_HOST_CONTROLLER  \r
795         If this bit is set, the USB host controller hardware will be reset. \r
796         No reset signal will be sent to the USB bus.\r
797   EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG\r
798         If this bit is set, a global reset signal will be sent to the USB bus.\r
799         This resets all of the USB bus logic, including the USB host \r
800         controller hardware and all the devices attached on the USB bus. \r
801         If this is an EHCI controller and the debug port has configured, then \r
802         this is will still reset the host controller.\r
803   EFI_USB_HC_RESET_HOST_WITH_DEBUG\r
804         If this bit is set, the USB host controller hardware will be reset. \r
805         If this is an EHCI controller and the debug port has been configured,\r
806         then this will still reset the host controller.\r
807         \r
808   Returns:\r
809   \r
810     EFI_SUCCESS \r
811         The reset operation succeeded.\r
812     EFI_INVALID_PARAMETER \r
813         Attributes is not valid.\r
814     EFI_UNSUPPOURTED\r
815         The type of reset specified by Attributes is not currently supported by\r
816         the host controller hardware.\r
817     EFI_ACCESS_DENIED\r
818         Reset operation is rejected due to the debug port being configured and \r
819         active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or \r
820         EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to\r
821         perform reset operation for this host controller.\r
822     EFI_DEVICE_ERROR  \r
823         An error was encountered while attempting to perform \r
824         the reset operation.\r
825         \r
826 --*/\r
827 {\r
828   EFI_STATUS        Status;\r
829   USB2_HC_DEV       *HcDev;\r
830   UINTN             FrameIndex;\r
831   FRAME_LIST_ENTRY  *FrameEntryPtr;\r
832 \r
833   HcDev = USB2_HC_DEV_FROM_THIS (This);\r
834 \r
835   switch (Attributes) {\r
836 \r
837   case EFI_USB_HC_RESET_GLOBAL:\r
838     \r
839     //\r
840     // Same behavior as Host Controller Reset\r
841     //\r
842 \r
843   case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
844         \r
845     //\r
846     // Host Controller must be Halt when Reset it\r
847     //\r
848     if (IsEhcHalted (HcDev)) {\r
849       Status = ResetEhc (HcDev);\r
850       if (EFI_ERROR (Status)) {\r
851         Status = EFI_DEVICE_ERROR;\r
852         goto exit;\r
853       }\r
854       //\r
855       // Set to zero by Host Controller when reset process completes\r
856       //\r
857       Status = WaitForEhcReset (HcDev, EHCI_GENERIC_TIMEOUT);\r
858       if (EFI_ERROR (Status)) {\r
859         Status = EFI_TIMEOUT;\r
860         goto exit;\r
861       }\r
862     } else {\r
863       Status = EFI_DEVICE_ERROR;\r
864       goto exit;\r
865     }\r
866 \r
867     //\r
868     // only asynchronous interrupt transfers are always alive on the bus, need to cleanup\r
869     //\r
870     CleanUpAllAsyncRequestTransfer (HcDev);\r
871     Status = ClearEhcAllStatus (HcDev);\r
872     if (EFI_ERROR (Status)) {\r
873       Status = EFI_DEVICE_ERROR;\r
874       goto exit;\r
875     }\r
876 \r
877     //\r
878     // Set appropriate 4G Segment Selector\r
879     //\r
880     Status = SetCtrlDataStructSeg (HcDev);\r
881     if (EFI_ERROR (Status)) {\r
882       Status = EFI_DEVICE_ERROR;\r
883       goto exit;\r
884     }\r
885 \r
886     //\r
887     // Init Perodic List Base Addr and Frame List\r
888     //\r
889     Status = SetFrameListBaseAddr (\r
890                HcDev, \r
891                (UINT32)GET_0B_TO_31B (HcDev->PeriodicFrameListBuffer)\r
892                );\r
893     if (EFI_ERROR (Status)) {\r
894       Status = EFI_DEVICE_ERROR;\r
895       goto exit;\r
896     }\r
897     FrameEntryPtr = (FRAME_LIST_ENTRY *) HcDev->PeriodicFrameListBuffer;\r
898     for (FrameIndex = 0; FrameIndex < HcDev->PeriodicFrameListLength; FrameIndex++) {\r
899       FrameEntryPtr->LinkTerminate = TRUE;\r
900       FrameEntryPtr++;\r
901     }\r
902 \r
903     //\r
904     // Start the Host Controller\r
905     //\r
906     if (IsEhcHalted (HcDev)) {\r
907       Status = StartScheduleExecution (HcDev);\r
908       if (EFI_ERROR (Status)) {\r
909         Status = EFI_DEVICE_ERROR;\r
910         goto exit;\r
911       }\r
912     }\r
913 \r
914     //\r
915     // Set all ports routing to EHC\r
916     //\r
917     Status = SetPortRoutingEhc (HcDev);\r
918     if (EFI_ERROR (Status)) {\r
919       Status = EFI_DEVICE_ERROR;\r
920       goto exit;\r
921     }\r
922     break;\r
923 \r
924   case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:\r
925         \r
926     Status = EFI_UNSUPPORTED;\r
927     break;\r
928 \r
929   case EFI_USB_HC_RESET_HOST_WITH_DEBUG:\r
930         \r
931     Status = EFI_UNSUPPORTED;\r
932     break;\r
933 \r
934   default:\r
935     Status = EFI_INVALID_PARAMETER;\r
936   }\r
937 \r
938 exit:\r
939   return Status;\r
940 }\r
941 \r
942 EFI_STATUS\r
943 EFIAPI\r
944 EhciGetState (\r
945   IN  EFI_USB2_HC_PROTOCOL *This,\r
946   OUT EFI_USB_HC_STATE     *State\r
947   )\r
948 /*++\r
949   \r
950   Routine Description:\r
951   \r
952     Retrieves current state of the USB host controller.\r
953   \r
954   Arguments:\r
955     \r
956     This      A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
957     State     A pointer to the EFI_USB_HC_STATE data structure that \r
958               indicates current state of the USB host controller.  \r
959               Type EFI_USB_HC_STATE is defined below.\r
960               \r
961     typedef enum {\r
962       EfiUsbHcStateHalt,\r
963       EfiUsbHcStateOperational,\r
964       EfiUsbHcStateSuspend,\r
965       EfiUsbHcStateMaximum\r
966     } EFI_USB_HC_STATE;\r
967   \r
968   Returns:\r
969   \r
970     EFI_SUCCESS \r
971             The state information of the host controller was returned in State.\r
972     EFI_INVALID_PARAMETER \r
973             State is NULL.\r
974     EFI_DEVICE_ERROR  \r
975             An error was encountered while attempting to retrieve the \r
976             host controller's current state.  \r
977 --*/\r
978 {\r
979   EFI_STATUS  Status;\r
980   USB2_HC_DEV *HcDev;\r
981   UINT32      UsbStatusAddr;\r
982   UINT32      UsbStatusReg;\r
983 \r
984   if (State == NULL) {\r
985     Status = EFI_INVALID_PARAMETER;\r
986     goto exit;\r
987   }\r
988 \r
989   UsbStatusAddr = USBSTS;\r
990   HcDev         = USB2_HC_DEV_FROM_THIS (This);\r
991 \r
992   Status = ReadEhcOperationalReg (\r
993              HcDev,\r
994              UsbStatusAddr,\r
995              &UsbStatusReg\r
996              );\r
997   if (EFI_ERROR (Status)) {\r
998     Status = EFI_DEVICE_ERROR;\r
999     goto exit;\r
1000   }\r
1001 \r
1002   if (UsbStatusReg & USBSTS_HCH) {\r
1003     *State = EfiUsbHcStateHalt;\r
1004   } else {\r
1005     *State = EfiUsbHcStateOperational;\r
1006   }\r
1007 \r
1008 exit:\r
1009   return Status;\r
1010 }\r
1011 \r
1012 EFI_STATUS\r
1013 EFIAPI\r
1014 EhciSetState (\r
1015   IN EFI_USB2_HC_PROTOCOL *This,\r
1016   IN EFI_USB_HC_STATE     State\r
1017   )\r
1018 /*++\r
1019   \r
1020   Routine Description:\r
1021   \r
1022     Sets the USB host controller to a specific state.\r
1023   \r
1024   Arguments:\r
1025     \r
1026     This     - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1027     State    - Indicates the state of the host controller that will be set.\r
1028   \r
1029   Returns:\r
1030   \r
1031     EFI_SUCCESS \r
1032           The USB host controller was successfully placed in the state \r
1033           specified by State.\r
1034     EFI_INVALID_PARAMETER \r
1035           State is invalid.\r
1036     EFI_DEVICE_ERROR  \r
1037           Failed to set the state specified by State due to device error.  \r
1038           \r
1039 --*/\r
1040 {\r
1041   EFI_STATUS        Status;\r
1042   USB2_HC_DEV       *HcDev;\r
1043   UINT32            UsbCommandAddr;\r
1044   UINT32            UsbCommandReg;\r
1045   EFI_USB_HC_STATE  CurrentState;\r
1046 \r
1047   UsbCommandAddr  = USBCMD;\r
1048   HcDev           = USB2_HC_DEV_FROM_THIS (This);\r
1049 \r
1050   Status          = EhciGetState (This, &CurrentState);\r
1051   if (EFI_ERROR (Status)) {\r
1052     Status = EFI_DEVICE_ERROR;\r
1053     goto exit;\r
1054   }\r
1055 \r
1056   switch (State) {\r
1057 \r
1058   case EfiUsbHcStateHalt:\r
1059 \r
1060     if (EfiUsbHcStateHalt == CurrentState) {\r
1061       Status = EFI_SUCCESS;\r
1062       goto exit;\r
1063     } else if (EfiUsbHcStateOperational == CurrentState) {\r
1064       Status = ReadEhcOperationalReg (\r
1065                  HcDev,\r
1066                  UsbCommandAddr,\r
1067                  &UsbCommandReg\r
1068                  );\r
1069       if (EFI_ERROR (Status)) {\r
1070         Status = EFI_DEVICE_ERROR;\r
1071         goto exit;\r
1072       }\r
1073 \r
1074       UsbCommandReg &= ~USBCMD_RS;\r
1075       Status = WriteEhcOperationalReg (\r
1076                  HcDev,\r
1077                  UsbCommandAddr,\r
1078                  UsbCommandReg\r
1079                  );\r
1080       if (EFI_ERROR (Status)) {\r
1081         Status = EFI_DEVICE_ERROR;\r
1082         goto exit;\r
1083       }\r
1084       //\r
1085       // Ensure the HC is in halt status after send the stop command\r
1086       //\r
1087       Status = WaitForEhcHalt (HcDev, EHCI_GENERIC_TIMEOUT);\r
1088       if (EFI_ERROR (Status)) {\r
1089         Status = EFI_TIMEOUT;\r
1090         goto exit;\r
1091       }\r
1092     }\r
1093     break;\r
1094 \r
1095   case EfiUsbHcStateOperational:\r
1096         \r
1097     if (IsEhcSysError (HcDev)) {\r
1098       Status = EFI_DEVICE_ERROR;\r
1099       goto exit;\r
1100     }\r
1101     if (EfiUsbHcStateOperational == CurrentState) {\r
1102       Status = EFI_SUCCESS;\r
1103       goto exit;\r
1104     } else if (EfiUsbHcStateHalt == CurrentState) {\r
1105       //\r
1106       // Set Host Controller Run\r
1107       //\r
1108       Status = ReadEhcOperationalReg (\r
1109                  HcDev,\r
1110                  UsbCommandAddr,\r
1111                  &UsbCommandReg\r
1112                  );\r
1113       if (EFI_ERROR (Status)) {\r
1114         return EFI_DEVICE_ERROR;\r
1115       }\r
1116 \r
1117       UsbCommandReg |= USBCMD_RS;\r
1118       Status = WriteEhcOperationalReg (\r
1119                  HcDev,\r
1120                  UsbCommandAddr,\r
1121                  UsbCommandReg\r
1122                  );\r
1123       if (EFI_ERROR (Status)) {\r
1124         Status = EFI_DEVICE_ERROR;\r
1125         goto exit;\r
1126       }\r
1127     }\r
1128     break;\r
1129 \r
1130   case EfiUsbHcStateSuspend:\r
1131         \r
1132     Status = EFI_UNSUPPORTED;\r
1133     break;\r
1134 \r
1135   default:\r
1136         \r
1137     Status = EFI_INVALID_PARAMETER;\r
1138   }\r
1139 \r
1140 exit:\r
1141   return Status;\r
1142 }\r
1143 \r
1144 EFI_STATUS\r
1145 EFIAPI\r
1146 EhciGetRootHubPortStatus (\r
1147   IN  EFI_USB2_HC_PROTOCOL *This,\r
1148   IN  UINT8                PortNumber,\r
1149   OUT EFI_USB_PORT_STATUS  *PortStatus\r
1150   )\r
1151 /*++\r
1152   \r
1153   Routine Description:\r
1154   \r
1155     Retrieves the current status of a USB root hub port.\r
1156   \r
1157   Arguments:\r
1158   \r
1159     This        - A pointer to the EFI_USB2_HC_PROTOCOL.\r
1160     PortNumber  - Specifies the root hub port from which the status \r
1161                   is to be retrieved.  This value is zero-based. For example, \r
1162                   if a root hub has two ports, then the first port is numbered 0,\r
1163                   and the second port is numbered 1.\r
1164     PortStatus  - A pointer to the current port status bits and \r
1165                   port status change bits.  \r
1166   \r
1167   Returns:\r
1168   \r
1169     EFI_SUCCESS           The status of the USB root hub port specified \r
1170                           by PortNumber was returned in PortStatus.\r
1171     EFI_INVALID_PARAMETER PortNumber is invalid. \r
1172     EFI_DEVICE_ERROR      Can't read register     \r
1173     \r
1174 --*/\r
1175 {\r
1176   EFI_STATUS  Status;\r
1177   USB2_HC_DEV *HcDev;\r
1178   UINT32      PortStatusControlAddr;\r
1179   UINT32      PortStatusControlReg;\r
1180   UINT8       MaxSpeed;\r
1181   UINT8       TotalPortNumber;\r
1182   UINT8       Is64BitCapable;\r
1183 \r
1184   if (PortStatus == NULL) {\r
1185     Status = EFI_INVALID_PARAMETER;\r
1186     goto exit;\r
1187   }\r
1188 \r
1189   EhciGetCapability (\r
1190     This, \r
1191     &MaxSpeed, \r
1192     &TotalPortNumber, \r
1193     &Is64BitCapable\r
1194     );\r
1195   \r
1196   if (PortNumber >= TotalPortNumber) {\r
1197     Status = EFI_INVALID_PARAMETER;\r
1198     goto exit;\r
1199   }\r
1200 \r
1201   HcDev                 = USB2_HC_DEV_FROM_THIS (This);\r
1202   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));\r
1203 \r
1204   //\r
1205   // Clear port status\r
1206   //\r
1207   PortStatus->PortStatus        = 0;\r
1208   PortStatus->PortChangeStatus  = 0;\r
1209 \r
1210   Status = ReadEhcOperationalReg (\r
1211              HcDev,\r
1212              PortStatusControlAddr,\r
1213              &PortStatusControlReg\r
1214              );\r
1215   if (EFI_ERROR (Status)) {\r
1216     Status = EFI_DEVICE_ERROR;\r
1217     goto exit;\r
1218   }\r
1219   \r
1220   //\r
1221   //    Fill Port Status bits\r
1222   //\r
1223   \r
1224   //\r
1225   // Current Connect Status\r
1226   //\r
1227   if (PORTSC_CCS & PortStatusControlReg) {\r
1228     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
1229   }\r
1230   //\r
1231   // Port Enabled/Disabled\r
1232   //\r
1233   if (PORTSC_PED & PortStatusControlReg) {\r
1234     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
1235   }\r
1236   //\r
1237   // Port Suspend\r
1238   //\r
1239   if (PORTSC_SUSP & PortStatusControlReg) {\r
1240     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
1241   }\r
1242   //\r
1243   // Over-current Active\r
1244   //\r
1245   if (PORTSC_OCA & PortStatusControlReg) {\r
1246     PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;\r
1247   }\r
1248   //\r
1249   // Port Reset\r
1250   //\r
1251   if (PORTSC_PR & PortStatusControlReg) {\r
1252     PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
1253   }\r
1254   //\r
1255   // Port Power\r
1256   //\r
1257   if (PORTSC_PP & PortStatusControlReg) {\r
1258     PortStatus->PortStatus |= USB_PORT_STAT_POWER;\r
1259   }\r
1260   //\r
1261   // Port Owner\r
1262   //\r
1263   if (PORTSC_PO & PortStatusControlReg) {\r
1264     PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
1265   }\r
1266   //\r
1267   // Identify device speed\r
1268   //\r
1269   if (PORTSC_LS_KSTATE & PortStatusControlReg) {\r
1270     //\r
1271     // Low Speed Device Attached\r
1272     //\r
1273     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
1274   } else {\r
1275     //\r
1276     // Not Low Speed Device Attached\r
1277     //\r
1278     if ((PORTSC_CCS & PortStatusControlReg) && (PORTSC_CSC & PortStatusControlReg)) {\r
1279       mDeviceSpeed[PortNumber] = IsHighSpeedDevice (This, PortNumber) ? USB_PORT_STAT_HIGH_SPEED : 0;\r
1280     }\r
1281     PortStatus->PortStatus |= mDeviceSpeed[PortNumber];\r
1282   }\r
1283   //\r
1284   // Fill Port Status Change bits\r
1285   //\r
1286   //\r
1287   // Connect Status Change\r
1288   //\r
1289   if (PORTSC_CSC & PortStatusControlReg) {\r
1290     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
1291   }\r
1292   //\r
1293   // Port Enabled/Disabled Change\r
1294   //\r
1295   if (PORTSC_PEDC & PortStatusControlReg) {\r
1296     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
1297   }\r
1298   //\r
1299   // Port Over Current Change\r
1300   //\r
1301   if (PORTSC_OCC & PortStatusControlReg) {\r
1302     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;\r
1303   }\r
1304 \r
1305 exit:\r
1306   return Status;\r
1307 }\r
1308 \r
1309 EFI_STATUS\r
1310 EFIAPI\r
1311 EhciSetRootHubPortFeature (\r
1312   IN  EFI_USB2_HC_PROTOCOL     *This,\r
1313   IN  UINT8                    PortNumber,\r
1314   IN  EFI_USB_PORT_FEATURE     PortFeature\r
1315   )\r
1316 /*++\r
1317   \r
1318   Routine Description:\r
1319   \r
1320     Sets a feature for the specified root hub port.\r
1321   \r
1322   Arguments:\r
1323   \r
1324     This        - A pointer to the EFI_USB2_HC_PROTOCOL.\r
1325     PortNumber  - Specifies the root hub port whose feature \r
1326                   is requested to be set.\r
1327     PortFeature - Indicates the feature selector associated \r
1328                   with the feature set request. \r
1329   \r
1330   Returns:\r
1331   \r
1332     EFI_SUCCESS \r
1333         The feature specified by PortFeature was set for the \r
1334         USB root hub port specified by PortNumber.\r
1335     EFI_INVALID_PARAMETER \r
1336         PortNumber is invalid or PortFeature is invalid.\r
1337     EFI_DEVICE_ERROR\r
1338         Can't read register\r
1339         \r
1340 --*/\r
1341 {\r
1342   EFI_STATUS  Status;\r
1343   USB2_HC_DEV *HcDev;\r
1344   UINT32      PortStatusControlAddr;\r
1345   UINT32      PortStatusControlReg;\r
1346   UINT8       MaxSpeed;\r
1347   UINT8       TotalPortNumber;\r
1348   UINT8       Is64BitCapable;\r
1349 \r
1350   EhciGetCapability (\r
1351     This, \r
1352     &MaxSpeed, \r
1353     &TotalPortNumber, \r
1354     &Is64BitCapable\r
1355     );\r
1356 \r
1357   if (PortNumber >= TotalPortNumber) {\r
1358     Status = EFI_INVALID_PARAMETER;\r
1359     goto exit;\r
1360   }\r
1361 \r
1362   HcDev                 = USB2_HC_DEV_FROM_THIS (This);\r
1363   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));\r
1364 \r
1365   Status = ReadEhcOperationalReg (\r
1366              HcDev,\r
1367              PortStatusControlAddr,\r
1368              &PortStatusControlReg\r
1369              );\r
1370   if (EFI_ERROR (Status)) {\r
1371     Status = EFI_DEVICE_ERROR;\r
1372     goto exit;\r
1373   }\r
1374 \r
1375   switch (PortFeature) {\r
1376 \r
1377   case EfiUsbPortEnable:\r
1378   \r
1379     //\r
1380     // Sofeware can't set this bit, Port can only be enable by the Host Controller\r
1381     // as a part of the reset and enable\r
1382     //\r
1383     PortStatusControlReg &= 0xffffffd5;\r
1384     PortStatusControlReg |= PORTSC_PED;\r
1385     break;\r
1386 \r
1387   case EfiUsbPortSuspend:\r
1388   \r
1389     PortStatusControlReg &= 0xffffffd5;\r
1390     PortStatusControlReg |= PORTSC_SUSP;\r
1391     break;\r
1392 \r
1393   case EfiUsbPortReset:\r
1394   \r
1395     //\r
1396     // Make sure Host Controller not halt before reset it\r
1397     //\r
1398     if (IsEhcHalted (HcDev)) {\r
1399       Status = StartScheduleExecution (HcDev);\r
1400       if (EFI_ERROR (Status)) {\r
1401         Status = EFI_DEVICE_ERROR;\r
1402         goto exit;\r
1403       }\r
1404       Status = WaitForEhcNotHalt (HcDev, EHCI_GENERIC_TIMEOUT);\r
1405       if (EFI_ERROR (Status)) {\r
1406         DEBUG ((gEHCDebugLevel, "WaitForEhcNotHalt TimeOut\n"));\r
1407         Status = EFI_DEVICE_ERROR;\r
1408         goto exit;\r
1409       }\r
1410     }\r
1411     PortStatusControlReg &= 0xffffffd5;\r
1412     PortStatusControlReg |= PORTSC_PR;\r
1413     //\r
1414     // Set one to PortReset bit must also set zero to PortEnable bit\r
1415     //\r
1416     PortStatusControlReg &= ~PORTSC_PED;\r
1417     break;\r
1418 \r
1419   case EfiUsbPortPower:\r
1420     \r
1421     //\r
1422     // No support, no operation\r
1423     //\r
1424     goto exit;\r
1425 \r
1426   case EfiUsbPortOwner:\r
1427   \r
1428     PortStatusControlReg &= 0xffffffd5;\r
1429     PortStatusControlReg |= PORTSC_PO;\r
1430     break;\r
1431 \r
1432   default:\r
1433         \r
1434     Status = EFI_INVALID_PARAMETER;\r
1435     goto exit;\r
1436   }\r
1437 \r
1438   Status = WriteEhcOperationalReg (\r
1439              HcDev,\r
1440              PortStatusControlAddr,\r
1441              PortStatusControlReg\r
1442              );\r
1443   if (EFI_ERROR (Status)) {\r
1444     Status = EFI_DEVICE_ERROR;\r
1445   }\r
1446 \r
1447 exit:\r
1448   return Status;\r
1449 }\r
1450 \r
1451 EFI_STATUS\r
1452 EFIAPI\r
1453 EhciClearRootHubPortFeature (\r
1454   IN  EFI_USB2_HC_PROTOCOL     *This,\r
1455   IN  UINT8                    PortNumber,\r
1456   IN  EFI_USB_PORT_FEATURE     PortFeature\r
1457   )\r
1458 /*++\r
1459   \r
1460   Routine Description:\r
1461   \r
1462     Clears a feature for the specified root hub port.\r
1463   \r
1464   Arguments:\r
1465   \r
1466     This        - A pointer to the EFI_USB2_HC_PROTOCOL instance. \r
1467     PortNumber  - Specifies the root hub port whose feature \r
1468                   is requested to be cleared.\r
1469     PortFeature - Indicates the feature selector associated with the \r
1470                   feature clear request.\r
1471                   \r
1472   Returns:\r
1473   \r
1474     EFI_SUCCESS \r
1475         The feature specified by PortFeature was cleared for the \r
1476         USB root hub port specified by PortNumber.\r
1477     EFI_INVALID_PARAMETER \r
1478         PortNumber is invalid or PortFeature is invalid.\r
1479     EFI_DEVICE_ERROR\r
1480         Can't read register\r
1481         \r
1482 --*/\r
1483 {\r
1484   EFI_STATUS  Status;\r
1485   USB2_HC_DEV *HcDev;\r
1486   UINT32      PortStatusControlAddr;\r
1487   UINT32      PortStatusControlReg;\r
1488   UINT8       MaxSpeed;\r
1489   UINT8       TotalPortNumber;\r
1490   UINT8       Is64BitCapable;\r
1491 \r
1492   EhciGetCapability (\r
1493     This, \r
1494     &MaxSpeed, \r
1495     &TotalPortNumber, \r
1496     &Is64BitCapable\r
1497     );\r
1498 \r
1499   if (PortNumber >= TotalPortNumber) {\r
1500     Status = EFI_INVALID_PARAMETER;\r
1501     goto exit;\r
1502   }\r
1503 \r
1504   HcDev                 = USB2_HC_DEV_FROM_THIS (This);\r
1505   PortStatusControlAddr = (UINT32) (PORTSC + (4 * PortNumber));\r
1506 \r
1507   Status = ReadEhcOperationalReg (\r
1508              HcDev,\r
1509              PortStatusControlAddr,\r
1510              &PortStatusControlReg\r
1511              );\r
1512   if (EFI_ERROR (Status)) {\r
1513     Status = EFI_DEVICE_ERROR;\r
1514     goto exit;\r
1515   }\r
1516 \r
1517   switch (PortFeature) {\r
1518 \r
1519   case EfiUsbPortEnable:\r
1520   \r
1521     //\r
1522     // Clear PORT_ENABLE feature means disable port.\r
1523     //\r
1524     PortStatusControlReg &= 0xffffffd5;\r
1525     PortStatusControlReg &= ~PORTSC_PED;\r
1526     break;\r
1527 \r
1528   case EfiUsbPortSuspend:\r
1529   \r
1530     //\r
1531     // A write of zero to this bit is ignored by the host controller.\r
1532     // The host controller will unconditionally set this bit to a zero when:\r
1533     //   1. software sets the Forct Port Resume bit to a zero from a one.\r
1534     //   2. software sets the Port Reset bit to a one frome a zero.\r
1535     //\r
1536     PortStatusControlReg &= 0xffffffd5;\r
1537     PortStatusControlReg &= ~PORTSC_FPR;\r
1538     break;\r
1539 \r
1540   case EfiUsbPortReset:\r
1541   \r
1542     //\r
1543     // Clear PORT_RESET means clear the reset signal.\r
1544     //\r
1545     PortStatusControlReg &= 0xffffffd5;\r
1546     PortStatusControlReg &= ~PORTSC_PR;\r
1547     break;\r
1548 \r
1549   case EfiUsbPortPower:\r
1550   \r
1551     //\r
1552     // No support, no operation\r
1553     //\r
1554     goto exit;\r
1555 \r
1556   case EfiUsbPortOwner:\r
1557   \r
1558     //\r
1559     // Clear port owner means this port owned by EHC\r
1560     //\r
1561     PortStatusControlReg &= 0xffffffd5;\r
1562     PortStatusControlReg &= ~PORTSC_PO;\r
1563     break;\r
1564 \r
1565   case EfiUsbPortConnectChange:\r
1566   \r
1567     //\r
1568     // Clear connect status change\r
1569     //\r
1570     PortStatusControlReg &= 0xffffffd5;\r
1571     PortStatusControlReg |= PORTSC_CSC;\r
1572     break;\r
1573 \r
1574   case EfiUsbPortEnableChange:\r
1575   \r
1576     //\r
1577     // Clear enable status change\r
1578     //\r
1579     PortStatusControlReg &= 0xffffffd5;\r
1580     PortStatusControlReg |= PORTSC_PEDC;\r
1581     break;\r
1582 \r
1583   case EfiUsbPortSuspendChange:\r
1584   \r
1585     //\r
1586     // No related bit, no operation\r
1587     //\r
1588     goto exit;\r
1589 \r
1590   case EfiUsbPortOverCurrentChange:\r
1591   \r
1592     //\r
1593     // Clear PortOverCurrent change\r
1594     //\r
1595     PortStatusControlReg &= 0xffffffd5;\r
1596     PortStatusControlReg |= PORTSC_OCC;\r
1597     break;\r
1598 \r
1599   case EfiUsbPortResetChange:\r
1600   \r
1601     //\r
1602     // No related bit, no operation\r
1603     //\r
1604     goto exit;\r
1605 \r
1606   default:\r
1607         \r
1608     Status = EFI_INVALID_PARAMETER;\r
1609     goto exit;\r
1610   }\r
1611 \r
1612   Status = WriteEhcOperationalReg (\r
1613              HcDev,\r
1614              PortStatusControlAddr,\r
1615              PortStatusControlReg\r
1616              );\r
1617   if (EFI_ERROR (Status)) {\r
1618     Status = EFI_DEVICE_ERROR;\r
1619     goto exit;\r
1620   }\r
1621 \r
1622 exit:\r
1623   return Status;\r
1624 }\r
1625 \r
1626 EFI_STATUS\r
1627 EFIAPI\r
1628 EhciControlTransfer (\r
1629   IN  EFI_USB2_HC_PROTOCOL                 *This,\r
1630   IN  UINT8                                DeviceAddress,\r
1631   IN  UINT8                                DeviceSpeed,\r
1632   IN  UINTN                                MaximumPacketLength,\r
1633   IN  EFI_USB_DEVICE_REQUEST               *Request,\r
1634   IN  EFI_USB_DATA_DIRECTION               TransferDirection,\r
1635   IN  OUT VOID                             *Data,\r
1636   IN  OUT UINTN                            *DataLength,\r
1637   IN  UINTN                                TimeOut,\r
1638   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR   *Translator,\r
1639   OUT UINT32                               *TransferResult\r
1640   )\r
1641 /*++\r
1642   \r
1643   Routine Description:\r
1644   \r
1645     Submits control transfer to a target USB device.\r
1646   \r
1647   Arguments:\r
1648     \r
1649     This            - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1650     DeviceAddress   - Represents the address of the target device on the USB,\r
1651                       which is assigned during USB enumeration.\r
1652     DeviceSpeed     - Indicates target device speed.\r
1653     MaximumPacketLength - Indicates the maximum packet size that the \r
1654                          default control transfer endpoint is capable of \r
1655                          sending or receiving.\r
1656     Request         - A pointer to the USB device request that will be sent \r
1657                       to the USB device. \r
1658     TransferDirection - Specifies the data direction for the transfer.\r
1659                         There are three values available, DataIn, DataOut \r
1660                         and NoData.\r
1661     Data            - A pointer to the buffer of data that will be transmitted \r
1662                       to USB device or received from USB device.\r
1663     DataLength      - Indicates the size, in bytes, of the data buffer \r
1664                       specified by Data.\r
1665     TimeOut         - Indicates the maximum time, in microseconds, \r
1666                       which the transfer is allowed to complete.\r
1667     Translator      - A pointr to the transaction translator data.\r
1668     TransferResult  - A pointer to the detailed result information generated \r
1669                       by this control transfer.\r
1670                      \r
1671   Returns:\r
1672   \r
1673     EFI_SUCCESS \r
1674         The control transfer was completed successfully.\r
1675     EFI_OUT_OF_RESOURCES  \r
1676         The control transfer could not be completed due to a lack of resources.\r
1677     EFI_INVALID_PARAMETER \r
1678         Some parameters are invalid.\r
1679     EFI_TIMEOUT \r
1680         The control transfer failed due to timeout.\r
1681     EFI_DEVICE_ERROR  \r
1682         The control transfer failed due to host controller or device error. \r
1683         Caller should check TranferResult for detailed error information.\r
1684 \r
1685 --*/\r
1686 {\r
1687   EFI_STATUS      Status;\r
1688   USB2_HC_DEV     *HcDev;\r
1689   UINT8           PktId;\r
1690   EHCI_QH_ENTITY  *QhPtr;\r
1691   EHCI_QTD_ENTITY *ControlQtdsPtr;\r
1692   UINT8           *DataCursor;\r
1693   VOID            *DataMap;\r
1694   UINT8           *RequestCursor;\r
1695   VOID            *RequestMap;\r
1696 \r
1697   QhPtr           = NULL;\r
1698   ControlQtdsPtr  = NULL;\r
1699   DataCursor      = NULL;\r
1700   DataMap         = NULL;\r
1701   RequestCursor   = NULL;\r
1702   RequestMap      = NULL;\r
1703   HcDev           = USB2_HC_DEV_FROM_THIS (This);\r
1704 \r
1705   //\r
1706   // Parameters Checking\r
1707   //\r
1708   if (TransferDirection != EfiUsbDataIn &&\r
1709         TransferDirection != EfiUsbDataOut &&\r
1710         TransferDirection != EfiUsbNoData\r
1711         ) {\r
1712     Status = EFI_INVALID_PARAMETER;\r
1713     goto exit;\r
1714   }\r
1715 \r
1716   if (EfiUsbNoData == TransferDirection) {\r
1717     if (NULL != Data || 0 != *DataLength) {\r
1718       Status = EFI_INVALID_PARAMETER;\r
1719       goto exit;\r
1720     }\r
1721   } else {\r
1722     if (NULL == Data || 0 == *DataLength) {\r
1723       Status = EFI_INVALID_PARAMETER;\r
1724       goto exit;\r
1725     }\r
1726   }\r
1727 \r
1728   if (Request == NULL || TransferResult == NULL) {\r
1729     Status = EFI_INVALID_PARAMETER;\r
1730     goto exit;\r
1731   }\r
1732 \r
1733   if (EFI_USB_SPEED_LOW == DeviceSpeed) {\r
1734     if (MaximumPacketLength != 8) {\r
1735       Status = EFI_INVALID_PARAMETER;\r
1736       goto exit;\r
1737     }\r
1738   } else if (MaximumPacketLength != 8 &&\r
1739            MaximumPacketLength != 16 &&\r
1740            MaximumPacketLength != 32 &&\r
1741            MaximumPacketLength != 64\r
1742           ) {\r
1743     Status = EFI_INVALID_PARAMETER;\r
1744     goto exit;\r
1745   }\r
1746   \r
1747   //\r
1748   // If errors exist that cause host controller halt,\r
1749   // then return EFI_DEVICE_ERROR.\r
1750   //\r
1751   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
1752     ClearEhcAllStatus (HcDev);\r
1753     *TransferResult = EFI_USB_ERR_SYSTEM;\r
1754     Status          = EFI_DEVICE_ERROR;\r
1755     goto exit;\r
1756   }\r
1757   \r
1758   //\r
1759   // Map the Request for bus master access.\r
1760   // BusMasterRead means cpu write\r
1761   //\r
1762   Status = MapRequestBuffer (\r
1763              HcDev,\r
1764              Request,\r
1765              &RequestCursor,\r
1766              &RequestMap\r
1767              );\r
1768   if (EFI_ERROR (Status)) {\r
1769     *TransferResult = EFI_USB_ERR_SYSTEM;\r
1770     Status          = EFI_DEVICE_ERROR;\r
1771     goto exit;\r
1772   }\r
1773   \r
1774   //\r
1775   // Map the source data buffer for bus master access.\r
1776   //\r
1777   Status = MapDataBuffer (\r
1778              HcDev,\r
1779              TransferDirection,\r
1780              Data,\r
1781              DataLength,\r
1782              &PktId,\r
1783              &DataCursor,\r
1784              &DataMap\r
1785              );\r
1786   if (EFI_ERROR (Status)) {\r
1787     *TransferResult = EFI_USB_ERR_SYSTEM;\r
1788     Status          = EFI_DEVICE_ERROR;\r
1789     goto unmap_request;\r
1790   }\r
1791   \r
1792   //\r
1793   // Create and init control Qh\r
1794   //\r
1795   Status = CreateControlQh (\r
1796              HcDev,\r
1797              DeviceAddress,\r
1798              DeviceSpeed,\r
1799              MaximumPacketLength,\r
1800              Translator,\r
1801              &QhPtr\r
1802              );\r
1803   if (EFI_ERROR (Status)) {\r
1804     *TransferResult = EFI_USB_ERR_SYSTEM;\r
1805     Status          = EFI_OUT_OF_RESOURCES;\r
1806     goto unmap_data;\r
1807   }\r
1808   \r
1809   //\r
1810   // Create and init control Qtds\r
1811   //\r
1812   Status = CreateControlQtds (\r
1813              HcDev,\r
1814              PktId,\r
1815              RequestCursor,\r
1816              DataCursor,\r
1817              *DataLength,\r
1818              Translator,\r
1819              &ControlQtdsPtr\r
1820              );\r
1821   if (EFI_ERROR (Status)) {\r
1822     *TransferResult = EFI_USB_ERR_SYSTEM;\r
1823     Status          = EFI_OUT_OF_RESOURCES;\r
1824     goto destory_qh;\r
1825   }\r
1826   \r
1827   //\r
1828   // Link Qtds to Qh\r
1829   //\r
1830   LinkQtdToQh (QhPtr, ControlQtdsPtr);\r
1831 \r
1832   ClearEhcAllStatus (HcDev);\r
1833 \r
1834   //\r
1835   // Link Qh and Qtds to Async Schedule List\r
1836   //\r
1837   Status = LinkQhToAsyncList (HcDev, QhPtr);\r
1838   if (EFI_ERROR (Status)) {\r
1839     *TransferResult = EFI_USB_ERR_SYSTEM;\r
1840     Status          = EFI_DEVICE_ERROR;\r
1841     goto destory_qtds;\r
1842   }\r
1843   \r
1844   //\r
1845   // Poll Qh-Qtds execution and get result.\r
1846   // detail status is returned\r
1847   //\r
1848   Status = ExecuteTransfer (\r
1849              HcDev,\r
1850              TRUE,\r
1851              QhPtr,\r
1852              DataLength,\r
1853              0,\r
1854              TimeOut,\r
1855              TransferResult\r
1856              );\r
1857   if (EFI_ERROR (Status)) {\r
1858     goto destory_qtds;\r
1859   }\r
1860   \r
1861   //\r
1862   // If has errors that cause host controller halt,\r
1863   // then return EFI_DEVICE_ERROR directly.\r
1864   //\r
1865   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
1866     *TransferResult |= EFI_USB_ERR_SYSTEM;\r
1867   }\r
1868 \r
1869   ClearEhcAllStatus (HcDev);\r
1870 \r
1871 destory_qtds:\r
1872   UnlinkQhFromAsyncList (HcDev, QhPtr);\r
1873   DestoryQtds (HcDev, ControlQtdsPtr);\r
1874 destory_qh:\r
1875   DestoryQh (HcDev, QhPtr);\r
1876 unmap_data:\r
1877   HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);\r
1878 unmap_request:\r
1879   HcDev->PciIo->Unmap (HcDev->PciIo, RequestMap);\r
1880 exit:\r
1881   HcDev->PciIo->Flush (HcDev->PciIo);\r
1882   return Status;\r
1883 }\r
1884 \r
1885 EFI_STATUS\r
1886 EFIAPI\r
1887 EhciBulkTransfer (\r
1888   IN  EFI_USB2_HC_PROTOCOL                *This,\r
1889   IN  UINT8                               DeviceAddress,\r
1890   IN  UINT8                               EndPointAddress,\r
1891   IN  UINT8                               DeviceSpeed,\r
1892   IN  UINTN                               MaximumPacketLength,\r
1893   IN  UINT8                               DataBuffersNumber,\r
1894   IN  OUT VOID                            *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
1895   IN  OUT UINTN                           *DataLength,\r
1896   IN  OUT UINT8                           *DataToggle,\r
1897   IN  UINTN                               TimeOut,\r
1898   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
1899   OUT UINT32                              *TransferResult\r
1900   )\r
1901 /*++\r
1902   \r
1903   Routine Description:\r
1904   \r
1905     Submits bulk transfer to a bulk endpoint of a USB device.\r
1906     \r
1907   Arguments:\r
1908     \r
1909     This              - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1910     DeviceAddress     - Represents the address of the target device on the USB,\r
1911                         which is assigned during USB enumeration.               \r
1912     EndPointAddress   - The combination of an endpoint number and an \r
1913                         endpoint direction of the target USB device. \r
1914                         Each endpoint address supports data transfer in \r
1915                         one direction except the control endpoint \r
1916                         (whose default endpoint address is 0). \r
1917                         It is the caller's responsibility to make sure that \r
1918                         the EndPointAddress represents a bulk endpoint.                  \r
1919     DeviceSpeed       - Indicates device speed. The supported values are EFI_USB_SPEED_FULL\r
1920                         and EFI_USB_SPEED_HIGH.\r
1921     MaximumPacketLength - Indicates the maximum packet size the target endpoint\r
1922                           is capable of sending or receiving.                 \r
1923     DataBuffersNumber - Number of data buffers prepared for the transfer.\r
1924     Data              - Array of pointers to the buffers of data that will be transmitted \r
1925                         to USB device or received from USB device.              \r
1926     DataLength        - When input, indicates the size, in bytes, of the data buffer\r
1927                         specified by Data. When output, indicates the actually \r
1928                         transferred data size.              \r
1929     DataToggle        - A pointer to the data toggle value. On input, it indicates \r
1930                         the initial data toggle value the bulk transfer should adopt;\r
1931                         on output, it is updated to indicate the data toggle value \r
1932                         of the subsequent bulk transfer. \r
1933     Translator        - A pointr to the transaction translator data. \r
1934     TimeOut           - Indicates the maximum time, in microseconds, which the \r
1935                         transfer is allowed to complete.              \r
1936     TransferResult    - A pointer to the detailed result information of the \r
1937                         bulk transfer.\r
1938 \r
1939   Returns:\r
1940   \r
1941     EFI_SUCCESS \r
1942         The bulk transfer was completed successfully.\r
1943     EFI_OUT_OF_RESOURCES  \r
1944         The bulk transfer could not be submitted due to lack of resource.\r
1945     EFI_INVALID_PARAMETER \r
1946         Some parameters are invalid.\r
1947     EFI_TIMEOUT \r
1948         The bulk transfer failed due to timeout.\r
1949     EFI_DEVICE_ERROR  \r
1950         The bulk transfer failed due to host controller or device error.\r
1951         Caller should check TranferResult for detailed error information.\r
1952 \r
1953 --*/\r
1954 {\r
1955   EFI_STATUS              Status;\r
1956   USB2_HC_DEV             *HcDev;\r
1957   UINT8                   PktId;\r
1958   EHCI_QH_ENTITY          *QhPtr;\r
1959   EHCI_QTD_ENTITY         *BulkQtdsPtr;\r
1960   UINT8                   *DataCursor;\r
1961   VOID                    *DataMap;\r
1962   EFI_USB_DATA_DIRECTION  TransferDirection;\r
1963 \r
1964   QhPtr       = NULL;\r
1965   BulkQtdsPtr = NULL;\r
1966   DataCursor  = NULL;\r
1967   DataMap     = NULL;\r
1968   HcDev       = USB2_HC_DEV_FROM_THIS (This);\r
1969 \r
1970   //\r
1971   // Parameters Checking\r
1972   //\r
1973   if (NULL == DataLength ||\r
1974         NULL == Data || \r
1975         NULL == Data[0] || \r
1976         NULL == TransferResult\r
1977         ) {\r
1978     Status = EFI_INVALID_PARAMETER;\r
1979     goto exit;\r
1980   }\r
1981 \r
1982   if (*DataLength == 0) {\r
1983     Status = EFI_INVALID_PARAMETER;\r
1984     goto exit;\r
1985   }\r
1986 \r
1987   if (1 != *DataToggle && 0 != *DataToggle) {\r
1988     Status = EFI_INVALID_PARAMETER;\r
1989     goto exit;\r
1990   }\r
1991 \r
1992   if (EFI_USB_SPEED_LOW == DeviceSpeed) {\r
1993     Status = EFI_INVALID_PARAMETER;\r
1994     goto exit;\r
1995   }\r
1996 \r
1997   if (EFI_USB_SPEED_FULL == DeviceSpeed) {\r
1998     if (MaximumPacketLength > 64) {\r
1999       Status = EFI_INVALID_PARAMETER;\r
2000       goto exit;\r
2001     }\r
2002   }\r
2003 \r
2004   if (EFI_USB_SPEED_HIGH == DeviceSpeed) {\r
2005     if (MaximumPacketLength > 512) {\r
2006       Status = EFI_INVALID_PARAMETER;\r
2007       goto exit;\r
2008     }\r
2009   }\r
2010   \r
2011   //\r
2012   // if has errors that cause host controller halt,\r
2013   // then return EFI_DEVICE_ERROR directly.\r
2014   //\r
2015   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
2016     ClearEhcAllStatus (HcDev);\r
2017     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2018     Status          = EFI_DEVICE_ERROR;\r
2019     goto exit;\r
2020   }\r
2021 \r
2022   Status = ClearEhcAllStatus (HcDev);\r
2023   if (EFI_ERROR (Status)) {\r
2024     Status = EFI_DEVICE_ERROR;\r
2025     goto exit;\r
2026   }\r
2027   \r
2028   //\r
2029   // construct QH and TD data structures,\r
2030   // and link them together\r
2031   //\r
2032   if (EndPointAddress & 0x80) {\r
2033     TransferDirection = EfiUsbDataIn;\r
2034   } else {\r
2035     TransferDirection = EfiUsbDataOut;\r
2036   }\r
2037 \r
2038   Status = MapDataBuffer (\r
2039              HcDev,\r
2040              TransferDirection,\r
2041              Data[0],\r
2042              DataLength,\r
2043              &PktId,\r
2044              &DataCursor,\r
2045              &DataMap\r
2046              );\r
2047   if (EFI_ERROR (Status)) {\r
2048     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2049     Status          = EFI_DEVICE_ERROR;\r
2050     goto exit;\r
2051   }\r
2052   \r
2053   //\r
2054   // Create and init Bulk Qh\r
2055   //\r
2056   Status = CreateBulkQh (\r
2057              HcDev,\r
2058              DeviceAddress,\r
2059              EndPointAddress,\r
2060              DeviceSpeed,\r
2061              *DataToggle,\r
2062              MaximumPacketLength,\r
2063              Translator,\r
2064              &QhPtr\r
2065              );\r
2066   if (EFI_ERROR (Status)) {\r
2067     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2068     Status          = EFI_OUT_OF_RESOURCES;\r
2069     goto unmap_data;\r
2070   }\r
2071   \r
2072   //\r
2073   // Create and init Bulk Qtds\r
2074   //\r
2075   Status = CreateBulkOrInterruptQtds (\r
2076              HcDev,\r
2077              PktId,\r
2078              DataCursor,\r
2079              *DataLength,\r
2080              Translator,\r
2081              &BulkQtdsPtr\r
2082              );\r
2083   if (EFI_ERROR (Status)) {\r
2084     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2085     Status          = EFI_OUT_OF_RESOURCES;\r
2086     goto destory_qh;\r
2087   }\r
2088   \r
2089   //\r
2090   // Link Qtds to Qh\r
2091   //\r
2092   LinkQtdToQh (QhPtr, BulkQtdsPtr);\r
2093 \r
2094   ClearEhcAllStatus (HcDev);\r
2095 \r
2096   //\r
2097   // Link Qh and qtds to Async Schedule List\r
2098   //\r
2099   Status = LinkQhToAsyncList (HcDev, QhPtr);\r
2100   if (EFI_ERROR (Status)) {\r
2101     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2102     Status          = EFI_DEVICE_ERROR;\r
2103     goto destory_qtds;\r
2104   }\r
2105   \r
2106   //\r
2107   // Poll QH-TDs execution and get result.\r
2108   // detail status is returned\r
2109   //\r
2110   Status = ExecuteTransfer (\r
2111              HcDev,\r
2112              FALSE,\r
2113              QhPtr,\r
2114              DataLength,\r
2115              DataToggle,\r
2116              TimeOut,\r
2117              TransferResult\r
2118              );\r
2119   if (EFI_ERROR (Status)) {\r
2120     goto destory_qtds;\r
2121   }\r
2122   \r
2123   //\r
2124   // if has errors that cause host controller halt,\r
2125   // then return EFI_DEVICE_ERROR directly.\r
2126   //\r
2127   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
2128     *TransferResult |= EFI_USB_ERR_SYSTEM;\r
2129   }\r
2130 \r
2131   ClearEhcAllStatus (HcDev);\r
2132 \r
2133 destory_qtds:\r
2134   UnlinkQhFromAsyncList (HcDev, QhPtr);\r
2135   DestoryQtds (HcDev, BulkQtdsPtr);\r
2136 destory_qh:\r
2137   DestoryQh (HcDev, QhPtr);\r
2138 unmap_data:\r
2139   HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);\r
2140 exit:\r
2141   HcDev->PciIo->Flush (HcDev->PciIo);\r
2142   return Status;\r
2143 }\r
2144 \r
2145 EFI_STATUS\r
2146 EFIAPI\r
2147 EhciAsyncInterruptTransfer (\r
2148   IN  EFI_USB2_HC_PROTOCOL                  * This,\r
2149   IN  UINT8                                 DeviceAddress,\r
2150   IN  UINT8                                 EndPointAddress,\r
2151   IN  UINT8                                 DeviceSpeed,\r
2152   IN  UINTN                                 MaximumPacketLength,\r
2153   IN  BOOLEAN                               IsNewTransfer,\r
2154   IN  OUT UINT8                             *DataToggle,\r
2155   IN  UINTN                                 PollingInterval,\r
2156   IN  UINTN                                 DataLength,\r
2157   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    * Translator,\r
2158   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK       CallBackFunction,\r
2159   IN  VOID                                  *Context OPTIONAL\r
2160   )\r
2161 /*++\r
2162   \r
2163   Routine Description:\r
2164   \r
2165     Submits an asynchronous interrupt transfer to an \r
2166     interrupt endpoint of a USB device.\r
2167     Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated \r
2168     in the following specification version.\r
2169     \r
2170   Arguments:\r
2171     \r
2172     This            - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
2173     DeviceAddress   - Represents the address of the target device on the USB,\r
2174                       which is assigned during USB enumeration.                \r
2175     EndPointAddress - The combination of an endpoint number and an endpoint \r
2176                       direction of the target USB device. Each endpoint address \r
2177                       supports data transfer in one direction except the \r
2178                       control endpoint (whose default endpoint address is 0). \r
2179                       It is the caller's responsibility to make sure that \r
2180                       the EndPointAddress represents an interrupt endpoint.              \r
2181     DeviceSpeed     - Indicates device speed.\r
2182     MaximumPacketLength  - Indicates the maximum packet size the target endpoint\r
2183                            is capable of sending or receiving.                   \r
2184     IsNewTransfer   - If TRUE, an asynchronous interrupt pipe is built between\r
2185                       the host and the target interrupt endpoint. \r
2186                       If FALSE, the specified asynchronous interrupt pipe \r
2187                       is canceled.               \r
2188     DataToggle      - A pointer to the data toggle value.  On input, it is valid \r
2189                       when IsNewTransfer is TRUE, and it indicates the initial \r
2190                       data toggle value the asynchronous interrupt transfer \r
2191                       should adopt.  \r
2192                       On output, it is valid when IsNewTransfer is FALSE, \r
2193                       and it is updated to indicate the data toggle value of \r
2194                       the subsequent asynchronous interrupt transfer.              \r
2195     PollingInterval - Indicates the interval, in milliseconds, that the \r
2196                       asynchronous interrupt transfer is polled.  \r
2197                       This parameter is required when IsNewTransfer is TRUE.               \r
2198     DataLength      - Indicates the length of data to be received at the \r
2199                       rate specified by PollingInterval from the target \r
2200                       asynchronous interrupt endpoint.  This parameter \r
2201                       is only required when IsNewTransfer is TRUE.             \r
2202     Translator      - A pointr to the transaction translator data.\r
2203     CallBackFunction  - The Callback function.This function is called at the \r
2204                         rate specified by PollingInterval.This parameter is \r
2205                         only required when IsNewTransfer is TRUE.               \r
2206     Context         - The context that is passed to the CallBackFunction.\r
2207                     - This is an optional parameter and may be NULL.\r
2208   \r
2209   Returns:\r
2210   \r
2211     EFI_SUCCESS \r
2212         The asynchronous interrupt transfer request has been successfully \r
2213         submitted or canceled.\r
2214     EFI_INVALID_PARAMETER \r
2215         Some parameters are invalid.\r
2216     EFI_OUT_OF_RESOURCES  \r
2217         The request could not be completed due to a lack of resources.  \r
2218     EFI_DEVICE_ERROR\r
2219         Can't read register\r
2220         \r
2221 --*/\r
2222 {\r
2223   EFI_STATUS          Status;\r
2224   USB2_HC_DEV         *HcDev;\r
2225   UINT8               PktId;\r
2226   EHCI_QH_ENTITY      *QhPtr;\r
2227   EHCI_QTD_ENTITY     *InterruptQtdsPtr;\r
2228   UINT8               *DataPtr;\r
2229   UINT8               *DataCursor;\r
2230   VOID                *DataMap;\r
2231   UINTN               MappedLength;\r
2232   EHCI_ASYNC_REQUEST  *AsyncRequestPtr;\r
2233   EFI_TPL             OldTpl;\r
2234 \r
2235   QhPtr             = NULL;\r
2236   InterruptQtdsPtr  = NULL;\r
2237   DataPtr           = NULL;\r
2238   DataCursor        = NULL;\r
2239   DataMap           = NULL;\r
2240   AsyncRequestPtr   = NULL;\r
2241   HcDev             = USB2_HC_DEV_FROM_THIS (This);\r
2242 \r
2243   //\r
2244   // Parameters Checking\r
2245   //\r
2246   if (!IsDataInTransfer (EndPointAddress)) {\r
2247     Status = EFI_INVALID_PARAMETER;\r
2248     goto exit;\r
2249   }\r
2250 \r
2251   if (IsNewTransfer) {\r
2252     if (0 == DataLength) {\r
2253       Status = EFI_INVALID_PARAMETER;\r
2254       goto exit;\r
2255     }\r
2256 \r
2257     if (*DataToggle != 1 && *DataToggle != 0) {\r
2258       Status = EFI_INVALID_PARAMETER;\r
2259       goto exit;\r
2260     }\r
2261 \r
2262     if (PollingInterval > 255 || PollingInterval < 1) {\r
2263       Status = EFI_INVALID_PARAMETER;\r
2264       goto exit;\r
2265     }\r
2266   }\r
2267   \r
2268   //\r
2269   // if has errors that cause host controller halt,\r
2270   // then return EFI_DEVICE_ERROR directly.\r
2271   //\r
2272   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
2273     ClearEhcAllStatus (HcDev);\r
2274     Status = EFI_DEVICE_ERROR;\r
2275     goto exit;\r
2276   }\r
2277 \r
2278   Status = ClearEhcAllStatus (HcDev);\r
2279   if (EFI_ERROR (Status)) {\r
2280     Status = EFI_DEVICE_ERROR;\r
2281     goto exit;\r
2282   }\r
2283   \r
2284   //\r
2285   // Delete Async interrupt transfer request\r
2286   //\r
2287   if (!IsNewTransfer) {\r
2288 \r
2289     OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);\r
2290 \r
2291     Status = DeleteAsyncRequestTransfer (\r
2292                HcDev,\r
2293                DeviceAddress,\r
2294                EndPointAddress,\r
2295                DataToggle\r
2296                );\r
2297 \r
2298     gBS->RestoreTPL (OldTpl);\r
2299 \r
2300     goto exit;\r
2301   }\r
2302 \r
2303   Status = EhciAllocatePool (\r
2304                  HcDev, \r
2305                  (UINT8 **) &AsyncRequestPtr, \r
2306                  sizeof (EHCI_ASYNC_REQUEST)\r
2307                  );\r
2308   if (EFI_ERROR (Status)) {\r
2309     Status = EFI_OUT_OF_RESOURCES;\r
2310     goto exit;\r
2311   }\r
2312 \r
2313   Status = EhciAllocatePool (HcDev, &DataPtr, DataLength);\r
2314   if (EFI_ERROR (Status)) {\r
2315     Status = EFI_OUT_OF_RESOURCES;\r
2316     goto free_request;\r
2317   }\r
2318 \r
2319   MappedLength = DataLength;\r
2320   Status = MapDataBuffer (\r
2321              HcDev,\r
2322              EfiUsbDataIn,\r
2323              DataPtr,\r
2324              &MappedLength,\r
2325              &PktId,\r
2326              &DataCursor,\r
2327              &DataMap\r
2328              );\r
2329   if (EFI_ERROR (Status)) {\r
2330     Status = EFI_DEVICE_ERROR;\r
2331     goto free_data;\r
2332   }\r
2333   \r
2334   //\r
2335   // Create and init Interrupt Qh\r
2336   //\r
2337   Status = CreateInterruptQh (\r
2338              HcDev,\r
2339              DeviceAddress,\r
2340              EndPointAddress,\r
2341              DeviceSpeed,\r
2342              *DataToggle,\r
2343              MaximumPacketLength,\r
2344              PollingInterval,\r
2345              Translator,\r
2346              &QhPtr\r
2347              );\r
2348   if (EFI_ERROR (Status)) {\r
2349     Status = EFI_OUT_OF_RESOURCES;\r
2350     goto unmap_data;\r
2351   }\r
2352   \r
2353   //\r
2354   // Create and init Interrupt Qtds\r
2355   //\r
2356   Status = CreateBulkOrInterruptQtds (\r
2357              HcDev,\r
2358              PktId,\r
2359              DataCursor,\r
2360              MappedLength,\r
2361              Translator,\r
2362              &InterruptQtdsPtr\r
2363              );\r
2364   if (EFI_ERROR (Status)) {\r
2365     Status = EFI_OUT_OF_RESOURCES;\r
2366     goto destory_qh;\r
2367   }\r
2368   \r
2369   //\r
2370   // Link Qtds to Qh\r
2371   //\r
2372   LinkQtdToQh (QhPtr, InterruptQtdsPtr);\r
2373 \r
2374   //\r
2375   // Init AsyncRequest Entry\r
2376   //\r
2377   AsyncRequestPtr->Context      = Context;\r
2378   AsyncRequestPtr->CallBackFunc = CallBackFunction;\r
2379   AsyncRequestPtr->TransferType = ASYNC_INTERRUPT_TRANSFER;\r
2380   AsyncRequestPtr->QhPtr        = QhPtr;\r
2381   AsyncRequestPtr->Prev         = NULL;\r
2382   AsyncRequestPtr->Next         = NULL;\r
2383 \r
2384   if (NULL == HcDev->AsyncRequestList) {\r
2385     Status = StartPollingTimer (HcDev);\r
2386     if (EFI_ERROR (Status)) {\r
2387       Status = EFI_DEVICE_ERROR;\r
2388       CleanUpAllAsyncRequestTransfer (HcDev);\r
2389       goto exit;\r
2390     }\r
2391   }\r
2392   \r
2393   //\r
2394   // Link Entry to AsyncRequest List\r
2395   //\r
2396   LinkToAsyncReqeust (HcDev, AsyncRequestPtr);\r
2397 \r
2398   ClearEhcAllStatus (HcDev);\r
2399 \r
2400   Status = DisablePeriodicSchedule (HcDev);\r
2401   if (EFI_ERROR (Status)) {\r
2402     Status = EFI_DEVICE_ERROR;\r
2403     goto exit;\r
2404   }\r
2405 \r
2406   Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);\r
2407   if (EFI_ERROR (Status)) {\r
2408     Status = EFI_TIMEOUT;\r
2409     goto exit;\r
2410   }\r
2411   \r
2412   //\r
2413   // Link Qh and Qtds to Periodic Schedule List\r
2414   //\r
2415   LinkQhToPeriodicList (HcDev, QhPtr);\r
2416 \r
2417   Status = EnablePeriodicSchedule (HcDev);\r
2418   if (EFI_ERROR (Status)) {\r
2419     Status = EFI_DEVICE_ERROR;\r
2420     goto exit;\r
2421   }\r
2422 \r
2423   Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);\r
2424   if (EFI_ERROR (Status)) {\r
2425     Status = EFI_TIMEOUT;\r
2426     goto exit;\r
2427   }\r
2428 \r
2429   if (IsEhcHalted (HcDev)) {\r
2430     Status = StartScheduleExecution (HcDev);\r
2431     if (EFI_ERROR (Status)) {\r
2432       Status = EFI_DEVICE_ERROR;\r
2433       goto exit;\r
2434     }\r
2435   }\r
2436 \r
2437   HcDev->PciIo->Flush (HcDev->PciIo);\r
2438   goto exit;\r
2439 \r
2440 destory_qh:\r
2441   DestoryQh (HcDev, QhPtr);\r
2442 free_data:\r
2443   EhciFreePool (HcDev, DataPtr, DataLength);\r
2444 free_request:\r
2445   EhciFreePool (\r
2446         HcDev, \r
2447         (UINT8 *) AsyncRequestPtr, \r
2448         sizeof (EHCI_ASYNC_REQUEST)\r
2449         );\r
2450 unmap_data:\r
2451   HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);\r
2452 exit:\r
2453   return Status;\r
2454 }\r
2455 \r
2456 EFI_STATUS\r
2457 EFIAPI\r
2458 EhciSyncInterruptTransfer (\r
2459   IN  EFI_USB2_HC_PROTOCOL                  *This,\r
2460   IN  UINT8                                 DeviceAddress,\r
2461   IN  UINT8                                 EndPointAddress,\r
2462   IN  UINT8                                 DeviceSpeed,\r
2463   IN  UINTN                                 MaximumPacketLength,\r
2464   IN  OUT VOID                              *Data,\r
2465   IN  OUT UINTN                             *DataLength,\r
2466   IN  OUT UINT8                             *DataToggle,\r
2467   IN  UINTN                                 TimeOut,\r
2468   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,\r
2469   OUT UINT32                                *TransferResult\r
2470   )\r
2471 /*++\r
2472   \r
2473   Routine Description:\r
2474   \r
2475     Submits synchronous interrupt transfer to an interrupt endpoint \r
2476     of a USB device. \r
2477     Translator parameter doesn't exist in UEFI2.0 spec, but it will be updated \r
2478     in the following specification version.\r
2479   \r
2480   Arguments:\r
2481     \r
2482     This            - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
2483     DeviceAddress   - Represents the address of the target device on the USB, \r
2484                       which is assigned during USB enumeration.\r
2485     EndPointAddress - The combination of an endpoint number and an endpoint \r
2486                       direction of the target USB device. Each endpoint \r
2487                       address supports data transfer in one direction \r
2488                       except the control endpoint (whose default \r
2489                       endpoint address is 0). It is the caller's responsibility\r
2490                       to make sure that the EndPointAddress represents \r
2491                       an interrupt endpoint. \r
2492     DeviceSpeed     - Indicates device speed.\r
2493     MaximumPacketLength - Indicates the maximum packet size the target endpoint \r
2494                           is capable of sending or receiving.\r
2495     Data            - A pointer to the buffer of data that will be transmitted \r
2496                       to USB device or received from USB device.\r
2497     DataLength      - On input, the size, in bytes, of the data buffer specified \r
2498                       by Data. On output, the number of bytes transferred.\r
2499     DataToggle      - A pointer to the data toggle value. On input, it indicates\r
2500                       the initial data toggle value the synchronous interrupt \r
2501                       transfer should adopt; \r
2502                       on output, it is updated to indicate the data toggle value \r
2503                       of the subsequent synchronous interrupt transfer. \r
2504     TimeOut         - Indicates the maximum time, in microseconds, which the \r
2505                       transfer is allowed to complete.\r
2506     Translator      - A pointr to the transaction translator data.\r
2507     TransferResult  - A pointer to the detailed result information from \r
2508                       the synchronous interrupt transfer.  \r
2509 \r
2510   Returns:\r
2511   \r
2512     EFI_SUCCESS \r
2513         The synchronous interrupt transfer was completed successfully.\r
2514     EFI_OUT_OF_RESOURCES  \r
2515         The synchronous interrupt transfer could not be submitted due \r
2516         to lack of resource.\r
2517     EFI_INVALID_PARAMETER \r
2518         Some parameters are invalid.\r
2519     EFI_TIMEOUT \r
2520         The synchronous interrupt transfer failed due to timeout.\r
2521     EFI_DEVICE_ERROR  \r
2522         The synchronous interrupt transfer failed due to host controller \r
2523         or device error. Caller should check TranferResult for detailed \r
2524         error information.  \r
2525         \r
2526 --*/\r
2527 {\r
2528   EFI_STATUS      Status;\r
2529   USB2_HC_DEV     *HcDev;\r
2530   UINT8           PktId;\r
2531   EHCI_QH_ENTITY  *QhPtr;\r
2532   EHCI_QTD_ENTITY *InterruptQtdsPtr;\r
2533   UINT8           *DataCursor;\r
2534   VOID            *DataMap;\r
2535 \r
2536   QhPtr             = NULL;\r
2537   InterruptQtdsPtr  = NULL;\r
2538   DataCursor        = NULL;\r
2539   DataMap           = NULL;\r
2540   HcDev             = USB2_HC_DEV_FROM_THIS (This);\r
2541 \r
2542   //\r
2543   // Parameters Checking\r
2544   //\r
2545   if (DataLength == NULL ||\r
2546         Data == NULL || \r
2547         TransferResult == NULL\r
2548         ) {\r
2549     Status = EFI_INVALID_PARAMETER;\r
2550     goto exit;\r
2551   }\r
2552 \r
2553   if (!IsDataInTransfer (EndPointAddress)) {\r
2554     Status = EFI_INVALID_PARAMETER;\r
2555     goto exit;\r
2556   }\r
2557 \r
2558   if (0 == *DataLength) {\r
2559     Status = EFI_INVALID_PARAMETER;\r
2560     goto exit;\r
2561   }\r
2562 \r
2563   if (*DataToggle != 1 && *DataToggle != 0) {\r
2564     Status = EFI_INVALID_PARAMETER;\r
2565     goto exit;\r
2566   }\r
2567 \r
2568   if (EFI_USB_SPEED_LOW == DeviceSpeed && 8 != MaximumPacketLength) {\r
2569     Status = EFI_INVALID_PARAMETER;\r
2570     goto exit;\r
2571   }\r
2572 \r
2573   if (EFI_USB_SPEED_FULL == DeviceSpeed && MaximumPacketLength > 64) {\r
2574     Status = EFI_INVALID_PARAMETER;\r
2575     goto exit;\r
2576   }\r
2577 \r
2578   if (EFI_USB_SPEED_HIGH == DeviceSpeed && MaximumPacketLength > 3072) {\r
2579     Status = EFI_INVALID_PARAMETER;\r
2580     goto exit;\r
2581   }\r
2582   \r
2583   //\r
2584   // if has errors that cause host controller halt,\r
2585   // then return EFI_DEVICE_ERROR directly.\r
2586   //\r
2587   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
2588     ClearEhcAllStatus (HcDev);\r
2589     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2590     Status          = EFI_DEVICE_ERROR;\r
2591     goto exit;\r
2592   }\r
2593 \r
2594   Status = ClearEhcAllStatus (HcDev);\r
2595   if (EFI_ERROR (Status)) {\r
2596     Status = EFI_DEVICE_ERROR;\r
2597     goto exit;\r
2598   }\r
2599 \r
2600   Status = MapDataBuffer (\r
2601              HcDev,\r
2602              EfiUsbDataIn,\r
2603              Data,\r
2604              DataLength,\r
2605              &PktId,\r
2606              &DataCursor,\r
2607              &DataMap\r
2608              );\r
2609   if (EFI_ERROR (Status)) {\r
2610     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2611     Status          = EFI_DEVICE_ERROR;\r
2612     goto exit;\r
2613   }\r
2614   \r
2615   //\r
2616   // Create and init Interrupt Qh\r
2617   //\r
2618   Status = CreateInterruptQh (\r
2619              HcDev,\r
2620              DeviceAddress,\r
2621              EndPointAddress,\r
2622              DeviceSpeed,\r
2623              *DataToggle,\r
2624              MaximumPacketLength,\r
2625              0,\r
2626              Translator,\r
2627              &QhPtr\r
2628              );\r
2629   if (EFI_ERROR (Status)) {\r
2630     Status = EFI_OUT_OF_RESOURCES;\r
2631     goto unmap_data;\r
2632   }\r
2633   \r
2634   //\r
2635   // Create and init Interrupt Qtds\r
2636   //\r
2637   Status = CreateBulkOrInterruptQtds (\r
2638              HcDev,\r
2639              PktId,\r
2640              DataCursor,\r
2641              *DataLength,\r
2642              Translator,\r
2643              &InterruptQtdsPtr\r
2644              );\r
2645   if (EFI_ERROR (Status)) {\r
2646     *TransferResult = EFI_USB_ERR_SYSTEM;\r
2647     Status          = EFI_OUT_OF_RESOURCES;\r
2648     goto destory_qh;\r
2649   }\r
2650   \r
2651   //\r
2652   // Link Qtds to Qh\r
2653   //\r
2654   LinkQtdToQh (QhPtr, InterruptQtdsPtr);\r
2655 \r
2656   ClearEhcAllStatus (HcDev);\r
2657 \r
2658   Status = DisablePeriodicSchedule (HcDev);\r
2659   if (EFI_ERROR (Status)) {\r
2660     Status = EFI_DEVICE_ERROR;\r
2661     goto exit;\r
2662   }\r
2663 \r
2664   Status = WaitForPeriodicScheduleDisable (HcDev, EHCI_GENERIC_TIMEOUT);\r
2665   if (EFI_ERROR (Status)) {\r
2666     Status = EFI_TIMEOUT;\r
2667     goto exit;\r
2668   }\r
2669   \r
2670   //\r
2671   // Link Qh and Qtds to Periodic Schedule List\r
2672   //\r
2673   LinkQhToPeriodicList (HcDev, QhPtr);\r
2674 \r
2675   Status = EnablePeriodicSchedule (HcDev);\r
2676   if (EFI_ERROR (Status)) {\r
2677     Status = EFI_DEVICE_ERROR;\r
2678     goto exit;\r
2679   }\r
2680 \r
2681   Status = WaitForPeriodicScheduleEnable (HcDev, EHCI_GENERIC_TIMEOUT);\r
2682   if (EFI_ERROR (Status)) {\r
2683     Status = EFI_TIMEOUT;\r
2684     goto exit;\r
2685   }\r
2686 \r
2687   if (IsEhcHalted (HcDev)) {\r
2688     Status = StartScheduleExecution (HcDev);\r
2689     if (EFI_ERROR (Status)) {\r
2690       Status = EFI_DEVICE_ERROR;\r
2691       goto exit;\r
2692     }\r
2693   }\r
2694   \r
2695   //\r
2696   // Poll QH-TDs execution and get result.\r
2697   // detail status is returned\r
2698   //\r
2699   Status = ExecuteTransfer (\r
2700              HcDev,\r
2701              FALSE,\r
2702              QhPtr,\r
2703              DataLength,\r
2704              DataToggle,\r
2705              TimeOut,\r
2706              TransferResult\r
2707              );\r
2708   if (EFI_ERROR (Status)) {\r
2709     goto destory_qtds;\r
2710   }\r
2711   \r
2712   //\r
2713   // if has errors that cause host controller halt,\r
2714   // then return EFI_DEVICE_ERROR directly.\r
2715   //\r
2716   if (IsEhcHalted (HcDev) || IsEhcSysError (HcDev)) {\r
2717     *TransferResult |= EFI_USB_ERR_SYSTEM;\r
2718   }\r
2719 \r
2720   ClearEhcAllStatus (HcDev);\r
2721 \r
2722 destory_qtds:\r
2723   UnlinkQhFromPeriodicList (HcDev, QhPtr, 0);\r
2724   DestoryQtds (HcDev, InterruptQtdsPtr);\r
2725 destory_qh:\r
2726   DestoryQh (HcDev, QhPtr);\r
2727 unmap_data:\r
2728   HcDev->PciIo->Unmap (HcDev->PciIo, DataMap);\r
2729 exit:\r
2730   HcDev->PciIo->Flush (HcDev->PciIo);\r
2731   return Status;\r
2732 }\r
2733 \r
2734 EFI_STATUS\r
2735 EFIAPI\r
2736 EhciIsochronousTransfer (\r
2737   IN  EFI_USB2_HC_PROTOCOL                  *This,\r
2738   IN  UINT8                                 DeviceAddress,\r
2739   IN  UINT8                                 EndPointAddress,\r
2740   IN  UINT8                                 DeviceSpeed,\r
2741   IN  UINTN                                 MaximumPacketLength,\r
2742   IN  UINT8                                 DataBuffersNumber,\r
2743   IN  OUT VOID                              *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
2744   IN  UINTN                                 DataLength,\r
2745   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR    *Translator,\r
2746   OUT UINT32                                *TransferResult\r
2747   )\r
2748 /*++\r
2749   \r
2750   Routine Description:\r
2751   \r
2752     Submits isochronous transfer to a target USB device.\r
2753   \r
2754   Arguments:\r
2755     \r
2756     This             - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
2757     DeviceAddress    - Represents the address of the target device on the USB,\r
2758                        which is assigned during USB enumeration.\r
2759     EndPointAddress  - End point address\r
2760     DeviceSpeed      - Indicates device speed.\r
2761     MaximumPacketLength    - Indicates the maximum packet size that the \r
2762                              default control transfer endpoint is capable of \r
2763                              sending or receiving.\r
2764     DataBuffersNumber - Number of data buffers prepared for the transfer.\r
2765     Data              - Array of pointers to the buffers of data that will be \r
2766                         transmitted to USB device or received from USB device.\r
2767     DataLength        - Indicates the size, in bytes, of the data buffer \r
2768                         specified by Data.\r
2769     Translator        - A pointr to the transaction translator data.\r
2770     TransferResult    - A pointer to the detailed result information generated \r
2771                         by this control transfer.               \r
2772                       \r
2773   Returns:\r
2774   \r
2775     EFI_UNSUPPORTED \r
2776 \r
2777 --*/\r
2778 {\r
2779   return EFI_UNSUPPORTED;\r
2780 }\r
2781 \r
2782 EFI_STATUS\r
2783 EFIAPI\r
2784 EhciAsyncIsochronousTransfer (\r
2785   IN  EFI_USB2_HC_PROTOCOL                *This,\r
2786   IN  UINT8                               DeviceAddress,\r
2787   IN  UINT8                               EndPointAddress,\r
2788   IN  UINT8                               DeviceSpeed,\r
2789   IN  UINTN                               MaximumPacketLength,\r
2790   IN  UINT8                               DataBuffersNumber,\r
2791   IN  OUT VOID                            *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
2792   IN  UINTN                               DataLength,\r
2793   IN  EFI_USB2_HC_TRANSACTION_TRANSLATOR  *Translator,\r
2794   IN  EFI_ASYNC_USB_TRANSFER_CALLBACK     IsochronousCallBack,\r
2795   IN  VOID                                *Context\r
2796   )\r
2797 /*++\r
2798   \r
2799   Routine Description:\r
2800   \r
2801     Submits Async isochronous transfer to a target USB device.\r
2802   \r
2803   Arguments:\r
2804     \r
2805     This                - A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
2806     DeviceAddress       - Represents the address of the target device on the USB,\r
2807                           which is assigned during USB enumeration.\r
2808     EndPointAddress     - End point address\r
2809     DeviceSpeed         - Indicates device speed.\r
2810     MaximumPacketLength - Indicates the maximum packet size that the \r
2811                           default control transfer endpoint is capable of \r
2812                           sending or receiving.\r
2813     DataBuffersNumber   - Number of data buffers prepared for the transfer.\r
2814     Data                - Array of pointers to the buffers of data that will be transmitted \r
2815                           to USB device or received from USB device.\r
2816     Translator          - A pointr to the transaction translator data.\r
2817     IsochronousCallBack - When the transfer complete, the call back function will be called\r
2818     Context             - Pass to the call back function as parameter\r
2819                     \r
2820   Returns:\r
2821   \r
2822     EFI_UNSUPPORTED \r
2823 \r
2824 --*/\r
2825 {\r
2826   return EFI_UNSUPPORTED;\r
2827 }\r