]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbHub.c
MdeModulePkg UsbBusDxe: Remove redundant functions
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbHub.c
CommitLineData
e237e7ae 1/** @file\r
2\r
8616fc4c 3 Unified interface for RootHub and Hub.\r
4\r
d1102dba 5Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 6This program and the accompanying materials\r
e237e7ae 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
e237e7ae 14**/\r
15\r
16#include "UsbBus.h"\r
17\r
aa79b0b3 18//\r
19// Array that maps the change bit to feature value which is\r
20// used to clear these change bit. USB HUB API will clear\r
21// these change bit automatically. For non-root hub, these\r
22// bits determine whether hub will report the port in changed\r
23// bit maps.\r
24//\r
92870c98 25USB_CHANGE_FEATURE_MAP mHubFeatureMap[] = {\r
aa79b0b3 26 {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},\r
27 {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},\r
28 {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},\r
29 {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},\r
92870c98 30 {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange}\r
aa79b0b3 31};\r
32\r
92870c98 33USB_CHANGE_FEATURE_MAP mRootHubFeatureMap[] = {\r
aa79b0b3 34 {USB_PORT_STAT_C_CONNECTION, EfiUsbPortConnectChange},\r
35 {USB_PORT_STAT_C_ENABLE, EfiUsbPortEnableChange},\r
36 {USB_PORT_STAT_C_SUSPEND, EfiUsbPortSuspendChange},\r
37 {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},\r
38 {USB_PORT_STAT_C_RESET, EfiUsbPortResetChange},\r
39};\r
40\r
e237e7ae 41//\r
42// USB hub class specific requests. Although USB hub\r
43// is related to an interface, these requests are sent\r
44// to the control endpoint of the device.\r
45//\r
92870c98 46/**\r
47 USB hub control transfer to set the hub depth.\r
48\r
49 @param HubDev The device of the hub.\r
50 @param Depth The depth to set.\r
51\r
52 @retval EFI_SUCCESS Depth of the hub is set.\r
53 @retval Others Failed to set the depth.\r
54\r
55**/\r
56EFI_STATUS\r
57UsbHubCtrlSetHubDepth (\r
58 IN USB_DEVICE *HubDev,\r
59 IN UINT16 Depth\r
60 )\r
61{\r
62 EFI_STATUS Status;\r
e237e7ae 63\r
92870c98 64 Status = UsbCtrlRequest (\r
65 HubDev,\r
66 EfiUsbNoData,\r
67 USB_REQ_TYPE_CLASS,\r
68 USB_HUB_TARGET_HUB,\r
69 USB_HUB_REQ_SET_DEPTH,\r
70 Depth,\r
71 0,\r
72 NULL,\r
73 0\r
74 );\r
75\r
76 return Status;\r
77}\r
e237e7ae 78\r
79/**\r
8616fc4c 80 USB hub control transfer to clear the hub feature.\r
e237e7ae 81\r
8616fc4c 82 @param HubDev The device of the hub.\r
83 @param Feature The feature to clear.\r
e237e7ae 84\r
8616fc4c 85 @retval EFI_SUCCESS Feature of the hub is cleared.\r
86 @retval Others Failed to clear the feature.\r
e237e7ae 87\r
88**/\r
e237e7ae 89EFI_STATUS\r
90UsbHubCtrlClearHubFeature (\r
91 IN USB_DEVICE *HubDev,\r
92 IN UINT16 Feature\r
93 )\r
94{\r
95 EFI_STATUS Status;\r
96\r
97 Status = UsbCtrlRequest (\r
98 HubDev,\r
99 EfiUsbNoData,\r
100 USB_REQ_TYPE_CLASS,\r
101 USB_HUB_TARGET_HUB,\r
102 USB_HUB_REQ_CLEAR_FEATURE,\r
103 Feature,\r
104 0,\r
105 NULL,\r
106 0\r
107 );\r
108\r
109 return Status;\r
110}\r
111\r
112\r
113/**\r
8616fc4c 114 Clear the feature of the device's port.\r
e237e7ae 115\r
8616fc4c 116 @param HubDev The hub device.\r
117 @param Port The port to clear feature.\r
118 @param Feature The feature to clear.\r
e237e7ae 119\r
120 @retval EFI_SUCCESS The feature of the port is cleared.\r
121 @retval Others Failed to clear the feature.\r
122\r
123**/\r
e237e7ae 124EFI_STATUS\r
125UsbHubCtrlClearPortFeature (\r
126 IN USB_DEVICE *HubDev,\r
127 IN UINT8 Port,\r
128 IN UINT16 Feature\r
129 )\r
130{\r
131 EFI_STATUS Status;\r
132\r
133 //\r
134 // In USB bus, all the port index starts from 0. But HUB\r
135 // indexes its port from 1. So, port number is added one.\r
136 //\r
137 Status = UsbCtrlRequest (\r
138 HubDev,\r
139 EfiUsbNoData,\r
140 USB_REQ_TYPE_CLASS,\r
141 USB_HUB_TARGET_PORT,\r
142 USB_HUB_REQ_CLEAR_FEATURE,\r
143 Feature,\r
c52fa98c 144 (UINT16) (Port + 1),\r
e237e7ae 145 NULL,\r
146 0\r
147 );\r
148\r
149 return Status;\r
150}\r
151\r
152\r
e237e7ae 153/**\r
154 Clear the transaction translate buffer if full/low\r
155 speed control/bulk transfer failed and the transfer\r
156 uses this hub as translator.Remember to clear the TT\r
157 buffer of transaction translator, not that of the\r
158 parent.\r
159\r
8616fc4c 160 @param HubDev The hub device.\r
161 @param Port The port of the hub.\r
162 @param DevAddr Address of the failed transaction.\r
163 @param EpNum The endpoint number of the failed transaction.\r
164 @param EpType The type of failed transaction.\r
e237e7ae 165\r
8616fc4c 166 @retval EFI_SUCCESS The TT buffer is cleared.\r
167 @retval Others Failed to clear the TT buffer.\r
e237e7ae 168\r
169**/\r
170EFI_STATUS\r
171UsbHubCtrlClearTTBuffer (\r
172 IN USB_DEVICE *HubDev,\r
173 IN UINT8 Port,\r
174 IN UINT16 DevAddr,\r
175 IN UINT16 EpNum,\r
176 IN UINT16 EpType\r
177 )\r
178{\r
179 EFI_STATUS Status;\r
180 UINT16 Value;\r
181\r
182 //\r
183 // Check USB2.0 spec page 424 for wValue's encoding\r
184 //\r
c52fa98c 185 Value = (UINT16) ((EpNum & 0x0F) | (DevAddr << 4) |\r
186 ((EpType & 0x03) << 11) | ((EpNum & 0x80) << 15));\r
e237e7ae 187\r
188 Status = UsbCtrlRequest (\r
189 HubDev,\r
190 EfiUsbNoData,\r
191 USB_REQ_TYPE_CLASS,\r
192 USB_HUB_TARGET_PORT,\r
193 USB_HUB_REQ_CLEAR_TT,\r
194 Value,\r
c52fa98c 195 (UINT16) (Port + 1),\r
e237e7ae 196 NULL,\r
197 0\r
198 );\r
199\r
200 return Status;\r
201}\r
202\r
92870c98 203/**\r
acebdf14 204 Usb hub control transfer to get the (super speed) hub descriptor.\r
e237e7ae 205\r
8616fc4c 206 @param HubDev The hub device.\r
207 @param Buf The buffer to hold the descriptor.\r
208 @param Len The length to retrieve.\r
e237e7ae 209\r
8616fc4c 210 @retval EFI_SUCCESS The hub descriptor is retrieved.\r
211 @retval Others Failed to retrieve the hub descriptor.\r
e237e7ae 212\r
213**/\r
e237e7ae 214EFI_STATUS\r
215UsbHubCtrlGetHubDesc (\r
216 IN USB_DEVICE *HubDev,\r
217 OUT VOID *Buf,\r
218 IN UINTN Len\r
219 )\r
220{\r
221 EFI_STATUS Status;\r
acebdf14
SZ
222 UINT8 DescType;\r
223\r
224 DescType = (HubDev->Speed == EFI_USB_SPEED_SUPER) ?\r
225 USB_DESC_TYPE_HUB_SUPER_SPEED :\r
226 USB_DESC_TYPE_HUB;\r
e237e7ae 227\r
228 Status = UsbCtrlRequest (\r
229 HubDev,\r
230 EfiUsbDataIn,\r
231 USB_REQ_TYPE_CLASS,\r
232 USB_HUB_TARGET_HUB,\r
233 USB_HUB_REQ_GET_DESC,\r
acebdf14 234 (UINT16) (DescType << 8),\r
e237e7ae 235 0,\r
236 Buf,\r
237 Len\r
238 );\r
239\r
240 return Status;\r
241}\r
242\r
243\r
244/**\r
8616fc4c 245 Usb hub control transfer to get the hub status.\r
e237e7ae 246\r
8616fc4c 247 @param HubDev The hub device.\r
248 @param State The variable to return the status.\r
e237e7ae 249\r
8616fc4c 250 @retval EFI_SUCCESS The hub status is returned in State.\r
251 @retval Others Failed to get the hub status.\r
e237e7ae 252\r
253**/\r
e237e7ae 254EFI_STATUS\r
255UsbHubCtrlGetHubStatus (\r
256 IN USB_DEVICE *HubDev,\r
257 OUT UINT32 *State\r
258 )\r
259{\r
260 EFI_STATUS Status;\r
261\r
262 Status = UsbCtrlRequest (\r
263 HubDev,\r
264 EfiUsbDataIn,\r
265 USB_REQ_TYPE_CLASS,\r
266 USB_HUB_TARGET_HUB,\r
267 USB_HUB_REQ_GET_STATUS,\r
268 0,\r
269 0,\r
270 State,\r
271 4\r
272 );\r
273\r
274 return Status;\r
275}\r
276\r
277\r
278/**\r
8616fc4c 279 Usb hub control transfer to get the port status.\r
e237e7ae 280\r
8616fc4c 281 @param HubDev The hub device.\r
282 @param Port The port of the hub.\r
283 @param State Variable to return the hub port state.\r
e237e7ae 284\r
8616fc4c 285 @retval EFI_SUCCESS The port state is returned in State.\r
d17371e8 286 @retval Others Failed to retrieve the port state.\r
e237e7ae 287\r
288**/\r
e237e7ae 289EFI_STATUS\r
290UsbHubCtrlGetPortStatus (\r
291 IN USB_DEVICE *HubDev,\r
292 IN UINT8 Port,\r
293 OUT VOID *State\r
294 )\r
295{\r
296 EFI_STATUS Status;\r
297\r
298 //\r
299 // In USB bus, all the port index starts from 0. But HUB\r
300 // indexes its port from 1. So, port number is added one.\r
301 // No need to convert the hub bit to UEFI definition, they\r
302 // are the same\r
303 //\r
304 Status = UsbCtrlRequest (\r
305 HubDev,\r
306 EfiUsbDataIn,\r
307 USB_REQ_TYPE_CLASS,\r
308 USB_HUB_TARGET_PORT,\r
309 USB_HUB_REQ_GET_STATUS,\r
310 0,\r
c52fa98c 311 (UINT16) (Port + 1),\r
e237e7ae 312 State,\r
313 4\r
314 );\r
315\r
316 return Status;\r
317}\r
318\r
319\r
e237e7ae 320/**\r
8616fc4c 321 Usb hub control transfer to set the port feature.\r
e237e7ae 322\r
8616fc4c 323 @param HubDev The Usb hub device.\r
324 @param Port The Usb port to set feature for.\r
325 @param Feature The feature to set.\r
e237e7ae 326\r
8616fc4c 327 @retval EFI_SUCCESS The feature is set for the port.\r
328 @retval Others Failed to set the feature.\r
e237e7ae 329\r
330**/\r
e237e7ae 331EFI_STATUS\r
332UsbHubCtrlSetPortFeature (\r
333 IN USB_DEVICE *HubDev,\r
334 IN UINT8 Port,\r
335 IN UINT8 Feature\r
336 )\r
337{\r
338 EFI_STATUS Status;\r
339\r
340 //\r
341 // In USB bus, all the port index starts from 0. But HUB\r
342 // indexes its port from 1. So, port number is added one.\r
343 //\r
344 Status = UsbCtrlRequest (\r
345 HubDev,\r
346 EfiUsbNoData,\r
347 USB_REQ_TYPE_CLASS,\r
348 USB_HUB_TARGET_PORT,\r
349 USB_HUB_REQ_SET_FEATURE,\r
350 Feature,\r
c52fa98c 351 (UINT16) (Port + 1),\r
e237e7ae 352 NULL,\r
353 0\r
354 );\r
355\r
356 return Status;\r
357}\r
358\r
359\r
360/**\r
361 Read the whole usb hub descriptor. It is necessary\r
362 to do it in two steps because hub descriptor is of\r
8616fc4c 363 variable length.\r
e237e7ae 364\r
8616fc4c 365 @param HubDev The hub device.\r
366 @param HubDesc The variable to return the descriptor.\r
e237e7ae 367\r
8616fc4c 368 @retval EFI_SUCCESS The hub descriptor is read.\r
369 @retval Others Failed to read the hub descriptor.\r
e237e7ae 370\r
371**/\r
e237e7ae 372EFI_STATUS\r
373UsbHubReadDesc (\r
374 IN USB_DEVICE *HubDev,\r
375 OUT EFI_USB_HUB_DESCRIPTOR *HubDesc\r
376 )\r
377{\r
378 EFI_STATUS Status;\r
379\r
acebdf14
SZ
380 //\r
381 // First get the hub descriptor length\r
382 //\r
383 Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);\r
92870c98 384\r
acebdf14
SZ
385 if (EFI_ERROR (Status)) {\r
386 return Status;\r
92870c98 387 }\r
e237e7ae 388\r
acebdf14
SZ
389 //\r
390 // Get the whole hub descriptor\r
391 //\r
392 return UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);\r
e237e7ae 393}\r
394\r
395\r
396\r
397/**\r
398 Ack the hub change bits. If these bits are not ACKed, Hub will\r
399 always return changed bit map from its interrupt endpoint.\r
400\r
8616fc4c 401 @param HubDev The hub device.\r
e237e7ae 402\r
8616fc4c 403 @retval EFI_SUCCESS The hub change status is ACKed.\r
404 @retval Others Failed to ACK the hub status.\r
e237e7ae 405\r
406**/\r
407EFI_STATUS\r
408UsbHubAckHubStatus (\r
409 IN USB_DEVICE *HubDev\r
410 )\r
411{\r
412 EFI_USB_PORT_STATUS HubState;\r
413 EFI_STATUS Status;\r
414\r
415 Status = UsbHubCtrlGetHubStatus (HubDev, (UINT32 *) &HubState);\r
416\r
417 if (EFI_ERROR (Status)) {\r
418 return Status;\r
419 }\r
420\r
421 if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_LOCAL_POWER)) {\r
422 UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_LOCAL_POWER);\r
423 }\r
424\r
425 if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_OVER_CURRENT)) {\r
426 UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_OVER_CURRENT);\r
427 }\r
428\r
429 return EFI_SUCCESS;\r
430}\r
431\r
432\r
433/**\r
434 Test whether the interface is a hub interface.\r
435\r
8616fc4c 436 @param UsbIf The interface to test.\r
e237e7ae 437\r
8616fc4c 438 @retval TRUE The interface is a hub interface.\r
439 @retval FALSE The interface isn't a hub interface.\r
e237e7ae 440\r
441**/\r
442BOOLEAN\r
443UsbIsHubInterface (\r
444 IN USB_INTERFACE *UsbIf\r
445 )\r
446{\r
447 EFI_USB_INTERFACE_DESCRIPTOR *Setting;\r
448\r
449 //\r
450 // If the hub is a high-speed hub with multiple TT,\r
451 // the hub will has a default setting of single TT.\r
452 //\r
453 Setting = &UsbIf->IfSetting->Desc;\r
454\r
455 if ((Setting->InterfaceClass == USB_HUB_CLASS_CODE) &&\r
456 (Setting->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {\r
457\r
458 return TRUE;\r
459 }\r
460\r
461 return FALSE;\r
462}\r
463\r
464\r
465/**\r
466 The callback function to the USB hub status change\r
467 interrupt endpoint. It is called periodically by\r
468 the underlying host controller.\r
469\r
8616fc4c 470 @param Data The data read.\r
471 @param DataLength The length of the data read.\r
472 @param Context The context.\r
473 @param Result The result of the last interrupt transfer.\r
e237e7ae 474\r
8616fc4c 475 @retval EFI_SUCCESS The process is OK.\r
476 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource.\r
e237e7ae 477\r
478**/\r
e237e7ae 479EFI_STATUS\r
6d3ea23f 480EFIAPI\r
e237e7ae 481UsbOnHubInterrupt (\r
482 IN VOID *Data,\r
483 IN UINTN DataLength,\r
484 IN VOID *Context,\r
485 IN UINT32 Result\r
486 )\r
487{\r
488 USB_INTERFACE *HubIf;\r
489 EFI_USB_IO_PROTOCOL *UsbIo;\r
490 EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;\r
491 EFI_STATUS Status;\r
492\r
493 HubIf = (USB_INTERFACE *) Context;\r
494 UsbIo = &(HubIf->UsbIo);\r
495 EpDesc = &(HubIf->HubEp->Desc);\r
496\r
497 if (Result != EFI_USB_NOERROR) {\r
498 //\r
499 // If endpoint is stalled, clear the stall. Use UsbIo to access\r
500 // the control transfer so internal status are maintained.\r
501 //\r
502 if (USB_BIT_IS_SET (Result, EFI_USB_ERR_STALL)) {\r
503 UsbIoClearFeature (\r
504 UsbIo,\r
505 USB_TARGET_ENDPOINT,\r
506 USB_FEATURE_ENDPOINT_HALT,\r
507 EpDesc->EndpointAddress\r
508 );\r
509 }\r
510\r
511 //\r
512 // Delete and submit a new async interrupt\r
513 //\r
514 Status = UsbIo->UsbAsyncInterruptTransfer (\r
515 UsbIo,\r
516 EpDesc->EndpointAddress,\r
517 FALSE,\r
518 0,\r
519 0,\r
520 NULL,\r
521 NULL\r
522 );\r
523\r
524 if (EFI_ERROR (Status)) {\r
d2577026 525 DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status));\r
e237e7ae 526 return Status;\r
527 }\r
528\r
529 Status = UsbIo->UsbAsyncInterruptTransfer (\r
530 UsbIo,\r
531 EpDesc->EndpointAddress,\r
532 TRUE,\r
533 USB_HUB_POLL_INTERVAL,\r
534 HubIf->NumOfPort / 8 + 1,\r
535 UsbOnHubInterrupt,\r
536 HubIf\r
537 );\r
538\r
539 if (EFI_ERROR (Status)) {\r
d2577026 540 DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status));\r
e237e7ae 541 }\r
542\r
543 return Status;\r
544 }\r
545\r
546 if ((DataLength == 0) || (Data == NULL)) {\r
547 return EFI_SUCCESS;\r
548 }\r
549\r
550 //\r
551 // OK, actually something is changed, save the change map\r
552 // then signal the HUB to do enumeration. This is a good\r
553 // practise since UsbOnHubInterrupt is called in the context\r
554 // of host contrller's AsyncInterrupt monitor.\r
555 //\r
556 HubIf->ChangeMap = AllocateZeroPool (DataLength);\r
557\r
558 if (HubIf->ChangeMap == NULL) {\r
559 return EFI_OUT_OF_RESOURCES;\r
560 }\r
561\r
562 CopyMem (HubIf->ChangeMap, Data, DataLength);\r
563 gBS->SignalEvent (HubIf->HubNotify);\r
564\r
565 return EFI_SUCCESS;\r
566}\r
567\r
e237e7ae 568\r
569\r
570\r
571/**\r
8616fc4c 572 Initialize the device for a non-root hub.\r
e237e7ae 573\r
8616fc4c 574 @param HubIf The USB hub interface.\r
e237e7ae 575\r
8616fc4c 576 @retval EFI_SUCCESS The hub is initialized.\r
577 @retval EFI_DEVICE_ERROR Failed to initialize the hub.\r
e237e7ae 578\r
579**/\r
e237e7ae 580EFI_STATUS\r
581UsbHubInit (\r
582 IN USB_INTERFACE *HubIf\r
583 )\r
584{\r
acebdf14
SZ
585 UINT8 HubDescBuffer[256];\r
586 EFI_USB_HUB_DESCRIPTOR *HubDesc;\r
e237e7ae 587 USB_ENDPOINT_DESC *EpDesc;\r
588 USB_INTERFACE_SETTING *Setting;\r
589 EFI_USB_IO_PROTOCOL *UsbIo;\r
590 USB_DEVICE *HubDev;\r
591 EFI_STATUS Status;\r
592 UINT8 Index;\r
d17371e8 593 UINT8 NumEndpoints;\r
92870c98 594 UINT16 Depth;\r
e237e7ae 595\r
596 //\r
597 // Locate the interrupt endpoint for port change map\r
598 //\r
599 HubIf->IsHub = FALSE;\r
600 Setting = HubIf->IfSetting;\r
601 HubDev = HubIf->Device;\r
602 EpDesc = NULL;\r
d17371e8 603 NumEndpoints = Setting->Desc.NumEndpoints;\r
e237e7ae 604\r
d17371e8 605 for (Index = 0; Index < NumEndpoints; Index++) {\r
e237e7ae 606 ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL));\r
607\r
608 EpDesc = Setting->Endpoints[Index];\r
609\r
610 if (USB_BIT_IS_SET (EpDesc->Desc.EndpointAddress, USB_ENDPOINT_DIR_IN) &&\r
611 (USB_ENDPOINT_TYPE (&EpDesc->Desc) == USB_ENDPOINT_INTERRUPT)) {\r
612 break;\r
613 }\r
614 }\r
615\r
d17371e8 616 if (Index == NumEndpoints) {\r
d2577026 617 DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address));\r
e237e7ae 618 return EFI_DEVICE_ERROR;\r
619 }\r
620\r
acebdf14
SZ
621 //\r
622 // The length field of descriptor is UINT8 type, so the buffer\r
623 // with 256 bytes is enough to hold the descriptor data.\r
624 //\r
625 HubDesc = (EFI_USB_HUB_DESCRIPTOR *) HubDescBuffer;\r
626 Status = UsbHubReadDesc (HubDev, HubDesc);\r
e237e7ae 627\r
628 if (EFI_ERROR (Status)) {\r
d2577026 629 DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));\r
e237e7ae 630 return Status;\r
631 }\r
632\r
acebdf14 633 HubIf->NumOfPort = HubDesc->NumPorts;\r
e237e7ae 634\r
d2577026 635 DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));\r
e237e7ae 636\r
92870c98 637 //\r
638 // OK, set IsHub to TRUE. Now usb bus can handle this device\r
639 // as a working HUB. If failed eariler, bus driver will not\r
640 // recognize it as a hub. Other parts of the bus should be able\r
641 // to work.\r
642 //\r
643 HubIf->IsHub = TRUE;\r
644 HubIf->HubApi = &mUsbHubApi;\r
645 HubIf->HubEp = EpDesc;\r
646\r
647 if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {\r
648 Depth = (UINT16)(HubIf->Device->Tier - 1);\r
649 DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));\r
650 UsbHubCtrlSetHubDepth (HubIf->Device, Depth);\r
d1102dba 651\r
acebdf14 652 for (Index = 0; Index < HubDesc->NumPorts; Index++) {\r
92870c98 653 UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);\r
d1102dba 654 }\r
92870c98 655 } else {\r
656 //\r
657 // Feed power to all the hub ports. It should be ok\r
658 // for both gang/individual powered hubs.\r
659 //\r
acebdf14 660 for (Index = 0; Index < HubDesc->NumPorts; Index++) {\r
92870c98 661 UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);\r
662 }\r
663\r
c843ef67 664 //\r
665 // Update for the usb hub has no power on delay requirement\r
666 //\r
acebdf14
SZ
667 if (HubDesc->PwrOn2PwrGood > 0) {\r
668 gBS->Stall (HubDesc->PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);\r
c843ef67 669 }\r
92870c98 670 UsbHubAckHubStatus (HubIf->Device);\r
671 }\r
672\r
e237e7ae 673 //\r
674 // Create an event to enumerate the hub's port. On\r
675 //\r
676 Status = gBS->CreateEvent (\r
677 EVT_NOTIFY_SIGNAL,\r
678 TPL_CALLBACK,\r
679 UsbHubEnumeration,\r
680 HubIf,\r
681 &HubIf->HubNotify\r
682 );\r
683\r
684 if (EFI_ERROR (Status)) {\r
d2577026 685 DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to create signal for hub %d - %r\n",\r
e237e7ae 686 HubDev->Address, Status));\r
687\r
688 return Status;\r
689 }\r
690\r
691 //\r
692 // Create AsyncInterrupt to query hub port change endpoint\r
693 // periodically. If the hub ports are changed, hub will return\r
694 // changed port map from the interrupt endpoint. The port map\r
695 // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for\r
696 // host change status).\r
697 //\r
698 UsbIo = &HubIf->UsbIo;\r
699 Status = UsbIo->UsbAsyncInterruptTransfer (\r
700 UsbIo,\r
701 EpDesc->Desc.EndpointAddress,\r
702 TRUE,\r
703 USB_HUB_POLL_INTERVAL,\r
704 HubIf->NumOfPort / 8 + 1,\r
705 UsbOnHubInterrupt,\r
706 HubIf\r
707 );\r
708\r
709 if (EFI_ERROR (Status)) {\r
d2577026 710 DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",\r
e237e7ae 711 HubDev->Address, Status));\r
712\r
713 gBS->CloseEvent (HubIf->HubNotify);\r
714 HubIf->HubNotify = NULL;\r
715\r
716 return Status;\r
717 }\r
718\r
d2577026 719 DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));\r
e237e7ae 720 return Status;\r
721}\r
722\r
723\r
724\r
725/**\r
726 Get the port status. This function is required to\r
727 ACK the port change bits although it will return\r
728 the port changes in PortState. Bus enumeration code\r
729 doesn't need to ACK the port change bits.\r
730\r
8616fc4c 731 @param HubIf The hub interface.\r
732 @param Port The port of the hub to get state.\r
733 @param PortState Variable to return the port state.\r
e237e7ae 734\r
8616fc4c 735 @retval EFI_SUCCESS The port status is successfully returned.\r
736 @retval Others Failed to return the status.\r
e237e7ae 737\r
738**/\r
e237e7ae 739EFI_STATUS\r
740UsbHubGetPortStatus (\r
741 IN USB_INTERFACE *HubIf,\r
742 IN UINT8 Port,\r
743 OUT EFI_USB_PORT_STATUS *PortState\r
744 )\r
745{\r
746 EFI_STATUS Status;\r
747\r
748 Status = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);\r
749\r
750 return Status;\r
751}\r
752\r
753\r
754\r
755/**\r
756 Clear the port change status.\r
757\r
8616fc4c 758 @param HubIf The hub interface.\r
759 @param Port The hub port.\r
e237e7ae 760\r
e237e7ae 761**/\r
e237e7ae 762VOID\r
763UsbHubClearPortChange (\r
764 IN USB_INTERFACE *HubIf,\r
765 IN UINT8 Port\r
766 )\r
767{\r
768 EFI_USB_PORT_STATUS PortState;\r
769 USB_CHANGE_FEATURE_MAP *Map;\r
770 UINTN Index;\r
771 EFI_STATUS Status;\r
772\r
773 Status = UsbHubGetPortStatus (HubIf, Port, &PortState);\r
774\r
775 if (EFI_ERROR (Status)) {\r
776 return;\r
777 }\r
778\r
779 //\r
780 // OK, get the usb port status, now ACK the change bits.\r
781 // Don't return error when failed to clear the change bits.\r
782 // It may lead to extra port state report. USB bus should\r
783 // be able to handle this.\r
784 //\r
60a2d248 785 for (Index = 0; Index < ARRAY_SIZE (mHubFeatureMap); Index++) {\r
e237e7ae 786 Map = &mHubFeatureMap[Index];\r
787\r
788 if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
23c326c2 789 UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT16) Map->Feature);\r
e237e7ae 790 }\r
791 }\r
792}\r
793\r
794\r
795\r
796/**\r
8616fc4c 797 Function to set the port feature for non-root hub.\r
e237e7ae 798\r
8616fc4c 799 @param HubIf The hub interface.\r
800 @param Port The port of the hub.\r
801 @param Feature The feature of the port to set.\r
e237e7ae 802\r
8616fc4c 803 @retval EFI_SUCCESS The hub port feature is set.\r
804 @retval Others Failed to set the port feature.\r
e237e7ae 805\r
806**/\r
e237e7ae 807EFI_STATUS\r
808UsbHubSetPortFeature (\r
809 IN USB_INTERFACE *HubIf,\r
810 IN UINT8 Port,\r
811 IN EFI_USB_PORT_FEATURE Feature\r
812 )\r
813{\r
814 EFI_STATUS Status;\r
815\r
c52fa98c 816 Status = UsbHubCtrlSetPortFeature (HubIf->Device, Port, (UINT8) Feature);\r
e237e7ae 817\r
818 return Status;\r
819}\r
820\r
821\r
822/**\r
8616fc4c 823 Interface function to clear the port feature for non-root hub.\r
e237e7ae 824\r
8616fc4c 825 @param HubIf The hub interface.\r
826 @param Port The port of the hub to clear feature for.\r
827 @param Feature The feature to clear.\r
e237e7ae 828\r
8616fc4c 829 @retval EFI_SUCCESS The port feature is cleared.\r
830 @retval Others Failed to clear the port feature.\r
e237e7ae 831\r
832**/\r
e237e7ae 833EFI_STATUS\r
834UsbHubClearPortFeature (\r
835 IN USB_INTERFACE *HubIf,\r
836 IN UINT8 Port,\r
837 IN EFI_USB_PORT_FEATURE Feature\r
838 )\r
839{\r
840 EFI_STATUS Status;\r
841\r
c52fa98c 842 Status = UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT8) Feature);\r
e237e7ae 843\r
844 return Status;\r
845}\r
846\r
847\r
848/**\r
d17371e8 849 Interface function to reset the port.\r
e237e7ae 850\r
8616fc4c 851 @param HubIf The hub interface.\r
852 @param Port The port to reset.\r
e237e7ae 853\r
8616fc4c 854 @retval EFI_SUCCESS The hub port is reset.\r
855 @retval EFI_TIMEOUT Failed to reset the port in time.\r
856 @retval Others Failed to reset the port.\r
e237e7ae 857\r
858**/\r
e237e7ae 859EFI_STATUS\r
860UsbHubResetPort (\r
861 IN USB_INTERFACE *HubIf,\r
862 IN UINT8 Port\r
863 )\r
864{\r
865 EFI_USB_PORT_STATUS PortState;\r
866 UINTN Index;\r
867 EFI_STATUS Status;\r
868\r
c52fa98c 869 Status = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET);\r
e237e7ae 870\r
871 if (EFI_ERROR (Status)) {\r
872 return Status;\r
873 }\r
874\r
875 //\r
71619ac2 876 // Drive the reset signal for worst 20ms. Check USB 2.0 Spec\r
e237e7ae 877 // section 7.1.7.5 for timing requirements.\r
878 //\r
41e8ff27 879 gBS->Stall (USB_SET_PORT_RESET_STALL);\r
e237e7ae 880\r
881 //\r
71619ac2 882 // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.\r
e237e7ae 883 //\r
884 ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));\r
885\r
41e8ff27 886 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
e237e7ae 887 Status = UsbHubGetPortStatus (HubIf, Port, &PortState);\r
888\r
127884c5
FT
889 if (EFI_ERROR (Status)) {\r
890 return Status;\r
891 }\r
892\r
e237e7ae 893 if (!EFI_ERROR (Status) &&\r
71619ac2 894 USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {\r
895 gBS->Stall (USB_SET_PORT_RECOVERY_STALL);\r
e237e7ae 896 return EFI_SUCCESS;\r
897 }\r
898\r
41e8ff27 899 gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);\r
e237e7ae 900 }\r
901\r
902 return EFI_TIMEOUT;\r
903}\r
904\r
905\r
906/**\r
8616fc4c 907 Release the hub's control of the interface.\r
e237e7ae 908\r
8616fc4c 909 @param HubIf The hub interface.\r
e237e7ae 910\r
8616fc4c 911 @retval EFI_SUCCESS The interface is release of hub control.\r
e237e7ae 912\r
913**/\r
e237e7ae 914EFI_STATUS\r
915UsbHubRelease (\r
916 IN USB_INTERFACE *HubIf\r
917 )\r
918{\r
919 EFI_USB_IO_PROTOCOL *UsbIo;\r
920 EFI_STATUS Status;\r
921\r
922 UsbIo = &HubIf->UsbIo;\r
923 Status = UsbIo->UsbAsyncInterruptTransfer (\r
924 UsbIo,\r
925 HubIf->HubEp->Desc.EndpointAddress,\r
926 FALSE,\r
927 USB_HUB_POLL_INTERVAL,\r
928 0,\r
929 NULL,\r
930 0\r
931 );\r
932\r
933 if (EFI_ERROR (Status)) {\r
934 return Status;\r
935 }\r
936\r
937 gBS->CloseEvent (HubIf->HubNotify);\r
938\r
939 HubIf->IsHub = FALSE;\r
940 HubIf->HubApi = NULL;\r
941 HubIf->HubEp = NULL;\r
942 HubIf->HubNotify = NULL;\r
943\r
d2577026 944 DEBUG (( EFI_D_INFO, "UsbHubRelease: hub device %d released\n", HubIf->Device->Address));\r
e237e7ae 945 return EFI_SUCCESS;\r
946}\r
947\r
948\r
949\r
950/**\r
8616fc4c 951 Initialize the interface for root hub.\r
e237e7ae 952\r
8616fc4c 953 @param HubIf The root hub interface.\r
e237e7ae 954\r
d17371e8 955 @retval EFI_SUCCESS The interface is initialized for root hub.\r
8616fc4c 956 @retval Others Failed to initialize the hub.\r
e237e7ae 957\r
958**/\r
e237e7ae 959EFI_STATUS\r
960UsbRootHubInit (\r
961 IN USB_INTERFACE *HubIf\r
962 )\r
963{\r
964 EFI_STATUS Status;\r
965 UINT8 MaxSpeed;\r
966 UINT8 NumOfPort;\r
967 UINT8 Support64;\r
968\r
969 Status = UsbHcGetCapability (HubIf->Device->Bus, &MaxSpeed, &NumOfPort, &Support64);\r
970\r
971 if (EFI_ERROR (Status)) {\r
972 return Status;\r
973 }\r
974\r
0e549d5b 975 DEBUG (( EFI_D_INFO, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",\r
e237e7ae 976 HubIf, MaxSpeed, NumOfPort));\r
977\r
978 HubIf->IsHub = TRUE;\r
979 HubIf->HubApi = &mUsbRootHubApi;\r
980 HubIf->HubEp = NULL;\r
981 HubIf->MaxSpeed = MaxSpeed;\r
982 HubIf->NumOfPort = NumOfPort;\r
983 HubIf->HubNotify = NULL;\r
984\r
985 //\r
986 // Create a timer to poll root hub ports periodically\r
987 //\r
988 Status = gBS->CreateEvent (\r
989 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
990 TPL_CALLBACK,\r
991 UsbRootHubEnumeration,\r
992 HubIf,\r
993 &HubIf->HubNotify\r
994 );\r
995\r
996 if (EFI_ERROR (Status)) {\r
997 return Status;\r
998 }\r
999\r
d2577026 1000 //\r
1001 // It should signal the event immediately here, or device detection\r
1002 // by bus enumeration might be delayed by the timer interval.\r
1003 //\r
1004 gBS->SignalEvent (HubIf->HubNotify);\r
1005\r
e237e7ae 1006 Status = gBS->SetTimer (\r
1007 HubIf->HubNotify,\r
1008 TimerPeriodic,\r
1009 USB_ROOTHUB_POLL_INTERVAL\r
1010 );\r
1011\r
1012 if (EFI_ERROR (Status)) {\r
1013 gBS->CloseEvent (HubIf->HubNotify);\r
1014 }\r
1015\r
1016 return Status;\r
1017}\r
1018\r
1019\r
e237e7ae 1020/**\r
1021 Get the port status. This function is required to\r
1022 ACK the port change bits although it will return\r
1023 the port changes in PortState. Bus enumeration code\r
1024 doesn't need to ACK the port change bits.\r
1025\r
8616fc4c 1026 @param HubIf The root hub interface.\r
1027 @param Port The root hub port to get the state.\r
1028 @param PortState Variable to return the port state.\r
e237e7ae 1029\r
8616fc4c 1030 @retval EFI_SUCCESS The port state is returned.\r
1031 @retval Others Failed to retrieve the port state.\r
e237e7ae 1032\r
1033**/\r
e237e7ae 1034EFI_STATUS\r
1035UsbRootHubGetPortStatus (\r
1036 IN USB_INTERFACE *HubIf,\r
1037 IN UINT8 Port,\r
1038 OUT EFI_USB_PORT_STATUS *PortState\r
1039 )\r
1040{\r
1041 USB_BUS *Bus;\r
1042 EFI_STATUS Status;\r
1043\r
1044 Bus = HubIf->Device->Bus;\r
1045 Status = UsbHcGetRootHubPortStatus (Bus, Port, PortState);\r
1046\r
1047 return Status;\r
1048}\r
1049\r
1050\r
1051/**\r
1052 Clear the port change status.\r
1053\r
8616fc4c 1054 @param HubIf The root hub interface.\r
1055 @param Port The root hub port.\r
e237e7ae 1056\r
e237e7ae 1057**/\r
e237e7ae 1058VOID\r
1059UsbRootHubClearPortChange (\r
1060 IN USB_INTERFACE *HubIf,\r
1061 IN UINT8 Port\r
1062 )\r
1063{\r
1064 EFI_USB_PORT_STATUS PortState;\r
1065 USB_CHANGE_FEATURE_MAP *Map;\r
1066 UINTN Index;\r
1067 EFI_STATUS Status;\r
1068\r
1069 Status = UsbRootHubGetPortStatus (HubIf, Port, &PortState);\r
1070\r
1071 if (EFI_ERROR (Status)) {\r
1072 return;\r
1073 }\r
1074\r
1075 //\r
1076 // OK, get the usb port status, now ACK the change bits.\r
1077 // Don't return error when failed to clear the change bits.\r
1078 // It may lead to extra port state report. USB bus should\r
1079 // be able to handle this.\r
1080 //\r
60a2d248 1081 for (Index = 0; Index < ARRAY_SIZE (mRootHubFeatureMap); Index++) {\r
e237e7ae 1082 Map = &mRootHubFeatureMap[Index];\r
1083\r
1084 if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {\r
c52fa98c 1085 UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, (EFI_USB_PORT_FEATURE) Map->Feature);\r
e237e7ae 1086 }\r
1087 }\r
1088}\r
1089\r
1090\r
e237e7ae 1091/**\r
8616fc4c 1092 Set the root hub port feature.\r
e237e7ae 1093\r
8616fc4c 1094 @param HubIf The Usb hub interface.\r
1095 @param Port The hub port.\r
1096 @param Feature The feature to set.\r
e237e7ae 1097\r
8616fc4c 1098 @retval EFI_SUCCESS The root hub port is set with the feature.\r
1099 @retval Others Failed to set the feature.\r
e237e7ae 1100\r
1101**/\r
e237e7ae 1102EFI_STATUS\r
1103UsbRootHubSetPortFeature (\r
1104 IN USB_INTERFACE *HubIf,\r
1105 IN UINT8 Port,\r
1106 IN EFI_USB_PORT_FEATURE Feature\r
1107 )\r
1108{\r
1109 EFI_STATUS Status;\r
1110\r
1111 Status = UsbHcSetRootHubPortFeature (HubIf->Device->Bus, Port, Feature);\r
1112\r
1113 return Status;\r
1114}\r
1115\r
1116\r
1117/**\r
8616fc4c 1118 Clear the root hub port feature.\r
e237e7ae 1119\r
8616fc4c 1120 @param HubIf The root hub interface.\r
1121 @param Port The root hub port.\r
1122 @param Feature The feature to clear.\r
e237e7ae 1123\r
8616fc4c 1124 @retval EFI_SUCCESS The root hub port is cleared of the feature.\r
1125 @retval Others Failed to clear the feature.\r
e237e7ae 1126\r
1127**/\r
e237e7ae 1128EFI_STATUS\r
1129UsbRootHubClearPortFeature (\r
1130 IN USB_INTERFACE *HubIf,\r
1131 IN UINT8 Port,\r
1132 IN EFI_USB_PORT_FEATURE Feature\r
1133 )\r
1134{\r
1135 EFI_STATUS Status;\r
1136\r
1137 Status = UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, Feature);\r
1138\r
1139 return Status;\r
1140}\r
1141\r
1142\r
1143/**\r
d17371e8 1144 Interface function to reset the root hub port.\r
e237e7ae 1145\r
8616fc4c 1146 @param RootIf The root hub interface.\r
1147 @param Port The port to reset.\r
e237e7ae 1148\r
8616fc4c 1149 @retval EFI_SUCCESS The hub port is reset.\r
1150 @retval EFI_TIMEOUT Failed to reset the port in time.\r
1151 @retval EFI_NOT_FOUND The low/full speed device connected to high speed.\r
1152 root hub is released to the companion UHCI.\r
1153 @retval Others Failed to reset the port.\r
e237e7ae 1154\r
1155**/\r
e237e7ae 1156EFI_STATUS\r
1157UsbRootHubResetPort (\r
1158 IN USB_INTERFACE *RootIf,\r
1159 IN UINT8 Port\r
1160 )\r
1161{\r
1162 USB_BUS *Bus;\r
1163 EFI_STATUS Status;\r
1164 EFI_USB_PORT_STATUS PortState;\r
1165 UINTN Index;\r
1166\r
1167 //\r
1168 // Notice: although EHCI requires that ENABLED bit be cleared\r
1169 // when reset the port, we don't need to care that here. It\r
1170 // should be handled in the EHCI driver.\r
1171 //\r
1172 Bus = RootIf->Device->Bus;\r
c3f44a77 1173\r
e237e7ae 1174 Status = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);\r
1175\r
1176 if (EFI_ERROR (Status)) {\r
d2577026 1177 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to start reset on port %d\n", Port));\r
e237e7ae 1178 return Status;\r
1179 }\r
1180\r
1181 //\r
1182 // Drive the reset signal for at least 50ms. Check USB 2.0 Spec\r
1183 // section 7.1.7.5 for timing requirements.\r
1184 //\r
41e8ff27 1185 gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL);\r
e237e7ae 1186\r
1187 Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);\r
1188\r
1189 if (EFI_ERROR (Status)) {\r
d2577026 1190 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port));\r
e237e7ae 1191 return Status;\r
1192 }\r
1193\r
41e8ff27 1194 gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL);\r
e237e7ae 1195\r
1196 //\r
1197 // USB host controller won't clear the RESET bit until\r
1198 // reset is actually finished.\r
1199 //\r
1200 ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));\r
1201\r
41e8ff27 1202 for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {\r
e237e7ae 1203 Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);\r
1204\r
1205 if (EFI_ERROR (Status)) {\r
1206 return Status;\r
1207 }\r
1208\r
1209 if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {\r
1210 break;\r
1211 }\r
1212\r
41e8ff27 1213 gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);\r
e237e7ae 1214 }\r
1215\r
41e8ff27 1216 if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {\r
1217 DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));\r
e237e7ae 1218 return EFI_TIMEOUT;\r
1219 }\r
1220\r
1221 if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_ENABLE)) {\r
1222 //\r
1223 // OK, the port is reset. If root hub is of high speed and\r
1224 // the device is of low/full speed, release the ownership to\r
1225 // companion UHCI. If root hub is of full speed, it won't\r
1226 // automatically enable the port, we need to enable it manually.\r
1227 //\r
1228 if (RootIf->MaxSpeed == EFI_USB_SPEED_HIGH) {\r
d2577026 1229 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port));\r
e237e7ae 1230\r
1231 UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortOwner);\r
1232 return EFI_NOT_FOUND;\r
1233\r
1234 } else {\r
1235\r
1236 Status = UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortEnable);\r
1237\r
1238 if (EFI_ERROR (Status)) {\r
d2577026 1239 DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port));\r
e237e7ae 1240 return Status;\r
1241 }\r
1242\r
41e8ff27 1243 gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);\r
e237e7ae 1244 }\r
1245 }\r
1246\r
1247 return EFI_SUCCESS;\r
1248}\r
1249\r
1250\r
1251/**\r
8616fc4c 1252 Release the root hub's control of the interface.\r
e237e7ae 1253\r
8616fc4c 1254 @param HubIf The root hub interface.\r
e237e7ae 1255\r
1256 @retval EFI_SUCCESS The root hub's control of the interface is\r
1257 released.\r
1258\r
1259**/\r
e237e7ae 1260EFI_STATUS\r
1261UsbRootHubRelease (\r
1262 IN USB_INTERFACE *HubIf\r
1263 )\r
1264{\r
0e549d5b 1265 DEBUG (( EFI_D_INFO, "UsbRootHubRelease: root hub released for hub %p\n", HubIf));\r
e237e7ae 1266\r
1267 gBS->SetTimer (HubIf->HubNotify, TimerCancel, USB_ROOTHUB_POLL_INTERVAL);\r
1268 gBS->CloseEvent (HubIf->HubNotify);\r
1269\r
1270 return EFI_SUCCESS;\r
1271}\r
1272\r
1273USB_HUB_API mUsbHubApi = {\r
1274 UsbHubInit,\r
1275 UsbHubGetPortStatus,\r
1276 UsbHubClearPortChange,\r
1277 UsbHubSetPortFeature,\r
1278 UsbHubClearPortFeature,\r
1279 UsbHubResetPort,\r
1280 UsbHubRelease\r
1281};\r
1282\r
1283USB_HUB_API mUsbRootHubApi = {\r
1284 UsbRootHubInit,\r
1285 UsbRootHubGetPortStatus,\r
1286 UsbRootHubClearPortChange,\r
1287 UsbRootHubSetPortFeature,\r
1288 UsbRootHubClearPortFeature,\r
1289 UsbRootHubResetPort,\r
1290 UsbRootHubRelease\r
1291};\r