]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Pei/OhcPeim.c
QuarkSocPkg: Add new package for Quark SoC X1000
[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 UINTN ReqMapLength = 0;
76 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;
77
78 UINTN DataMapLength = 0;
79 EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;
80
81 HeadTd = NULL;
82 DataTd = NULL;
83
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;
94 }
95
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;
99 }
100
101 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS(This);
102
103 if (TransferDirection == EfiUsbDataIn) {
104 DataPidDir = TD_IN_PID;
105 StatusPidDir = TD_OUT_PID;
106 } else {
107 DataPidDir = TD_OUT_PID;
108 StatusPidDir = TD_IN_PID;
109 }
110
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;
118 }
119 }
120 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
121 Ed = OhciCreateED (Ohc);
122 if (Ed == NULL) {
123 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\n"));
124 return EFI_OUT_OF_RESOURCES;
125 }
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);
139 //
140 // Setup Stage
141 //
142 if(Request != NULL) {
143 ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);
144 ReqMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Request;
145 }
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"));
150 goto FREE_ED_BUFF;
151 }
152 HeadTd = SetupTd;
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;
166
167 DataMapLength = *DataLength;
168 if ((Data != NULL) && (DataMapLength != 0)) {
169 DataMapPhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
170 }
171 //
172 //Data Stage
173 //
174 LeftLength = DataMapLength;
175 ActualSendLength = DataMapLength;
176 DataToggle = 1;
177 while (LeftLength > 0) {
178 ActualSendLength = LeftLength;
179 if (LeftLength > MaxPacketLength) {
180 ActualSendLength = MaxPacketLength;
181 }
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;
186 goto FREE_TD_BUFF;
187 }
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);
202 DataToggle ^= 1;
203 DataMapPhyAddr += ActualSendLength;
204 LeftLength -= ActualSendLength;
205 }
206 //
207 // Status Stage
208 //
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;
213 goto FREE_TD_BUFF;
214 }
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);
229 //
230 // Empty Stage
231 //
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"));
236 goto FREE_TD_BUFF;
237 }
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);
255 //
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"));
267 goto FREE_TD_BUFF;
268 }
269 }
270
271 TimeCount = 0;
272 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
273
274 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
275 MicroSecondDelay (HC_1_MILLISECOND);
276 TimeCount++;
277 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &ErrorCode);
278 }
279 //
280 *TransferResult = ConvertErrorCode (ErrorCode);
281
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));
285 } else {
286 DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
287 }
288
289 *DataLength = 0;
290 }
291
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"));
298 goto FREE_TD_BUFF;
299 }
300 }
301
302 FREE_TD_BUFF:
303 while (HeadTd) {
304 DataTd = HeadTd;
305 HeadTd = HeadTd->NextTDPointer;
306 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
307 }
308
309 FREE_ED_BUFF:
310 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
311
312 return Status;
313 }
314
315 /**
316 Submits bulk transfer to a bulk endpoint of a USB device.
317
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
333 bulk transfer.
334
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.
340
341 **/
342 EFI_STATUS
343 EFIAPI
344 OhciBulkTransfer (
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,
350 IN OUT VOID *Data,
351 IN OUT UINTN *DataLength,
352 IN OUT UINT8 *DataToggle,
353 IN UINTN TimeOut,
354 OUT UINT32 *TransferResult
355 )
356 {
357 USB_OHCI_HC_DEV *Ohc;
358 ED_DESCRIPTOR *Ed;
359 UINT8 EdDir;
360 UINT32 DataPidDir;
361 TD_DESCRIPTOR *HeadTd;
362 TD_DESCRIPTOR *DataTd;
363 TD_DESCRIPTOR *EmptyTd;
364 EFI_STATUS Status;
365 EFI_USB_DATA_DIRECTION TransferDirection;
366 UINT8 EndPointNum;
367 UINTN TimeCount;
368 UINT32 ErrorCode;
369
370 UINT8 CurrentToggle;
371 VOID *Mapping;
372 UINTN MapLength;
373 EFI_PHYSICAL_ADDRESS MapPyhAddr;
374 UINTN LeftLength;
375 UINTN ActualSendLength;
376 BOOLEAN FirstTD;
377
378 Mapping = NULL;
379 MapLength = 0;
380 MapPyhAddr = 0;
381 LeftLength = 0;
382 Status = EFI_SUCCESS;
383
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;
389 }
390
391 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
392
393 if ((EndPointAddress & 0x80) != 0) {
394 TransferDirection = EfiUsbDataIn;
395 EdDir = ED_IN_DIR;
396 DataPidDir = TD_IN_PID;
397 } else {
398 TransferDirection = EfiUsbDataOut;
399 EdDir = ED_OUT_DIR;
400 DataPidDir = TD_OUT_PID;
401 }
402
403 EndPointNum = (EndPointAddress & 0xF);
404
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;
411 }
412 }
413
414 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
415
416 Ed = OhciCreateED (Ohc);
417 if (Ed == NULL) {
418 DEBUG ((EFI_D_INFO, "OhcBulkTransfer: Fail to allocate ED buffer\r\n"));
419 return EFI_OUT_OF_RESOURCES;
420 }
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);
434
435 if(Data != NULL) {
436 MapLength = *DataLength;
437 MapPyhAddr = (EFI_PHYSICAL_ADDRESS)(UINTN)Data;
438 }
439 //
440 //Data Stage
441 //
442 LeftLength = MapLength;
443 ActualSendLength = MapLength;
444 CurrentToggle = *DataToggle;
445 HeadTd = NULL;
446 FirstTD = TRUE;
447 while (LeftLength > 0) {
448 ActualSendLength = LeftLength;
449 if (LeftLength > MaxPacketLength) {
450 ActualSendLength = MaxPacketLength;
451 }
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;
456 goto FREE_TD_BUFF;
457 }
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;
471 if (FirstTD) {
472 HeadTd = DataTd;
473 FirstTD = FALSE;
474 } else {
475 OhciLinkTD (HeadTd, DataTd);
476 }
477 CurrentToggle ^= 1;
478 MapPyhAddr += ActualSendLength;
479 LeftLength -= ActualSendLength;
480 }
481 //
482 // Empty Stage
483 //
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"));
488 goto FREE_TD_BUFF;
489 }
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);
507
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;
515 goto FREE_TD_BUFF;
516 }
517 }
518
519 TimeCount = 0;
520 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
521
522 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
523 MicroSecondDelay (HC_1_MILLISECOND);
524 TimeCount++;
525 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &ErrorCode);
526 }
527
528 *TransferResult = ConvertErrorCode (ErrorCode);
529
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));
533 } else {
534 DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
535 }
536 *DataLength = 0;
537 }
538 *DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
539
540 FREE_TD_BUFF:
541 while (HeadTd) {
542 DataTd = HeadTd;
543 HeadTd = HeadTd->NextTDPointer;
544 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
545 }
546 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
547
548 return Status;
549 }
550 /**
551 Retrieves the number of root hub ports.
552
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.
557
558 @retval EFI_SUCCESS The port number was retrieved successfully.
559 @retval EFI_INVALID_PARAMETER PortNumber is NULL.
560
561 **/
562
563 EFI_STATUS
564 EFIAPI
565 OhciGetRootHubNumOfPorts (
566 IN EFI_PEI_SERVICES **PeiServices,
567 IN PEI_USB_HOST_CONTROLLER_PPI *This,
568 OUT UINT8 *NumOfPorts
569 )
570 {
571 USB_OHCI_HC_DEV *Ohc;
572 if (NumOfPorts == NULL) {
573 return EFI_INVALID_PARAMETER;
574 }
575 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
576 *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
577
578 return EFI_SUCCESS;
579 }
580 /**
581 Retrieves the current status of a USB root hub port.
582
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.
587
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.
591
592 **/
593
594 EFI_STATUS
595 EFIAPI
596 OhciGetRootHubPortStatus (
597 IN EFI_PEI_SERVICES **PeiServices,
598 IN PEI_USB_HOST_CONTROLLER_PPI *This,
599 IN UINT8 PortNumber,
600 OUT EFI_USB_PORT_STATUS *PortStatus
601 )
602 {
603 USB_OHCI_HC_DEV *Ohc;
604 UINT8 NumOfPorts;
605
606 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
607
608 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
609 if (PortNumber >= NumOfPorts) {
610 return EFI_INVALID_PARAMETER;
611 }
612 PortStatus->PortStatus = 0;
613 PortStatus->PortChangeStatus = 0;
614
615 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
616 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
617 }
618 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
619 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
620 }
621 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
622 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
623 }
624 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
625 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
626 }
627 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
628 PortStatus->PortStatus |= USB_PORT_STAT_RESET;
629 }
630 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
631 PortStatus->PortStatus |= USB_PORT_STAT_POWER;
632 }
633 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
634 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
635 }
636 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
637 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
638 }
639 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
640 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
641 }
642 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
643 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
644 }
645 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
646 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
647 }
648 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
649 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
650 }
651
652 return EFI_SUCCESS;
653 }
654 /**
655 Sets a feature for the specified root hub port.
656
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.
661
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.
665
666 **/
667
668 EFI_STATUS
669 EFIAPI
670 OhciSetRootHubPortFeature (
671 IN EFI_PEI_SERVICES **PeiServices,
672 IN PEI_USB_HOST_CONTROLLER_PPI *This,
673 IN UINT8 PortNumber,
674 IN EFI_USB_PORT_FEATURE PortFeature
675 )
676 {
677 USB_OHCI_HC_DEV *Ohc;
678 EFI_STATUS Status;
679 UINT8 NumOfPorts;
680 UINTN RetryTimes;
681
682 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
683 if (PortNumber >= NumOfPorts) {
684 return EFI_INVALID_PARAMETER;
685 }
686
687 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
688
689 Status = EFI_SUCCESS;
690
691
692 switch (PortFeature) {
693 case EfiUsbPortPower:
694 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
695
696 //
697 // Verify the state
698 //
699 RetryTimes = 0;
700 do {
701 MicroSecondDelay (HC_1_MILLISECOND);
702 RetryTimes++;
703 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
704 RetryTimes < MAX_RETRY_TIMES);
705
706 if (RetryTimes >= MAX_RETRY_TIMES) {
707 return EFI_DEVICE_ERROR;
708 }
709 break;
710
711 case EfiUsbPortReset:
712 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
713
714 //
715 // Verify the state
716 //
717 RetryTimes = 0;
718 do {
719 MicroSecondDelay (HC_1_MILLISECOND);
720 RetryTimes++;
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);
724
725 if (RetryTimes >= MAX_RETRY_TIMES) {
726 return EFI_DEVICE_ERROR;
727 }
728
729 OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
730 break;
731
732 case EfiUsbPortEnable:
733 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
734
735 //
736 // Verify the state
737 //
738 RetryTimes = 0;
739 do {
740 MicroSecondDelay (HC_1_MILLISECOND);;
741 RetryTimes++;
742 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
743 RetryTimes < MAX_RETRY_TIMES);
744
745 if (RetryTimes >= MAX_RETRY_TIMES) {
746 return EFI_DEVICE_ERROR;
747 }
748 break;
749
750
751 case EfiUsbPortSuspend:
752 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
753
754 //
755 // Verify the state
756 //
757 RetryTimes = 0;
758 do {
759 MicroSecondDelay (HC_1_MILLISECOND);;
760 RetryTimes++;
761 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
762 RetryTimes < MAX_RETRY_TIMES);
763
764 if (RetryTimes >= MAX_RETRY_TIMES) {
765 return EFI_DEVICE_ERROR;
766 }
767 break;
768
769 default:
770 return EFI_INVALID_PARAMETER;
771 }
772
773 return Status;
774 }
775
776 /**
777 Clears a feature for the specified root hub port.
778
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.
785
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.
789
790 **/
791
792 EFI_STATUS
793 EFIAPI
794 OhciClearRootHubPortFeature (
795 IN EFI_PEI_SERVICES **PeiServices,
796 IN PEI_USB_HOST_CONTROLLER_PPI *This,
797 IN UINT8 PortNumber,
798 IN EFI_USB_PORT_FEATURE PortFeature
799 )
800 {
801 USB_OHCI_HC_DEV *Ohc;
802 EFI_STATUS Status;
803 UINT8 NumOfPorts;
804 UINTN RetryTimes;
805
806
807 OhciGetRootHubNumOfPorts (PeiServices, This, &NumOfPorts);
808 if (PortNumber >= NumOfPorts) {
809 return EFI_INVALID_PARAMETER;
810 }
811
812 Ohc = PEI_RECOVERY_USB_OHC_DEV_FROM_EHCI_THIS (This);
813
814 Status = EFI_SUCCESS;
815
816 switch (PortFeature) {
817 case EfiUsbPortEnable:
818 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
819
820 //
821 // Verify the state
822 //
823 RetryTimes = 0;
824 do {
825 MicroSecondDelay (HC_1_MILLISECOND);
826 RetryTimes++;
827 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
828 RetryTimes < MAX_RETRY_TIMES);
829
830 if (RetryTimes >= MAX_RETRY_TIMES) {
831 return EFI_DEVICE_ERROR;
832 }
833 break;
834
835 case EfiUsbPortSuspend:
836 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
837
838 //
839 // Verify the state
840 //
841 RetryTimes = 0;
842 do {
843 MicroSecondDelay (HC_1_MILLISECOND);
844 RetryTimes++;
845 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
846 RetryTimes < MAX_RETRY_TIMES);
847
848 if (RetryTimes >= MAX_RETRY_TIMES) {
849 return EFI_DEVICE_ERROR;
850 }
851 break;
852
853 case EfiUsbPortReset:
854 break;
855
856 case EfiUsbPortPower:
857 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
858
859 //
860 // Verify the state
861 //
862 RetryTimes = 0;
863 do {
864 MicroSecondDelay (HC_1_MILLISECOND);
865 RetryTimes++;
866 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
867 RetryTimes < MAX_RETRY_TIMES);
868
869 if (RetryTimes >= MAX_RETRY_TIMES) {
870 return EFI_DEVICE_ERROR;
871 }
872 break;
873
874 case EfiUsbPortConnectChange:
875 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
876
877 //
878 // Verify the state
879 //
880 RetryTimes = 0;
881 do {
882 MicroSecondDelay (HC_1_MILLISECOND);
883 RetryTimes++;
884 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
885 RetryTimes < MAX_RETRY_TIMES);
886
887 if (RetryTimes >= MAX_RETRY_TIMES) {
888 return EFI_DEVICE_ERROR;
889 }
890 break;
891
892 case EfiUsbPortResetChange:
893 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
894
895 //
896 // Verify the state
897 //
898 RetryTimes = 0;
899 do {
900 MicroSecondDelay (HC_1_MILLISECOND);
901 RetryTimes++;
902 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
903 RetryTimes < MAX_RETRY_TIMES);
904
905 if (RetryTimes >= MAX_RETRY_TIMES) {
906 return EFI_DEVICE_ERROR;
907 }
908 break;
909
910
911 case EfiUsbPortEnableChange:
912 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
913
914 //
915 // Verify the state
916 //
917 RetryTimes = 0;
918 do {
919 MicroSecondDelay (HC_1_MILLISECOND);
920 RetryTimes++;
921 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
922 RetryTimes < MAX_RETRY_TIMES);
923
924 if (RetryTimes >= MAX_RETRY_TIMES) {
925 return EFI_DEVICE_ERROR;
926 }
927 break;
928
929 case EfiUsbPortSuspendChange:
930 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
931
932 //
933 // Verify the state
934 //
935 RetryTimes = 0;
936 do {
937 MicroSecondDelay (HC_1_MILLISECOND);
938 RetryTimes++;
939 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
940 RetryTimes < MAX_RETRY_TIMES);
941
942 if (RetryTimes >= MAX_RETRY_TIMES) {
943 return EFI_DEVICE_ERROR;
944 }
945 break;
946
947 case EfiUsbPortOverCurrentChange:
948 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
949
950 //
951 // Verify the state
952 //
953 RetryTimes = 0;
954 do {
955 MicroSecondDelay (HC_1_MILLISECOND);
956 RetryTimes++;
957 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
958 RetryTimes < MAX_RETRY_TIMES);
959
960 if (RetryTimes >= MAX_RETRY_TIMES) {
961 return EFI_DEVICE_ERROR;
962 }
963 break;
964
965 default:
966 return EFI_INVALID_PARAMETER;
967 }
968
969 return Status;
970 }
971 /**
972 Provides software reset for the USB host controller.
973
974 @param This This EFI_USB_HC_PROTOCOL instance.
975 @param Attributes A bit mask of the reset operation to perform.
976
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.
982
983 **/
984 EFI_STATUS
985 InitializeUsbHC (
986 IN EFI_PEI_SERVICES **PeiServices,
987 IN USB_OHCI_HC_DEV *Ohc,
988 IN UINT16 Attributes
989 )
990 {
991 EFI_STATUS Status;
992 UINT8 Index;
993 UINT8 NumOfPorts;
994 UINT32 PowerOnGoodTime;
995 UINT32 Data32;
996 BOOLEAN Flag = FALSE;
997
998 if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
999 return EFI_INVALID_PARAMETER;
1000 }
1001 Status = EFI_SUCCESS;
1002
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;
1008 }
1009 MicroSecondDelay (50 * HC_1_MILLISECOND);
1010 //
1011 // Wait for host controller reset.
1012 //
1013 PowerOnGoodTime = 50;
1014 do {
1015 MicroSecondDelay (HC_1_MILLISECOND);
1016 Data32 = OhciGetOperationalReg (Ohc, HC_COMMAND_STATUS );
1017 if ((Data32 & HC_RESET) == 0) {
1018 Flag = TRUE;
1019 break;
1020 }
1021 }while(PowerOnGoodTime--);
1022 if (!Flag){
1023 return EFI_DEVICE_ERROR;
1024 }
1025 }
1026
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;
1032 }
1033 MicroSecondDelay (50 * HC_1_MILLISECOND);
1034 }
1035 //
1036 // Initialize host controller operational registers
1037 //
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);
1047
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);
1060 }
1061 }
1062
1063 Ohc->MemPool = UsbHcInitMemPool(TRUE, 0);
1064 if(Ohc->MemPool == NULL) {
1065 return EFI_OUT_OF_RESOURCES;
1066 }
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);
1072 //
1073 // Wait till first SOF occurs, and then clear it
1074 //
1075 while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
1076 OhciClearInterruptStatus (Ohc, START_OF_FRAME);
1077 MicroSecondDelay (HC_1_MILLISECOND);
1078
1079 return EFI_SUCCESS;
1080 }
1081
1082 /**
1083 Submits control transfer to a target USB device.
1084
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.
1087
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.
1100
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.
1106
1107 **/
1108 EFI_STATUS
1109 EFIAPI
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,
1118 IN OUT VOID *Data,
1119 IN OUT UINTN *DataLength,
1120 IN UINTN TimeOut,
1121 OUT UINT32 *TransferResult
1122 )
1123 {
1124 EFI_STATUS Status;
1125 EFI_USB_DEVICE_REQUEST *NewRequest;
1126 VOID *NewData;
1127 UINT8 *Alloc;
1128
1129 //
1130 // Allocate memory external to IMR protected region for transfer data.
1131 //
1132 Status = PeiServicesAllocatePool (
1133 sizeof(EFI_USB_DEVICE_REQUEST) + *DataLength,
1134 (VOID **) &Alloc
1135 );
1136 ASSERT_EFI_ERROR (Status);
1137
1138 //
1139 // Setup pointers to transfer buffers.
1140 //
1141 NewRequest = (EFI_USB_DEVICE_REQUEST *) Alloc;
1142 Alloc += sizeof(EFI_USB_DEVICE_REQUEST);
1143 NewData = (VOID *) Alloc;
1144
1145 //
1146 // Copy callers request packet into transfer request packet.
1147 //
1148 if (Request != NULL) {
1149 CopyMem (NewRequest,Request,sizeof(EFI_USB_DEVICE_REQUEST));
1150 } else {
1151 NewRequest = NULL;
1152 }
1153 //
1154 // Copy callers data into transfer data buffer.
1155 //
1156 if (Data != NULL) {
1157 if (DataLength > 0) {
1158 CopyMem (NewData,Data,*DataLength);
1159 }
1160 } else {
1161 NewData = NULL;
1162 }
1163
1164 //
1165 // Call underlying OhciControlTransfer to do work.
1166 //
1167 Status = OhciControlTransfer (
1168 PeiServices,
1169 This,
1170 DeviceAddress,
1171 DeviceSpeed,
1172 MaxPacketLength,
1173 NewRequest,
1174 TransferDirection,
1175 NewData,
1176 DataLength,
1177 TimeOut,
1178 TransferResult
1179 );
1180
1181 //
1182 // Copy transfer buffer back into callers buffer.
1183 //
1184 if (Data != NULL && *DataLength > 0) {
1185 CopyMem (Data, NewData, *DataLength);
1186 }
1187
1188 return Status;
1189 }
1190
1191 /**
1192 Submits bulk transfer to a bulk endpoint of a USB device.
1193
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.
1196
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
1212 bulk transfer.
1213
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.
1219
1220 **/
1221 EFI_STATUS
1222 EFIAPI
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,
1229 IN OUT VOID *Data,
1230 IN OUT UINTN *DataLength,
1231 IN OUT UINT8 *DataToggle,
1232 IN UINTN TimeOut,
1233 OUT UINT32 *TransferResult
1234 )
1235 {
1236 EFI_STATUS Status;
1237 UINT8 *NewData;
1238
1239 //
1240 // Allocate memory external to IMR protected region for transfer data.
1241 //
1242 Status = PeiServicesAllocatePool (
1243 *DataLength,
1244 (VOID **) &NewData
1245 );
1246 ASSERT_EFI_ERROR (Status);
1247
1248 //
1249 // Copy callers data into transfer buffer.
1250 //
1251 if (Data != NULL) {
1252 if (DataLength > 0) {
1253 CopyMem (NewData,Data,*DataLength);
1254 }
1255 } else {
1256 NewData = NULL;
1257 }
1258
1259 //
1260 // Call underlying OhciBulkTransfer to do work.
1261 //
1262 Status = OhciBulkTransfer (
1263 PeiServices,
1264 This,
1265 DeviceAddress,
1266 EndPointAddress,
1267 MaxPacketLength,
1268 NewData,
1269 DataLength,
1270 DataToggle,
1271 TimeOut,
1272 TransferResult
1273 );
1274
1275 //
1276 // Copy transfer buffer back into callers buffer.
1277 //
1278 if (Data != NULL && *DataLength > 0) {
1279 CopyMem (Data, NewData, *DataLength);
1280 }
1281
1282 return Status;
1283 }
1284
1285 /**
1286 @param FileHandle Handle of the file being invoked.
1287 @param PeiServices Describes the list of possible PEI Services.
1288
1289 @retval EFI_SUCCESS PPI successfully installed.
1290
1291 **/
1292 EFI_STATUS
1293 OhcPeimEntry (
1294 IN EFI_PEI_FILE_HANDLE FileHandle,
1295 IN CONST EFI_PEI_SERVICES **PeiServices
1296 )
1297 {
1298
1299 PEI_USB_CONTROLLER_PPI *ChipSetUsbControllerPpi;
1300 EFI_STATUS Status;
1301 UINT8 Index;
1302 UINTN ControllerType;
1303 UINTN BaseAddress;
1304 UINTN MemPages;
1305 USB_OHCI_HC_DEV *Ohc;
1306 EFI_PHYSICAL_ADDRESS TempPtr;
1307
1308
1309 //
1310 // Shadow this PEIM to run from memory
1311 //
1312 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1313 return EFI_SUCCESS;
1314 }
1315 Status = PeiServicesLocatePpi (
1316 &gPeiUsbControllerPpiGuid,
1317 0,
1318 NULL,
1319 (VOID **) &ChipSetUsbControllerPpi
1320 );
1321 if (EFI_ERROR (Status)) {
1322 return EFI_UNSUPPORTED;
1323 }
1324
1325 Index = 0;
1326 while (TRUE) {
1327 Status = ChipSetUsbControllerPpi->GetUsbController (
1328 (EFI_PEI_SERVICES **) PeiServices,
1329 ChipSetUsbControllerPpi,
1330 Index,
1331 &ControllerType,
1332 &BaseAddress
1333 );
1334 //
1335 // When status is error, meant no controller is found
1336 //
1337 if (EFI_ERROR (Status)) {
1338 break;
1339 }
1340 //
1341 // This PEIM is for OHC type controller.
1342 //
1343 if (ControllerType != PEI_OHCI_CONTROLLER) {
1344 Index++;
1345 continue;
1346 }
1347
1348 MemPages = sizeof (USB_OHCI_HC_DEV) / PAGESIZE + 1;
1349 Status = PeiServicesAllocatePages (
1350 EfiBootServicesCode,
1351 MemPages,
1352 &TempPtr
1353 );
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;
1357 }
1358 ZeroMem((VOID *)(UINTN)TempPtr, MemPages*PAGESIZE);
1359 Ohc = (USB_OHCI_HC_DEV *) ((UINTN) TempPtr);
1360
1361 Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;
1362
1363 Ohc->UsbHostControllerBaseAddress = (UINT32) BaseAddress;
1364
1365 //
1366 // Initialize Uhc's hardware
1367 //
1368 Status = InitializeUsbHC (
1369 (EFI_PEI_SERVICES **)PeiServices,
1370 Ohc,
1371 EFI_USB_HC_RESET_GLOBAL
1372 );
1373 if (EFI_ERROR (Status)) {
1374 DEBUG ((EFI_D_INFO, "OhcPeimEntry: Fail to init %dth OHCI ControllerPpi\n", Index));
1375 return Status;
1376 }
1377 //
1378 // Control & Bulk transfer services are accessed via their Redirect
1379 // routine versions on Quark so that USB DMA transfers do not cause an
1380 // IMR violation.
1381 //
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;
1388
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;
1392
1393 Status = PeiServicesInstallPpi (&Ohc->PpiDescriptor);
1394 if (EFI_ERROR (Status)) {
1395 Index++;
1396 continue;
1397 }
1398 Index++;
1399 }
1400 return EFI_SUCCESS;
1401 }
1402