1 /** @file
2 This file contains the implementation of Usb Hc Protocol.
3 
4 Copyright (c) 2013-2015 Intel Corporation.
5 
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 
17 #include "Ohci.h"
18 
19 /**
20   Provides software reset for the USB host controller.
21 
22   @param  This                  This EFI_USB_HC_PROTOCOL instance.
23   @param  Attributes            A bit mask of the reset operation to perform.
24 
25   @retval EFI_SUCCESS           The reset operation succeeded.
26   @retval EFI_INVALID_PARAMETER Attributes is not valid.
27   @retval EFI_UNSUPPOURTED      The type of reset specified by Attributes is
28                                 not currently supported by the host controller.
29   @retval EFI_DEVICE_ERROR      Host controller isn't halted to reset.
30 
31 **/
32 EFI_STATUS
33 EFIAPI
OhciReset(IN EFI_USB_HC_PROTOCOL * This,IN UINT16 Attributes)34 OhciReset (
35   IN EFI_USB_HC_PROTOCOL  *This,
36   IN UINT16               Attributes
37   )
38 {
39   EFI_STATUS              Status;
40   USB_OHCI_HC_DEV         *Ohc;
41   UINT8                   Index;
42   UINT8                   NumOfPorts;
43   UINT32                  PowerOnGoodTime;
44   UINT32                  Data32;
45   BOOLEAN                 Flag = FALSE;
46 
47   if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
48     return EFI_INVALID_PARAMETER;
49   }
50 
51   Status = EFI_SUCCESS;
52   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
53 
54   if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
55     gBS->Stall (50 * 1000);
56     Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);
57     if (EFI_ERROR (Status)) {
58       return EFI_DEVICE_ERROR;
59     }
60     gBS->Stall (50 * 1000);
61     //
62     // Wait for host controller reset.
63     //
64     PowerOnGoodTime = 50;
65     do {
66       gBS->Stall (1 * 1000);
67       Data32 = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS );
68       if (EFI_ERROR (Status)) {
69         return EFI_DEVICE_ERROR;
70       }
71       if ((Data32 & HC_RESET) == 0) {
72         Flag = TRUE;
73         break;
74       }
75     }while(PowerOnGoodTime--);
76     if (!Flag){
77       return EFI_DEVICE_ERROR;
78     }
79   }
80   OhciFreeIntTransferMemory (Ohc);
81   Status = OhciInitializeInterruptList (Ohc);
82   OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
83   if ((Attributes &  EFI_USB_HC_RESET_GLOBAL) != 0) {
84     Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
85     if (EFI_ERROR (Status)) {
86       return EFI_DEVICE_ERROR;
87     }
88     gBS->Stall (50 * 1000);
89   }
90   //
91   // Initialize host controller operational registers
92   //
93   OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);
94   OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
95   OhciSetPeriodicStart (Ohc, 0x2a2f);
96   OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x3);
97   OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);
98   OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);
99   OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);
100   //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
101   //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
102 
103   OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);
104   OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);
105   OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);
106   OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);
107   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
108   for (Index = 0; Index < NumOfPorts; Index++) {
109     if (!EFI_ERROR (OhciSetRootHubPortFeature (This, Index, EfiUsbPortReset))) {
110       gBS->Stall (200 * 1000);
111       OhciClearRootHubPortFeature (This, Index, EfiUsbPortReset);
112       gBS->Stall (1000);
113       OhciSetRootHubPortFeature (This, Index, EfiUsbPortEnable);
114       gBS->Stall (1000);
115     }
116   }
117   OhciSetMemoryPointer (Ohc, HC_HCCA, Ohc->HccaMemoryBlock);
118   OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
119   OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
120   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | BULK_ENABLE, 1); /*ISOCHRONOUS_ENABLE*/
121   OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
122   gBS->Stall (50*1000);
123   //
124   // Wait till first SOF occurs, and then clear it
125   //
126   while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
127   OhciClearInterruptStatus (Ohc, START_OF_FRAME);
128   gBS->Stall (1000);
129 
130   return Status;
131 }
132 
133 /**
134   Retrieve the current state of the USB host controller.
135 
136   @param  This                  This EFI_USB_HC_PROTOCOL instance.
137   @param  State                 Variable to return the current host controller
138                                 state.
139 
140   @retval EFI_SUCCESS           Host controller state was returned in State.
141   @retval EFI_INVALID_PARAMETER State is NULL.
142   @retval EFI_DEVICE_ERROR      An error was encountered while attempting to
143                                 retrieve the host controller's current state.
144 
145 **/
146 
147 EFI_STATUS
148 EFIAPI
OhciGetState(IN EFI_USB_HC_PROTOCOL * This,OUT EFI_USB_HC_STATE * State)149 OhciGetState (
150   IN  EFI_USB_HC_PROTOCOL  *This,
151   OUT EFI_USB_HC_STATE     *State
152   )
153 {
154   USB_OHCI_HC_DEV         *Ohc;
155   UINT32                  FuncState;
156 
157   if (State == NULL) {
158     return EFI_INVALID_PARAMETER;
159   }
160 
161   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
162 
163   FuncState = OhciGetHcControl (Ohc, HC_FUNCTIONAL_STATE);
164 
165   switch (FuncState) {
166     case HC_STATE_RESET:
167     case HC_STATE_RESUME:
168       *State = EfiUsbHcStateHalt;
169       break;
170 
171     case HC_STATE_OPERATIONAL:
172       *State = EfiUsbHcStateOperational;
173       break;
174 
175     case HC_STATE_SUSPEND:
176       *State = EfiUsbHcStateSuspend;
177       break;
178 
179     default:
180       ASSERT (FALSE);
181   }
182   return EFI_SUCCESS;
183 }
184 
185 /**
186   Sets the USB host controller to a specific state.
187 
188   @param  This                  This EFI_USB_HC_PROTOCOL instance.
189   @param  State                 The state of the host controller that will be set.
190 
191   @retval EFI_SUCCESS           The USB host controller was successfully placed
192                                 in the state specified by State.
193   @retval EFI_INVALID_PARAMETER State is invalid.
194   @retval EFI_DEVICE_ERROR      Failed to set the state due to device error.
195 
196 **/
197 
198 EFI_STATUS
199 EFIAPI
OhciSetState(IN EFI_USB_HC_PROTOCOL * This,IN EFI_USB_HC_STATE State)200 OhciSetState(
201   IN EFI_USB_HC_PROTOCOL  *This,
202   IN EFI_USB_HC_STATE     State
203   )
204 {
205   EFI_STATUS              Status;
206   USB_OHCI_HC_DEV         *Ohc;
207 
208   Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
209 
210   switch (State) {
211     case EfiUsbHcStateHalt:
212       Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
213       break;
214 
215     case EfiUsbHcStateOperational:
216       Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
217       break;
218 
219     case EfiUsbHcStateSuspend:
220       Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_SUSPEND);
221       break;
222 
223     default:
224       Status = EFI_INVALID_PARAMETER;
225   }
226 
227   gBS->Stall (1000);
228 
229   return Status;
230 }
231 
232 /**
233 
234   Submits control transfer to a target USB device.
235 
236   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
237   @param  DeviceAddress         Represents the address of the target device on the USB,
238                                 which is assigned during USB enumeration.
239   @param  IsSlowDevice          Indicates whether the target device is slow device
240                                 or full-speed device.
241   @param  MaxPaketLength        Indicates the maximum packet size that the
242                                 default control transfer endpoint is capable of
243                                 sending or receiving.
244   @param  Request               A pointer to the USB device request that will be sent
245                                 to the USB device.
246   @param  TransferDirection     Specifies the data direction for the transfer.
247                                 There are three values available, DataIn, DataOut
248                                 and NoData.
249   @param  Data                  A pointer to the buffer of data that will be transmitted
250                                 to USB device or received from USB device.
251   @param  DataLength            Indicates the size, in bytes, of the data buffer
252                                 specified by Data.
253   @param  TimeOut               Indicates the maximum time, in microseconds,
254                                 which the transfer is allowed to complete.
255   @param  TransferResult        A pointer to the detailed result information generated
256                                 by this control transfer.
257 
258   @retval EFI_SUCCESS           The control transfer was completed successfully.
259   @retval EFI_OUT_OF_RESOURCES  The control transfer could not be completed due to a lack of resources.
260   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
261   @retval EFI_TIMEOUT           The control transfer failed due to timeout.
262   @retval EFI_DEVICE_ERROR      The control transfer failed due to host controller or device error.
263                                 Caller should check TranferResult for detailed error information.
264 
265 --*/
266 
267 
268 EFI_STATUS
269 EFIAPI
OhciControlTransfer(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN BOOLEAN IsSlowDevice,IN UINT8 MaxPacketLength,IN EFI_USB_DEVICE_REQUEST * Request,IN EFI_USB_DATA_DIRECTION TransferDirection,IN OUT VOID * Data OPTIONAL,IN OUT UINTN * DataLength OPTIONAL,IN UINTN TimeOut,OUT UINT32 * TransferResult)270 OhciControlTransfer (
271   IN     EFI_USB_HC_PROTOCOL     *This,
272   IN     UINT8                   DeviceAddress,
273   IN     BOOLEAN                 IsSlowDevice,
274   IN     UINT8                   MaxPacketLength,
275   IN     EFI_USB_DEVICE_REQUEST  *Request,
276   IN     EFI_USB_DATA_DIRECTION  TransferDirection,
277   IN OUT VOID                    *Data                 OPTIONAL,
278   IN OUT UINTN                   *DataLength           OPTIONAL,
279   IN     UINTN                   TimeOut,
280   OUT    UINT32                  *TransferResult
281   )
282 {
283   USB_OHCI_HC_DEV                *Ohc;
284   ED_DESCRIPTOR                  *HeadEd;
285   ED_DESCRIPTOR                  *Ed;
286   TD_DESCRIPTOR                  *HeadTd;
287   TD_DESCRIPTOR                  *SetupTd;
288   TD_DESCRIPTOR                  *DataTd;
289   TD_DESCRIPTOR                  *StatusTd;
290   TD_DESCRIPTOR                  *EmptyTd;
291   EFI_STATUS                     Status;
292   UINT32                         DataPidDir;
293   UINT32                         StatusPidDir;
294   UINTN                          TimeCount;
295   OHCI_ED_RESULT                 EdResult;
296 
297   EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;
298 
299   UINTN                          ActualSendLength;
300   UINTN                          LeftLength;
301   UINT8                          DataToggle;
302 
303   VOID                           *ReqMapping = NULL;
304   UINTN                          ReqMapLength = 0;
305   EFI_PHYSICAL_ADDRESS           ReqMapPhyAddr = 0;
306 
307   VOID                           *DataMapping = NULL;
308   UINTN                          DataMapLength = 0;
309   EFI_PHYSICAL_ADDRESS           DataMapPhyAddr = 0;
310 
311   HeadTd = NULL;
312   DataTd = NULL;
313 
314   if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&
315        TransferDirection != EfiUsbNoData) ||
316       Request == NULL || DataLength == NULL || TransferResult == NULL ||
317       (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||
318       (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||
319       (IsSlowDevice && MaxPacketLength != 8) ||
320       (MaxPacketLength != 8 && MaxPacketLength != 16 &&
321        MaxPacketLength != 32 && MaxPacketLength != 64)) {
322     return EFI_INVALID_PARAMETER;
323   }
324 
325   if (*DataLength > MAX_BYTES_PER_TD) {
326     DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\r\n"));
327     return EFI_INVALID_PARAMETER;
328   }
329 
330   Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
331 
332   if (TransferDirection == EfiUsbDataIn) {
333     DataPidDir = TD_IN_PID;
334     StatusPidDir = TD_OUT_PID;
335   } else {
336     DataPidDir = TD_OUT_PID;
337     StatusPidDir = TD_IN_PID;
338   }
339 
340   Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
341   if (EFI_ERROR(Status)) {
342     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_ENABLE\r\n"));
343     *TransferResult = EFI_USB_ERR_SYSTEM;
344     return EFI_DEVICE_ERROR;
345   }
346   Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 0);
347   if (EFI_ERROR(Status)) {
348     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_LIST_FILLED\r\n"));
349     *TransferResult = EFI_USB_ERR_SYSTEM;
350     return EFI_DEVICE_ERROR;
351   }
352   gBS->Stall(20 * 1000);
353 
354   OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
355   Ed = OhciCreateED (Ohc);
356   if (Ed == NULL) {
357     Status = EFI_OUT_OF_RESOURCES;
358     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));
359     goto CTRL_EXIT;
360   }
361   OhciSetEDField (Ed, ED_SKIP, 1);
362   OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
363   OhciSetEDField (Ed, ED_ENDPT_NUM, 0);
364   OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
365   OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
366   OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
367   OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
368   OhciSetEDField (Ed, ED_PDATA, 0);
369   OhciSetEDField (Ed, ED_ZERO, 0);
370   OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
371   OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
372   OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
373   HeadEd = OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);
374   //
375   // Setup Stage
376   //
377   if(Request != NULL) {
378     ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);
379     MapOp = EfiPciIoOperationBusMasterRead;
380     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Request, &ReqMapLength, &ReqMapPhyAddr, &ReqMapping);
381     if (EFI_ERROR(Status)) {
382       DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to Map Request Buffer\r\n"));
383       goto FREE_ED_BUFF;
384     }
385   }
386   SetupTd = OhciCreateTD (Ohc);
387   if (SetupTd == NULL) {
388     Status = EFI_OUT_OF_RESOURCES;
389     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\r\n"));
390     goto UNMAP_SETUP_BUFF;
391   }
392   HeadTd = SetupTd;
393   OhciSetTDField (SetupTd, TD_PDATA, 0);
394   OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);
395   OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);
396   OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);
397   OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);
398   OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);
399   OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);
400   OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINT32)ReqMapPhyAddr);
401   OhciSetTDField (SetupTd, TD_NEXT_PTR, 0);
402   OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINT32)(ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1));
403   SetupTd->ActualSendLength = sizeof (EFI_USB_DEVICE_REQUEST);
404   SetupTd->DataBuffer = (UINT32)ReqMapPhyAddr;
405   SetupTd->NextTDPointer = 0;
406 
407   if (TransferDirection == EfiUsbDataIn) {
408     MapOp = EfiPciIoOperationBusMasterWrite;
409   } else {
410     MapOp = EfiPciIoOperationBusMasterRead;
411   }
412   DataMapLength = *DataLength;
413   if ((Data != NULL) && (DataMapLength != 0)) {
414     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, Data, &DataMapLength, &DataMapPhyAddr, &DataMapping);
415     if (EFI_ERROR(Status)) {
416       DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail To Map Data Buffer\r\n"));
417       goto FREE_TD_BUFF;
418     }
419   }
420   //
421   //Data Stage
422   //
423   LeftLength = DataMapLength;
424   ActualSendLength = DataMapLength;
425   DataToggle = 1;
426   while (LeftLength > 0) {
427     ActualSendLength = LeftLength;
428     if (LeftLength > MaxPacketLength) {
429       ActualSendLength = MaxPacketLength;
430     }
431     DataTd = OhciCreateTD (Ohc);
432     if (DataTd == NULL) {
433       DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
434       Status = EFI_OUT_OF_RESOURCES;
435       goto UNMAP_DATA_BUFF;
436     }
437     OhciSetTDField (DataTd, TD_PDATA, 0);
438     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
439     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
440     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
441     OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);
442     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
443     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
444     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);
445     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(DataMapPhyAddr + ActualSendLength - 1));
446     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
447     DataTd->ActualSendLength = (UINT32)ActualSendLength;
448     DataTd->DataBuffer = (UINT32)DataMapPhyAddr;
449     DataTd->NextTDPointer = 0;
450     OhciLinkTD (HeadTd, DataTd);
451     DataToggle ^= 1;
452     DataMapPhyAddr += ActualSendLength;
453     LeftLength -= ActualSendLength;
454   }
455   //
456   // Status Stage
457   //
458   StatusTd = OhciCreateTD (Ohc);
459   if (StatusTd == NULL) {
460     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Status Stage TD\r\n"));
461     Status = EFI_OUT_OF_RESOURCES;
462     goto UNMAP_DATA_BUFF;
463   }
464   OhciSetTDField (StatusTd, TD_PDATA, 0);
465   OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);
466   OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);
467   OhciSetTDField (StatusTd, TD_DELAY_INT, 7);
468   OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);
469   OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);
470   OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);
471   OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, 0);
472   OhciSetTDField (StatusTd, TD_NEXT_PTR, 0);
473   OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, 0);
474   StatusTd->ActualSendLength = 0;
475   StatusTd->DataBuffer = 0;
476   StatusTd->NextTDPointer = 0;
477   OhciLinkTD (HeadTd, StatusTd);
478   //
479   // Empty Stage
480   //
481   EmptyTd = OhciCreateTD (Ohc);
482   if (EmptyTd == NULL) {
483     Status = EFI_OUT_OF_RESOURCES;
484     goto UNMAP_DATA_BUFF;
485   }
486   OhciSetTDField (EmptyTd, TD_PDATA, 0);
487   OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
488   OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
489   OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
490   //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
491   EmptyTd->Word0.DataToggle = 0;
492   OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
493   OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
494   OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
495   OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
496   OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
497   EmptyTd->ActualSendLength = 0;
498   EmptyTd->DataBuffer = 0;
499   EmptyTd->NextTDPointer = 0;
500   OhciLinkTD (HeadTd, EmptyTd);
501   Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
502   OhciAttachTDListToED (Ed, HeadTd);
503   //
504   // For debugging,  dump ED & TD buffer befor transferring
505   //
506   //
507   //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);
508   //
509   OhciSetEDField (Ed, ED_SKIP, 0);
510   Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);
511   if (EFI_ERROR(Status)) {
512     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_ENABLE\r\n"));
513     *TransferResult = EFI_USB_ERR_SYSTEM;
514     Status = EFI_DEVICE_ERROR;
515     goto UNMAP_DATA_BUFF;
516   }
517   Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);
518   if (EFI_ERROR(Status)) {
519     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_LIST_FILLED\r\n"));
520     *TransferResult = EFI_USB_ERR_SYSTEM;
521     Status = EFI_DEVICE_ERROR;
522     goto UNMAP_DATA_BUFF;
523   }
524   gBS->Stall(20 * 1000);
525 
526 
527   TimeCount = 0;
528   Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
529 
530   while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
531     gBS->Stall (1000);
532     TimeCount++;
533     Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
534   }
535   //
536   // For debugging, dump ED & TD buffer after transferring
537   //
538   //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);
539   //
540   *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
541 
542   if (EdResult.ErrorCode != TD_NO_ERROR) {
543     if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
544       DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));
545     } else {
546       DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
547     }
548     *DataLength = 0;
549   } else {
550     DEBUG ((EFI_D_INFO, "Control transfer successed\r\n"));
551   }
552 
553 UNMAP_DATA_BUFF:
554   OhciSetEDField (Ed, ED_SKIP, 1);
555   if (HeadEd == Ed) {
556     OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
557   } else {
558     HeadEd->NextED = Ed->NextED;
559   }
560   if(DataMapping != NULL) {
561     Ohc->PciIo->Unmap(Ohc->PciIo, DataMapping);
562   }
563 
564 FREE_TD_BUFF:
565   while (HeadTd) {
566     DataTd = HeadTd;
567     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
568     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
569   }
570 
571 UNMAP_SETUP_BUFF:
572   if(ReqMapping != NULL) {
573     Ohc->PciIo->Unmap(Ohc->PciIo, ReqMapping);
574   }
575 
576 FREE_ED_BUFF:
577   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
578 
579 CTRL_EXIT:
580   return Status;
581 }
582 
583 /**
584 
585   Submits bulk transfer to a bulk endpoint of a USB device.
586 
587   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
588   @param  DeviceAddress         Represents the address of the target device on the USB,
589                                 which is assigned during USB enumeration.
590   @param  EndPointAddress       The combination of an endpoint number and an
591                                 endpoint direction of the target USB device.
592                                 Each endpoint address supports data transfer in
593                                 one direction except the control endpoint
594                                 (whose default endpoint address is 0).
595                                 It is the caller's responsibility to make sure that
596                                 the EndPointAddress represents a bulk endpoint.
597   @param  MaximumPacketLength   Indicates the maximum packet size the target endpoint
598                                 is capable of sending or receiving.
599   @param  Data                  A pointer to the buffer of data that will be transmitted
600                                 to USB device or received from USB device.
601   @param  DataLength            When input, indicates the size, in bytes, of the data buffer
602                                 specified by Data. When output, indicates the actually
603                                 transferred data size.
604   @param  DataToggle            A pointer to the data toggle value. On input, it indicates
605                                 the initial data toggle value the bulk transfer should adopt;
606                                 on output, it is updated to indicate the data toggle value
607                                 of the subsequent bulk transfer.
608   @param  TimeOut               Indicates the maximum time, in microseconds, which the
609                                 transfer is allowed to complete.
610   TransferResult                A pointer to the detailed result information of the
611                                 bulk transfer.
612 
613   @retval EFI_SUCCESS           The bulk transfer was completed successfully.
614   @retval EFI_OUT_OF_RESOURCES  The bulk transfer could not be submitted due to lack of resource.
615   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
616   @retval EFI_TIMEOUT           The bulk transfer failed due to timeout.
617   @retval EFI_DEVICE_ERROR      The bulk transfer failed due to host controller or device error.
618                                 Caller should check TranferResult for detailed error information.
619 
620 **/
621 
622 
623 EFI_STATUS
624 EFIAPI
OhciBulkTransfer(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 MaxPacketLength,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,OUT UINT32 * TransferResult)625 OhciBulkTransfer(
626   IN     EFI_USB_HC_PROTOCOL  *This,
627   IN     UINT8                DeviceAddress,
628   IN     UINT8                EndPointAddress,
629   IN     UINT8                MaxPacketLength,
630   IN OUT VOID                 *Data,
631   IN OUT UINTN                *DataLength,
632   IN OUT UINT8                *DataToggle,
633   IN     UINTN                TimeOut,
634   OUT    UINT32               *TransferResult
635   )
636 {
637   USB_OHCI_HC_DEV                *Ohc;
638   ED_DESCRIPTOR                  *HeadEd;
639   ED_DESCRIPTOR                  *Ed;
640   UINT8                          EdDir;
641   UINT32                         DataPidDir;
642   TD_DESCRIPTOR                  *HeadTd;
643   TD_DESCRIPTOR                  *DataTd;
644   TD_DESCRIPTOR                  *EmptyTd;
645   EFI_STATUS                     Status;
646   EFI_USB_DATA_DIRECTION         TransferDirection;
647   UINT8                          EndPointNum;
648   UINTN                          TimeCount;
649   OHCI_ED_RESULT                 EdResult;
650 
651   EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;
652   VOID                           *Mapping;
653   UINTN                          MapLength;
654   EFI_PHYSICAL_ADDRESS           MapPyhAddr;
655   UINTN                          LeftLength;
656   UINTN                          ActualSendLength;
657   BOOLEAN                        FirstTD;
658 
659   Mapping = NULL;
660   MapLength = 0;
661   MapPyhAddr = 0;
662   LeftLength = 0;
663   Status = EFI_SUCCESS;
664 
665   if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
666       *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
667       (MaxPacketLength != 8 && MaxPacketLength != 16 &&
668        MaxPacketLength != 32 && MaxPacketLength != 64)) {
669     return EFI_INVALID_PARAMETER;
670   }
671 
672   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
673 
674   if ((EndPointAddress & 0x80) != 0) {
675     TransferDirection = EfiUsbDataIn;
676     EdDir = ED_IN_DIR;
677     DataPidDir = TD_IN_PID;
678     MapOp = EfiPciIoOperationBusMasterWrite;
679   } else {
680     TransferDirection = EfiUsbDataOut;
681     EdDir = ED_OUT_DIR;
682     DataPidDir = TD_OUT_PID;
683     MapOp = EfiPciIoOperationBusMasterRead;
684   }
685 
686   EndPointNum = (EndPointAddress & 0xF);
687   EdResult.NextToggle = *DataToggle;
688 
689   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);
690   if (EFI_ERROR(Status)) {
691     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
692     *TransferResult = EFI_USB_ERR_SYSTEM;
693     return EFI_DEVICE_ERROR;
694   }
695   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);
696   if (EFI_ERROR(Status)) {
697     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
698     *TransferResult = EFI_USB_ERR_SYSTEM;
699     return EFI_DEVICE_ERROR;
700   }
701   gBS->Stall(20 * 1000);
702 
703   OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
704 
705   Ed = OhciCreateED (Ohc);
706   if (Ed == NULL) {
707     return EFI_OUT_OF_RESOURCES;
708   }
709   OhciSetEDField (Ed, ED_SKIP, 1);
710   OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
711   OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
712   OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
713   OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
714   OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
715   OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
716   OhciSetEDField (Ed, ED_PDATA, 0);
717   OhciSetEDField (Ed, ED_ZERO, 0);
718   OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
719   OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
720   OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
721   HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
722 
723   if(Data != NULL) {
724     MapLength = *DataLength;
725     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);
726     if (EFI_ERROR(Status)) {
727       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
728       goto FREE_ED_BUFF;
729     }
730   }
731   //
732   //Data Stage
733   //
734   LeftLength = MapLength;
735   ActualSendLength = MapLength;
736   HeadTd = NULL;
737   FirstTD = TRUE;
738   while (LeftLength > 0) {
739     ActualSendLength = LeftLength;
740     if (LeftLength > MaxPacketLength) {
741       ActualSendLength = MaxPacketLength;
742     }
743     DataTd = OhciCreateTD (Ohc);
744     if (DataTd == NULL) {
745       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
746       Status = EFI_OUT_OF_RESOURCES;
747       goto FREE_OHCI_TDBUFF;
748     }
749     OhciSetTDField (DataTd, TD_PDATA, 0);
750     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
751     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
752     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
753     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
754     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
755     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
756     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
757     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
758     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
759     DataTd->ActualSendLength = (UINT32)ActualSendLength;
760     DataTd->DataBuffer = (UINT32)MapPyhAddr;
761     DataTd->NextTDPointer = 0;
762     if (FirstTD) {
763       HeadTd = DataTd;
764       FirstTD = FALSE;
765     } else {
766       OhciLinkTD (HeadTd, DataTd);
767     }
768     *DataToggle ^= 1;
769     MapPyhAddr += ActualSendLength;
770     LeftLength -= ActualSendLength;
771   }
772   //
773   // Empty Stage
774   //
775   EmptyTd = OhciCreateTD (Ohc);
776   if (EmptyTd == NULL) {
777     Status = EFI_OUT_OF_RESOURCES;
778     DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
779     goto FREE_OHCI_TDBUFF;
780   }
781   OhciSetTDField (EmptyTd, TD_PDATA, 0);
782   OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
783   OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
784   OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
785   //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
786   EmptyTd->Word0.DataToggle = 0;
787   OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
788   OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
789   OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
790   OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
791   OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
792   EmptyTd->ActualSendLength = 0;
793   EmptyTd->DataBuffer = 0;
794   EmptyTd->NextTDPointer = 0;
795   OhciLinkTD (HeadTd, EmptyTd);
796   Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
797   OhciAttachTDListToED (Ed, HeadTd);
798 
799   OhciSetEDField (Ed, ED_SKIP, 0);
800   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
801   if (EFI_ERROR(Status)) {
802     *TransferResult = EFI_USB_ERR_SYSTEM;
803     Status = EFI_DEVICE_ERROR;
804     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
805     goto FREE_OHCI_TDBUFF;
806   }
807   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);
808   if (EFI_ERROR(Status)) {
809     *TransferResult = EFI_USB_ERR_SYSTEM;
810     Status = EFI_DEVICE_ERROR;
811     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
812     goto FREE_OHCI_TDBUFF;
813   }
814   gBS->Stall(20 * 1000);
815 
816   TimeCount = 0;
817   Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
818   while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
819     gBS->Stall (1000);
820     TimeCount++;
821     Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
822   }
823 
824   *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
825 
826   if (EdResult.ErrorCode != TD_NO_ERROR) {
827     if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
828       DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
829     } else {
830       DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
831       *DataToggle = EdResult.NextToggle;
832     }
833     *DataLength = 0;
834   } else {
835     DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));
836   }
837   //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
838 
839 FREE_OHCI_TDBUFF:
840   OhciSetEDField (Ed, ED_SKIP, 1);
841   if (HeadEd == Ed) {
842     OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
843   }else {
844     HeadEd->NextED = Ed->NextED;
845   }
846   while (HeadTd) {
847     DataTd = HeadTd;
848     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
849     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
850   }
851 
852   if(Mapping != NULL) {
853     Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
854   }
855 
856 FREE_ED_BUFF:
857   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
858 
859   return Status;
860 }
861 /**
862 
863   Submits an interrupt transfer to an interrupt endpoint of a USB device.
864 
865   @param  Ohc                   Device private data
866   @param  DeviceAddress         Represents the address of the target device on the USB,
867                                 which is assigned during USB enumeration.
868   @param  EndPointAddress       The combination of an endpoint number and an endpoint
869                                 direction of the target USB device. Each endpoint address
870                                 supports data transfer in one direction except the
871                                 control endpoint (whose default endpoint address is 0).
872                                 It is the caller's responsibility to make sure that
873                                 the EndPointAddress represents an interrupt endpoint.
874   @param  IsSlowDevice          Indicates whether the target device is slow device
875                                 or full-speed device.
876   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
877                                 is capable of sending or receiving.
878   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
879                                 the host and the target interrupt endpoint.
880                                 If FALSE, the specified asynchronous interrupt pipe
881                                 is canceled.
882   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
883                                 when IsNewTransfer is TRUE, and it indicates the initial
884                                 data toggle value the asynchronous interrupt transfer
885                                 should adopt.
886                                 On output, it is valid when IsNewTransfer is FALSE,
887                                 and it is updated to indicate the data toggle value of
888                                 the subsequent asynchronous interrupt transfer.
889   @param  PollingInterval       Indicates the interval, in milliseconds, that the
890                                 asynchronous interrupt transfer is polled.
891                                 This parameter is required when IsNewTransfer is TRUE.
892   @param  UCBuffer              Uncacheable buffer
893   @param  DataLength            Indicates the length of data to be received at the
894                                 rate specified by PollingInterval from the target
895                                 asynchronous interrupt endpoint.  This parameter
896                                 is only required when IsNewTransfer is TRUE.
897   @param  CallBackFunction      The Callback function.This function is called at the
898                                 rate specified by PollingInterval.This parameter is
899                                 only required when IsNewTransfer is TRUE.
900   @param  Context               The context that is passed to the CallBackFunction.
901                                 This is an optional parameter and may be NULL.
902   @param  IsPeriodic            Periodic interrupt or not
903   @param  OutputED              The correspoding ED carried out
904   @param  OutputTD              The correspoding TD carried out
905 
906 
907   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
908                                 submitted or canceled.
909   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
910   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
911 
912 **/
913 
914 EFI_STATUS
OhciInterruptTransfer(IN USB_OHCI_HC_DEV * Ohc,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN BOOLEAN IsSlowDevice,IN UINT8 MaxPacketLength,IN BOOLEAN IsNewTransfer,IN OUT UINT8 * DataToggle OPTIONAL,IN UINTN PollingInterval OPTIONAL,IN VOID * UCBuffer OPTIONAL,IN UINTN DataLength OPTIONAL,IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,IN VOID * Context OPTIONAL,IN BOOLEAN IsPeriodic OPTIONAL,OUT ED_DESCRIPTOR ** OutputED OPTIONAL,OUT TD_DESCRIPTOR ** OutputTD OPTIONAL)915 OhciInterruptTransfer (
916   IN     USB_OHCI_HC_DEV                  *Ohc,
917   IN     UINT8                            DeviceAddress,
918   IN     UINT8                            EndPointAddress,
919   IN     BOOLEAN                          IsSlowDevice,
920   IN     UINT8                            MaxPacketLength,
921   IN     BOOLEAN                          IsNewTransfer,
922   IN OUT UINT8                            *DataToggle        OPTIONAL,
923   IN     UINTN                            PollingInterval    OPTIONAL,
924   IN     VOID                             *UCBuffer          OPTIONAL,
925   IN     UINTN                            DataLength         OPTIONAL,
926   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
927   IN     VOID                             *Context           OPTIONAL,
928   IN     BOOLEAN                          IsPeriodic         OPTIONAL,
929   OUT    ED_DESCRIPTOR                    **OutputED         OPTIONAL,
930   OUT    TD_DESCRIPTOR                    **OutputTD         OPTIONAL
931   )
932 {
933   ED_DESCRIPTOR            *Ed;
934   UINT8                    EdDir;
935   ED_DESCRIPTOR            *HeadEd;
936   TD_DESCRIPTOR            *HeadTd;
937   TD_DESCRIPTOR            *DataTd;
938   TD_DESCRIPTOR            *EmptTd;
939   UINTN                    Depth;
940   UINTN                    Index;
941   EFI_STATUS               Status;
942   UINT8                    EndPointNum;
943   UINT32                   DataPidDir;
944   EFI_USB_DATA_DIRECTION   TransferDirection;
945   INTERRUPT_CONTEXT_ENTRY  *Entry;
946   EFI_TPL                  OldTpl;
947   BOOLEAN                  FirstTD;
948 
949  VOID                      *Mapping;
950  UINTN                     MapLength;
951  EFI_PHYSICAL_ADDRESS      MapPyhAddr;
952  UINTN                     LeftLength;
953  UINTN                     ActualSendLength;
954 
955 
956   if (DataLength > MAX_BYTES_PER_TD) {
957     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));
958     return EFI_INVALID_PARAMETER;
959   }
960 
961   if ((EndPointAddress & 0x80) != 0) {
962     TransferDirection = EfiUsbDataIn;
963     EdDir = ED_IN_DIR;
964     DataPidDir = TD_IN_PID;
965   } else {
966     TransferDirection = EfiUsbDataOut;
967     EdDir = ED_OUT_DIR;
968     DataPidDir = TD_OUT_PID;
969   }
970 
971   EndPointNum = (EndPointAddress & 0xF);
972 
973   if (!IsNewTransfer) {
974     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
975     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);
976     OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);
977     Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);
978     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
979     gBS->RestoreTPL (OldTpl);
980     return Status;
981   }
982   MapLength = DataLength;
983   Status = Ohc->PciIo->Map(
984                          Ohc->PciIo,
985                          EfiPciIoOperationBusMasterWrite,
986                          UCBuffer,
987                          &MapLength,
988                          &MapPyhAddr,
989                          &Mapping
990                          );
991   if (EFI_ERROR (Status)) {
992     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
993     goto EXIT;
994   }
995   Depth = 5;
996   Index = 1;
997   while (PollingInterval >= Index * 2 && Depth > 0) {
998     Index *= 2;
999     Depth--;
1000   }
1001   //
1002   //ED Stage
1003   //
1004   HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);
1005   if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {
1006     OhciSetEDField (Ed, ED_SKIP, 1);
1007   } else {
1008     Ed = OhciCreateED (Ohc);
1009     if (Ed == NULL) {
1010       Status = EFI_OUT_OF_RESOURCES;
1011       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
1012       goto UNMAP_OHCI_XBUFF;
1013     }
1014     OhciSetEDField (Ed, ED_SKIP, 1);
1015     OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
1016     OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
1017     OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
1018     OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
1019     OhciSetEDField (Ed, ED_FORMAT, 0);
1020     OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
1021     OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);
1022     OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
1023     OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
1024     OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
1025     OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);
1026   }
1027   //
1028   //Data Stage
1029   //
1030   LeftLength = MapLength;
1031   ActualSendLength = MapLength;
1032   HeadTd = NULL;
1033   FirstTD = TRUE;
1034   while (LeftLength > 0) {
1035     ActualSendLength = LeftLength;
1036     if (LeftLength > MaxPacketLength) {
1037       ActualSendLength = MaxPacketLength;
1038     }
1039     DataTd = OhciCreateTD (Ohc);
1040     if (DataTd == NULL) {
1041       Status = EFI_OUT_OF_RESOURCES;
1042       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
1043       goto FREE_OHCI_TDBUFF;
1044     }
1045     OhciSetTDField (DataTd, TD_PDATA, 0);
1046     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
1047     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
1048     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
1049     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
1050     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
1051     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
1052     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
1053     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
1054     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
1055     DataTd->ActualSendLength = (UINT32)ActualSendLength;
1056     DataTd->DataBuffer = (UINT32)MapPyhAddr;
1057     DataTd->NextTDPointer = 0;
1058     if (FirstTD) {
1059       HeadTd = DataTd;
1060       FirstTD = FALSE;
1061     } else {
1062       OhciLinkTD (HeadTd, DataTd);
1063     }
1064     *DataToggle ^= 1;
1065     MapPyhAddr += ActualSendLength;
1066     LeftLength -= ActualSendLength;
1067   }
1068 
1069   EmptTd = OhciCreateTD (Ohc);
1070   if (EmptTd == NULL) {
1071     Status = EFI_OUT_OF_RESOURCES;
1072     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
1073     goto FREE_OHCI_TDBUFF;
1074   }
1075   OhciSetTDField (EmptTd, TD_PDATA, 0);
1076   OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);
1077   OhciSetTDField (EmptTd, TD_DIR_PID, 0);
1078   OhciSetTDField (EmptTd, TD_DELAY_INT, 0);
1079   //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
1080   EmptTd->Word0.DataToggle = 0;
1081   OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);
1082   OhciSetTDField (EmptTd, TD_COND_CODE, 0);
1083   OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);
1084   OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);
1085   OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);
1086   EmptTd->ActualSendLength = 0;
1087   EmptTd->DataBuffer = 0;
1088   EmptTd->NextTDPointer = 0;
1089   OhciLinkTD (HeadTd, EmptTd);
1090   Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;
1091   OhciAttachTDListToED (Ed, HeadTd);
1092 
1093   if (OutputED != NULL) {
1094     *OutputED = Ed;
1095   }
1096   if (OutputTD != NULL) {
1097     *OutputTD = HeadTd;
1098   }
1099 
1100   if (CallBackFunction != NULL) {
1101     Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));
1102     if (Entry == NULL) {
1103       goto FREE_OHCI_TDBUFF;
1104     }
1105 
1106     Entry->DeviceAddress = DeviceAddress;
1107     Entry->EndPointAddress = EndPointAddress;
1108     Entry->Ed = Ed;
1109     Entry->DataTd = HeadTd;
1110     Entry->IsSlowDevice = IsSlowDevice;
1111     Entry->MaxPacketLength = MaxPacketLength;
1112     Entry->PollingInterval = PollingInterval;
1113     Entry->CallBackFunction = CallBackFunction;
1114     Entry->Context = Context;
1115     Entry->IsPeriodic = IsPeriodic;
1116     Entry->UCBuffer = UCBuffer;
1117     Entry->UCBufferMapping = Mapping;
1118     Entry->DataLength = DataLength;
1119     Entry->Toggle = DataToggle;
1120     Entry->NextEntry = NULL;
1121     OhciAddInterruptContextEntry (Ohc, Entry);
1122   }
1123   OhciSetEDField (Ed, ED_SKIP, 0);
1124 
1125   if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {
1126     Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
1127     gBS->Stall (1000);
1128   }
1129 
1130   return EFI_SUCCESS;
1131 
1132 FREE_OHCI_TDBUFF:
1133   while (HeadTd) {
1134     DataTd = HeadTd;
1135     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
1136     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
1137   }
1138 
1139 //FREE_OHCI_EDBUFF:
1140   if ((HeadEd != Ed) && HeadEd && Ed) {
1141     while(HeadEd->NextED != (UINT32)(UINTN)Ed) {
1142       HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);
1143     }
1144   HeadEd->NextED = Ed->NextED;
1145     UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
1146   }
1147 
1148 UNMAP_OHCI_XBUFF:
1149   Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
1150 
1151 EXIT:
1152   return Status;
1153 }
1154 
1155 /**
1156 
1157   Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
1158 
1159   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1160   @param  DeviceAddress         Represents the address of the target device on the USB,
1161                                 which is assigned during USB enumeration.
1162   @param  EndPointAddress       The combination of an endpoint number and an endpoint
1163                                 direction of the target USB device. Each endpoint address
1164                                 supports data transfer in one direction except the
1165                                 control endpoint (whose default endpoint address is 0).
1166                                 It is the caller's responsibility to make sure that
1167                                 the EndPointAddress represents an interrupt endpoint.
1168   @param  IsSlowDevice          Indicates whether the target device is slow device
1169                                 or full-speed device.
1170   @param  MaxiumPacketLength    Indicates the maximum packet size the target endpoint
1171                                 is capable of sending or receiving.
1172   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
1173                                 the host and the target interrupt endpoint.
1174                                 If FALSE, the specified asynchronous interrupt pipe
1175                                 is canceled.
1176   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
1177                                 when IsNewTransfer is TRUE, and it indicates the initial
1178                                 data toggle value the asynchronous interrupt transfer
1179                                 should adopt.
1180                                 On output, it is valid when IsNewTransfer is FALSE,
1181                                 and it is updated to indicate the data toggle value of
1182                                 the subsequent asynchronous interrupt transfer.
1183   @param  PollingInterval       Indicates the interval, in milliseconds, that the
1184                                 asynchronous interrupt transfer is polled.
1185                                 This parameter is required when IsNewTransfer is TRUE.
1186   @param  DataLength            Indicates the length of data to be received at the
1187                                 rate specified by PollingInterval from the target
1188                                 asynchronous interrupt endpoint.  This parameter
1189                                 is only required when IsNewTransfer is TRUE.
1190   @param  CallBackFunction      The Callback function.This function is called at the
1191                                 rate specified by PollingInterval.This parameter is
1192                                 only required when IsNewTransfer is TRUE.
1193   @param  Context               The context that is passed to the CallBackFunction.
1194                                 This is an optional parameter and may be NULL.
1195 
1196   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
1197                                 submitted or canceled.
1198   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1199   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
1200 
1201 **/
1202 
1203 
1204 EFI_STATUS
1205 EFIAPI
OhciAsyncInterruptTransfer(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN BOOLEAN IsSlowDevice,IN UINT8 MaxPacketLength,IN BOOLEAN IsNewTransfer,IN OUT UINT8 * DataToggle OPTIONAL,IN UINTN PollingInterval OPTIONAL,IN UINTN DataLength OPTIONAL,IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,IN VOID * Context OPTIONAL)1206 OhciAsyncInterruptTransfer (
1207   IN     EFI_USB_HC_PROTOCOL              *This,
1208   IN     UINT8                            DeviceAddress,
1209   IN     UINT8                            EndPointAddress,
1210   IN     BOOLEAN                          IsSlowDevice,
1211   IN     UINT8                            MaxPacketLength,
1212   IN     BOOLEAN                          IsNewTransfer,
1213   IN OUT UINT8                            *DataToggle        OPTIONAL,
1214   IN     UINTN                            PollingInterval    OPTIONAL,
1215   IN     UINTN                            DataLength         OPTIONAL,
1216   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
1217   IN     VOID                             *Context           OPTIONAL
1218   )
1219 {
1220   EFI_STATUS              Status;
1221   USB_OHCI_HC_DEV         *Ohc;
1222   VOID                    *UCBuffer;
1223 
1224   if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||
1225     (IsNewTransfer && (DataLength == 0 ||
1226     (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {
1227     return EFI_INVALID_PARAMETER;
1228   }
1229 
1230   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1231   if ( IsNewTransfer ) {
1232     UCBuffer = AllocatePool(DataLength);
1233     if (UCBuffer == NULL) {
1234       return EFI_OUT_OF_RESOURCES;
1235     }
1236   } else {
1237     UCBuffer = NULL;
1238   }
1239   Status = OhciInterruptTransfer (
1240              Ohc,
1241              DeviceAddress,
1242              EndPointAddress,
1243              IsSlowDevice,
1244              MaxPacketLength,
1245              IsNewTransfer,
1246              DataToggle,
1247              PollingInterval,
1248              UCBuffer,
1249              DataLength,
1250              CallBackFunction,
1251              Context,
1252              TRUE,
1253              NULL,
1254              NULL
1255              );
1256   if ( IsNewTransfer ) {
1257     if (EFI_ERROR(Status)) {
1258       gBS->FreePool (UCBuffer);
1259     }
1260   }
1261   return Status;
1262 }
1263 
1264 
1265 /**
1266 
1267   Submits synchronous interrupt transfer to an interrupt endpoint
1268   of a USB device.
1269 
1270   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1271   @param  DeviceAddress         Represents the address of the target device on the USB,
1272                                 which is assigned during USB enumeration.
1273   @param  EndPointAddress       The combination of an endpoint number and an endpoint
1274                                 direction of the target USB device. Each endpoint
1275                                 address supports data transfer in one direction
1276                                 except the control endpoint (whose default
1277                                 endpoint address is 0). It is the caller's responsibility
1278                                 to make sure that the EndPointAddress represents
1279                                 an interrupt endpoint.
1280   @param  IsSlowDevice          Indicates whether the target device is slow device
1281                                 or full-speed device.
1282   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
1283                                 is capable of sending or receiving.
1284   @param  Data                  A pointer to the buffer of data that will be transmitted
1285                                 to USB device or received from USB device.
1286   @param  DataLength            On input, the size, in bytes, of the data buffer specified
1287                                 by Data. On output, the number of bytes transferred.
1288   @param  DataToggle            A pointer to the data toggle value. On input, it indicates
1289                                 the initial data toggle value the synchronous interrupt
1290                                 transfer should adopt;
1291                                 on output, it is updated to indicate the data toggle value
1292                                 of the subsequent synchronous interrupt transfer.
1293   @param  TimeOut               Indicates the maximum time, in microseconds, which the
1294                                 transfer is allowed to complete.
1295   @param  TransferResult        A pointer to the detailed result information from
1296                                 the synchronous interrupt transfer.
1297 
1298   @retval EFI_UNSUPPORTED       This interface not available.
1299   @retval EFI_INVALID_PARAMETER Parameters not follow spec
1300 
1301 **/
1302 
1303 
1304 EFI_STATUS
1305 EFIAPI
OhciSyncInterruptTransfer(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN BOOLEAN IsSlowDevice,IN UINT8 MaxPacketLength,IN OUT VOID * Data,IN OUT UINTN * DataLength,IN OUT UINT8 * DataToggle,IN UINTN TimeOut,OUT UINT32 * TransferResult)1306 OhciSyncInterruptTransfer (
1307   IN     EFI_USB_HC_PROTOCOL  *This,
1308   IN     UINT8                DeviceAddress,
1309   IN     UINT8                EndPointAddress,
1310   IN     BOOLEAN              IsSlowDevice,
1311   IN     UINT8                MaxPacketLength,
1312   IN OUT VOID                 *Data,
1313   IN OUT UINTN                *DataLength,
1314   IN OUT UINT8                *DataToggle,
1315   IN     UINTN                TimeOut,
1316   OUT    UINT32               *TransferResult
1317   )
1318 {
1319   USB_OHCI_HC_DEV         *Ohc;
1320   EFI_STATUS              Status;
1321   ED_DESCRIPTOR           *Ed;
1322   TD_DESCRIPTOR           *HeadTd;
1323   OHCI_ED_RESULT          EdResult;
1324   VOID                    *UCBuffer;
1325 
1326   if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||
1327       (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||
1328       DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {
1329     return EFI_INVALID_PARAMETER;
1330   }
1331 
1332   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1333   UCBuffer = AllocatePool (*DataLength);
1334   if (UCBuffer == NULL) {
1335     return EFI_OUT_OF_RESOURCES;
1336   }
1337   Status = OhciInterruptTransfer (
1338              Ohc,
1339              DeviceAddress,
1340              EndPointAddress,
1341              IsSlowDevice,
1342              MaxPacketLength,
1343              TRUE,
1344              DataToggle,
1345              1,
1346              UCBuffer,
1347              *DataLength,
1348              NULL,
1349              NULL,
1350              FALSE,
1351              &Ed,
1352              &HeadTd
1353              );
1354 
1355   if (!EFI_ERROR (Status)) {
1356     Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
1357     while (Status == EFI_NOT_READY && TimeOut > 0) {
1358       gBS->Stall (1000);
1359       TimeOut--;
1360       Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
1361     }
1362 
1363     *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
1364   }
1365   CopyMem(Data, UCBuffer, *DataLength);
1366   Status = OhciInterruptTransfer (
1367              Ohc,
1368              DeviceAddress,
1369              EndPointAddress,
1370              IsSlowDevice,
1371              MaxPacketLength,
1372              FALSE,
1373              DataToggle,
1374              0,
1375              NULL,
1376              0,
1377              NULL,
1378              NULL,
1379              FALSE,
1380              NULL,
1381              NULL
1382              );
1383 
1384   return Status;
1385 }
1386 /**
1387 
1388   Submits isochronous transfer to a target USB device.
1389 
1390   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1391   @param  DeviceAddress         Represents the address of the target device on the USB,
1392                                 which is assigned during USB enumeration.
1393   @param  EndPointAddress       End point address
1394   @param  MaximumPacketLength   Indicates the maximum packet size that the
1395                                 default control transfer endpoint is capable of
1396                                 sending or receiving.
1397   @param  Data                  A pointer to the buffer of data that will be transmitted
1398                                 to USB device or received from USB device.
1399   @param  DataLength            Indicates the size, in bytes, of the data buffer
1400                                 specified by Data.
1401   @param  TransferResult        A pointer to the detailed result information generated
1402                                 by this control transfer.
1403 
1404   @retval EFI_UNSUPPORTED       This interface not available
1405   @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
1406 
1407 **/
1408 
1409 
1410 EFI_STATUS
1411 EFIAPI
OhciIsochronousTransfer(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 MaximumPacketLength,IN OUT VOID * Data,IN OUT UINTN DataLength,OUT UINT32 * TransferResult)1412 OhciIsochronousTransfer (
1413   IN     EFI_USB_HC_PROTOCOL  *This,
1414   IN     UINT8                DeviceAddress,
1415   IN     UINT8                EndPointAddress,
1416   IN     UINT8                MaximumPacketLength,
1417   IN OUT VOID                 *Data,
1418   IN OUT UINTN                DataLength,
1419   OUT    UINT32               *TransferResult
1420   )
1421 {
1422   if (Data == NULL || DataLength == 0 || TransferResult == NULL) {
1423     return EFI_INVALID_PARAMETER;
1424   }
1425 
1426   return EFI_UNSUPPORTED;
1427 }
1428 
1429 /**
1430 
1431   Submits Async isochronous transfer to a target USB device.
1432 
1433   @param  his                   A pointer to the EFI_USB_HC_PROTOCOL instance.
1434   @param  DeviceAddress         Represents the address of the target device on the USB,
1435                                 which is assigned during USB enumeration.
1436   @param  EndPointAddress       End point address
1437   @param  MaximumPacketLength   Indicates the maximum packet size that the
1438                                 default control transfer endpoint is capable of
1439                                 sending or receiving.
1440   @param  Data                  A pointer to the buffer of data that will be transmitted
1441                                 to USB device or received from USB device.
1442   @param  IsochronousCallBack   When the transfer complete, the call back function will be called
1443   @param  Context               Pass to the call back function as parameter
1444 
1445   @retval EFI_UNSUPPORTED       This interface not available
1446   @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
1447 
1448 **/
1449 
1450 EFI_STATUS
1451 EFIAPI
OhciAsyncIsochronousTransfer(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 DeviceAddress,IN UINT8 EndPointAddress,IN UINT8 MaximumPacketLength,IN OUT VOID * Data,IN OUT UINTN DataLength,IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,IN VOID * Context OPTIONAL)1452 OhciAsyncIsochronousTransfer (
1453   IN     EFI_USB_HC_PROTOCOL                *This,
1454   IN     UINT8                              DeviceAddress,
1455   IN     UINT8                              EndPointAddress,
1456   IN     UINT8                              MaximumPacketLength,
1457   IN OUT VOID                               *Data,
1458   IN OUT UINTN                              DataLength,
1459   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    IsochronousCallBack,
1460   IN     VOID                               *Context OPTIONAL
1461   )
1462 {
1463 
1464   if (Data == NULL || DataLength == 0) {
1465     return EFI_INVALID_PARAMETER;
1466   }
1467 
1468   return EFI_UNSUPPORTED;
1469 }
1470 
1471 /**
1472 
1473   Retrieves the number of root hub ports.
1474 
1475   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1476   @param  NumOfPorts            A pointer to the number of the root hub ports.
1477 
1478   @retval EFI_SUCCESS           The port number was retrieved successfully.
1479 **/
1480 EFI_STATUS
1481 EFIAPI
OhciGetRootHubNumOfPorts(IN EFI_USB_HC_PROTOCOL * This,OUT UINT8 * NumOfPorts)1482 OhciGetRootHubNumOfPorts (
1483   IN  EFI_USB_HC_PROTOCOL  *This,
1484   OUT UINT8                *NumOfPorts
1485   )
1486 {
1487   USB_OHCI_HC_DEV  *Ohc;
1488   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1489 
1490   if (NumOfPorts == NULL) {
1491     return EFI_INVALID_PARAMETER;
1492   }
1493 
1494   *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
1495 
1496   return EFI_SUCCESS;
1497 }
1498 /**
1499 
1500   Retrieves the current status of a USB root hub port.
1501 
1502   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
1503   @param  PortNumber            Specifies the root hub port from which the status
1504                                 is to be retrieved.  This value is zero-based. For example,
1505                                 if a root hub has two ports, then the first port is numbered 0,
1506                                 and the second port is numbered 1.
1507   @param  PortStatus            A pointer to the current port status bits and
1508                                 port status change bits.
1509 
1510   @retval EFI_SUCCESS           The status of the USB root hub port specified by PortNumber
1511                                 was returned in PortStatus.
1512   @retval EFI_INVALID_PARAMETER Port number not valid
1513 **/
1514 
1515 
1516 EFI_STATUS
1517 EFIAPI
OhciGetRootHubPortStatus(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 PortNumber,OUT EFI_USB_PORT_STATUS * PortStatus)1518 OhciGetRootHubPortStatus (
1519   IN  EFI_USB_HC_PROTOCOL  *This,
1520   IN  UINT8                PortNumber,
1521   OUT EFI_USB_PORT_STATUS  *PortStatus
1522   )
1523 {
1524   USB_OHCI_HC_DEV  *Ohc;
1525   UINT8            NumOfPorts;
1526 
1527   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1528 
1529   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1530   if (PortNumber >= NumOfPorts) {
1531     return EFI_INVALID_PARAMETER;
1532   }
1533   PortStatus->PortStatus = 0;
1534   PortStatus->PortChangeStatus = 0;
1535 
1536   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
1537     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
1538   }
1539   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
1540     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
1541   }
1542   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
1543     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
1544   }
1545   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
1546     PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
1547   }
1548   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
1549     PortStatus->PortStatus |= USB_PORT_STAT_RESET;
1550   }
1551   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
1552     PortStatus->PortStatus |= USB_PORT_STAT_POWER;
1553   }
1554   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
1555     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
1556   }
1557   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
1558     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
1559   }
1560   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
1561     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
1562   }
1563   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
1564     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
1565   }
1566   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
1567     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
1568   }
1569   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
1570     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
1571   }
1572 
1573   return EFI_SUCCESS;
1574 }
1575 /**
1576 
1577   Sets a feature for the specified root hub port.
1578 
1579   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
1580   @param  PortNumber            Specifies the root hub port whose feature
1581                                 is requested to be set.
1582   @param  PortFeature           Indicates the feature selector associated
1583                                 with the feature set request.
1584 
1585   @retval EFI_SUCCESS           The feature specified by PortFeature was set for the
1586                                 USB root hub port specified by PortNumber.
1587   @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue
1588   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1589 **/
1590 EFI_STATUS
1591 EFIAPI
OhciSetRootHubPortFeature(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)1592 OhciSetRootHubPortFeature (
1593   IN EFI_USB_HC_PROTOCOL   *This,
1594   IN UINT8                 PortNumber,
1595   IN EFI_USB_PORT_FEATURE  PortFeature
1596   )
1597 {
1598   USB_OHCI_HC_DEV         *Ohc;
1599   EFI_STATUS              Status;
1600   UINT8                   NumOfPorts;
1601   UINTN                   RetryTimes;
1602 
1603   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1604   if (PortNumber >= NumOfPorts) {
1605     return EFI_INVALID_PARAMETER;
1606   }
1607 
1608   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1609 
1610   Status = EFI_SUCCESS;
1611 
1612 
1613   switch (PortFeature) {
1614     case EfiUsbPortPower:
1615       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
1616 
1617       //
1618       // Verify the state
1619       //
1620       RetryTimes = 0;
1621       do {
1622         gBS->Stall (1000);
1623         RetryTimes++;
1624       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
1625                RetryTimes < MAX_RETRY_TIMES);
1626 
1627       if (RetryTimes >= MAX_RETRY_TIMES) {
1628         return EFI_DEVICE_ERROR;
1629       }
1630       break;
1631 
1632     case EfiUsbPortReset:
1633       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
1634 
1635       //
1636       // Verify the state
1637       //
1638       RetryTimes = 0;
1639       do {
1640         gBS->Stall (1000);
1641         RetryTimes++;
1642       } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
1643                 OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
1644                RetryTimes < MAX_RETRY_TIMES);
1645 
1646       if (RetryTimes >= MAX_RETRY_TIMES) {
1647         return EFI_DEVICE_ERROR;
1648       }
1649 
1650       OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
1651       break;
1652 
1653     case EfiUsbPortEnable:
1654       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
1655 
1656       //
1657       // Verify the state
1658       //
1659       RetryTimes = 0;
1660       do {
1661         gBS->Stall (1000);
1662         RetryTimes++;
1663       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
1664                RetryTimes < MAX_RETRY_TIMES);
1665 
1666       if (RetryTimes >= MAX_RETRY_TIMES) {
1667         return EFI_DEVICE_ERROR;
1668       }
1669       break;
1670 
1671 
1672     case EfiUsbPortSuspend:
1673       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
1674 
1675       //
1676       // Verify the state
1677       //
1678       RetryTimes = 0;
1679       do {
1680         gBS->Stall (1000);
1681         RetryTimes++;
1682       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
1683                RetryTimes < MAX_RETRY_TIMES);
1684 
1685       if (RetryTimes >= MAX_RETRY_TIMES) {
1686         return EFI_DEVICE_ERROR;
1687       }
1688       break;
1689 
1690     default:
1691       return EFI_INVALID_PARAMETER;
1692   }
1693 
1694   return Status;
1695 }
1696 
1697 /**
1698 
1699   Clears a feature for the specified root hub port.
1700 
1701   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1702   @param  PortNumber            Specifies the root hub port whose feature
1703                                 is requested to be cleared.
1704   @param  PortFeature           Indicates the feature selector associated with the
1705                                 feature clear request.
1706 
1707   @retval EFI_SUCCESS           The feature specified by PortFeature was cleared for the
1708                                 USB root hub port specified by PortNumber.
1709   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1710   @retval EFI_DEVICE_ERROR      Some error happened when clearing feature
1711 **/
1712 EFI_STATUS
1713 EFIAPI
OhciClearRootHubPortFeature(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)1714 OhciClearRootHubPortFeature (
1715   IN EFI_USB_HC_PROTOCOL   *This,
1716   IN UINT8                 PortNumber,
1717   IN EFI_USB_PORT_FEATURE  PortFeature
1718   )
1719 {
1720   USB_OHCI_HC_DEV         *Ohc;
1721   EFI_STATUS              Status;
1722   UINT8                   NumOfPorts;
1723   UINTN                   RetryTimes;
1724 
1725 
1726   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1727   if (PortNumber >= NumOfPorts) {
1728     return EFI_INVALID_PARAMETER;
1729   }
1730 
1731   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1732 
1733   Status = EFI_SUCCESS;
1734 
1735   switch (PortFeature) {
1736     case EfiUsbPortEnable:
1737       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
1738 
1739       //
1740       // Verify the state
1741       //
1742       RetryTimes = 0;
1743       do {
1744         gBS->Stall (1000);
1745         RetryTimes++;
1746       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
1747                RetryTimes < MAX_RETRY_TIMES);
1748 
1749       if (RetryTimes >= MAX_RETRY_TIMES) {
1750         return EFI_DEVICE_ERROR;
1751       }
1752       break;
1753 
1754     case EfiUsbPortSuspend:
1755       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
1756 
1757       //
1758       // Verify the state
1759       //
1760       RetryTimes = 0;
1761       do {
1762         gBS->Stall (1000);
1763         RetryTimes++;
1764       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
1765                RetryTimes < MAX_RETRY_TIMES);
1766 
1767       if (RetryTimes >= MAX_RETRY_TIMES) {
1768         return EFI_DEVICE_ERROR;
1769       }
1770       break;
1771 
1772     case EfiUsbPortReset:
1773       break;
1774 
1775     case EfiUsbPortPower:
1776       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
1777 
1778       //
1779       // Verify the state
1780       //
1781       RetryTimes = 0;
1782       do {
1783         gBS->Stall (1000);
1784         RetryTimes++;
1785       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
1786                RetryTimes < MAX_RETRY_TIMES);
1787 
1788       if (RetryTimes >= MAX_RETRY_TIMES) {
1789         return EFI_DEVICE_ERROR;
1790       }
1791       break;
1792 
1793     case EfiUsbPortConnectChange:
1794       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
1795 
1796       //
1797       // Verify the state
1798       //
1799       RetryTimes = 0;
1800       do {
1801         gBS->Stall (1000);
1802         RetryTimes++;
1803       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
1804                RetryTimes < MAX_RETRY_TIMES);
1805 
1806       if (RetryTimes >= MAX_RETRY_TIMES) {
1807         return EFI_DEVICE_ERROR;
1808       }
1809       break;
1810 
1811     case EfiUsbPortResetChange:
1812       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
1813 
1814       //
1815       // Verify the state
1816       //
1817       RetryTimes = 0;
1818       do {
1819         gBS->Stall (1000);
1820         RetryTimes++;
1821       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
1822                RetryTimes < MAX_RETRY_TIMES);
1823 
1824       if (RetryTimes >= MAX_RETRY_TIMES) {
1825         return EFI_DEVICE_ERROR;
1826       }
1827       break;
1828 
1829 
1830     case EfiUsbPortEnableChange:
1831       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
1832 
1833       //
1834       // Verify the state
1835       //
1836       RetryTimes = 0;
1837       do {
1838         gBS->Stall (1000);
1839         RetryTimes++;
1840       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
1841                RetryTimes < MAX_RETRY_TIMES);
1842 
1843       if (RetryTimes >= MAX_RETRY_TIMES) {
1844         return EFI_DEVICE_ERROR;
1845       }
1846       break;
1847 
1848     case EfiUsbPortSuspendChange:
1849       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
1850 
1851       //
1852       // Verify the state
1853       //
1854       RetryTimes = 0;
1855       do {
1856         gBS->Stall (1000);
1857         RetryTimes++;
1858       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
1859                RetryTimes < MAX_RETRY_TIMES);
1860 
1861       if (RetryTimes >= MAX_RETRY_TIMES) {
1862         return EFI_DEVICE_ERROR;
1863       }
1864       break;
1865 
1866     case EfiUsbPortOverCurrentChange:
1867       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
1868 
1869       //
1870       // Verify the state
1871       //
1872       RetryTimes = 0;
1873       do {
1874         gBS->Stall (1000);
1875         RetryTimes++;
1876       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
1877                RetryTimes < MAX_RETRY_TIMES);
1878 
1879       if (RetryTimes >= MAX_RETRY_TIMES) {
1880         return EFI_DEVICE_ERROR;
1881       }
1882       break;
1883 
1884     default:
1885       return EFI_INVALID_PARAMETER;
1886   }
1887 
1888   return Status;
1889 }
1890 
1891 EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
1892   OHCIDriverBindingSupported,
1893   OHCIDriverBindingStart,
1894   OHCIDriverBindingStop,
1895   0x10,
1896   NULL,
1897   NULL
1898 };
1899 
1900 
1901 /**
1902   Entry point for EFI drivers.
1903 
1904   @param  ImageHandle           EFI_HANDLE.
1905   @param  SystemTable           EFI_SYSTEM_TABLE.
1906 
1907   @retval EFI_SUCCESS           Driver is successfully loaded.
1908   @return Others                Failed.
1909 
1910 **/
1911 EFI_STATUS
1912 EFIAPI
OHCIDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1913 OHCIDriverEntryPoint (
1914   IN EFI_HANDLE          ImageHandle,
1915   IN EFI_SYSTEM_TABLE    *SystemTable
1916   )
1917 {
1918   return EfiLibInstallDriverBindingComponentName2 (
1919            ImageHandle,
1920            SystemTable,
1921            &gOhciDriverBinding,
1922            ImageHandle,
1923            &gOhciComponentName,
1924            &gOhciComponentName2
1925            );
1926 }
1927 
1928 
1929 /**
1930   Test to see if this driver supports ControllerHandle. Any
1931   ControllerHandle that has UsbHcProtocol installed will be supported.
1932 
1933   @param  This                 Protocol instance pointer.
1934   @param  Controller           Handle of device to test.
1935   @param  RemainingDevicePath  Not used.
1936 
1937   @return EFI_SUCCESS          This driver supports this device.
1938   @return EFI_UNSUPPORTED      This driver does not support this device.
1939 
1940 **/
1941 EFI_STATUS
1942 EFIAPI
OHCIDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1943 OHCIDriverBindingSupported (
1944   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1945   IN EFI_HANDLE                   Controller,
1946   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1947   )
1948 {
1949   EFI_STATUS              Status;
1950   EFI_PCI_IO_PROTOCOL     *PciIo;
1951   USB_CLASSC              UsbClassCReg;
1952   //
1953   // Test whether there is PCI IO Protocol attached on the controller handle.
1954   //
1955   Status = gBS->OpenProtocol (
1956                   Controller,
1957                   &gEfiPciIoProtocolGuid,
1958                   (VOID **) &PciIo,
1959                   This->DriverBindingHandle,
1960                   Controller,
1961                   EFI_OPEN_PROTOCOL_BY_DRIVER
1962                   );
1963 
1964   if (EFI_ERROR (Status)) {
1965     return EFI_UNSUPPORTED;
1966   }
1967 
1968   Status = PciIo->Pci.Read (
1969                         PciIo,
1970                         EfiPciIoWidthUint8,
1971                         PCI_CLASSCODE_OFFSET,
1972                         sizeof (USB_CLASSC) / sizeof (UINT8),
1973                         &UsbClassCReg
1974                         );
1975 
1976   if (EFI_ERROR (Status)) {
1977     Status = EFI_UNSUPPORTED;
1978     goto ON_EXIT;
1979   }
1980   //
1981   // Test whether the controller belongs to OHCI type
1982   //
1983   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
1984       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
1985       (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
1986       ) {
1987 
1988     Status = EFI_UNSUPPORTED;
1989   }
1990 ON_EXIT:
1991   gBS->CloseProtocol (
1992          Controller,
1993          &gEfiPciIoProtocolGuid,
1994          This->DriverBindingHandle,
1995          Controller
1996          );
1997 
1998   return Status;
1999 
2000 }
2001 
2002 /**
2003 
2004   Allocate and initialize the empty OHCI device.
2005 
2006   @param  PciIo                  The PCIIO to use.
2007   @param  OriginalPciAttributes  The original PCI attributes.
2008 
2009   @return Allocated OHCI device  If err, return NULL.
2010 
2011 **/
2012 
2013 USB_OHCI_HC_DEV *
OhciAllocateDev(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT64 OriginalPciAttributes)2014 OhciAllocateDev (
2015   IN EFI_PCI_IO_PROTOCOL  *PciIo,
2016   IN UINT64               OriginalPciAttributes
2017   )
2018 {
2019   USB_OHCI_HC_DEV         *Ohc;
2020   EFI_STATUS              Status;
2021   VOID                    *Buf;
2022   EFI_PHYSICAL_ADDRESS    PhyAddr;
2023   VOID                    *Map;
2024   UINTN                   Pages;
2025   UINTN                   Bytes;
2026 
2027   Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));
2028   if (Ohc == NULL) {
2029     return NULL;
2030   }
2031 
2032   Ohc->Signature                      = USB_OHCI_HC_DEV_SIGNATURE;
2033   Ohc->PciIo                          = PciIo;
2034 
2035   Ohc->UsbHc.Reset                    = OhciReset;
2036   Ohc->UsbHc.GetState                 = OhciGetState;
2037   Ohc->UsbHc.SetState                 = OhciSetState;
2038   Ohc->UsbHc.ControlTransfer          = OhciControlTransfer;
2039   Ohc->UsbHc.BulkTransfer             = OhciBulkTransfer;
2040   Ohc->UsbHc.AsyncInterruptTransfer   = OhciAsyncInterruptTransfer;
2041   Ohc->UsbHc.SyncInterruptTransfer    = OhciSyncInterruptTransfer;
2042   Ohc->UsbHc.IsochronousTransfer      = OhciIsochronousTransfer;
2043   Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;
2044   Ohc->UsbHc.GetRootHubPortNumber     = OhciGetRootHubNumOfPorts;
2045   Ohc->UsbHc.GetRootHubPortStatus     = OhciGetRootHubPortStatus;
2046   Ohc->UsbHc.SetRootHubPortFeature    = OhciSetRootHubPortFeature;
2047   Ohc->UsbHc.ClearRootHubPortFeature  = OhciClearRootHubPortFeature;
2048   Ohc->UsbHc.MajorRevision            = 0x1;
2049   Ohc->UsbHc.MinorRevision            = 0x1;
2050 
2051   Ohc->OriginalPciAttributes = OriginalPciAttributes;
2052 
2053   Ohc->HccaMemoryBlock = NULL;
2054   Ohc->HccaMemoryMapping   = NULL;
2055   Ohc->HccaMemoryBuf = NULL;
2056   Ohc->HccaMemoryPages = 0;
2057   Ohc->InterruptContextList = NULL;
2058   Ohc->ControllerNameTable = NULL;
2059   Ohc->HouseKeeperTimer = NULL;
2060 
2061   Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);
2062   if(Ohc->MemPool == NULL) {
2063     goto FREE_DEV_BUFFER;
2064   }
2065 
2066   Bytes = 4096;
2067   Pages = EFI_SIZE_TO_PAGES (Bytes);
2068 
2069   Status = PciIo->AllocateBuffer (
2070                     PciIo,
2071                     AllocateAnyPages,
2072                     EfiBootServicesData,
2073                     Pages,
2074                     &Buf,
2075                     0
2076                     );
2077 
2078   if (EFI_ERROR (Status)) {
2079     goto FREE_MEM_POOL;
2080   }
2081 
2082   Status = PciIo->Map (
2083                     PciIo,
2084                     EfiPciIoOperationBusMasterCommonBuffer,
2085                     Buf,
2086                     &Bytes,
2087                     &PhyAddr,
2088                     &Map
2089                     );
2090 
2091   if (EFI_ERROR (Status) || (Bytes != 4096)) {
2092     goto FREE_MEM_PAGE;
2093   }
2094 
2095   Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;
2096   Ohc->HccaMemoryMapping = Map;
2097   Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;
2098   Ohc->HccaMemoryPages = Pages;
2099 
2100   return Ohc;
2101 
2102 FREE_MEM_PAGE:
2103   PciIo->FreeBuffer (PciIo, Pages, Buf);
2104 FREE_MEM_POOL:
2105   UsbHcFreeMemPool (Ohc->MemPool);
2106 FREE_DEV_BUFFER:
2107   FreePool(Ohc);
2108 
2109   return NULL;
2110 }
2111 /**
2112 
2113   Free the OHCI device and release its associated resources.
2114 
2115   @param  Ohc                   The OHCI device to release.
2116 
2117 **/
2118 VOID
OhciFreeDev(IN USB_OHCI_HC_DEV * Ohc)2119 OhciFreeDev (
2120   IN USB_OHCI_HC_DEV      *Ohc
2121   )
2122 {
2123   OhciFreeFixedIntMemory (Ohc);
2124 
2125   if (Ohc->HouseKeeperTimer != NULL) {
2126     gBS->CloseEvent (Ohc->HouseKeeperTimer);
2127   }
2128 
2129   if (Ohc->ExitBootServiceEvent != NULL) {
2130     gBS->CloseEvent (Ohc->ExitBootServiceEvent);
2131   }
2132 
2133   if (Ohc->MemPool != NULL) {
2134     UsbHcFreeMemPool (Ohc->MemPool);
2135   }
2136 
2137   if (Ohc->HccaMemoryMapping != NULL ) {
2138     Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);
2139   }
2140 
2141   if (Ohc->ControllerNameTable != NULL) {
2142     FreeUnicodeStringTable (Ohc->ControllerNameTable);
2143   }
2144 
2145   FreePool (Ohc);
2146 }
2147 /**
2148 
2149   Uninstall all Ohci Interface.
2150 
2151   @param  Controller            Controller handle.
2152   @param  This                  Protocol instance pointer.
2153 
2154 **/
2155 VOID
OhciCleanDevUp(IN EFI_HANDLE Controller,IN EFI_USB_HC_PROTOCOL * This)2156 OhciCleanDevUp (
2157   IN  EFI_HANDLE           Controller,
2158   IN  EFI_USB_HC_PROTOCOL  *This
2159   )
2160 {
2161   USB_OHCI_HC_DEV  *Ohc;
2162 
2163   //
2164   // Retrieve private context structure
2165   //
2166   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
2167 
2168   //
2169   // Uninstall the USB_HC and USB_HC2 protocol
2170   //
2171   gBS->UninstallProtocolInterface (
2172          Controller,
2173          &gEfiUsbHcProtocolGuid,
2174          &Ohc->UsbHc
2175          );
2176 
2177   //
2178   // Cancel the timer event
2179   //
2180   gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);
2181 
2182   //
2183   // Stop the host controller
2184   //
2185   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
2186   This->Reset (This, EFI_USB_HC_RESET_GLOBAL);
2187   This->SetState (This, EfiUsbHcStateHalt);
2188 
2189   //
2190   // Free resources
2191   //
2192   OhciFreeDynamicIntMemory (Ohc);
2193 
2194   //
2195   // Restore original PCI attributes
2196   //
2197   Ohc->PciIo->Attributes (
2198                 Ohc->PciIo,
2199                 EfiPciIoAttributeOperationSet,
2200                 Ohc->OriginalPciAttributes,
2201                 NULL
2202                 );
2203 
2204   //
2205   // Free the private context structure
2206   //
2207   OhciFreeDev (Ohc);
2208 }
2209 
2210 /**
2211 
2212   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
2213 
2214   @param  Event                 Pointer to this event
2215   @param  Context               Event hanlder private data
2216 **/
2217 VOID
2218 EFIAPI
OhcExitBootService(EFI_EVENT Event,VOID * Context)2219 OhcExitBootService (
2220   EFI_EVENT                      Event,
2221   VOID                           *Context
2222   )
2223 {
2224   USB_OHCI_HC_DEV           *Ohc;
2225   EFI_USB_HC_PROTOCOL       *UsbHc;
2226   Ohc = (USB_OHCI_HC_DEV *) Context;
2227 
2228   UsbHc = &Ohc->UsbHc;
2229   //
2230   // Stop the Host Controller
2231   //
2232   //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
2233   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
2234   UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);
2235   UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);
2236 
2237   return;
2238 }
2239 
2240 
2241 /**
2242   Starting the Usb OHCI Driver.
2243 
2244   @param  This                  Protocol instance pointer.
2245   @param  Controller            Handle of device to test.
2246   @param  RemainingDevicePath   Not used.
2247 
2248   @retval EFI_SUCCESS           This driver supports this device.
2249   @retval EFI_UNSUPPORTED       This driver does not support this device.
2250   @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.
2251                                 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
2252 
2253 **/
2254 EFI_STATUS
2255 EFIAPI
OHCIDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)2256 OHCIDriverBindingStart (
2257   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
2258   IN EFI_HANDLE                   Controller,
2259   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
2260   )
2261 {
2262   EFI_STATUS              Status;
2263   EFI_PCI_IO_PROTOCOL     *PciIo;
2264   USB_OHCI_HC_DEV         *Ohc;
2265   UINT64                  Supports;
2266   UINT64                  OriginalPciAttributes;
2267   BOOLEAN                 PciAttributesSaved;
2268 
2269   //
2270   // Open PCIIO, then enable the HC device and turn off emulation
2271   //
2272   Ohc = NULL;
2273   Status = gBS->OpenProtocol (
2274                   Controller,
2275                   &gEfiPciIoProtocolGuid,
2276                   (VOID **) &PciIo,
2277                   This->DriverBindingHandle,
2278                   Controller,
2279                   EFI_OPEN_PROTOCOL_BY_DRIVER
2280                   );
2281 
2282   if (EFI_ERROR (Status)) {
2283     return Status;
2284   }
2285 
2286   PciAttributesSaved = FALSE;
2287   //
2288   // Save original PCI attributes
2289   //
2290   Status = PciIo->Attributes (
2291                     PciIo,
2292                     EfiPciIoAttributeOperationGet,
2293                     0,
2294                     &OriginalPciAttributes
2295                     );
2296 
2297   if (EFI_ERROR (Status)) {
2298     goto CLOSE_PCIIO;
2299   }
2300   PciAttributesSaved = TRUE;
2301 
2302   //
2303   // Robustnesss improvement such as for UoL
2304   // Default is not required.
2305   //
2306   //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
2307   //  OhciTurnOffUsbEmulation (PciIo);
2308   //}
2309 
2310   Status = PciIo->Attributes (
2311                     PciIo,
2312                     EfiPciIoAttributeOperationSupported,
2313                     0,
2314                     &Supports
2315                     );
2316   if (!EFI_ERROR (Status)) {
2317     Supports &= EFI_PCI_DEVICE_ENABLE;
2318     Status = PciIo->Attributes (
2319                       PciIo,
2320                       EfiPciIoAttributeOperationEnable,
2321                       Supports,
2322                       NULL
2323                       );
2324   }
2325 
2326   if (EFI_ERROR (Status)) {
2327     goto CLOSE_PCIIO;
2328   }
2329   //
2330   //Allocate memory for OHC private data structure
2331   //
2332   Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);
2333   if (Ohc == NULL){
2334     Status = EFI_OUT_OF_RESOURCES;
2335     goto CLOSE_PCIIO;
2336   }
2337 
2338   //Status = OhciInitializeInterruptList ( Uhc );
2339   //if (EFI_ERROR (Status)) {
2340   //  goto FREE_OHC;
2341   //}
2342 
2343   //
2344   // Set 0.01 s timer
2345   //
2346   Status = gBS->CreateEvent (
2347                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
2348                   TPL_NOTIFY,
2349                   OhciHouseKeeper,
2350                   Ohc,
2351                   &Ohc->HouseKeeperTimer
2352                   );
2353   if (EFI_ERROR (Status)) {
2354     goto FREE_OHC;
2355   }
2356 
2357   Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);
2358   if (EFI_ERROR (Status)) {
2359     goto FREE_OHC;
2360   }
2361 
2362   //
2363   //Install Host Controller Protocol
2364   //
2365   Status = gBS->InstallProtocolInterface (
2366                   &Controller,
2367                   &gEfiUsbHcProtocolGuid,
2368                   EFI_NATIVE_INTERFACE,
2369                   &Ohc->UsbHc
2370                   );
2371   if (EFI_ERROR (Status)) {
2372     DEBUG ((EFI_D_INFO, "Install protocol error"));
2373     goto FREE_OHC;
2374   }
2375   //
2376   // Create event to stop the HC when exit boot service.
2377   //
2378   Status = gBS->CreateEventEx (
2379                   EVT_NOTIFY_SIGNAL,
2380                   TPL_NOTIFY,
2381                   OhcExitBootService,
2382                   Ohc,
2383                   &gEfiEventExitBootServicesGuid,
2384                   &Ohc->ExitBootServiceEvent
2385                   );
2386   if (EFI_ERROR (Status)) {
2387     DEBUG ((EFI_D_INFO, "Create exit boot event error"));
2388     goto UNINSTALL_USBHC;
2389   }
2390   AddUnicodeString2 (
2391     "eng",
2392     gOhciComponentName.SupportedLanguages,
2393     &Ohc->ControllerNameTable,
2394     L"Usb Universal Host Controller",
2395     TRUE
2396     );
2397   AddUnicodeString2 (
2398     "en",
2399     gOhciComponentName2.SupportedLanguages,
2400     &Ohc->ControllerNameTable,
2401     L"Usb Universal Host Controller",
2402     FALSE
2403     );
2404 
2405   return EFI_SUCCESS;
2406 
2407 UNINSTALL_USBHC:
2408   gBS->UninstallMultipleProtocolInterfaces (
2409          Controller,
2410          &gEfiUsbHcProtocolGuid,
2411          &Ohc->UsbHc,
2412          NULL
2413          );
2414 
2415 FREE_OHC:
2416   OhciFreeDev (Ohc);
2417 
2418 CLOSE_PCIIO:
2419   if (PciAttributesSaved) {
2420   //
2421   // Restore original PCI attributes
2422   //
2423     PciIo->Attributes (
2424              PciIo,
2425              EfiPciIoAttributeOperationSet,
2426              OriginalPciAttributes,
2427              NULL
2428              );
2429   }
2430 
2431   gBS->CloseProtocol (
2432          Controller,
2433          &gEfiPciIoProtocolGuid,
2434          This->DriverBindingHandle,
2435          Controller
2436          );
2437   return Status;
2438 }
2439 
2440 /**
2441   Stop this driver on ControllerHandle. Support stoping any child handles
2442   created by this driver.
2443 
2444   @param  This                  Protocol instance pointer.
2445   @param  Controller            Handle of device to stop driver on.
2446   @param  NumberOfChildren      Number of Children in the ChildHandleBuffer.
2447   @param  ChildHandleBuffer     List of handles for the children we need to stop.
2448 
2449   @return EFI_SUCCESS
2450   @return others
2451 
2452 **/
2453 EFI_STATUS
2454 EFIAPI
OHCIDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)2455 OHCIDriverBindingStop (
2456   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
2457   IN EFI_HANDLE                   Controller,
2458   IN UINTN                        NumberOfChildren,
2459   IN EFI_HANDLE                   *ChildHandleBuffer
2460   )
2461 {
2462   EFI_STATUS           Status;
2463   EFI_USB_HC_PROTOCOL  *UsbHc;
2464 
2465   Status = gBS->OpenProtocol (
2466                   Controller,
2467                   &gEfiUsbHcProtocolGuid,
2468                   (VOID **)&UsbHc,
2469                   This->DriverBindingHandle,
2470                   Controller,
2471                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2472                   );
2473   if (EFI_ERROR (Status)) {
2474     return Status;
2475   }
2476 
2477   OhciCleanDevUp(Controller, UsbHc);
2478 
2479   gBS->CloseProtocol (
2480          Controller,
2481          &gEfiPciIoProtocolGuid,
2482          This->DriverBindingHandle,
2483          Controller
2484          );
2485   return EFI_SUCCESS;
2486 }
2487 
2488 
2489