1 /** @file
2 This file contains the implementation of Usb Hc Protocol.
3 
4 Copyright (c) 2013-2016 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   UINT32                         DataPidDir;
641   TD_DESCRIPTOR                  *HeadTd;
642   TD_DESCRIPTOR                  *DataTd;
643   TD_DESCRIPTOR                  *EmptyTd;
644   EFI_STATUS                     Status;
645   UINT8                          EndPointNum;
646   UINTN                          TimeCount;
647   OHCI_ED_RESULT                 EdResult;
648 
649   EFI_PCI_IO_PROTOCOL_OPERATION  MapOp;
650   VOID                           *Mapping;
651   UINTN                          MapLength;
652   EFI_PHYSICAL_ADDRESS           MapPyhAddr;
653   UINTN                          LeftLength;
654   UINTN                          ActualSendLength;
655   BOOLEAN                        FirstTD;
656 
657   Mapping = NULL;
658   MapLength = 0;
659   MapPyhAddr = 0;
660   LeftLength = 0;
661   Status = EFI_SUCCESS;
662 
663   if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
664       *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
665       (MaxPacketLength != 8 && MaxPacketLength != 16 &&
666        MaxPacketLength != 32 && MaxPacketLength != 64)) {
667     return EFI_INVALID_PARAMETER;
668   }
669 
670   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
671 
672   if ((EndPointAddress & 0x80) != 0) {
673     DataPidDir = TD_IN_PID;
674     MapOp = EfiPciIoOperationBusMasterWrite;
675   } else {
676     DataPidDir = TD_OUT_PID;
677     MapOp = EfiPciIoOperationBusMasterRead;
678   }
679 
680   EndPointNum = (EndPointAddress & 0xF);
681   EdResult.NextToggle = *DataToggle;
682 
683   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);
684   if (EFI_ERROR(Status)) {
685     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
686     *TransferResult = EFI_USB_ERR_SYSTEM;
687     return EFI_DEVICE_ERROR;
688   }
689   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);
690   if (EFI_ERROR(Status)) {
691     DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
692     *TransferResult = EFI_USB_ERR_SYSTEM;
693     return EFI_DEVICE_ERROR;
694   }
695   gBS->Stall(20 * 1000);
696 
697   OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
698 
699   Ed = OhciCreateED (Ohc);
700   if (Ed == NULL) {
701     return EFI_OUT_OF_RESOURCES;
702   }
703   OhciSetEDField (Ed, ED_SKIP, 1);
704   OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
705   OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
706   OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
707   OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
708   OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
709   OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
710   OhciSetEDField (Ed, ED_PDATA, 0);
711   OhciSetEDField (Ed, ED_ZERO, 0);
712   OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
713   OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
714   OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
715   HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
716 
717   if(Data != NULL) {
718     MapLength = *DataLength;
719     Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);
720     if (EFI_ERROR(Status)) {
721       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
722       goto FREE_ED_BUFF;
723     }
724   }
725   //
726   //Data Stage
727   //
728   LeftLength = MapLength;
729   ActualSendLength = MapLength;
730   HeadTd = NULL;
731   FirstTD = TRUE;
732   while (LeftLength > 0) {
733     ActualSendLength = LeftLength;
734     if (LeftLength > MaxPacketLength) {
735       ActualSendLength = MaxPacketLength;
736     }
737     DataTd = OhciCreateTD (Ohc);
738     if (DataTd == NULL) {
739       DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
740       Status = EFI_OUT_OF_RESOURCES;
741       goto FREE_OHCI_TDBUFF;
742     }
743     OhciSetTDField (DataTd, TD_PDATA, 0);
744     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
745     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
746     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
747     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
748     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
749     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
750     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
751     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
752     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
753     DataTd->ActualSendLength = (UINT32)ActualSendLength;
754     DataTd->DataBuffer = (UINT32)MapPyhAddr;
755     DataTd->NextTDPointer = 0;
756     if (FirstTD) {
757       HeadTd = DataTd;
758       FirstTD = FALSE;
759     } else {
760       OhciLinkTD (HeadTd, DataTd);
761     }
762     *DataToggle ^= 1;
763     MapPyhAddr += ActualSendLength;
764     LeftLength -= ActualSendLength;
765   }
766   //
767   // Empty Stage
768   //
769   EmptyTd = OhciCreateTD (Ohc);
770   if (EmptyTd == NULL) {
771     Status = EFI_OUT_OF_RESOURCES;
772     DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
773     goto FREE_OHCI_TDBUFF;
774   }
775   OhciSetTDField (EmptyTd, TD_PDATA, 0);
776   OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
777   OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
778   OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
779   //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
780   EmptyTd->Word0.DataToggle = 0;
781   OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
782   OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
783   OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
784   OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
785   OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
786   EmptyTd->ActualSendLength = 0;
787   EmptyTd->DataBuffer = 0;
788   EmptyTd->NextTDPointer = 0;
789   OhciLinkTD (HeadTd, EmptyTd);
790   Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
791   OhciAttachTDListToED (Ed, HeadTd);
792 
793   OhciSetEDField (Ed, ED_SKIP, 0);
794   Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
795   if (EFI_ERROR(Status)) {
796     *TransferResult = EFI_USB_ERR_SYSTEM;
797     Status = EFI_DEVICE_ERROR;
798     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
799     goto FREE_OHCI_TDBUFF;
800   }
801   Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);
802   if (EFI_ERROR(Status)) {
803     *TransferResult = EFI_USB_ERR_SYSTEM;
804     Status = EFI_DEVICE_ERROR;
805     DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
806     goto FREE_OHCI_TDBUFF;
807   }
808   gBS->Stall(20 * 1000);
809 
810   TimeCount = 0;
811   Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
812   while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
813     gBS->Stall (1000);
814     TimeCount++;
815     Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
816   }
817 
818   *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
819 
820   if (EdResult.ErrorCode != TD_NO_ERROR) {
821     if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
822       DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
823     } else {
824       DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
825       *DataToggle = EdResult.NextToggle;
826     }
827     *DataLength = 0;
828   } else {
829     DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));
830   }
831   //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
832 
833 FREE_OHCI_TDBUFF:
834   OhciSetEDField (Ed, ED_SKIP, 1);
835   if (HeadEd == Ed) {
836     OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
837   }else {
838     HeadEd->NextED = Ed->NextED;
839   }
840   while (HeadTd) {
841     DataTd = HeadTd;
842     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
843     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
844   }
845 
846   if(Mapping != NULL) {
847     Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
848   }
849 
850 FREE_ED_BUFF:
851   UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
852 
853   return Status;
854 }
855 /**
856 
857   Submits an interrupt transfer to an interrupt endpoint of a USB device.
858 
859   @param  Ohc                   Device private data
860   @param  DeviceAddress         Represents the address of the target device on the USB,
861                                 which is assigned during USB enumeration.
862   @param  EndPointAddress       The combination of an endpoint number and an endpoint
863                                 direction of the target USB device. Each endpoint address
864                                 supports data transfer in one direction except the
865                                 control endpoint (whose default endpoint address is 0).
866                                 It is the caller's responsibility to make sure that
867                                 the EndPointAddress represents an interrupt endpoint.
868   @param  IsSlowDevice          Indicates whether the target device is slow device
869                                 or full-speed device.
870   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
871                                 is capable of sending or receiving.
872   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
873                                 the host and the target interrupt endpoint.
874                                 If FALSE, the specified asynchronous interrupt pipe
875                                 is canceled.
876   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
877                                 when IsNewTransfer is TRUE, and it indicates the initial
878                                 data toggle value the asynchronous interrupt transfer
879                                 should adopt.
880                                 On output, it is valid when IsNewTransfer is FALSE,
881                                 and it is updated to indicate the data toggle value of
882                                 the subsequent asynchronous interrupt transfer.
883   @param  PollingInterval       Indicates the interval, in milliseconds, that the
884                                 asynchronous interrupt transfer is polled.
885                                 This parameter is required when IsNewTransfer is TRUE.
886   @param  UCBuffer              Uncacheable buffer
887   @param  DataLength            Indicates the length of data to be received at the
888                                 rate specified by PollingInterval from the target
889                                 asynchronous interrupt endpoint.  This parameter
890                                 is only required when IsNewTransfer is TRUE.
891   @param  CallBackFunction      The Callback function.This function is called at the
892                                 rate specified by PollingInterval.This parameter is
893                                 only required when IsNewTransfer is TRUE.
894   @param  Context               The context that is passed to the CallBackFunction.
895                                 This is an optional parameter and may be NULL.
896   @param  IsPeriodic            Periodic interrupt or not
897   @param  OutputED              The correspoding ED carried out
898   @param  OutputTD              The correspoding TD carried out
899 
900 
901   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
902                                 submitted or canceled.
903   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
904   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
905 
906 **/
907 
908 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)909 OhciInterruptTransfer (
910   IN     USB_OHCI_HC_DEV                  *Ohc,
911   IN     UINT8                            DeviceAddress,
912   IN     UINT8                            EndPointAddress,
913   IN     BOOLEAN                          IsSlowDevice,
914   IN     UINT8                            MaxPacketLength,
915   IN     BOOLEAN                          IsNewTransfer,
916   IN OUT UINT8                            *DataToggle        OPTIONAL,
917   IN     UINTN                            PollingInterval    OPTIONAL,
918   IN     VOID                             *UCBuffer          OPTIONAL,
919   IN     UINTN                            DataLength         OPTIONAL,
920   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
921   IN     VOID                             *Context           OPTIONAL,
922   IN     BOOLEAN                          IsPeriodic         OPTIONAL,
923   OUT    ED_DESCRIPTOR                    **OutputED         OPTIONAL,
924   OUT    TD_DESCRIPTOR                    **OutputTD         OPTIONAL
925   )
926 {
927   ED_DESCRIPTOR            *Ed;
928   UINT8                    EdDir;
929   ED_DESCRIPTOR            *HeadEd;
930   TD_DESCRIPTOR            *HeadTd;
931   TD_DESCRIPTOR            *DataTd;
932   TD_DESCRIPTOR            *EmptTd;
933   UINTN                    Depth;
934   UINTN                    Index;
935   EFI_STATUS               Status;
936   UINT8                    EndPointNum;
937   UINT32                   DataPidDir;
938   INTERRUPT_CONTEXT_ENTRY  *Entry;
939   EFI_TPL                  OldTpl;
940   BOOLEAN                  FirstTD;
941 
942  VOID                      *Mapping;
943  UINTN                     MapLength;
944  EFI_PHYSICAL_ADDRESS      MapPyhAddr;
945  UINTN                     LeftLength;
946  UINTN                     ActualSendLength;
947 
948 
949   if (DataLength > MAX_BYTES_PER_TD) {
950     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));
951     return EFI_INVALID_PARAMETER;
952   }
953 
954   if ((EndPointAddress & 0x80) != 0) {
955     EdDir = ED_IN_DIR;
956     DataPidDir = TD_IN_PID;
957   } else {
958     EdDir = ED_OUT_DIR;
959     DataPidDir = TD_OUT_PID;
960   }
961 
962   EndPointNum = (EndPointAddress & 0xF);
963 
964   if (!IsNewTransfer) {
965     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
966     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);
967     OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);
968     Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);
969     OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
970     gBS->RestoreTPL (OldTpl);
971     return Status;
972   }
973   MapLength = DataLength;
974   Status = Ohc->PciIo->Map(
975                          Ohc->PciIo,
976                          EfiPciIoOperationBusMasterWrite,
977                          UCBuffer,
978                          &MapLength,
979                          &MapPyhAddr,
980                          &Mapping
981                          );
982   if (EFI_ERROR (Status)) {
983     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
984     goto EXIT;
985   }
986   Depth = 5;
987   Index = 1;
988   while (PollingInterval >= Index * 2 && Depth > 0) {
989     Index *= 2;
990     Depth--;
991   }
992   //
993   //ED Stage
994   //
995   HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);
996   if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {
997     OhciSetEDField (Ed, ED_SKIP, 1);
998   } else {
999     Ed = OhciCreateED (Ohc);
1000     if (Ed == NULL) {
1001       Status = EFI_OUT_OF_RESOURCES;
1002       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
1003       goto UNMAP_OHCI_XBUFF;
1004     }
1005     OhciSetEDField (Ed, ED_SKIP, 1);
1006     OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
1007     OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
1008     OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
1009     OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
1010     OhciSetEDField (Ed, ED_FORMAT, 0);
1011     OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
1012     OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);
1013     OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
1014     OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
1015     OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
1016     OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);
1017   }
1018   //
1019   //Data Stage
1020   //
1021   LeftLength = MapLength;
1022   ActualSendLength = MapLength;
1023   HeadTd = NULL;
1024   FirstTD = TRUE;
1025   while (LeftLength > 0) {
1026     ActualSendLength = LeftLength;
1027     if (LeftLength > MaxPacketLength) {
1028       ActualSendLength = MaxPacketLength;
1029     }
1030     DataTd = OhciCreateTD (Ohc);
1031     if (DataTd == NULL) {
1032       Status = EFI_OUT_OF_RESOURCES;
1033       DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
1034       goto FREE_OHCI_TDBUFF;
1035     }
1036     OhciSetTDField (DataTd, TD_PDATA, 0);
1037     OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
1038     OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
1039     OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
1040     OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
1041     OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
1042     OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
1043     OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
1044     OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
1045     OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
1046     DataTd->ActualSendLength = (UINT32)ActualSendLength;
1047     DataTd->DataBuffer = (UINT32)MapPyhAddr;
1048     DataTd->NextTDPointer = 0;
1049     if (FirstTD) {
1050       HeadTd = DataTd;
1051       FirstTD = FALSE;
1052     } else {
1053       OhciLinkTD (HeadTd, DataTd);
1054     }
1055     *DataToggle ^= 1;
1056     MapPyhAddr += ActualSendLength;
1057     LeftLength -= ActualSendLength;
1058   }
1059 
1060   EmptTd = OhciCreateTD (Ohc);
1061   if (EmptTd == NULL) {
1062     Status = EFI_OUT_OF_RESOURCES;
1063     DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
1064     goto FREE_OHCI_TDBUFF;
1065   }
1066   OhciSetTDField (EmptTd, TD_PDATA, 0);
1067   OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);
1068   OhciSetTDField (EmptTd, TD_DIR_PID, 0);
1069   OhciSetTDField (EmptTd, TD_DELAY_INT, 0);
1070   //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
1071   EmptTd->Word0.DataToggle = 0;
1072   OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);
1073   OhciSetTDField (EmptTd, TD_COND_CODE, 0);
1074   OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);
1075   OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);
1076   OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);
1077   EmptTd->ActualSendLength = 0;
1078   EmptTd->DataBuffer = 0;
1079   EmptTd->NextTDPointer = 0;
1080   OhciLinkTD (HeadTd, EmptTd);
1081   Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;
1082   OhciAttachTDListToED (Ed, HeadTd);
1083 
1084   if (OutputED != NULL) {
1085     *OutputED = Ed;
1086   }
1087   if (OutputTD != NULL) {
1088     *OutputTD = HeadTd;
1089   }
1090 
1091   if (CallBackFunction != NULL) {
1092     Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));
1093     if (Entry == NULL) {
1094       goto FREE_OHCI_TDBUFF;
1095     }
1096 
1097     Entry->DeviceAddress = DeviceAddress;
1098     Entry->EndPointAddress = EndPointAddress;
1099     Entry->Ed = Ed;
1100     Entry->DataTd = HeadTd;
1101     Entry->IsSlowDevice = IsSlowDevice;
1102     Entry->MaxPacketLength = MaxPacketLength;
1103     Entry->PollingInterval = PollingInterval;
1104     Entry->CallBackFunction = CallBackFunction;
1105     Entry->Context = Context;
1106     Entry->IsPeriodic = IsPeriodic;
1107     Entry->UCBuffer = UCBuffer;
1108     Entry->UCBufferMapping = Mapping;
1109     Entry->DataLength = DataLength;
1110     Entry->Toggle = DataToggle;
1111     Entry->NextEntry = NULL;
1112     OhciAddInterruptContextEntry (Ohc, Entry);
1113   }
1114   OhciSetEDField (Ed, ED_SKIP, 0);
1115 
1116   if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {
1117     Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
1118     gBS->Stall (1000);
1119   }
1120 
1121   return EFI_SUCCESS;
1122 
1123 FREE_OHCI_TDBUFF:
1124   while (HeadTd) {
1125     DataTd = HeadTd;
1126     HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
1127     UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
1128   }
1129 
1130 //FREE_OHCI_EDBUFF:
1131   if ((HeadEd != Ed) && HeadEd && Ed) {
1132     while(HeadEd->NextED != (UINT32)(UINTN)Ed) {
1133       HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);
1134     }
1135   HeadEd->NextED = Ed->NextED;
1136     UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
1137   }
1138 
1139 UNMAP_OHCI_XBUFF:
1140   Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
1141 
1142 EXIT:
1143   return Status;
1144 }
1145 
1146 /**
1147 
1148   Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
1149 
1150   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1151   @param  DeviceAddress         Represents the address of the target device on the USB,
1152                                 which is assigned during USB enumeration.
1153   @param  EndPointAddress       The combination of an endpoint number and an endpoint
1154                                 direction of the target USB device. Each endpoint address
1155                                 supports data transfer in one direction except the
1156                                 control endpoint (whose default endpoint address is 0).
1157                                 It is the caller's responsibility to make sure that
1158                                 the EndPointAddress represents an interrupt endpoint.
1159   @param  IsSlowDevice          Indicates whether the target device is slow device
1160                                 or full-speed device.
1161   @param  MaxiumPacketLength    Indicates the maximum packet size the target endpoint
1162                                 is capable of sending or receiving.
1163   @param  IsNewTransfer         If TRUE, an asynchronous interrupt pipe is built between
1164                                 the host and the target interrupt endpoint.
1165                                 If FALSE, the specified asynchronous interrupt pipe
1166                                 is canceled.
1167   @param  DataToggle            A pointer to the data toggle value.  On input, it is valid
1168                                 when IsNewTransfer is TRUE, and it indicates the initial
1169                                 data toggle value the asynchronous interrupt transfer
1170                                 should adopt.
1171                                 On output, it is valid when IsNewTransfer is FALSE,
1172                                 and it is updated to indicate the data toggle value of
1173                                 the subsequent asynchronous interrupt transfer.
1174   @param  PollingInterval       Indicates the interval, in milliseconds, that the
1175                                 asynchronous interrupt transfer is polled.
1176                                 This parameter is required when IsNewTransfer is TRUE.
1177   @param  DataLength            Indicates the length of data to be received at the
1178                                 rate specified by PollingInterval from the target
1179                                 asynchronous interrupt endpoint.  This parameter
1180                                 is only required when IsNewTransfer is TRUE.
1181   @param  CallBackFunction      The Callback function.This function is called at the
1182                                 rate specified by PollingInterval.This parameter is
1183                                 only required when IsNewTransfer is TRUE.
1184   @param  Context               The context that is passed to the CallBackFunction.
1185                                 This is an optional parameter and may be NULL.
1186 
1187   @retval EFI_SUCCESS           The asynchronous interrupt transfer request has been successfully
1188                                 submitted or canceled.
1189   @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1190   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
1191 
1192 **/
1193 
1194 
1195 EFI_STATUS
1196 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)1197 OhciAsyncInterruptTransfer (
1198   IN     EFI_USB_HC_PROTOCOL              *This,
1199   IN     UINT8                            DeviceAddress,
1200   IN     UINT8                            EndPointAddress,
1201   IN     BOOLEAN                          IsSlowDevice,
1202   IN     UINT8                            MaxPacketLength,
1203   IN     BOOLEAN                          IsNewTransfer,
1204   IN OUT UINT8                            *DataToggle        OPTIONAL,
1205   IN     UINTN                            PollingInterval    OPTIONAL,
1206   IN     UINTN                            DataLength         OPTIONAL,
1207   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK  CallBackFunction   OPTIONAL,
1208   IN     VOID                             *Context           OPTIONAL
1209   )
1210 {
1211   EFI_STATUS              Status;
1212   USB_OHCI_HC_DEV         *Ohc;
1213   VOID                    *UCBuffer;
1214 
1215   if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||
1216     (IsNewTransfer && (DataLength == 0 ||
1217     (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {
1218     return EFI_INVALID_PARAMETER;
1219   }
1220 
1221   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1222   if ( IsNewTransfer ) {
1223     UCBuffer = AllocatePool(DataLength);
1224     if (UCBuffer == NULL) {
1225       return EFI_OUT_OF_RESOURCES;
1226     }
1227   } else {
1228     UCBuffer = NULL;
1229   }
1230   Status = OhciInterruptTransfer (
1231              Ohc,
1232              DeviceAddress,
1233              EndPointAddress,
1234              IsSlowDevice,
1235              MaxPacketLength,
1236              IsNewTransfer,
1237              DataToggle,
1238              PollingInterval,
1239              UCBuffer,
1240              DataLength,
1241              CallBackFunction,
1242              Context,
1243              TRUE,
1244              NULL,
1245              NULL
1246              );
1247   if ( IsNewTransfer ) {
1248     if (EFI_ERROR(Status)) {
1249       gBS->FreePool (UCBuffer);
1250     }
1251   }
1252   return Status;
1253 }
1254 
1255 
1256 /**
1257 
1258   Submits synchronous interrupt transfer to an interrupt endpoint
1259   of a USB device.
1260 
1261   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1262   @param  DeviceAddress         Represents the address of the target device on the USB,
1263                                 which is assigned during USB enumeration.
1264   @param  EndPointAddress       The combination of an endpoint number and an endpoint
1265                                 direction of the target USB device. Each endpoint
1266                                 address supports data transfer in one direction
1267                                 except the control endpoint (whose default
1268                                 endpoint address is 0). It is the caller's responsibility
1269                                 to make sure that the EndPointAddress represents
1270                                 an interrupt endpoint.
1271   @param  IsSlowDevice          Indicates whether the target device is slow device
1272                                 or full-speed device.
1273   @param  MaxPacketLength       Indicates the maximum packet size the target endpoint
1274                                 is capable of sending or receiving.
1275   @param  Data                  A pointer to the buffer of data that will be transmitted
1276                                 to USB device or received from USB device.
1277   @param  DataLength            On input, the size, in bytes, of the data buffer specified
1278                                 by Data. On output, the number of bytes transferred.
1279   @param  DataToggle            A pointer to the data toggle value. On input, it indicates
1280                                 the initial data toggle value the synchronous interrupt
1281                                 transfer should adopt;
1282                                 on output, it is updated to indicate the data toggle value
1283                                 of the subsequent synchronous interrupt transfer.
1284   @param  TimeOut               Indicates the maximum time, in microseconds, which the
1285                                 transfer is allowed to complete.
1286   @param  TransferResult        A pointer to the detailed result information from
1287                                 the synchronous interrupt transfer.
1288 
1289   @retval EFI_UNSUPPORTED       This interface not available.
1290   @retval EFI_INVALID_PARAMETER Parameters not follow spec
1291 
1292 **/
1293 
1294 
1295 EFI_STATUS
1296 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)1297 OhciSyncInterruptTransfer (
1298   IN     EFI_USB_HC_PROTOCOL  *This,
1299   IN     UINT8                DeviceAddress,
1300   IN     UINT8                EndPointAddress,
1301   IN     BOOLEAN              IsSlowDevice,
1302   IN     UINT8                MaxPacketLength,
1303   IN OUT VOID                 *Data,
1304   IN OUT UINTN                *DataLength,
1305   IN OUT UINT8                *DataToggle,
1306   IN     UINTN                TimeOut,
1307   OUT    UINT32               *TransferResult
1308   )
1309 {
1310   USB_OHCI_HC_DEV         *Ohc;
1311   EFI_STATUS              Status;
1312   ED_DESCRIPTOR           *Ed;
1313   TD_DESCRIPTOR           *HeadTd;
1314   OHCI_ED_RESULT          EdResult;
1315   VOID                    *UCBuffer;
1316 
1317   if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||
1318       (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||
1319       DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {
1320     return EFI_INVALID_PARAMETER;
1321   }
1322 
1323   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1324   UCBuffer = AllocatePool (*DataLength);
1325   if (UCBuffer == NULL) {
1326     return EFI_OUT_OF_RESOURCES;
1327   }
1328   Status = OhciInterruptTransfer (
1329              Ohc,
1330              DeviceAddress,
1331              EndPointAddress,
1332              IsSlowDevice,
1333              MaxPacketLength,
1334              TRUE,
1335              DataToggle,
1336              1,
1337              UCBuffer,
1338              *DataLength,
1339              NULL,
1340              NULL,
1341              FALSE,
1342              &Ed,
1343              &HeadTd
1344              );
1345 
1346   if (!EFI_ERROR (Status)) {
1347     Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
1348     while (Status == EFI_NOT_READY && TimeOut > 0) {
1349       gBS->Stall (1000);
1350       TimeOut--;
1351       Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
1352     }
1353 
1354     *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
1355   }
1356   CopyMem(Data, UCBuffer, *DataLength);
1357   Status = OhciInterruptTransfer (
1358              Ohc,
1359              DeviceAddress,
1360              EndPointAddress,
1361              IsSlowDevice,
1362              MaxPacketLength,
1363              FALSE,
1364              DataToggle,
1365              0,
1366              NULL,
1367              0,
1368              NULL,
1369              NULL,
1370              FALSE,
1371              NULL,
1372              NULL
1373              );
1374 
1375   return Status;
1376 }
1377 /**
1378 
1379   Submits isochronous transfer to a target USB device.
1380 
1381   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1382   @param  DeviceAddress         Represents the address of the target device on the USB,
1383                                 which is assigned during USB enumeration.
1384   @param  EndPointAddress       End point address
1385   @param  MaximumPacketLength   Indicates the maximum packet size that the
1386                                 default control transfer endpoint is capable of
1387                                 sending or receiving.
1388   @param  Data                  A pointer to the buffer of data that will be transmitted
1389                                 to USB device or received from USB device.
1390   @param  DataLength            Indicates the size, in bytes, of the data buffer
1391                                 specified by Data.
1392   @param  TransferResult        A pointer to the detailed result information generated
1393                                 by this control transfer.
1394 
1395   @retval EFI_UNSUPPORTED       This interface not available
1396   @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
1397 
1398 **/
1399 
1400 
1401 EFI_STATUS
1402 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)1403 OhciIsochronousTransfer (
1404   IN     EFI_USB_HC_PROTOCOL  *This,
1405   IN     UINT8                DeviceAddress,
1406   IN     UINT8                EndPointAddress,
1407   IN     UINT8                MaximumPacketLength,
1408   IN OUT VOID                 *Data,
1409   IN OUT UINTN                DataLength,
1410   OUT    UINT32               *TransferResult
1411   )
1412 {
1413   if (Data == NULL || DataLength == 0 || TransferResult == NULL) {
1414     return EFI_INVALID_PARAMETER;
1415   }
1416 
1417   return EFI_UNSUPPORTED;
1418 }
1419 
1420 /**
1421 
1422   Submits Async isochronous transfer to a target USB device.
1423 
1424   @param  his                   A pointer to the EFI_USB_HC_PROTOCOL instance.
1425   @param  DeviceAddress         Represents the address of the target device on the USB,
1426                                 which is assigned during USB enumeration.
1427   @param  EndPointAddress       End point address
1428   @param  MaximumPacketLength   Indicates the maximum packet size that the
1429                                 default control transfer endpoint is capable of
1430                                 sending or receiving.
1431   @param  Data                  A pointer to the buffer of data that will be transmitted
1432                                 to USB device or received from USB device.
1433   @param  IsochronousCallBack   When the transfer complete, the call back function will be called
1434   @param  Context               Pass to the call back function as parameter
1435 
1436   @retval EFI_UNSUPPORTED       This interface not available
1437   @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
1438 
1439 **/
1440 
1441 EFI_STATUS
1442 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)1443 OhciAsyncIsochronousTransfer (
1444   IN     EFI_USB_HC_PROTOCOL                *This,
1445   IN     UINT8                              DeviceAddress,
1446   IN     UINT8                              EndPointAddress,
1447   IN     UINT8                              MaximumPacketLength,
1448   IN OUT VOID                               *Data,
1449   IN OUT UINTN                              DataLength,
1450   IN     EFI_ASYNC_USB_TRANSFER_CALLBACK    IsochronousCallBack,
1451   IN     VOID                               *Context OPTIONAL
1452   )
1453 {
1454 
1455   if (Data == NULL || DataLength == 0) {
1456     return EFI_INVALID_PARAMETER;
1457   }
1458 
1459   return EFI_UNSUPPORTED;
1460 }
1461 
1462 /**
1463 
1464   Retrieves the number of root hub ports.
1465 
1466   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1467   @param  NumOfPorts            A pointer to the number of the root hub ports.
1468 
1469   @retval EFI_SUCCESS           The port number was retrieved successfully.
1470 **/
1471 EFI_STATUS
1472 EFIAPI
OhciGetRootHubNumOfPorts(IN EFI_USB_HC_PROTOCOL * This,OUT UINT8 * NumOfPorts)1473 OhciGetRootHubNumOfPorts (
1474   IN  EFI_USB_HC_PROTOCOL  *This,
1475   OUT UINT8                *NumOfPorts
1476   )
1477 {
1478   USB_OHCI_HC_DEV  *Ohc;
1479   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1480 
1481   if (NumOfPorts == NULL) {
1482     return EFI_INVALID_PARAMETER;
1483   }
1484 
1485   *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
1486 
1487   return EFI_SUCCESS;
1488 }
1489 /**
1490 
1491   Retrieves the current status of a USB root hub port.
1492 
1493   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
1494   @param  PortNumber            Specifies the root hub port from which the status
1495                                 is to be retrieved.  This value is zero-based. For example,
1496                                 if a root hub has two ports, then the first port is numbered 0,
1497                                 and the second port is numbered 1.
1498   @param  PortStatus            A pointer to the current port status bits and
1499                                 port status change bits.
1500 
1501   @retval EFI_SUCCESS           The status of the USB root hub port specified by PortNumber
1502                                 was returned in PortStatus.
1503   @retval EFI_INVALID_PARAMETER Port number not valid
1504 **/
1505 
1506 
1507 EFI_STATUS
1508 EFIAPI
OhciGetRootHubPortStatus(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 PortNumber,OUT EFI_USB_PORT_STATUS * PortStatus)1509 OhciGetRootHubPortStatus (
1510   IN  EFI_USB_HC_PROTOCOL  *This,
1511   IN  UINT8                PortNumber,
1512   OUT EFI_USB_PORT_STATUS  *PortStatus
1513   )
1514 {
1515   USB_OHCI_HC_DEV  *Ohc;
1516   UINT8            NumOfPorts;
1517 
1518   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1519 
1520   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1521   if (PortNumber >= NumOfPorts) {
1522     return EFI_INVALID_PARAMETER;
1523   }
1524   PortStatus->PortStatus = 0;
1525   PortStatus->PortChangeStatus = 0;
1526 
1527   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
1528     PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
1529   }
1530   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
1531     PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
1532   }
1533   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
1534     PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
1535   }
1536   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
1537     PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
1538   }
1539   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
1540     PortStatus->PortStatus |= USB_PORT_STAT_RESET;
1541   }
1542   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
1543     PortStatus->PortStatus |= USB_PORT_STAT_POWER;
1544   }
1545   if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
1546     PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
1547   }
1548   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
1549     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
1550   }
1551   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
1552     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
1553   }
1554   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
1555     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
1556   }
1557   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
1558     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
1559   }
1560   if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
1561     PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
1562   }
1563 
1564   return EFI_SUCCESS;
1565 }
1566 /**
1567 
1568   Sets a feature for the specified root hub port.
1569 
1570   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL.
1571   @param  PortNumber            Specifies the root hub port whose feature
1572                                 is requested to be set.
1573   @param  PortFeature           Indicates the feature selector associated
1574                                 with the feature set request.
1575 
1576   @retval EFI_SUCCESS           The feature specified by PortFeature was set for the
1577                                 USB root hub port specified by PortNumber.
1578   @retval EFI_DEVICE_ERROR      Set feature failed because of hardware issue
1579   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1580 **/
1581 EFI_STATUS
1582 EFIAPI
OhciSetRootHubPortFeature(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)1583 OhciSetRootHubPortFeature (
1584   IN EFI_USB_HC_PROTOCOL   *This,
1585   IN UINT8                 PortNumber,
1586   IN EFI_USB_PORT_FEATURE  PortFeature
1587   )
1588 {
1589   USB_OHCI_HC_DEV         *Ohc;
1590   EFI_STATUS              Status;
1591   UINT8                   NumOfPorts;
1592   UINTN                   RetryTimes;
1593 
1594   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1595   if (PortNumber >= NumOfPorts) {
1596     return EFI_INVALID_PARAMETER;
1597   }
1598 
1599   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1600 
1601   Status = EFI_SUCCESS;
1602 
1603 
1604   switch (PortFeature) {
1605     case EfiUsbPortPower:
1606       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
1607 
1608       //
1609       // Verify the state
1610       //
1611       RetryTimes = 0;
1612       do {
1613         gBS->Stall (1000);
1614         RetryTimes++;
1615       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
1616                RetryTimes < MAX_RETRY_TIMES);
1617 
1618       if (RetryTimes >= MAX_RETRY_TIMES) {
1619         return EFI_DEVICE_ERROR;
1620       }
1621       break;
1622 
1623     case EfiUsbPortReset:
1624       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
1625 
1626       //
1627       // Verify the state
1628       //
1629       RetryTimes = 0;
1630       do {
1631         gBS->Stall (1000);
1632         RetryTimes++;
1633       } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
1634                 OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
1635                RetryTimes < MAX_RETRY_TIMES);
1636 
1637       if (RetryTimes >= MAX_RETRY_TIMES) {
1638         return EFI_DEVICE_ERROR;
1639       }
1640 
1641       OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
1642       break;
1643 
1644     case EfiUsbPortEnable:
1645       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
1646 
1647       //
1648       // Verify the state
1649       //
1650       RetryTimes = 0;
1651       do {
1652         gBS->Stall (1000);
1653         RetryTimes++;
1654       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
1655                RetryTimes < MAX_RETRY_TIMES);
1656 
1657       if (RetryTimes >= MAX_RETRY_TIMES) {
1658         return EFI_DEVICE_ERROR;
1659       }
1660       break;
1661 
1662 
1663     case EfiUsbPortSuspend:
1664       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
1665 
1666       //
1667       // Verify the state
1668       //
1669       RetryTimes = 0;
1670       do {
1671         gBS->Stall (1000);
1672         RetryTimes++;
1673       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
1674                RetryTimes < MAX_RETRY_TIMES);
1675 
1676       if (RetryTimes >= MAX_RETRY_TIMES) {
1677         return EFI_DEVICE_ERROR;
1678       }
1679       break;
1680 
1681     default:
1682       return EFI_INVALID_PARAMETER;
1683   }
1684 
1685   return Status;
1686 }
1687 
1688 /**
1689 
1690   Clears a feature for the specified root hub port.
1691 
1692   @param  This                  A pointer to the EFI_USB_HC_PROTOCOL instance.
1693   @param  PortNumber            Specifies the root hub port whose feature
1694                                 is requested to be cleared.
1695   @param  PortFeature           Indicates the feature selector associated with the
1696                                 feature clear request.
1697 
1698   @retval EFI_SUCCESS           The feature specified by PortFeature was cleared for the
1699                                 USB root hub port specified by PortNumber.
1700   @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1701   @retval EFI_DEVICE_ERROR      Some error happened when clearing feature
1702 **/
1703 EFI_STATUS
1704 EFIAPI
OhciClearRootHubPortFeature(IN EFI_USB_HC_PROTOCOL * This,IN UINT8 PortNumber,IN EFI_USB_PORT_FEATURE PortFeature)1705 OhciClearRootHubPortFeature (
1706   IN EFI_USB_HC_PROTOCOL   *This,
1707   IN UINT8                 PortNumber,
1708   IN EFI_USB_PORT_FEATURE  PortFeature
1709   )
1710 {
1711   USB_OHCI_HC_DEV         *Ohc;
1712   EFI_STATUS              Status;
1713   UINT8                   NumOfPorts;
1714   UINTN                   RetryTimes;
1715 
1716 
1717   OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1718   if (PortNumber >= NumOfPorts) {
1719     return EFI_INVALID_PARAMETER;
1720   }
1721 
1722   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1723 
1724   Status = EFI_SUCCESS;
1725 
1726   switch (PortFeature) {
1727     case EfiUsbPortEnable:
1728       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
1729 
1730       //
1731       // Verify the state
1732       //
1733       RetryTimes = 0;
1734       do {
1735         gBS->Stall (1000);
1736         RetryTimes++;
1737       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
1738                RetryTimes < MAX_RETRY_TIMES);
1739 
1740       if (RetryTimes >= MAX_RETRY_TIMES) {
1741         return EFI_DEVICE_ERROR;
1742       }
1743       break;
1744 
1745     case EfiUsbPortSuspend:
1746       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
1747 
1748       //
1749       // Verify the state
1750       //
1751       RetryTimes = 0;
1752       do {
1753         gBS->Stall (1000);
1754         RetryTimes++;
1755       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
1756                RetryTimes < MAX_RETRY_TIMES);
1757 
1758       if (RetryTimes >= MAX_RETRY_TIMES) {
1759         return EFI_DEVICE_ERROR;
1760       }
1761       break;
1762 
1763     case EfiUsbPortReset:
1764       break;
1765 
1766     case EfiUsbPortPower:
1767       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
1768 
1769       //
1770       // Verify the state
1771       //
1772       RetryTimes = 0;
1773       do {
1774         gBS->Stall (1000);
1775         RetryTimes++;
1776       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
1777                RetryTimes < MAX_RETRY_TIMES);
1778 
1779       if (RetryTimes >= MAX_RETRY_TIMES) {
1780         return EFI_DEVICE_ERROR;
1781       }
1782       break;
1783 
1784     case EfiUsbPortConnectChange:
1785       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
1786 
1787       //
1788       // Verify the state
1789       //
1790       RetryTimes = 0;
1791       do {
1792         gBS->Stall (1000);
1793         RetryTimes++;
1794       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
1795                RetryTimes < MAX_RETRY_TIMES);
1796 
1797       if (RetryTimes >= MAX_RETRY_TIMES) {
1798         return EFI_DEVICE_ERROR;
1799       }
1800       break;
1801 
1802     case EfiUsbPortResetChange:
1803       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
1804 
1805       //
1806       // Verify the state
1807       //
1808       RetryTimes = 0;
1809       do {
1810         gBS->Stall (1000);
1811         RetryTimes++;
1812       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
1813                RetryTimes < MAX_RETRY_TIMES);
1814 
1815       if (RetryTimes >= MAX_RETRY_TIMES) {
1816         return EFI_DEVICE_ERROR;
1817       }
1818       break;
1819 
1820 
1821     case EfiUsbPortEnableChange:
1822       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
1823 
1824       //
1825       // Verify the state
1826       //
1827       RetryTimes = 0;
1828       do {
1829         gBS->Stall (1000);
1830         RetryTimes++;
1831       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
1832                RetryTimes < MAX_RETRY_TIMES);
1833 
1834       if (RetryTimes >= MAX_RETRY_TIMES) {
1835         return EFI_DEVICE_ERROR;
1836       }
1837       break;
1838 
1839     case EfiUsbPortSuspendChange:
1840       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
1841 
1842       //
1843       // Verify the state
1844       //
1845       RetryTimes = 0;
1846       do {
1847         gBS->Stall (1000);
1848         RetryTimes++;
1849       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
1850                RetryTimes < MAX_RETRY_TIMES);
1851 
1852       if (RetryTimes >= MAX_RETRY_TIMES) {
1853         return EFI_DEVICE_ERROR;
1854       }
1855       break;
1856 
1857     case EfiUsbPortOverCurrentChange:
1858       Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
1859 
1860       //
1861       // Verify the state
1862       //
1863       RetryTimes = 0;
1864       do {
1865         gBS->Stall (1000);
1866         RetryTimes++;
1867       } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
1868                RetryTimes < MAX_RETRY_TIMES);
1869 
1870       if (RetryTimes >= MAX_RETRY_TIMES) {
1871         return EFI_DEVICE_ERROR;
1872       }
1873       break;
1874 
1875     default:
1876       return EFI_INVALID_PARAMETER;
1877   }
1878 
1879   return Status;
1880 }
1881 
1882 EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
1883   OHCIDriverBindingSupported,
1884   OHCIDriverBindingStart,
1885   OHCIDriverBindingStop,
1886   0x10,
1887   NULL,
1888   NULL
1889 };
1890 
1891 
1892 /**
1893   Entry point for EFI drivers.
1894 
1895   @param  ImageHandle           EFI_HANDLE.
1896   @param  SystemTable           EFI_SYSTEM_TABLE.
1897 
1898   @retval EFI_SUCCESS           Driver is successfully loaded.
1899   @return Others                Failed.
1900 
1901 **/
1902 EFI_STATUS
1903 EFIAPI
OHCIDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1904 OHCIDriverEntryPoint (
1905   IN EFI_HANDLE          ImageHandle,
1906   IN EFI_SYSTEM_TABLE    *SystemTable
1907   )
1908 {
1909   return EfiLibInstallDriverBindingComponentName2 (
1910            ImageHandle,
1911            SystemTable,
1912            &gOhciDriverBinding,
1913            ImageHandle,
1914            &gOhciComponentName,
1915            &gOhciComponentName2
1916            );
1917 }
1918 
1919 
1920 /**
1921   Test to see if this driver supports ControllerHandle. Any
1922   ControllerHandle that has UsbHcProtocol installed will be supported.
1923 
1924   @param  This                 Protocol instance pointer.
1925   @param  Controller           Handle of device to test.
1926   @param  RemainingDevicePath  Not used.
1927 
1928   @return EFI_SUCCESS          This driver supports this device.
1929   @return EFI_UNSUPPORTED      This driver does not support this device.
1930 
1931 **/
1932 EFI_STATUS
1933 EFIAPI
OHCIDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)1934 OHCIDriverBindingSupported (
1935   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1936   IN EFI_HANDLE                   Controller,
1937   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
1938   )
1939 {
1940   EFI_STATUS              Status;
1941   EFI_PCI_IO_PROTOCOL     *PciIo;
1942   USB_CLASSC              UsbClassCReg;
1943   //
1944   // Test whether there is PCI IO Protocol attached on the controller handle.
1945   //
1946   Status = gBS->OpenProtocol (
1947                   Controller,
1948                   &gEfiPciIoProtocolGuid,
1949                   (VOID **) &PciIo,
1950                   This->DriverBindingHandle,
1951                   Controller,
1952                   EFI_OPEN_PROTOCOL_BY_DRIVER
1953                   );
1954 
1955   if (EFI_ERROR (Status)) {
1956     return EFI_UNSUPPORTED;
1957   }
1958 
1959   Status = PciIo->Pci.Read (
1960                         PciIo,
1961                         EfiPciIoWidthUint8,
1962                         PCI_CLASSCODE_OFFSET,
1963                         sizeof (USB_CLASSC) / sizeof (UINT8),
1964                         &UsbClassCReg
1965                         );
1966 
1967   if (EFI_ERROR (Status)) {
1968     Status = EFI_UNSUPPORTED;
1969     goto ON_EXIT;
1970   }
1971   //
1972   // Test whether the controller belongs to OHCI type
1973   //
1974   if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
1975       (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
1976       (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
1977       ) {
1978 
1979     Status = EFI_UNSUPPORTED;
1980   }
1981 ON_EXIT:
1982   gBS->CloseProtocol (
1983          Controller,
1984          &gEfiPciIoProtocolGuid,
1985          This->DriverBindingHandle,
1986          Controller
1987          );
1988 
1989   return Status;
1990 
1991 }
1992 
1993 /**
1994 
1995   Allocate and initialize the empty OHCI device.
1996 
1997   @param  PciIo                  The PCIIO to use.
1998   @param  OriginalPciAttributes  The original PCI attributes.
1999 
2000   @return Allocated OHCI device  If err, return NULL.
2001 
2002 **/
2003 
2004 USB_OHCI_HC_DEV *
OhciAllocateDev(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT64 OriginalPciAttributes)2005 OhciAllocateDev (
2006   IN EFI_PCI_IO_PROTOCOL  *PciIo,
2007   IN UINT64               OriginalPciAttributes
2008   )
2009 {
2010   USB_OHCI_HC_DEV         *Ohc;
2011   EFI_STATUS              Status;
2012   VOID                    *Buf;
2013   EFI_PHYSICAL_ADDRESS    PhyAddr;
2014   VOID                    *Map;
2015   UINTN                   Pages;
2016   UINTN                   Bytes;
2017 
2018   Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));
2019   if (Ohc == NULL) {
2020     return NULL;
2021   }
2022 
2023   Ohc->Signature                      = USB_OHCI_HC_DEV_SIGNATURE;
2024   Ohc->PciIo                          = PciIo;
2025 
2026   Ohc->UsbHc.Reset                    = OhciReset;
2027   Ohc->UsbHc.GetState                 = OhciGetState;
2028   Ohc->UsbHc.SetState                 = OhciSetState;
2029   Ohc->UsbHc.ControlTransfer          = OhciControlTransfer;
2030   Ohc->UsbHc.BulkTransfer             = OhciBulkTransfer;
2031   Ohc->UsbHc.AsyncInterruptTransfer   = OhciAsyncInterruptTransfer;
2032   Ohc->UsbHc.SyncInterruptTransfer    = OhciSyncInterruptTransfer;
2033   Ohc->UsbHc.IsochronousTransfer      = OhciIsochronousTransfer;
2034   Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;
2035   Ohc->UsbHc.GetRootHubPortNumber     = OhciGetRootHubNumOfPorts;
2036   Ohc->UsbHc.GetRootHubPortStatus     = OhciGetRootHubPortStatus;
2037   Ohc->UsbHc.SetRootHubPortFeature    = OhciSetRootHubPortFeature;
2038   Ohc->UsbHc.ClearRootHubPortFeature  = OhciClearRootHubPortFeature;
2039   Ohc->UsbHc.MajorRevision            = 0x1;
2040   Ohc->UsbHc.MinorRevision            = 0x1;
2041 
2042   Ohc->OriginalPciAttributes = OriginalPciAttributes;
2043 
2044   Ohc->HccaMemoryBlock = NULL;
2045   Ohc->HccaMemoryMapping   = NULL;
2046   Ohc->HccaMemoryBuf = NULL;
2047   Ohc->HccaMemoryPages = 0;
2048   Ohc->InterruptContextList = NULL;
2049   Ohc->ControllerNameTable = NULL;
2050   Ohc->HouseKeeperTimer = NULL;
2051 
2052   Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);
2053   if(Ohc->MemPool == NULL) {
2054     goto FREE_DEV_BUFFER;
2055   }
2056 
2057   Bytes = 4096;
2058   Pages = EFI_SIZE_TO_PAGES (Bytes);
2059 
2060   Status = PciIo->AllocateBuffer (
2061                     PciIo,
2062                     AllocateAnyPages,
2063                     EfiBootServicesData,
2064                     Pages,
2065                     &Buf,
2066                     0
2067                     );
2068 
2069   if (EFI_ERROR (Status)) {
2070     goto FREE_MEM_POOL;
2071   }
2072 
2073   Status = PciIo->Map (
2074                     PciIo,
2075                     EfiPciIoOperationBusMasterCommonBuffer,
2076                     Buf,
2077                     &Bytes,
2078                     &PhyAddr,
2079                     &Map
2080                     );
2081 
2082   if (EFI_ERROR (Status) || (Bytes != 4096)) {
2083     goto FREE_MEM_PAGE;
2084   }
2085 
2086   Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;
2087   Ohc->HccaMemoryMapping = Map;
2088   Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;
2089   Ohc->HccaMemoryPages = Pages;
2090 
2091   return Ohc;
2092 
2093 FREE_MEM_PAGE:
2094   PciIo->FreeBuffer (PciIo, Pages, Buf);
2095 FREE_MEM_POOL:
2096   UsbHcFreeMemPool (Ohc->MemPool);
2097 FREE_DEV_BUFFER:
2098   FreePool(Ohc);
2099 
2100   return NULL;
2101 }
2102 /**
2103 
2104   Free the OHCI device and release its associated resources.
2105 
2106   @param  Ohc                   The OHCI device to release.
2107 
2108 **/
2109 VOID
OhciFreeDev(IN USB_OHCI_HC_DEV * Ohc)2110 OhciFreeDev (
2111   IN USB_OHCI_HC_DEV      *Ohc
2112   )
2113 {
2114   OhciFreeFixedIntMemory (Ohc);
2115 
2116   if (Ohc->HouseKeeperTimer != NULL) {
2117     gBS->CloseEvent (Ohc->HouseKeeperTimer);
2118   }
2119 
2120   if (Ohc->ExitBootServiceEvent != NULL) {
2121     gBS->CloseEvent (Ohc->ExitBootServiceEvent);
2122   }
2123 
2124   if (Ohc->MemPool != NULL) {
2125     UsbHcFreeMemPool (Ohc->MemPool);
2126   }
2127 
2128   if (Ohc->HccaMemoryMapping != NULL ) {
2129     Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);
2130   }
2131 
2132   if (Ohc->ControllerNameTable != NULL) {
2133     FreeUnicodeStringTable (Ohc->ControllerNameTable);
2134   }
2135 
2136   FreePool (Ohc);
2137 }
2138 /**
2139 
2140   Uninstall all Ohci Interface.
2141 
2142   @param  Controller            Controller handle.
2143   @param  This                  Protocol instance pointer.
2144 
2145 **/
2146 VOID
OhciCleanDevUp(IN EFI_HANDLE Controller,IN EFI_USB_HC_PROTOCOL * This)2147 OhciCleanDevUp (
2148   IN  EFI_HANDLE           Controller,
2149   IN  EFI_USB_HC_PROTOCOL  *This
2150   )
2151 {
2152   USB_OHCI_HC_DEV  *Ohc;
2153 
2154   //
2155   // Retrieve private context structure
2156   //
2157   Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
2158 
2159   //
2160   // Uninstall the USB_HC and USB_HC2 protocol
2161   //
2162   gBS->UninstallProtocolInterface (
2163          Controller,
2164          &gEfiUsbHcProtocolGuid,
2165          &Ohc->UsbHc
2166          );
2167 
2168   //
2169   // Cancel the timer event
2170   //
2171   gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);
2172 
2173   //
2174   // Stop the host controller
2175   //
2176   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
2177   This->Reset (This, EFI_USB_HC_RESET_GLOBAL);
2178   This->SetState (This, EfiUsbHcStateHalt);
2179 
2180   //
2181   // Free resources
2182   //
2183   OhciFreeDynamicIntMemory (Ohc);
2184 
2185   //
2186   // Restore original PCI attributes
2187   //
2188   Ohc->PciIo->Attributes (
2189                 Ohc->PciIo,
2190                 EfiPciIoAttributeOperationSet,
2191                 Ohc->OriginalPciAttributes,
2192                 NULL
2193                 );
2194 
2195   //
2196   // Free the private context structure
2197   //
2198   OhciFreeDev (Ohc);
2199 }
2200 
2201 /**
2202 
2203   One notified function to stop the Host Controller when gBS->ExitBootServices() called.
2204 
2205   @param  Event                 Pointer to this event
2206   @param  Context               Event handler private data
2207 **/
2208 VOID
2209 EFIAPI
OhcExitBootService(EFI_EVENT Event,VOID * Context)2210 OhcExitBootService (
2211   EFI_EVENT                      Event,
2212   VOID                           *Context
2213   )
2214 {
2215   USB_OHCI_HC_DEV           *Ohc;
2216   EFI_USB_HC_PROTOCOL       *UsbHc;
2217   Ohc = (USB_OHCI_HC_DEV *) Context;
2218 
2219   UsbHc = &Ohc->UsbHc;
2220   //
2221   // Stop the Host Controller
2222   //
2223   //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
2224   OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
2225   UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);
2226   UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);
2227 
2228   return;
2229 }
2230 
2231 
2232 /**
2233   Starting the Usb OHCI Driver.
2234 
2235   @param  This                  Protocol instance pointer.
2236   @param  Controller            Handle of device to test.
2237   @param  RemainingDevicePath   Not used.
2238 
2239   @retval EFI_SUCCESS           This driver supports this device.
2240   @retval EFI_UNSUPPORTED       This driver does not support this device.
2241   @retval EFI_DEVICE_ERROR      This driver cannot be started due to device Error.
2242                                 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
2243 
2244 **/
2245 EFI_STATUS
2246 EFIAPI
OHCIDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)2247 OHCIDriverBindingStart (
2248   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
2249   IN EFI_HANDLE                   Controller,
2250   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
2251   )
2252 {
2253   EFI_STATUS              Status;
2254   EFI_PCI_IO_PROTOCOL     *PciIo;
2255   USB_OHCI_HC_DEV         *Ohc;
2256   UINT64                  Supports;
2257   UINT64                  OriginalPciAttributes;
2258   BOOLEAN                 PciAttributesSaved;
2259 
2260   //
2261   // Open PCIIO, then enable the HC device and turn off emulation
2262   //
2263   Ohc = NULL;
2264   Status = gBS->OpenProtocol (
2265                   Controller,
2266                   &gEfiPciIoProtocolGuid,
2267                   (VOID **) &PciIo,
2268                   This->DriverBindingHandle,
2269                   Controller,
2270                   EFI_OPEN_PROTOCOL_BY_DRIVER
2271                   );
2272 
2273   if (EFI_ERROR (Status)) {
2274     return Status;
2275   }
2276 
2277   PciAttributesSaved = FALSE;
2278   //
2279   // Save original PCI attributes
2280   //
2281   Status = PciIo->Attributes (
2282                     PciIo,
2283                     EfiPciIoAttributeOperationGet,
2284                     0,
2285                     &OriginalPciAttributes
2286                     );
2287 
2288   if (EFI_ERROR (Status)) {
2289     goto CLOSE_PCIIO;
2290   }
2291   PciAttributesSaved = TRUE;
2292 
2293   //
2294   // Robustnesss improvement such as for UoL
2295   // Default is not required.
2296   //
2297   //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
2298   //  OhciTurnOffUsbEmulation (PciIo);
2299   //}
2300 
2301   Status = PciIo->Attributes (
2302                     PciIo,
2303                     EfiPciIoAttributeOperationSupported,
2304                     0,
2305                     &Supports
2306                     );
2307   if (!EFI_ERROR (Status)) {
2308     Supports &= EFI_PCI_DEVICE_ENABLE;
2309     Status = PciIo->Attributes (
2310                       PciIo,
2311                       EfiPciIoAttributeOperationEnable,
2312                       Supports,
2313                       NULL
2314                       );
2315   }
2316 
2317   if (EFI_ERROR (Status)) {
2318     goto CLOSE_PCIIO;
2319   }
2320   //
2321   //Allocate memory for OHC private data structure
2322   //
2323   Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);
2324   if (Ohc == NULL){
2325     Status = EFI_OUT_OF_RESOURCES;
2326     goto CLOSE_PCIIO;
2327   }
2328 
2329   //Status = OhciInitializeInterruptList ( Uhc );
2330   //if (EFI_ERROR (Status)) {
2331   //  goto FREE_OHC;
2332   //}
2333 
2334   //
2335   // Set 0.01 s timer
2336   //
2337   Status = gBS->CreateEvent (
2338                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
2339                   TPL_NOTIFY,
2340                   OhciHouseKeeper,
2341                   Ohc,
2342                   &Ohc->HouseKeeperTimer
2343                   );
2344   if (EFI_ERROR (Status)) {
2345     goto FREE_OHC;
2346   }
2347 
2348   Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);
2349   if (EFI_ERROR (Status)) {
2350     goto FREE_OHC;
2351   }
2352 
2353   //
2354   //Install Host Controller Protocol
2355   //
2356   Status = gBS->InstallProtocolInterface (
2357                   &Controller,
2358                   &gEfiUsbHcProtocolGuid,
2359                   EFI_NATIVE_INTERFACE,
2360                   &Ohc->UsbHc
2361                   );
2362   if (EFI_ERROR (Status)) {
2363     DEBUG ((EFI_D_INFO, "Install protocol error"));
2364     goto FREE_OHC;
2365   }
2366   //
2367   // Create event to stop the HC when exit boot service.
2368   //
2369   Status = gBS->CreateEventEx (
2370                   EVT_NOTIFY_SIGNAL,
2371                   TPL_NOTIFY,
2372                   OhcExitBootService,
2373                   Ohc,
2374                   &gEfiEventExitBootServicesGuid,
2375                   &Ohc->ExitBootServiceEvent
2376                   );
2377   if (EFI_ERROR (Status)) {
2378     DEBUG ((EFI_D_INFO, "Create exit boot event error"));
2379     goto UNINSTALL_USBHC;
2380   }
2381   AddUnicodeString2 (
2382     "eng",
2383     gOhciComponentName.SupportedLanguages,
2384     &Ohc->ControllerNameTable,
2385     L"Usb Universal Host Controller",
2386     TRUE
2387     );
2388   AddUnicodeString2 (
2389     "en",
2390     gOhciComponentName2.SupportedLanguages,
2391     &Ohc->ControllerNameTable,
2392     L"Usb Universal Host Controller",
2393     FALSE
2394     );
2395 
2396   return EFI_SUCCESS;
2397 
2398 UNINSTALL_USBHC:
2399   gBS->UninstallMultipleProtocolInterfaces (
2400          Controller,
2401          &gEfiUsbHcProtocolGuid,
2402          &Ohc->UsbHc,
2403          NULL
2404          );
2405 
2406 FREE_OHC:
2407   OhciFreeDev (Ohc);
2408 
2409 CLOSE_PCIIO:
2410   if (PciAttributesSaved) {
2411   //
2412   // Restore original PCI attributes
2413   //
2414     PciIo->Attributes (
2415              PciIo,
2416              EfiPciIoAttributeOperationSet,
2417              OriginalPciAttributes,
2418              NULL
2419              );
2420   }
2421 
2422   gBS->CloseProtocol (
2423          Controller,
2424          &gEfiPciIoProtocolGuid,
2425          This->DriverBindingHandle,
2426          Controller
2427          );
2428   return Status;
2429 }
2430 
2431 /**
2432   Stop this driver on ControllerHandle. Support stopping any child handles
2433   created by this driver.
2434 
2435   @param  This                  Protocol instance pointer.
2436   @param  Controller            Handle of device to stop driver on.
2437   @param  NumberOfChildren      Number of Children in the ChildHandleBuffer.
2438   @param  ChildHandleBuffer     List of handles for the children we need to stop.
2439 
2440   @return EFI_SUCCESS
2441   @return others
2442 
2443 **/
2444 EFI_STATUS
2445 EFIAPI
OHCIDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)2446 OHCIDriverBindingStop (
2447   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
2448   IN EFI_HANDLE                   Controller,
2449   IN UINTN                        NumberOfChildren,
2450   IN EFI_HANDLE                   *ChildHandleBuffer
2451   )
2452 {
2453   EFI_STATUS           Status;
2454   EFI_USB_HC_PROTOCOL  *UsbHc;
2455 
2456   Status = gBS->OpenProtocol (
2457                   Controller,
2458                   &gEfiUsbHcProtocolGuid,
2459                   (VOID **)&UsbHc,
2460                   This->DriverBindingHandle,
2461                   Controller,
2462                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2463                   );
2464   if (EFI_ERROR (Status)) {
2465     return Status;
2466   }
2467 
2468   OhciCleanDevUp(Controller, UsbHc);
2469 
2470   gBS->CloseProtocol (
2471          Controller,
2472          &gEfiPciIoProtocolGuid,
2473          This->DriverBindingHandle,
2474          Controller
2475          );
2476   return EFI_SUCCESS;
2477 }
2478 
2479 
2480