2 This file contains the implementation of Usb Hc Protocol.
4 Copyright (c) 2013-2015 Intel Corporation.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
14 Submits control transfer to a target USB device.
16 @param PeiServices The pointer of EFI_PEI_SERVICES.
17 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
18 @param DeviceAddress The target device address.
19 @param DeviceSpeed Target device speed.
20 @param MaximumPacketLength Maximum packet size the default control transfer
21 endpoint is capable of sending or receiving.
22 @param Request USB device request to send.
23 @param TransferDirection Specifies the data direction for the data stage.
24 @param Data Data buffer to be transmitted or received from USB device.
25 @param DataLength The size (in bytes) of the data buffer.
26 @param TimeOut Indicates the maximum timeout, in millisecond.
27 @param TransferResult Return the result of this control transfer.
29 @retval EFI_SUCCESS Transfer was completed successfully.
30 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
31 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
32 @retval EFI_TIMEOUT Transfer failed due to timeout.
33 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
39 IN EFI_PEI_SERVICES
**PeiServices
,
40 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
41 IN UINT8 DeviceAddress
,
43 IN UINT8 MaxPacketLength
,
44 IN EFI_USB_DEVICE_REQUEST
*Request
,
45 IN EFI_USB_DATA_DIRECTION TransferDirection
,
47 IN OUT UINTN
*DataLength
,
49 OUT UINT32
*TransferResult
54 TD_DESCRIPTOR
*HeadTd
;
55 TD_DESCRIPTOR
*SetupTd
;
56 TD_DESCRIPTOR
*DataTd
;
57 TD_DESCRIPTOR
*StatusTd
;
58 TD_DESCRIPTOR
*EmptyTd
;
65 UINTN ActualSendLength
;
69 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr
= 0;
71 UINTN DataMapLength
= 0;
72 EFI_PHYSICAL_ADDRESS DataMapPhyAddr
= 0;
77 if ((TransferDirection
!= EfiUsbDataOut
&& TransferDirection
!= EfiUsbDataIn
&&
78 TransferDirection
!= EfiUsbNoData
) ||
79 Request
== NULL
|| DataLength
== NULL
|| TransferResult
== NULL
||
80 (TransferDirection
== EfiUsbNoData
&& (*DataLength
!= 0 || Data
!= NULL
)) ||
81 (TransferDirection
!= EfiUsbNoData
&& (*DataLength
== 0 || Data
== NULL
)) ||
82 (DeviceSpeed
!= EFI_USB_SPEED_LOW
&& DeviceSpeed
!= EFI_USB_SPEED_FULL
) ||
83 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
84 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
85 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: EFI_INVALID_PARAMETER\n"));
86 return EFI_INVALID_PARAMETER
;
89 if (*DataLength
> MAX_BYTES_PER_TD
) {
90 DEBUG ((EFI_D_ERROR
, "OhciControlTransfer: Request data size is too large\n"));
91 return EFI_INVALID_PARAMETER
;
94 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This
);
96 if (TransferDirection
== EfiUsbDataIn
) {
97 DataPidDir
= TD_IN_PID
;
98 StatusPidDir
= TD_OUT_PID
;
100 DataPidDir
= TD_OUT_PID
;
101 StatusPidDir
= TD_IN_PID
;
104 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 0);
105 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
106 MicroSecondDelay (HC_1_MILLISECOND
);
107 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
108 *TransferResult
= EFI_USB_ERR_SYSTEM
;
109 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to disable CONTROL transfer\n"));
110 return EFI_DEVICE_ERROR
;
113 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
114 Ed
= OhciCreateED (Ohc
);
116 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate ED buffer\n"));
117 return EFI_OUT_OF_RESOURCES
;
119 OhciSetEDField (Ed
, ED_SKIP
, 1);
120 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
121 OhciSetEDField (Ed
, ED_ENDPT_NUM
, 0);
122 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
123 OhciSetEDField (Ed
, ED_SPEED
, DeviceSpeed
);
124 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
125 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
126 OhciSetEDField (Ed
, ED_PDATA
, 0);
127 OhciSetEDField (Ed
, ED_ZERO
, 0);
128 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, (UINT32
) NULL
);
129 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, (UINT32
) NULL
);
130 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, (UINT32
) NULL
);
131 OhciAttachEDToList (Ohc
, CONTROL_LIST
, Ed
, NULL
);
135 if(Request
!= NULL
) {
136 ReqMapPhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Request
;
138 SetupTd
= OhciCreateTD (Ohc
);
139 if (SetupTd
== NULL
) {
140 Status
= EFI_OUT_OF_RESOURCES
;
141 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Setup TD buffer\n"));
145 OhciSetTDField (SetupTd
, TD_PDATA
, 0);
146 OhciSetTDField (SetupTd
, TD_BUFFER_ROUND
, 1);
147 OhciSetTDField (SetupTd
, TD_DIR_PID
, TD_SETUP_PID
);
148 OhciSetTDField (SetupTd
, TD_DELAY_INT
, TD_NO_DELAY
);
149 OhciSetTDField (SetupTd
, TD_DT_TOGGLE
, 2);
150 OhciSetTDField (SetupTd
, TD_ERROR_CNT
, 0);
151 OhciSetTDField (SetupTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
152 OhciSetTDField (SetupTd
, TD_CURR_BUFFER_PTR
, (UINTN
)ReqMapPhyAddr
);
153 OhciSetTDField (SetupTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
154 OhciSetTDField (SetupTd
, TD_BUFFER_END_PTR
, (UINTN
)ReqMapPhyAddr
+ sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
155 SetupTd
->ActualSendLength
= 0;
156 SetupTd
->DataBuffer
= NULL
;
157 SetupTd
->NextTDPointer
= NULL
;
159 DataMapLength
= *DataLength
;
160 if ((Data
!= NULL
) && (DataMapLength
!= 0)) {
161 DataMapPhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
;
166 LeftLength
= DataMapLength
;
167 ActualSendLength
= DataMapLength
;
169 while (LeftLength
> 0) {
170 ActualSendLength
= LeftLength
;
171 if (LeftLength
> MaxPacketLength
) {
172 ActualSendLength
= MaxPacketLength
;
174 DataTd
= OhciCreateTD (Ohc
);
175 if (DataTd
== NULL
) {
176 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Data TD buffer\n"));
177 Status
= EFI_OUT_OF_RESOURCES
;
180 OhciSetTDField (DataTd
, TD_PDATA
, 0);
181 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
182 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
183 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
184 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, DataToggle
);
185 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
186 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
187 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) DataMapPhyAddr
);
188 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
) DataMapPhyAddr
+ ActualSendLength
- 1);
189 OhciSetTDField (DataTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
190 DataTd
->ActualSendLength
= ActualSendLength
;
191 DataTd
->DataBuffer
= (UINT8
*)(UINTN
)DataMapPhyAddr
;
192 DataTd
->NextTDPointer
= 0;
193 OhciLinkTD (HeadTd
, DataTd
);
195 DataMapPhyAddr
+= ActualSendLength
;
196 LeftLength
-= ActualSendLength
;
201 StatusTd
= OhciCreateTD (Ohc
);
202 if (StatusTd
== NULL
) {
203 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Status TD buffer\n"));
204 Status
= EFI_OUT_OF_RESOURCES
;
207 OhciSetTDField (StatusTd
, TD_PDATA
, 0);
208 OhciSetTDField (StatusTd
, TD_BUFFER_ROUND
, 1);
209 OhciSetTDField (StatusTd
, TD_DIR_PID
, StatusPidDir
);
210 OhciSetTDField (StatusTd
, TD_DELAY_INT
, 7);
211 OhciSetTDField (StatusTd
, TD_DT_TOGGLE
, 3);
212 OhciSetTDField (StatusTd
, TD_ERROR_CNT
, 0);
213 OhciSetTDField (StatusTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
214 OhciSetTDField (StatusTd
, TD_CURR_BUFFER_PTR
, (UINT32
) NULL
);
215 OhciSetTDField (StatusTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
216 OhciSetTDField (StatusTd
, TD_BUFFER_END_PTR
, (UINT32
) NULL
);
217 StatusTd
->ActualSendLength
= 0;
218 StatusTd
->DataBuffer
= NULL
;
219 StatusTd
->NextTDPointer
= NULL
;
220 OhciLinkTD (HeadTd
, StatusTd
);
224 EmptyTd
= OhciCreateTD (Ohc
);
225 if (EmptyTd
== NULL
) {
226 Status
= EFI_OUT_OF_RESOURCES
;
227 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Empty TD buffer\n"));
230 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
231 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
232 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
233 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
234 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
235 EmptyTd
->Word0
.DataToggle
= 0;
236 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
237 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
238 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
239 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
240 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
241 EmptyTd
->ActualSendLength
= 0;
242 EmptyTd
->DataBuffer
= NULL
;
243 EmptyTd
->NextTDPointer
= NULL
;
244 OhciLinkTD (HeadTd
, EmptyTd
);
245 Ed
->TdTailPointer
= EmptyTd
;
246 OhciAttachTDListToED (Ed
, HeadTd
);
248 OhciSetEDField (Ed
, ED_SKIP
, 0);
249 MicroSecondDelay (20 * HC_1_MILLISECOND
);
250 OhciSetHcCommandStatus (Ohc
, CONTROL_LIST_FILLED
, 1);
251 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 1);
252 MicroSecondDelay (20 * HC_1_MILLISECOND
);
253 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 1) {
254 MicroSecondDelay (HC_1_MILLISECOND
);
255 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 1) {
256 *TransferResult
= EFI_USB_ERR_SYSTEM
;
257 Status
= EFI_DEVICE_ERROR
;
258 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to enable CONTROL transfer\n"));
264 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &ErrorCode
);
266 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
267 MicroSecondDelay (HC_1_MILLISECOND
);
269 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &ErrorCode
);
272 *TransferResult
= ConvertErrorCode (ErrorCode
);
274 if (ErrorCode
!= TD_NO_ERROR
) {
275 if (ErrorCode
== TD_TOBE_PROCESSED
) {
276 DEBUG ((EFI_D_INFO
, "Control pipe timeout, > %d mS\r\n", TimeOut
));
278 DEBUG ((EFI_D_INFO
, "Control pipe broken\r\n"));
284 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 0);
285 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
286 MicroSecondDelay (HC_1_MILLISECOND
);
287 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
288 *TransferResult
= EFI_USB_ERR_SYSTEM
;
289 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n"));
297 HeadTd
= HeadTd
->NextTDPointer
;
298 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
302 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
308 Submits bulk transfer to a bulk endpoint of a USB device.
310 @param PeiServices The pointer of EFI_PEI_SERVICES.
311 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
312 @param DeviceAddress Target device address.
313 @param EndPointAddress Endpoint number and its direction in bit 7.
314 @param MaxiPacketLength Maximum packet size the endpoint is capable of
315 sending or receiving.
316 @param Data A pointers to the buffers of data to transmit
317 from or receive into.
318 @param DataLength The lenght of the data buffer.
319 @param DataToggle On input, the initial data toggle for the transfer;
320 On output, it is updated to to next data toggle to use of
321 the subsequent bulk transfer.
322 @param TimeOut Indicates the maximum time, in millisecond, which the
323 transfer is allowed to complete.
324 @param TransferResult A pointer to the detailed result information of the
327 @retval EFI_SUCCESS The transfer was completed successfully.
328 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
329 @retval EFI_INVALID_PARAMETER Parameters are invalid.
330 @retval EFI_TIMEOUT The transfer failed due to timeout.
331 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
337 IN EFI_PEI_SERVICES
**PeiServices
,
338 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
339 IN UINT8 DeviceAddress
,
340 IN UINT8 EndPointAddress
,
341 IN UINT8 MaxPacketLength
,
343 IN OUT UINTN
*DataLength
,
344 IN OUT UINT8
*DataToggle
,
346 OUT UINT32
*TransferResult
349 USB_OHCI_HC_DEV
*Ohc
;
352 TD_DESCRIPTOR
*HeadTd
;
353 TD_DESCRIPTOR
*DataTd
;
354 TD_DESCRIPTOR
*EmptyTd
;
362 EFI_PHYSICAL_ADDRESS MapPyhAddr
;
364 UINTN ActualSendLength
;
370 Status
= EFI_SUCCESS
;
372 if (Data
== NULL
|| DataLength
== NULL
|| DataToggle
== NULL
|| TransferResult
== NULL
||
373 *DataLength
== 0 || (*DataToggle
!= 0 && *DataToggle
!= 1) ||
374 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
375 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
376 return EFI_INVALID_PARAMETER
;
379 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
381 if ((EndPointAddress
& 0x80) != 0) {
382 DataPidDir
= TD_IN_PID
;
384 DataPidDir
= TD_OUT_PID
;
387 EndPointNum
= (EndPointAddress
& 0xF);
389 OhciSetHcControl (Ohc
, BULK_ENABLE
, 0);
390 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 0) {
391 MicroSecondDelay (HC_1_MILLISECOND
);
392 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 0) {
393 *TransferResult
= EFI_USB_ERR_SYSTEM
;
394 return EFI_DEVICE_ERROR
;
398 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
400 Ed
= OhciCreateED (Ohc
);
402 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
403 return EFI_OUT_OF_RESOURCES
;
405 OhciSetEDField (Ed
, ED_SKIP
, 1);
406 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
407 OhciSetEDField (Ed
, ED_ENDPT_NUM
, EndPointNum
);
408 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
409 OhciSetEDField (Ed
, ED_SPEED
, HI_SPEED
);
410 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
411 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
412 OhciSetEDField (Ed
, ED_PDATA
, 0);
413 OhciSetEDField (Ed
, ED_ZERO
, 0);
414 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, (UINT32
) NULL
);
415 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, (UINT32
) NULL
);
416 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, (UINT32
) NULL
);
417 OhciAttachEDToList (Ohc
, BULK_LIST
, Ed
, NULL
);
420 MapLength
= *DataLength
;
421 MapPyhAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
;
426 LeftLength
= MapLength
;
427 ActualSendLength
= MapLength
;
428 CurrentToggle
= *DataToggle
;
431 while (LeftLength
> 0) {
432 ActualSendLength
= LeftLength
;
433 if (LeftLength
> MaxPacketLength
) {
434 ActualSendLength
= MaxPacketLength
;
436 DataTd
= OhciCreateTD (Ohc
);
437 if (DataTd
== NULL
) {
438 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n"));
439 Status
= EFI_OUT_OF_RESOURCES
;
442 OhciSetTDField (DataTd
, TD_PDATA
, 0);
443 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
444 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
445 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
446 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, CurrentToggle
);
447 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
448 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
449 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) MapPyhAddr
);
450 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
) MapPyhAddr
+ ActualSendLength
- 1);
451 OhciSetTDField (DataTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
452 DataTd
->ActualSendLength
= ActualSendLength
;
453 DataTd
->DataBuffer
= (UINT8
*)(UINTN
)MapPyhAddr
;
454 DataTd
->NextTDPointer
= 0;
459 OhciLinkTD (HeadTd
, DataTd
);
462 MapPyhAddr
+= ActualSendLength
;
463 LeftLength
-= ActualSendLength
;
468 EmptyTd
= OhciCreateTD (Ohc
);
469 if (EmptyTd
== NULL
) {
470 Status
= EFI_OUT_OF_RESOURCES
;
471 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n"));
474 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
475 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
476 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
477 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
478 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
479 EmptyTd
->Word0
.DataToggle
= 0;
480 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
481 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
482 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
483 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
484 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
485 EmptyTd
->ActualSendLength
= 0;
486 EmptyTd
->DataBuffer
= NULL
;
487 EmptyTd
->NextTDPointer
= NULL
;
488 OhciLinkTD (HeadTd
, EmptyTd
);
489 Ed
->TdTailPointer
= EmptyTd
;
490 OhciAttachTDListToED (Ed
, HeadTd
);
492 OhciSetEDField (Ed
, ED_SKIP
, 0);
493 OhciSetHcCommandStatus (Ohc
, BULK_LIST_FILLED
, 1);
494 OhciSetHcControl (Ohc
, BULK_ENABLE
, 1);
495 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 1) {
496 MicroSecondDelay (HC_1_MILLISECOND
);
497 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 1) {
498 *TransferResult
= EFI_USB_ERR_SYSTEM
;
504 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &ErrorCode
);
506 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
507 MicroSecondDelay (HC_1_MILLISECOND
);
509 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &ErrorCode
);
512 *TransferResult
= ConvertErrorCode (ErrorCode
);
514 if (ErrorCode
!= TD_NO_ERROR
) {
515 if (ErrorCode
== TD_TOBE_PROCESSED
) {
516 DEBUG ((EFI_D_INFO
, "Bulk pipe timeout, > %d mS\r\n", TimeOut
));
518 DEBUG ((EFI_D_INFO
, "Bulk pipe broken\r\n"));
522 *DataToggle
= (UINT8
) OhciGetEDField (Ed
, ED_DTTOGGLE
);
527 HeadTd
= HeadTd
->NextTDPointer
;
528 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
530 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
535 Retrieves the number of root hub ports.
537 @param[in] PeiServices The pointer to the PEI Services Table.
538 @param[in] This The pointer to this instance of the
539 PEI_USB_HOST_CONTROLLER_PPI.
540 @param[out] NumOfPorts The pointer to the number of the root hub ports.
542 @retval EFI_SUCCESS The port number was retrieved successfully.
543 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
549 OhciGetRootHubNumOfPorts (
550 IN EFI_PEI_SERVICES
**PeiServices
,
551 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
552 OUT UINT8
*NumOfPorts
555 USB_OHCI_HC_DEV
*Ohc
;
556 if (NumOfPorts
== NULL
) {
557 return EFI_INVALID_PARAMETER
;
559 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
560 *NumOfPorts
= (UINT8
)OhciGetRootHubDescriptor(Ohc
, RH_NUM_DS_PORTS
);
565 Retrieves the current status of a USB root hub port.
567 @param PeiServices The pointer of EFI_PEI_SERVICES.
568 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
569 @param PortNumber The root hub port to retrieve the state from.
570 @param PortStatus Variable to receive the port state.
572 @retval EFI_SUCCESS The status of the USB root hub port specified.
573 by PortNumber was returned in PortStatus.
574 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
580 OhciGetRootHubPortStatus (
581 IN EFI_PEI_SERVICES
**PeiServices
,
582 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
584 OUT EFI_USB_PORT_STATUS
*PortStatus
587 USB_OHCI_HC_DEV
*Ohc
;
590 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
592 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
593 if (PortNumber
>= NumOfPorts
) {
594 return EFI_INVALID_PARAMETER
;
596 PortStatus
->PortStatus
= 0;
597 PortStatus
->PortChangeStatus
= 0;
599 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_CURR_CONNECT_STAT
)) {
600 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
602 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_ENABLE_STAT
)) {
603 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
605 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_SUSPEND_STAT
)) {
606 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
608 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_OC_INDICATOR
)) {
609 PortStatus
->PortStatus
|= USB_PORT_STAT_OVERCURRENT
;
611 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_RESET_STAT
)) {
612 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
614 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_POWER_STAT
)) {
615 PortStatus
->PortStatus
|= USB_PORT_STAT_POWER
;
617 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_LSDEVICE_ATTACHED
)) {
618 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
620 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
)) {
621 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
623 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
)) {
624 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
626 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
)) {
627 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_SUSPEND
;
629 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
)) {
630 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_OVERCURRENT
;
632 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
)) {
633 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_RESET
;
639 Sets a feature for the specified root hub port.
641 @param PeiServices The pointer of EFI_PEI_SERVICES
642 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI
643 @param PortNumber Root hub port to set.
644 @param PortFeature Feature to set.
646 @retval EFI_SUCCESS The feature specified by PortFeature was set.
647 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
648 @retval EFI_TIMEOUT The time out occurred.
654 OhciSetRootHubPortFeature (
655 IN EFI_PEI_SERVICES
**PeiServices
,
656 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
658 IN EFI_USB_PORT_FEATURE PortFeature
661 USB_OHCI_HC_DEV
*Ohc
;
666 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
667 if (PortNumber
>= NumOfPorts
) {
668 return EFI_INVALID_PARAMETER
;
671 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
673 Status
= EFI_SUCCESS
;
676 switch (PortFeature
) {
677 case EfiUsbPortPower
:
678 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_POWER
);
685 MicroSecondDelay (HC_1_MILLISECOND
);
687 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 0 &&
688 RetryTimes
< MAX_RETRY_TIMES
);
690 if (RetryTimes
>= MAX_RETRY_TIMES
) {
691 return EFI_DEVICE_ERROR
;
695 case EfiUsbPortReset
:
696 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_RESET
);
703 MicroSecondDelay (HC_1_MILLISECOND
);
705 } while ((OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 0 ||
706 OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT
) == 1) &&
707 RetryTimes
< MAX_RETRY_TIMES
);
709 if (RetryTimes
>= MAX_RETRY_TIMES
) {
710 return EFI_DEVICE_ERROR
;
713 OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
716 case EfiUsbPortEnable
:
717 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_ENABLE
);
724 MicroSecondDelay (HC_1_MILLISECOND
);;
726 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 0 &&
727 RetryTimes
< MAX_RETRY_TIMES
);
729 if (RetryTimes
>= MAX_RETRY_TIMES
) {
730 return EFI_DEVICE_ERROR
;
735 case EfiUsbPortSuspend
:
736 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_SUSPEND
);
743 MicroSecondDelay (HC_1_MILLISECOND
);;
745 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 0 &&
746 RetryTimes
< MAX_RETRY_TIMES
);
748 if (RetryTimes
>= MAX_RETRY_TIMES
) {
749 return EFI_DEVICE_ERROR
;
754 return EFI_INVALID_PARAMETER
;
761 Clears a feature for the specified root hub port.
763 @param PeiServices The pointer of EFI_PEI_SERVICES.
764 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
765 @param PortNumber Specifies the root hub port whose feature
766 is requested to be cleared.
767 @param PortFeature Indicates the feature selector associated with the
768 feature clear request.
770 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
771 for the USB root hub port specified by PortNumber.
772 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
778 OhciClearRootHubPortFeature (
779 IN EFI_PEI_SERVICES
**PeiServices
,
780 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
782 IN EFI_USB_PORT_FEATURE PortFeature
785 USB_OHCI_HC_DEV
*Ohc
;
791 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
792 if (PortNumber
>= NumOfPorts
) {
793 return EFI_INVALID_PARAMETER
;
796 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
798 Status
= EFI_SUCCESS
;
800 switch (PortFeature
) {
801 case EfiUsbPortEnable
:
802 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_ENABLE
);
809 MicroSecondDelay (HC_1_MILLISECOND
);
811 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 1 &&
812 RetryTimes
< MAX_RETRY_TIMES
);
814 if (RetryTimes
>= MAX_RETRY_TIMES
) {
815 return EFI_DEVICE_ERROR
;
819 case EfiUsbPortSuspend
:
820 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_SUSPEND_STATUS
);
827 MicroSecondDelay (HC_1_MILLISECOND
);
829 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 1 &&
830 RetryTimes
< MAX_RETRY_TIMES
);
832 if (RetryTimes
>= MAX_RETRY_TIMES
) {
833 return EFI_DEVICE_ERROR
;
837 case EfiUsbPortReset
:
840 case EfiUsbPortPower
:
841 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_POWER
);
848 MicroSecondDelay (HC_1_MILLISECOND
);
850 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 1 &&
851 RetryTimes
< MAX_RETRY_TIMES
);
853 if (RetryTimes
>= MAX_RETRY_TIMES
) {
854 return EFI_DEVICE_ERROR
;
858 case EfiUsbPortConnectChange
:
859 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
);
866 MicroSecondDelay (HC_1_MILLISECOND
);
868 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
) == 1 &&
869 RetryTimes
< MAX_RETRY_TIMES
);
871 if (RetryTimes
>= MAX_RETRY_TIMES
) {
872 return EFI_DEVICE_ERROR
;
876 case EfiUsbPortResetChange
:
877 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
884 MicroSecondDelay (HC_1_MILLISECOND
);
886 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 1 &&
887 RetryTimes
< MAX_RETRY_TIMES
);
889 if (RetryTimes
>= MAX_RETRY_TIMES
) {
890 return EFI_DEVICE_ERROR
;
895 case EfiUsbPortEnableChange
:
896 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
);
903 MicroSecondDelay (HC_1_MILLISECOND
);
905 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
) == 1 &&
906 RetryTimes
< MAX_RETRY_TIMES
);
908 if (RetryTimes
>= MAX_RETRY_TIMES
) {
909 return EFI_DEVICE_ERROR
;
913 case EfiUsbPortSuspendChange
:
914 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
);
921 MicroSecondDelay (HC_1_MILLISECOND
);
923 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
) == 1 &&
924 RetryTimes
< MAX_RETRY_TIMES
);
926 if (RetryTimes
>= MAX_RETRY_TIMES
) {
927 return EFI_DEVICE_ERROR
;
931 case EfiUsbPortOverCurrentChange
:
932 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
);
939 MicroSecondDelay (HC_1_MILLISECOND
);
941 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
) == 1 &&
942 RetryTimes
< MAX_RETRY_TIMES
);
944 if (RetryTimes
>= MAX_RETRY_TIMES
) {
945 return EFI_DEVICE_ERROR
;
950 return EFI_INVALID_PARAMETER
;
956 Provides software reset for the USB host controller.
958 @param This This EFI_USB_HC_PROTOCOL instance.
959 @param Attributes A bit mask of the reset operation to perform.
961 @retval EFI_SUCCESS The reset operation succeeded.
962 @retval EFI_INVALID_PARAMETER Attributes is not valid.
963 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
964 not currently supported by the host controller.
965 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
970 IN EFI_PEI_SERVICES
**PeiServices
,
971 IN USB_OHCI_HC_DEV
*Ohc
,
978 UINT32 PowerOnGoodTime
;
980 BOOLEAN Flag
= FALSE
;
982 if ((Attributes
& ~(EFI_USB_HC_RESET_GLOBAL
| EFI_USB_HC_RESET_HOST_CONTROLLER
)) != 0) {
983 return EFI_INVALID_PARAMETER
;
985 Status
= EFI_SUCCESS
;
987 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
988 MicroSecondDelay (50 * HC_1_MILLISECOND
);
989 Status
= OhciSetHcCommandStatus (Ohc
, HC_RESET
, HC_RESET
);
990 if (EFI_ERROR (Status
)) {
991 return EFI_DEVICE_ERROR
;
993 MicroSecondDelay (50 * HC_1_MILLISECOND
);
995 // Wait for host controller reset.
997 PowerOnGoodTime
= 50;
999 MicroSecondDelay (HC_1_MILLISECOND
);
1000 Data32
= OhciGetOperationalReg (Ohc
, HC_COMMAND_STATUS
);
1001 if ((Data32
& HC_RESET
) == 0) {
1005 }while(PowerOnGoodTime
--);
1007 return EFI_DEVICE_ERROR
;
1011 OhciSetFrameInterval (Ohc
, FRAME_INTERVAL
, 0x2edf);
1012 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
1013 Status
= OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_RESET
);
1014 if (EFI_ERROR (Status
)) {
1015 return EFI_DEVICE_ERROR
;
1017 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1020 // Initialize host controller operational registers
1022 OhciSetFrameInterval (Ohc
, FS_LARGEST_DATA_PACKET
, 0x2778);
1023 OhciSetFrameInterval (Ohc
, FRAME_INTERVAL
, 0x2edf);
1024 OhciSetPeriodicStart (Ohc
, 0x2a2f);
1025 OhciSetHcControl (Ohc
, CONTROL_BULK_RATIO
, 0x0);
1026 OhciSetHcCommandStatus (Ohc
, CONTROL_LIST_FILLED
| BULK_LIST_FILLED
, 0);
1027 OhciSetRootHubDescriptor (Ohc
, RH_PSWITCH_MODE
, 0);
1028 OhciSetRootHubDescriptor (Ohc
, RH_NO_PSWITCH
| RH_NOC_PROT
, 1);
1029 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
1030 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
1032 OhciSetRootHubDescriptor (Ohc
, RH_DEV_REMOVABLE
, 0);
1033 OhciSetRootHubDescriptor (Ohc
, RH_PORT_PWR_CTRL_MASK
, 0xffff);
1034 OhciSetRootHubStatus (Ohc
, RH_LOCAL_PSTAT_CHANGE
);
1035 OhciSetRootHubPortStatus (Ohc
, 0, RH_SET_PORT_POWER
);
1036 OhciGetRootHubNumOfPorts (PeiServices
, &Ohc
->UsbHostControllerPpi
, &NumOfPorts
);
1037 for (Index
= 0; Index
< NumOfPorts
; Index
++) {
1038 if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortReset
))) {
1039 MicroSecondDelay (200 * HC_1_MILLISECOND
);
1040 OhciClearRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortReset
);
1041 MicroSecondDelay (HC_1_MILLISECOND
);
1042 OhciSetRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortEnable
);
1043 MicroSecondDelay (HC_1_MILLISECOND
);
1047 Ohc
->MemPool
= UsbHcInitMemPool(TRUE
, 0);
1048 if(Ohc
->MemPool
== NULL
) {
1049 return EFI_OUT_OF_RESOURCES
;
1051 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
1052 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
1053 OhciSetHcControl (Ohc
, CONTROL_ENABLE
| BULK_ENABLE
, 1);
1054 OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_OPERATIONAL
);
1055 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1057 // Wait till first SOF occurs, and then clear it
1059 while (OhciGetHcInterruptStatus (Ohc
, START_OF_FRAME
) == 0);
1060 OhciClearInterruptStatus (Ohc
, START_OF_FRAME
);
1061 MicroSecondDelay (HC_1_MILLISECOND
);
1067 Submits control transfer to a target USB device.
1069 Calls underlying OhciControlTransfer to do work. This wrapper routine required
1070 on Quark so that USB DMA transfers do not cause an IMR violation.
1072 @param PeiServices The pointer of EFI_PEI_SERVICES.
1073 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
1074 @param DeviceAddress The target device address.
1075 @param DeviceSpeed Target device speed.
1076 @param MaximumPacketLength Maximum packet size the default control transfer
1077 endpoint is capable of sending or receiving.
1078 @param Request USB device request to send.
1079 @param TransferDirection Specifies the data direction for the data stage.
1080 @param Data Data buffer to be transmitted or received from USB device.
1081 @param DataLength The size (in bytes) of the data buffer.
1082 @param TimeOut Indicates the maximum timeout, in millisecond.
1083 @param TransferResult Return the result of this control transfer.
1085 @retval EFI_SUCCESS Transfer was completed successfully.
1086 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
1087 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1088 @retval EFI_TIMEOUT Transfer failed due to timeout.
1089 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
1094 RedirectOhciControlTransfer (
1095 IN EFI_PEI_SERVICES
**PeiServices
,
1096 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
1097 IN UINT8 DeviceAddress
,
1098 IN UINT8 DeviceSpeed
,
1099 IN UINT8 MaxPacketLength
,
1100 IN EFI_USB_DEVICE_REQUEST
*Request
,
1101 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1103 IN OUT UINTN
*DataLength
,
1105 OUT UINT32
*TransferResult
1109 EFI_USB_DEVICE_REQUEST
*NewRequest
;
1114 // Allocate memory external to IMR protected region for transfer data.
1116 Status
= PeiServicesAllocatePool (
1117 sizeof(EFI_USB_DEVICE_REQUEST
) + *DataLength
,
1120 ASSERT_EFI_ERROR (Status
);
1123 // Setup pointers to transfer buffers.
1125 NewRequest
= (EFI_USB_DEVICE_REQUEST
*) Alloc
;
1126 Alloc
+= sizeof(EFI_USB_DEVICE_REQUEST
);
1127 NewData
= (VOID
*) Alloc
;
1130 // Copy callers request packet into transfer request packet.
1132 if (Request
!= NULL
) {
1133 CopyMem (NewRequest
,Request
,sizeof(EFI_USB_DEVICE_REQUEST
));
1138 // Copy callers data into transfer data buffer.
1141 if (DataLength
> 0) {
1142 CopyMem (NewData
,Data
,*DataLength
);
1149 // Call underlying OhciControlTransfer to do work.
1151 Status
= OhciControlTransfer (
1166 // Copy transfer buffer back into callers buffer.
1168 if (Data
!= NULL
&& *DataLength
> 0) {
1169 CopyMem (Data
, NewData
, *DataLength
);
1176 Submits bulk transfer to a bulk endpoint of a USB device.
1178 Calls underlying OhciBulkTransfer to do work. This wrapper routine required
1179 on Quark so that USB DMA transfers do not cause an IMR violation.
1181 @param PeiServices The pointer of EFI_PEI_SERVICES.
1182 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
1183 @param DeviceAddress Target device address.
1184 @param EndPointAddress Endpoint number and its direction in bit 7.
1185 @param MaxiPacketLength Maximum packet size the endpoint is capable of
1186 sending or receiving.
1187 @param Data A pointers to the buffers of data to transmit
1188 from or receive into.
1189 @param DataLength The lenght of the data buffer.
1190 @param DataToggle On input, the initial data toggle for the transfer;
1191 On output, it is updated to to next data toggle to use of
1192 the subsequent bulk transfer.
1193 @param TimeOut Indicates the maximum time, in millisecond, which the
1194 transfer is allowed to complete.
1195 @param TransferResult A pointer to the detailed result information of the
1198 @retval EFI_SUCCESS The transfer was completed successfully.
1199 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1200 @retval EFI_INVALID_PARAMETER Parameters are invalid.
1201 @retval EFI_TIMEOUT The transfer failed due to timeout.
1202 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
1207 RedirectOhciBulkTransfer (
1208 IN EFI_PEI_SERVICES
**PeiServices
,
1209 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
1210 IN UINT8 DeviceAddress
,
1211 IN UINT8 EndPointAddress
,
1212 IN UINT8 MaxPacketLength
,
1214 IN OUT UINTN
*DataLength
,
1215 IN OUT UINT8
*DataToggle
,
1217 OUT UINT32
*TransferResult
1224 // Allocate memory external to IMR protected region for transfer data.
1226 Status
= PeiServicesAllocatePool (
1230 ASSERT_EFI_ERROR (Status
);
1233 // Copy callers data into transfer buffer.
1236 if (DataLength
> 0) {
1237 CopyMem (NewData
,Data
,*DataLength
);
1244 // Call underlying OhciBulkTransfer to do work.
1246 Status
= OhciBulkTransfer (
1260 // Copy transfer buffer back into callers buffer.
1262 if (Data
!= NULL
&& *DataLength
> 0) {
1263 CopyMem (Data
, NewData
, *DataLength
);
1270 @param FileHandle Handle of the file being invoked.
1271 @param PeiServices Describes the list of possible PEI Services.
1273 @retval EFI_SUCCESS PPI successfully installed.
1278 IN EFI_PEI_FILE_HANDLE FileHandle
,
1279 IN CONST EFI_PEI_SERVICES
**PeiServices
1283 PEI_USB_CONTROLLER_PPI
*ChipSetUsbControllerPpi
;
1286 UINTN ControllerType
;
1289 USB_OHCI_HC_DEV
*Ohc
;
1290 EFI_PHYSICAL_ADDRESS TempPtr
;
1294 // Shadow this PEIM to run from memory
1296 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1299 Status
= PeiServicesLocatePpi (
1300 &gPeiUsbControllerPpiGuid
,
1303 (VOID
**) &ChipSetUsbControllerPpi
1305 if (EFI_ERROR (Status
)) {
1306 return EFI_UNSUPPORTED
;
1311 Status
= ChipSetUsbControllerPpi
->GetUsbController (
1312 (EFI_PEI_SERVICES
**) PeiServices
,
1313 ChipSetUsbControllerPpi
,
1319 // When status is error, meant no controller is found
1321 if (EFI_ERROR (Status
)) {
1325 // This PEIM is for OHC type controller.
1327 if (ControllerType
!= PEI_OHCI_CONTROLLER
) {
1332 MemPages
= sizeof (USB_OHCI_HC_DEV
) / PAGESIZE
+ 1;
1333 Status
= PeiServicesAllocatePages (
1334 EfiBootServicesCode
,
1338 if (EFI_ERROR (Status
)) {
1339 DEBUG ((EFI_D_INFO
, "OhcPeimEntry: Fail to allocate buffer for the %dth OHCI ControllerPpi\n", Index
));
1340 return EFI_OUT_OF_RESOURCES
;
1342 ZeroMem((VOID
*)(UINTN
)TempPtr
, MemPages
*PAGESIZE
);
1343 Ohc
= (USB_OHCI_HC_DEV
*) ((UINTN
) TempPtr
);
1345 Ohc
->Signature
= USB_OHCI_HC_DEV_SIGNATURE
;
1347 Ohc
->UsbHostControllerBaseAddress
= (UINT32
) BaseAddress
;
1350 // Initialize Uhc's hardware
1352 Status
= InitializeUsbHC (
1353 (EFI_PEI_SERVICES
**)PeiServices
,
1355 EFI_USB_HC_RESET_GLOBAL
1357 if (EFI_ERROR (Status
)) {
1358 DEBUG ((EFI_D_INFO
, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index
));
1362 // Control & Bulk transfer services are accessed via their Redirect
1363 // routine versions on Quark so that USB DMA transfers do not cause an
1366 Ohc
->UsbHostControllerPpi
.ControlTransfer
= RedirectOhciControlTransfer
;
1367 Ohc
->UsbHostControllerPpi
.BulkTransfer
= RedirectOhciBulkTransfer
;
1368 Ohc
->UsbHostControllerPpi
.GetRootHubPortNumber
= OhciGetRootHubNumOfPorts
;
1369 Ohc
->UsbHostControllerPpi
.GetRootHubPortStatus
= OhciGetRootHubPortStatus
;
1370 Ohc
->UsbHostControllerPpi
.SetRootHubPortFeature
= OhciSetRootHubPortFeature
;
1371 Ohc
->UsbHostControllerPpi
.ClearRootHubPortFeature
= OhciClearRootHubPortFeature
;
1373 Ohc
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1374 Ohc
->PpiDescriptor
.Guid
= &gPeiUsbHostControllerPpiGuid
;
1375 Ohc
->PpiDescriptor
.Ppi
= &Ohc
->UsbHostControllerPpi
;
1377 Status
= PeiServicesInstallPpi (&Ohc
->PpiDescriptor
);
1378 if (EFI_ERROR (Status
)) {