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 Submits control transfer to a target USB device.
22 @param PeiServices The pointer of EFI_PEI_SERVICES.
23 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
24 @param DeviceAddress The target device address.
25 @param DeviceSpeed Target device speed.
26 @param MaximumPacketLength Maximum packet size the default control transfer
27 endpoint is capable of sending or receiving.
28 @param Request USB device request to send.
29 @param TransferDirection Specifies the data direction for the data stage.
30 @param Data Data buffer to be transmitted or received from USB device.
31 @param DataLength The size (in bytes) of the data buffer.
32 @param TimeOut Indicates the maximum timeout, in millisecond.
33 @param TransferResult Return the result of this control transfer.
35 @retval EFI_SUCCESS Transfer was completed successfully.
36 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
37 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
38 @retval EFI_TIMEOUT Transfer failed due to timeout.
39 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
45 IN EFI_PEI_SERVICES
**PeiServices
,
46 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
47 IN UINT8 DeviceAddress
,
49 IN UINT8 MaxPacketLength
,
50 IN EFI_USB_DEVICE_REQUEST
*Request
,
51 IN EFI_USB_DATA_DIRECTION TransferDirection
,
53 IN OUT UINTN
*DataLength
,
55 OUT UINT32
*TransferResult
60 TD_DESCRIPTOR
*HeadTd
;
61 TD_DESCRIPTOR
*SetupTd
;
62 TD_DESCRIPTOR
*DataTd
;
63 TD_DESCRIPTOR
*StatusTd
;
64 TD_DESCRIPTOR
*EmptyTd
;
71 UINTN ActualSendLength
;
75 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr
= 0;
77 UINTN DataMapLength
= 0;
78 EFI_PHYSICAL_ADDRESS DataMapPhyAddr
= 0;
83 if ((TransferDirection
!= EfiUsbDataOut
&& TransferDirection
!= EfiUsbDataIn
&&
84 TransferDirection
!= EfiUsbNoData
) ||
85 Request
== NULL
|| DataLength
== NULL
|| TransferResult
== NULL
||
86 (TransferDirection
== EfiUsbNoData
&& (*DataLength
!= 0 || Data
!= NULL
)) ||
87 (TransferDirection
!= EfiUsbNoData
&& (*DataLength
== 0 || Data
== NULL
)) ||
88 (DeviceSpeed
!= EFI_USB_SPEED_LOW
&& DeviceSpeed
!= EFI_USB_SPEED_FULL
) ||
89 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
90 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
91 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: EFI_INVALID_PARAMETER\n"));
92 return EFI_INVALID_PARAMETER
;
95 if (*DataLength
> MAX_BYTES_PER_TD
) {
96 DEBUG ((EFI_D_ERROR
, "OhciControlTransfer: Request data size is too large\n"));
97 return EFI_INVALID_PARAMETER
;
100 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This
);
102 if (TransferDirection
== EfiUsbDataIn
) {
103 DataPidDir
= TD_IN_PID
;
104 StatusPidDir
= TD_OUT_PID
;
106 DataPidDir
= TD_OUT_PID
;
107 StatusPidDir
= TD_IN_PID
;
110 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 0);
111 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
112 MicroSecondDelay (HC_1_MILLISECOND
);
113 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
114 *TransferResult
= EFI_USB_ERR_SYSTEM
;
115 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to disable CONTROL transfer\n"));
116 return EFI_DEVICE_ERROR
;
119 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
120 Ed
= OhciCreateED (Ohc
);
122 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate ED buffer\n"));
123 return EFI_OUT_OF_RESOURCES
;
125 OhciSetEDField (Ed
, ED_SKIP
, 1);
126 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
127 OhciSetEDField (Ed
, ED_ENDPT_NUM
, 0);
128 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
129 OhciSetEDField (Ed
, ED_SPEED
, DeviceSpeed
);
130 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
131 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
132 OhciSetEDField (Ed
, ED_PDATA
, 0);
133 OhciSetEDField (Ed
, ED_ZERO
, 0);
134 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, (UINT32
) NULL
);
135 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, (UINT32
) NULL
);
136 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, (UINT32
) NULL
);
137 OhciAttachEDToList (Ohc
, CONTROL_LIST
, Ed
, NULL
);
141 if(Request
!= NULL
) {
142 ReqMapPhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Request
;
144 SetupTd
= OhciCreateTD (Ohc
);
145 if (SetupTd
== NULL
) {
146 Status
= EFI_OUT_OF_RESOURCES
;
147 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Setup TD buffer\n"));
151 OhciSetTDField (SetupTd
, TD_PDATA
, 0);
152 OhciSetTDField (SetupTd
, TD_BUFFER_ROUND
, 1);
153 OhciSetTDField (SetupTd
, TD_DIR_PID
, TD_SETUP_PID
);
154 OhciSetTDField (SetupTd
, TD_DELAY_INT
, TD_NO_DELAY
);
155 OhciSetTDField (SetupTd
, TD_DT_TOGGLE
, 2);
156 OhciSetTDField (SetupTd
, TD_ERROR_CNT
, 0);
157 OhciSetTDField (SetupTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
158 OhciSetTDField (SetupTd
, TD_CURR_BUFFER_PTR
, (UINTN
)ReqMapPhyAddr
);
159 OhciSetTDField (SetupTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
160 OhciSetTDField (SetupTd
, TD_BUFFER_END_PTR
, (UINTN
)ReqMapPhyAddr
+ sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
161 SetupTd
->ActualSendLength
= 0;
162 SetupTd
->DataBuffer
= NULL
;
163 SetupTd
->NextTDPointer
= NULL
;
165 DataMapLength
= *DataLength
;
166 if ((Data
!= NULL
) && (DataMapLength
!= 0)) {
167 DataMapPhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
;
172 LeftLength
= DataMapLength
;
173 ActualSendLength
= DataMapLength
;
175 while (LeftLength
> 0) {
176 ActualSendLength
= LeftLength
;
177 if (LeftLength
> MaxPacketLength
) {
178 ActualSendLength
= MaxPacketLength
;
180 DataTd
= OhciCreateTD (Ohc
);
181 if (DataTd
== NULL
) {
182 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Data TD buffer\n"));
183 Status
= EFI_OUT_OF_RESOURCES
;
186 OhciSetTDField (DataTd
, TD_PDATA
, 0);
187 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
188 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
189 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
190 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, DataToggle
);
191 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
192 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
193 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) DataMapPhyAddr
);
194 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
) DataMapPhyAddr
+ ActualSendLength
- 1);
195 OhciSetTDField (DataTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
196 DataTd
->ActualSendLength
= ActualSendLength
;
197 DataTd
->DataBuffer
= (UINT8
*)(UINTN
)DataMapPhyAddr
;
198 DataTd
->NextTDPointer
= 0;
199 OhciLinkTD (HeadTd
, DataTd
);
201 DataMapPhyAddr
+= ActualSendLength
;
202 LeftLength
-= ActualSendLength
;
207 StatusTd
= OhciCreateTD (Ohc
);
208 if (StatusTd
== NULL
) {
209 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Status TD buffer\n"));
210 Status
= EFI_OUT_OF_RESOURCES
;
213 OhciSetTDField (StatusTd
, TD_PDATA
, 0);
214 OhciSetTDField (StatusTd
, TD_BUFFER_ROUND
, 1);
215 OhciSetTDField (StatusTd
, TD_DIR_PID
, StatusPidDir
);
216 OhciSetTDField (StatusTd
, TD_DELAY_INT
, 7);
217 OhciSetTDField (StatusTd
, TD_DT_TOGGLE
, 3);
218 OhciSetTDField (StatusTd
, TD_ERROR_CNT
, 0);
219 OhciSetTDField (StatusTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
220 OhciSetTDField (StatusTd
, TD_CURR_BUFFER_PTR
, (UINT32
) NULL
);
221 OhciSetTDField (StatusTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
222 OhciSetTDField (StatusTd
, TD_BUFFER_END_PTR
, (UINT32
) NULL
);
223 StatusTd
->ActualSendLength
= 0;
224 StatusTd
->DataBuffer
= NULL
;
225 StatusTd
->NextTDPointer
= NULL
;
226 OhciLinkTD (HeadTd
, StatusTd
);
230 EmptyTd
= OhciCreateTD (Ohc
);
231 if (EmptyTd
== NULL
) {
232 Status
= EFI_OUT_OF_RESOURCES
;
233 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Empty TD buffer\n"));
236 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
237 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
238 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
239 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
240 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
241 EmptyTd
->Word0
.DataToggle
= 0;
242 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
243 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
244 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
245 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
246 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
247 EmptyTd
->ActualSendLength
= 0;
248 EmptyTd
->DataBuffer
= NULL
;
249 EmptyTd
->NextTDPointer
= NULL
;
250 OhciLinkTD (HeadTd
, EmptyTd
);
251 Ed
->TdTailPointer
= EmptyTd
;
252 OhciAttachTDListToED (Ed
, HeadTd
);
254 OhciSetEDField (Ed
, ED_SKIP
, 0);
255 MicroSecondDelay (20 * HC_1_MILLISECOND
);
256 OhciSetHcCommandStatus (Ohc
, CONTROL_LIST_FILLED
, 1);
257 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 1);
258 MicroSecondDelay (20 * HC_1_MILLISECOND
);
259 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 1) {
260 MicroSecondDelay (HC_1_MILLISECOND
);
261 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 1) {
262 *TransferResult
= EFI_USB_ERR_SYSTEM
;
263 Status
= EFI_DEVICE_ERROR
;
264 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to enable CONTROL transfer\n"));
270 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &ErrorCode
);
272 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
273 MicroSecondDelay (HC_1_MILLISECOND
);
275 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &ErrorCode
);
278 *TransferResult
= ConvertErrorCode (ErrorCode
);
280 if (ErrorCode
!= TD_NO_ERROR
) {
281 if (ErrorCode
== TD_TOBE_PROCESSED
) {
282 DEBUG ((EFI_D_INFO
, "Control pipe timeout, > %d mS\r\n", TimeOut
));
284 DEBUG ((EFI_D_INFO
, "Control pipe broken\r\n"));
290 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 0);
291 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
292 MicroSecondDelay (HC_1_MILLISECOND
);
293 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
294 *TransferResult
= EFI_USB_ERR_SYSTEM
;
295 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n"));
303 HeadTd
= HeadTd
->NextTDPointer
;
304 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
308 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
314 Submits bulk transfer to a bulk endpoint of a USB device.
316 @param PeiServices The pointer of EFI_PEI_SERVICES.
317 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
318 @param DeviceAddress Target device address.
319 @param EndPointAddress Endpoint number and its direction in bit 7.
320 @param MaxiPacketLength Maximum packet size the endpoint is capable of
321 sending or receiving.
322 @param Data A pointers to the buffers of data to transmit
323 from or receive into.
324 @param DataLength The lenght of the data buffer.
325 @param DataToggle On input, the initial data toggle for the transfer;
326 On output, it is updated to to next data toggle to use of
327 the subsequent bulk transfer.
328 @param TimeOut Indicates the maximum time, in millisecond, which the
329 transfer is allowed to complete.
330 @param TransferResult A pointer to the detailed result information of the
333 @retval EFI_SUCCESS The transfer was completed successfully.
334 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
335 @retval EFI_INVALID_PARAMETER Parameters are invalid.
336 @retval EFI_TIMEOUT The transfer failed due to timeout.
337 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
343 IN EFI_PEI_SERVICES
**PeiServices
,
344 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
345 IN UINT8 DeviceAddress
,
346 IN UINT8 EndPointAddress
,
347 IN UINT8 MaxPacketLength
,
349 IN OUT UINTN
*DataLength
,
350 IN OUT UINT8
*DataToggle
,
352 OUT UINT32
*TransferResult
355 USB_OHCI_HC_DEV
*Ohc
;
358 TD_DESCRIPTOR
*HeadTd
;
359 TD_DESCRIPTOR
*DataTd
;
360 TD_DESCRIPTOR
*EmptyTd
;
368 EFI_PHYSICAL_ADDRESS MapPyhAddr
;
370 UINTN ActualSendLength
;
376 Status
= EFI_SUCCESS
;
378 if (Data
== NULL
|| DataLength
== NULL
|| DataToggle
== NULL
|| TransferResult
== NULL
||
379 *DataLength
== 0 || (*DataToggle
!= 0 && *DataToggle
!= 1) ||
380 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
381 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
382 return EFI_INVALID_PARAMETER
;
385 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
387 if ((EndPointAddress
& 0x80) != 0) {
388 DataPidDir
= TD_IN_PID
;
390 DataPidDir
= TD_OUT_PID
;
393 EndPointNum
= (EndPointAddress
& 0xF);
395 OhciSetHcControl (Ohc
, BULK_ENABLE
, 0);
396 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 0) {
397 MicroSecondDelay (HC_1_MILLISECOND
);
398 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 0) {
399 *TransferResult
= EFI_USB_ERR_SYSTEM
;
400 return EFI_DEVICE_ERROR
;
404 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
406 Ed
= OhciCreateED (Ohc
);
408 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
409 return EFI_OUT_OF_RESOURCES
;
411 OhciSetEDField (Ed
, ED_SKIP
, 1);
412 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
413 OhciSetEDField (Ed
, ED_ENDPT_NUM
, EndPointNum
);
414 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
415 OhciSetEDField (Ed
, ED_SPEED
, HI_SPEED
);
416 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
417 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
418 OhciSetEDField (Ed
, ED_PDATA
, 0);
419 OhciSetEDField (Ed
, ED_ZERO
, 0);
420 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, (UINT32
) NULL
);
421 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, (UINT32
) NULL
);
422 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, (UINT32
) NULL
);
423 OhciAttachEDToList (Ohc
, BULK_LIST
, Ed
, NULL
);
426 MapLength
= *DataLength
;
427 MapPyhAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
;
432 LeftLength
= MapLength
;
433 ActualSendLength
= MapLength
;
434 CurrentToggle
= *DataToggle
;
437 while (LeftLength
> 0) {
438 ActualSendLength
= LeftLength
;
439 if (LeftLength
> MaxPacketLength
) {
440 ActualSendLength
= MaxPacketLength
;
442 DataTd
= OhciCreateTD (Ohc
);
443 if (DataTd
== NULL
) {
444 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n"));
445 Status
= EFI_OUT_OF_RESOURCES
;
448 OhciSetTDField (DataTd
, TD_PDATA
, 0);
449 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
450 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
451 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
452 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, CurrentToggle
);
453 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
454 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
455 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) MapPyhAddr
);
456 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
) MapPyhAddr
+ ActualSendLength
- 1);
457 OhciSetTDField (DataTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
458 DataTd
->ActualSendLength
= ActualSendLength
;
459 DataTd
->DataBuffer
= (UINT8
*)(UINTN
)MapPyhAddr
;
460 DataTd
->NextTDPointer
= 0;
465 OhciLinkTD (HeadTd
, DataTd
);
468 MapPyhAddr
+= ActualSendLength
;
469 LeftLength
-= ActualSendLength
;
474 EmptyTd
= OhciCreateTD (Ohc
);
475 if (EmptyTd
== NULL
) {
476 Status
= EFI_OUT_OF_RESOURCES
;
477 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n"));
480 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
481 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
482 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
483 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
484 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
485 EmptyTd
->Word0
.DataToggle
= 0;
486 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
487 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
488 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
489 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
490 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
491 EmptyTd
->ActualSendLength
= 0;
492 EmptyTd
->DataBuffer
= NULL
;
493 EmptyTd
->NextTDPointer
= NULL
;
494 OhciLinkTD (HeadTd
, EmptyTd
);
495 Ed
->TdTailPointer
= EmptyTd
;
496 OhciAttachTDListToED (Ed
, HeadTd
);
498 OhciSetEDField (Ed
, ED_SKIP
, 0);
499 OhciSetHcCommandStatus (Ohc
, BULK_LIST_FILLED
, 1);
500 OhciSetHcControl (Ohc
, BULK_ENABLE
, 1);
501 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 1) {
502 MicroSecondDelay (HC_1_MILLISECOND
);
503 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 1) {
504 *TransferResult
= EFI_USB_ERR_SYSTEM
;
510 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &ErrorCode
);
512 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
513 MicroSecondDelay (HC_1_MILLISECOND
);
515 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &ErrorCode
);
518 *TransferResult
= ConvertErrorCode (ErrorCode
);
520 if (ErrorCode
!= TD_NO_ERROR
) {
521 if (ErrorCode
== TD_TOBE_PROCESSED
) {
522 DEBUG ((EFI_D_INFO
, "Bulk pipe timeout, > %d mS\r\n", TimeOut
));
524 DEBUG ((EFI_D_INFO
, "Bulk pipe broken\r\n"));
528 *DataToggle
= (UINT8
) OhciGetEDField (Ed
, ED_DTTOGGLE
);
533 HeadTd
= HeadTd
->NextTDPointer
;
534 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
536 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
541 Retrieves the number of root hub ports.
543 @param[in] PeiServices The pointer to the PEI Services Table.
544 @param[in] This The pointer to this instance of the
545 PEI_USB_HOST_CONTROLLER_PPI.
546 @param[out] NumOfPorts The pointer to the number of the root hub ports.
548 @retval EFI_SUCCESS The port number was retrieved successfully.
549 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
555 OhciGetRootHubNumOfPorts (
556 IN EFI_PEI_SERVICES
**PeiServices
,
557 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
558 OUT UINT8
*NumOfPorts
561 USB_OHCI_HC_DEV
*Ohc
;
562 if (NumOfPorts
== NULL
) {
563 return EFI_INVALID_PARAMETER
;
565 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
566 *NumOfPorts
= (UINT8
)OhciGetRootHubDescriptor(Ohc
, RH_NUM_DS_PORTS
);
571 Retrieves the current status of a USB root hub port.
573 @param PeiServices The pointer of EFI_PEI_SERVICES.
574 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
575 @param PortNumber The root hub port to retrieve the state from.
576 @param PortStatus Variable to receive the port state.
578 @retval EFI_SUCCESS The status of the USB root hub port specified.
579 by PortNumber was returned in PortStatus.
580 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
586 OhciGetRootHubPortStatus (
587 IN EFI_PEI_SERVICES
**PeiServices
,
588 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
590 OUT EFI_USB_PORT_STATUS
*PortStatus
593 USB_OHCI_HC_DEV
*Ohc
;
596 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
598 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
599 if (PortNumber
>= NumOfPorts
) {
600 return EFI_INVALID_PARAMETER
;
602 PortStatus
->PortStatus
= 0;
603 PortStatus
->PortChangeStatus
= 0;
605 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_CURR_CONNECT_STAT
)) {
606 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
608 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_ENABLE_STAT
)) {
609 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
611 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_SUSPEND_STAT
)) {
612 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
614 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_OC_INDICATOR
)) {
615 PortStatus
->PortStatus
|= USB_PORT_STAT_OVERCURRENT
;
617 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_RESET_STAT
)) {
618 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
620 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_POWER_STAT
)) {
621 PortStatus
->PortStatus
|= USB_PORT_STAT_POWER
;
623 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_LSDEVICE_ATTACHED
)) {
624 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
626 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
)) {
627 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
629 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
)) {
630 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
632 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
)) {
633 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_SUSPEND
;
635 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
)) {
636 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_OVERCURRENT
;
638 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
)) {
639 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_RESET
;
645 Sets a feature for the specified root hub port.
647 @param PeiServices The pointer of EFI_PEI_SERVICES
648 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI
649 @param PortNumber Root hub port to set.
650 @param PortFeature Feature to set.
652 @retval EFI_SUCCESS The feature specified by PortFeature was set.
653 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
654 @retval EFI_TIMEOUT The time out occurred.
660 OhciSetRootHubPortFeature (
661 IN EFI_PEI_SERVICES
**PeiServices
,
662 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
664 IN EFI_USB_PORT_FEATURE PortFeature
667 USB_OHCI_HC_DEV
*Ohc
;
672 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
673 if (PortNumber
>= NumOfPorts
) {
674 return EFI_INVALID_PARAMETER
;
677 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
679 Status
= EFI_SUCCESS
;
682 switch (PortFeature
) {
683 case EfiUsbPortPower
:
684 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_POWER
);
691 MicroSecondDelay (HC_1_MILLISECOND
);
693 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 0 &&
694 RetryTimes
< MAX_RETRY_TIMES
);
696 if (RetryTimes
>= MAX_RETRY_TIMES
) {
697 return EFI_DEVICE_ERROR
;
701 case EfiUsbPortReset
:
702 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_RESET
);
709 MicroSecondDelay (HC_1_MILLISECOND
);
711 } while ((OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 0 ||
712 OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT
) == 1) &&
713 RetryTimes
< MAX_RETRY_TIMES
);
715 if (RetryTimes
>= MAX_RETRY_TIMES
) {
716 return EFI_DEVICE_ERROR
;
719 OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
722 case EfiUsbPortEnable
:
723 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_ENABLE
);
730 MicroSecondDelay (HC_1_MILLISECOND
);;
732 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 0 &&
733 RetryTimes
< MAX_RETRY_TIMES
);
735 if (RetryTimes
>= MAX_RETRY_TIMES
) {
736 return EFI_DEVICE_ERROR
;
741 case EfiUsbPortSuspend
:
742 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_SUSPEND
);
749 MicroSecondDelay (HC_1_MILLISECOND
);;
751 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 0 &&
752 RetryTimes
< MAX_RETRY_TIMES
);
754 if (RetryTimes
>= MAX_RETRY_TIMES
) {
755 return EFI_DEVICE_ERROR
;
760 return EFI_INVALID_PARAMETER
;
767 Clears a feature for the specified root hub port.
769 @param PeiServices The pointer of EFI_PEI_SERVICES.
770 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
771 @param PortNumber Specifies the root hub port whose feature
772 is requested to be cleared.
773 @param PortFeature Indicates the feature selector associated with the
774 feature clear request.
776 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
777 for the USB root hub port specified by PortNumber.
778 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
784 OhciClearRootHubPortFeature (
785 IN EFI_PEI_SERVICES
**PeiServices
,
786 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
788 IN EFI_USB_PORT_FEATURE PortFeature
791 USB_OHCI_HC_DEV
*Ohc
;
797 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
798 if (PortNumber
>= NumOfPorts
) {
799 return EFI_INVALID_PARAMETER
;
802 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
804 Status
= EFI_SUCCESS
;
806 switch (PortFeature
) {
807 case EfiUsbPortEnable
:
808 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_ENABLE
);
815 MicroSecondDelay (HC_1_MILLISECOND
);
817 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 1 &&
818 RetryTimes
< MAX_RETRY_TIMES
);
820 if (RetryTimes
>= MAX_RETRY_TIMES
) {
821 return EFI_DEVICE_ERROR
;
825 case EfiUsbPortSuspend
:
826 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_SUSPEND_STATUS
);
833 MicroSecondDelay (HC_1_MILLISECOND
);
835 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 1 &&
836 RetryTimes
< MAX_RETRY_TIMES
);
838 if (RetryTimes
>= MAX_RETRY_TIMES
) {
839 return EFI_DEVICE_ERROR
;
843 case EfiUsbPortReset
:
846 case EfiUsbPortPower
:
847 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_POWER
);
854 MicroSecondDelay (HC_1_MILLISECOND
);
856 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 1 &&
857 RetryTimes
< MAX_RETRY_TIMES
);
859 if (RetryTimes
>= MAX_RETRY_TIMES
) {
860 return EFI_DEVICE_ERROR
;
864 case EfiUsbPortConnectChange
:
865 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
);
872 MicroSecondDelay (HC_1_MILLISECOND
);
874 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
) == 1 &&
875 RetryTimes
< MAX_RETRY_TIMES
);
877 if (RetryTimes
>= MAX_RETRY_TIMES
) {
878 return EFI_DEVICE_ERROR
;
882 case EfiUsbPortResetChange
:
883 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
890 MicroSecondDelay (HC_1_MILLISECOND
);
892 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 1 &&
893 RetryTimes
< MAX_RETRY_TIMES
);
895 if (RetryTimes
>= MAX_RETRY_TIMES
) {
896 return EFI_DEVICE_ERROR
;
901 case EfiUsbPortEnableChange
:
902 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
);
909 MicroSecondDelay (HC_1_MILLISECOND
);
911 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
) == 1 &&
912 RetryTimes
< MAX_RETRY_TIMES
);
914 if (RetryTimes
>= MAX_RETRY_TIMES
) {
915 return EFI_DEVICE_ERROR
;
919 case EfiUsbPortSuspendChange
:
920 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
);
927 MicroSecondDelay (HC_1_MILLISECOND
);
929 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
) == 1 &&
930 RetryTimes
< MAX_RETRY_TIMES
);
932 if (RetryTimes
>= MAX_RETRY_TIMES
) {
933 return EFI_DEVICE_ERROR
;
937 case EfiUsbPortOverCurrentChange
:
938 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
);
945 MicroSecondDelay (HC_1_MILLISECOND
);
947 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
) == 1 &&
948 RetryTimes
< MAX_RETRY_TIMES
);
950 if (RetryTimes
>= MAX_RETRY_TIMES
) {
951 return EFI_DEVICE_ERROR
;
956 return EFI_INVALID_PARAMETER
;
962 Provides software reset for the USB host controller.
964 @param This This EFI_USB_HC_PROTOCOL instance.
965 @param Attributes A bit mask of the reset operation to perform.
967 @retval EFI_SUCCESS The reset operation succeeded.
968 @retval EFI_INVALID_PARAMETER Attributes is not valid.
969 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
970 not currently supported by the host controller.
971 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
976 IN EFI_PEI_SERVICES
**PeiServices
,
977 IN USB_OHCI_HC_DEV
*Ohc
,
984 UINT32 PowerOnGoodTime
;
986 BOOLEAN Flag
= FALSE
;
988 if ((Attributes
& ~(EFI_USB_HC_RESET_GLOBAL
| EFI_USB_HC_RESET_HOST_CONTROLLER
)) != 0) {
989 return EFI_INVALID_PARAMETER
;
991 Status
= EFI_SUCCESS
;
993 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
994 MicroSecondDelay (50 * HC_1_MILLISECOND
);
995 Status
= OhciSetHcCommandStatus (Ohc
, HC_RESET
, HC_RESET
);
996 if (EFI_ERROR (Status
)) {
997 return EFI_DEVICE_ERROR
;
999 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1001 // Wait for host controller reset.
1003 PowerOnGoodTime
= 50;
1005 MicroSecondDelay (HC_1_MILLISECOND
);
1006 Data32
= OhciGetOperationalReg (Ohc
, HC_COMMAND_STATUS
);
1007 if ((Data32
& HC_RESET
) == 0) {
1011 }while(PowerOnGoodTime
--);
1013 return EFI_DEVICE_ERROR
;
1017 OhciSetFrameInterval (Ohc
, FRAME_INTERVAL
, 0x2edf);
1018 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
1019 Status
= OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_RESET
);
1020 if (EFI_ERROR (Status
)) {
1021 return EFI_DEVICE_ERROR
;
1023 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1026 // Initialize host controller operational registers
1028 OhciSetFrameInterval (Ohc
, FS_LARGEST_DATA_PACKET
, 0x2778);
1029 OhciSetFrameInterval (Ohc
, FRAME_INTERVAL
, 0x2edf);
1030 OhciSetPeriodicStart (Ohc
, 0x2a2f);
1031 OhciSetHcControl (Ohc
, CONTROL_BULK_RATIO
, 0x0);
1032 OhciSetHcCommandStatus (Ohc
, CONTROL_LIST_FILLED
| BULK_LIST_FILLED
, 0);
1033 OhciSetRootHubDescriptor (Ohc
, RH_PSWITCH_MODE
, 0);
1034 OhciSetRootHubDescriptor (Ohc
, RH_NO_PSWITCH
| RH_NOC_PROT
, 1);
1035 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
1036 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
1038 OhciSetRootHubDescriptor (Ohc
, RH_DEV_REMOVABLE
, 0);
1039 OhciSetRootHubDescriptor (Ohc
, RH_PORT_PWR_CTRL_MASK
, 0xffff);
1040 OhciSetRootHubStatus (Ohc
, RH_LOCAL_PSTAT_CHANGE
);
1041 OhciSetRootHubPortStatus (Ohc
, 0, RH_SET_PORT_POWER
);
1042 OhciGetRootHubNumOfPorts (PeiServices
, &Ohc
->UsbHostControllerPpi
, &NumOfPorts
);
1043 for (Index
= 0; Index
< NumOfPorts
; Index
++) {
1044 if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortReset
))) {
1045 MicroSecondDelay (200 * HC_1_MILLISECOND
);
1046 OhciClearRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortReset
);
1047 MicroSecondDelay (HC_1_MILLISECOND
);
1048 OhciSetRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortEnable
);
1049 MicroSecondDelay (HC_1_MILLISECOND
);
1053 Ohc
->MemPool
= UsbHcInitMemPool(TRUE
, 0);
1054 if(Ohc
->MemPool
== NULL
) {
1055 return EFI_OUT_OF_RESOURCES
;
1057 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
1058 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
1059 OhciSetHcControl (Ohc
, CONTROL_ENABLE
| BULK_ENABLE
, 1);
1060 OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_OPERATIONAL
);
1061 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1063 // Wait till first SOF occurs, and then clear it
1065 while (OhciGetHcInterruptStatus (Ohc
, START_OF_FRAME
) == 0);
1066 OhciClearInterruptStatus (Ohc
, START_OF_FRAME
);
1067 MicroSecondDelay (HC_1_MILLISECOND
);
1073 Submits control transfer to a target USB device.
1075 Calls underlying OhciControlTransfer to do work. This wrapper routine required
1076 on Quark so that USB DMA transfers do not cause an IMR violation.
1078 @param PeiServices The pointer of EFI_PEI_SERVICES.
1079 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
1080 @param DeviceAddress The target device address.
1081 @param DeviceSpeed Target device speed.
1082 @param MaximumPacketLength Maximum packet size the default control transfer
1083 endpoint is capable of sending or receiving.
1084 @param Request USB device request to send.
1085 @param TransferDirection Specifies the data direction for the data stage.
1086 @param Data Data buffer to be transmitted or received from USB device.
1087 @param DataLength The size (in bytes) of the data buffer.
1088 @param TimeOut Indicates the maximum timeout, in millisecond.
1089 @param TransferResult Return the result of this control transfer.
1091 @retval EFI_SUCCESS Transfer was completed successfully.
1092 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
1093 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1094 @retval EFI_TIMEOUT Transfer failed due to timeout.
1095 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
1100 RedirectOhciControlTransfer (
1101 IN EFI_PEI_SERVICES
**PeiServices
,
1102 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
1103 IN UINT8 DeviceAddress
,
1104 IN UINT8 DeviceSpeed
,
1105 IN UINT8 MaxPacketLength
,
1106 IN EFI_USB_DEVICE_REQUEST
*Request
,
1107 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1109 IN OUT UINTN
*DataLength
,
1111 OUT UINT32
*TransferResult
1115 EFI_USB_DEVICE_REQUEST
*NewRequest
;
1120 // Allocate memory external to IMR protected region for transfer data.
1122 Status
= PeiServicesAllocatePool (
1123 sizeof(EFI_USB_DEVICE_REQUEST
) + *DataLength
,
1126 ASSERT_EFI_ERROR (Status
);
1129 // Setup pointers to transfer buffers.
1131 NewRequest
= (EFI_USB_DEVICE_REQUEST
*) Alloc
;
1132 Alloc
+= sizeof(EFI_USB_DEVICE_REQUEST
);
1133 NewData
= (VOID
*) Alloc
;
1136 // Copy callers request packet into transfer request packet.
1138 if (Request
!= NULL
) {
1139 CopyMem (NewRequest
,Request
,sizeof(EFI_USB_DEVICE_REQUEST
));
1144 // Copy callers data into transfer data buffer.
1147 if (DataLength
> 0) {
1148 CopyMem (NewData
,Data
,*DataLength
);
1155 // Call underlying OhciControlTransfer to do work.
1157 Status
= OhciControlTransfer (
1172 // Copy transfer buffer back into callers buffer.
1174 if (Data
!= NULL
&& *DataLength
> 0) {
1175 CopyMem (Data
, NewData
, *DataLength
);
1182 Submits bulk transfer to a bulk endpoint of a USB device.
1184 Calls underlying OhciBulkTransfer to do work. This wrapper routine required
1185 on Quark so that USB DMA transfers do not cause an IMR violation.
1187 @param PeiServices The pointer of EFI_PEI_SERVICES.
1188 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
1189 @param DeviceAddress Target device address.
1190 @param EndPointAddress Endpoint number and its direction in bit 7.
1191 @param MaxiPacketLength Maximum packet size the endpoint is capable of
1192 sending or receiving.
1193 @param Data A pointers to the buffers of data to transmit
1194 from or receive into.
1195 @param DataLength The lenght of the data buffer.
1196 @param DataToggle On input, the initial data toggle for the transfer;
1197 On output, it is updated to to next data toggle to use of
1198 the subsequent bulk transfer.
1199 @param TimeOut Indicates the maximum time, in millisecond, which the
1200 transfer is allowed to complete.
1201 @param TransferResult A pointer to the detailed result information of the
1204 @retval EFI_SUCCESS The transfer was completed successfully.
1205 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1206 @retval EFI_INVALID_PARAMETER Parameters are invalid.
1207 @retval EFI_TIMEOUT The transfer failed due to timeout.
1208 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
1213 RedirectOhciBulkTransfer (
1214 IN EFI_PEI_SERVICES
**PeiServices
,
1215 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
1216 IN UINT8 DeviceAddress
,
1217 IN UINT8 EndPointAddress
,
1218 IN UINT8 MaxPacketLength
,
1220 IN OUT UINTN
*DataLength
,
1221 IN OUT UINT8
*DataToggle
,
1223 OUT UINT32
*TransferResult
1230 // Allocate memory external to IMR protected region for transfer data.
1232 Status
= PeiServicesAllocatePool (
1236 ASSERT_EFI_ERROR (Status
);
1239 // Copy callers data into transfer buffer.
1242 if (DataLength
> 0) {
1243 CopyMem (NewData
,Data
,*DataLength
);
1250 // Call underlying OhciBulkTransfer to do work.
1252 Status
= OhciBulkTransfer (
1266 // Copy transfer buffer back into callers buffer.
1268 if (Data
!= NULL
&& *DataLength
> 0) {
1269 CopyMem (Data
, NewData
, *DataLength
);
1276 @param FileHandle Handle of the file being invoked.
1277 @param PeiServices Describes the list of possible PEI Services.
1279 @retval EFI_SUCCESS PPI successfully installed.
1284 IN EFI_PEI_FILE_HANDLE FileHandle
,
1285 IN CONST EFI_PEI_SERVICES
**PeiServices
1289 PEI_USB_CONTROLLER_PPI
*ChipSetUsbControllerPpi
;
1292 UINTN ControllerType
;
1295 USB_OHCI_HC_DEV
*Ohc
;
1296 EFI_PHYSICAL_ADDRESS TempPtr
;
1300 // Shadow this PEIM to run from memory
1302 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1305 Status
= PeiServicesLocatePpi (
1306 &gPeiUsbControllerPpiGuid
,
1309 (VOID
**) &ChipSetUsbControllerPpi
1311 if (EFI_ERROR (Status
)) {
1312 return EFI_UNSUPPORTED
;
1317 Status
= ChipSetUsbControllerPpi
->GetUsbController (
1318 (EFI_PEI_SERVICES
**) PeiServices
,
1319 ChipSetUsbControllerPpi
,
1325 // When status is error, meant no controller is found
1327 if (EFI_ERROR (Status
)) {
1331 // This PEIM is for OHC type controller.
1333 if (ControllerType
!= PEI_OHCI_CONTROLLER
) {
1338 MemPages
= sizeof (USB_OHCI_HC_DEV
) / PAGESIZE
+ 1;
1339 Status
= PeiServicesAllocatePages (
1340 EfiBootServicesCode
,
1344 if (EFI_ERROR (Status
)) {
1345 DEBUG ((EFI_D_INFO
, "OhcPeimEntry: Fail to allocate buffer for the %dth OHCI ControllerPpi\n", Index
));
1346 return EFI_OUT_OF_RESOURCES
;
1348 ZeroMem((VOID
*)(UINTN
)TempPtr
, MemPages
*PAGESIZE
);
1349 Ohc
= (USB_OHCI_HC_DEV
*) ((UINTN
) TempPtr
);
1351 Ohc
->Signature
= USB_OHCI_HC_DEV_SIGNATURE
;
1353 Ohc
->UsbHostControllerBaseAddress
= (UINT32
) BaseAddress
;
1356 // Initialize Uhc's hardware
1358 Status
= InitializeUsbHC (
1359 (EFI_PEI_SERVICES
**)PeiServices
,
1361 EFI_USB_HC_RESET_GLOBAL
1363 if (EFI_ERROR (Status
)) {
1364 DEBUG ((EFI_D_INFO
, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index
));
1368 // Control & Bulk transfer services are accessed via their Redirect
1369 // routine versions on Quark so that USB DMA transfers do not cause an
1372 Ohc
->UsbHostControllerPpi
.ControlTransfer
= RedirectOhciControlTransfer
;
1373 Ohc
->UsbHostControllerPpi
.BulkTransfer
= RedirectOhciBulkTransfer
;
1374 Ohc
->UsbHostControllerPpi
.GetRootHubPortNumber
= OhciGetRootHubNumOfPorts
;
1375 Ohc
->UsbHostControllerPpi
.GetRootHubPortStatus
= OhciGetRootHubPortStatus
;
1376 Ohc
->UsbHostControllerPpi
.SetRootHubPortFeature
= OhciSetRootHubPortFeature
;
1377 Ohc
->UsbHostControllerPpi
.ClearRootHubPortFeature
= OhciClearRootHubPortFeature
;
1379 Ohc
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1380 Ohc
->PpiDescriptor
.Guid
= &gPeiUsbHostControllerPpiGuid
;
1381 Ohc
->PpiDescriptor
.Ppi
= &Ohc
->UsbHostControllerPpi
;
1383 Status
= PeiServicesInstallPpi (&Ohc
->PpiDescriptor
);
1384 if (EFI_ERROR (Status
)) {