]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkSouthCluster/Usb/Ohci/Dxe/Ohci.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Usb / Ohci / Dxe / Ohci.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 "Ohci.h"
18
19 /**
20 Provides software reset for the USB host controller.
21
22 @param This This EFI_USB_HC_PROTOCOL instance.
23 @param Attributes A bit mask of the reset operation to perform.
24
25 @retval EFI_SUCCESS The reset operation succeeded.
26 @retval EFI_INVALID_PARAMETER Attributes is not valid.
27 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is
28 not currently supported by the host controller.
29 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.
30
31 **/
32 EFI_STATUS
33 EFIAPI
34 OhciReset (
35 IN EFI_USB_HC_PROTOCOL *This,
36 IN UINT16 Attributes
37 )
38 {
39 EFI_STATUS Status;
40 USB_OHCI_HC_DEV *Ohc;
41 UINT8 Index;
42 UINT8 NumOfPorts;
43 UINT32 PowerOnGoodTime;
44 UINT32 Data32;
45 BOOLEAN Flag = FALSE;
46
47 if ((Attributes & ~(EFI_USB_HC_RESET_GLOBAL | EFI_USB_HC_RESET_HOST_CONTROLLER)) != 0) {
48 return EFI_INVALID_PARAMETER;
49 }
50
51 Status = EFI_SUCCESS;
52 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
53
54 if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
55 gBS->Stall (50 * 1000);
56 Status = OhciSetHcCommandStatus (Ohc, HC_RESET, HC_RESET);
57 if (EFI_ERROR (Status)) {
58 return EFI_DEVICE_ERROR;
59 }
60 gBS->Stall (50 * 1000);
61 //
62 // Wait for host controller reset.
63 //
64 PowerOnGoodTime = 50;
65 do {
66 gBS->Stall (1 * 1000);
67 Data32 = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS );
68 if (EFI_ERROR (Status)) {
69 return EFI_DEVICE_ERROR;
70 }
71 if ((Data32 & HC_RESET) == 0) {
72 Flag = TRUE;
73 break;
74 }
75 }while(PowerOnGoodTime--);
76 if (!Flag){
77 return EFI_DEVICE_ERROR;
78 }
79 }
80 OhciFreeIntTransferMemory (Ohc);
81 Status = OhciInitializeInterruptList (Ohc);
82 OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
83 if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {
84 Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
85 if (EFI_ERROR (Status)) {
86 return EFI_DEVICE_ERROR;
87 }
88 gBS->Stall (50 * 1000);
89 }
90 //
91 // Initialize host controller operational registers
92 //
93 OhciSetFrameInterval (Ohc, FS_LARGEST_DATA_PACKET, 0x2778);
94 OhciSetFrameInterval (Ohc, FRAME_INTERVAL, 0x2edf);
95 OhciSetPeriodicStart (Ohc, 0x2a2f);
96 OhciSetHcControl (Ohc, CONTROL_BULK_RATIO, 0x3);
97 OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED | BULK_LIST_FILLED, 0);
98 OhciSetRootHubDescriptor (Ohc, RH_PSWITCH_MODE, 0);
99 OhciSetRootHubDescriptor (Ohc, RH_NO_PSWITCH | RH_NOC_PROT, 1);
100 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NO_PSWITCH, 0);
101 //OhciSetRootHubDescriptor (Hc, RH_PSWITCH_MODE | RH_NOC_PROT, 1);
102
103 OhciSetRootHubDescriptor (Ohc, RH_DEV_REMOVABLE, 0);
104 OhciSetRootHubDescriptor (Ohc, RH_PORT_PWR_CTRL_MASK, 0xffff);
105 OhciSetRootHubStatus (Ohc, RH_LOCAL_PSTAT_CHANGE);
106 OhciSetRootHubPortStatus (Ohc, 0, RH_SET_PORT_POWER);
107 OhciGetRootHubNumOfPorts (This, &NumOfPorts);
108 for (Index = 0; Index < NumOfPorts; Index++) {
109 if (!EFI_ERROR (OhciSetRootHubPortFeature (This, Index, EfiUsbPortReset))) {
110 gBS->Stall (200 * 1000);
111 OhciClearRootHubPortFeature (This, Index, EfiUsbPortReset);
112 gBS->Stall (1000);
113 OhciSetRootHubPortFeature (This, Index, EfiUsbPortEnable);
114 gBS->Stall (1000);
115 }
116 }
117 OhciSetMemoryPointer (Ohc, HC_HCCA, Ohc->HccaMemoryBlock);
118 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
119 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
120 OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | BULK_ENABLE, 1); /*ISOCHRONOUS_ENABLE*/
121 OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
122 gBS->Stall (50*1000);
123 //
124 // Wait till first SOF occurs, and then clear it
125 //
126 while (OhciGetHcInterruptStatus (Ohc, START_OF_FRAME) == 0);
127 OhciClearInterruptStatus (Ohc, START_OF_FRAME);
128 gBS->Stall (1000);
129
130 return Status;
131 }
132
133 /**
134 Retrieve the current state of the USB host controller.
135
136 @param This This EFI_USB_HC_PROTOCOL instance.
137 @param State Variable to return the current host controller
138 state.
139
140 @retval EFI_SUCCESS Host controller state was returned in State.
141 @retval EFI_INVALID_PARAMETER State is NULL.
142 @retval EFI_DEVICE_ERROR An error was encountered while attempting to
143 retrieve the host controller's current state.
144
145 **/
146
147 EFI_STATUS
148 EFIAPI
149 OhciGetState (
150 IN EFI_USB_HC_PROTOCOL *This,
151 OUT EFI_USB_HC_STATE *State
152 )
153 {
154 USB_OHCI_HC_DEV *Ohc;
155 UINT32 FuncState;
156
157 if (State == NULL) {
158 return EFI_INVALID_PARAMETER;
159 }
160
161 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
162
163 FuncState = OhciGetHcControl (Ohc, HC_FUNCTIONAL_STATE);
164
165 switch (FuncState) {
166 case HC_STATE_RESET:
167 case HC_STATE_RESUME:
168 *State = EfiUsbHcStateHalt;
169 break;
170
171 case HC_STATE_OPERATIONAL:
172 *State = EfiUsbHcStateOperational;
173 break;
174
175 case HC_STATE_SUSPEND:
176 *State = EfiUsbHcStateSuspend;
177 break;
178
179 default:
180 ASSERT (FALSE);
181 }
182 return EFI_SUCCESS;
183 }
184
185 /**
186 Sets the USB host controller to a specific state.
187
188 @param This This EFI_USB_HC_PROTOCOL instance.
189 @param State The state of the host controller that will be set.
190
191 @retval EFI_SUCCESS The USB host controller was successfully placed
192 in the state specified by State.
193 @retval EFI_INVALID_PARAMETER State is invalid.
194 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.
195
196 **/
197
198 EFI_STATUS
199 EFIAPI
200 OhciSetState(
201 IN EFI_USB_HC_PROTOCOL *This,
202 IN EFI_USB_HC_STATE State
203 )
204 {
205 EFI_STATUS Status;
206 USB_OHCI_HC_DEV *Ohc;
207
208 Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
209
210 switch (State) {
211 case EfiUsbHcStateHalt:
212 Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_RESET);
213 break;
214
215 case EfiUsbHcStateOperational:
216 Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_OPERATIONAL);
217 break;
218
219 case EfiUsbHcStateSuspend:
220 Status = OhciSetHcControl (Ohc, HC_FUNCTIONAL_STATE, HC_STATE_SUSPEND);
221 break;
222
223 default:
224 Status = EFI_INVALID_PARAMETER;
225 }
226
227 gBS->Stall (1000);
228
229 return Status;
230 }
231
232 /**
233
234 Submits control transfer to a target USB device.
235
236 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
237 @param DeviceAddress Represents the address of the target device on the USB,
238 which is assigned during USB enumeration.
239 @param IsSlowDevice Indicates whether the target device is slow device
240 or full-speed device.
241 @param MaxPaketLength Indicates the maximum packet size that the
242 default control transfer endpoint is capable of
243 sending or receiving.
244 @param Request A pointer to the USB device request that will be sent
245 to the USB device.
246 @param TransferDirection Specifies the data direction for the transfer.
247 There are three values available, DataIn, DataOut
248 and NoData.
249 @param Data A pointer to the buffer of data that will be transmitted
250 to USB device or received from USB device.
251 @param DataLength Indicates the size, in bytes, of the data buffer
252 specified by Data.
253 @param TimeOut Indicates the maximum time, in microseconds,
254 which the transfer is allowed to complete.
255 @param TransferResult A pointer to the detailed result information generated
256 by this control transfer.
257
258 @retval EFI_SUCCESS The control transfer was completed successfully.
259 @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources.
260 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
261 @retval EFI_TIMEOUT The control transfer failed due to timeout.
262 @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error.
263 Caller should check TranferResult for detailed error information.
264
265 --*/
266
267
268 EFI_STATUS
269 EFIAPI
270 OhciControlTransfer (
271 IN EFI_USB_HC_PROTOCOL *This,
272 IN UINT8 DeviceAddress,
273 IN BOOLEAN IsSlowDevice,
274 IN UINT8 MaxPacketLength,
275 IN EFI_USB_DEVICE_REQUEST *Request,
276 IN EFI_USB_DATA_DIRECTION TransferDirection,
277 IN OUT VOID *Data OPTIONAL,
278 IN OUT UINTN *DataLength OPTIONAL,
279 IN UINTN TimeOut,
280 OUT UINT32 *TransferResult
281 )
282 {
283 USB_OHCI_HC_DEV *Ohc;
284 ED_DESCRIPTOR *HeadEd;
285 ED_DESCRIPTOR *Ed;
286 TD_DESCRIPTOR *HeadTd;
287 TD_DESCRIPTOR *SetupTd;
288 TD_DESCRIPTOR *DataTd;
289 TD_DESCRIPTOR *StatusTd;
290 TD_DESCRIPTOR *EmptyTd;
291 EFI_STATUS Status;
292 UINT32 DataPidDir;
293 UINT32 StatusPidDir;
294 UINTN TimeCount;
295 OHCI_ED_RESULT EdResult;
296
297 EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
298
299 UINTN ActualSendLength;
300 UINTN LeftLength;
301 UINT8 DataToggle;
302
303 VOID *ReqMapping = NULL;
304 UINTN ReqMapLength = 0;
305 EFI_PHYSICAL_ADDRESS ReqMapPhyAddr = 0;
306
307 VOID *DataMapping = NULL;
308 UINTN DataMapLength = 0;
309 EFI_PHYSICAL_ADDRESS DataMapPhyAddr = 0;
310
311 HeadTd = NULL;
312 DataTd = NULL;
313
314 if ((TransferDirection != EfiUsbDataOut && TransferDirection != EfiUsbDataIn &&
315 TransferDirection != EfiUsbNoData) ||
316 Request == NULL || DataLength == NULL || TransferResult == NULL ||
317 (TransferDirection == EfiUsbNoData && (*DataLength != 0 || Data != NULL)) ||
318 (TransferDirection != EfiUsbNoData && (*DataLength == 0 || Data == NULL)) ||
319 (IsSlowDevice && MaxPacketLength != 8) ||
320 (MaxPacketLength != 8 && MaxPacketLength != 16 &&
321 MaxPacketLength != 32 && MaxPacketLength != 64)) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 if (*DataLength > MAX_BYTES_PER_TD) {
326 DEBUG ((EFI_D_ERROR, "OhciControlTransfer: Request data size is too large\r\n"));
327 return EFI_INVALID_PARAMETER;
328 }
329
330 Ohc = USB_OHCI_HC_DEV_FROM_THIS(This);
331
332 if (TransferDirection == EfiUsbDataIn) {
333 DataPidDir = TD_IN_PID;
334 StatusPidDir = TD_OUT_PID;
335 } else {
336 DataPidDir = TD_OUT_PID;
337 StatusPidDir = TD_IN_PID;
338 }
339
340 Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 0);
341 if (EFI_ERROR(Status)) {
342 DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_ENABLE\r\n"));
343 *TransferResult = EFI_USB_ERR_SYSTEM;
344 return EFI_DEVICE_ERROR;
345 }
346 Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 0);
347 if (EFI_ERROR(Status)) {
348 DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable CONTROL_LIST_FILLED\r\n"));
349 *TransferResult = EFI_USB_ERR_SYSTEM;
350 return EFI_DEVICE_ERROR;
351 }
352 gBS->Stall(20 * 1000);
353
354 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
355 Ed = OhciCreateED (Ohc);
356 if (Ed == NULL) {
357 Status = EFI_OUT_OF_RESOURCES;
358 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate ED buffer\r\n"));
359 goto CTRL_EXIT;
360 }
361 OhciSetEDField (Ed, ED_SKIP, 1);
362 OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
363 OhciSetEDField (Ed, ED_ENDPT_NUM, 0);
364 OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
365 OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
366 OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
367 OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
368 OhciSetEDField (Ed, ED_PDATA, 0);
369 OhciSetEDField (Ed, ED_ZERO, 0);
370 OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
371 OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
372 OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
373 HeadEd = OhciAttachEDToList (Ohc, CONTROL_LIST, Ed, NULL);
374 //
375 // Setup Stage
376 //
377 if(Request != NULL) {
378 ReqMapLength = sizeof(EFI_USB_DEVICE_REQUEST);
379 MapOp = EfiPciIoOperationBusMasterRead;
380 Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Request, &ReqMapLength, &ReqMapPhyAddr, &ReqMapping);
381 if (EFI_ERROR(Status)) {
382 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to Map Request Buffer\r\n"));
383 goto FREE_ED_BUFF;
384 }
385 }
386 SetupTd = OhciCreateTD (Ohc);
387 if (SetupTd == NULL) {
388 Status = EFI_OUT_OF_RESOURCES;
389 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate Setup TD buffer\r\n"));
390 goto UNMAP_SETUP_BUFF;
391 }
392 HeadTd = SetupTd;
393 OhciSetTDField (SetupTd, TD_PDATA, 0);
394 OhciSetTDField (SetupTd, TD_BUFFER_ROUND, 1);
395 OhciSetTDField (SetupTd, TD_DIR_PID, TD_SETUP_PID);
396 OhciSetTDField (SetupTd, TD_DELAY_INT, TD_NO_DELAY);
397 OhciSetTDField (SetupTd, TD_DT_TOGGLE, 2);
398 OhciSetTDField (SetupTd, TD_ERROR_CNT, 0);
399 OhciSetTDField (SetupTd, TD_COND_CODE, TD_TOBE_PROCESSED);
400 OhciSetTDField (SetupTd, TD_CURR_BUFFER_PTR, (UINT32)ReqMapPhyAddr);
401 OhciSetTDField (SetupTd, TD_NEXT_PTR, 0);
402 OhciSetTDField (SetupTd, TD_BUFFER_END_PTR, (UINT32)(ReqMapPhyAddr + sizeof (EFI_USB_DEVICE_REQUEST) - 1));
403 SetupTd->ActualSendLength = sizeof (EFI_USB_DEVICE_REQUEST);
404 SetupTd->DataBuffer = (UINT32)ReqMapPhyAddr;
405 SetupTd->NextTDPointer = 0;
406
407 if (TransferDirection == EfiUsbDataIn) {
408 MapOp = EfiPciIoOperationBusMasterWrite;
409 } else {
410 MapOp = EfiPciIoOperationBusMasterRead;
411 }
412 DataMapLength = *DataLength;
413 if ((Data != NULL) && (DataMapLength != 0)) {
414 Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, Data, &DataMapLength, &DataMapPhyAddr, &DataMapping);
415 if (EFI_ERROR(Status)) {
416 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail To Map Data Buffer\r\n"));
417 goto FREE_TD_BUFF;
418 }
419 }
420 //
421 //Data Stage
422 //
423 LeftLength = DataMapLength;
424 ActualSendLength = DataMapLength;
425 DataToggle = 1;
426 while (LeftLength > 0) {
427 ActualSendLength = LeftLength;
428 if (LeftLength > MaxPacketLength) {
429 ActualSendLength = MaxPacketLength;
430 }
431 DataTd = OhciCreateTD (Ohc);
432 if (DataTd == NULL) {
433 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
434 Status = EFI_OUT_OF_RESOURCES;
435 goto UNMAP_DATA_BUFF;
436 }
437 OhciSetTDField (DataTd, TD_PDATA, 0);
438 OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
439 OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
440 OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
441 OhciSetTDField (DataTd, TD_DT_TOGGLE, DataToggle);
442 OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
443 OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
444 OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) DataMapPhyAddr);
445 OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(DataMapPhyAddr + ActualSendLength - 1));
446 OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
447 DataTd->ActualSendLength = (UINT32)ActualSendLength;
448 DataTd->DataBuffer = (UINT32)DataMapPhyAddr;
449 DataTd->NextTDPointer = 0;
450 OhciLinkTD (HeadTd, DataTd);
451 DataToggle ^= 1;
452 DataMapPhyAddr += ActualSendLength;
453 LeftLength -= ActualSendLength;
454 }
455 //
456 // Status Stage
457 //
458 StatusTd = OhciCreateTD (Ohc);
459 if (StatusTd == NULL) {
460 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to allocate buffer for Status Stage TD\r\n"));
461 Status = EFI_OUT_OF_RESOURCES;
462 goto UNMAP_DATA_BUFF;
463 }
464 OhciSetTDField (StatusTd, TD_PDATA, 0);
465 OhciSetTDField (StatusTd, TD_BUFFER_ROUND, 1);
466 OhciSetTDField (StatusTd, TD_DIR_PID, StatusPidDir);
467 OhciSetTDField (StatusTd, TD_DELAY_INT, 7);
468 OhciSetTDField (StatusTd, TD_DT_TOGGLE, 3);
469 OhciSetTDField (StatusTd, TD_ERROR_CNT, 0);
470 OhciSetTDField (StatusTd, TD_COND_CODE, TD_TOBE_PROCESSED);
471 OhciSetTDField (StatusTd, TD_CURR_BUFFER_PTR, 0);
472 OhciSetTDField (StatusTd, TD_NEXT_PTR, 0);
473 OhciSetTDField (StatusTd, TD_BUFFER_END_PTR, 0);
474 StatusTd->ActualSendLength = 0;
475 StatusTd->DataBuffer = 0;
476 StatusTd->NextTDPointer = 0;
477 OhciLinkTD (HeadTd, StatusTd);
478 //
479 // Empty Stage
480 //
481 EmptyTd = OhciCreateTD (Ohc);
482 if (EmptyTd == NULL) {
483 Status = EFI_OUT_OF_RESOURCES;
484 goto UNMAP_DATA_BUFF;
485 }
486 OhciSetTDField (EmptyTd, TD_PDATA, 0);
487 OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
488 OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
489 OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
490 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
491 EmptyTd->Word0.DataToggle = 0;
492 OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
493 OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
494 OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
495 OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
496 OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
497 EmptyTd->ActualSendLength = 0;
498 EmptyTd->DataBuffer = 0;
499 EmptyTd->NextTDPointer = 0;
500 OhciLinkTD (HeadTd, EmptyTd);
501 Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
502 OhciAttachTDListToED (Ed, HeadTd);
503 //
504 // For debugging, dump ED & TD buffer befor transferring
505 //
506 //
507 //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, TRUE);
508 //
509 OhciSetEDField (Ed, ED_SKIP, 0);
510 Status = OhciSetHcControl (Ohc, CONTROL_ENABLE, 1);
511 if (EFI_ERROR(Status)) {
512 DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_ENABLE\r\n"));
513 *TransferResult = EFI_USB_ERR_SYSTEM;
514 Status = EFI_DEVICE_ERROR;
515 goto UNMAP_DATA_BUFF;
516 }
517 Status = OhciSetHcCommandStatus (Ohc, CONTROL_LIST_FILLED, 1);
518 if (EFI_ERROR(Status)) {
519 DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to enable CONTROL_LIST_FILLED\r\n"));
520 *TransferResult = EFI_USB_ERR_SYSTEM;
521 Status = EFI_DEVICE_ERROR;
522 goto UNMAP_DATA_BUFF;
523 }
524 gBS->Stall(20 * 1000);
525
526
527 TimeCount = 0;
528 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
529
530 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
531 gBS->Stall (1000);
532 TimeCount++;
533 Status = CheckIfDone (Ohc, CONTROL_LIST, Ed, HeadTd, &EdResult);
534 }
535 //
536 // For debugging, dump ED & TD buffer after transferring
537 //
538 //OhciDumpEdTdInfo (Ohc, Ed, HeadTd, FALSE);
539 //
540 *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
541
542 if (EdResult.ErrorCode != TD_NO_ERROR) {
543 if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
544 DEBUG ((EFI_D_INFO, "Control pipe timeout, > %d mS\r\n", TimeOut));
545 } else {
546 DEBUG ((EFI_D_INFO, "Control pipe broken\r\n"));
547 }
548 *DataLength = 0;
549 } else {
550 DEBUG ((EFI_D_INFO, "Control transfer successed\r\n"));
551 }
552
553 UNMAP_DATA_BUFF:
554 OhciSetEDField (Ed, ED_SKIP, 1);
555 if (HeadEd == Ed) {
556 OhciSetMemoryPointer (Ohc, HC_CONTROL_HEAD, NULL);
557 } else {
558 HeadEd->NextED = Ed->NextED;
559 }
560 if(DataMapping != NULL) {
561 Ohc->PciIo->Unmap(Ohc->PciIo, DataMapping);
562 }
563
564 FREE_TD_BUFF:
565 while (HeadTd) {
566 DataTd = HeadTd;
567 HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
568 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
569 }
570
571 UNMAP_SETUP_BUFF:
572 if(ReqMapping != NULL) {
573 Ohc->PciIo->Unmap(Ohc->PciIo, ReqMapping);
574 }
575
576 FREE_ED_BUFF:
577 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
578
579 CTRL_EXIT:
580 return Status;
581 }
582
583 /**
584
585 Submits bulk transfer to a bulk endpoint of a USB device.
586
587 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
588 @param DeviceAddress Represents the address of the target device on the USB,
589 which is assigned during USB enumeration.
590 @param EndPointAddress The combination of an endpoint number and an
591 endpoint direction of the target USB device.
592 Each endpoint address supports data transfer in
593 one direction except the control endpoint
594 (whose default endpoint address is 0).
595 It is the caller's responsibility to make sure that
596 the EndPointAddress represents a bulk endpoint.
597 @param MaximumPacketLength Indicates the maximum packet size the target endpoint
598 is capable of sending or receiving.
599 @param Data A pointer to the buffer of data that will be transmitted
600 to USB device or received from USB device.
601 @param DataLength When input, indicates the size, in bytes, of the data buffer
602 specified by Data. When output, indicates the actually
603 transferred data size.
604 @param DataToggle A pointer to the data toggle value. On input, it indicates
605 the initial data toggle value the bulk transfer should adopt;
606 on output, it is updated to indicate the data toggle value
607 of the subsequent bulk transfer.
608 @param TimeOut Indicates the maximum time, in microseconds, which the
609 transfer is allowed to complete.
610 TransferResult A pointer to the detailed result information of the
611 bulk transfer.
612
613 @retval EFI_SUCCESS The bulk transfer was completed successfully.
614 @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to lack of resource.
615 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
616 @retval EFI_TIMEOUT The bulk transfer failed due to timeout.
617 @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error.
618 Caller should check TranferResult for detailed error information.
619
620 **/
621
622
623 EFI_STATUS
624 EFIAPI
625 OhciBulkTransfer(
626 IN EFI_USB_HC_PROTOCOL *This,
627 IN UINT8 DeviceAddress,
628 IN UINT8 EndPointAddress,
629 IN UINT8 MaxPacketLength,
630 IN OUT VOID *Data,
631 IN OUT UINTN *DataLength,
632 IN OUT UINT8 *DataToggle,
633 IN UINTN TimeOut,
634 OUT UINT32 *TransferResult
635 )
636 {
637 USB_OHCI_HC_DEV *Ohc;
638 ED_DESCRIPTOR *HeadEd;
639 ED_DESCRIPTOR *Ed;
640 UINT8 EdDir;
641 UINT32 DataPidDir;
642 TD_DESCRIPTOR *HeadTd;
643 TD_DESCRIPTOR *DataTd;
644 TD_DESCRIPTOR *EmptyTd;
645 EFI_STATUS Status;
646 EFI_USB_DATA_DIRECTION TransferDirection;
647 UINT8 EndPointNum;
648 UINTN TimeCount;
649 OHCI_ED_RESULT EdResult;
650
651 EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
652 VOID *Mapping;
653 UINTN MapLength;
654 EFI_PHYSICAL_ADDRESS MapPyhAddr;
655 UINTN LeftLength;
656 UINTN ActualSendLength;
657 BOOLEAN FirstTD;
658
659 Mapping = NULL;
660 MapLength = 0;
661 MapPyhAddr = 0;
662 LeftLength = 0;
663 Status = EFI_SUCCESS;
664
665 if (Data == NULL || DataLength == NULL || DataToggle == NULL || TransferResult == NULL ||
666 *DataLength == 0 || (*DataToggle != 0 && *DataToggle != 1) ||
667 (MaxPacketLength != 8 && MaxPacketLength != 16 &&
668 MaxPacketLength != 32 && MaxPacketLength != 64)) {
669 return EFI_INVALID_PARAMETER;
670 }
671
672 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
673
674 if ((EndPointAddress & 0x80) != 0) {
675 TransferDirection = EfiUsbDataIn;
676 EdDir = ED_IN_DIR;
677 DataPidDir = TD_IN_PID;
678 MapOp = EfiPciIoOperationBusMasterWrite;
679 } else {
680 TransferDirection = EfiUsbDataOut;
681 EdDir = ED_OUT_DIR;
682 DataPidDir = TD_OUT_PID;
683 MapOp = EfiPciIoOperationBusMasterRead;
684 }
685
686 EndPointNum = (EndPointAddress & 0xF);
687 EdResult.NextToggle = *DataToggle;
688
689 Status = OhciSetHcControl (Ohc, BULK_ENABLE, 0);
690 if (EFI_ERROR(Status)) {
691 DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_ENABLE\r\n"));
692 *TransferResult = EFI_USB_ERR_SYSTEM;
693 return EFI_DEVICE_ERROR;
694 }
695 Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 0);
696 if (EFI_ERROR(Status)) {
697 DEBUG ((EFI_D_INFO, "OhciControlTransfer: fail to disable BULK_LIST_FILLED\r\n"));
698 *TransferResult = EFI_USB_ERR_SYSTEM;
699 return EFI_DEVICE_ERROR;
700 }
701 gBS->Stall(20 * 1000);
702
703 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
704
705 Ed = OhciCreateED (Ohc);
706 if (Ed == NULL) {
707 return EFI_OUT_OF_RESOURCES;
708 }
709 OhciSetEDField (Ed, ED_SKIP, 1);
710 OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
711 OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
712 OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
713 OhciSetEDField (Ed, ED_SPEED, HI_SPEED);
714 OhciSetEDField (Ed, ED_FORMAT | ED_HALTED | ED_DTTOGGLE, 0);
715 OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
716 OhciSetEDField (Ed, ED_PDATA, 0);
717 OhciSetEDField (Ed, ED_ZERO, 0);
718 OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
719 OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
720 OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
721 HeadEd = OhciAttachEDToList (Ohc, BULK_LIST, Ed, NULL);
722
723 if(Data != NULL) {
724 MapLength = *DataLength;
725 Status = Ohc->PciIo->Map (Ohc->PciIo, MapOp, (UINT8 *)Data, &MapLength, &MapPyhAddr, &Mapping);
726 if (EFI_ERROR(Status)) {
727 DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to Map Data Buffer for Bulk\r\n"));
728 goto FREE_ED_BUFF;
729 }
730 }
731 //
732 //Data Stage
733 //
734 LeftLength = MapLength;
735 ActualSendLength = MapLength;
736 HeadTd = NULL;
737 FirstTD = TRUE;
738 while (LeftLength > 0) {
739 ActualSendLength = LeftLength;
740 if (LeftLength > MaxPacketLength) {
741 ActualSendLength = MaxPacketLength;
742 }
743 DataTd = OhciCreateTD (Ohc);
744 if (DataTd == NULL) {
745 DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
746 Status = EFI_OUT_OF_RESOURCES;
747 goto FREE_OHCI_TDBUFF;
748 }
749 OhciSetTDField (DataTd, TD_PDATA, 0);
750 OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
751 OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
752 OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
753 OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
754 OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
755 OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
756 OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
757 OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
758 OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
759 DataTd->ActualSendLength = (UINT32)ActualSendLength;
760 DataTd->DataBuffer = (UINT32)MapPyhAddr;
761 DataTd->NextTDPointer = 0;
762 if (FirstTD) {
763 HeadTd = DataTd;
764 FirstTD = FALSE;
765 } else {
766 OhciLinkTD (HeadTd, DataTd);
767 }
768 *DataToggle ^= 1;
769 MapPyhAddr += ActualSendLength;
770 LeftLength -= ActualSendLength;
771 }
772 //
773 // Empty Stage
774 //
775 EmptyTd = OhciCreateTD (Ohc);
776 if (EmptyTd == NULL) {
777 Status = EFI_OUT_OF_RESOURCES;
778 DEBUG ((EFI_D_INFO, "OhciBulkTransfer: Fail to allocate buffer for Empty TD\r\n"));
779 goto FREE_OHCI_TDBUFF;
780 }
781 OhciSetTDField (EmptyTd, TD_PDATA, 0);
782 OhciSetTDField (EmptyTd, TD_BUFFER_ROUND, 0);
783 OhciSetTDField (EmptyTd, TD_DIR_PID, 0);
784 OhciSetTDField (EmptyTd, TD_DELAY_INT, 0);
785 //OhciSetTDField (EmptyTd, TD_DT_TOGGLE, CurrentToggle);
786 EmptyTd->Word0.DataToggle = 0;
787 OhciSetTDField (EmptyTd, TD_ERROR_CNT, 0);
788 OhciSetTDField (EmptyTd, TD_COND_CODE, 0);
789 OhciSetTDField (EmptyTd, TD_CURR_BUFFER_PTR, 0);
790 OhciSetTDField (EmptyTd, TD_BUFFER_END_PTR, 0);
791 OhciSetTDField (EmptyTd, TD_NEXT_PTR, 0);
792 EmptyTd->ActualSendLength = 0;
793 EmptyTd->DataBuffer = 0;
794 EmptyTd->NextTDPointer = 0;
795 OhciLinkTD (HeadTd, EmptyTd);
796 Ed->TdTailPointer = (UINT32)(UINTN)EmptyTd;
797 OhciAttachTDListToED (Ed, HeadTd);
798
799 OhciSetEDField (Ed, ED_SKIP, 0);
800 Status = OhciSetHcCommandStatus (Ohc, BULK_LIST_FILLED, 1);
801 if (EFI_ERROR(Status)) {
802 *TransferResult = EFI_USB_ERR_SYSTEM;
803 Status = EFI_DEVICE_ERROR;
804 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_LIST_FILLED\r\n"));
805 goto FREE_OHCI_TDBUFF;
806 }
807 Status = OhciSetHcControl (Ohc, BULK_ENABLE, 1);
808 if (EFI_ERROR(Status)) {
809 *TransferResult = EFI_USB_ERR_SYSTEM;
810 Status = EFI_DEVICE_ERROR;
811 DEBUG ((EFI_D_INFO, "OhciControlTransfer: Fail to enable BULK_ENABLE\r\n"));
812 goto FREE_OHCI_TDBUFF;
813 }
814 gBS->Stall(20 * 1000);
815
816 TimeCount = 0;
817 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
818 while (Status == EFI_NOT_READY && TimeCount <= TimeOut) {
819 gBS->Stall (1000);
820 TimeCount++;
821 Status = CheckIfDone (Ohc, BULK_LIST, Ed, HeadTd, &EdResult);
822 }
823
824 *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
825
826 if (EdResult.ErrorCode != TD_NO_ERROR) {
827 if (EdResult.ErrorCode == TD_TOBE_PROCESSED) {
828 DEBUG ((EFI_D_INFO, "Bulk pipe timeout, > %d mS\r\n", TimeOut));
829 } else {
830 DEBUG ((EFI_D_INFO, "Bulk pipe broken\r\n"));
831 *DataToggle = EdResult.NextToggle;
832 }
833 *DataLength = 0;
834 } else {
835 DEBUG ((EFI_D_INFO, "Bulk transfer successed\r\n"));
836 }
837 //*DataToggle = (UINT8) OhciGetEDField (Ed, ED_DTTOGGLE);
838
839 FREE_OHCI_TDBUFF:
840 OhciSetEDField (Ed, ED_SKIP, 1);
841 if (HeadEd == Ed) {
842 OhciSetMemoryPointer (Ohc, HC_BULK_HEAD, NULL);
843 }else {
844 HeadEd->NextED = Ed->NextED;
845 }
846 while (HeadTd) {
847 DataTd = HeadTd;
848 HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
849 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
850 }
851
852 if(Mapping != NULL) {
853 Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
854 }
855
856 FREE_ED_BUFF:
857 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
858
859 return Status;
860 }
861 /**
862
863 Submits an interrupt transfer to an interrupt endpoint of a USB device.
864
865 @param Ohc Device private data
866 @param DeviceAddress Represents the address of the target device on the USB,
867 which is assigned during USB enumeration.
868 @param EndPointAddress The combination of an endpoint number and an endpoint
869 direction of the target USB device. Each endpoint address
870 supports data transfer in one direction except the
871 control endpoint (whose default endpoint address is 0).
872 It is the caller's responsibility to make sure that
873 the EndPointAddress represents an interrupt endpoint.
874 @param IsSlowDevice Indicates whether the target device is slow device
875 or full-speed device.
876 @param MaxPacketLength Indicates the maximum packet size the target endpoint
877 is capable of sending or receiving.
878 @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
879 the host and the target interrupt endpoint.
880 If FALSE, the specified asynchronous interrupt pipe
881 is canceled.
882 @param DataToggle A pointer to the data toggle value. On input, it is valid
883 when IsNewTransfer is TRUE, and it indicates the initial
884 data toggle value the asynchronous interrupt transfer
885 should adopt.
886 On output, it is valid when IsNewTransfer is FALSE,
887 and it is updated to indicate the data toggle value of
888 the subsequent asynchronous interrupt transfer.
889 @param PollingInterval Indicates the interval, in milliseconds, that the
890 asynchronous interrupt transfer is polled.
891 This parameter is required when IsNewTransfer is TRUE.
892 @param UCBuffer Uncacheable buffer
893 @param DataLength Indicates the length of data to be received at the
894 rate specified by PollingInterval from the target
895 asynchronous interrupt endpoint. This parameter
896 is only required when IsNewTransfer is TRUE.
897 @param CallBackFunction The Callback function.This function is called at the
898 rate specified by PollingInterval.This parameter is
899 only required when IsNewTransfer is TRUE.
900 @param Context The context that is passed to the CallBackFunction.
901 This is an optional parameter and may be NULL.
902 @param IsPeriodic Periodic interrupt or not
903 @param OutputED The correspoding ED carried out
904 @param OutputTD The correspoding TD carried out
905
906
907 @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
908 submitted or canceled.
909 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
910 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
911
912 **/
913
914 EFI_STATUS
915 OhciInterruptTransfer (
916 IN USB_OHCI_HC_DEV *Ohc,
917 IN UINT8 DeviceAddress,
918 IN UINT8 EndPointAddress,
919 IN BOOLEAN IsSlowDevice,
920 IN UINT8 MaxPacketLength,
921 IN BOOLEAN IsNewTransfer,
922 IN OUT UINT8 *DataToggle OPTIONAL,
923 IN UINTN PollingInterval OPTIONAL,
924 IN VOID *UCBuffer OPTIONAL,
925 IN UINTN DataLength OPTIONAL,
926 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
927 IN VOID *Context OPTIONAL,
928 IN BOOLEAN IsPeriodic OPTIONAL,
929 OUT ED_DESCRIPTOR **OutputED OPTIONAL,
930 OUT TD_DESCRIPTOR **OutputTD OPTIONAL
931 )
932 {
933 ED_DESCRIPTOR *Ed;
934 UINT8 EdDir;
935 ED_DESCRIPTOR *HeadEd;
936 TD_DESCRIPTOR *HeadTd;
937 TD_DESCRIPTOR *DataTd;
938 TD_DESCRIPTOR *EmptTd;
939 UINTN Depth;
940 UINTN Index;
941 EFI_STATUS Status;
942 UINT8 EndPointNum;
943 UINT32 DataPidDir;
944 EFI_USB_DATA_DIRECTION TransferDirection;
945 INTERRUPT_CONTEXT_ENTRY *Entry;
946 EFI_TPL OldTpl;
947 BOOLEAN FirstTD;
948
949 VOID *Mapping;
950 UINTN MapLength;
951 EFI_PHYSICAL_ADDRESS MapPyhAddr;
952 UINTN LeftLength;
953 UINTN ActualSendLength;
954
955
956 if (DataLength > MAX_BYTES_PER_TD) {
957 DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Error param\r\n"));
958 return EFI_INVALID_PARAMETER;
959 }
960
961 if ((EndPointAddress & 0x80) != 0) {
962 TransferDirection = EfiUsbDataIn;
963 EdDir = ED_IN_DIR;
964 DataPidDir = TD_IN_PID;
965 } else {
966 TransferDirection = EfiUsbDataOut;
967 EdDir = ED_OUT_DIR;
968 DataPidDir = TD_OUT_PID;
969 }
970
971 EndPointNum = (EndPointAddress & 0xF);
972
973 if (!IsNewTransfer) {
974 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
975 OhciSetHcControl (Ohc, PERIODIC_ENABLE, 0);
976 OhciFreeInterruptContext (Ohc, DeviceAddress, EndPointAddress, DataToggle);
977 Status = OhciFreeInterruptEdByAddr (Ohc, DeviceAddress, EndPointNum);
978 OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
979 gBS->RestoreTPL (OldTpl);
980 return Status;
981 }
982 MapLength = DataLength;
983 Status = Ohc->PciIo->Map(
984 Ohc->PciIo,
985 EfiPciIoOperationBusMasterWrite,
986 UCBuffer,
987 &MapLength,
988 &MapPyhAddr,
989 &Mapping
990 );
991 if (EFI_ERROR (Status)) {
992 DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Failt to PciIo->Map buffer \r\n"));
993 goto EXIT;
994 }
995 Depth = 5;
996 Index = 1;
997 while (PollingInterval >= Index * 2 && Depth > 0) {
998 Index *= 2;
999 Depth--;
1000 }
1001 //
1002 //ED Stage
1003 //
1004 HeadEd = OhciFindMinInterruptEDList (Ohc, (UINT32)Depth);
1005 if ((Ed = OhciFindWorkingEd (HeadEd, DeviceAddress, EndPointNum, EdDir)) != NULL) {
1006 OhciSetEDField (Ed, ED_SKIP, 1);
1007 } else {
1008 Ed = OhciCreateED (Ohc);
1009 if (Ed == NULL) {
1010 Status = EFI_OUT_OF_RESOURCES;
1011 DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for ED\r\n"));
1012 goto UNMAP_OHCI_XBUFF;
1013 }
1014 OhciSetEDField (Ed, ED_SKIP, 1);
1015 OhciSetEDField (Ed, ED_FUNC_ADD, DeviceAddress);
1016 OhciSetEDField (Ed, ED_ENDPT_NUM, EndPointNum);
1017 OhciSetEDField (Ed, ED_DIR, ED_FROM_TD_DIR);
1018 OhciSetEDField (Ed, ED_SPEED, IsSlowDevice);
1019 OhciSetEDField (Ed, ED_FORMAT, 0);
1020 OhciSetEDField (Ed, ED_MAX_PACKET, MaxPacketLength);
1021 OhciSetEDField (Ed, ED_PDATA | ED_ZERO | ED_HALTED | ED_DTTOGGLE, 0);
1022 OhciSetEDField (Ed, ED_TDHEAD_PTR, 0);
1023 OhciSetEDField (Ed, ED_TDTAIL_PTR, 0);
1024 OhciSetEDField (Ed, ED_NEXT_EDPTR, 0);
1025 OhciAttachEDToList (Ohc, INTERRUPT_LIST, Ed, HeadEd);
1026 }
1027 //
1028 //Data Stage
1029 //
1030 LeftLength = MapLength;
1031 ActualSendLength = MapLength;
1032 HeadTd = NULL;
1033 FirstTD = TRUE;
1034 while (LeftLength > 0) {
1035 ActualSendLength = LeftLength;
1036 if (LeftLength > MaxPacketLength) {
1037 ActualSendLength = MaxPacketLength;
1038 }
1039 DataTd = OhciCreateTD (Ohc);
1040 if (DataTd == NULL) {
1041 Status = EFI_OUT_OF_RESOURCES;
1042 DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Data Stage TD\r\n"));
1043 goto FREE_OHCI_TDBUFF;
1044 }
1045 OhciSetTDField (DataTd, TD_PDATA, 0);
1046 OhciSetTDField (DataTd, TD_BUFFER_ROUND, 1);
1047 OhciSetTDField (DataTd, TD_DIR_PID, DataPidDir);
1048 OhciSetTDField (DataTd, TD_DELAY_INT, TD_NO_DELAY);
1049 OhciSetTDField (DataTd, TD_DT_TOGGLE, *DataToggle);
1050 OhciSetTDField (DataTd, TD_ERROR_CNT, 0);
1051 OhciSetTDField (DataTd, TD_COND_CODE, TD_TOBE_PROCESSED);
1052 OhciSetTDField (DataTd, TD_CURR_BUFFER_PTR, (UINT32) MapPyhAddr);
1053 OhciSetTDField (DataTd, TD_BUFFER_END_PTR, (UINT32)(MapPyhAddr + ActualSendLength - 1));
1054 OhciSetTDField (DataTd, TD_NEXT_PTR, 0);
1055 DataTd->ActualSendLength = (UINT32)ActualSendLength;
1056 DataTd->DataBuffer = (UINT32)MapPyhAddr;
1057 DataTd->NextTDPointer = 0;
1058 if (FirstTD) {
1059 HeadTd = DataTd;
1060 FirstTD = FALSE;
1061 } else {
1062 OhciLinkTD (HeadTd, DataTd);
1063 }
1064 *DataToggle ^= 1;
1065 MapPyhAddr += ActualSendLength;
1066 LeftLength -= ActualSendLength;
1067 }
1068
1069 EmptTd = OhciCreateTD (Ohc);
1070 if (EmptTd == NULL) {
1071 Status = EFI_OUT_OF_RESOURCES;
1072 DEBUG ((EFI_D_ERROR, "OhciInterruptTransfer: Fail to allocate buffer for Empty Stage TD\r\n"));
1073 goto FREE_OHCI_TDBUFF;
1074 }
1075 OhciSetTDField (EmptTd, TD_PDATA, 0);
1076 OhciSetTDField (EmptTd, TD_BUFFER_ROUND, 0);
1077 OhciSetTDField (EmptTd, TD_DIR_PID, 0);
1078 OhciSetTDField (EmptTd, TD_DELAY_INT, 0);
1079 //OhciSetTDField (EmptTd, TD_DT_TOGGLE, CurrentToggle);
1080 EmptTd->Word0.DataToggle = 0;
1081 OhciSetTDField (EmptTd, TD_ERROR_CNT, 0);
1082 OhciSetTDField (EmptTd, TD_COND_CODE, 0);
1083 OhciSetTDField (EmptTd, TD_CURR_BUFFER_PTR, 0);
1084 OhciSetTDField (EmptTd, TD_BUFFER_END_PTR, 0);
1085 OhciSetTDField (EmptTd, TD_NEXT_PTR, 0);
1086 EmptTd->ActualSendLength = 0;
1087 EmptTd->DataBuffer = 0;
1088 EmptTd->NextTDPointer = 0;
1089 OhciLinkTD (HeadTd, EmptTd);
1090 Ed->TdTailPointer = (UINT32)(UINTN)EmptTd;
1091 OhciAttachTDListToED (Ed, HeadTd);
1092
1093 if (OutputED != NULL) {
1094 *OutputED = Ed;
1095 }
1096 if (OutputTD != NULL) {
1097 *OutputTD = HeadTd;
1098 }
1099
1100 if (CallBackFunction != NULL) {
1101 Entry = AllocatePool (sizeof (INTERRUPT_CONTEXT_ENTRY));
1102 if (Entry == NULL) {
1103 goto FREE_OHCI_TDBUFF;
1104 }
1105
1106 Entry->DeviceAddress = DeviceAddress;
1107 Entry->EndPointAddress = EndPointAddress;
1108 Entry->Ed = Ed;
1109 Entry->DataTd = HeadTd;
1110 Entry->IsSlowDevice = IsSlowDevice;
1111 Entry->MaxPacketLength = MaxPacketLength;
1112 Entry->PollingInterval = PollingInterval;
1113 Entry->CallBackFunction = CallBackFunction;
1114 Entry->Context = Context;
1115 Entry->IsPeriodic = IsPeriodic;
1116 Entry->UCBuffer = UCBuffer;
1117 Entry->UCBufferMapping = Mapping;
1118 Entry->DataLength = DataLength;
1119 Entry->Toggle = DataToggle;
1120 Entry->NextEntry = NULL;
1121 OhciAddInterruptContextEntry (Ohc, Entry);
1122 }
1123 OhciSetEDField (Ed, ED_SKIP, 0);
1124
1125 if (OhciGetHcControl (Ohc, PERIODIC_ENABLE) == 0) {
1126 Status = OhciSetHcControl (Ohc, PERIODIC_ENABLE, 1);
1127 gBS->Stall (1000);
1128 }
1129
1130 return EFI_SUCCESS;
1131
1132 FREE_OHCI_TDBUFF:
1133 while (HeadTd) {
1134 DataTd = HeadTd;
1135 HeadTd = (TD_DESCRIPTOR *)(UINTN)(HeadTd->NextTDPointer);
1136 UsbHcFreeMem(Ohc->MemPool, DataTd, sizeof(TD_DESCRIPTOR));
1137 }
1138
1139 //FREE_OHCI_EDBUFF:
1140 if ((HeadEd != Ed) && HeadEd && Ed) {
1141 while(HeadEd->NextED != (UINT32)(UINTN)Ed) {
1142 HeadEd = (ED_DESCRIPTOR *)(UINTN)(HeadEd->NextED);
1143 }
1144 HeadEd->NextED = Ed->NextED;
1145 UsbHcFreeMem(Ohc->MemPool, Ed, sizeof(ED_DESCRIPTOR));
1146 }
1147
1148 UNMAP_OHCI_XBUFF:
1149 Ohc->PciIo->Unmap(Ohc->PciIo, Mapping);
1150
1151 EXIT:
1152 return Status;
1153 }
1154
1155 /**
1156
1157 Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.
1158
1159 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1160 @param DeviceAddress Represents the address of the target device on the USB,
1161 which is assigned during USB enumeration.
1162 @param EndPointAddress The combination of an endpoint number and an endpoint
1163 direction of the target USB device. Each endpoint address
1164 supports data transfer in one direction except the
1165 control endpoint (whose default endpoint address is 0).
1166 It is the caller's responsibility to make sure that
1167 the EndPointAddress represents an interrupt endpoint.
1168 @param IsSlowDevice Indicates whether the target device is slow device
1169 or full-speed device.
1170 @param MaxiumPacketLength Indicates the maximum packet size the target endpoint
1171 is capable of sending or receiving.
1172 @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
1173 the host and the target interrupt endpoint.
1174 If FALSE, the specified asynchronous interrupt pipe
1175 is canceled.
1176 @param DataToggle A pointer to the data toggle value. On input, it is valid
1177 when IsNewTransfer is TRUE, and it indicates the initial
1178 data toggle value the asynchronous interrupt transfer
1179 should adopt.
1180 On output, it is valid when IsNewTransfer is FALSE,
1181 and it is updated to indicate the data toggle value of
1182 the subsequent asynchronous interrupt transfer.
1183 @param PollingInterval Indicates the interval, in milliseconds, that the
1184 asynchronous interrupt transfer is polled.
1185 This parameter is required when IsNewTransfer is TRUE.
1186 @param DataLength Indicates the length of data to be received at the
1187 rate specified by PollingInterval from the target
1188 asynchronous interrupt endpoint. This parameter
1189 is only required when IsNewTransfer is TRUE.
1190 @param CallBackFunction The Callback function.This function is called at the
1191 rate specified by PollingInterval.This parameter is
1192 only required when IsNewTransfer is TRUE.
1193 @param Context The context that is passed to the CallBackFunction.
1194 This is an optional parameter and may be NULL.
1195
1196 @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully
1197 submitted or canceled.
1198 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
1199 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1200
1201 **/
1202
1203
1204 EFI_STATUS
1205 EFIAPI
1206 OhciAsyncInterruptTransfer (
1207 IN EFI_USB_HC_PROTOCOL *This,
1208 IN UINT8 DeviceAddress,
1209 IN UINT8 EndPointAddress,
1210 IN BOOLEAN IsSlowDevice,
1211 IN UINT8 MaxPacketLength,
1212 IN BOOLEAN IsNewTransfer,
1213 IN OUT UINT8 *DataToggle OPTIONAL,
1214 IN UINTN PollingInterval OPTIONAL,
1215 IN UINTN DataLength OPTIONAL,
1216 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL,
1217 IN VOID *Context OPTIONAL
1218 )
1219 {
1220 EFI_STATUS Status;
1221 USB_OHCI_HC_DEV *Ohc;
1222 VOID *UCBuffer;
1223
1224 if (DataToggle == NULL || (EndPointAddress & 0x80) == 0 ||
1225 (IsNewTransfer && (DataLength == 0 ||
1226 (*DataToggle != 0 && *DataToggle != 1) || (PollingInterval < 1 || PollingInterval > 255)))) {
1227 return EFI_INVALID_PARAMETER;
1228 }
1229
1230 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1231 if ( IsNewTransfer ) {
1232 UCBuffer = AllocatePool(DataLength);
1233 if (UCBuffer == NULL) {
1234 return EFI_OUT_OF_RESOURCES;
1235 }
1236 } else {
1237 UCBuffer = NULL;
1238 }
1239 Status = OhciInterruptTransfer (
1240 Ohc,
1241 DeviceAddress,
1242 EndPointAddress,
1243 IsSlowDevice,
1244 MaxPacketLength,
1245 IsNewTransfer,
1246 DataToggle,
1247 PollingInterval,
1248 UCBuffer,
1249 DataLength,
1250 CallBackFunction,
1251 Context,
1252 TRUE,
1253 NULL,
1254 NULL
1255 );
1256 if ( IsNewTransfer ) {
1257 if (EFI_ERROR(Status)) {
1258 gBS->FreePool (UCBuffer);
1259 }
1260 }
1261 return Status;
1262 }
1263
1264
1265 /**
1266
1267 Submits synchronous interrupt transfer to an interrupt endpoint
1268 of a USB device.
1269
1270 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1271 @param DeviceAddress Represents the address of the target device on the USB,
1272 which is assigned during USB enumeration.
1273 @param EndPointAddress The combination of an endpoint number and an endpoint
1274 direction of the target USB device. Each endpoint
1275 address supports data transfer in one direction
1276 except the control endpoint (whose default
1277 endpoint address is 0). It is the caller's responsibility
1278 to make sure that the EndPointAddress represents
1279 an interrupt endpoint.
1280 @param IsSlowDevice Indicates whether the target device is slow device
1281 or full-speed device.
1282 @param MaxPacketLength Indicates the maximum packet size the target endpoint
1283 is capable of sending or receiving.
1284 @param Data A pointer to the buffer of data that will be transmitted
1285 to USB device or received from USB device.
1286 @param DataLength On input, the size, in bytes, of the data buffer specified
1287 by Data. On output, the number of bytes transferred.
1288 @param DataToggle A pointer to the data toggle value. On input, it indicates
1289 the initial data toggle value the synchronous interrupt
1290 transfer should adopt;
1291 on output, it is updated to indicate the data toggle value
1292 of the subsequent synchronous interrupt transfer.
1293 @param TimeOut Indicates the maximum time, in microseconds, which the
1294 transfer is allowed to complete.
1295 @param TransferResult A pointer to the detailed result information from
1296 the synchronous interrupt transfer.
1297
1298 @retval EFI_UNSUPPORTED This interface not available.
1299 @retval EFI_INVALID_PARAMETER Parameters not follow spec
1300
1301 **/
1302
1303
1304 EFI_STATUS
1305 EFIAPI
1306 OhciSyncInterruptTransfer (
1307 IN EFI_USB_HC_PROTOCOL *This,
1308 IN UINT8 DeviceAddress,
1309 IN UINT8 EndPointAddress,
1310 IN BOOLEAN IsSlowDevice,
1311 IN UINT8 MaxPacketLength,
1312 IN OUT VOID *Data,
1313 IN OUT UINTN *DataLength,
1314 IN OUT UINT8 *DataToggle,
1315 IN UINTN TimeOut,
1316 OUT UINT32 *TransferResult
1317 )
1318 {
1319 USB_OHCI_HC_DEV *Ohc;
1320 EFI_STATUS Status;
1321 ED_DESCRIPTOR *Ed;
1322 TD_DESCRIPTOR *HeadTd;
1323 OHCI_ED_RESULT EdResult;
1324 VOID *UCBuffer;
1325
1326 if ((EndPointAddress & 0x80) == 0 || Data == NULL || DataLength == NULL || *DataLength == 0 ||
1327 (IsSlowDevice && MaxPacketLength > 8) || (!IsSlowDevice && MaxPacketLength > 64) ||
1328 DataToggle == NULL || (*DataToggle != 0 && *DataToggle != 1) || TransferResult == NULL) {
1329 return EFI_INVALID_PARAMETER;
1330 }
1331
1332 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1333 UCBuffer = AllocatePool (*DataLength);
1334 if (UCBuffer == NULL) {
1335 return EFI_OUT_OF_RESOURCES;
1336 }
1337 Status = OhciInterruptTransfer (
1338 Ohc,
1339 DeviceAddress,
1340 EndPointAddress,
1341 IsSlowDevice,
1342 MaxPacketLength,
1343 TRUE,
1344 DataToggle,
1345 1,
1346 UCBuffer,
1347 *DataLength,
1348 NULL,
1349 NULL,
1350 FALSE,
1351 &Ed,
1352 &HeadTd
1353 );
1354
1355 if (!EFI_ERROR (Status)) {
1356 Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
1357 while (Status == EFI_NOT_READY && TimeOut > 0) {
1358 gBS->Stall (1000);
1359 TimeOut--;
1360 Status = CheckIfDone (Ohc, INTERRUPT_LIST, Ed, HeadTd, &EdResult);
1361 }
1362
1363 *TransferResult = ConvertErrorCode (EdResult.ErrorCode);
1364 }
1365 CopyMem(Data, UCBuffer, *DataLength);
1366 Status = OhciInterruptTransfer (
1367 Ohc,
1368 DeviceAddress,
1369 EndPointAddress,
1370 IsSlowDevice,
1371 MaxPacketLength,
1372 FALSE,
1373 DataToggle,
1374 0,
1375 NULL,
1376 0,
1377 NULL,
1378 NULL,
1379 FALSE,
1380 NULL,
1381 NULL
1382 );
1383
1384 return Status;
1385 }
1386 /**
1387
1388 Submits isochronous transfer to a target USB device.
1389
1390 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1391 @param DeviceAddress Represents the address of the target device on the USB,
1392 which is assigned during USB enumeration.
1393 @param EndPointAddress End point address
1394 @param MaximumPacketLength Indicates the maximum packet size that the
1395 default control transfer endpoint is capable of
1396 sending or receiving.
1397 @param Data A pointer to the buffer of data that will be transmitted
1398 to USB device or received from USB device.
1399 @param DataLength Indicates the size, in bytes, of the data buffer
1400 specified by Data.
1401 @param TransferResult A pointer to the detailed result information generated
1402 by this control transfer.
1403
1404 @retval EFI_UNSUPPORTED This interface not available
1405 @retval EFI_INVALID_PARAMETER Data is NULL or DataLength is 0 or TransferResult is NULL
1406
1407 **/
1408
1409
1410 EFI_STATUS
1411 EFIAPI
1412 OhciIsochronousTransfer (
1413 IN EFI_USB_HC_PROTOCOL *This,
1414 IN UINT8 DeviceAddress,
1415 IN UINT8 EndPointAddress,
1416 IN UINT8 MaximumPacketLength,
1417 IN OUT VOID *Data,
1418 IN OUT UINTN DataLength,
1419 OUT UINT32 *TransferResult
1420 )
1421 {
1422 if (Data == NULL || DataLength == 0 || TransferResult == NULL) {
1423 return EFI_INVALID_PARAMETER;
1424 }
1425
1426 return EFI_UNSUPPORTED;
1427 }
1428
1429 /**
1430
1431 Submits Async isochronous transfer to a target USB device.
1432
1433 @param his A pointer to the EFI_USB_HC_PROTOCOL instance.
1434 @param DeviceAddress Represents the address of the target device on the USB,
1435 which is assigned during USB enumeration.
1436 @param EndPointAddress End point address
1437 @param MaximumPacketLength Indicates the maximum packet size that the
1438 default control transfer endpoint is capable of
1439 sending or receiving.
1440 @param Data A pointer to the buffer of data that will be transmitted
1441 to USB device or received from USB device.
1442 @param IsochronousCallBack When the transfer complete, the call back function will be called
1443 @param Context Pass to the call back function as parameter
1444
1445 @retval EFI_UNSUPPORTED This interface not available
1446 @retval EFI_INVALID_PARAMETER Data is NULL or Datalength is 0
1447
1448 **/
1449
1450 EFI_STATUS
1451 EFIAPI
1452 OhciAsyncIsochronousTransfer (
1453 IN EFI_USB_HC_PROTOCOL *This,
1454 IN UINT8 DeviceAddress,
1455 IN UINT8 EndPointAddress,
1456 IN UINT8 MaximumPacketLength,
1457 IN OUT VOID *Data,
1458 IN OUT UINTN DataLength,
1459 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
1460 IN VOID *Context OPTIONAL
1461 )
1462 {
1463
1464 if (Data == NULL || DataLength == 0) {
1465 return EFI_INVALID_PARAMETER;
1466 }
1467
1468 return EFI_UNSUPPORTED;
1469 }
1470
1471 /**
1472
1473 Retrieves the number of root hub ports.
1474
1475 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1476 @param NumOfPorts A pointer to the number of the root hub ports.
1477
1478 @retval EFI_SUCCESS The port number was retrieved successfully.
1479 **/
1480 EFI_STATUS
1481 EFIAPI
1482 OhciGetRootHubNumOfPorts (
1483 IN EFI_USB_HC_PROTOCOL *This,
1484 OUT UINT8 *NumOfPorts
1485 )
1486 {
1487 USB_OHCI_HC_DEV *Ohc;
1488 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1489
1490 if (NumOfPorts == NULL) {
1491 return EFI_INVALID_PARAMETER;
1492 }
1493
1494 *NumOfPorts = (UINT8)OhciGetRootHubDescriptor(Ohc, RH_NUM_DS_PORTS);
1495
1496 return EFI_SUCCESS;
1497 }
1498 /**
1499
1500 Retrieves the current status of a USB root hub port.
1501
1502 @param This A pointer to the EFI_USB_HC_PROTOCOL.
1503 @param PortNumber Specifies the root hub port from which the status
1504 is to be retrieved. This value is zero-based. For example,
1505 if a root hub has two ports, then the first port is numbered 0,
1506 and the second port is numbered 1.
1507 @param PortStatus A pointer to the current port status bits and
1508 port status change bits.
1509
1510 @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber
1511 was returned in PortStatus.
1512 @retval EFI_INVALID_PARAMETER Port number not valid
1513 **/
1514
1515
1516 EFI_STATUS
1517 EFIAPI
1518 OhciGetRootHubPortStatus (
1519 IN EFI_USB_HC_PROTOCOL *This,
1520 IN UINT8 PortNumber,
1521 OUT EFI_USB_PORT_STATUS *PortStatus
1522 )
1523 {
1524 USB_OHCI_HC_DEV *Ohc;
1525 UINT8 NumOfPorts;
1526
1527 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1528
1529 OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1530 if (PortNumber >= NumOfPorts) {
1531 return EFI_INVALID_PARAMETER;
1532 }
1533 PortStatus->PortStatus = 0;
1534 PortStatus->PortChangeStatus = 0;
1535
1536 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_CURR_CONNECT_STAT)) {
1537 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
1538 }
1539 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_ENABLE_STAT)) {
1540 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
1541 }
1542 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_SUSPEND_STAT)) {
1543 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
1544 }
1545 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_OC_INDICATOR)) {
1546 PortStatus->PortStatus |= USB_PORT_STAT_OVERCURRENT;
1547 }
1548 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_RESET_STAT)) {
1549 PortStatus->PortStatus |= USB_PORT_STAT_RESET;
1550 }
1551 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_PORT_POWER_STAT)) {
1552 PortStatus->PortStatus |= USB_PORT_STAT_POWER;
1553 }
1554 if (OhciReadRootHubPortStatus (Ohc,PortNumber, RH_LSDEVICE_ATTACHED)) {
1555 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
1556 }
1557 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE)) {
1558 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
1559 }
1560 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE)) {
1561 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
1562 }
1563 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE)) {
1564 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_SUSPEND;
1565 }
1566 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE)) {
1567 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_OVERCURRENT;
1568 }
1569 if (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE)) {
1570 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_RESET;
1571 }
1572
1573 return EFI_SUCCESS;
1574 }
1575 /**
1576
1577 Sets a feature for the specified root hub port.
1578
1579 @param This A pointer to the EFI_USB_HC_PROTOCOL.
1580 @param PortNumber Specifies the root hub port whose feature
1581 is requested to be set.
1582 @param PortFeature Indicates the feature selector associated
1583 with the feature set request.
1584
1585 @retval EFI_SUCCESS The feature specified by PortFeature was set for the
1586 USB root hub port specified by PortNumber.
1587 @retval EFI_DEVICE_ERROR Set feature failed because of hardware issue
1588 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1589 **/
1590 EFI_STATUS
1591 EFIAPI
1592 OhciSetRootHubPortFeature (
1593 IN EFI_USB_HC_PROTOCOL *This,
1594 IN UINT8 PortNumber,
1595 IN EFI_USB_PORT_FEATURE PortFeature
1596 )
1597 {
1598 USB_OHCI_HC_DEV *Ohc;
1599 EFI_STATUS Status;
1600 UINT8 NumOfPorts;
1601 UINTN RetryTimes;
1602
1603 OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1604 if (PortNumber >= NumOfPorts) {
1605 return EFI_INVALID_PARAMETER;
1606 }
1607
1608 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1609
1610 Status = EFI_SUCCESS;
1611
1612
1613 switch (PortFeature) {
1614 case EfiUsbPortPower:
1615 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_POWER);
1616
1617 //
1618 // Verify the state
1619 //
1620 RetryTimes = 0;
1621 do {
1622 gBS->Stall (1000);
1623 RetryTimes++;
1624 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 0 &&
1625 RetryTimes < MAX_RETRY_TIMES);
1626
1627 if (RetryTimes >= MAX_RETRY_TIMES) {
1628 return EFI_DEVICE_ERROR;
1629 }
1630 break;
1631
1632 case EfiUsbPortReset:
1633 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_RESET);
1634
1635 //
1636 // Verify the state
1637 //
1638 RetryTimes = 0;
1639 do {
1640 gBS->Stall (1000);
1641 RetryTimes++;
1642 } while ((OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 0 ||
1643 OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT) == 1) &&
1644 RetryTimes < MAX_RETRY_TIMES);
1645
1646 if (RetryTimes >= MAX_RETRY_TIMES) {
1647 return EFI_DEVICE_ERROR;
1648 }
1649
1650 OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
1651 break;
1652
1653 case EfiUsbPortEnable:
1654 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_ENABLE);
1655
1656 //
1657 // Verify the state
1658 //
1659 RetryTimes = 0;
1660 do {
1661 gBS->Stall (1000);
1662 RetryTimes++;
1663 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 0 &&
1664 RetryTimes < MAX_RETRY_TIMES);
1665
1666 if (RetryTimes >= MAX_RETRY_TIMES) {
1667 return EFI_DEVICE_ERROR;
1668 }
1669 break;
1670
1671
1672 case EfiUsbPortSuspend:
1673 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_SET_PORT_SUSPEND);
1674
1675 //
1676 // Verify the state
1677 //
1678 RetryTimes = 0;
1679 do {
1680 gBS->Stall (1000);
1681 RetryTimes++;
1682 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 0 &&
1683 RetryTimes < MAX_RETRY_TIMES);
1684
1685 if (RetryTimes >= MAX_RETRY_TIMES) {
1686 return EFI_DEVICE_ERROR;
1687 }
1688 break;
1689
1690 default:
1691 return EFI_INVALID_PARAMETER;
1692 }
1693
1694 return Status;
1695 }
1696
1697 /**
1698
1699 Clears a feature for the specified root hub port.
1700
1701 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.
1702 @param PortNumber Specifies the root hub port whose feature
1703 is requested to be cleared.
1704 @param PortFeature Indicates the feature selector associated with the
1705 feature clear request.
1706
1707 @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the
1708 USB root hub port specified by PortNumber.
1709 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.
1710 @retval EFI_DEVICE_ERROR Some error happened when clearing feature
1711 **/
1712 EFI_STATUS
1713 EFIAPI
1714 OhciClearRootHubPortFeature (
1715 IN EFI_USB_HC_PROTOCOL *This,
1716 IN UINT8 PortNumber,
1717 IN EFI_USB_PORT_FEATURE PortFeature
1718 )
1719 {
1720 USB_OHCI_HC_DEV *Ohc;
1721 EFI_STATUS Status;
1722 UINT8 NumOfPorts;
1723 UINTN RetryTimes;
1724
1725
1726 OhciGetRootHubNumOfPorts (This, &NumOfPorts);
1727 if (PortNumber >= NumOfPorts) {
1728 return EFI_INVALID_PARAMETER;
1729 }
1730
1731 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
1732
1733 Status = EFI_SUCCESS;
1734
1735 switch (PortFeature) {
1736 case EfiUsbPortEnable:
1737 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_ENABLE);
1738
1739 //
1740 // Verify the state
1741 //
1742 RetryTimes = 0;
1743 do {
1744 gBS->Stall (1000);
1745 RetryTimes++;
1746 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT) == 1 &&
1747 RetryTimes < MAX_RETRY_TIMES);
1748
1749 if (RetryTimes >= MAX_RETRY_TIMES) {
1750 return EFI_DEVICE_ERROR;
1751 }
1752 break;
1753
1754 case EfiUsbPortSuspend:
1755 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_SUSPEND_STATUS);
1756
1757 //
1758 // Verify the state
1759 //
1760 RetryTimes = 0;
1761 do {
1762 gBS->Stall (1000);
1763 RetryTimes++;
1764 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT) == 1 &&
1765 RetryTimes < MAX_RETRY_TIMES);
1766
1767 if (RetryTimes >= MAX_RETRY_TIMES) {
1768 return EFI_DEVICE_ERROR;
1769 }
1770 break;
1771
1772 case EfiUsbPortReset:
1773 break;
1774
1775 case EfiUsbPortPower:
1776 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CLEAR_PORT_POWER);
1777
1778 //
1779 // Verify the state
1780 //
1781 RetryTimes = 0;
1782 do {
1783 gBS->Stall (1000);
1784 RetryTimes++;
1785 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_POWER_STAT) == 1 &&
1786 RetryTimes < MAX_RETRY_TIMES);
1787
1788 if (RetryTimes >= MAX_RETRY_TIMES) {
1789 return EFI_DEVICE_ERROR;
1790 }
1791 break;
1792
1793 case EfiUsbPortConnectChange:
1794 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE);
1795
1796 //
1797 // Verify the state
1798 //
1799 RetryTimes = 0;
1800 do {
1801 gBS->Stall (1000);
1802 RetryTimes++;
1803 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_CONNECT_STATUS_CHANGE) == 1 &&
1804 RetryTimes < MAX_RETRY_TIMES);
1805
1806 if (RetryTimes >= MAX_RETRY_TIMES) {
1807 return EFI_DEVICE_ERROR;
1808 }
1809 break;
1810
1811 case EfiUsbPortResetChange:
1812 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE);
1813
1814 //
1815 // Verify the state
1816 //
1817 RetryTimes = 0;
1818 do {
1819 gBS->Stall (1000);
1820 RetryTimes++;
1821 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_RESET_STAT_CHANGE) == 1 &&
1822 RetryTimes < MAX_RETRY_TIMES);
1823
1824 if (RetryTimes >= MAX_RETRY_TIMES) {
1825 return EFI_DEVICE_ERROR;
1826 }
1827 break;
1828
1829
1830 case EfiUsbPortEnableChange:
1831 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE);
1832
1833 //
1834 // Verify the state
1835 //
1836 RetryTimes = 0;
1837 do {
1838 gBS->Stall (1000);
1839 RetryTimes++;
1840 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_ENABLE_STAT_CHANGE) == 1 &&
1841 RetryTimes < MAX_RETRY_TIMES);
1842
1843 if (RetryTimes >= MAX_RETRY_TIMES) {
1844 return EFI_DEVICE_ERROR;
1845 }
1846 break;
1847
1848 case EfiUsbPortSuspendChange:
1849 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE);
1850
1851 //
1852 // Verify the state
1853 //
1854 RetryTimes = 0;
1855 do {
1856 gBS->Stall (1000);
1857 RetryTimes++;
1858 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_PORT_SUSPEND_STAT_CHANGE) == 1 &&
1859 RetryTimes < MAX_RETRY_TIMES);
1860
1861 if (RetryTimes >= MAX_RETRY_TIMES) {
1862 return EFI_DEVICE_ERROR;
1863 }
1864 break;
1865
1866 case EfiUsbPortOverCurrentChange:
1867 Status = OhciSetRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE);
1868
1869 //
1870 // Verify the state
1871 //
1872 RetryTimes = 0;
1873 do {
1874 gBS->Stall (1000);
1875 RetryTimes++;
1876 } while (OhciReadRootHubPortStatus (Ohc, PortNumber, RH_OC_INDICATOR_CHANGE) == 1 &&
1877 RetryTimes < MAX_RETRY_TIMES);
1878
1879 if (RetryTimes >= MAX_RETRY_TIMES) {
1880 return EFI_DEVICE_ERROR;
1881 }
1882 break;
1883
1884 default:
1885 return EFI_INVALID_PARAMETER;
1886 }
1887
1888 return Status;
1889 }
1890
1891 EFI_DRIVER_BINDING_PROTOCOL gOhciDriverBinding = {
1892 OHCIDriverBindingSupported,
1893 OHCIDriverBindingStart,
1894 OHCIDriverBindingStop,
1895 0x10,
1896 NULL,
1897 NULL
1898 };
1899
1900
1901 /**
1902 Entry point for EFI drivers.
1903
1904 @param ImageHandle EFI_HANDLE.
1905 @param SystemTable EFI_SYSTEM_TABLE.
1906
1907 @retval EFI_SUCCESS Driver is successfully loaded.
1908 @return Others Failed.
1909
1910 **/
1911 EFI_STATUS
1912 EFIAPI
1913 OHCIDriverEntryPoint (
1914 IN EFI_HANDLE ImageHandle,
1915 IN EFI_SYSTEM_TABLE *SystemTable
1916 )
1917 {
1918 return EfiLibInstallDriverBindingComponentName2 (
1919 ImageHandle,
1920 SystemTable,
1921 &gOhciDriverBinding,
1922 ImageHandle,
1923 &gOhciComponentName,
1924 &gOhciComponentName2
1925 );
1926 }
1927
1928
1929 /**
1930 Test to see if this driver supports ControllerHandle. Any
1931 ControllerHandle that has UsbHcProtocol installed will be supported.
1932
1933 @param This Protocol instance pointer.
1934 @param Controller Handle of device to test.
1935 @param RemainingDevicePath Not used.
1936
1937 @return EFI_SUCCESS This driver supports this device.
1938 @return EFI_UNSUPPORTED This driver does not support this device.
1939
1940 **/
1941 EFI_STATUS
1942 EFIAPI
1943 OHCIDriverBindingSupported (
1944 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1945 IN EFI_HANDLE Controller,
1946 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1947 )
1948 {
1949 EFI_STATUS Status;
1950 EFI_PCI_IO_PROTOCOL *PciIo;
1951 USB_CLASSC UsbClassCReg;
1952 //
1953 // Test whether there is PCI IO Protocol attached on the controller handle.
1954 //
1955 Status = gBS->OpenProtocol (
1956 Controller,
1957 &gEfiPciIoProtocolGuid,
1958 (VOID **) &PciIo,
1959 This->DriverBindingHandle,
1960 Controller,
1961 EFI_OPEN_PROTOCOL_BY_DRIVER
1962 );
1963
1964 if (EFI_ERROR (Status)) {
1965 return EFI_UNSUPPORTED;
1966 }
1967
1968 Status = PciIo->Pci.Read (
1969 PciIo,
1970 EfiPciIoWidthUint8,
1971 PCI_CLASSCODE_OFFSET,
1972 sizeof (USB_CLASSC) / sizeof (UINT8),
1973 &UsbClassCReg
1974 );
1975
1976 if (EFI_ERROR (Status)) {
1977 Status = EFI_UNSUPPORTED;
1978 goto ON_EXIT;
1979 }
1980 //
1981 // Test whether the controller belongs to OHCI type
1982 //
1983 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
1984 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
1985 (UsbClassCReg.ProgInterface != PCI_IF_OHCI)
1986 ) {
1987
1988 Status = EFI_UNSUPPORTED;
1989 }
1990 ON_EXIT:
1991 gBS->CloseProtocol (
1992 Controller,
1993 &gEfiPciIoProtocolGuid,
1994 This->DriverBindingHandle,
1995 Controller
1996 );
1997
1998 return Status;
1999
2000 }
2001
2002 /**
2003
2004 Allocate and initialize the empty OHCI device.
2005
2006 @param PciIo The PCIIO to use.
2007 @param OriginalPciAttributes The original PCI attributes.
2008
2009 @return Allocated OHCI device If err, return NULL.
2010
2011 **/
2012
2013 USB_OHCI_HC_DEV *
2014 OhciAllocateDev (
2015 IN EFI_PCI_IO_PROTOCOL *PciIo,
2016 IN UINT64 OriginalPciAttributes
2017 )
2018 {
2019 USB_OHCI_HC_DEV *Ohc;
2020 EFI_STATUS Status;
2021 VOID *Buf;
2022 EFI_PHYSICAL_ADDRESS PhyAddr;
2023 VOID *Map;
2024 UINTN Pages;
2025 UINTN Bytes;
2026
2027 Ohc = AllocateZeroPool (sizeof (USB_OHCI_HC_DEV));
2028 if (Ohc == NULL) {
2029 return NULL;
2030 }
2031
2032 Ohc->Signature = USB_OHCI_HC_DEV_SIGNATURE;
2033 Ohc->PciIo = PciIo;
2034
2035 Ohc->UsbHc.Reset = OhciReset;
2036 Ohc->UsbHc.GetState = OhciGetState;
2037 Ohc->UsbHc.SetState = OhciSetState;
2038 Ohc->UsbHc.ControlTransfer = OhciControlTransfer;
2039 Ohc->UsbHc.BulkTransfer = OhciBulkTransfer;
2040 Ohc->UsbHc.AsyncInterruptTransfer = OhciAsyncInterruptTransfer;
2041 Ohc->UsbHc.SyncInterruptTransfer = OhciSyncInterruptTransfer;
2042 Ohc->UsbHc.IsochronousTransfer = OhciIsochronousTransfer;
2043 Ohc->UsbHc.AsyncIsochronousTransfer = OhciAsyncIsochronousTransfer;
2044 Ohc->UsbHc.GetRootHubPortNumber = OhciGetRootHubNumOfPorts;
2045 Ohc->UsbHc.GetRootHubPortStatus = OhciGetRootHubPortStatus;
2046 Ohc->UsbHc.SetRootHubPortFeature = OhciSetRootHubPortFeature;
2047 Ohc->UsbHc.ClearRootHubPortFeature = OhciClearRootHubPortFeature;
2048 Ohc->UsbHc.MajorRevision = 0x1;
2049 Ohc->UsbHc.MinorRevision = 0x1;
2050
2051 Ohc->OriginalPciAttributes = OriginalPciAttributes;
2052
2053 Ohc->HccaMemoryBlock = NULL;
2054 Ohc->HccaMemoryMapping = NULL;
2055 Ohc->HccaMemoryBuf = NULL;
2056 Ohc->HccaMemoryPages = 0;
2057 Ohc->InterruptContextList = NULL;
2058 Ohc->ControllerNameTable = NULL;
2059 Ohc->HouseKeeperTimer = NULL;
2060
2061 Ohc->MemPool = UsbHcInitMemPool(PciIo, TRUE, 0);
2062 if(Ohc->MemPool == NULL) {
2063 goto FREE_DEV_BUFFER;
2064 }
2065
2066 Bytes = 4096;
2067 Pages = EFI_SIZE_TO_PAGES (Bytes);
2068
2069 Status = PciIo->AllocateBuffer (
2070 PciIo,
2071 AllocateAnyPages,
2072 EfiBootServicesData,
2073 Pages,
2074 &Buf,
2075 0
2076 );
2077
2078 if (EFI_ERROR (Status)) {
2079 goto FREE_MEM_POOL;
2080 }
2081
2082 Status = PciIo->Map (
2083 PciIo,
2084 EfiPciIoOperationBusMasterCommonBuffer,
2085 Buf,
2086 &Bytes,
2087 &PhyAddr,
2088 &Map
2089 );
2090
2091 if (EFI_ERROR (Status) || (Bytes != 4096)) {
2092 goto FREE_MEM_PAGE;
2093 }
2094
2095 Ohc->HccaMemoryBlock = (HCCA_MEMORY_BLOCK *)(UINTN)PhyAddr;
2096 Ohc->HccaMemoryMapping = Map;
2097 Ohc->HccaMemoryBuf = (VOID *)(UINTN)Buf;
2098 Ohc->HccaMemoryPages = Pages;
2099
2100 return Ohc;
2101
2102 FREE_MEM_PAGE:
2103 PciIo->FreeBuffer (PciIo, Pages, Buf);
2104 FREE_MEM_POOL:
2105 UsbHcFreeMemPool (Ohc->MemPool);
2106 FREE_DEV_BUFFER:
2107 FreePool(Ohc);
2108
2109 return NULL;
2110 }
2111 /**
2112
2113 Free the OHCI device and release its associated resources.
2114
2115 @param Ohc The OHCI device to release.
2116
2117 **/
2118 VOID
2119 OhciFreeDev (
2120 IN USB_OHCI_HC_DEV *Ohc
2121 )
2122 {
2123 OhciFreeFixedIntMemory (Ohc);
2124
2125 if (Ohc->HouseKeeperTimer != NULL) {
2126 gBS->CloseEvent (Ohc->HouseKeeperTimer);
2127 }
2128
2129 if (Ohc->ExitBootServiceEvent != NULL) {
2130 gBS->CloseEvent (Ohc->ExitBootServiceEvent);
2131 }
2132
2133 if (Ohc->MemPool != NULL) {
2134 UsbHcFreeMemPool (Ohc->MemPool);
2135 }
2136
2137 if (Ohc->HccaMemoryMapping != NULL ) {
2138 Ohc->PciIo->FreeBuffer (Ohc->PciIo, Ohc->HccaMemoryPages, Ohc->HccaMemoryBuf);
2139 }
2140
2141 if (Ohc->ControllerNameTable != NULL) {
2142 FreeUnicodeStringTable (Ohc->ControllerNameTable);
2143 }
2144
2145 FreePool (Ohc);
2146 }
2147 /**
2148
2149 Uninstall all Ohci Interface.
2150
2151 @param Controller Controller handle.
2152 @param This Protocol instance pointer.
2153
2154 **/
2155 VOID
2156 OhciCleanDevUp (
2157 IN EFI_HANDLE Controller,
2158 IN EFI_USB_HC_PROTOCOL *This
2159 )
2160 {
2161 USB_OHCI_HC_DEV *Ohc;
2162
2163 //
2164 // Retrieve private context structure
2165 //
2166 Ohc = USB_OHCI_HC_DEV_FROM_THIS (This);
2167
2168 //
2169 // Uninstall the USB_HC and USB_HC2 protocol
2170 //
2171 gBS->UninstallProtocolInterface (
2172 Controller,
2173 &gEfiUsbHcProtocolGuid,
2174 &Ohc->UsbHc
2175 );
2176
2177 //
2178 // Cancel the timer event
2179 //
2180 gBS->SetTimer (Ohc->HouseKeeperTimer, TimerCancel, 0);
2181
2182 //
2183 // Stop the host controller
2184 //
2185 OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
2186 This->Reset (This, EFI_USB_HC_RESET_GLOBAL);
2187 This->SetState (This, EfiUsbHcStateHalt);
2188
2189 //
2190 // Free resources
2191 //
2192 OhciFreeDynamicIntMemory (Ohc);
2193
2194 //
2195 // Restore original PCI attributes
2196 //
2197 Ohc->PciIo->Attributes (
2198 Ohc->PciIo,
2199 EfiPciIoAttributeOperationSet,
2200 Ohc->OriginalPciAttributes,
2201 NULL
2202 );
2203
2204 //
2205 // Free the private context structure
2206 //
2207 OhciFreeDev (Ohc);
2208 }
2209
2210 /**
2211
2212 One notified function to stop the Host Controller when gBS->ExitBootServices() called.
2213
2214 @param Event Pointer to this event
2215 @param Context Event hanlder private data
2216 **/
2217 VOID
2218 EFIAPI
2219 OhcExitBootService (
2220 EFI_EVENT Event,
2221 VOID *Context
2222 )
2223 {
2224 USB_OHCI_HC_DEV *Ohc;
2225 EFI_USB_HC_PROTOCOL *UsbHc;
2226 Ohc = (USB_OHCI_HC_DEV *) Context;
2227
2228 UsbHc = &Ohc->UsbHc;
2229 //
2230 // Stop the Host Controller
2231 //
2232 //OhciStopHc (Ohc, OHC_GENERIC_TIMEOUT);
2233 OhciSetHcControl (Ohc, PERIODIC_ENABLE | CONTROL_ENABLE | ISOCHRONOUS_ENABLE | BULK_ENABLE, 0);
2234 UsbHc->Reset (UsbHc, EFI_USB_HC_RESET_GLOBAL);
2235 UsbHc->SetState (UsbHc, EfiUsbHcStateHalt);
2236
2237 return;
2238 }
2239
2240
2241 /**
2242 Starting the Usb OHCI Driver.
2243
2244 @param This Protocol instance pointer.
2245 @param Controller Handle of device to test.
2246 @param RemainingDevicePath Not used.
2247
2248 @retval EFI_SUCCESS This driver supports this device.
2249 @retval EFI_UNSUPPORTED This driver does not support this device.
2250 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
2251 EFI_OUT_OF_RESOURCES- Failed due to resource shortage.
2252
2253 **/
2254 EFI_STATUS
2255 EFIAPI
2256 OHCIDriverBindingStart (
2257 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2258 IN EFI_HANDLE Controller,
2259 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
2260 )
2261 {
2262 EFI_STATUS Status;
2263 EFI_PCI_IO_PROTOCOL *PciIo;
2264 USB_OHCI_HC_DEV *Ohc;
2265 UINT64 Supports;
2266 UINT64 OriginalPciAttributes;
2267 BOOLEAN PciAttributesSaved;
2268
2269 //
2270 // Open PCIIO, then enable the HC device and turn off emulation
2271 //
2272 Ohc = NULL;
2273 Status = gBS->OpenProtocol (
2274 Controller,
2275 &gEfiPciIoProtocolGuid,
2276 (VOID **) &PciIo,
2277 This->DriverBindingHandle,
2278 Controller,
2279 EFI_OPEN_PROTOCOL_BY_DRIVER
2280 );
2281
2282 if (EFI_ERROR (Status)) {
2283 return Status;
2284 }
2285
2286 PciAttributesSaved = FALSE;
2287 //
2288 // Save original PCI attributes
2289 //
2290 Status = PciIo->Attributes (
2291 PciIo,
2292 EfiPciIoAttributeOperationGet,
2293 0,
2294 &OriginalPciAttributes
2295 );
2296
2297 if (EFI_ERROR (Status)) {
2298 goto CLOSE_PCIIO;
2299 }
2300 PciAttributesSaved = TRUE;
2301
2302 //
2303 // Robustnesss improvement such as for UoL
2304 // Default is not required.
2305 //
2306 //if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {
2307 // OhciTurnOffUsbEmulation (PciIo);
2308 //}
2309
2310 Status = PciIo->Attributes (
2311 PciIo,
2312 EfiPciIoAttributeOperationSupported,
2313 0,
2314 &Supports
2315 );
2316 if (!EFI_ERROR (Status)) {
2317 Supports &= EFI_PCI_DEVICE_ENABLE;
2318 Status = PciIo->Attributes (
2319 PciIo,
2320 EfiPciIoAttributeOperationEnable,
2321 Supports,
2322 NULL
2323 );
2324 }
2325
2326 if (EFI_ERROR (Status)) {
2327 goto CLOSE_PCIIO;
2328 }
2329 //
2330 //Allocate memory for OHC private data structure
2331 //
2332 Ohc = OhciAllocateDev(PciIo, OriginalPciAttributes);
2333 if (Ohc == NULL){
2334 Status = EFI_OUT_OF_RESOURCES;
2335 goto CLOSE_PCIIO;
2336 }
2337
2338 //Status = OhciInitializeInterruptList ( Uhc );
2339 //if (EFI_ERROR (Status)) {
2340 // goto FREE_OHC;
2341 //}
2342
2343 //
2344 // Set 0.01 s timer
2345 //
2346 Status = gBS->CreateEvent (
2347 EVT_TIMER | EVT_NOTIFY_SIGNAL,
2348 TPL_NOTIFY,
2349 OhciHouseKeeper,
2350 Ohc,
2351 &Ohc->HouseKeeperTimer
2352 );
2353 if (EFI_ERROR (Status)) {
2354 goto FREE_OHC;
2355 }
2356
2357 Status = gBS->SetTimer (Ohc->HouseKeeperTimer, TimerPeriodic, 10 * 1000 * 10);
2358 if (EFI_ERROR (Status)) {
2359 goto FREE_OHC;
2360 }
2361
2362 //
2363 //Install Host Controller Protocol
2364 //
2365 Status = gBS->InstallProtocolInterface (
2366 &Controller,
2367 &gEfiUsbHcProtocolGuid,
2368 EFI_NATIVE_INTERFACE,
2369 &Ohc->UsbHc
2370 );
2371 if (EFI_ERROR (Status)) {
2372 DEBUG ((EFI_D_INFO, "Install protocol error"));
2373 goto FREE_OHC;
2374 }
2375 //
2376 // Create event to stop the HC when exit boot service.
2377 //
2378 Status = gBS->CreateEventEx (
2379 EVT_NOTIFY_SIGNAL,
2380 TPL_NOTIFY,
2381 OhcExitBootService,
2382 Ohc,
2383 &gEfiEventExitBootServicesGuid,
2384 &Ohc->ExitBootServiceEvent
2385 );
2386 if (EFI_ERROR (Status)) {
2387 DEBUG ((EFI_D_INFO, "Create exit boot event error"));
2388 goto UNINSTALL_USBHC;
2389 }
2390 AddUnicodeString2 (
2391 "eng",
2392 gOhciComponentName.SupportedLanguages,
2393 &Ohc->ControllerNameTable,
2394 L"Usb Universal Host Controller",
2395 TRUE
2396 );
2397 AddUnicodeString2 (
2398 "en",
2399 gOhciComponentName2.SupportedLanguages,
2400 &Ohc->ControllerNameTable,
2401 L"Usb Universal Host Controller",
2402 FALSE
2403 );
2404
2405 return EFI_SUCCESS;
2406
2407 UNINSTALL_USBHC:
2408 gBS->UninstallMultipleProtocolInterfaces (
2409 Controller,
2410 &gEfiUsbHcProtocolGuid,
2411 &Ohc->UsbHc,
2412 NULL
2413 );
2414
2415 FREE_OHC:
2416 OhciFreeDev (Ohc);
2417
2418 CLOSE_PCIIO:
2419 if (PciAttributesSaved) {
2420 //
2421 // Restore original PCI attributes
2422 //
2423 PciIo->Attributes (
2424 PciIo,
2425 EfiPciIoAttributeOperationSet,
2426 OriginalPciAttributes,
2427 NULL
2428 );
2429 }
2430
2431 gBS->CloseProtocol (
2432 Controller,
2433 &gEfiPciIoProtocolGuid,
2434 This->DriverBindingHandle,
2435 Controller
2436 );
2437 return Status;
2438 }
2439
2440 /**
2441 Stop this driver on ControllerHandle. Support stoping any child handles
2442 created by this driver.
2443
2444 @param This Protocol instance pointer.
2445 @param Controller Handle of device to stop driver on.
2446 @param NumberOfChildren Number of Children in the ChildHandleBuffer.
2447 @param ChildHandleBuffer List of handles for the children we need to stop.
2448
2449 @return EFI_SUCCESS
2450 @return others
2451
2452 **/
2453 EFI_STATUS
2454 EFIAPI
2455 OHCIDriverBindingStop (
2456 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2457 IN EFI_HANDLE Controller,
2458 IN UINTN NumberOfChildren,
2459 IN EFI_HANDLE *ChildHandleBuffer
2460 )
2461 {
2462 EFI_STATUS Status;
2463 EFI_USB_HC_PROTOCOL *UsbHc;
2464
2465 Status = gBS->OpenProtocol (
2466 Controller,
2467 &gEfiUsbHcProtocolGuid,
2468 (VOID **)&UsbHc,
2469 This->DriverBindingHandle,
2470 Controller,
2471 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2472 );
2473 if (EFI_ERROR (Status)) {
2474 return Status;
2475 }
2476
2477 OhciCleanDevUp(Controller, UsbHc);
2478
2479 gBS->CloseProtocol (
2480 Controller,
2481 &gEfiPciIoProtocolGuid,
2482 This->DriverBindingHandle,
2483 Controller
2484 );
2485 return EFI_SUCCESS;
2486 }
2487
2488