]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c
Clean up to fix build break.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / EhciDxe / Ehci.c
CommitLineData
913cb9dc 1/** @file\r
78c2ffb5 2 \r
3 The Ehci controller driver.\r
913cb9dc 4\r
b4c24e2d 5Copyright (c) 2006 - 2008, Intel Corporation\r
913cb9dc 6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
913cb9dc 14**/\r
15\r
16\r
17#include "Ehci.h"\r
18\r
19//\r
20// Two arrays used to translate the EHCI port state (change)\r
21// to the UEFI protocol's port state (change).\r
22//\r
23USB_PORT_STATE_MAP mUsbPortStateMap[] = {\r
24 {PORTSC_CONN, USB_PORT_STAT_CONNECTION},\r
25 {PORTSC_ENABLED, USB_PORT_STAT_ENABLE},\r
26 {PORTSC_SUSPEND, USB_PORT_STAT_SUSPEND},\r
27 {PORTSC_OVERCUR, USB_PORT_STAT_OVERCURRENT},\r
28 {PORTSC_RESET, USB_PORT_STAT_RESET},\r
29 {PORTSC_POWER, USB_PORT_STAT_POWER},\r
30 {PORTSC_OWNER, USB_PORT_STAT_OWNER}\r
31};\r
32\r
33USB_PORT_STATE_MAP mUsbPortChangeMap[] = {\r
34 {PORTSC_CONN_CHANGE, USB_PORT_STAT_C_CONNECTION},\r
35 {PORTSC_ENABLE_CHANGE, USB_PORT_STAT_C_ENABLE},\r
36 {PORTSC_OVERCUR_CHANGE, USB_PORT_STAT_C_OVERCURRENT}\r
37};\r
38\r
39\r
40/**\r
41 Retrieves the capablility of root hub ports.\r
42\r
78c2ffb5 43 @param This This EFI_USB_HC_PROTOCOL instance.\r
44 @param MaxSpeed Max speed supported by the controller.\r
45 @param PortNumber Number of the root hub ports.\r
46 @param Is64BitCapable Whether the controller supports 64-bit memory\r
47 addressing.\r
913cb9dc 48\r
78c2ffb5 49 @retval EFI_SUCCESS Host controller capability were retrieved successfully.\r
50 @retval EFI_INVALID_PARAMETER Either of the three capability pointer is NULL.\r
913cb9dc 51\r
52**/\r
913cb9dc 53EFI_STATUS\r
54EFIAPI\r
55EhcGetCapability (\r
56 IN EFI_USB2_HC_PROTOCOL *This,\r
57 OUT UINT8 *MaxSpeed,\r
58 OUT UINT8 *PortNumber,\r
59 OUT UINT8 *Is64BitCapable\r
60 )\r
61{\r
62 USB2_HC_DEV *Ehc;\r
63 EFI_TPL OldTpl;\r
64\r
65 if ((MaxSpeed == NULL) || (PortNumber == NULL) || (Is64BitCapable == NULL)) {\r
66 return EFI_INVALID_PARAMETER;\r
67 }\r
68\r
69 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
70 Ehc = EHC_FROM_THIS (This);\r
71\r
72 *MaxSpeed = EFI_USB_SPEED_HIGH;\r
73 *PortNumber = (UINT8) (Ehc->HcStructParams & HCSP_NPORTS);\r
74 *Is64BitCapable = (UINT8) (Ehc->HcCapParams & HCCP_64BIT);\r
75\r
1c619535 76 DEBUG ((EFI_D_INFO, "EhcGetCapability: %d ports, 64 bit %d\n", *PortNumber, *Is64BitCapable));\r
913cb9dc 77\r
78 gBS->RestoreTPL (OldTpl);\r
79 return EFI_SUCCESS;\r
80}\r
81\r
82\r
83/**\r
84 Provides software reset for the USB host controller.\r
85\r
78c2ffb5 86 @param This This EFI_USB2_HC_PROTOCOL instance.\r
87 @param Attributes A bit mask of the reset operation to perform.\r
913cb9dc 88\r
78c2ffb5 89 @retval EFI_SUCCESS The reset operation succeeded.\r
90 @retval EFI_INVALID_PARAMETER Attributes is not valid.\r
91 @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is\r
92 not currently supported by the host controller.\r
93 @retval EFI_DEVICE_ERROR Host controller isn't halted to reset.\r
913cb9dc 94\r
95**/\r
913cb9dc 96EFI_STATUS\r
97EFIAPI\r
98EhcReset (\r
99 IN EFI_USB2_HC_PROTOCOL *This,\r
100 IN UINT16 Attributes\r
101 )\r
102{\r
103 USB2_HC_DEV *Ehc;\r
104 EFI_TPL OldTpl;\r
105 EFI_STATUS Status;\r
106\r
107 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
108 Ehc = EHC_FROM_THIS (This);\r
109\r
110 switch (Attributes) {\r
111 case EFI_USB_HC_RESET_GLOBAL:\r
112 //\r
113 // Flow through, same behavior as Host Controller Reset\r
114 //\r
115 case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
116 //\r
117 // Host Controller must be Halt when Reset it\r
118 //\r
119 if (!EhcIsHalt (Ehc)) {\r
41e8ff27 120 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
913cb9dc 121\r
122 if (EFI_ERROR (Status)) {\r
123 Status = EFI_DEVICE_ERROR;\r
124 goto ON_EXIT;\r
125 }\r
126 }\r
68246fa8 127\r
913cb9dc 128 //\r
129 // Clean up the asynchronous transfers, currently only\r
130 // interrupt supports asynchronous operation.\r
131 //\r
132 EhciDelAllAsyncIntTransfers (Ehc);\r
133 EhcAckAllInterrupt (Ehc);\r
134 EhcFreeSched (Ehc);\r
135\r
41e8ff27 136 Status = EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
913cb9dc 137\r
138 if (EFI_ERROR (Status)) {\r
139 goto ON_EXIT;\r
140 }\r
141\r
142 Status = EhcInitHC (Ehc);\r
143 break;\r
144\r
145 case EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG:\r
146 case EFI_USB_HC_RESET_HOST_WITH_DEBUG:\r
147 Status = EFI_UNSUPPORTED;\r
148 break;\r
149\r
150 default:\r
151 Status = EFI_INVALID_PARAMETER;\r
152 }\r
153\r
154ON_EXIT:\r
1c619535 155 DEBUG ((EFI_D_INFO, "EhcReset: exit status %r\n", Status));\r
913cb9dc 156 gBS->RestoreTPL (OldTpl);\r
157 return Status;\r
158}\r
159\r
160\r
161/**\r
162 Retrieve the current state of the USB host controller.\r
163\r
78c2ffb5 164 @param This This EFI_USB2_HC_PROTOCOL instance.\r
165 @param State Variable to return the current host controller\r
166 state.\r
913cb9dc 167\r
78c2ffb5 168 @retval EFI_SUCCESS Host controller state was returned in State.\r
169 @retval EFI_INVALID_PARAMETER State is NULL.\r
170 @retval EFI_DEVICE_ERROR An error was encountered while attempting to\r
171 retrieve the host controller's current state.\r
913cb9dc 172\r
173**/\r
913cb9dc 174EFI_STATUS\r
175EFIAPI\r
176EhcGetState (\r
177 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
178 OUT EFI_USB_HC_STATE *State\r
179 )\r
180{\r
181 EFI_TPL OldTpl;\r
182 USB2_HC_DEV *Ehc;\r
183\r
184 if (State == NULL) {\r
185 return EFI_INVALID_PARAMETER;\r
186 }\r
187\r
188 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
189 Ehc = EHC_FROM_THIS (This);\r
190\r
191 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {\r
192 *State = EfiUsbHcStateHalt;\r
193 } else {\r
194 *State = EfiUsbHcStateOperational;\r
195 }\r
196\r
197 gBS->RestoreTPL (OldTpl);\r
198\r
1c619535 199 DEBUG ((EFI_D_INFO, "EhcGetState: current state %d\n", *State));\r
913cb9dc 200 return EFI_SUCCESS;\r
201}\r
202\r
203\r
204/**\r
205 Sets the USB host controller to a specific state.\r
206\r
78c2ffb5 207 @param This This EFI_USB2_HC_PROTOCOL instance.\r
208 @param State The state of the host controller that will be set.\r
913cb9dc 209\r
78c2ffb5 210 @retval EFI_SUCCESS The USB host controller was successfully placed\r
211 in the state specified by State.\r
212 @retval EFI_INVALID_PARAMETER State is invalid.\r
213 @retval EFI_DEVICE_ERROR Failed to set the state due to device error.\r
913cb9dc 214\r
215**/\r
913cb9dc 216EFI_STATUS\r
217EFIAPI\r
218EhcSetState (\r
219 IN EFI_USB2_HC_PROTOCOL *This,\r
220 IN EFI_USB_HC_STATE State\r
221 )\r
222{\r
223 USB2_HC_DEV *Ehc;\r
224 EFI_TPL OldTpl;\r
225 EFI_STATUS Status;\r
226 EFI_USB_HC_STATE CurState;\r
227\r
228 Status = EhcGetState (This, &CurState);\r
229\r
230 if (EFI_ERROR (Status)) {\r
231 return EFI_DEVICE_ERROR;\r
232 }\r
233\r
234 if (CurState == State) {\r
235 return EFI_SUCCESS;\r
236 }\r
237\r
238 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
239 Ehc = EHC_FROM_THIS (This);\r
240\r
241 switch (State) {\r
242 case EfiUsbHcStateHalt:\r
41e8ff27 243 Status = EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
913cb9dc 244 break;\r
245\r
246 case EfiUsbHcStateOperational:\r
247 if (EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR)) {\r
248 Status = EFI_DEVICE_ERROR;\r
249 break;\r
250 }\r
251\r
41e8ff27 252 //\r
253 // Software must not write a one to this field unless the host controller\r
68246fa8 254 // is in the Halted state. Doing so will yield undefined results.\r
41e8ff27 255 // refers to Spec[EHCI1.0-2.3.1]\r
68246fa8 256 //\r
41e8ff27 257 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {\r
258 Status = EFI_DEVICE_ERROR;\r
259 break;\r
260 }\r
261\r
262 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);\r
913cb9dc 263 break;\r
264\r
265 case EfiUsbHcStateSuspend:\r
266 Status = EFI_UNSUPPORTED;\r
267 break;\r
268\r
269 default:\r
270 Status = EFI_INVALID_PARAMETER;\r
271 }\r
272\r
1c619535 273 DEBUG ((EFI_D_INFO, "EhcSetState: exit status %r\n", Status));\r
913cb9dc 274 gBS->RestoreTPL (OldTpl);\r
275 return Status;\r
276}\r
277\r
278\r
279/**\r
280 Retrieves the current status of a USB root hub port.\r
281\r
78c2ffb5 282 @param This This EFI_USB2_HC_PROTOCOL instance.\r
283 @param PortNumber The root hub port to retrieve the state from.\r
284 This value is zero-based.\r
285 @param PortStatus Variable to receive the port state.\r
913cb9dc 286\r
78c2ffb5 287 @retval EFI_SUCCESS The status of the USB root hub port specified.\r
288 by PortNumber was returned in PortStatus.\r
289 @retval EFI_INVALID_PARAMETER PortNumber is invalid.\r
290 @retval EFI_DEVICE_ERROR Can't read register.\r
913cb9dc 291\r
292**/\r
913cb9dc 293EFI_STATUS\r
294EFIAPI\r
295EhcGetRootHubPortStatus (\r
296 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
297 IN CONST UINT8 PortNumber,\r
298 OUT EFI_USB_PORT_STATUS *PortStatus\r
299 )\r
300{\r
301 USB2_HC_DEV *Ehc;\r
302 EFI_TPL OldTpl;\r
303 UINT32 Offset;\r
304 UINT32 State;\r
305 UINT32 TotalPort;\r
306 UINTN Index;\r
307 UINTN MapSize;\r
308 EFI_STATUS Status;\r
309\r
310 if (PortStatus == NULL) {\r
311 return EFI_INVALID_PARAMETER;\r
312 }\r
313\r
314 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
315\r
316 Ehc = EHC_FROM_THIS (This);\r
317 Status = EFI_SUCCESS;\r
318\r
319 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);\r
320\r
321 if (PortNumber >= TotalPort) {\r
322 Status = EFI_INVALID_PARAMETER;\r
323 goto ON_EXIT;\r
324 }\r
325\r
326 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));\r
327 PortStatus->PortStatus = 0;\r
328 PortStatus->PortChangeStatus = 0;\r
329\r
330 State = EhcReadOpReg (Ehc, Offset);\r
331\r
332 //\r
333 // Identify device speed. If in K state, it is low speed.\r
334 // If the port is enabled after reset, the device is of\r
335 // high speed. The USB bus driver should retrieve the actual\r
336 // port speed after reset.\r
337 //\r
338 if (EHC_BIT_IS_SET (State, PORTSC_LINESTATE_K)) {\r
339 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
340\r
341 } else if (EHC_BIT_IS_SET (State, PORTSC_ENABLED)) {\r
342 PortStatus->PortStatus |= USB_PORT_STAT_HIGH_SPEED;\r
343 }\r
344\r
345 //\r
346 // Convert the EHCI port/port change state to UEFI status\r
347 //\r
348 MapSize = sizeof (mUsbPortStateMap) / sizeof (USB_PORT_STATE_MAP);\r
349\r
350 for (Index = 0; Index < MapSize; Index++) {\r
351 if (EHC_BIT_IS_SET (State, mUsbPortStateMap[Index].HwState)) {\r
c52fa98c 352 PortStatus->PortStatus = (UINT16) (PortStatus->PortStatus | mUsbPortStateMap[Index].UefiState);\r
913cb9dc 353 }\r
354 }\r
355\r
356 MapSize = sizeof (mUsbPortChangeMap) / sizeof (USB_PORT_STATE_MAP);\r
357\r
358 for (Index = 0; Index < MapSize; Index++) {\r
359 if (EHC_BIT_IS_SET (State, mUsbPortChangeMap[Index].HwState)) {\r
c52fa98c 360 PortStatus->PortChangeStatus = (UINT16) (PortStatus->PortChangeStatus | mUsbPortChangeMap[Index].UefiState);\r
913cb9dc 361 }\r
362 }\r
363\r
364ON_EXIT:\r
365 gBS->RestoreTPL (OldTpl);\r
366 return Status;\r
367}\r
368\r
369\r
370/**\r
371 Sets a feature for the specified root hub port.\r
372\r
78c2ffb5 373 @param This This EFI_USB2_HC_PROTOCOL instance.\r
374 @param PortNumber Root hub port to set.\r
375 @param PortFeature Feature to set.\r
913cb9dc 376\r
78c2ffb5 377 @retval EFI_SUCCESS The feature specified by PortFeature was set.\r
378 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
379 @retval EFI_DEVICE_ERROR Can't read register.\r
913cb9dc 380\r
381**/\r
913cb9dc 382EFI_STATUS\r
383EFIAPI\r
384EhcSetRootHubPortFeature (\r
385 IN EFI_USB2_HC_PROTOCOL *This,\r
386 IN UINT8 PortNumber,\r
387 IN EFI_USB_PORT_FEATURE PortFeature\r
388 )\r
389{\r
390 USB2_HC_DEV *Ehc;\r
391 EFI_TPL OldTpl;\r
392 UINT32 Offset;\r
393 UINT32 State;\r
394 UINT32 TotalPort;\r
395 EFI_STATUS Status;\r
396\r
397 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
398 Ehc = EHC_FROM_THIS (This);\r
399 Status = EFI_SUCCESS;\r
400\r
401 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);\r
402\r
403 if (PortNumber >= TotalPort) {\r
404 Status = EFI_INVALID_PARAMETER;\r
405 goto ON_EXIT;\r
406 }\r
407\r
408 Offset = (UINT32) (EHC_PORT_STAT_OFFSET + (4 * PortNumber));\r
409 State = EhcReadOpReg (Ehc, Offset);\r
410\r
411 //\r
412 // Mask off the port status change bits, these bits are\r
413 // write clean bit\r
414 //\r
415 State &= ~PORTSC_CHANGE_MASK;\r
416\r
417 switch (PortFeature) {\r
418 case EfiUsbPortEnable:\r
419 //\r
420 // Sofeware can't set this bit, Port can only be enable by\r
421 // EHCI as a part of the reset and enable\r
422 //\r
423 State |= PORTSC_ENABLED;\r
424 EhcWriteOpReg (Ehc, Offset, State);\r
425 break;\r
426\r
427 case EfiUsbPortSuspend:\r
428 State |= PORTSC_SUSPEND;\r
429 EhcWriteOpReg (Ehc, Offset, State);\r
430 break;\r
431\r
432 case EfiUsbPortReset:\r
433 //\r
434 // Make sure Host Controller not halt before reset it\r
435 //\r
436 if (EhcIsHalt (Ehc)) {\r
41e8ff27 437 Status = EhcRunHC (Ehc, EHC_GENERIC_TIMEOUT);\r
913cb9dc 438\r
439 if (EFI_ERROR (Status)) {\r
1c619535 440 DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature :failed to start HC - %r\n", Status));\r
913cb9dc 441 break;\r
442 }\r
443 }\r
68246fa8 444\r
913cb9dc 445 //\r
446 // Set one to PortReset bit must also set zero to PortEnable bit\r
447 //\r
448 State |= PORTSC_RESET;\r
449 State &= ~PORTSC_ENABLED;\r
450 EhcWriteOpReg (Ehc, Offset, State);\r
451 break;\r
452\r
453 case EfiUsbPortPower:\r
454 //\r
455 // Not supported, ignore the operation\r
456 //\r
457 Status = EFI_SUCCESS;\r
458 break;\r
459\r
460 case EfiUsbPortOwner:\r
461 State |= PORTSC_OWNER;\r
462 EhcWriteOpReg (Ehc, Offset, State);\r
463 break;\r
464\r
465 default:\r
466 Status = EFI_INVALID_PARAMETER;\r
467 }\r
468\r
469ON_EXIT:\r
1c619535 470 DEBUG ((EFI_D_INFO, "EhcSetRootHubPortFeature: exit status %r\n", Status));\r
913cb9dc 471\r
472 gBS->RestoreTPL (OldTpl);\r
473 return Status;\r
474}\r
475\r
476\r
477/**\r
478 Clears a feature for the specified root hub port.\r
479\r
78c2ffb5 480 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
481 @param PortNumber Specifies the root hub port whose feature is\r
482 requested to be cleared.\r
483 @param PortFeature Indicates the feature selector associated with the\r
484 feature clear request.\r
913cb9dc 485\r
78c2ffb5 486 @retval EFI_SUCCESS The feature specified by PortFeature was cleared\r
487 for the USB root hub port specified by PortNumber.\r
488 @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid.\r
489 @retval EFI_DEVICE_ERROR Can't read register.\r
913cb9dc 490\r
491**/\r
913cb9dc 492EFI_STATUS\r
493EFIAPI\r
494EhcClearRootHubPortFeature (\r
495 IN EFI_USB2_HC_PROTOCOL *This,\r
496 IN UINT8 PortNumber,\r
497 IN EFI_USB_PORT_FEATURE PortFeature\r
498 )\r
499{\r
500 USB2_HC_DEV *Ehc;\r
501 EFI_TPL OldTpl;\r
502 UINT32 Offset;\r
503 UINT32 State;\r
504 UINT32 TotalPort;\r
505 EFI_STATUS Status;\r
506\r
507 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
508 Ehc = EHC_FROM_THIS (This);\r
509 Status = EFI_SUCCESS;\r
510\r
511 TotalPort = (Ehc->HcStructParams & HCSP_NPORTS);\r
512\r
513 if (PortNumber >= TotalPort) {\r
514 Status = EFI_INVALID_PARAMETER;\r
515 goto ON_EXIT;\r
516 }\r
517\r
518 Offset = EHC_PORT_STAT_OFFSET + (4 * PortNumber);\r
519 State = EhcReadOpReg (Ehc, Offset);\r
520 State &= ~PORTSC_CHANGE_MASK;\r
521\r
522 switch (PortFeature) {\r
523 case EfiUsbPortEnable:\r
524 //\r
525 // Clear PORT_ENABLE feature means disable port.\r
526 //\r
527 State &= ~PORTSC_ENABLED;\r
528 EhcWriteOpReg (Ehc, Offset, State);\r
529 break;\r
530\r
531 case EfiUsbPortSuspend:\r
532 //\r
533 // A write of zero to this bit is ignored by the host\r
534 // controller. The host controller will unconditionally\r
535 // set this bit to a zero when:\r
536 // 1. software sets the Forct Port Resume bit to a zero from a one.\r
537 // 2. software sets the Port Reset bit to a one frome a zero.\r
538 //\r
539 State &= ~PORSTSC_RESUME;\r
540 EhcWriteOpReg (Ehc, Offset, State);\r
541 break;\r
542\r
543 case EfiUsbPortReset:\r
544 //\r
545 // Clear PORT_RESET means clear the reset signal.\r
546 //\r
547 State &= ~PORTSC_RESET;\r
548 EhcWriteOpReg (Ehc, Offset, State);\r
549 break;\r
550\r
551 case EfiUsbPortOwner:\r
552 //\r
553 // Clear port owner means this port owned by EHC\r
554 //\r
555 State &= ~PORTSC_OWNER;\r
556 EhcWriteOpReg (Ehc, Offset, State);\r
557 break;\r
558\r
559 case EfiUsbPortConnectChange:\r
560 //\r
561 // Clear connect status change\r
562 //\r
563 State |= PORTSC_CONN_CHANGE;\r
564 EhcWriteOpReg (Ehc, Offset, State);\r
565 break;\r
566\r
567 case EfiUsbPortEnableChange:\r
568 //\r
569 // Clear enable status change\r
570 //\r
571 State |= PORTSC_ENABLE_CHANGE;\r
572 EhcWriteOpReg (Ehc, Offset, State);\r
573 break;\r
574\r
575 case EfiUsbPortOverCurrentChange:\r
576 //\r
577 // Clear PortOverCurrent change\r
578 //\r
579 State |= PORTSC_OVERCUR_CHANGE;\r
580 EhcWriteOpReg (Ehc, Offset, State);\r
581 break;\r
582\r
583 case EfiUsbPortPower:\r
584 case EfiUsbPortSuspendChange:\r
585 case EfiUsbPortResetChange:\r
586 //\r
587 // Not supported or not related operation\r
588 //\r
589 break;\r
590\r
591 default:\r
592 Status = EFI_INVALID_PARAMETER;\r
593 break;\r
594 }\r
595\r
596ON_EXIT:\r
1c619535 597 DEBUG ((EFI_D_INFO, "EhcClearRootHubPortFeature: exit status %r\n", Status));\r
913cb9dc 598 gBS->RestoreTPL (OldTpl);\r
599 return Status;\r
600}\r
601\r
602\r
603/**\r
604 Submits control transfer to a target USB device.\r
605\r
78c2ffb5 606 @param This This EFI_USB2_HC_PROTOCOL instance.\r
607 @param DeviceAddress The target device address.\r
608 @param DeviceSpeed Target device speed.\r
609 @param MaximumPacketLength Maximum packet size the default control transfer\r
610 endpoint is capable of sending or receiving.\r
611 @param Request USB device request to send.\r
612 @param TransferDirection Specifies the data direction for the data stage\r
613 @param Data Data buffer to be transmitted or received from USB\r
614 device.\r
615 @param DataLength The size (in bytes) of the data buffer.\r
616 @param TimeOut Indicates the maximum timeout, in millisecond.\r
617 @param Translator Transaction translator to be used by this device.\r
618 @param TransferResult Return the result of this control transfer.\r
619\r
620 @retval EFI_SUCCESS Transfer was completed successfully.\r
621 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resources.\r
622 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
623 @retval EFI_TIMEOUT Transfer failed due to timeout.\r
624 @retval EFI_DEVICE_ERROR Transfer failed due to host controller or device error.\r
913cb9dc 625\r
626**/\r
913cb9dc 627EFI_STATUS\r
628EFIAPI\r
629EhcControlTransfer (\r
630 IN EFI_USB2_HC_PROTOCOL *This,\r
631 IN UINT8 DeviceAddress,\r
632 IN UINT8 DeviceSpeed,\r
633 IN UINTN MaximumPacketLength,\r
634 IN EFI_USB_DEVICE_REQUEST *Request,\r
635 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
636 IN OUT VOID *Data,\r
637 IN OUT UINTN *DataLength,\r
638 IN UINTN TimeOut,\r
639 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
640 OUT UINT32 *TransferResult\r
641 )\r
642{\r
643 USB2_HC_DEV *Ehc;\r
644 URB *Urb;\r
645 EFI_TPL OldTpl;\r
646 UINT8 Endpoint;\r
647 EFI_STATUS Status;\r
648\r
649 //\r
650 // Validate parameters\r
651 //\r
652 if ((Request == NULL) || (TransferResult == NULL)) {\r
653 return EFI_INVALID_PARAMETER;\r
654 }\r
655\r
656 if ((TransferDirection != EfiUsbDataIn) &&\r
657 (TransferDirection != EfiUsbDataOut) &&\r
658 (TransferDirection != EfiUsbNoData)) {\r
659 return EFI_INVALID_PARAMETER;\r
660 }\r
661\r
662 if ((TransferDirection == EfiUsbNoData) &&\r
663 ((Data != NULL) || (*DataLength != 0))) {\r
664 return EFI_INVALID_PARAMETER;\r
665 }\r
666\r
667 if ((TransferDirection != EfiUsbNoData) &&\r
668 ((Data == NULL) || (*DataLength == 0))) {\r
669 return EFI_INVALID_PARAMETER;\r
670 }\r
671\r
672 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
673 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
674 return EFI_INVALID_PARAMETER;\r
675 }\r
676\r
677 if ((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) {\r
678 return EFI_INVALID_PARAMETER;\r
679 }\r
680\r
681 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
682 Ehc = EHC_FROM_THIS (This);\r
683\r
684 Status = EFI_DEVICE_ERROR;\r
685 *TransferResult = EFI_USB_ERR_SYSTEM;\r
686\r
687 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
1c619535 688 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: HC halted at entrance\n"));\r
913cb9dc 689\r
690 EhcAckAllInterrupt (Ehc);\r
691 goto ON_EXIT;\r
692 }\r
693\r
694 EhcAckAllInterrupt (Ehc);\r
695\r
696 //\r
697 // Create a new URB, insert it into the asynchronous\r
698 // schedule list, then poll the execution status.\r
699 //\r
700 //\r
701 // Encode the direction in address, although default control\r
702 // endpoint is bidirectional. EhcCreateUrb expects this\r
703 // combination of Ep addr and its direction.\r
704 //\r
c52fa98c 705 Endpoint = (UINT8) (0 | ((TransferDirection == EfiUsbDataIn) ? 0x80 : 0));\r
913cb9dc 706 Urb = EhcCreateUrb (\r
707 Ehc,\r
708 DeviceAddress,\r
709 Endpoint,\r
710 DeviceSpeed,\r
711 0,\r
712 MaximumPacketLength,\r
713 Translator,\r
714 EHC_CTRL_TRANSFER,\r
715 Request,\r
716 Data,\r
717 *DataLength,\r
718 NULL,\r
719 NULL,\r
720 1\r
721 );\r
722\r
723 if (Urb == NULL) {\r
1c619535 724 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: failed to create URB"));\r
913cb9dc 725\r
726 Status = EFI_OUT_OF_RESOURCES;\r
727 goto ON_EXIT;\r
728 }\r
729\r
730 EhcLinkQhToAsync (Ehc, Urb->Qh);\r
731 Status = EhcExecTransfer (Ehc, Urb, TimeOut);\r
732 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);\r
733\r
734 //\r
735 // Get the status from URB. The result is updated in EhcCheckUrbResult\r
736 // which is called by EhcExecTransfer\r
737 //\r
738 *TransferResult = Urb->Result;\r
739 *DataLength = Urb->Completed;\r
740\r
741 if (*TransferResult == EFI_USB_NOERROR) {\r
742 Status = EFI_SUCCESS;\r
743 }\r
744\r
745 EhcAckAllInterrupt (Ehc);\r
746 EhcFreeUrb (Ehc, Urb);\r
747\r
748ON_EXIT:\r
749 Ehc->PciIo->Flush (Ehc->PciIo);\r
750 gBS->RestoreTPL (OldTpl);\r
751\r
752 if (EFI_ERROR (Status)) {\r
1c619535 753 DEBUG ((EFI_D_ERROR, "EhcControlTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
913cb9dc 754 }\r
755\r
756 return Status;\r
757}\r
758\r
759\r
760/**\r
761 Submits bulk transfer to a bulk endpoint of a USB device.\r
762\r
78c2ffb5 763 @param This This EFI_USB2_HC_PROTOCOL instance.\r
764 @param DeviceAddress Target device address.\r
765 @param EndPointAddress Endpoint number and its direction in bit 7.\r
766 @param DeviceSpeed Device speed, Low speed device doesn't support bulk\r
767 transfer.\r
768 @param MaximumPacketLength Maximum packet size the endpoint is capable of\r
769 sending or receiving.\r
770 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
771 @param Data Array of pointers to the buffers of data to transmit\r
913cb9dc 772 from or receive into.\r
78c2ffb5 773 @param DataLength The lenght of the data buffer.\r
774 @param DataToggle On input, the initial data toggle for the transfer;\r
775 On output, it is updated to to next data toggle to\r
776 use of the subsequent bulk transfer.\r
777 @param TimeOut Indicates the maximum time, in millisecond, which\r
778 the transfer is allowed to complete.\r
779 @param Translator A pointr to the transaction translator data.\r
780 @param TransferResult A pointer to the detailed result information of the\r
781 bulk transfer.\r
782\r
783 @retval EFI_SUCCESS The transfer was completed successfully.\r
784 @retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.\r
785 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
786 @retval EFI_TIMEOUT The transfer failed due to timeout.\r
787 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.\r
913cb9dc 788\r
789**/\r
913cb9dc 790EFI_STATUS\r
791EFIAPI\r
792EhcBulkTransfer (\r
793 IN EFI_USB2_HC_PROTOCOL *This,\r
794 IN UINT8 DeviceAddress,\r
795 IN UINT8 EndPointAddress,\r
796 IN UINT8 DeviceSpeed,\r
797 IN UINTN MaximumPacketLength,\r
798 IN UINT8 DataBuffersNumber,\r
799 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
800 IN OUT UINTN *DataLength,\r
801 IN OUT UINT8 *DataToggle,\r
802 IN UINTN TimeOut,\r
803 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
804 OUT UINT32 *TransferResult\r
805 )\r
806{\r
807 USB2_HC_DEV *Ehc;\r
808 URB *Urb;\r
809 EFI_TPL OldTpl;\r
810 EFI_STATUS Status;\r
811\r
812 //\r
813 // Validate the parameters\r
814 //\r
815 if ((DataLength == NULL) || (*DataLength == 0) ||\r
816 (Data == NULL) || (Data[0] == NULL) || (TransferResult == NULL)) {\r
817 return EFI_INVALID_PARAMETER;\r
818 }\r
819\r
820 if ((*DataToggle != 0) && (*DataToggle != 1)) {\r
821 return EFI_INVALID_PARAMETER;\r
822 }\r
823\r
824 if ((DeviceSpeed == EFI_USB_SPEED_LOW) ||\r
825 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
826 ((EFI_USB_SPEED_HIGH == DeviceSpeed) && (MaximumPacketLength > 512))) {\r
827 return EFI_INVALID_PARAMETER;\r
828 }\r
829\r
830 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
831 Ehc = EHC_FROM_THIS (This);\r
832\r
833 *TransferResult = EFI_USB_ERR_SYSTEM;\r
834 Status = EFI_DEVICE_ERROR;\r
835\r
836 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
1c619535 837 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: HC is halted\n"));\r
913cb9dc 838\r
839 EhcAckAllInterrupt (Ehc);\r
840 goto ON_EXIT;\r
841 }\r
842\r
843 EhcAckAllInterrupt (Ehc);\r
844\r
845 //\r
846 // Create a new URB, insert it into the asynchronous\r
847 // schedule list, then poll the execution status.\r
848 //\r
849 Urb = EhcCreateUrb (\r
850 Ehc,\r
851 DeviceAddress,\r
852 EndPointAddress,\r
853 DeviceSpeed,\r
854 *DataToggle,\r
855 MaximumPacketLength,\r
856 Translator,\r
857 EHC_BULK_TRANSFER,\r
858 NULL,\r
859 Data[0],\r
860 *DataLength,\r
861 NULL,\r
862 NULL,\r
863 1\r
864 );\r
865\r
866 if (Urb == NULL) {\r
1c619535 867 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: failed to create URB\n"));\r
913cb9dc 868\r
869 Status = EFI_OUT_OF_RESOURCES;\r
870 goto ON_EXIT;\r
871 }\r
872\r
873 EhcLinkQhToAsync (Ehc, Urb->Qh);\r
874 Status = EhcExecTransfer (Ehc, Urb, TimeOut);\r
875 EhcUnlinkQhFromAsync (Ehc, Urb->Qh);\r
876\r
877 *TransferResult = Urb->Result;\r
878 *DataLength = Urb->Completed;\r
879 *DataToggle = Urb->DataToggle;\r
880\r
881 if (*TransferResult == EFI_USB_NOERROR) {\r
882 Status = EFI_SUCCESS;\r
883 }\r
884\r
885 EhcAckAllInterrupt (Ehc);\r
886 EhcFreeUrb (Ehc, Urb);\r
887\r
888ON_EXIT:\r
889 Ehc->PciIo->Flush (Ehc->PciIo);\r
890 gBS->RestoreTPL (OldTpl);\r
891\r
892 if (EFI_ERROR (Status)) {\r
1c619535 893 DEBUG ((EFI_D_ERROR, "EhcBulkTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
913cb9dc 894 }\r
895\r
896 return Status;\r
897}\r
898\r
899\r
900/**\r
901 Submits an asynchronous interrupt transfer to an\r
902 interrupt endpoint of a USB device.\r
903\r
78c2ffb5 904 @param This This EFI_USB2_HC_PROTOCOL instance.\r
905 @param DeviceAddress Target device address.\r
906 @param EndPointAddress Endpoint number and its direction encoded in bit 7\r
907 @param DeviceSpeed Indicates device speed.\r
908 @param MaximumPacketLength Maximum packet size the target endpoint is capable\r
909 @param IsNewTransfer If TRUE, to submit an new asynchronous interrupt\r
910 transfer If FALSE, to remove the specified\r
911 asynchronous interrupt.\r
912 @param DataToggle On input, the initial data toggle to use; on output,\r
913 it is updated to indicate the next data toggle.\r
914 @param PollingInterval The he interval, in milliseconds, that the transfer\r
915 is polled.\r
916 @param DataLength The length of data to receive at the rate specified\r
917 by PollingInterval.\r
918 @param Translator Transaction translator to use.\r
919 @param CallBackFunction Function to call at the rate specified by\r
920 PollingInterval.\r
921 @param Context Context to CallBackFunction.\r
922\r
923 @retval EFI_SUCCESS The request has been successfully submitted or canceled.\r
924 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
925 @retval EFI_OUT_OF_RESOURCES The request failed due to a lack of resources.\r
926 @retval EFI_DEVICE_ERROR The transfer failed due to host controller error.\r
913cb9dc 927\r
928**/\r
913cb9dc 929EFI_STATUS\r
930EFIAPI\r
931EhcAsyncInterruptTransfer (\r
932 IN EFI_USB2_HC_PROTOCOL * This,\r
933 IN UINT8 DeviceAddress,\r
934 IN UINT8 EndPointAddress,\r
935 IN UINT8 DeviceSpeed,\r
936 IN UINTN MaximumPacketLength,\r
937 IN BOOLEAN IsNewTransfer,\r
938 IN OUT UINT8 *DataToggle,\r
939 IN UINTN PollingInterval,\r
940 IN UINTN DataLength,\r
941 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,\r
942 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
943 IN VOID *Context OPTIONAL\r
944 )\r
945{\r
946 USB2_HC_DEV *Ehc;\r
947 URB *Urb;\r
948 EFI_TPL OldTpl;\r
949 EFI_STATUS Status;\r
950 UINT8 *Data;\r
951\r
952 //\r
953 // Validate parameters\r
954 //\r
955 if (!EHCI_IS_DATAIN (EndPointAddress)) {\r
956 return EFI_INVALID_PARAMETER;\r
957 }\r
958\r
959 if (IsNewTransfer) {\r
960 if (DataLength == 0) {\r
961 return EFI_INVALID_PARAMETER;\r
962 }\r
963\r
964 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
965 return EFI_INVALID_PARAMETER;\r
966 }\r
967\r
968 if ((PollingInterval > 255) || (PollingInterval < 1)) {\r
969 return EFI_INVALID_PARAMETER;\r
970 }\r
971 }\r
972\r
973 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
974 Ehc = EHC_FROM_THIS (This);\r
975\r
976 //\r
977 // Delete Async interrupt transfer request. DataToggle will return\r
978 // the next data toggle to use.\r
979 //\r
980 if (!IsNewTransfer) {\r
981 Status = EhciDelAsyncIntTransfer (Ehc, DeviceAddress, EndPointAddress, DataToggle);\r
982\r
1c619535 983 DEBUG ((EFI_D_INFO, "EhcAsyncInterruptTransfer: remove old transfer - %r\n", Status));\r
913cb9dc 984 goto ON_EXIT;\r
985 }\r
986\r
987 Status = EFI_SUCCESS;\r
988\r
989 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
1c619535 990 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: HC is halt\n"));\r
913cb9dc 991 EhcAckAllInterrupt (Ehc);\r
992\r
993 Status = EFI_DEVICE_ERROR;\r
994 goto ON_EXIT;\r
995 }\r
996\r
997 EhcAckAllInterrupt (Ehc);\r
998\r
999 Data = AllocatePool (DataLength);\r
1000\r
1001 if (Data == NULL) {\r
1c619535 1002 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to allocate buffer\n"));\r
913cb9dc 1003\r
1004 Status = EFI_OUT_OF_RESOURCES;\r
1005 goto ON_EXIT;\r
1006 }\r
1007\r
1008 Urb = EhcCreateUrb (\r
1009 Ehc,\r
1010 DeviceAddress,\r
1011 EndPointAddress,\r
1012 DeviceSpeed,\r
1013 *DataToggle,\r
1014 MaximumPacketLength,\r
1015 Translator,\r
1016 EHC_INT_TRANSFER_ASYNC,\r
1017 NULL,\r
1018 Data,\r
1019 DataLength,\r
1020 CallBackFunction,\r
1021 Context,\r
1022 PollingInterval\r
1023 );\r
1024\r
1025 if (Urb == NULL) {\r
1c619535 1026 DEBUG ((EFI_D_ERROR, "EhcAsyncInterruptTransfer: failed to create URB\n"));\r
913cb9dc 1027\r
1028 gBS->FreePool (Data);\r
1029 Status = EFI_OUT_OF_RESOURCES;\r
1030 goto ON_EXIT;\r
1031 }\r
1032\r
1033 //\r
1034 // New asynchronous transfer must inserted to the head.\r
1035 // Check the comments in EhcMoniteAsyncRequests\r
1036 //\r
1037 EhcLinkQhToPeriod (Ehc, Urb->Qh);\r
1038 InsertHeadList (&Ehc->AsyncIntTransfers, &Urb->UrbList);\r
1039\r
1040ON_EXIT:\r
1041 Ehc->PciIo->Flush (Ehc->PciIo);\r
1042 gBS->RestoreTPL (OldTpl);\r
1043\r
1044 return Status;\r
1045}\r
1046\r
1047\r
1048/**\r
1049 Submits synchronous interrupt transfer to an interrupt endpoint\r
1050 of a USB device.\r
1051\r
78c2ffb5 1052 @param This This EFI_USB2_HC_PROTOCOL instance.\r
1053 @param DeviceAddress Target device address.\r
1054 @param EndPointAddress Endpoint number and its direction encoded in bit 7\r
1055 @param DeviceSpeed Indicates device speed.\r
1056 @param MaximumPacketLength Maximum packet size the target endpoint is capable\r
1057 of sending or receiving.\r
1058 @param Data Buffer of data that will be transmitted to USB\r
1059 device or received from USB device.\r
1060 @param DataLength On input, the size, in bytes, of the data buffer; On\r
1061 output, the number of bytes transferred.\r
1062 @param DataToggle On input, the initial data toggle to use; on output,\r
1063 it is updated to indicate the next data toggle.\r
1064 @param TimeOut Maximum time, in second, to complete.\r
1065 @param Translator Transaction translator to use.\r
1066 @param TransferResult Variable to receive the transfer result.\r
1067\r
1068 @return EFI_SUCCESS The transfer was completed successfully.\r
1069 @return EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.\r
1070 @return EFI_INVALID_PARAMETER Some parameters are invalid.\r
1071 @return EFI_TIMEOUT The transfer failed due to timeout.\r
1072 @return EFI_DEVICE_ERROR The failed due to host controller or device error\r
913cb9dc 1073\r
1074**/\r
913cb9dc 1075EFI_STATUS\r
1076EFIAPI\r
1077EhcSyncInterruptTransfer (\r
1078 IN EFI_USB2_HC_PROTOCOL *This,\r
1079 IN UINT8 DeviceAddress,\r
1080 IN UINT8 EndPointAddress,\r
1081 IN UINT8 DeviceSpeed,\r
1082 IN UINTN MaximumPacketLength,\r
1083 IN OUT VOID *Data,\r
1084 IN OUT UINTN *DataLength,\r
1085 IN OUT UINT8 *DataToggle,\r
1086 IN UINTN TimeOut,\r
1087 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1088 OUT UINT32 *TransferResult\r
1089 )\r
1090{\r
1091 USB2_HC_DEV *Ehc;\r
1092 EFI_TPL OldTpl;\r
1093 URB *Urb;\r
1094 EFI_STATUS Status;\r
1095\r
1096 //\r
1097 // Validates parameters\r
1098 //\r
1099 if ((DataLength == NULL) || (*DataLength == 0) ||\r
1100 (Data == NULL) || (TransferResult == NULL)) {\r
1101 return EFI_INVALID_PARAMETER;\r
1102 }\r
1103\r
1104 if (!EHCI_IS_DATAIN (EndPointAddress)) {\r
1105 return EFI_INVALID_PARAMETER;\r
1106 }\r
1107\r
1108 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1109 return EFI_INVALID_PARAMETER;\r
1110 }\r
1111\r
1112 if (((DeviceSpeed == EFI_USB_SPEED_LOW) && (MaximumPacketLength != 8)) ||\r
1113 ((DeviceSpeed == EFI_USB_SPEED_FULL) && (MaximumPacketLength > 64)) ||\r
1114 ((DeviceSpeed == EFI_USB_SPEED_HIGH) && (MaximumPacketLength > 3072))) {\r
1115 return EFI_INVALID_PARAMETER;\r
1116 }\r
1117\r
1118 OldTpl = gBS->RaiseTPL (EHC_TPL);\r
1119 Ehc = EHC_FROM_THIS (This);\r
1120\r
1121 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1122 Status = EFI_DEVICE_ERROR;\r
1123\r
1124 if (EhcIsHalt (Ehc) || EhcIsSysError (Ehc)) {\r
1c619535 1125 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: HC is halt\n"));\r
913cb9dc 1126\r
1127 EhcAckAllInterrupt (Ehc);\r
1128 goto ON_EXIT;\r
1129 }\r
1130\r
1131 EhcAckAllInterrupt (Ehc);\r
1132\r
1133 Urb = EhcCreateUrb (\r
1134 Ehc,\r
1135 DeviceAddress,\r
1136 EndPointAddress,\r
1137 DeviceSpeed,\r
1138 *DataToggle,\r
1139 MaximumPacketLength,\r
1140 Translator,\r
1141 EHC_INT_TRANSFER_SYNC,\r
1142 NULL,\r
1143 Data,\r
1144 *DataLength,\r
1145 NULL,\r
1146 NULL,\r
1147 1\r
1148 );\r
1149\r
1150 if (Urb == NULL) {\r
1c619535 1151 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: failed to create URB\n"));\r
913cb9dc 1152\r
1153 Status = EFI_OUT_OF_RESOURCES;\r
1154 goto ON_EXIT;\r
1155 }\r
1156\r
1157 EhcLinkQhToPeriod (Ehc, Urb->Qh);\r
1158 Status = EhcExecTransfer (Ehc, Urb, TimeOut);\r
1159 EhcUnlinkQhFromPeriod (Ehc, Urb->Qh);\r
1160\r
1161 *TransferResult = Urb->Result;\r
1162 *DataLength = Urb->Completed;\r
1163 *DataToggle = Urb->DataToggle;\r
1164\r
1165 if (*TransferResult == EFI_USB_NOERROR) {\r
1166 Status = EFI_SUCCESS;\r
1167 }\r
1168\r
1169ON_EXIT:\r
1170 Ehc->PciIo->Flush (Ehc->PciIo);\r
1171 gBS->RestoreTPL (OldTpl);\r
1172\r
1173 if (EFI_ERROR (Status)) {\r
1c619535 1174 DEBUG ((EFI_D_ERROR, "EhcSyncInterruptTransfer: error - %r, transfer - %x\n", Status, *TransferResult));\r
913cb9dc 1175 }\r
1176\r
1177 return Status;\r
1178}\r
1179\r
1180\r
1181/**\r
1182 Submits isochronous transfer to a target USB device.\r
1183\r
1184 @param This This EFI_USB2_HC_PROTOCOL instance.\r
78c2ffb5 1185 @param DeviceAddress Target device address.\r
1186 @param EndPointAddress End point address with its direction.\r
913cb9dc 1187 @param DeviceSpeed Device speed, Low speed device doesn't support this\r
1188 type.\r
1189 @param MaximumPacketLength Maximum packet size that the endpoint is capable of\r
1190 sending or receiving.\r
1191 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1192 @param Data Array of pointers to the buffers of data that will\r
1193 be transmitted to USB device or received from USB\r
1194 device.\r
78c2ffb5 1195 @param DataLength The size, in bytes, of the data buffer.\r
913cb9dc 1196 @param Translator Transaction translator to use.\r
78c2ffb5 1197 @param TransferResult Variable to receive the transfer result.\r
913cb9dc 1198\r
78c2ffb5 1199 @return EFI_UNSUPPORTED Isochronous transfer is unsupported.\r
913cb9dc 1200\r
1201**/\r
913cb9dc 1202EFI_STATUS\r
1203EFIAPI\r
1204EhcIsochronousTransfer (\r
1205 IN EFI_USB2_HC_PROTOCOL *This,\r
1206 IN UINT8 DeviceAddress,\r
1207 IN UINT8 EndPointAddress,\r
1208 IN UINT8 DeviceSpeed,\r
1209 IN UINTN MaximumPacketLength,\r
1210 IN UINT8 DataBuffersNumber,\r
1211 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1212 IN UINTN DataLength,\r
1213 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1214 OUT UINT32 *TransferResult\r
1215 )\r
1216{\r
1217 return EFI_UNSUPPORTED;\r
1218}\r
1219\r
1220\r
1221/**\r
1222 Submits Async isochronous transfer to a target USB device.\r
1223\r
1224 @param This This EFI_USB2_HC_PROTOCOL instance.\r
78c2ffb5 1225 @param DeviceAddress Target device address.\r
1226 @param EndPointAddress End point address with its direction.\r
913cb9dc 1227 @param DeviceSpeed Device speed, Low speed device doesn't support this\r
1228 type.\r
1229 @param MaximumPacketLength Maximum packet size that the endpoint is capable of\r
1230 sending or receiving.\r
1231 @param DataBuffersNumber Number of data buffers prepared for the transfer.\r
1232 @param Data Array of pointers to the buffers of data that will\r
1233 be transmitted to USB device or received from USB\r
1234 device.\r
78c2ffb5 1235 @param DataLength The size, in bytes, of the data buffer.\r
913cb9dc 1236 @param Translator Transaction translator to use.\r
78c2ffb5 1237 @param IsochronousCallBack Function to be called when the transfer complete.\r
913cb9dc 1238 @param Context Context passed to the call back function as\r
78c2ffb5 1239 parameter.\r
913cb9dc 1240\r
78c2ffb5 1241 @return EFI_UNSUPPORTED Isochronous transfer isn't supported.\r
913cb9dc 1242\r
1243**/\r
913cb9dc 1244EFI_STATUS\r
1245EFIAPI\r
1246EhcAsyncIsochronousTransfer (\r
1247 IN EFI_USB2_HC_PROTOCOL *This,\r
1248 IN UINT8 DeviceAddress,\r
1249 IN UINT8 EndPointAddress,\r
1250 IN UINT8 DeviceSpeed,\r
1251 IN UINTN MaximumPacketLength,\r
1252 IN UINT8 DataBuffersNumber,\r
1253 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1254 IN UINTN DataLength,\r
1255 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1256 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1257 IN VOID *Context\r
1258 )\r
1259{\r
1260 return EFI_UNSUPPORTED;\r
1261}\r
1262\r
78c2ffb5 1263/**\r
1264 Entry point for EFI drivers.\r
1265\r
1266 @param ImageHandle EFI_HANDLE.\r
1267 @param SystemTable EFI_SYSTEM_TABLE.\r
1268\r
1269 @return EFI_SUCCESS Success.\r
1270 EFI_DEVICE_ERROR Fail.\r
1271\r
1272**/\r
913cb9dc 1273EFI_STATUS\r
1274EFIAPI\r
1275EhcDriverEntryPoint (\r
1276 IN EFI_HANDLE ImageHandle,\r
1277 IN EFI_SYSTEM_TABLE *SystemTable\r
1278 )\r
913cb9dc 1279{\r
f527bce3 1280 return EfiLibInstallDriverBindingComponentName2 (\r
913cb9dc 1281 ImageHandle,\r
1282 SystemTable,\r
1283 &gEhciDriverBinding,\r
1284 ImageHandle,\r
1285 &gEhciComponentName,\r
f527bce3 1286 &gEhciComponentName2\r
913cb9dc 1287 );\r
1288}\r
1289\r
1290\r
1291/**\r
1292 Test to see if this driver supports ControllerHandle. Any\r
1293 ControllerHandle that has Usb2HcProtocol installed will\r
1294 be supported.\r
1295\r
1296 @param This Protocol instance pointer.\r
78c2ffb5 1297 @param Controller Handle of device to test.\r
1298 @param RemainingDevicePath Not used.\r
913cb9dc 1299\r
78c2ffb5 1300 @return EFI_SUCCESS This driver supports this device.\r
1301 @return EFI_UNSUPPORTED This driver does not support this device.\r
913cb9dc 1302\r
1303**/\r
1304EFI_STATUS\r
1305EFIAPI\r
1306EhcDriverBindingSupported (\r
1307 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1308 IN EFI_HANDLE Controller,\r
1309 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1310 )\r
1311{\r
1312 EFI_STATUS Status;\r
1313 EFI_PCI_IO_PROTOCOL *PciIo;\r
1314 USB_CLASSC UsbClassCReg;\r
1315\r
1316 //\r
1317 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1318 //\r
1319 Status = gBS->OpenProtocol (\r
1320 Controller,\r
1321 &gEfiPciIoProtocolGuid,\r
c52fa98c 1322 (VOID **) &PciIo,\r
913cb9dc 1323 This->DriverBindingHandle,\r
1324 Controller,\r
1325 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1326 );\r
1327\r
1328 if (EFI_ERROR (Status)) {\r
1329 return EFI_UNSUPPORTED;\r
1330 }\r
1331\r
1332 Status = PciIo->Pci.Read (\r
1333 PciIo,\r
1334 EfiPciIoWidthUint8,\r
1335 EHC_PCI_CLASSC,\r
1336 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1337 &UsbClassCReg\r
1338 );\r
1339\r
1340 if (EFI_ERROR (Status)) {\r
1341 Status = EFI_UNSUPPORTED;\r
1342 goto ON_EXIT;\r
1343 }\r
1344\r
1345 //\r
1346 // Test whether the controller belongs to Ehci type\r
1347 //\r
1348 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1349 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1350 (UsbClassCReg.PI != EHC_PCI_CLASSC_PI)) {\r
1351\r
1352 Status = EFI_UNSUPPORTED;\r
1353 }\r
1354\r
1355ON_EXIT:\r
1356 gBS->CloseProtocol (\r
1357 Controller,\r
1358 &gEfiPciIoProtocolGuid,\r
1359 This->DriverBindingHandle,\r
1360 Controller\r
1361 );\r
1362\r
1363 return Status;\r
1364}\r
1365\r
1366\r
1367/**\r
78c2ffb5 1368 Create and initialize a USB2_HC_DEV.\r
913cb9dc 1369\r
78c2ffb5 1370 @param PciIo The PciIo on this device.\r
1371 @param OriginalPciAttributes Original PCI attributes.\r
913cb9dc 1372\r
78c2ffb5 1373 @return The allocated and initialized USB2_HC_DEV structure if created,\r
1374 otherwise NULL.\r
913cb9dc 1375\r
1376**/\r
913cb9dc 1377USB2_HC_DEV *\r
1378EhcCreateUsb2Hc (\r
68246fa8 1379 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
1380 IN UINT64 OriginalPciAttributes\r
913cb9dc 1381 )\r
1382{\r
1383 USB2_HC_DEV *Ehc;\r
1384 EFI_STATUS Status;\r
1385\r
1386 Ehc = AllocateZeroPool (sizeof (USB2_HC_DEV));\r
1387\r
1388 if (Ehc == NULL) {\r
1389 return NULL;\r
1390 }\r
1391\r
1392 //\r
1393 // Init EFI_USB2_HC_PROTOCOL interface and private data structure\r
1394 //\r
1395 Ehc->Signature = USB2_HC_DEV_SIGNATURE;\r
1396\r
1397 Ehc->Usb2Hc.GetCapability = EhcGetCapability;\r
1398 Ehc->Usb2Hc.Reset = EhcReset;\r
1399 Ehc->Usb2Hc.GetState = EhcGetState;\r
1400 Ehc->Usb2Hc.SetState = EhcSetState;\r
1401 Ehc->Usb2Hc.ControlTransfer = EhcControlTransfer;\r
1402 Ehc->Usb2Hc.BulkTransfer = EhcBulkTransfer;\r
1403 Ehc->Usb2Hc.AsyncInterruptTransfer = EhcAsyncInterruptTransfer;\r
1404 Ehc->Usb2Hc.SyncInterruptTransfer = EhcSyncInterruptTransfer;\r
1405 Ehc->Usb2Hc.IsochronousTransfer = EhcIsochronousTransfer;\r
1406 Ehc->Usb2Hc.AsyncIsochronousTransfer = EhcAsyncIsochronousTransfer;\r
1407 Ehc->Usb2Hc.GetRootHubPortStatus = EhcGetRootHubPortStatus;\r
1408 Ehc->Usb2Hc.SetRootHubPortFeature = EhcSetRootHubPortFeature;\r
1409 Ehc->Usb2Hc.ClearRootHubPortFeature = EhcClearRootHubPortFeature;\r
b4c24e2d 1410 Ehc->Usb2Hc.MajorRevision = 0x2;\r
1411 Ehc->Usb2Hc.MinorRevision = 0x0;\r
913cb9dc 1412\r
68246fa8 1413 Ehc->PciIo = PciIo;\r
1414 Ehc->OriginalPciAttributes = OriginalPciAttributes;\r
913cb9dc 1415\r
1416 InitializeListHead (&Ehc->AsyncIntTransfers);\r
1417\r
1418 Ehc->HcStructParams = EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET);\r
1419 Ehc->HcCapParams = EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET);\r
1420 Ehc->CapLen = EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET) & 0x0FF;\r
1421\r
1c619535 1422 DEBUG ((EFI_D_INFO, "EhcCreateUsb2Hc: capability length %d\n", Ehc->CapLen));\r
913cb9dc 1423\r
1424 //\r
1425 // Create AsyncRequest Polling Timer\r
1426 //\r
1427 Status = gBS->CreateEvent (\r
1428 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
1429 TPL_CALLBACK,\r
1430 EhcMoniteAsyncRequests,\r
1431 Ehc,\r
1432 &Ehc->PollTimer\r
1433 );\r
1434\r
1435 if (EFI_ERROR (Status)) {\r
1436 gBS->FreePool (Ehc);\r
1437 return NULL;\r
1438 }\r
1439\r
1440 return Ehc;\r
1441}\r
1442\r
1443\r
1444/**\r
78c2ffb5 1445 Starting the Usb EHCI Driver.\r
913cb9dc 1446\r
1447 @param This Protocol instance pointer.\r
78c2ffb5 1448 @param Controller Handle of device to test.\r
1449 @param RemainingDevicePath Not used.\r
913cb9dc 1450\r
78c2ffb5 1451 @return EFI_SUCCESS supports this device.\r
1452 @return EFI_UNSUPPORTED do not support this device.\r
1453 @return EFI_DEVICE_ERROR cannot be started due to device Error.\r
1454 @return EFI_OUT_OF_RESOURCES cannot allocate resources.\r
913cb9dc 1455\r
1456**/\r
1457EFI_STATUS\r
1458EFIAPI\r
1459EhcDriverBindingStart (\r
1460 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1461 IN EFI_HANDLE Controller,\r
1462 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1463 )\r
1464{\r
1465 EFI_STATUS Status;\r
1466 USB2_HC_DEV *Ehc;\r
1467 EFI_PCI_IO_PROTOCOL *PciIo;\r
96f6af14 1468 UINT64 Supports;\r
68246fa8 1469 UINT64 OriginalPciAttributes;\r
6a6d955c 1470 BOOLEAN PciAttributesSaved;\r
913cb9dc 1471\r
1472 //\r
1473 // Open the PciIo Protocol, then enable the USB host controller\r
1474 //\r
1475 Status = gBS->OpenProtocol (\r
1476 Controller,\r
1477 &gEfiPciIoProtocolGuid,\r
c52fa98c 1478 (VOID **) &PciIo,\r
913cb9dc 1479 This->DriverBindingHandle,\r
1480 Controller,\r
1481 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1482 );\r
1483\r
1484 if (EFI_ERROR (Status)) {\r
1c619535 1485 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to open PCI_IO\n"));\r
913cb9dc 1486 return EFI_DEVICE_ERROR;\r
1487 }\r
1488\r
6a6d955c 1489 PciAttributesSaved = FALSE;\r
68246fa8 1490 //\r
1491 // Save original PCI attributes\r
1492 //\r
1493 Status = PciIo->Attributes (\r
1494 PciIo,\r
1495 EfiPciIoAttributeOperationGet,\r
1496 0,\r
1497 &OriginalPciAttributes\r
1498 );\r
1499\r
1500 if (EFI_ERROR (Status)) {\r
6a6d955c 1501 goto CLOSE_PCIIO;\r
68246fa8 1502 }\r
6a6d955c 1503 PciAttributesSaved = TRUE;\r
68246fa8 1504\r
913cb9dc 1505 Status = PciIo->Attributes (\r
1506 PciIo,\r
96f6af14
LG
1507 EfiPciIoAttributeOperationSupported,\r
1508 0,\r
1509 &Supports\r
913cb9dc 1510 );\r
96f6af14
LG
1511 if (!EFI_ERROR (Status)) {\r
1512 Supports &= EFI_PCI_DEVICE_ENABLE;\r
1513 Status = PciIo->Attributes (\r
1514 PciIo,\r
1515 EfiPciIoAttributeOperationEnable,\r
1516 Supports,\r
1517 NULL\r
1518 );\r
1519 }\r
913cb9dc 1520\r
1521 if (EFI_ERROR (Status)) {\r
1c619535 1522 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to enable controller\n"));\r
913cb9dc 1523 goto CLOSE_PCIIO;\r
1524 }\r
1525\r
1526 //\r
1527 // Create then install USB2_HC_PROTOCOL\r
1528 //\r
68246fa8 1529 Ehc = EhcCreateUsb2Hc (PciIo, OriginalPciAttributes);\r
913cb9dc 1530\r
1531 if (Ehc == NULL) {\r
1c619535 1532 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to create USB2_HC\n"));\r
913cb9dc 1533\r
1534 Status = EFI_OUT_OF_RESOURCES;\r
1535 goto CLOSE_PCIIO;\r
1536 }\r
1537\r
1538 Status = gBS->InstallProtocolInterface (\r
1539 &Controller,\r
1540 &gEfiUsb2HcProtocolGuid,\r
1541 EFI_NATIVE_INTERFACE,\r
1542 &Ehc->Usb2Hc\r
1543 );\r
1544\r
1545 if (EFI_ERROR (Status)) {\r
1c619535 1546 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to install USB2_HC Protocol\n"));\r
913cb9dc 1547 goto FREE_POOL;\r
1548 }\r
1549\r
1550 //\r
1551 // Robustnesss improvement such as for UoL\r
f0a83bb3 1552 // Default is not required.\r
913cb9dc 1553 //\r
cc582cff 1554 if (FeaturePcdGet (PcdTurnOffUsbLegacySupport)) {\r
dd4047a5 1555 EhcClearLegacySupport (Ehc);\r
1556 }\r
41e8ff27 1557 EhcResetHC (Ehc, EHC_RESET_TIMEOUT);\r
913cb9dc 1558\r
1559 Status = EhcInitHC (Ehc);\r
1560\r
1561 if (EFI_ERROR (Status)) {\r
1c619535 1562 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to init host controller\n"));\r
913cb9dc 1563 goto UNINSTALL_USBHC;\r
1564 }\r
1565\r
1566 //\r
1567 // Start the asynchronous interrupt monitor\r
1568 //\r
41e8ff27 1569 Status = gBS->SetTimer (Ehc->PollTimer, TimerPeriodic, EHC_ASYNC_POLL_INTERVAL);\r
913cb9dc 1570\r
1571 if (EFI_ERROR (Status)) {\r
1c619535 1572 DEBUG ((EFI_D_ERROR, "EhcDriverBindingStart: failed to start async interrupt monitor\n"));\r
913cb9dc 1573\r
41e8ff27 1574 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
913cb9dc 1575 goto UNINSTALL_USBHC;\r
1576 }\r
1577\r
1578 //\r
1579 // Install the component name protocol, don't fail the start\r
1580 // because of something for display.\r
1581 //\r
f527bce3 1582 AddUnicodeString2 (\r
913cb9dc 1583 "eng",\r
1584 gEhciComponentName.SupportedLanguages,\r
1585 &Ehc->ControllerNameTable,\r
f527bce3 1586 L"Enhanced Host Controller (USB 2.0)",\r
1587 TRUE\r
913cb9dc 1588 );\r
f527bce3 1589 AddUnicodeString2 (\r
1590 "en",\r
1591 gEhciComponentName2.SupportedLanguages,\r
1592 &Ehc->ControllerNameTable,\r
1593 L"Enhanced Host Controller (USB 2.0)",\r
1594 FALSE\r
1595 );\r
1596\r
913cb9dc 1597\r
0e549d5b 1598 DEBUG ((EFI_D_INFO, "EhcDriverBindingStart: EHCI started for controller @ %p\n", Controller));\r
913cb9dc 1599 return EFI_SUCCESS;\r
1600\r
1601UNINSTALL_USBHC:\r
1602 gBS->UninstallProtocolInterface (\r
1603 Controller,\r
1604 &gEfiUsb2HcProtocolGuid,\r
1605 &Ehc->Usb2Hc\r
1606 );\r
1607\r
1608FREE_POOL:\r
1609 EhcFreeSched (Ehc);\r
1610 gBS->CloseEvent (Ehc->PollTimer);\r
1611 gBS->FreePool (Ehc);\r
1612\r
1613CLOSE_PCIIO:\r
a92d4e8a 1614 if (PciAttributesSaved) {\r
6a6d955c 1615 //\r
1616 // Restore original PCI attributes\r
1617 //\r
1618 PciIo->Attributes (\r
1619 PciIo,\r
1620 EfiPciIoAttributeOperationSet,\r
1621 OriginalPciAttributes,\r
1622 NULL\r
1623 );\r
1624 }\r
68246fa8 1625\r
913cb9dc 1626 gBS->CloseProtocol (\r
1627 Controller,\r
1628 &gEfiPciIoProtocolGuid,\r
1629 This->DriverBindingHandle,\r
1630 Controller\r
1631 );\r
1632\r
1633 return Status;\r
1634}\r
1635\r
1636\r
1637/**\r
1638 Stop this driver on ControllerHandle. Support stoping any child handles\r
1639 created by this driver.\r
1640\r
1641 @param This Protocol instance pointer.\r
78c2ffb5 1642 @param Controller Handle of device to stop driver on.\r
1643 @param NumberOfChildren Number of Children in the ChildHandleBuffer.\r
913cb9dc 1644 @param ChildHandleBuffer List of handles for the children we need to stop.\r
1645\r
78c2ffb5 1646 @return EFI_SUCCESS Success.\r
1647 @return EFI_DEVICE_ERROR Fail.\r
913cb9dc 1648\r
1649**/\r
1650EFI_STATUS\r
1651EFIAPI\r
1652EhcDriverBindingStop (\r
1653 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1654 IN EFI_HANDLE Controller,\r
1655 IN UINTN NumberOfChildren,\r
1656 IN EFI_HANDLE *ChildHandleBuffer\r
1657 )\r
1658{\r
1659 EFI_STATUS Status;\r
1660 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
1661 EFI_PCI_IO_PROTOCOL *PciIo;\r
1662 USB2_HC_DEV *Ehc;\r
1663\r
1664 //\r
1665 // Test whether the Controller handler passed in is a valid\r
1666 // Usb controller handle that should be supported, if not,\r
1667 // return the error status directly\r
1668 //\r
1669 Status = gBS->OpenProtocol (\r
1670 Controller,\r
1671 &gEfiUsb2HcProtocolGuid,\r
c52fa98c 1672 (VOID **) &Usb2Hc,\r
913cb9dc 1673 This->DriverBindingHandle,\r
1674 Controller,\r
1675 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1676 );\r
1677\r
1678 if (EFI_ERROR (Status)) {\r
1679 return Status;\r
1680 }\r
1681\r
1682 Ehc = EHC_FROM_THIS (Usb2Hc);\r
1683 PciIo = Ehc->PciIo;\r
1684\r
1685 //\r
1686 // Stop AsyncRequest Polling timer then stop the EHCI driver\r
1687 // and uninstall the EHCI protocl.\r
1688 //\r
41e8ff27 1689 gBS->SetTimer (Ehc->PollTimer, TimerCancel, EHC_ASYNC_POLL_INTERVAL);\r
1690 EhcHaltHC (Ehc, EHC_GENERIC_TIMEOUT);\r
913cb9dc 1691\r
1692 Status = gBS->UninstallProtocolInterface (\r
1693 Controller,\r
1694 &gEfiUsb2HcProtocolGuid,\r
1695 Usb2Hc\r
1696 );\r
1697\r
1698 if (EFI_ERROR (Status)) {\r
1699 return Status;\r
1700 }\r
1701\r
1702 if (Ehc->PollTimer != NULL) {\r
1703 gBS->CloseEvent (Ehc->PollTimer);\r
1704 }\r
1705\r
1706 EhcFreeSched (Ehc);\r
1707\r
78c2ffb5 1708 if (Ehc->ControllerNameTable != NULL) {\r
913cb9dc 1709 FreeUnicodeStringTable (Ehc->ControllerNameTable);\r
1710 }\r
1711\r
1712 //\r
68246fa8 1713 // Restore original PCI attributes\r
913cb9dc 1714 //\r
68246fa8 1715 PciIo->Attributes (\r
1716 PciIo,\r
1717 EfiPciIoAttributeOperationSet,\r
1718 Ehc->OriginalPciAttributes,\r
1719 NULL\r
1720 );\r
913cb9dc 1721\r
1722 gBS->CloseProtocol (\r
1723 Controller,\r
1724 &gEfiPciIoProtocolGuid,\r
1725 This->DriverBindingHandle,\r
1726 Controller\r
1727 );\r
1728\r
68246fa8 1729 FreePool (Ehc);\r
1730\r
96f6af14 1731 return EFI_SUCCESS;\r
913cb9dc 1732}\r
1733\r
1734EFI_DRIVER_BINDING_PROTOCOL\r
1735gEhciDriverBinding = {\r
1736 EhcDriverBindingSupported,\r
1737 EhcDriverBindingStart,\r
1738 EhcDriverBindingStop,\r
1739 0x10,\r
1740 NULL,\r
1741 NULL\r
1742};\r