]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c
QuarkSocPkg: Ohci/Pei: remove set but unused variables
[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 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
10
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.
13
14 **/
15
16
17 #include "OhcPeim.h"
18
19 /**
20 Submits control transfer to a target USB device.
21
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.
34
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.
40
41 **/
42 EFI_STATUS
43 EFIAPI
44 OhciControlTransfer (
45 IN EFI_PEI_SERVICES **PeiServices,
46 IN PEI_USB_HOST_CONTROLLER_PPI *This,
47 IN UINT8 DeviceAddress,
48 IN UINT8 DeviceSpeed,
49 IN UINT8 MaxPacketLength,
50 IN EFI_USB_DEVICE_REQUEST *Request,
51 IN EFI_USB_DATA_DIRECTION TransferDirection,
52 IN OUT VOID *Data,
53 IN OUT UINTN *DataLength,
54 IN UINTN TimeOut,
55 OUT UINT32 *TransferResult
56 )
57 {
58 USB_OHCI_HC_DEV *Ohc;
59 ED_DESCRIPTOR *Ed;
60 TD_DESCRIPTOR *HeadTd;
61 TD_DESCRIPTOR *SetupTd;
62 TD_DESCRIPTOR *DataTd;
63 TD_DESCRIPTOR *StatusTd;
64 TD_DESCRIPTOR *EmptyTd;
65 EFI_STATUS Status;
66 UINT32 DataPidDir;
67 UINT32 StatusPidDir;
68 UINTN TimeCount;
69 UINT32 ErrorCode;
70
71 UINTN ActualSendLength;
72 UINTN LeftLength;
73 UINT8 DataToggle;
74
75 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;
76
77 UINTN DataMapLength = 0;
78 EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;
79
80 HeadTd = NULL;
81 DataTd = NULL;
82
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;
93 }
94
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;
98 }
99
100 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This);
101
102 if (TransferDirection == EfiUsbDataIn) {
103 DataPidDir = TD_IN_PID;
104 StatusPidDir = TD_OUT_PID;
105 } else {
106 DataPidDir = TD_OUT_PID;
107 StatusPidDir = TD_IN_PID;
108 }
109
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;
117 }
118 }
119 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
120 Ed = OhciCreateED (Ohc);
121 if (Ed == NULL) {
122 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n"));
123 return EFI_OUT_OF_RESOURCES;
124 }
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);
138 //
139 // Setup Stage
140 //
141 if(Request != NULL) {
142 ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request;
143 }
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"));
148 goto FREE_ED_BUFF;
149 }
150 HeadTd = SetupTd;
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;
164
165 DataMapLength = *DataLength;
166 if ((Data != NULL) && (DataMapLength != 0)) {
167 DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
168 }
169 //
170 //Data Stage
171 //
172 LeftLength = DataMapLength;
173 ActualSendLength = DataMapLength;
174 DataToggle = 1;
175 while (LeftLength > 0) {
176 ActualSendLength = LeftLength;
177 if (LeftLength > MaxPacketLength) {
178 ActualSendLength = MaxPacketLength;
179 }
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;
184 goto FREE_TD_BUFF;
185 }
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);
200 DataToggle ^= 1;
201 DataMapPhyAddr += ActualSendLength;
202 LeftLength -= ActualSendLength;
203 }
204 //
205 // Status Stage
206 //
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;
211 goto FREE_TD_BUFF;
212 }
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);
227 //
228 // Empty Stage
229 //
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"));
234 goto FREE_TD_BUFF;
235 }
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);
253 //
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"));
265 goto FREE_TD_BUFF;
266 }
267 }
268
269 TimeCount = 0;
270 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
271
272 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
273 MicroSecondDelay (HC_1_MILLISECOND);
274 TimeCount++;
275 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
276 }
277 //
278 *TransferResult = ConvertErrorCode (ErrorCode);
279
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));
283 } else {
284 DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
285 }
286
287 *DataLength = 0;
288 }
289
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"));
296 goto FREE_TD_BUFF;
297 }
298 }
299
300 FREE_TD_BUFF:
301 while (HeadTd) {
302 DataTd = HeadTd;
303 HeadTd = HeadTd->NextTDPointer;
304 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
305 }
306
307 FREE_ED_BUFF:
308 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
309
310 return Status;
311 }
312
313 /**
314 Submits bulk transfer to a bulk endpoint of a USB device.
315
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
331 bulk transfer.
332
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.
338
339 **/
340 EFI_STATUS
341 EFIAPI
342 OhciBulkTransfer (
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,
348 IN OUT VOID *Data,
349 IN OUT UINTN *DataLength,
350 IN OUT UINT8 *DataToggle,
351 IN UINTN TimeOut,
352 OUT UINT32 *TransferResult
353 )
354 {
355 USB_OHCI_HC_DEV *Ohc;
356 ED_DESCRIPTOR *Ed;
357 UINT32 DataPidDir;
358 TD_DESCRIPTOR *HeadTd;
359 TD_DESCRIPTOR *DataTd;
360 TD_DESCRIPTOR *EmptyTd;
361 EFI_STATUS Status;
362 UINT8 EndPointNum;
363 UINTN TimeCount;
364 UINT32 ErrorCode;
365
366 UINT8 CurrentToggle;
367 UINTN MapLength;
368 EFI_PHYSICAL_ADDRESS MapPyhAddr;
369 UINTN LeftLength;
370 UINTN ActualSendLength;
371 BOOLEAN FirstTD;
372
373 MapLength = 0;
374 MapPyhAddr = 0;
375 LeftLength = 0;
376 Status = EFI_SUCCESS;
377
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;
383 }
384
385 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
386
387 if ((EndPointAddress & 0x80) != 0) {
388 DataPidDir = TD_IN_PID;
389 } else {
390 DataPidDir = TD_OUT_PID;
391 }
392
393 EndPointNum = (EndPointAddress & 0xF);
394
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;
401 }
402 }
403
404 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
405
406 Ed = OhciCreateED (Ohc);
407 if (Ed == NULL) {
408 DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
409 return EFI_OUT_OF_RESOURCES;
410 }
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);
424
425 if(Data != NULL) {
426 MapLength = *DataLength;
427 MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
428 }
429 //
430 //Data Stage
431 //
432 LeftLength = MapLength;
433 ActualSendLength = MapLength;
434 CurrentToggle = *DataToggle;
435 HeadTd = NULL;
436 FirstTD = TRUE;
437 while (LeftLength > 0) {
438 ActualSendLength = LeftLength;
439 if (LeftLength > MaxPacketLength) {
440 ActualSendLength = MaxPacketLength;
441 }
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;
446 goto FREE_TD_BUFF;
447 }
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;
461 if (FirstTD) {
462 HeadTd = DataTd;
463 FirstTD = FALSE;
464 } else {
465 OhciLinkTD (HeadTd, DataTd);
466 }
467 CurrentToggle ^= 1;
468 MapPyhAddr += ActualSendLength;
469 LeftLength -= ActualSendLength;
470 }
471 //
472 // Empty Stage
473 //
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"));
478 goto FREE_TD_BUFF;
479 }
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);
497
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;
505 goto FREE_TD_BUFF;
506 }
507 }
508
509 TimeCount = 0;
510 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
511
512 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
513 MicroSecondDelay (HC_1_MILLISECOND);
514 TimeCount++;
515 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
516 }
517
518 *TransferResult = ConvertErrorCode (ErrorCode);
519
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));
523 } else {
524 DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
525 }
526 *DataLength = 0;
527 }
528 *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
529
530 FREE_TD_BUFF:
531 while (HeadTd) {
532 DataTd = HeadTd;
533 HeadTd = HeadTd->NextTDPointer;
534 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
535 }
536 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
537
538 return Status;
539 }
540 /**
541 Retrieves the number of root hub ports.
542
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.
547
548 @retval EFI_SUCCESS The port number was retrieved successfully.
549 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
550
551 **/
552
553 EFI_STATUS
554 EFIAPI
555 OhciGetRootHubNumOfPorts (
556 IN EFI_PEI_SERVICES **PeiServices,
557 IN PEI_USB_HOST_CONTROLLER_PPI *This,
558 OUT UINT8 *NumOfPorts
559 )
560 {
561 USB_OHCI_HC_DEV *Ohc;
562 if (NumOfPorts == NULL) {
563 return EFI_INVALID_PARAMETER;
564 }
565 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
566 *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
567
568 return EFI_SUCCESS;
569 }
570 /**
571 Retrieves the current status of a USB root hub port.
572
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.
577
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.
581
582 **/
583
584 EFI_STATUS
585 EFIAPI
586 OhciGetRootHubPortStatus (
587 IN EFI_PEI_SERVICES **PeiServices,
588 IN PEI_USB_HOST_CONTROLLER_PPI *This,
589 IN UINT8 PortNumber,
590 OUT EFI_USB_PORT_STATUS *PortStatus
591 )
592 {
593 USB_OHCI_HC_DEV *Ohc;
594 UINT8 NumOfPorts;
595
596 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
597
598 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
599 if (PortNumber >= NumOfPorts) {
600 return EFI_INVALID_PARAMETER;
601 }
602 PortStatus->PortStatus = 0;
603 PortStatus->PortChangeStatus = 0;
604
605 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
606 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
607 }
608 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
609 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
610 }
611 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
612 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
613 }
614 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
615 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
616 }
617 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
618 PortStatus->PortStatus |= USB_PORT_STAT_RESET;
619 }
620 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
621 PortStatus->PortStatus |= USB_PORT_STAT_POWER;
622 }
623 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
624 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
625 }
626 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
627 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
628 }
629 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
630 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
631 }
632 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
633 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
634 }
635 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
636 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
637 }
638 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
639 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
640 }
641
642 return EFI_SUCCESS;
643 }
644 /**
645 Sets a feature for the specified root hub port.
646
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.
651
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.
655
656 **/
657
658 EFI_STATUS
659 EFIAPI
660 OhciSetRootHubPortFeature (
661 IN EFI_PEI_SERVICES **PeiServices,
662 IN PEI_USB_HOST_CONTROLLER_PPI *This,
663 IN UINT8 PortNumber,
664 IN EFI_USB_PORT_FEATURE PortFeature
665 )
666 {
667 USB_OHCI_HC_DEV *Ohc;
668 EFI_STATUS Status;
669 UINT8 NumOfPorts;
670 UINTN RetryTimes;
671
672 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
673 if (PortNumber >= NumOfPorts) {
674 return EFI_INVALID_PARAMETER;
675 }
676
677 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
678
679 Status = EFI_SUCCESS;
680
681
682 switch (PortFeature) {
683 case EfiUsbPortPower:
684 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
685
686 //
687 // Verify the state
688 //
689 RetryTimes = 0;
690 do {
691 MicroSecondDelay (HC_1_MILLISECOND);
692 RetryTimes++;
693 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
694 RetryTimes < MAX_RETRY_TIMES);
695
696 if (RetryTimes >= MAX_RETRY_TIMES) {
697 return EFI_DEVICE_ERROR;
698 }
699 break;
700
701 case EfiUsbPortReset:
702 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
703
704 //
705 // Verify the state
706 //
707 RetryTimes = 0;
708 do {
709 MicroSecondDelay (HC_1_MILLISECOND);
710 RetryTimes++;
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);
714
715 if (RetryTimes >= MAX_RETRY_TIMES) {
716 return EFI_DEVICE_ERROR;
717 }
718
719 OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
720 break;
721
722 case EfiUsbPortEnable:
723 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
724
725 //
726 // Verify the state
727 //
728 RetryTimes = 0;
729 do {
730 MicroSecondDelay (HC_1_MILLISECOND);;
731 RetryTimes++;
732 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
733 RetryTimes < MAX_RETRY_TIMES);
734
735 if (RetryTimes >= MAX_RETRY_TIMES) {
736 return EFI_DEVICE_ERROR;
737 }
738 break;
739
740
741 case EfiUsbPortSuspend:
742 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
743
744 //
745 // Verify the state
746 //
747 RetryTimes = 0;
748 do {
749 MicroSecondDelay (HC_1_MILLISECOND);;
750 RetryTimes++;
751 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
752 RetryTimes < MAX_RETRY_TIMES);
753
754 if (RetryTimes >= MAX_RETRY_TIMES) {
755 return EFI_DEVICE_ERROR;
756 }
757 break;
758
759 default:
760 return EFI_INVALID_PARAMETER;
761 }
762
763 return Status;
764 }
765
766 /**
767 Clears a feature for the specified root hub port.
768
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.
775
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.
779
780 **/
781
782 EFI_STATUS
783 EFIAPI
784 OhciClearRootHubPortFeature (
785 IN EFI_PEI_SERVICES **PeiServices,
786 IN PEI_USB_HOST_CONTROLLER_PPI *This,
787 IN UINT8 PortNumber,
788 IN EFI_USB_PORT_FEATURE PortFeature
789 )
790 {
791 USB_OHCI_HC_DEV *Ohc;
792 EFI_STATUS Status;
793 UINT8 NumOfPorts;
794 UINTN RetryTimes;
795
796
797 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
798 if (PortNumber >= NumOfPorts) {
799 return EFI_INVALID_PARAMETER;
800 }
801
802 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
803
804 Status = EFI_SUCCESS;
805
806 switch (PortFeature) {
807 case EfiUsbPortEnable:
808 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
809
810 //
811 // Verify the state
812 //
813 RetryTimes = 0;
814 do {
815 MicroSecondDelay (HC_1_MILLISECOND);
816 RetryTimes++;
817 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
818 RetryTimes < MAX_RETRY_TIMES);
819
820 if (RetryTimes >= MAX_RETRY_TIMES) {
821 return EFI_DEVICE_ERROR;
822 }
823 break;
824
825 case EfiUsbPortSuspend:
826 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
827
828 //
829 // Verify the state
830 //
831 RetryTimes = 0;
832 do {
833 MicroSecondDelay (HC_1_MILLISECOND);
834 RetryTimes++;
835 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
836 RetryTimes < MAX_RETRY_TIMES);
837
838 if (RetryTimes >= MAX_RETRY_TIMES) {
839 return EFI_DEVICE_ERROR;
840 }
841 break;
842
843 case EfiUsbPortReset:
844 break;
845
846 case EfiUsbPortPower:
847 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
848
849 //
850 // Verify the state
851 //
852 RetryTimes = 0;
853 do {
854 MicroSecondDelay (HC_1_MILLISECOND);
855 RetryTimes++;
856 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
857 RetryTimes < MAX_RETRY_TIMES);
858
859 if (RetryTimes >= MAX_RETRY_TIMES) {
860 return EFI_DEVICE_ERROR;
861 }
862 break;
863
864 case EfiUsbPortConnectChange:
865 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
866
867 //
868 // Verify the state
869 //
870 RetryTimes = 0;
871 do {
872 MicroSecondDelay (HC_1_MILLISECOND);
873 RetryTimes++;
874 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
875 RetryTimes < MAX_RETRY_TIMES);
876
877 if (RetryTimes >= MAX_RETRY_TIMES) {
878 return EFI_DEVICE_ERROR;
879 }
880 break;
881
882 case EfiUsbPortResetChange:
883 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
884
885 //
886 // Verify the state
887 //
888 RetryTimes = 0;
889 do {
890 MicroSecondDelay (HC_1_MILLISECOND);
891 RetryTimes++;
892 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
893 RetryTimes < MAX_RETRY_TIMES);
894
895 if (RetryTimes >= MAX_RETRY_TIMES) {
896 return EFI_DEVICE_ERROR;
897 }
898 break;
899
900
901 case EfiUsbPortEnableChange:
902 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
903
904 //
905 // Verify the state
906 //
907 RetryTimes = 0;
908 do {
909 MicroSecondDelay (HC_1_MILLISECOND);
910 RetryTimes++;
911 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
912 RetryTimes < MAX_RETRY_TIMES);
913
914 if (RetryTimes >= MAX_RETRY_TIMES) {
915 return EFI_DEVICE_ERROR;
916 }
917 break;
918
919 case EfiUsbPortSuspendChange:
920 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
921
922 //
923 // Verify the state
924 //
925 RetryTimes = 0;
926 do {
927 MicroSecondDelay (HC_1_MILLISECOND);
928 RetryTimes++;
929 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
930 RetryTimes < MAX_RETRY_TIMES);
931
932 if (RetryTimes >= MAX_RETRY_TIMES) {
933 return EFI_DEVICE_ERROR;
934 }
935 break;
936
937 case EfiUsbPortOverCurrentChange:
938 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
939
940 //
941 // Verify the state
942 //
943 RetryTimes = 0;
944 do {
945 MicroSecondDelay (HC_1_MILLISECOND);
946 RetryTimes++;
947 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
948 RetryTimes < MAX_RETRY_TIMES);
949
950 if (RetryTimes >= MAX_RETRY_TIMES) {
951 return EFI_DEVICE_ERROR;
952 }
953 break;
954
955 default:
956 return EFI_INVALID_PARAMETER;
957 }
958
959 return Status;
960 }
961 /**
962 Provides software reset for the USB host controller.
963
964 @param This This EFI_USB_HC_PROTOCOL instance.
965 @param Attributes A bit mask of the reset operation to perform.
966
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.
972
973 **/
974 EFI_STATUS
975 InitializeUsbHC (
976 IN EFI_PEI_SERVICES **PeiServices,
977 IN USB_OHCI_HC_DEV *Ohc,
978 IN UINT16 Attributes
979 )
980 {
981 EFI_STATUS Status;
982 UINT8 Index;
983 UINT8 NumOfPorts;
984 UINT32 PowerOnGoodTime;
985 UINT32 Data32;
986 BOOLEAN Flag = FALSE;
987
988 if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
989 return EFI_INVALID_PARAMETER;
990 }
991 Status = EFI_SUCCESS;
992
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;
998 }
999 MicroSecondDelay (50 * HC_1_MILLISECOND);
1000 //
1001 // Wait for host controller reset.
1002 //
1003 PowerOnGoodTime = 50;
1004 do {
1005 MicroSecondDelay (HC_1_MILLISECOND);
1006 Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS );
1007 if ((Data32 & HC_RESET) == 0) {
1008 Flag = TRUE;
1009 break;
1010 }
1011 }while(PowerOnGoodTime--);
1012 if (!Flag){
1013 return EFI_DEVICE_ERROR;
1014 }
1015 }
1016
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;
1022 }
1023 MicroSecondDelay (50 * HC_1_MILLISECOND);
1024 }
1025 //
1026 // Initialize host controller operational registers
1027 //
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);
1037
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);
1050 }
1051 }
1052
1053 Ohc->MemPool = UsbHcInitMemPool(TRUE, 0);
1054 if(Ohc->MemPool == NULL) {
1055 return EFI_OUT_OF_RESOURCES;
1056 }
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);
1062 //
1063 // Wait till first SOF occurs, and then clear it
1064 //
1065 while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
1066 OhciClearInterruptStatus (Ohc, START_OF_FRAME);
1067 MicroSecondDelay (HC_1_MILLISECOND);
1068
1069 return EFI_SUCCESS;
1070 }
1071
1072 /**
1073 Submits control transfer to a target USB device.
1074
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.
1077
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.
1090
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.
1096
1097 **/
1098 EFI_STATUS
1099 EFIAPI
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,
1108 IN OUT VOID *Data,
1109 IN OUT UINTN *DataLength,
1110 IN UINTN TimeOut,
1111 OUT UINT32 *TransferResult
1112 )
1113 {
1114 EFI_STATUS Status;
1115 EFI_USB_DEVICE_REQUEST *NewRequest;
1116 VOID *NewData;
1117 UINT8 *Alloc;
1118
1119 //
1120 // Allocate memory external to IMR protected region for transfer data.
1121 //
1122 Status = PeiServicesAllocatePool (
1123 sizeof(EFI_USB_DEVICE_REQUEST) + *DataLength,
1124 (VOID **) &Alloc
1125 );
1126 ASSERT_EFI_ERROR (Status);
1127
1128 //
1129 // Setup pointers to transfer buffers.
1130 //
1131 NewRequest = (EFI_USB_DEVICE_REQUEST *) Alloc;
1132 Alloc += sizeof(EFI_USB_DEVICE_REQUEST);
1133 NewData = (VOID *) Alloc;
1134
1135 //
1136 // Copy callers request packet into transfer request packet.
1137 //
1138 if (Request != NULL) {
1139 CopyMem (NewRequest,Request,sizeof(EFI_USB_DEVICE_REQUEST));
1140 } else {
1141 NewRequest = NULL;
1142 }
1143 //
1144 // Copy callers data into transfer data buffer.
1145 //
1146 if (Data != NULL) {
1147 if (DataLength > 0) {
1148 CopyMem (NewData,Data,*DataLength);
1149 }
1150 } else {
1151 NewData = NULL;
1152 }
1153
1154 //
1155 // Call underlying OhciControlTransfer to do work.
1156 //
1157 Status = OhciControlTransfer (
1158 PeiServices,
1159 This,
1160 DeviceAddress,
1161 DeviceSpeed,
1162 MaxPacketLength,
1163 NewRequest,
1164 TransferDirection,
1165 NewData,
1166 DataLength,
1167 TimeOut,
1168 TransferResult
1169 );
1170
1171 //
1172 // Copy transfer buffer back into callers buffer.
1173 //
1174 if (Data != NULL && *DataLength > 0) {
1175 CopyMem (Data, NewData, *DataLength);
1176 }
1177
1178 return Status;
1179 }
1180
1181 /**
1182 Submits bulk transfer to a bulk endpoint of a USB device.
1183
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.
1186
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
1202 bulk transfer.
1203
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.
1209
1210 **/
1211 EFI_STATUS
1212 EFIAPI
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,
1219 IN OUT VOID *Data,
1220 IN OUT UINTN *DataLength,
1221 IN OUT UINT8 *DataToggle,
1222 IN UINTN TimeOut,
1223 OUT UINT32 *TransferResult
1224 )
1225 {
1226 EFI_STATUS Status;
1227 UINT8 *NewData;
1228
1229 //
1230 // Allocate memory external to IMR protected region for transfer data.
1231 //
1232 Status = PeiServicesAllocatePool (
1233 *DataLength,
1234 (VOID **) &NewData
1235 );
1236 ASSERT_EFI_ERROR (Status);
1237
1238 //
1239 // Copy callers data into transfer buffer.
1240 //
1241 if (Data != NULL) {
1242 if (DataLength > 0) {
1243 CopyMem (NewData,Data,*DataLength);
1244 }
1245 } else {
1246 NewData = NULL;
1247 }
1248
1249 //
1250 // Call underlying OhciBulkTransfer to do work.
1251 //
1252 Status = OhciBulkTransfer (
1253 PeiServices,
1254 This,
1255 DeviceAddress,
1256 EndPointAddress,
1257 MaxPacketLength,
1258 NewData,
1259 DataLength,
1260 DataToggle,
1261 TimeOut,
1262 TransferResult
1263 );
1264
1265 //
1266 // Copy transfer buffer back into callers buffer.
1267 //
1268 if (Data != NULL && *DataLength > 0) {
1269 CopyMem (Data, NewData, *DataLength);
1270 }
1271
1272 return Status;
1273 }
1274
1275 /**
1276 @param FileHandle Handle of the file being invoked.
1277 @param PeiServices Describes the list of possible PEI Services.
1278
1279 @retval EFI_SUCCESS PPI successfully installed.
1280
1281 **/
1282 EFI_STATUS
1283 OhcPeimEntry (
1284 IN EFI_PEI_FILE_HANDLE FileHandle,
1285 IN CONST EFI_PEI_SERVICES **PeiServices
1286 )
1287 {
1288
1289 PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi;
1290 EFI_STATUS Status;
1291 UINT8 Index;
1292 UINTN ControllerType;
1293 UINTN BaseAddress;
1294 UINTN MemPages;
1295 USB_OHCI_HC_DEV *Ohc;
1296 EFI_PHYSICAL_ADDRESS TempPtr;
1297
1298
1299 //
1300 // Shadow this PEIM to run from memory
1301 //
1302 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1303 return EFI_SUCCESS;
1304 }
1305 Status = PeiServicesLocatePpi (
1306 &gPeiUsbControllerPpiGuid,
1307 0,
1308 NULL,
1309 (VOID **) &ChipSetUsbControllerPpi
1310 );
1311 if (EFI_ERROR (Status)) {
1312 return EFI_UNSUPPORTED;
1313 }
1314
1315 Index = 0;
1316 while (TRUE) {
1317 Status = ChipSetUsbControllerPpi->GetUsbController (
1318 (EFI_PEI_SERVICES **) PeiServices,
1319 ChipSetUsbControllerPpi,
1320 Index,
1321 &ControllerType,
1322 &BaseAddress
1323 );
1324 //
1325 // When status is error, meant no controller is found
1326 //
1327 if (EFI_ERROR (Status)) {
1328 break;
1329 }
1330 //
1331 // This PEIM is for OHC type controller.
1332 //
1333 if (ControllerType != PEI_OHCI_CONTROLLER) {
1334 Index++;
1335 continue;
1336 }
1337
1338 MemPages = sizeof (USB_OHCI_HC_DEV) / PAGESIZE + 1;
1339 Status = PeiServicesAllocatePages (
1340 EfiBootServicesCode,
1341 MemPages,
1342 &TempPtr
1343 );
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;
1347 }
1348 ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
1349 Ohc = (USB_OHCI_HC_DEV *) ((UINTN) TempPtr);
1350
1351 Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;
1352
1353 Ohc->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
1354
1355 //
1356 // Initialize Uhc's hardware
1357 //
1358 Status = InitializeUsbHC (
1359 (EFI_PEI_SERVICES **)PeiServices,
1360 Ohc,
1361 EFI_USB_HC_RESET_GLOBAL
1362 );
1363 if (EFI_ERROR (Status)) {
1364 DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index));
1365 return Status;
1366 }
1367 //
1368 // Control & Bulk transfer services are accessed via their Redirect
1369 // routine versions on Quark so that USB DMA transfers do not cause an
1370 // IMR violation.
1371 //
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;
1378
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;
1382
1383 Status = PeiServicesInstallPpi (&Ohc->PpiDescriptor);
1384 if (EFI_ERROR (Status)) {
1385 Index++;
1386 continue;
1387 }
1388 Index++;
1389 }
1390 return EFI_SUCCESS;
1391 }
1392