2 This file contains the implementation of Usb Hc Protocol.
4 Copyright (c) 2013-2015 Intel Corporation.
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
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.
20 Provides software reset for the USB host controller.
22 @param This This EFI_USB_HC_PROTOCOL instance.
23 @param Attributes A bit mask of the reset operation to perform.
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.
35 IN EFI_USB_HC_PROTOCOL
*This
,
43 UINT32 PowerOnGoodTime
;
47 if ((Attributes
& ~(EFI_USB_HC_RESET_GLOBAL
| EFI_USB_HC_RESET_HOST_CONTROLLER
)) != 0) {
48 return EFI_INVALID_PARAMETER
;
52 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
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
;
60 gBS
->Stall (50 * 1000);
62 // Wait for host controller reset.
66 gBS
->Stall (1 * 1000);
67 Data32
= OhciGetOperationalReg (Ohc
->PciIo
, HC_COMMAND_STATUS
);
68 if (EFI_ERROR (Status
)) {
69 return EFI_DEVICE_ERROR
;
71 if ((Data32
& HC_RESET
) == 0) {
75 }while(PowerOnGoodTime
--);
77 return EFI_DEVICE_ERROR
;
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
;
88 gBS
->Stall (50 * 1000);
91 // Initialize host controller operational registers
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);
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
);
113 OhciSetRootHubPortFeature (This
, Index
, EfiUsbPortEnable
);
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);
124 // Wait till first SOF occurs, and then clear it
126 while (OhciGetHcInterruptStatus (Ohc
, START_OF_FRAME
) == 0);
127 OhciClearInterruptStatus (Ohc
, START_OF_FRAME
);
134 Retrieve the current state of the USB host controller.
136 @param This This EFI_USB_HC_PROTOCOL instance.
137 @param State Variable to return the current host controller
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.
150 IN EFI_USB_HC_PROTOCOL
*This
,
151 OUT EFI_USB_HC_STATE
*State
154 USB_OHCI_HC_DEV
*Ohc
;
158 return EFI_INVALID_PARAMETER
;
161 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
163 FuncState
= OhciGetHcControl (Ohc
, HC_FUNCTIONAL_STATE
);
167 case HC_STATE_RESUME
:
168 *State
= EfiUsbHcStateHalt
;
171 case HC_STATE_OPERATIONAL
:
172 *State
= EfiUsbHcStateOperational
;
175 case HC_STATE_SUSPEND
:
176 *State
= EfiUsbHcStateSuspend
;
186 Sets the USB host controller to a specific state.
188 @param This This EFI_USB_HC_PROTOCOL instance.
189 @param State The state of the host controller that will be set.
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.
201 IN EFI_USB_HC_PROTOCOL
*This
,
202 IN EFI_USB_HC_STATE State
206 USB_OHCI_HC_DEV
*Ohc
;
208 Ohc
= USB_OHCI_HC_DEV_FROM_THIS(This
);
211 case EfiUsbHcStateHalt
:
212 Status
= OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_RESET
);
215 case EfiUsbHcStateOperational
:
216 Status
= OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_OPERATIONAL
);
219 case EfiUsbHcStateSuspend
:
220 Status
= OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_SUSPEND
);
224 Status
= EFI_INVALID_PARAMETER
;
234 Submits control transfer to a target USB device.
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
246 @param TransferDirection Specifies the data direction for the transfer.
247 There are three values available, DataIn, DataOut
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
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.
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.
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
,
280 OUT UINT32
*TransferResult
283 USB_OHCI_HC_DEV
*Ohc
;
284 ED_DESCRIPTOR
*HeadEd
;
286 TD_DESCRIPTOR
*HeadTd
;
287 TD_DESCRIPTOR
*SetupTd
;
288 TD_DESCRIPTOR
*DataTd
;
289 TD_DESCRIPTOR
*StatusTd
;
290 TD_DESCRIPTOR
*EmptyTd
;
295 OHCI_ED_RESULT EdResult
;
297 EFI_PCI_IO_PROTOCOL_OPERATION MapOp
;
299 UINTN ActualSendLength
;
303 VOID
*ReqMapping
= NULL
;
304 UINTN ReqMapLength
= 0;
305 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr
= 0;
307 VOID
*DataMapping
= NULL
;
308 UINTN DataMapLength
= 0;
309 EFI_PHYSICAL_ADDRESS DataMapPhyAddr
= 0;
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
;
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
;
330 Ohc
= USB_OHCI_HC_DEV_FROM_THIS(This
);
332 if (TransferDirection
== EfiUsbDataIn
) {
333 DataPidDir
= TD_IN_PID
;
334 StatusPidDir
= TD_OUT_PID
;
336 DataPidDir
= TD_OUT_PID
;
337 StatusPidDir
= TD_IN_PID
;
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
;
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
;
352 gBS
->Stall(20 * 1000);
354 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
355 Ed
= OhciCreateED (Ohc
);
357 Status
= EFI_OUT_OF_RESOURCES
;
358 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));
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
);
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"));
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
;
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;
407 if (TransferDirection
== EfiUsbDataIn
) {
408 MapOp
= EfiPciIoOperationBusMasterWrite
;
410 MapOp
= EfiPciIoOperationBusMasterRead
;
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"));
423 LeftLength
= DataMapLength
;
424 ActualSendLength
= DataMapLength
;
426 while (LeftLength
> 0) {
427 ActualSendLength
= LeftLength
;
428 if (LeftLength
> MaxPacketLength
) {
429 ActualSendLength
= MaxPacketLength
;
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
;
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
);
452 DataMapPhyAddr
+= ActualSendLength
;
453 LeftLength
-= ActualSendLength
;
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
;
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
);
481 EmptyTd
= OhciCreateTD (Ohc
);
482 if (EmptyTd
== NULL
) {
483 Status
= EFI_OUT_OF_RESOURCES
;
484 goto UNMAP_DATA_BUFF
;
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
);
504 // For debugging, dump ED & TD buffer befor transferring
507 //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);
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
;
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
;
524 gBS
->Stall(20 * 1000);
528 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &EdResult
);
530 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
533 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &EdResult
);
536 // For debugging, dump ED & TD buffer after transferring
538 //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);
540 *TransferResult
= ConvertErrorCode (EdResult
.ErrorCode
);
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
));
546 DEBUG ((EFI_D_INFO
, "Control pipe broken\r\n"));
550 DEBUG ((EFI_D_INFO
, "Control transfer successed\r\n"));
554 OhciSetEDField (Ed
, ED_SKIP
, 1);
556 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
558 HeadEd
->NextED
= Ed
->NextED
;
560 if(DataMapping
!= NULL
) {
561 Ohc
->PciIo
->Unmap(Ohc
->PciIo
, DataMapping
);
567 HeadTd
= (TD_DESCRIPTOR
*)(UINTN
)(HeadTd
->NextTDPointer
);
568 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
572 if(ReqMapping
!= NULL
) {
573 Ohc
->PciIo
->Unmap(Ohc
->PciIo
, ReqMapping
);
577 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
585 Submits bulk transfer to a bulk endpoint of a USB device.
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
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.
626 IN EFI_USB_HC_PROTOCOL
*This
,
627 IN UINT8 DeviceAddress
,
628 IN UINT8 EndPointAddress
,
629 IN UINT8 MaxPacketLength
,
631 IN OUT UINTN
*DataLength
,
632 IN OUT UINT8
*DataToggle
,
634 OUT UINT32
*TransferResult
637 USB_OHCI_HC_DEV
*Ohc
;
638 ED_DESCRIPTOR
*HeadEd
;
642 TD_DESCRIPTOR
*HeadTd
;
643 TD_DESCRIPTOR
*DataTd
;
644 TD_DESCRIPTOR
*EmptyTd
;
646 EFI_USB_DATA_DIRECTION TransferDirection
;
649 OHCI_ED_RESULT EdResult
;
651 EFI_PCI_IO_PROTOCOL_OPERATION MapOp
;
654 EFI_PHYSICAL_ADDRESS MapPyhAddr
;
656 UINTN ActualSendLength
;
663 Status
= EFI_SUCCESS
;
665 if (Data
== NULL
|| DataLength
== NULL
|| DataToggle
== NULL
|| TransferResult
== NULL
||
666 *DataLength
== 0 || (*DataToggle
!= 0 && *DataToggle
!= 1) ||
667 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
668 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
669 return EFI_INVALID_PARAMETER
;
672 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
674 if ((EndPointAddress
& 0x80) != 0) {
675 TransferDirection
= EfiUsbDataIn
;
677 DataPidDir
= TD_IN_PID
;
678 MapOp
= EfiPciIoOperationBusMasterWrite
;
680 TransferDirection
= EfiUsbDataOut
;
682 DataPidDir
= TD_OUT_PID
;
683 MapOp
= EfiPciIoOperationBusMasterRead
;
686 EndPointNum
= (EndPointAddress
& 0xF);
687 EdResult
.NextToggle
= *DataToggle
;
689 Status
= OhciSetHcControl (Ohc
, BULK_ENABLE
, 0);
690 if (EFI_ERROR(Status
)) {
691 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
692 *TransferResult
= EFI_USB_ERR_SYSTEM
;
693 return EFI_DEVICE_ERROR
;
695 Status
= OhciSetHcCommandStatus (Ohc
, BULK_LIST_FILLED
, 0);
696 if (EFI_ERROR(Status
)) {
697 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
698 *TransferResult
= EFI_USB_ERR_SYSTEM
;
699 return EFI_DEVICE_ERROR
;
701 gBS
->Stall(20 * 1000);
703 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
705 Ed
= OhciCreateED (Ohc
);
707 return EFI_OUT_OF_RESOURCES
;
709 OhciSetEDField (Ed
, ED_SKIP
, 1);
710 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
711 OhciSetEDField (Ed
, ED_ENDPT_NUM
, EndPointNum
);
712 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
713 OhciSetEDField (Ed
, ED_SPEED
, HI_SPEED
);
714 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
715 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
716 OhciSetEDField (Ed
, ED_PDATA
, 0);
717 OhciSetEDField (Ed
, ED_ZERO
, 0);
718 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, 0);
719 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, 0);
720 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, 0);
721 HeadEd
= OhciAttachEDToList (Ohc
, BULK_LIST
, Ed
, NULL
);
724 MapLength
= *DataLength
;
725 Status
= Ohc
->PciIo
->Map (Ohc
->PciIo
, MapOp
, (UINT8
*)Data
, &MapLength
, &MapPyhAddr
, &Mapping
);
726 if (EFI_ERROR(Status
)) {
727 DEBUG ((EFI_D_INFO
, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
734 LeftLength
= MapLength
;
735 ActualSendLength
= MapLength
;
738 while (LeftLength
> 0) {
739 ActualSendLength
= LeftLength
;
740 if (LeftLength
> MaxPacketLength
) {
741 ActualSendLength
= MaxPacketLength
;
743 DataTd
= OhciCreateTD (Ohc
);
744 if (DataTd
== NULL
) {
745 DEBUG ((EFI_D_INFO
, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
746 Status
= EFI_OUT_OF_RESOURCES
;
747 goto FREE_OHCI_TDBUFF
;
749 OhciSetTDField (DataTd
, TD_PDATA
, 0);
750 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
751 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
752 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
753 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, *DataToggle
);
754 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
755 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
756 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) MapPyhAddr
);
757 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
)(MapPyhAddr
+ ActualSendLength
- 1));
758 OhciSetTDField (DataTd
, TD_NEXT_PTR
, 0);
759 DataTd
->ActualSendLength
= (UINT32
)ActualSendLength
;
760 DataTd
->DataBuffer
= (UINT32
)MapPyhAddr
;
761 DataTd
->NextTDPointer
= 0;
766 OhciLinkTD (HeadTd
, DataTd
);
769 MapPyhAddr
+= ActualSendLength
;
770 LeftLength
-= ActualSendLength
;
775 EmptyTd
= OhciCreateTD (Ohc
);
776 if (EmptyTd
== NULL
) {
777 Status
= EFI_OUT_OF_RESOURCES
;
778 DEBUG ((EFI_D_INFO
, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
779 goto FREE_OHCI_TDBUFF
;
781 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
782 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
783 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
784 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
785 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
786 EmptyTd
->Word0
.DataToggle
= 0;
787 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
788 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
789 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
790 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
791 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
792 EmptyTd
->ActualSendLength
= 0;
793 EmptyTd
->DataBuffer
= 0;
794 EmptyTd
->NextTDPointer
= 0;
795 OhciLinkTD (HeadTd
, EmptyTd
);
796 Ed
->TdTailPointer
= (UINT32
)(UINTN
)EmptyTd
;
797 OhciAttachTDListToED (Ed
, HeadTd
);
799 OhciSetEDField (Ed
, ED_SKIP
, 0);
800 Status
= OhciSetHcCommandStatus (Ohc
, BULK_LIST_FILLED
, 1);
801 if (EFI_ERROR(Status
)) {
802 *TransferResult
= EFI_USB_ERR_SYSTEM
;
803 Status
= EFI_DEVICE_ERROR
;
804 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
805 goto FREE_OHCI_TDBUFF
;
807 Status
= OhciSetHcControl (Ohc
, BULK_ENABLE
, 1);
808 if (EFI_ERROR(Status
)) {
809 *TransferResult
= EFI_USB_ERR_SYSTEM
;
810 Status
= EFI_DEVICE_ERROR
;
811 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
812 goto FREE_OHCI_TDBUFF
;
814 gBS
->Stall(20 * 1000);
817 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &EdResult
);
818 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
821 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &EdResult
);
824 *TransferResult
= ConvertErrorCode (EdResult
.ErrorCode
);
826 if (EdResult
.ErrorCode
!= TD_NO_ERROR
) {
827 if (EdResult
.ErrorCode
== TD_TOBE_PROCESSED
) {
828 DEBUG ((EFI_D_INFO
, "Bulk pipe timeout, > %d mS\r\n", TimeOut
));
830 DEBUG ((EFI_D_INFO
, "Bulk pipe broken\r\n"));
831 *DataToggle
= EdResult
.NextToggle
;
835 DEBUG ((EFI_D_INFO
, "Bulk transfer successed\r\n"));
837 //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
840 OhciSetEDField (Ed
, ED_SKIP
, 1);
842 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
844 HeadEd
->NextED
= Ed
->NextED
;
848 HeadTd
= (TD_DESCRIPTOR
*)(UINTN
)(HeadTd
->NextTDPointer
);
849 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
852 if(Mapping
!= NULL
) {
853 Ohc
->PciIo
->Unmap(Ohc
->PciIo
, Mapping
);
857 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
863 Submits an interrupt transfer to an interrupt endpoint of a USB device.
865 @param Ohc Device private data
866 @param DeviceAddress Represents the address of the target device on the USB,
867 which is assigned during USB enumeration.
868 @param EndPointAddress The combination of an endpoint number and an endpoint
869 direction of the target USB device. Each endpoint address
870 supports data transfer in one direction except the
871 control endpoint (whose default endpoint address is 0).
872 It is the caller's responsibility to make sure that
873 the EndPointAddress represents an interrupt endpoint.
874 @param IsSlowDevice Indicates whether the target device is slow device
875 or full-speed device.
876 @param MaxPacketLength Indicates the maximum packet size the target endpoint
877 is capable of sending or receiving.
878 @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
879 the host and the target interrupt endpoint.
880 If FALSE, the specified asynchronous interrupt pipe
882 @param DataToggle A pointer to the data toggle value. On input, it is valid
883 when IsNewTransfer is TRUE, and it indicates the initial
884 data toggle value the asynchronous interrupt transfer
886 On output, it is valid when IsNewTransfer is FALSE,
887 and it is updated to indicate the data toggle value of
888 the subsequent asynchronous interrupt transfer.
889 @param PollingInterval Indicates the interval, in milliseconds, that the
890 asynchronous interrupt transfer is polled.
891 This parameter is required when IsNewTransfer is TRUE.
892 @param UCBuffer Uncacheable buffer
893 @param DataLength Indicates the length of data to be received at the
894 rate specified by PollingInterval from the target
895 asynchronous interrupt endpoint. This parameter
896 is only required when IsNewTransfer is TRUE.
897 @param CallBackFunction The Callback function.This function is called at the
898 rate specified by PollingInterval.This parameter is
899 only required when IsNewTransfer is TRUE.
900 @param Context The context that is passed to the CallBackFunction.
901 This is an optional parameter and may be NULL.
902 @param IsPeriodic Periodic interrupt or not
903 @param OutputED The correspoding ED carried out
904 @param OutputTD The correspoding TD carried out
907 @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
908 submitted or canceled.
909 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
910 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
915 OhciInterruptTransfer (
916 IN USB_OHCI_HC_DEV
*Ohc
,
917 IN UINT8 DeviceAddress
,
918 IN UINT8 EndPointAddress
,
919 IN BOOLEAN IsSlowDevice
,
920 IN UINT8 MaxPacketLength
,
921 IN BOOLEAN IsNewTransfer
,
922 IN OUT UINT8
*DataToggle OPTIONAL
,
923 IN UINTN PollingInterval OPTIONAL
,
924 IN VOID
*UCBuffer OPTIONAL
,
925 IN UINTN DataLength OPTIONAL
,
926 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL
,
927 IN VOID
*Context OPTIONAL
,
928 IN BOOLEAN IsPeriodic OPTIONAL
,
929 OUT ED_DESCRIPTOR
**OutputED OPTIONAL
,
930 OUT TD_DESCRIPTOR
**OutputTD OPTIONAL
935 ED_DESCRIPTOR
*HeadEd
;
936 TD_DESCRIPTOR
*HeadTd
;
937 TD_DESCRIPTOR
*DataTd
;
938 TD_DESCRIPTOR
*EmptTd
;
944 EFI_USB_DATA_DIRECTION TransferDirection
;
945 INTERRUPT_CONTEXT_ENTRY
*Entry
;
951 EFI_PHYSICAL_ADDRESS MapPyhAddr
;
953 UINTN ActualSendLength
;
956 if (DataLength
> MAX_BYTES_PER_TD
) {
957 DEBUG ((EFI_D_ERROR
, "OhciInterruptTransfer: Error param\r\n"));
958 return EFI_INVALID_PARAMETER
;
961 if ((EndPointAddress
& 0x80) != 0) {
962 TransferDirection
= EfiUsbDataIn
;
964 DataPidDir
= TD_IN_PID
;
966 TransferDirection
= EfiUsbDataOut
;
968 DataPidDir
= TD_OUT_PID
;
971 EndPointNum
= (EndPointAddress
& 0xF);
973 if (!IsNewTransfer
) {
974 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
975 OhciSetHcControl (Ohc
, PERIODIC_ENABLE
, 0);
976 OhciFreeInterruptContext (Ohc
, DeviceAddress
, EndPointAddress
, DataToggle
);
977 Status
= OhciFreeInterruptEdByAddr (Ohc
, DeviceAddress
, EndPointNum
);
978 OhciSetHcControl (Ohc
, PERIODIC_ENABLE
, 1);
979 gBS
->RestoreTPL (OldTpl
);
982 MapLength
= DataLength
;
983 Status
= Ohc
->PciIo
->Map(
985 EfiPciIoOperationBusMasterWrite
,
991 if (EFI_ERROR (Status
)) {
992 DEBUG ((EFI_D_ERROR
, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
997 while (PollingInterval
>= Index
* 2 && Depth
> 0) {
1004 HeadEd
= OhciFindMinInterruptEDList (Ohc
, (UINT32
)Depth
);
1005 if ((Ed
= OhciFindWorkingEd (HeadEd
, DeviceAddress
, EndPointNum
, EdDir
)) != NULL
) {
1006 OhciSetEDField (Ed
, ED_SKIP
, 1);
1008 Ed
= OhciCreateED (Ohc
);
1010 Status
= EFI_OUT_OF_RESOURCES
;
1011 DEBUG ((EFI_D_ERROR
, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
1012 goto UNMAP_OHCI_XBUFF
;
1014 OhciSetEDField (Ed
, ED_SKIP
, 1);
1015 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
1016 OhciSetEDField (Ed
, ED_ENDPT_NUM
, EndPointNum
);
1017 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
1018 OhciSetEDField (Ed
, ED_SPEED
, IsSlowDevice
);
1019 OhciSetEDField (Ed
, ED_FORMAT
, 0);
1020 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
1021 OhciSetEDField (Ed
, ED_PDATA
| ED_ZERO
| ED_HALTED
| ED_DTTOGGLE
, 0);
1022 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, 0);
1023 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, 0);
1024 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, 0);
1025 OhciAttachEDToList (Ohc
, INTERRUPT_LIST
, Ed
, HeadEd
);
1030 LeftLength
= MapLength
;
1031 ActualSendLength
= MapLength
;
1034 while (LeftLength
> 0) {
1035 ActualSendLength
= LeftLength
;
1036 if (LeftLength
> MaxPacketLength
) {
1037 ActualSendLength
= MaxPacketLength
;
1039 DataTd
= OhciCreateTD (Ohc
);
1040 if (DataTd
== NULL
) {
1041 Status
= EFI_OUT_OF_RESOURCES
;
1042 DEBUG ((EFI_D_ERROR
, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
1043 goto FREE_OHCI_TDBUFF
;
1045 OhciSetTDField (DataTd
, TD_PDATA
, 0);
1046 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
1047 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
1048 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
1049 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, *DataToggle
);
1050 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
1051 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
1052 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) MapPyhAddr
);
1053 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
)(MapPyhAddr
+ ActualSendLength
- 1));
1054 OhciSetTDField (DataTd
, TD_NEXT_PTR
, 0);
1055 DataTd
->ActualSendLength
= (UINT32
)ActualSendLength
;
1056 DataTd
->DataBuffer
= (UINT32
)MapPyhAddr
;
1057 DataTd
->NextTDPointer
= 0;
1062 OhciLinkTD (HeadTd
, DataTd
);
1065 MapPyhAddr
+= ActualSendLength
;
1066 LeftLength
-= ActualSendLength
;
1069 EmptTd
= OhciCreateTD (Ohc
);
1070 if (EmptTd
== NULL
) {
1071 Status
= EFI_OUT_OF_RESOURCES
;
1072 DEBUG ((EFI_D_ERROR
, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
1073 goto FREE_OHCI_TDBUFF
;
1075 OhciSetTDField (EmptTd
, TD_PDATA
, 0);
1076 OhciSetTDField (EmptTd
, TD_BUFFER_ROUND
, 0);
1077 OhciSetTDField (EmptTd
, TD_DIR_PID
, 0);
1078 OhciSetTDField (EmptTd
, TD_DELAY_INT
, 0);
1079 //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
1080 EmptTd
->Word0
.DataToggle
= 0;
1081 OhciSetTDField (EmptTd
, TD_ERROR_CNT
, 0);
1082 OhciSetTDField (EmptTd
, TD_COND_CODE
, 0);
1083 OhciSetTDField (EmptTd
, TD_CURR_BUFFER_PTR
, 0);
1084 OhciSetTDField (EmptTd
, TD_BUFFER_END_PTR
, 0);
1085 OhciSetTDField (EmptTd
, TD_NEXT_PTR
, 0);
1086 EmptTd
->ActualSendLength
= 0;
1087 EmptTd
->DataBuffer
= 0;
1088 EmptTd
->NextTDPointer
= 0;
1089 OhciLinkTD (HeadTd
, EmptTd
);
1090 Ed
->TdTailPointer
= (UINT32
)(UINTN
)EmptTd
;
1091 OhciAttachTDListToED (Ed
, HeadTd
);
1093 if (OutputED
!= NULL
) {
1096 if (OutputTD
!= NULL
) {
1100 if (CallBackFunction
!= NULL
) {
1101 Entry
= AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY
));
1102 if (Entry
== NULL
) {
1103 goto FREE_OHCI_TDBUFF
;
1106 Entry
->DeviceAddress
= DeviceAddress
;
1107 Entry
->EndPointAddress
= EndPointAddress
;
1109 Entry
->DataTd
= HeadTd
;
1110 Entry
->IsSlowDevice
= IsSlowDevice
;
1111 Entry
->MaxPacketLength
= MaxPacketLength
;
1112 Entry
->PollingInterval
= PollingInterval
;
1113 Entry
->CallBackFunction
= CallBackFunction
;
1114 Entry
->Context
= Context
;
1115 Entry
->IsPeriodic
= IsPeriodic
;
1116 Entry
->UCBuffer
= UCBuffer
;
1117 Entry
->UCBufferMapping
= Mapping
;
1118 Entry
->DataLength
= DataLength
;
1119 Entry
->Toggle
= DataToggle
;
1120 Entry
->NextEntry
= NULL
;
1121 OhciAddInterruptContextEntry (Ohc
, Entry
);
1123 OhciSetEDField (Ed
, ED_SKIP
, 0);
1125 if (OhciGetHcControl (Ohc
, PERIODIC_ENABLE
) == 0) {
1126 Status
= OhciSetHcControl (Ohc
, PERIODIC_ENABLE
, 1);
1135 HeadTd
= (TD_DESCRIPTOR
*)(UINTN
)(HeadTd
->NextTDPointer
);
1136 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
1140 if ((HeadEd
!= Ed
) && HeadEd
&& Ed
) {
1141 while(HeadEd
->NextED
!= (UINT32
)(UINTN
)Ed
) {
1142 HeadEd
= (ED_DESCRIPTOR
*)(UINTN
)(HeadEd
->NextED
);
1144 HeadEd
->NextED
= Ed
->NextED
;
1145 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
1149 Ohc
->PciIo
->Unmap(Ohc
->PciIo
, Mapping
);
1157 Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
1159 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1160 @param DeviceAddress Represents the address of the target device on the USB,
1161 which is assigned during USB enumeration.
1162 @param EndPointAddress The combination of an endpoint number and an endpoint
1163 direction of the target USB device. Each endpoint address
1164 supports data transfer in one direction except the
1165 control endpoint (whose default endpoint address is 0).
1166 It is the caller's responsibility to make sure that
1167 the EndPointAddress represents an interrupt endpoint.
1168 @param IsSlowDevice Indicates whether the target device is slow device
1169 or full-speed device.
1170 @param MaxiumPacketLength Indicates the maximum packet size the target endpoint
1171 is capable of sending or receiving.
1172 @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
1173 the host and the target interrupt endpoint.
1174 If FALSE, the specified asynchronous interrupt pipe
1176 @param DataToggle A pointer to the data toggle value. On input, it is valid
1177 when IsNewTransfer is TRUE, and it indicates the initial
1178 data toggle value the asynchronous interrupt transfer
1180 On output, it is valid when IsNewTransfer is FALSE,
1181 and it is updated to indicate the data toggle value of
1182 the subsequent asynchronous interrupt transfer.
1183 @param PollingInterval Indicates the interval, in milliseconds, that the
1184 asynchronous interrupt transfer is polled.
1185 This parameter is required when IsNewTransfer is TRUE.
1186 @param DataLength Indicates the length of data to be received at the
1187 rate specified by PollingInterval from the target
1188 asynchronous interrupt endpoint. This parameter
1189 is only required when IsNewTransfer is TRUE.
1190 @param CallBackFunction The Callback function.This function is called at the
1191 rate specified by PollingInterval.This parameter is
1192 only required when IsNewTransfer is TRUE.
1193 @param Context The context that is passed to the CallBackFunction.
1194 This is an optional parameter and may be NULL.
1196 @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
1197 submitted or canceled.
1198 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1199 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1206 OhciAsyncInterruptTransfer (
1207 IN EFI_USB_HC_PROTOCOL
*This
,
1208 IN UINT8 DeviceAddress
,
1209 IN UINT8 EndPointAddress
,
1210 IN BOOLEAN IsSlowDevice
,
1211 IN UINT8 MaxPacketLength
,
1212 IN BOOLEAN IsNewTransfer
,
1213 IN OUT UINT8
*DataToggle OPTIONAL
,
1214 IN UINTN PollingInterval OPTIONAL
,
1215 IN UINTN DataLength OPTIONAL
,
1216 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL
,
1217 IN VOID
*Context OPTIONAL
1221 USB_OHCI_HC_DEV
*Ohc
;
1224 if (DataToggle
== NULL
|| (EndPointAddress
& 0x80) == 0 ||
1225 (IsNewTransfer
&& (DataLength
== 0 ||
1226 (*DataToggle
!= 0 && *DataToggle
!= 1) || (PollingInterval
< 1 || PollingInterval
> 255)))) {
1227 return EFI_INVALID_PARAMETER
;
1230 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
1231 if ( IsNewTransfer
) {
1232 UCBuffer
= AllocatePool(DataLength
);
1233 if (UCBuffer
== NULL
) {
1234 return EFI_OUT_OF_RESOURCES
;
1239 Status
= OhciInterruptTransfer (
1256 if ( IsNewTransfer
) {
1257 if (EFI_ERROR(Status
)) {
1258 gBS
->FreePool (UCBuffer
);
1267 Submits synchronous interrupt transfer to an interrupt endpoint
1270 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1271 @param DeviceAddress Represents the address of the target device on the USB,
1272 which is assigned during USB enumeration.
1273 @param EndPointAddress The combination of an endpoint number and an endpoint
1274 direction of the target USB device. Each endpoint
1275 address supports data transfer in one direction
1276 except the control endpoint (whose default
1277 endpoint address is 0). It is the caller's responsibility
1278 to make sure that the EndPointAddress represents
1279 an interrupt endpoint.
1280 @param IsSlowDevice Indicates whether the target device is slow device
1281 or full-speed device.
1282 @param MaxPacketLength Indicates the maximum packet size the target endpoint
1283 is capable of sending or receiving.
1284 @param Data A pointer to the buffer of data that will be transmitted
1285 to USB device or received from USB device.
1286 @param DataLength On input, the size, in bytes, of the data buffer specified
1287 by Data. On output, the number of bytes transferred.
1288 @param DataToggle A pointer to the data toggle value. On input, it indicates
1289 the initial data toggle value the synchronous interrupt
1290 transfer should adopt;
1291 on output, it is updated to indicate the data toggle value
1292 of the subsequent synchronous interrupt transfer.
1293 @param TimeOut Indicates the maximum time, in microseconds, which the
1294 transfer is allowed to complete.
1295 @param TransferResult A pointer to the detailed result information from
1296 the synchronous interrupt transfer.
1298 @retval EFI_UNSUPPORTED This interface not available.
1299 @retval EFI_INVALID_PARAMETER Parameters not follow spec
1306 OhciSyncInterruptTransfer (
1307 IN EFI_USB_HC_PROTOCOL
*This
,
1308 IN UINT8 DeviceAddress
,
1309 IN UINT8 EndPointAddress
,
1310 IN BOOLEAN IsSlowDevice
,
1311 IN UINT8 MaxPacketLength
,
1313 IN OUT UINTN
*DataLength
,
1314 IN OUT UINT8
*DataToggle
,
1316 OUT UINT32
*TransferResult
1319 USB_OHCI_HC_DEV
*Ohc
;
1322 TD_DESCRIPTOR
*HeadTd
;
1323 OHCI_ED_RESULT EdResult
;
1326 if ((EndPointAddress
& 0x80) == 0 || Data
== NULL
|| DataLength
== NULL
|| *DataLength
== 0 ||
1327 (IsSlowDevice
&& MaxPacketLength
> 8) || (!IsSlowDevice
&& MaxPacketLength
> 64) ||
1328 DataToggle
== NULL
|| (*DataToggle
!= 0 && *DataToggle
!= 1) || TransferResult
== NULL
) {
1329 return EFI_INVALID_PARAMETER
;
1332 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
1333 UCBuffer
= AllocatePool (*DataLength
);
1334 if (UCBuffer
== NULL
) {
1335 return EFI_OUT_OF_RESOURCES
;
1337 Status
= OhciInterruptTransfer (
1355 if (!EFI_ERROR (Status
)) {
1356 Status
= CheckIfDone (Ohc
, INTERRUPT_LIST
, Ed
, HeadTd
, &EdResult
);
1357 while (Status
== EFI_NOT_READY
&& TimeOut
> 0) {
1360 Status
= CheckIfDone (Ohc
, INTERRUPT_LIST
, Ed
, HeadTd
, &EdResult
);
1363 *TransferResult
= ConvertErrorCode (EdResult
.ErrorCode
);
1365 CopyMem(Data
, UCBuffer
, *DataLength
);
1366 Status
= OhciInterruptTransfer (
1388 Submits isochronous transfer to a target USB device.
1390 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1391 @param DeviceAddress Represents the address of the target device on the USB,
1392 which is assigned during USB enumeration.
1393 @param EndPointAddress End point address
1394 @param MaximumPacketLength Indicates the maximum packet size that the
1395 default control transfer endpoint is capable of
1396 sending or receiving.
1397 @param Data A pointer to the buffer of data that will be transmitted
1398 to USB device or received from USB device.
1399 @param DataLength Indicates the size, in bytes, of the data buffer
1401 @param TransferResult A pointer to the detailed result information generated
1402 by this control transfer.
1404 @retval EFI_UNSUPPORTED This interface not available
1405 @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
1412 OhciIsochronousTransfer (
1413 IN EFI_USB_HC_PROTOCOL
*This
,
1414 IN UINT8 DeviceAddress
,
1415 IN UINT8 EndPointAddress
,
1416 IN UINT8 MaximumPacketLength
,
1418 IN OUT UINTN DataLength
,
1419 OUT UINT32
*TransferResult
1422 if (Data
== NULL
|| DataLength
== 0 || TransferResult
== NULL
) {
1423 return EFI_INVALID_PARAMETER
;
1426 return EFI_UNSUPPORTED
;
1431 Submits Async isochronous transfer to a target USB device.
1433 @param his A pointer to the EFI_USB_HC_PROTOCOL instance.
1434 @param DeviceAddress Represents the address of the target device on the USB,
1435 which is assigned during USB enumeration.
1436 @param EndPointAddress End point address
1437 @param MaximumPacketLength Indicates the maximum packet size that the
1438 default control transfer endpoint is capable of
1439 sending or receiving.
1440 @param Data A pointer to the buffer of data that will be transmitted
1441 to USB device or received from USB device.
1442 @param IsochronousCallBack When the transfer complete, the call back function will be called
1443 @param Context Pass to the call back function as parameter
1445 @retval EFI_UNSUPPORTED This interface not available
1446 @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
1452 OhciAsyncIsochronousTransfer (
1453 IN EFI_USB_HC_PROTOCOL
*This
,
1454 IN UINT8 DeviceAddress
,
1455 IN UINT8 EndPointAddress
,
1456 IN UINT8 MaximumPacketLength
,
1458 IN OUT UINTN DataLength
,
1459 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack
,
1460 IN VOID
*Context OPTIONAL
1464 if (Data
== NULL
|| DataLength
== 0) {
1465 return EFI_INVALID_PARAMETER
;
1468 return EFI_UNSUPPORTED
;
1473 Retrieves the number of root hub ports.
1475 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1476 @param NumOfPorts A pointer to the number of the root hub ports.
1478 @retval EFI_SUCCESS The port number was retrieved successfully.
1482 OhciGetRootHubNumOfPorts (
1483 IN EFI_USB_HC_PROTOCOL
*This
,
1484 OUT UINT8
*NumOfPorts
1487 USB_OHCI_HC_DEV
*Ohc
;
1488 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
1490 if (NumOfPorts
== NULL
) {
1491 return EFI_INVALID_PARAMETER
;
1494 *NumOfPorts
= (UINT8
)OhciGetRootHubDescriptor(Ohc
, RH_NUM_DS_PORTS
);
1500 Retrieves the current status of a USB root hub port.
1502 @param This A pointer to the EFI_USB_HC_PROTOCOL.
1503 @param PortNumber Specifies the root hub port from which the status
1504 is to be retrieved. This value is zero-based. For example,
1505 if a root hub has two ports, then the first port is numbered 0,
1506 and the second port is numbered 1.
1507 @param PortStatus A pointer to the current port status bits and
1508 port status change bits.
1510 @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber
1511 was returned in PortStatus.
1512 @retval EFI_INVALID_PARAMETER Port number not valid
1518 OhciGetRootHubPortStatus (
1519 IN EFI_USB_HC_PROTOCOL
*This
,
1520 IN UINT8 PortNumber
,
1521 OUT EFI_USB_PORT_STATUS
*PortStatus
1524 USB_OHCI_HC_DEV
*Ohc
;
1527 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
1529 OhciGetRootHubNumOfPorts (This
, &NumOfPorts
);
1530 if (PortNumber
>= NumOfPorts
) {
1531 return EFI_INVALID_PARAMETER
;
1533 PortStatus
->PortStatus
= 0;
1534 PortStatus
->PortChangeStatus
= 0;
1536 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_CURR_CONNECT_STAT
)) {
1537 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
1539 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_ENABLE_STAT
)) {
1540 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
1542 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_SUSPEND_STAT
)) {
1543 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
1545 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_OC_INDICATOR
)) {
1546 PortStatus
->PortStatus
|= USB_PORT_STAT_OVERCURRENT
;
1548 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_RESET_STAT
)) {
1549 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
1551 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_POWER_STAT
)) {
1552 PortStatus
->PortStatus
|= USB_PORT_STAT_POWER
;
1554 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_LSDEVICE_ATTACHED
)) {
1555 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1557 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
)) {
1558 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
1560 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
)) {
1561 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
1563 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
)) {
1564 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_SUSPEND
;
1566 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
)) {
1567 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_OVERCURRENT
;
1569 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
)) {
1570 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_RESET
;
1577 Sets a feature for the specified root hub port.
1579 @param This A pointer to the EFI_USB_HC_PROTOCOL.
1580 @param PortNumber Specifies the root hub port whose feature
1581 is requested to be set.
1582 @param PortFeature Indicates the feature selector associated
1583 with the feature set request.
1585 @retval EFI_SUCCESS The feature specified by PortFeature was set for the
1586 USB root hub port specified by PortNumber.
1587 @retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
1588 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1592 OhciSetRootHubPortFeature (
1593 IN EFI_USB_HC_PROTOCOL
*This
,
1594 IN UINT8 PortNumber
,
1595 IN EFI_USB_PORT_FEATURE PortFeature
1598 USB_OHCI_HC_DEV
*Ohc
;
1603 OhciGetRootHubNumOfPorts (This
, &NumOfPorts
);
1604 if (PortNumber
>= NumOfPorts
) {
1605 return EFI_INVALID_PARAMETER
;
1608 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
1610 Status
= EFI_SUCCESS
;
1613 switch (PortFeature
) {
1614 case EfiUsbPortPower
:
1615 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_POWER
);
1624 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 0 &&
1625 RetryTimes
< MAX_RETRY_TIMES
);
1627 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1628 return EFI_DEVICE_ERROR
;
1632 case EfiUsbPortReset
:
1633 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_RESET
);
1642 } while ((OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 0 ||
1643 OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT
) == 1) &&
1644 RetryTimes
< MAX_RETRY_TIMES
);
1646 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1647 return EFI_DEVICE_ERROR
;
1650 OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
1653 case EfiUsbPortEnable
:
1654 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_ENABLE
);
1663 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 0 &&
1664 RetryTimes
< MAX_RETRY_TIMES
);
1666 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1667 return EFI_DEVICE_ERROR
;
1672 case EfiUsbPortSuspend
:
1673 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_SUSPEND
);
1682 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 0 &&
1683 RetryTimes
< MAX_RETRY_TIMES
);
1685 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1686 return EFI_DEVICE_ERROR
;
1691 return EFI_INVALID_PARAMETER
;
1699 Clears a feature for the specified root hub port.
1701 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1702 @param PortNumber Specifies the root hub port whose feature
1703 is requested to be cleared.
1704 @param PortFeature Indicates the feature selector associated with the
1705 feature clear request.
1707 @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the
1708 USB root hub port specified by PortNumber.
1709 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1710 @retval EFI_DEVICE_ERROR Some error happened when clearing feature
1714 OhciClearRootHubPortFeature (
1715 IN EFI_USB_HC_PROTOCOL
*This
,
1716 IN UINT8 PortNumber
,
1717 IN EFI_USB_PORT_FEATURE PortFeature
1720 USB_OHCI_HC_DEV
*Ohc
;
1726 OhciGetRootHubNumOfPorts (This
, &NumOfPorts
);
1727 if (PortNumber
>= NumOfPorts
) {
1728 return EFI_INVALID_PARAMETER
;
1731 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
1733 Status
= EFI_SUCCESS
;
1735 switch (PortFeature
) {
1736 case EfiUsbPortEnable
:
1737 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_ENABLE
);
1746 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 1 &&
1747 RetryTimes
< MAX_RETRY_TIMES
);
1749 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1750 return EFI_DEVICE_ERROR
;
1754 case EfiUsbPortSuspend
:
1755 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_SUSPEND_STATUS
);
1764 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 1 &&
1765 RetryTimes
< MAX_RETRY_TIMES
);
1767 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1768 return EFI_DEVICE_ERROR
;
1772 case EfiUsbPortReset
:
1775 case EfiUsbPortPower
:
1776 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_POWER
);
1785 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 1 &&
1786 RetryTimes
< MAX_RETRY_TIMES
);
1788 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1789 return EFI_DEVICE_ERROR
;
1793 case EfiUsbPortConnectChange
:
1794 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
);
1803 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
) == 1 &&
1804 RetryTimes
< MAX_RETRY_TIMES
);
1806 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1807 return EFI_DEVICE_ERROR
;
1811 case EfiUsbPortResetChange
:
1812 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
1821 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 1 &&
1822 RetryTimes
< MAX_RETRY_TIMES
);
1824 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1825 return EFI_DEVICE_ERROR
;
1830 case EfiUsbPortEnableChange
:
1831 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
);
1840 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
) == 1 &&
1841 RetryTimes
< MAX_RETRY_TIMES
);
1843 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1844 return EFI_DEVICE_ERROR
;
1848 case EfiUsbPortSuspendChange
:
1849 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
);
1858 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
) == 1 &&
1859 RetryTimes
< MAX_RETRY_TIMES
);
1861 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1862 return EFI_DEVICE_ERROR
;
1866 case EfiUsbPortOverCurrentChange
:
1867 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
);
1876 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
) == 1 &&
1877 RetryTimes
< MAX_RETRY_TIMES
);
1879 if (RetryTimes
>= MAX_RETRY_TIMES
) {
1880 return EFI_DEVICE_ERROR
;
1885 return EFI_INVALID_PARAMETER
;
1891 EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding
= {
1892 OHCIDriverBindingSupported
,
1893 OHCIDriverBindingStart
,
1894 OHCIDriverBindingStop
,
1902 Entry point for EFI drivers.
1904 @param ImageHandle EFI_HANDLE.
1905 @param SystemTable EFI_SYSTEM_TABLE.
1907 @retval EFI_SUCCESS Driver is successfully loaded.
1908 @return Others Failed.
1913 OHCIDriverEntryPoint (
1914 IN EFI_HANDLE ImageHandle
,
1915 IN EFI_SYSTEM_TABLE
*SystemTable
1918 return EfiLibInstallDriverBindingComponentName2 (
1921 &gOhciDriverBinding
,
1923 &gOhciComponentName
,
1924 &gOhciComponentName2
1930 Test to see if this driver supports ControllerHandle. Any
1931 ControllerHandle that has UsbHcProtocol installed will be supported.
1933 @param This Protocol instance pointer.
1934 @param Controller Handle of device to test.
1935 @param RemainingDevicePath Not used.
1937 @return EFI_SUCCESS This driver supports this device.
1938 @return EFI_UNSUPPORTED This driver does not support this device.
1943 OHCIDriverBindingSupported (
1944 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1945 IN EFI_HANDLE Controller
,
1946 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1950 EFI_PCI_IO_PROTOCOL
*PciIo
;
1951 USB_CLASSC UsbClassCReg
;
1953 // Test whether there is PCI IO Protocol attached on the controller handle.
1955 Status
= gBS
->OpenProtocol (
1957 &gEfiPciIoProtocolGuid
,
1959 This
->DriverBindingHandle
,
1961 EFI_OPEN_PROTOCOL_BY_DRIVER
1964 if (EFI_ERROR (Status
)) {
1965 return EFI_UNSUPPORTED
;
1968 Status
= PciIo
->Pci
.Read (
1971 PCI_CLASSCODE_OFFSET
,
1972 sizeof (USB_CLASSC
) / sizeof (UINT8
),
1976 if (EFI_ERROR (Status
)) {
1977 Status
= EFI_UNSUPPORTED
;
1981 // Test whether the controller belongs to OHCI type
1983 if ((UsbClassCReg
.BaseCode
!= PCI_CLASS_SERIAL
) ||
1984 (UsbClassCReg
.SubClassCode
!= PCI_CLASS_SERIAL_USB
) ||
1985 (UsbClassCReg
.ProgInterface
!= PCI_IF_OHCI
)
1988 Status
= EFI_UNSUPPORTED
;
1991 gBS
->CloseProtocol (
1993 &gEfiPciIoProtocolGuid
,
1994 This
->DriverBindingHandle
,
2004 Allocate and initialize the empty OHCI device.
2006 @param PciIo The PCIIO to use.
2007 @param OriginalPciAttributes The original PCI attributes.
2009 @return Allocated OHCI device If err, return NULL.
2015 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2016 IN UINT64 OriginalPciAttributes
2019 USB_OHCI_HC_DEV
*Ohc
;
2022 EFI_PHYSICAL_ADDRESS PhyAddr
;
2027 Ohc
= AllocateZeroPool (sizeof (USB_OHCI_HC_DEV
));
2032 Ohc
->Signature
= USB_OHCI_HC_DEV_SIGNATURE
;
2035 Ohc
->UsbHc
.Reset
= OhciReset
;
2036 Ohc
->UsbHc
.GetState
= OhciGetState
;
2037 Ohc
->UsbHc
.SetState
= OhciSetState
;
2038 Ohc
->UsbHc
.ControlTransfer
= OhciControlTransfer
;
2039 Ohc
->UsbHc
.BulkTransfer
= OhciBulkTransfer
;
2040 Ohc
->UsbHc
.AsyncInterruptTransfer
= OhciAsyncInterruptTransfer
;
2041 Ohc
->UsbHc
.SyncInterruptTransfer
= OhciSyncInterruptTransfer
;
2042 Ohc
->UsbHc
.IsochronousTransfer
= OhciIsochronousTransfer
;
2043 Ohc
->UsbHc
.AsyncIsochronousTransfer
= OhciAsyncIsochronousTransfer
;
2044 Ohc
->UsbHc
.GetRootHubPortNumber
= OhciGetRootHubNumOfPorts
;
2045 Ohc
->UsbHc
.GetRootHubPortStatus
= OhciGetRootHubPortStatus
;
2046 Ohc
->UsbHc
.SetRootHubPortFeature
= OhciSetRootHubPortFeature
;
2047 Ohc
->UsbHc
.ClearRootHubPortFeature
= OhciClearRootHubPortFeature
;
2048 Ohc
->UsbHc
.MajorRevision
= 0x1;
2049 Ohc
->UsbHc
.MinorRevision
= 0x1;
2051 Ohc
->OriginalPciAttributes
= OriginalPciAttributes
;
2053 Ohc
->HccaMemoryBlock
= NULL
;
2054 Ohc
->HccaMemoryMapping
= NULL
;
2055 Ohc
->HccaMemoryBuf
= NULL
;
2056 Ohc
->HccaMemoryPages
= 0;
2057 Ohc
->InterruptContextList
= NULL
;
2058 Ohc
->ControllerNameTable
= NULL
;
2059 Ohc
->HouseKeeperTimer
= NULL
;
2061 Ohc
->MemPool
= UsbHcInitMemPool(PciIo
, TRUE
, 0);
2062 if(Ohc
->MemPool
== NULL
) {
2063 goto FREE_DEV_BUFFER
;
2067 Pages
= EFI_SIZE_TO_PAGES (Bytes
);
2069 Status
= PciIo
->AllocateBuffer (
2072 EfiBootServicesData
,
2078 if (EFI_ERROR (Status
)) {
2082 Status
= PciIo
->Map (
2084 EfiPciIoOperationBusMasterCommonBuffer
,
2091 if (EFI_ERROR (Status
) || (Bytes
!= 4096)) {
2095 Ohc
->HccaMemoryBlock
= (HCCA_MEMORY_BLOCK
*)(UINTN
)PhyAddr
;
2096 Ohc
->HccaMemoryMapping
= Map
;
2097 Ohc
->HccaMemoryBuf
= (VOID
*)(UINTN
)Buf
;
2098 Ohc
->HccaMemoryPages
= Pages
;
2103 PciIo
->FreeBuffer (PciIo
, Pages
, Buf
);
2105 UsbHcFreeMemPool (Ohc
->MemPool
);
2113 Free the OHCI device and release its associated resources.
2115 @param Ohc The OHCI device to release.
2120 IN USB_OHCI_HC_DEV
*Ohc
2123 OhciFreeFixedIntMemory (Ohc
);
2125 if (Ohc
->HouseKeeperTimer
!= NULL
) {
2126 gBS
->CloseEvent (Ohc
->HouseKeeperTimer
);
2129 if (Ohc
->ExitBootServiceEvent
!= NULL
) {
2130 gBS
->CloseEvent (Ohc
->ExitBootServiceEvent
);
2133 if (Ohc
->MemPool
!= NULL
) {
2134 UsbHcFreeMemPool (Ohc
->MemPool
);
2137 if (Ohc
->HccaMemoryMapping
!= NULL
) {
2138 Ohc
->PciIo
->FreeBuffer (Ohc
->PciIo
, Ohc
->HccaMemoryPages
, Ohc
->HccaMemoryBuf
);
2141 if (Ohc
->ControllerNameTable
!= NULL
) {
2142 FreeUnicodeStringTable (Ohc
->ControllerNameTable
);
2149 Uninstall all Ohci Interface.
2151 @param Controller Controller handle.
2152 @param This Protocol instance pointer.
2157 IN EFI_HANDLE Controller
,
2158 IN EFI_USB_HC_PROTOCOL
*This
2161 USB_OHCI_HC_DEV
*Ohc
;
2164 // Retrieve private context structure
2166 Ohc
= USB_OHCI_HC_DEV_FROM_THIS (This
);
2169 // Uninstall the USB_HC and USB_HC2 protocol
2171 gBS
->UninstallProtocolInterface (
2173 &gEfiUsbHcProtocolGuid
,
2178 // Cancel the timer event
2180 gBS
->SetTimer (Ohc
->HouseKeeperTimer
, TimerCancel
, 0);
2183 // Stop the host controller
2185 OhciSetHcControl (Ohc
, PERIODIC_ENABLE
| CONTROL_ENABLE
| ISOCHRONOUS_ENABLE
| BULK_ENABLE
, 0);
2186 This
->Reset (This
, EFI_USB_HC_RESET_GLOBAL
);
2187 This
->SetState (This
, EfiUsbHcStateHalt
);
2192 OhciFreeDynamicIntMemory (Ohc
);
2195 // Restore original PCI attributes
2197 Ohc
->PciIo
->Attributes (
2199 EfiPciIoAttributeOperationSet
,
2200 Ohc
->OriginalPciAttributes
,
2205 // Free the private context structure
2212 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
2214 @param Event Pointer to this event
2215 @param Context Event hanlder private data
2219 OhcExitBootService (
2224 USB_OHCI_HC_DEV
*Ohc
;
2225 EFI_USB_HC_PROTOCOL
*UsbHc
;
2226 Ohc
= (USB_OHCI_HC_DEV
*) Context
;
2228 UsbHc
= &Ohc
->UsbHc
;
2230 // Stop the Host Controller
2232 //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
2233 OhciSetHcControl (Ohc
, PERIODIC_ENABLE
| CONTROL_ENABLE
| ISOCHRONOUS_ENABLE
| BULK_ENABLE
, 0);
2234 UsbHc
->Reset (UsbHc
, EFI_USB_HC_RESET_GLOBAL
);
2235 UsbHc
->SetState (UsbHc
, EfiUsbHcStateHalt
);
2242 Starting the Usb OHCI Driver.
2244 @param This Protocol instance pointer.
2245 @param Controller Handle of device to test.
2246 @param RemainingDevicePath Not used.
2248 @retval EFI_SUCCESS This driver supports this device.
2249 @retval EFI_UNSUPPORTED This driver does not support this device.
2250 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
2251 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
2256 OHCIDriverBindingStart (
2257 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2258 IN EFI_HANDLE Controller
,
2259 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2263 EFI_PCI_IO_PROTOCOL
*PciIo
;
2264 USB_OHCI_HC_DEV
*Ohc
;
2266 UINT64 OriginalPciAttributes
;
2267 BOOLEAN PciAttributesSaved
;
2270 // Open PCIIO, then enable the HC device and turn off emulation
2273 Status
= gBS
->OpenProtocol (
2275 &gEfiPciIoProtocolGuid
,
2277 This
->DriverBindingHandle
,
2279 EFI_OPEN_PROTOCOL_BY_DRIVER
2282 if (EFI_ERROR (Status
)) {
2286 PciAttributesSaved
= FALSE
;
2288 // Save original PCI attributes
2290 Status
= PciIo
->Attributes (
2292 EfiPciIoAttributeOperationGet
,
2294 &OriginalPciAttributes
2297 if (EFI_ERROR (Status
)) {
2300 PciAttributesSaved
= TRUE
;
2303 // Robustnesss improvement such as for UoL
2304 // Default is not required.
2306 //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
2307 // OhciTurnOffUsbEmulation (PciIo);
2310 Status
= PciIo
->Attributes (
2312 EfiPciIoAttributeOperationSupported
,
2316 if (!EFI_ERROR (Status
)) {
2317 Supports
&= EFI_PCI_DEVICE_ENABLE
;
2318 Status
= PciIo
->Attributes (
2320 EfiPciIoAttributeOperationEnable
,
2326 if (EFI_ERROR (Status
)) {
2330 //Allocate memory for OHC private data structure
2332 Ohc
= OhciAllocateDev(PciIo
, OriginalPciAttributes
);
2334 Status
= EFI_OUT_OF_RESOURCES
;
2338 //Status = OhciInitializeInterruptList ( Uhc );
2339 //if (EFI_ERROR (Status)) {
2346 Status
= gBS
->CreateEvent (
2347 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
2351 &Ohc
->HouseKeeperTimer
2353 if (EFI_ERROR (Status
)) {
2357 Status
= gBS
->SetTimer (Ohc
->HouseKeeperTimer
, TimerPeriodic
, 10 * 1000 * 10);
2358 if (EFI_ERROR (Status
)) {
2363 //Install Host Controller Protocol
2365 Status
= gBS
->InstallProtocolInterface (
2367 &gEfiUsbHcProtocolGuid
,
2368 EFI_NATIVE_INTERFACE
,
2371 if (EFI_ERROR (Status
)) {
2372 DEBUG ((EFI_D_INFO
, "Install protocol error"));
2376 // Create event to stop the HC when exit boot service.
2378 Status
= gBS
->CreateEventEx (
2383 &gEfiEventExitBootServicesGuid
,
2384 &Ohc
->ExitBootServiceEvent
2386 if (EFI_ERROR (Status
)) {
2387 DEBUG ((EFI_D_INFO
, "Create exit boot event error"));
2388 goto UNINSTALL_USBHC
;
2392 gOhciComponentName
.SupportedLanguages
,
2393 &Ohc
->ControllerNameTable
,
2394 L
"Usb Universal Host Controller",
2399 gOhciComponentName2
.SupportedLanguages
,
2400 &Ohc
->ControllerNameTable
,
2401 L
"Usb Universal Host Controller",
2408 gBS
->UninstallMultipleProtocolInterfaces (
2410 &gEfiUsbHcProtocolGuid
,
2419 if (PciAttributesSaved
) {
2421 // Restore original PCI attributes
2425 EfiPciIoAttributeOperationSet
,
2426 OriginalPciAttributes
,
2431 gBS
->CloseProtocol (
2433 &gEfiPciIoProtocolGuid
,
2434 This
->DriverBindingHandle
,
2441 Stop this driver on ControllerHandle. Support stoping any child handles
2442 created by this driver.
2444 @param This Protocol instance pointer.
2445 @param Controller Handle of device to stop driver on.
2446 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
2447 @param ChildHandleBuffer List of handles for the children we need to stop.
2455 OHCIDriverBindingStop (
2456 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2457 IN EFI_HANDLE Controller
,
2458 IN UINTN NumberOfChildren
,
2459 IN EFI_HANDLE
*ChildHandleBuffer
2463 EFI_USB_HC_PROTOCOL
*UsbHc
;
2465 Status
= gBS
->OpenProtocol (
2467 &gEfiUsbHcProtocolGuid
,
2469 This
->DriverBindingHandle
,
2471 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2473 if (EFI_ERROR (Status
)) {
2477 OhciCleanDevUp(Controller
, UsbHc
);
2479 gBS
->CloseProtocol (
2481 &gEfiPciIoProtocolGuid
,
2482 This
->DriverBindingHandle
,