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 UINTN ReqMapLength
= 0;
76 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr
= 0;
78 UINTN DataMapLength
= 0;
79 EFI_PHYSICAL_ADDRESS DataMapPhyAddr
= 0;
84 if ((TransferDirection
!= EfiUsbDataOut
&& TransferDirection
!= EfiUsbDataIn
&&
85 TransferDirection
!= EfiUsbNoData
) ||
86 Request
== NULL
|| DataLength
== NULL
|| TransferResult
== NULL
||
87 (TransferDirection
== EfiUsbNoData
&& (*DataLength
!= 0 || Data
!= NULL
)) ||
88 (TransferDirection
!= EfiUsbNoData
&& (*DataLength
== 0 || Data
== NULL
)) ||
89 (DeviceSpeed
!= EFI_USB_SPEED_LOW
&& DeviceSpeed
!= EFI_USB_SPEED_FULL
) ||
90 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
91 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
92 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: EFI_INVALID_PARAMETER\n"));
93 return EFI_INVALID_PARAMETER
;
96 if (*DataLength
> MAX_BYTES_PER_TD
) {
97 DEBUG ((EFI_D_ERROR
, "OhciControlTransfer: Request data size is too large\n"));
98 return EFI_INVALID_PARAMETER
;
101 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This
);
103 if (TransferDirection
== EfiUsbDataIn
) {
104 DataPidDir
= TD_IN_PID
;
105 StatusPidDir
= TD_OUT_PID
;
107 DataPidDir
= TD_OUT_PID
;
108 StatusPidDir
= TD_IN_PID
;
111 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 0);
112 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
113 MicroSecondDelay (HC_1_MILLISECOND
);
114 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
115 *TransferResult
= EFI_USB_ERR_SYSTEM
;
116 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to disable CONTROL transfer\n"));
117 return EFI_DEVICE_ERROR
;
120 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
121 Ed
= OhciCreateED (Ohc
);
123 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate ED buffer\n"));
124 return EFI_OUT_OF_RESOURCES
;
126 OhciSetEDField (Ed
, ED_SKIP
, 1);
127 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
128 OhciSetEDField (Ed
, ED_ENDPT_NUM
, 0);
129 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
130 OhciSetEDField (Ed
, ED_SPEED
, DeviceSpeed
);
131 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
132 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
133 OhciSetEDField (Ed
, ED_PDATA
, 0);
134 OhciSetEDField (Ed
, ED_ZERO
, 0);
135 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, (UINT32
) NULL
);
136 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, (UINT32
) NULL
);
137 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, (UINT32
) NULL
);
138 OhciAttachEDToList (Ohc
, CONTROL_LIST
, Ed
, NULL
);
142 if(Request
!= NULL
) {
143 ReqMapLength
= sizeof(EFI_USB_DEVICE_REQUEST
);
144 ReqMapPhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Request
;
146 SetupTd
= OhciCreateTD (Ohc
);
147 if (SetupTd
== NULL
) {
148 Status
= EFI_OUT_OF_RESOURCES
;
149 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Setup TD buffer\n"));
153 OhciSetTDField (SetupTd
, TD_PDATA
, 0);
154 OhciSetTDField (SetupTd
, TD_BUFFER_ROUND
, 1);
155 OhciSetTDField (SetupTd
, TD_DIR_PID
, TD_SETUP_PID
);
156 OhciSetTDField (SetupTd
, TD_DELAY_INT
, TD_NO_DELAY
);
157 OhciSetTDField (SetupTd
, TD_DT_TOGGLE
, 2);
158 OhciSetTDField (SetupTd
, TD_ERROR_CNT
, 0);
159 OhciSetTDField (SetupTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
160 OhciSetTDField (SetupTd
, TD_CURR_BUFFER_PTR
, (UINTN
)ReqMapPhyAddr
);
161 OhciSetTDField (SetupTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
162 OhciSetTDField (SetupTd
, TD_BUFFER_END_PTR
, (UINTN
)ReqMapPhyAddr
+ sizeof (EFI_USB_DEVICE_REQUEST
) - 1);
163 SetupTd
->ActualSendLength
= 0;
164 SetupTd
->DataBuffer
= NULL
;
165 SetupTd
->NextTDPointer
= NULL
;
167 DataMapLength
= *DataLength
;
168 if ((Data
!= NULL
) && (DataMapLength
!= 0)) {
169 DataMapPhyAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
;
174 LeftLength
= DataMapLength
;
175 ActualSendLength
= DataMapLength
;
177 while (LeftLength
> 0) {
178 ActualSendLength
= LeftLength
;
179 if (LeftLength
> MaxPacketLength
) {
180 ActualSendLength
= MaxPacketLength
;
182 DataTd
= OhciCreateTD (Ohc
);
183 if (DataTd
== NULL
) {
184 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Data TD buffer\n"));
185 Status
= EFI_OUT_OF_RESOURCES
;
188 OhciSetTDField (DataTd
, TD_PDATA
, 0);
189 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
190 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
191 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
192 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, DataToggle
);
193 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
194 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
195 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) DataMapPhyAddr
);
196 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
) DataMapPhyAddr
+ ActualSendLength
- 1);
197 OhciSetTDField (DataTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
198 DataTd
->ActualSendLength
= ActualSendLength
;
199 DataTd
->DataBuffer
= (UINT8
*)(UINTN
)DataMapPhyAddr
;
200 DataTd
->NextTDPointer
= 0;
201 OhciLinkTD (HeadTd
, DataTd
);
203 DataMapPhyAddr
+= ActualSendLength
;
204 LeftLength
-= ActualSendLength
;
209 StatusTd
= OhciCreateTD (Ohc
);
210 if (StatusTd
== NULL
) {
211 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Status TD buffer\n"));
212 Status
= EFI_OUT_OF_RESOURCES
;
215 OhciSetTDField (StatusTd
, TD_PDATA
, 0);
216 OhciSetTDField (StatusTd
, TD_BUFFER_ROUND
, 1);
217 OhciSetTDField (StatusTd
, TD_DIR_PID
, StatusPidDir
);
218 OhciSetTDField (StatusTd
, TD_DELAY_INT
, 7);
219 OhciSetTDField (StatusTd
, TD_DT_TOGGLE
, 3);
220 OhciSetTDField (StatusTd
, TD_ERROR_CNT
, 0);
221 OhciSetTDField (StatusTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
222 OhciSetTDField (StatusTd
, TD_CURR_BUFFER_PTR
, (UINT32
) NULL
);
223 OhciSetTDField (StatusTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
224 OhciSetTDField (StatusTd
, TD_BUFFER_END_PTR
, (UINT32
) NULL
);
225 StatusTd
->ActualSendLength
= 0;
226 StatusTd
->DataBuffer
= NULL
;
227 StatusTd
->NextTDPointer
= NULL
;
228 OhciLinkTD (HeadTd
, StatusTd
);
232 EmptyTd
= OhciCreateTD (Ohc
);
233 if (EmptyTd
== NULL
) {
234 Status
= EFI_OUT_OF_RESOURCES
;
235 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to allocate Empty TD buffer\n"));
238 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
239 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
240 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
241 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
242 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
243 EmptyTd
->Word0
.DataToggle
= 0;
244 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
245 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
246 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
247 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
248 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
249 EmptyTd
->ActualSendLength
= 0;
250 EmptyTd
->DataBuffer
= NULL
;
251 EmptyTd
->NextTDPointer
= NULL
;
252 OhciLinkTD (HeadTd
, EmptyTd
);
253 Ed
->TdTailPointer
= EmptyTd
;
254 OhciAttachTDListToED (Ed
, HeadTd
);
256 OhciSetEDField (Ed
, ED_SKIP
, 0);
257 MicroSecondDelay (20 * HC_1_MILLISECOND
);
258 OhciSetHcCommandStatus (Ohc
, CONTROL_LIST_FILLED
, 1);
259 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 1);
260 MicroSecondDelay (20 * HC_1_MILLISECOND
);
261 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 1) {
262 MicroSecondDelay (HC_1_MILLISECOND
);
263 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 1) {
264 *TransferResult
= EFI_USB_ERR_SYSTEM
;
265 Status
= EFI_DEVICE_ERROR
;
266 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Fail to enable CONTROL transfer\n"));
272 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &ErrorCode
);
274 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
275 MicroSecondDelay (HC_1_MILLISECOND
);
277 Status
= CheckIfDone (Ohc
, CONTROL_LIST
, Ed
, HeadTd
, &ErrorCode
);
280 *TransferResult
= ConvertErrorCode (ErrorCode
);
282 if (ErrorCode
!= TD_NO_ERROR
) {
283 if (ErrorCode
== TD_TOBE_PROCESSED
) {
284 DEBUG ((EFI_D_INFO
, "Control pipe timeout, > %d mS\r\n", TimeOut
));
286 DEBUG ((EFI_D_INFO
, "Control pipe broken\r\n"));
292 OhciSetHcControl (Ohc
, CONTROL_ENABLE
, 0);
293 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
294 MicroSecondDelay (HC_1_MILLISECOND
);
295 if (OhciGetHcControl (Ohc
, CONTROL_ENABLE
) != 0) {
296 *TransferResult
= EFI_USB_ERR_SYSTEM
;
297 DEBUG ((EFI_D_INFO
, "OhciControlTransfer: Cannot disable CONTROL_ENABLE transfer\n"));
305 HeadTd
= HeadTd
->NextTDPointer
;
306 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
310 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
316 Submits bulk transfer to a bulk endpoint of a USB device.
318 @param PeiServices The pointer of EFI_PEI_SERVICES.
319 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
320 @param DeviceAddress Target device address.
321 @param EndPointAddress Endpoint number and its direction in bit 7.
322 @param MaxiPacketLength Maximum packet size the endpoint is capable of
323 sending or receiving.
324 @param Data A pointers to the buffers of data to transmit
325 from or receive into.
326 @param DataLength The lenght of the data buffer.
327 @param DataToggle On input, the initial data toggle for the transfer;
328 On output, it is updated to to next data toggle to use of
329 the subsequent bulk transfer.
330 @param TimeOut Indicates the maximum time, in millisecond, which the
331 transfer is allowed to complete.
332 @param TransferResult A pointer to the detailed result information of the
335 @retval EFI_SUCCESS The transfer was completed successfully.
336 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
337 @retval EFI_INVALID_PARAMETER Parameters are invalid.
338 @retval EFI_TIMEOUT The transfer failed due to timeout.
339 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
345 IN EFI_PEI_SERVICES
**PeiServices
,
346 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
347 IN UINT8 DeviceAddress
,
348 IN UINT8 EndPointAddress
,
349 IN UINT8 MaxPacketLength
,
351 IN OUT UINTN
*DataLength
,
352 IN OUT UINT8
*DataToggle
,
354 OUT UINT32
*TransferResult
357 USB_OHCI_HC_DEV
*Ohc
;
361 TD_DESCRIPTOR
*HeadTd
;
362 TD_DESCRIPTOR
*DataTd
;
363 TD_DESCRIPTOR
*EmptyTd
;
365 EFI_USB_DATA_DIRECTION TransferDirection
;
373 EFI_PHYSICAL_ADDRESS MapPyhAddr
;
375 UINTN ActualSendLength
;
382 Status
= EFI_SUCCESS
;
384 if (Data
== NULL
|| DataLength
== NULL
|| DataToggle
== NULL
|| TransferResult
== NULL
||
385 *DataLength
== 0 || (*DataToggle
!= 0 && *DataToggle
!= 1) ||
386 (MaxPacketLength
!= 8 && MaxPacketLength
!= 16 &&
387 MaxPacketLength
!= 32 && MaxPacketLength
!= 64)) {
388 return EFI_INVALID_PARAMETER
;
391 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
393 if ((EndPointAddress
& 0x80) != 0) {
394 TransferDirection
= EfiUsbDataIn
;
396 DataPidDir
= TD_IN_PID
;
398 TransferDirection
= EfiUsbDataOut
;
400 DataPidDir
= TD_OUT_PID
;
403 EndPointNum
= (EndPointAddress
& 0xF);
405 OhciSetHcControl (Ohc
, BULK_ENABLE
, 0);
406 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 0) {
407 MicroSecondDelay (HC_1_MILLISECOND
);
408 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 0) {
409 *TransferResult
= EFI_USB_ERR_SYSTEM
;
410 return EFI_DEVICE_ERROR
;
414 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
416 Ed
= OhciCreateED (Ohc
);
418 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
419 return EFI_OUT_OF_RESOURCES
;
421 OhciSetEDField (Ed
, ED_SKIP
, 1);
422 OhciSetEDField (Ed
, ED_FUNC_ADD
, DeviceAddress
);
423 OhciSetEDField (Ed
, ED_ENDPT_NUM
, EndPointNum
);
424 OhciSetEDField (Ed
, ED_DIR
, ED_FROM_TD_DIR
);
425 OhciSetEDField (Ed
, ED_SPEED
, HI_SPEED
);
426 OhciSetEDField (Ed
, ED_FORMAT
| ED_HALTED
| ED_DTTOGGLE
, 0);
427 OhciSetEDField (Ed
, ED_MAX_PACKET
, MaxPacketLength
);
428 OhciSetEDField (Ed
, ED_PDATA
, 0);
429 OhciSetEDField (Ed
, ED_ZERO
, 0);
430 OhciSetEDField (Ed
, ED_TDHEAD_PTR
, (UINT32
) NULL
);
431 OhciSetEDField (Ed
, ED_TDTAIL_PTR
, (UINT32
) NULL
);
432 OhciSetEDField (Ed
, ED_NEXT_EDPTR
, (UINT32
) NULL
);
433 OhciAttachEDToList (Ohc
, BULK_LIST
, Ed
, NULL
);
436 MapLength
= *DataLength
;
437 MapPyhAddr
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Data
;
442 LeftLength
= MapLength
;
443 ActualSendLength
= MapLength
;
444 CurrentToggle
= *DataToggle
;
447 while (LeftLength
> 0) {
448 ActualSendLength
= LeftLength
;
449 if (LeftLength
> MaxPacketLength
) {
450 ActualSendLength
= MaxPacketLength
;
452 DataTd
= OhciCreateTD (Ohc
);
453 if (DataTd
== NULL
) {
454 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate Data TD buffer\r\n"));
455 Status
= EFI_OUT_OF_RESOURCES
;
458 OhciSetTDField (DataTd
, TD_PDATA
, 0);
459 OhciSetTDField (DataTd
, TD_BUFFER_ROUND
, 1);
460 OhciSetTDField (DataTd
, TD_DIR_PID
, DataPidDir
);
461 OhciSetTDField (DataTd
, TD_DELAY_INT
, TD_NO_DELAY
);
462 OhciSetTDField (DataTd
, TD_DT_TOGGLE
, CurrentToggle
);
463 OhciSetTDField (DataTd
, TD_ERROR_CNT
, 0);
464 OhciSetTDField (DataTd
, TD_COND_CODE
, TD_TOBE_PROCESSED
);
465 OhciSetTDField (DataTd
, TD_CURR_BUFFER_PTR
, (UINT32
) MapPyhAddr
);
466 OhciSetTDField (DataTd
, TD_BUFFER_END_PTR
, (UINT32
) MapPyhAddr
+ ActualSendLength
- 1);
467 OhciSetTDField (DataTd
, TD_NEXT_PTR
, (UINT32
) NULL
);
468 DataTd
->ActualSendLength
= ActualSendLength
;
469 DataTd
->DataBuffer
= (UINT8
*)(UINTN
)MapPyhAddr
;
470 DataTd
->NextTDPointer
= 0;
475 OhciLinkTD (HeadTd
, DataTd
);
478 MapPyhAddr
+= ActualSendLength
;
479 LeftLength
-= ActualSendLength
;
484 EmptyTd
= OhciCreateTD (Ohc
);
485 if (EmptyTd
== NULL
) {
486 Status
= EFI_OUT_OF_RESOURCES
;
487 DEBUG ((EFI_D_INFO
, "OhcBulkTransfer: Fail to allocate Empty TD buffer\r\n"));
490 OhciSetTDField (EmptyTd
, TD_PDATA
, 0);
491 OhciSetTDField (EmptyTd
, TD_BUFFER_ROUND
, 0);
492 OhciSetTDField (EmptyTd
, TD_DIR_PID
, 0);
493 OhciSetTDField (EmptyTd
, TD_DELAY_INT
, 0);
494 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
495 EmptyTd
->Word0
.DataToggle
= 0;
496 OhciSetTDField (EmptyTd
, TD_ERROR_CNT
, 0);
497 OhciSetTDField (EmptyTd
, TD_COND_CODE
, 0);
498 OhciSetTDField (EmptyTd
, TD_CURR_BUFFER_PTR
, 0);
499 OhciSetTDField (EmptyTd
, TD_BUFFER_END_PTR
, 0);
500 OhciSetTDField (EmptyTd
, TD_NEXT_PTR
, 0);
501 EmptyTd
->ActualSendLength
= 0;
502 EmptyTd
->DataBuffer
= NULL
;
503 EmptyTd
->NextTDPointer
= NULL
;
504 OhciLinkTD (HeadTd
, EmptyTd
);
505 Ed
->TdTailPointer
= EmptyTd
;
506 OhciAttachTDListToED (Ed
, HeadTd
);
508 OhciSetEDField (Ed
, ED_SKIP
, 0);
509 OhciSetHcCommandStatus (Ohc
, BULK_LIST_FILLED
, 1);
510 OhciSetHcControl (Ohc
, BULK_ENABLE
, 1);
511 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 1) {
512 MicroSecondDelay (HC_1_MILLISECOND
);
513 if (OhciGetHcControl (Ohc
, BULK_ENABLE
) != 1) {
514 *TransferResult
= EFI_USB_ERR_SYSTEM
;
520 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &ErrorCode
);
522 while (Status
== EFI_NOT_READY
&& TimeCount
<= TimeOut
) {
523 MicroSecondDelay (HC_1_MILLISECOND
);
525 Status
= CheckIfDone (Ohc
, BULK_LIST
, Ed
, HeadTd
, &ErrorCode
);
528 *TransferResult
= ConvertErrorCode (ErrorCode
);
530 if (ErrorCode
!= TD_NO_ERROR
) {
531 if (ErrorCode
== TD_TOBE_PROCESSED
) {
532 DEBUG ((EFI_D_INFO
, "Bulk pipe timeout, > %d mS\r\n", TimeOut
));
534 DEBUG ((EFI_D_INFO
, "Bulk pipe broken\r\n"));
538 *DataToggle
= (UINT8
) OhciGetEDField (Ed
, ED_DTTOGGLE
);
543 HeadTd
= HeadTd
->NextTDPointer
;
544 UsbHcFreeMem(Ohc
->MemPool
, DataTd
, sizeof(TD_DESCRIPTOR
));
546 UsbHcFreeMem(Ohc
->MemPool
, Ed
, sizeof(ED_DESCRIPTOR
));
551 Retrieves the number of root hub ports.
553 @param[in] PeiServices The pointer to the PEI Services Table.
554 @param[in] This The pointer to this instance of the
555 PEI_USB_HOST_CONTROLLER_PPI.
556 @param[out] NumOfPorts The pointer to the number of the root hub ports.
558 @retval EFI_SUCCESS The port number was retrieved successfully.
559 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
565 OhciGetRootHubNumOfPorts (
566 IN EFI_PEI_SERVICES
**PeiServices
,
567 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
568 OUT UINT8
*NumOfPorts
571 USB_OHCI_HC_DEV
*Ohc
;
572 if (NumOfPorts
== NULL
) {
573 return EFI_INVALID_PARAMETER
;
575 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
576 *NumOfPorts
= (UINT8
)OhciGetRootHubDescriptor(Ohc
, RH_NUM_DS_PORTS
);
581 Retrieves the current status of a USB root hub port.
583 @param PeiServices The pointer of EFI_PEI_SERVICES.
584 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
585 @param PortNumber The root hub port to retrieve the state from.
586 @param PortStatus Variable to receive the port state.
588 @retval EFI_SUCCESS The status of the USB root hub port specified.
589 by PortNumber was returned in PortStatus.
590 @retval EFI_INVALID_PARAMETER PortNumber is invalid.
596 OhciGetRootHubPortStatus (
597 IN EFI_PEI_SERVICES
**PeiServices
,
598 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
600 OUT EFI_USB_PORT_STATUS
*PortStatus
603 USB_OHCI_HC_DEV
*Ohc
;
606 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
608 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
609 if (PortNumber
>= NumOfPorts
) {
610 return EFI_INVALID_PARAMETER
;
612 PortStatus
->PortStatus
= 0;
613 PortStatus
->PortChangeStatus
= 0;
615 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_CURR_CONNECT_STAT
)) {
616 PortStatus
->PortStatus
|= USB_PORT_STAT_CONNECTION
;
618 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_ENABLE_STAT
)) {
619 PortStatus
->PortStatus
|= USB_PORT_STAT_ENABLE
;
621 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_SUSPEND_STAT
)) {
622 PortStatus
->PortStatus
|= USB_PORT_STAT_SUSPEND
;
624 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_OC_INDICATOR
)) {
625 PortStatus
->PortStatus
|= USB_PORT_STAT_OVERCURRENT
;
627 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_RESET_STAT
)) {
628 PortStatus
->PortStatus
|= USB_PORT_STAT_RESET
;
630 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_PORT_POWER_STAT
)) {
631 PortStatus
->PortStatus
|= USB_PORT_STAT_POWER
;
633 if (OhciReadRootHubPortStatus (Ohc
,PortNumber
, RH_LSDEVICE_ATTACHED
)) {
634 PortStatus
->PortStatus
|= USB_PORT_STAT_LOW_SPEED
;
636 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
)) {
637 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_ENABLE
;
639 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
)) {
640 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_CONNECTION
;
642 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
)) {
643 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_SUSPEND
;
645 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
)) {
646 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_OVERCURRENT
;
648 if (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
)) {
649 PortStatus
->PortChangeStatus
|= USB_PORT_STAT_C_RESET
;
655 Sets a feature for the specified root hub port.
657 @param PeiServices The pointer of EFI_PEI_SERVICES
658 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI
659 @param PortNumber Root hub port to set.
660 @param PortFeature Feature to set.
662 @retval EFI_SUCCESS The feature specified by PortFeature was set.
663 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
664 @retval EFI_TIMEOUT The time out occurred.
670 OhciSetRootHubPortFeature (
671 IN EFI_PEI_SERVICES
**PeiServices
,
672 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
674 IN EFI_USB_PORT_FEATURE PortFeature
677 USB_OHCI_HC_DEV
*Ohc
;
682 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
683 if (PortNumber
>= NumOfPorts
) {
684 return EFI_INVALID_PARAMETER
;
687 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
689 Status
= EFI_SUCCESS
;
692 switch (PortFeature
) {
693 case EfiUsbPortPower
:
694 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_POWER
);
701 MicroSecondDelay (HC_1_MILLISECOND
);
703 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 0 &&
704 RetryTimes
< MAX_RETRY_TIMES
);
706 if (RetryTimes
>= MAX_RETRY_TIMES
) {
707 return EFI_DEVICE_ERROR
;
711 case EfiUsbPortReset
:
712 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_RESET
);
719 MicroSecondDelay (HC_1_MILLISECOND
);
721 } while ((OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 0 ||
722 OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT
) == 1) &&
723 RetryTimes
< MAX_RETRY_TIMES
);
725 if (RetryTimes
>= MAX_RETRY_TIMES
) {
726 return EFI_DEVICE_ERROR
;
729 OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
732 case EfiUsbPortEnable
:
733 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_ENABLE
);
740 MicroSecondDelay (HC_1_MILLISECOND
);;
742 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 0 &&
743 RetryTimes
< MAX_RETRY_TIMES
);
745 if (RetryTimes
>= MAX_RETRY_TIMES
) {
746 return EFI_DEVICE_ERROR
;
751 case EfiUsbPortSuspend
:
752 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_SET_PORT_SUSPEND
);
759 MicroSecondDelay (HC_1_MILLISECOND
);;
761 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 0 &&
762 RetryTimes
< MAX_RETRY_TIMES
);
764 if (RetryTimes
>= MAX_RETRY_TIMES
) {
765 return EFI_DEVICE_ERROR
;
770 return EFI_INVALID_PARAMETER
;
777 Clears a feature for the specified root hub port.
779 @param PeiServices The pointer of EFI_PEI_SERVICES.
780 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
781 @param PortNumber Specifies the root hub port whose feature
782 is requested to be cleared.
783 @param PortFeature Indicates the feature selector associated with the
784 feature clear request.
786 @retval EFI_SUCCESS The feature specified by PortFeature was cleared
787 for the USB root hub port specified by PortNumber.
788 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
794 OhciClearRootHubPortFeature (
795 IN EFI_PEI_SERVICES
**PeiServices
,
796 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
798 IN EFI_USB_PORT_FEATURE PortFeature
801 USB_OHCI_HC_DEV
*Ohc
;
807 OhciGetRootHubNumOfPorts (PeiServices
, This
, &NumOfPorts
);
808 if (PortNumber
>= NumOfPorts
) {
809 return EFI_INVALID_PARAMETER
;
812 Ohc
= PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This
);
814 Status
= EFI_SUCCESS
;
816 switch (PortFeature
) {
817 case EfiUsbPortEnable
:
818 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_ENABLE
);
825 MicroSecondDelay (HC_1_MILLISECOND
);
827 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT
) == 1 &&
828 RetryTimes
< MAX_RETRY_TIMES
);
830 if (RetryTimes
>= MAX_RETRY_TIMES
) {
831 return EFI_DEVICE_ERROR
;
835 case EfiUsbPortSuspend
:
836 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_SUSPEND_STATUS
);
843 MicroSecondDelay (HC_1_MILLISECOND
);
845 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT
) == 1 &&
846 RetryTimes
< MAX_RETRY_TIMES
);
848 if (RetryTimes
>= MAX_RETRY_TIMES
) {
849 return EFI_DEVICE_ERROR
;
853 case EfiUsbPortReset
:
856 case EfiUsbPortPower
:
857 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CLEAR_PORT_POWER
);
864 MicroSecondDelay (HC_1_MILLISECOND
);
866 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_POWER_STAT
) == 1 &&
867 RetryTimes
< MAX_RETRY_TIMES
);
869 if (RetryTimes
>= MAX_RETRY_TIMES
) {
870 return EFI_DEVICE_ERROR
;
874 case EfiUsbPortConnectChange
:
875 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
);
882 MicroSecondDelay (HC_1_MILLISECOND
);
884 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_CONNECT_STATUS_CHANGE
) == 1 &&
885 RetryTimes
< MAX_RETRY_TIMES
);
887 if (RetryTimes
>= MAX_RETRY_TIMES
) {
888 return EFI_DEVICE_ERROR
;
892 case EfiUsbPortResetChange
:
893 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
);
900 MicroSecondDelay (HC_1_MILLISECOND
);
902 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_RESET_STAT_CHANGE
) == 1 &&
903 RetryTimes
< MAX_RETRY_TIMES
);
905 if (RetryTimes
>= MAX_RETRY_TIMES
) {
906 return EFI_DEVICE_ERROR
;
911 case EfiUsbPortEnableChange
:
912 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
);
919 MicroSecondDelay (HC_1_MILLISECOND
);
921 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_ENABLE_STAT_CHANGE
) == 1 &&
922 RetryTimes
< MAX_RETRY_TIMES
);
924 if (RetryTimes
>= MAX_RETRY_TIMES
) {
925 return EFI_DEVICE_ERROR
;
929 case EfiUsbPortSuspendChange
:
930 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
);
937 MicroSecondDelay (HC_1_MILLISECOND
);
939 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_PORT_SUSPEND_STAT_CHANGE
) == 1 &&
940 RetryTimes
< MAX_RETRY_TIMES
);
942 if (RetryTimes
>= MAX_RETRY_TIMES
) {
943 return EFI_DEVICE_ERROR
;
947 case EfiUsbPortOverCurrentChange
:
948 Status
= OhciSetRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
);
955 MicroSecondDelay (HC_1_MILLISECOND
);
957 } while (OhciReadRootHubPortStatus (Ohc
, PortNumber
, RH_OC_INDICATOR_CHANGE
) == 1 &&
958 RetryTimes
< MAX_RETRY_TIMES
);
960 if (RetryTimes
>= MAX_RETRY_TIMES
) {
961 return EFI_DEVICE_ERROR
;
966 return EFI_INVALID_PARAMETER
;
972 Provides software reset for the USB host controller.
974 @param This This EFI_USB_HC_PROTOCOL instance.
975 @param Attributes A bit mask of the reset operation to perform.
977 @retval EFI_SUCCESS The reset operation succeeded.
978 @retval EFI_INVALID_PARAMETER Attributes is not valid.
979 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
980 not currently supported by the host controller.
981 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
986 IN EFI_PEI_SERVICES
**PeiServices
,
987 IN USB_OHCI_HC_DEV
*Ohc
,
994 UINT32 PowerOnGoodTime
;
996 BOOLEAN Flag
= FALSE
;
998 if ((Attributes
& ~(EFI_USB_HC_RESET_GLOBAL
| EFI_USB_HC_RESET_HOST_CONTROLLER
)) != 0) {
999 return EFI_INVALID_PARAMETER
;
1001 Status
= EFI_SUCCESS
;
1003 if ((Attributes
& EFI_USB_HC_RESET_HOST_CONTROLLER
) != 0) {
1004 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1005 Status
= OhciSetHcCommandStatus (Ohc
, HC_RESET
, HC_RESET
);
1006 if (EFI_ERROR (Status
)) {
1007 return EFI_DEVICE_ERROR
;
1009 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1011 // Wait for host controller reset.
1013 PowerOnGoodTime
= 50;
1015 MicroSecondDelay (HC_1_MILLISECOND
);
1016 Data32
= OhciGetOperationalReg (Ohc
, HC_COMMAND_STATUS
);
1017 if ((Data32
& HC_RESET
) == 0) {
1021 }while(PowerOnGoodTime
--);
1023 return EFI_DEVICE_ERROR
;
1027 OhciSetFrameInterval (Ohc
, FRAME_INTERVAL
, 0x2edf);
1028 if ((Attributes
& EFI_USB_HC_RESET_GLOBAL
) != 0) {
1029 Status
= OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_RESET
);
1030 if (EFI_ERROR (Status
)) {
1031 return EFI_DEVICE_ERROR
;
1033 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1036 // Initialize host controller operational registers
1038 OhciSetFrameInterval (Ohc
, FS_LARGEST_DATA_PACKET
, 0x2778);
1039 OhciSetFrameInterval (Ohc
, FRAME_INTERVAL
, 0x2edf);
1040 OhciSetPeriodicStart (Ohc
, 0x2a2f);
1041 OhciSetHcControl (Ohc
, CONTROL_BULK_RATIO
, 0x0);
1042 OhciSetHcCommandStatus (Ohc
, CONTROL_LIST_FILLED
| BULK_LIST_FILLED
, 0);
1043 OhciSetRootHubDescriptor (Ohc
, RH_PSWITCH_MODE
, 0);
1044 OhciSetRootHubDescriptor (Ohc
, RH_NO_PSWITCH
| RH_NOC_PROT
, 1);
1045 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
1046 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
1048 OhciSetRootHubDescriptor (Ohc
, RH_DEV_REMOVABLE
, 0);
1049 OhciSetRootHubDescriptor (Ohc
, RH_PORT_PWR_CTRL_MASK
, 0xffff);
1050 OhciSetRootHubStatus (Ohc
, RH_LOCAL_PSTAT_CHANGE
);
1051 OhciSetRootHubPortStatus (Ohc
, 0, RH_SET_PORT_POWER
);
1052 OhciGetRootHubNumOfPorts (PeiServices
, &Ohc
->UsbHostControllerPpi
, &NumOfPorts
);
1053 for (Index
= 0; Index
< NumOfPorts
; Index
++) {
1054 if (!EFI_ERROR (OhciSetRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortReset
))) {
1055 MicroSecondDelay (200 * HC_1_MILLISECOND
);
1056 OhciClearRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortReset
);
1057 MicroSecondDelay (HC_1_MILLISECOND
);
1058 OhciSetRootHubPortFeature (PeiServices
, &Ohc
->UsbHostControllerPpi
, Index
, EfiUsbPortEnable
);
1059 MicroSecondDelay (HC_1_MILLISECOND
);
1063 Ohc
->MemPool
= UsbHcInitMemPool(TRUE
, 0);
1064 if(Ohc
->MemPool
== NULL
) {
1065 return EFI_OUT_OF_RESOURCES
;
1067 OhciSetMemoryPointer (Ohc
, HC_CONTROL_HEAD
, NULL
);
1068 OhciSetMemoryPointer (Ohc
, HC_BULK_HEAD
, NULL
);
1069 OhciSetHcControl (Ohc
, CONTROL_ENABLE
| BULK_ENABLE
, 1);
1070 OhciSetHcControl (Ohc
, HC_FUNCTIONAL_STATE
, HC_STATE_OPERATIONAL
);
1071 MicroSecondDelay (50 * HC_1_MILLISECOND
);
1073 // Wait till first SOF occurs, and then clear it
1075 while (OhciGetHcInterruptStatus (Ohc
, START_OF_FRAME
) == 0);
1076 OhciClearInterruptStatus (Ohc
, START_OF_FRAME
);
1077 MicroSecondDelay (HC_1_MILLISECOND
);
1083 Submits control transfer to a target USB device.
1085 Calls underlying OhciControlTransfer to do work. This wrapper routine required
1086 on Quark so that USB DMA transfers do not cause an IMR violation.
1088 @param PeiServices The pointer of EFI_PEI_SERVICES.
1089 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
1090 @param DeviceAddress The target device address.
1091 @param DeviceSpeed Target device speed.
1092 @param MaximumPacketLength Maximum packet size the default control transfer
1093 endpoint is capable of sending or receiving.
1094 @param Request USB device request to send.
1095 @param TransferDirection Specifies the data direction for the data stage.
1096 @param Data Data buffer to be transmitted or received from USB device.
1097 @param DataLength The size (in bytes) of the data buffer.
1098 @param TimeOut Indicates the maximum timeout, in millisecond.
1099 @param TransferResult Return the result of this control transfer.
1101 @retval EFI_SUCCESS Transfer was completed successfully.
1102 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.
1103 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1104 @retval EFI_TIMEOUT Transfer failed due to timeout.
1105 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.
1110 RedirectOhciControlTransfer (
1111 IN EFI_PEI_SERVICES
**PeiServices
,
1112 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
1113 IN UINT8 DeviceAddress
,
1114 IN UINT8 DeviceSpeed
,
1115 IN UINT8 MaxPacketLength
,
1116 IN EFI_USB_DEVICE_REQUEST
*Request
,
1117 IN EFI_USB_DATA_DIRECTION TransferDirection
,
1119 IN OUT UINTN
*DataLength
,
1121 OUT UINT32
*TransferResult
1125 EFI_USB_DEVICE_REQUEST
*NewRequest
;
1130 // Allocate memory external to IMR protected region for transfer data.
1132 Status
= PeiServicesAllocatePool (
1133 sizeof(EFI_USB_DEVICE_REQUEST
) + *DataLength
,
1136 ASSERT_EFI_ERROR (Status
);
1139 // Setup pointers to transfer buffers.
1141 NewRequest
= (EFI_USB_DEVICE_REQUEST
*) Alloc
;
1142 Alloc
+= sizeof(EFI_USB_DEVICE_REQUEST
);
1143 NewData
= (VOID
*) Alloc
;
1146 // Copy callers request packet into transfer request packet.
1148 if (Request
!= NULL
) {
1149 CopyMem (NewRequest
,Request
,sizeof(EFI_USB_DEVICE_REQUEST
));
1154 // Copy callers data into transfer data buffer.
1157 if (DataLength
> 0) {
1158 CopyMem (NewData
,Data
,*DataLength
);
1165 // Call underlying OhciControlTransfer to do work.
1167 Status
= OhciControlTransfer (
1182 // Copy transfer buffer back into callers buffer.
1184 if (Data
!= NULL
&& *DataLength
> 0) {
1185 CopyMem (Data
, NewData
, *DataLength
);
1192 Submits bulk transfer to a bulk endpoint of a USB device.
1194 Calls underlying OhciBulkTransfer to do work. This wrapper routine required
1195 on Quark so that USB DMA transfers do not cause an IMR violation.
1197 @param PeiServices The pointer of EFI_PEI_SERVICES.
1198 @param This The pointer of PEI_USB_HOST_CONTROLLER_PPI.
1199 @param DeviceAddress Target device address.
1200 @param EndPointAddress Endpoint number and its direction in bit 7.
1201 @param MaxiPacketLength Maximum packet size the endpoint is capable of
1202 sending or receiving.
1203 @param Data A pointers to the buffers of data to transmit
1204 from or receive into.
1205 @param DataLength The lenght of the data buffer.
1206 @param DataToggle On input, the initial data toggle for the transfer;
1207 On output, it is updated to to next data toggle to use of
1208 the subsequent bulk transfer.
1209 @param TimeOut Indicates the maximum time, in millisecond, which the
1210 transfer is allowed to complete.
1211 @param TransferResult A pointer to the detailed result information of the
1214 @retval EFI_SUCCESS The transfer was completed successfully.
1215 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
1216 @retval EFI_INVALID_PARAMETER Parameters are invalid.
1217 @retval EFI_TIMEOUT The transfer failed due to timeout.
1218 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.
1223 RedirectOhciBulkTransfer (
1224 IN EFI_PEI_SERVICES
**PeiServices
,
1225 IN PEI_USB_HOST_CONTROLLER_PPI
*This
,
1226 IN UINT8 DeviceAddress
,
1227 IN UINT8 EndPointAddress
,
1228 IN UINT8 MaxPacketLength
,
1230 IN OUT UINTN
*DataLength
,
1231 IN OUT UINT8
*DataToggle
,
1233 OUT UINT32
*TransferResult
1240 // Allocate memory external to IMR protected region for transfer data.
1242 Status
= PeiServicesAllocatePool (
1246 ASSERT_EFI_ERROR (Status
);
1249 // Copy callers data into transfer buffer.
1252 if (DataLength
> 0) {
1253 CopyMem (NewData
,Data
,*DataLength
);
1260 // Call underlying OhciBulkTransfer to do work.
1262 Status
= OhciBulkTransfer (
1276 // Copy transfer buffer back into callers buffer.
1278 if (Data
!= NULL
&& *DataLength
> 0) {
1279 CopyMem (Data
, NewData
, *DataLength
);
1286 @param FileHandle Handle of the file being invoked.
1287 @param PeiServices Describes the list of possible PEI Services.
1289 @retval EFI_SUCCESS PPI successfully installed.
1294 IN EFI_PEI_FILE_HANDLE FileHandle
,
1295 IN CONST EFI_PEI_SERVICES
**PeiServices
1299 PEI_USB_CONTROLLER_PPI
*ChipSetUsbControllerPpi
;
1302 UINTN ControllerType
;
1305 USB_OHCI_HC_DEV
*Ohc
;
1306 EFI_PHYSICAL_ADDRESS TempPtr
;
1310 // Shadow this PEIM to run from memory
1312 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle
))) {
1315 Status
= PeiServicesLocatePpi (
1316 &gPeiUsbControllerPpiGuid
,
1319 (VOID
**) &ChipSetUsbControllerPpi
1321 if (EFI_ERROR (Status
)) {
1322 return EFI_UNSUPPORTED
;
1327 Status
= ChipSetUsbControllerPpi
->GetUsbController (
1328 (EFI_PEI_SERVICES
**) PeiServices
,
1329 ChipSetUsbControllerPpi
,
1335 // When status is error, meant no controller is found
1337 if (EFI_ERROR (Status
)) {
1341 // This PEIM is for OHC type controller.
1343 if (ControllerType
!= PEI_OHCI_CONTROLLER
) {
1348 MemPages
= sizeof (USB_OHCI_HC_DEV
) / PAGESIZE
+ 1;
1349 Status
= PeiServicesAllocatePages (
1350 EfiBootServicesCode
,
1354 if (EFI_ERROR (Status
)) {
1355 DEBUG ((EFI_D_INFO
, "OhcPeimEntry: Fail to allocate buffer for the %dth OHCI ControllerPpi\n", Index
));
1356 return EFI_OUT_OF_RESOURCES
;
1358 ZeroMem((VOID
*)(UINTN
)TempPtr
, MemPages
*PAGESIZE
);
1359 Ohc
= (USB_OHCI_HC_DEV
*) ((UINTN
) TempPtr
);
1361 Ohc
->Signature
= USB_OHCI_HC_DEV_SIGNATURE
;
1363 Ohc
->UsbHostControllerBaseAddress
= (UINT32
) BaseAddress
;
1366 // Initialize Uhc's hardware
1368 Status
= InitializeUsbHC (
1369 (EFI_PEI_SERVICES
**)PeiServices
,
1371 EFI_USB_HC_RESET_GLOBAL
1373 if (EFI_ERROR (Status
)) {
1374 DEBUG ((EFI_D_INFO
, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index
));
1378 // Control & Bulk transfer services are accessed via their Redirect
1379 // routine versions on Quark so that USB DMA transfers do not cause an
1382 Ohc
->UsbHostControllerPpi
.ControlTransfer
= RedirectOhciControlTransfer
;
1383 Ohc
->UsbHostControllerPpi
.BulkTransfer
= RedirectOhciBulkTransfer
;
1384 Ohc
->UsbHostControllerPpi
.GetRootHubPortNumber
= OhciGetRootHubNumOfPorts
;
1385 Ohc
->UsbHostControllerPpi
.GetRootHubPortStatus
= OhciGetRootHubPortStatus
;
1386 Ohc
->UsbHostControllerPpi
.SetRootHubPortFeature
= OhciSetRootHubPortFeature
;
1387 Ohc
->UsbHostControllerPpi
.ClearRootHubPortFeature
= OhciClearRootHubPortFeature
;
1389 Ohc
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
1390 Ohc
->PpiDescriptor
.Guid
= &gPeiUsbHostControllerPpiGuid
;
1391 Ohc
->PpiDescriptor
.Ppi
= &Ohc
->UsbHostControllerPpi
;
1393 Status
= PeiServicesInstallPpi (&Ohc
->PpiDescriptor
);
1394 if (EFI_ERROR (Status
)) {