]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c
ArmPkg/CompilerIntrinsicsLib: Add uread, uwrite GCC assembly sources
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Usb / Ohci / Pei / OhcPeim.c
1 /** @file
2 This file contains the implementation of Usb Hc Protocol.
3
4 Copyright (c) 2013-2015 Intel Corporation.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10
11 #include "OhcPeim.h"
12
13 /**
14 Submits control transfer to a target USB device.
15
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.
28
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.
34
35 **/
36 EFI_STATUS
37 EFIAPI
38 OhciControlTransfer (
39 IN EFI_PEI_SERVICES **PeiServices,
40 IN PEI_USB_HOST_CONTROLLER_PPI *This,
41 IN UINT8 DeviceAddress,
42 IN UINT8 DeviceSpeed,
43 IN UINT8 MaxPacketLength,
44 IN EFI_USB_DEVICE_REQUEST *Request,
45 IN EFI_USB_DATA_DIRECTION TransferDirection,
46 IN OUT VOID *Data,
47 IN OUT UINTN *DataLength,
48 IN UINTN TimeOut,
49 OUT UINT32 *TransferResult
50 )
51 {
52 USB_OHCI_HC_DEV *Ohc;
53 ED_DESCRIPTOR *Ed;
54 TD_DESCRIPTOR *HeadTd;
55 TD_DESCRIPTOR *SetupTd;
56 TD_DESCRIPTOR *DataTd;
57 TD_DESCRIPTOR *StatusTd;
58 TD_DESCRIPTOR *EmptyTd;
59 EFI_STATUS Status;
60 UINT32 DataPidDir;
61 UINT32 StatusPidDir;
62 UINTN TimeCount;
63 UINT32 ErrorCode;
64
65 UINTN ActualSendLength;
66 UINTN LeftLength;
67 UINT8 DataToggle;
68
69 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;
70
71 UINTN DataMapLength = 0;
72 EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;
73
74 HeadTd = NULL;
75 DataTd = NULL;
76
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;
87 }
88
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;
92 }
93
94 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This);
95
96 if (TransferDirection == EfiUsbDataIn) {
97 DataPidDir = TD_IN_PID;
98 StatusPidDir = TD_OUT_PID;
99 } else {
100 DataPidDir = TD_OUT_PID;
101 StatusPidDir = TD_IN_PID;
102 }
103
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;
111 }
112 }
113 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
114 Ed = OhciCreateED (Ohc);
115 if (Ed == NULL) {
116 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n"));
117 return EFI_OUT_OF_RESOURCES;
118 }
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);
132 //
133 // Setup Stage
134 //
135 if(Request != NULL) {
136 ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request;
137 }
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"));
142 goto FREE_ED_BUFF;
143 }
144 HeadTd = SetupTd;
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;
158
159 DataMapLength = *DataLength;
160 if ((Data != NULL) && (DataMapLength != 0)) {
161 DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
162 }
163 //
164 //Data Stage
165 //
166 LeftLength = DataMapLength;
167 ActualSendLength = DataMapLength;
168 DataToggle = 1;
169 while (LeftLength > 0) {
170 ActualSendLength = LeftLength;
171 if (LeftLength > MaxPacketLength) {
172 ActualSendLength = MaxPacketLength;
173 }
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;
178 goto FREE_TD_BUFF;
179 }
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);
194 DataToggle ^= 1;
195 DataMapPhyAddr += ActualSendLength;
196 LeftLength -= ActualSendLength;
197 }
198 //
199 // Status Stage
200 //
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;
205 goto FREE_TD_BUFF;
206 }
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);
221 //
222 // Empty Stage
223 //
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"));
228 goto FREE_TD_BUFF;
229 }
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);
247 //
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"));
259 goto FREE_TD_BUFF;
260 }
261 }
262
263 TimeCount = 0;
264 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
265
266 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
267 MicroSecondDelay (HC_1_MILLISECOND);
268 TimeCount++;
269 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
270 }
271 //
272 *TransferResult = ConvertErrorCode (ErrorCode);
273
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));
277 } else {
278 DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
279 }
280
281 *DataLength = 0;
282 }
283
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"));
290 goto FREE_TD_BUFF;
291 }
292 }
293
294 FREE_TD_BUFF:
295 while (HeadTd) {
296 DataTd = HeadTd;
297 HeadTd = HeadTd->NextTDPointer;
298 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
299 }
300
301 FREE_ED_BUFF:
302 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
303
304 return Status;
305 }
306
307 /**
308 Submits bulk transfer to a bulk endpoint of a USB device.
309
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
325 bulk transfer.
326
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.
332
333 **/
334 EFI_STATUS
335 EFIAPI
336 OhciBulkTransfer (
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,
342 IN OUT VOID *Data,
343 IN OUT UINTN *DataLength,
344 IN OUT UINT8 *DataToggle,
345 IN UINTN TimeOut,
346 OUT UINT32 *TransferResult
347 )
348 {
349 USB_OHCI_HC_DEV *Ohc;
350 ED_DESCRIPTOR *Ed;
351 UINT32 DataPidDir;
352 TD_DESCRIPTOR *HeadTd;
353 TD_DESCRIPTOR *DataTd;
354 TD_DESCRIPTOR *EmptyTd;
355 EFI_STATUS Status;
356 UINT8 EndPointNum;
357 UINTN TimeCount;
358 UINT32 ErrorCode;
359
360 UINT8 CurrentToggle;
361 UINTN MapLength;
362 EFI_PHYSICAL_ADDRESS MapPyhAddr;
363 UINTN LeftLength;
364 UINTN ActualSendLength;
365 BOOLEAN FirstTD;
366
367 MapLength = 0;
368 MapPyhAddr = 0;
369 LeftLength = 0;
370 Status = EFI_SUCCESS;
371
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;
377 }
378
379 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
380
381 if ((EndPointAddress & 0x80) != 0) {
382 DataPidDir = TD_IN_PID;
383 } else {
384 DataPidDir = TD_OUT_PID;
385 }
386
387 EndPointNum = (EndPointAddress & 0xF);
388
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;
395 }
396 }
397
398 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
399
400 Ed = OhciCreateED (Ohc);
401 if (Ed == NULL) {
402 DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
403 return EFI_OUT_OF_RESOURCES;
404 }
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);
418
419 if(Data != NULL) {
420 MapLength = *DataLength;
421 MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
422 }
423 //
424 //Data Stage
425 //
426 LeftLength = MapLength;
427 ActualSendLength = MapLength;
428 CurrentToggle = *DataToggle;
429 HeadTd = NULL;
430 FirstTD = TRUE;
431 while (LeftLength > 0) {
432 ActualSendLength = LeftLength;
433 if (LeftLength > MaxPacketLength) {
434 ActualSendLength = MaxPacketLength;
435 }
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;
440 goto FREE_TD_BUFF;
441 }
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;
455 if (FirstTD) {
456 HeadTd = DataTd;
457 FirstTD = FALSE;
458 } else {
459 OhciLinkTD (HeadTd, DataTd);
460 }
461 CurrentToggle ^= 1;
462 MapPyhAddr += ActualSendLength;
463 LeftLength -= ActualSendLength;
464 }
465 //
466 // Empty Stage
467 //
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"));
472 goto FREE_TD_BUFF;
473 }
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);
491
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;
499 goto FREE_TD_BUFF;
500 }
501 }
502
503 TimeCount = 0;
504 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
505
506 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
507 MicroSecondDelay (HC_1_MILLISECOND);
508 TimeCount++;
509 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
510 }
511
512 *TransferResult = ConvertErrorCode (ErrorCode);
513
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));
517 } else {
518 DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
519 }
520 *DataLength = 0;
521 }
522 *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
523
524 FREE_TD_BUFF:
525 while (HeadTd) {
526 DataTd = HeadTd;
527 HeadTd = HeadTd->NextTDPointer;
528 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
529 }
530 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
531
532 return Status;
533 }
534 /**
535 Retrieves the number of root hub ports.
536
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.
541
542 @retval EFI_SUCCESS The port number was retrieved successfully.
543 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
544
545 **/
546
547 EFI_STATUS
548 EFIAPI
549 OhciGetRootHubNumOfPorts (
550 IN EFI_PEI_SERVICES **PeiServices,
551 IN PEI_USB_HOST_CONTROLLER_PPI *This,
552 OUT UINT8 *NumOfPorts
553 )
554 {
555 USB_OHCI_HC_DEV *Ohc;
556 if (NumOfPorts == NULL) {
557 return EFI_INVALID_PARAMETER;
558 }
559 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
560 *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
561
562 return EFI_SUCCESS;
563 }
564 /**
565 Retrieves the current status of a USB root hub port.
566
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.
571
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.
575
576 **/
577
578 EFI_STATUS
579 EFIAPI
580 OhciGetRootHubPortStatus (
581 IN EFI_PEI_SERVICES **PeiServices,
582 IN PEI_USB_HOST_CONTROLLER_PPI *This,
583 IN UINT8 PortNumber,
584 OUT EFI_USB_PORT_STATUS *PortStatus
585 )
586 {
587 USB_OHCI_HC_DEV *Ohc;
588 UINT8 NumOfPorts;
589
590 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
591
592 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
593 if (PortNumber >= NumOfPorts) {
594 return EFI_INVALID_PARAMETER;
595 }
596 PortStatus->PortStatus = 0;
597 PortStatus->PortChangeStatus = 0;
598
599 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
600 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
601 }
602 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
603 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
604 }
605 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
606 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
607 }
608 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
609 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
610 }
611 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
612 PortStatus->PortStatus |= USB_PORT_STAT_RESET;
613 }
614 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
615 PortStatus->PortStatus |= USB_PORT_STAT_POWER;
616 }
617 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
618 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
619 }
620 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
621 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
622 }
623 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
624 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
625 }
626 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
627 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
628 }
629 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
630 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
631 }
632 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
633 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
634 }
635
636 return EFI_SUCCESS;
637 }
638 /**
639 Sets a feature for the specified root hub port.
640
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.
645
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.
649
650 **/
651
652 EFI_STATUS
653 EFIAPI
654 OhciSetRootHubPortFeature (
655 IN EFI_PEI_SERVICES **PeiServices,
656 IN PEI_USB_HOST_CONTROLLER_PPI *This,
657 IN UINT8 PortNumber,
658 IN EFI_USB_PORT_FEATURE PortFeature
659 )
660 {
661 USB_OHCI_HC_DEV *Ohc;
662 EFI_STATUS Status;
663 UINT8 NumOfPorts;
664 UINTN RetryTimes;
665
666 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
667 if (PortNumber >= NumOfPorts) {
668 return EFI_INVALID_PARAMETER;
669 }
670
671 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
672
673 Status = EFI_SUCCESS;
674
675
676 switch (PortFeature) {
677 case EfiUsbPortPower:
678 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
679
680 //
681 // Verify the state
682 //
683 RetryTimes = 0;
684 do {
685 MicroSecondDelay (HC_1_MILLISECOND);
686 RetryTimes++;
687 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
688 RetryTimes < MAX_RETRY_TIMES);
689
690 if (RetryTimes >= MAX_RETRY_TIMES) {
691 return EFI_DEVICE_ERROR;
692 }
693 break;
694
695 case EfiUsbPortReset:
696 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
697
698 //
699 // Verify the state
700 //
701 RetryTimes = 0;
702 do {
703 MicroSecondDelay (HC_1_MILLISECOND);
704 RetryTimes++;
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);
708
709 if (RetryTimes >= MAX_RETRY_TIMES) {
710 return EFI_DEVICE_ERROR;
711 }
712
713 OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
714 break;
715
716 case EfiUsbPortEnable:
717 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
718
719 //
720 // Verify the state
721 //
722 RetryTimes = 0;
723 do {
724 MicroSecondDelay (HC_1_MILLISECOND);;
725 RetryTimes++;
726 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
727 RetryTimes < MAX_RETRY_TIMES);
728
729 if (RetryTimes >= MAX_RETRY_TIMES) {
730 return EFI_DEVICE_ERROR;
731 }
732 break;
733
734
735 case EfiUsbPortSuspend:
736 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
737
738 //
739 // Verify the state
740 //
741 RetryTimes = 0;
742 do {
743 MicroSecondDelay (HC_1_MILLISECOND);;
744 RetryTimes++;
745 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
746 RetryTimes < MAX_RETRY_TIMES);
747
748 if (RetryTimes >= MAX_RETRY_TIMES) {
749 return EFI_DEVICE_ERROR;
750 }
751 break;
752
753 default:
754 return EFI_INVALID_PARAMETER;
755 }
756
757 return Status;
758 }
759
760 /**
761 Clears a feature for the specified root hub port.
762
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.
769
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.
773
774 **/
775
776 EFI_STATUS
777 EFIAPI
778 OhciClearRootHubPortFeature (
779 IN EFI_PEI_SERVICES **PeiServices,
780 IN PEI_USB_HOST_CONTROLLER_PPI *This,
781 IN UINT8 PortNumber,
782 IN EFI_USB_PORT_FEATURE PortFeature
783 )
784 {
785 USB_OHCI_HC_DEV *Ohc;
786 EFI_STATUS Status;
787 UINT8 NumOfPorts;
788 UINTN RetryTimes;
789
790
791 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
792 if (PortNumber >= NumOfPorts) {
793 return EFI_INVALID_PARAMETER;
794 }
795
796 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
797
798 Status = EFI_SUCCESS;
799
800 switch (PortFeature) {
801 case EfiUsbPortEnable:
802 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
803
804 //
805 // Verify the state
806 //
807 RetryTimes = 0;
808 do {
809 MicroSecondDelay (HC_1_MILLISECOND);
810 RetryTimes++;
811 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
812 RetryTimes < MAX_RETRY_TIMES);
813
814 if (RetryTimes >= MAX_RETRY_TIMES) {
815 return EFI_DEVICE_ERROR;
816 }
817 break;
818
819 case EfiUsbPortSuspend:
820 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
821
822 //
823 // Verify the state
824 //
825 RetryTimes = 0;
826 do {
827 MicroSecondDelay (HC_1_MILLISECOND);
828 RetryTimes++;
829 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
830 RetryTimes < MAX_RETRY_TIMES);
831
832 if (RetryTimes >= MAX_RETRY_TIMES) {
833 return EFI_DEVICE_ERROR;
834 }
835 break;
836
837 case EfiUsbPortReset:
838 break;
839
840 case EfiUsbPortPower:
841 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
842
843 //
844 // Verify the state
845 //
846 RetryTimes = 0;
847 do {
848 MicroSecondDelay (HC_1_MILLISECOND);
849 RetryTimes++;
850 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
851 RetryTimes < MAX_RETRY_TIMES);
852
853 if (RetryTimes >= MAX_RETRY_TIMES) {
854 return EFI_DEVICE_ERROR;
855 }
856 break;
857
858 case EfiUsbPortConnectChange:
859 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
860
861 //
862 // Verify the state
863 //
864 RetryTimes = 0;
865 do {
866 MicroSecondDelay (HC_1_MILLISECOND);
867 RetryTimes++;
868 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
869 RetryTimes < MAX_RETRY_TIMES);
870
871 if (RetryTimes >= MAX_RETRY_TIMES) {
872 return EFI_DEVICE_ERROR;
873 }
874 break;
875
876 case EfiUsbPortResetChange:
877 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
878
879 //
880 // Verify the state
881 //
882 RetryTimes = 0;
883 do {
884 MicroSecondDelay (HC_1_MILLISECOND);
885 RetryTimes++;
886 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
887 RetryTimes < MAX_RETRY_TIMES);
888
889 if (RetryTimes >= MAX_RETRY_TIMES) {
890 return EFI_DEVICE_ERROR;
891 }
892 break;
893
894
895 case EfiUsbPortEnableChange:
896 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
897
898 //
899 // Verify the state
900 //
901 RetryTimes = 0;
902 do {
903 MicroSecondDelay (HC_1_MILLISECOND);
904 RetryTimes++;
905 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
906 RetryTimes < MAX_RETRY_TIMES);
907
908 if (RetryTimes >= MAX_RETRY_TIMES) {
909 return EFI_DEVICE_ERROR;
910 }
911 break;
912
913 case EfiUsbPortSuspendChange:
914 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
915
916 //
917 // Verify the state
918 //
919 RetryTimes = 0;
920 do {
921 MicroSecondDelay (HC_1_MILLISECOND);
922 RetryTimes++;
923 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
924 RetryTimes < MAX_RETRY_TIMES);
925
926 if (RetryTimes >= MAX_RETRY_TIMES) {
927 return EFI_DEVICE_ERROR;
928 }
929 break;
930
931 case EfiUsbPortOverCurrentChange:
932 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
933
934 //
935 // Verify the state
936 //
937 RetryTimes = 0;
938 do {
939 MicroSecondDelay (HC_1_MILLISECOND);
940 RetryTimes++;
941 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
942 RetryTimes < MAX_RETRY_TIMES);
943
944 if (RetryTimes >= MAX_RETRY_TIMES) {
945 return EFI_DEVICE_ERROR;
946 }
947 break;
948
949 default:
950 return EFI_INVALID_PARAMETER;
951 }
952
953 return Status;
954 }
955 /**
956 Provides software reset for the USB host controller.
957
958 @param This This EFI_USB_HC_PROTOCOL instance.
959 @param Attributes A bit mask of the reset operation to perform.
960
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.
966
967 **/
968 EFI_STATUS
969 InitializeUsbHC (
970 IN EFI_PEI_SERVICES **PeiServices,
971 IN USB_OHCI_HC_DEV *Ohc,
972 IN UINT16 Attributes
973 )
974 {
975 EFI_STATUS Status;
976 UINT8 Index;
977 UINT8 NumOfPorts;
978 UINT32 PowerOnGoodTime;
979 UINT32 Data32;
980 BOOLEAN Flag = FALSE;
981
982 if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
983 return EFI_INVALID_PARAMETER;
984 }
985 Status = EFI_SUCCESS;
986
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;
992 }
993 MicroSecondDelay (50 * HC_1_MILLISECOND);
994 //
995 // Wait for host controller reset.
996 //
997 PowerOnGoodTime = 50;
998 do {
999 MicroSecondDelay (HC_1_MILLISECOND);
1000 Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS );
1001 if ((Data32 & HC_RESET) == 0) {
1002 Flag = TRUE;
1003 break;
1004 }
1005 }while(PowerOnGoodTime--);
1006 if (!Flag){
1007 return EFI_DEVICE_ERROR;
1008 }
1009 }
1010
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;
1016 }
1017 MicroSecondDelay (50 * HC_1_MILLISECOND);
1018 }
1019 //
1020 // Initialize host controller operational registers
1021 //
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);
1031
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);
1044 }
1045 }
1046
1047 Ohc->MemPool = UsbHcInitMemPool(TRUE, 0);
1048 if(Ohc->MemPool == NULL) {
1049 return EFI_OUT_OF_RESOURCES;
1050 }
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);
1056 //
1057 // Wait till first SOF occurs, and then clear it
1058 //
1059 while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
1060 OhciClearInterruptStatus (Ohc, START_OF_FRAME);
1061 MicroSecondDelay (HC_1_MILLISECOND);
1062
1063 return EFI_SUCCESS;
1064 }
1065
1066 /**
1067 Submits control transfer to a target USB device.
1068
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.
1071
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.
1084
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.
1090
1091 **/
1092 EFI_STATUS
1093 EFIAPI
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,
1102 IN OUT VOID *Data,
1103 IN OUT UINTN *DataLength,
1104 IN UINTN TimeOut,
1105 OUT UINT32 *TransferResult
1106 )
1107 {
1108 EFI_STATUS Status;
1109 EFI_USB_DEVICE_REQUEST *NewRequest;
1110 VOID *NewData;
1111 UINT8 *Alloc;
1112
1113 //
1114 // Allocate memory external to IMR protected region for transfer data.
1115 //
1116 Status = PeiServicesAllocatePool (
1117 sizeof(EFI_USB_DEVICE_REQUEST) + *DataLength,
1118 (VOID **) &Alloc
1119 );
1120 ASSERT_EFI_ERROR (Status);
1121
1122 //
1123 // Setup pointers to transfer buffers.
1124 //
1125 NewRequest = (EFI_USB_DEVICE_REQUEST *) Alloc;
1126 Alloc += sizeof(EFI_USB_DEVICE_REQUEST);
1127 NewData = (VOID *) Alloc;
1128
1129 //
1130 // Copy callers request packet into transfer request packet.
1131 //
1132 if (Request != NULL) {
1133 CopyMem (NewRequest,Request,sizeof(EFI_USB_DEVICE_REQUEST));
1134 } else {
1135 NewRequest = NULL;
1136 }
1137 //
1138 // Copy callers data into transfer data buffer.
1139 //
1140 if (Data != NULL) {
1141 if (DataLength > 0) {
1142 CopyMem (NewData,Data,*DataLength);
1143 }
1144 } else {
1145 NewData = NULL;
1146 }
1147
1148 //
1149 // Call underlying OhciControlTransfer to do work.
1150 //
1151 Status = OhciControlTransfer (
1152 PeiServices,
1153 This,
1154 DeviceAddress,
1155 DeviceSpeed,
1156 MaxPacketLength,
1157 NewRequest,
1158 TransferDirection,
1159 NewData,
1160 DataLength,
1161 TimeOut,
1162 TransferResult
1163 );
1164
1165 //
1166 // Copy transfer buffer back into callers buffer.
1167 //
1168 if (Data != NULL && *DataLength > 0) {
1169 CopyMem (Data, NewData, *DataLength);
1170 }
1171
1172 return Status;
1173 }
1174
1175 /**
1176 Submits bulk transfer to a bulk endpoint of a USB device.
1177
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.
1180
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
1196 bulk transfer.
1197
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.
1203
1204 **/
1205 EFI_STATUS
1206 EFIAPI
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,
1213 IN OUT VOID *Data,
1214 IN OUT UINTN *DataLength,
1215 IN OUT UINT8 *DataToggle,
1216 IN UINTN TimeOut,
1217 OUT UINT32 *TransferResult
1218 )
1219 {
1220 EFI_STATUS Status;
1221 UINT8 *NewData;
1222
1223 //
1224 // Allocate memory external to IMR protected region for transfer data.
1225 //
1226 Status = PeiServicesAllocatePool (
1227 *DataLength,
1228 (VOID **) &NewData
1229 );
1230 ASSERT_EFI_ERROR (Status);
1231
1232 //
1233 // Copy callers data into transfer buffer.
1234 //
1235 if (Data != NULL) {
1236 if (DataLength > 0) {
1237 CopyMem (NewData,Data,*DataLength);
1238 }
1239 } else {
1240 NewData = NULL;
1241 }
1242
1243 //
1244 // Call underlying OhciBulkTransfer to do work.
1245 //
1246 Status = OhciBulkTransfer (
1247 PeiServices,
1248 This,
1249 DeviceAddress,
1250 EndPointAddress,
1251 MaxPacketLength,
1252 NewData,
1253 DataLength,
1254 DataToggle,
1255 TimeOut,
1256 TransferResult
1257 );
1258
1259 //
1260 // Copy transfer buffer back into callers buffer.
1261 //
1262 if (Data != NULL && *DataLength > 0) {
1263 CopyMem (Data, NewData, *DataLength);
1264 }
1265
1266 return Status;
1267 }
1268
1269 /**
1270 @param FileHandle Handle of the file being invoked.
1271 @param PeiServices Describes the list of possible PEI Services.
1272
1273 @retval EFI_SUCCESS PPI successfully installed.
1274
1275 **/
1276 EFI_STATUS
1277 OhcPeimEntry (
1278 IN EFI_PEI_FILE_HANDLE FileHandle,
1279 IN CONST EFI_PEI_SERVICES **PeiServices
1280 )
1281 {
1282
1283 PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi;
1284 EFI_STATUS Status;
1285 UINT8 Index;
1286 UINTN ControllerType;
1287 UINTN BaseAddress;
1288 UINTN MemPages;
1289 USB_OHCI_HC_DEV *Ohc;
1290 EFI_PHYSICAL_ADDRESS TempPtr;
1291
1292
1293 //
1294 // Shadow this PEIM to run from memory
1295 //
1296 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1297 return EFI_SUCCESS;
1298 }
1299 Status = PeiServicesLocatePpi (
1300 &gPeiUsbControllerPpiGuid,
1301 0,
1302 NULL,
1303 (VOID **) &ChipSetUsbControllerPpi
1304 );
1305 if (EFI_ERROR (Status)) {
1306 return EFI_UNSUPPORTED;
1307 }
1308
1309 Index = 0;
1310 while (TRUE) {
1311 Status = ChipSetUsbControllerPpi->GetUsbController (
1312 (EFI_PEI_SERVICES **) PeiServices,
1313 ChipSetUsbControllerPpi,
1314 Index,
1315 &ControllerType,
1316 &BaseAddress
1317 );
1318 //
1319 // When status is error, meant no controller is found
1320 //
1321 if (EFI_ERROR (Status)) {
1322 break;
1323 }
1324 //
1325 // This PEIM is for OHC type controller.
1326 //
1327 if (ControllerType != PEI_OHCI_CONTROLLER) {
1328 Index++;
1329 continue;
1330 }
1331
1332 MemPages = sizeof (USB_OHCI_HC_DEV) / PAGESIZE + 1;
1333 Status = PeiServicesAllocatePages (
1334 EfiBootServicesCode,
1335 MemPages,
1336 &TempPtr
1337 );
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;
1341 }
1342 ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
1343 Ohc = (USB_OHCI_HC_DEV *) ((UINTN) TempPtr);
1344
1345 Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;
1346
1347 Ohc->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
1348
1349 //
1350 // Initialize Uhc's hardware
1351 //
1352 Status = InitializeUsbHC (
1353 (EFI_PEI_SERVICES **)PeiServices,
1354 Ohc,
1355 EFI_USB_HC_RESET_GLOBAL
1356 );
1357 if (EFI_ERROR (Status)) {
1358 DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index));
1359 return Status;
1360 }
1361 //
1362 // Control & Bulk transfer services are accessed via their Redirect
1363 // routine versions on Quark so that USB DMA transfers do not cause an
1364 // IMR violation.
1365 //
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;
1372
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;
1376
1377 Status = PeiServicesInstallPpi (&Ohc->PpiDescriptor);
1378 if (EFI_ERROR (Status)) {
1379 Index++;
1380 continue;
1381 }
1382 Index++;
1383 }
1384 return EFI_SUCCESS;
1385 }
1386