]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
Initial import.
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbBus / Dxe / usbbus.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12 Module Name:\r
13\r
14 UsbBus.c\r
15\r
16 Abstract:\r
17\r
18 USB Bus Driver\r
19\r
20 Revision History\r
21\r
22--*/\r
23\r
24#include "usbbus.h"\r
25\r
26//#ifdef EFI_DEBUG\r
27UINTN gUSBDebugLevel = EFI_D_ERROR;\r
28UINTN gUSBErrorLevel = EFI_D_ERROR;\r
29//#endif\r
30//\r
31// The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER\r
32// structure in the UsbBusDriverControllerDriverStop(). Then we can\r
33// Close all opened protocols and release this structure.\r
34//\r
35STATIC EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;\r
36\r
37\r
38\r
39//\r
40// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface\r
41//\r
42EFI_STATUS\r
43EFIAPI\r
44UsbBusControllerDriverSupported (\r
45 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
46 IN EFI_HANDLE Controller,\r
47 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
48 );\r
49\r
50EFI_STATUS\r
51EFIAPI\r
52UsbBusControllerDriverStart (\r
53 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
54 IN EFI_HANDLE Controller,\r
55 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
56 );\r
57\r
58EFI_STATUS\r
59EFIAPI\r
60UsbBusControllerDriverStop (\r
61 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
62 IN EFI_HANDLE Controller,\r
63 IN UINTN NumberOfChildren,\r
64 IN EFI_HANDLE *ChildHandleBuffer\r
65 );\r
66\r
67EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding = {\r
68 UsbBusControllerDriverSupported,\r
69 UsbBusControllerDriverStart,\r
70 UsbBusControllerDriverStop,\r
71 0x10,\r
72 NULL,\r
73 NULL\r
74};\r
75\r
76//\r
77// Internal use only\r
78//\r
79STATIC\r
80EFI_STATUS\r
81ReportUsbStatusCode (\r
82 IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,\r
83 IN EFI_STATUS_CODE_TYPE Type,\r
84 IN EFI_STATUS_CODE_VALUE Code\r
85 );\r
86\r
87//\r
88// Supported function\r
89//\r
90VOID\r
91InitializeUsbIoInstance (\r
92 IN USB_IO_CONTROLLER_DEVICE *UsbIoController\r
93 );\r
94\r
95STATIC\r
96USB_IO_CONTROLLER_DEVICE *\r
97CreateUsbIoControllerDevice (\r
98 VOID\r
99 );\r
100\r
101STATIC\r
102EFI_STATUS\r
103InitUsbIoController (\r
104 IN USB_IO_CONTROLLER_DEVICE *UsbIoController\r
105 );\r
106\r
107//\r
108// USB Device Configuration / Deconfiguration\r
109//\r
110STATIC\r
111EFI_STATUS\r
112UsbDeviceConfiguration (\r
113 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,\r
114 IN EFI_HANDLE HostController,\r
115 IN UINT8 ParentPort,\r
116 IN USB_IO_DEVICE *UsbIoDevice\r
117 );\r
118\r
119//\r
120// Usb Bus enumeration function\r
121//\r
122STATIC\r
123VOID\r
124EFIAPI\r
125UsbEnumeration (\r
126 IN EFI_EVENT Event,\r
127 IN VOID *Context\r
128 );\r
129\r
130EFI_STATUS\r
131ResetRootPort (\r
132 IN EFI_USB_HC_PROTOCOL *UsbHCInterface,\r
133 IN UINT8 PortNum,\r
134 IN UINT8 RetryTimes\r
135 );\r
136\r
137EFI_STATUS\r
138ResetHubPort (\r
139 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
140 IN UINT8 PortIndex\r
141 );\r
142\r
143EFI_STATUS\r
144ClearRootPortConnectionChangeStatus (\r
145 IN UINT8 PortNum,\r
146 IN EFI_USB_HC_PROTOCOL *UsbHCInterface\r
147 );\r
148\r
149STATIC\r
150EFI_STATUS\r
151ParentPortReset (\r
152 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
153 IN BOOLEAN ReConfigure,\r
154 IN UINT8 RetryTimes\r
155 );\r
156\r
157//\r
158// Following are address allocate and free functions\r
159//\r
160STATIC\r
161UINT8\r
162UsbAllocateAddress (\r
163 IN UINT8 *AddressPool\r
164 )\r
165{\r
166 UINT8 ByteIndex;\r
167 UINT8 BitIndex;\r
168\r
169 for (ByteIndex = 0; ByteIndex < 16; ByteIndex++) {\r
170 for (BitIndex = 0; BitIndex < 8; BitIndex++) {\r
171 if ((AddressPool[ByteIndex] & (1 << BitIndex)) == 0) {\r
172 //\r
173 // Found one, covert to address, and mark it use\r
174 //\r
175 AddressPool[ByteIndex] |= (1 << BitIndex);\r
176 return (UINT8) (ByteIndex * 8 + BitIndex);\r
177 }\r
178 }\r
179 }\r
180\r
181 return 0;\r
182\r
183}\r
184\r
185STATIC\r
186VOID\r
187UsbFreeAddress (\r
188 IN UINT8 DevAddress,\r
189 IN UINT8 *AddressPool\r
190 )\r
191{\r
192 UINT8 WhichByte;\r
193 UINT8 WhichBit;\r
194 //\r
195 // Locate the position\r
196 //\r
197 WhichByte = (UINT8) (DevAddress / 8);\r
198 WhichBit = (UINT8) (DevAddress & 0x7);\r
199\r
200 AddressPool[WhichByte] &= (~(1 << WhichBit));\r
201}\r
202\r
203EFI_STATUS\r
204EFIAPI\r
205UsbBusControllerDriverSupported (\r
206 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
207 IN EFI_HANDLE Controller,\r
208 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
209 )\r
210/*++\r
211\r
212 Routine Description:\r
213 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
214 that has UsbHcProtocol installed will be supported.\r
215\r
216 Arguments:\r
217 This - Protocol instance pointer.\r
218 Controller - Handle of device to test\r
219 RemainingDevicePath - Not used\r
220\r
221 Returns:\r
222 EFI_SUCCESS - This driver supports this device.\r
223 EFI_UNSUPPORTED - This driver does not support this device.\r
224\r
225--*/\r
226{\r
227 EFI_STATUS OpenStatus;\r
228\r
229 //\r
230 // Check whether USB Host Controller Protocol is already\r
231 // installed on this handle. If it is installed, we can start\r
232 // USB Bus Driver now.\r
233 //\r
234 OpenStatus = gBS->OpenProtocol (\r
235 Controller,\r
236 &gEfiUsbHcProtocolGuid,\r
237 NULL,\r
238 This->DriverBindingHandle,\r
239 Controller,\r
240 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
241 );\r
242\r
243 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {\r
244 return EFI_UNSUPPORTED;\r
245 }\r
246\r
247 return OpenStatus;\r
248}\r
249\r
250\r
251EFI_STATUS\r
252EFIAPI\r
253UsbBusControllerDriverStart (\r
254 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
255 IN EFI_HANDLE Controller,\r
256 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
257 )\r
258/*++\r
259\r
260 Routine Description:\r
261\r
262 Starting the Usb Bus Driver\r
263\r
264 Arguments:\r
265\r
266 This - Protocol instance pointer.\r
267 Controller - Handle of device to test\r
268 RemainingDevicePath - Not used\r
269\r
270 Returns:\r
271\r
272 EFI_SUCCESS - This driver supports this device.\r
273 EFI_UNSUPPORTED - This driver does not support this device.\r
274 EFI_DEVICE_ERROR - This driver cannot be started due to device\r
275 Error\r
276 EFI_OUT_OF_RESOURCES- Can't allocate memory resources\r
277 EFI_ALREADY_STARTED - This driver has been started\r
278\r
279--*/\r
280{\r
281 EFI_STATUS Status;\r
282 EFI_STATUS OpenStatus;\r
283 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
284 USB_IO_DEVICE *RootHub;\r
285 USB_IO_CONTROLLER_DEVICE *RootHubController;\r
286 EFI_USB_HC_PROTOCOL *UsbHCInterface;\r
287\r
288 //\r
289 // Allocate USB_BUS_CONTROLLER_DEVICE structure\r
290 //\r
291 UsbBusDev = NULL;\r
292 UsbBusDev = AllocateZeroPool (sizeof (USB_BUS_CONTROLLER_DEVICE));\r
293 if (UsbBusDev == NULL) {\r
294 return EFI_OUT_OF_RESOURCES;\r
295 }\r
296\r
297 UsbBusDev->Signature = USB_BUS_DEVICE_SIGNATURE;\r
298 UsbBusDev->AddressPool[0] = 1;\r
299\r
300 //\r
301 // Get the Device Path Protocol on Controller's handle\r
302 //\r
303 OpenStatus = gBS->OpenProtocol (\r
304 Controller,\r
305 &gEfiDevicePathProtocolGuid,\r
306 (VOID **) &UsbBusDev->DevicePath,\r
307 This->DriverBindingHandle,\r
308 Controller,\r
309 EFI_OPEN_PROTOCOL_BY_DRIVER\r
310 );\r
311\r
312 if (EFI_ERROR (OpenStatus)) {\r
313 gBS->FreePool (UsbBusDev);\r
314 return EFI_UNSUPPORTED;\r
315 }\r
316 //\r
317 // Locate the Host Controller Interface\r
318 //\r
319 OpenStatus = gBS->OpenProtocol (\r
320 Controller,\r
321 &gEfiUsbHcProtocolGuid,\r
322 (VOID **) &UsbHCInterface,\r
323 This->DriverBindingHandle,\r
324 Controller,\r
325 EFI_OPEN_PROTOCOL_BY_DRIVER\r
326 );\r
327\r
328 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {\r
329 \r
330 //\r
331 // Report Status Code here since we will reset the host controller\r
332 //\r
333 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
334 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
335 EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,\r
336 UsbBusDev->DevicePath\r
337 );\r
338\r
339 gBS->CloseProtocol (\r
340 Controller,\r
341 &gEfiDevicePathProtocolGuid,\r
342 This->DriverBindingHandle,\r
343 Controller\r
344 );\r
345 gBS->FreePool (UsbBusDev);\r
346 return EFI_UNSUPPORTED;\r
347 }\r
348\r
349 if (OpenStatus == EFI_ALREADY_STARTED) {\r
350 gBS->CloseProtocol (\r
351 Controller,\r
352 &gEfiDevicePathProtocolGuid,\r
353 This->DriverBindingHandle,\r
354 Controller\r
355 );\r
356 gBS->FreePool (UsbBusDev);\r
357 return EFI_ALREADY_STARTED;\r
358 }\r
359\r
360 UsbBusDev->UsbHCInterface = UsbHCInterface;\r
361\r
362 //\r
363 // Attach EFI_USB_BUS_PROTOCOL to controller handle,\r
364 // for locate UsbBusDev later\r
365 //\r
366 Status = gBS->InstallProtocolInterface (\r
367 &Controller,\r
368 &mUsbBusProtocolGuid,\r
369 EFI_NATIVE_INTERFACE,\r
370 &UsbBusDev->BusIdentify\r
371 );\r
372\r
373 if (EFI_ERROR (Status)) {\r
374\r
375 gBS->CloseProtocol (\r
376 Controller,\r
377 &gEfiDevicePathProtocolGuid,\r
378 This->DriverBindingHandle,\r
379 Controller\r
380 );\r
381 gBS->CloseProtocol (\r
382 Controller,\r
383 &gEfiUsbHcProtocolGuid,\r
384 This->DriverBindingHandle,\r
385 Controller\r
386 );\r
387 gBS->FreePool (UsbBusDev);\r
388 return Status;\r
389 }\r
390 //\r
391 // Add root hub to the tree\r
392 //\r
393 RootHub = NULL;\r
394 RootHub = AllocateZeroPool (sizeof (USB_IO_DEVICE));\r
395 if (RootHub == NULL) {\r
396 gBS->UninstallProtocolInterface (\r
397 Controller,\r
398 &mUsbBusProtocolGuid,\r
399 &UsbBusDev->BusIdentify\r
400 );\r
401 gBS->CloseProtocol (\r
402 Controller,\r
403 &gEfiDevicePathProtocolGuid,\r
404 This->DriverBindingHandle,\r
405 Controller\r
406 );\r
407 gBS->CloseProtocol (\r
408 Controller,\r
409 &gEfiUsbHcProtocolGuid,\r
410 This->DriverBindingHandle,\r
411 Controller\r
412 );\r
413 gBS->FreePool (UsbBusDev);\r
414 return EFI_OUT_OF_RESOURCES;\r
415 }\r
416\r
417 RootHub->BusController = UsbBusDev;\r
418 RootHub->DeviceAddress = UsbAllocateAddress (UsbBusDev->AddressPool);\r
419\r
420 UsbBusDev->Root = RootHub;\r
421\r
422 //\r
423 // Allocate Root Hub Controller\r
424 //\r
425 RootHubController = CreateUsbIoControllerDevice ();\r
426 if (RootHubController == NULL) {\r
427 gBS->UninstallProtocolInterface (\r
428 Controller,\r
429 &mUsbBusProtocolGuid,\r
430 &UsbBusDev->BusIdentify\r
431 );\r
432 gBS->CloseProtocol (\r
433 Controller,\r
434 &gEfiDevicePathProtocolGuid,\r
435 This->DriverBindingHandle,\r
436 Controller\r
437 );\r
438 gBS->CloseProtocol (\r
439 Controller,\r
440 &gEfiUsbHcProtocolGuid,\r
441 This->DriverBindingHandle,\r
442 Controller\r
443 );\r
444 gBS->FreePool (UsbBusDev);\r
445 gBS->FreePool (RootHub);\r
446 return EFI_OUT_OF_RESOURCES;\r
447 }\r
448\r
449 UsbHCInterface->GetRootHubPortNumber (\r
450 UsbHCInterface,\r
451 &RootHubController->DownstreamPorts\r
452 );\r
453 RootHubController->UsbDevice = RootHub;\r
454 RootHubController->IsUsbHub = TRUE;\r
455 RootHubController->DevicePath = UsbBusDev->DevicePath;\r
456 RootHubController->HostController = Controller;\r
457\r
458 RootHub->NumOfControllers = 1;\r
459 RootHub->UsbController[0] = RootHubController;\r
460\r
461 //\r
462 // Report Status Code here since we will reset the host controller\r
463 //\r
464 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
465 EFI_PROGRESS_CODE,\r
466 EFI_IO_BUS_USB | EFI_IOB_PC_RESET,\r
467 UsbBusDev->DevicePath\r
468 );\r
469\r
470 //\r
471 // Reset USB Host Controller\r
472 //\r
473 UsbHCInterface->Reset (\r
474 UsbHCInterface,\r
475 EFI_USB_HC_RESET_GLOBAL\r
476 );\r
477\r
478 //\r
479 // Report Status Code while we are going to bring up the Host Controller\r
480 // and start bus enumeration\r
481 //\r
482 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
483 EFI_PROGRESS_CODE,\r
484 EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE,\r
485 UsbBusDev->DevicePath\r
486 );\r
487\r
488 //\r
489 // Start USB Host Controller\r
490 //\r
491 UsbHCInterface->SetState (\r
492 UsbHCInterface,\r
493 EfiUsbHcStateOperational\r
494 );\r
495\r
496 //\r
497 // Create a timer to query root ports periodically\r
498 //\r
499 Status = gBS->CreateEvent (\r
500 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
501 EFI_TPL_CALLBACK,\r
502 UsbEnumeration,\r
503 RootHubController,\r
504 &RootHubController->HubNotify\r
505 );\r
506 if (EFI_ERROR (Status)) {\r
507 gBS->UninstallProtocolInterface (\r
508 Controller,\r
509 &mUsbBusProtocolGuid,\r
510 &UsbBusDev->BusIdentify\r
511 );\r
512\r
513 gBS->CloseProtocol (\r
514 Controller,\r
515 &gEfiDevicePathProtocolGuid,\r
516 This->DriverBindingHandle,\r
517 Controller\r
518 );\r
519\r
520 gBS->CloseProtocol (\r
521 Controller,\r
522 &gEfiUsbHcProtocolGuid,\r
523 This->DriverBindingHandle,\r
524 Controller\r
525 );\r
526\r
527 gBS->FreePool (RootHubController);\r
528 gBS->FreePool (RootHub);\r
529 gBS->FreePool (UsbBusDev);\r
530 return EFI_UNSUPPORTED;\r
531 }\r
532\r
533 //\r
534 // Before depending on the timer to check root ports periodically,\r
535 // here we should check them immediately for the first time, or\r
536 // there will be an interval between bus start and devices start.\r
537 //\r
538 gBS->SignalEvent (RootHubController->HubNotify);\r
539 \r
540 Status = gBS->SetTimer (\r
541 RootHubController->HubNotify,\r
542 TimerPeriodic,\r
543 BUSPOLLING_PERIOD\r
544 );\r
545 if (EFI_ERROR (Status)) {\r
546 gBS->UninstallProtocolInterface (\r
547 Controller,\r
548 &mUsbBusProtocolGuid,\r
549 &UsbBusDev->BusIdentify\r
550 );\r
551\r
552 gBS->CloseProtocol (\r
553 Controller,\r
554 &gEfiDevicePathProtocolGuid,\r
555 This->DriverBindingHandle,\r
556 Controller\r
557 );\r
558\r
559 gBS->CloseProtocol (\r
560 Controller,\r
561 &gEfiUsbHcProtocolGuid,\r
562 This->DriverBindingHandle,\r
563 Controller\r
564 );\r
565\r
566 gBS->CloseEvent (RootHubController->HubNotify);\r
567 gBS->FreePool (RootHubController);\r
568 gBS->FreePool (RootHub);\r
569 gBS->FreePool (UsbBusDev);\r
570 return EFI_UNSUPPORTED;\r
571 }\r
572\r
573 return EFI_SUCCESS;\r
574}\r
575//\r
576// Stop the bus controller\r
577//\r
578EFI_STATUS\r
579EFIAPI\r
580UsbBusControllerDriverStop (\r
581 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
582 IN EFI_HANDLE Controller,\r
583 IN UINTN NumberOfChildren,\r
584 IN EFI_HANDLE *ChildHandleBuffer\r
585 )\r
586/*++\r
587\r
588 Routine Description:\r
589 Stop this driver on ControllerHandle. Support stoping any child handles\r
590 created by this driver.\r
591\r
592 Arguments:\r
593 This - Protocol instance pointer.\r
594 Controller - Handle of device to stop driver on\r
595 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
596 ChildHandleBuffer - List of handles for the children we need to stop.\r
597\r
598 Returns:\r
599 EFI_SUCCESS\r
600 EFI_DEVICE_ERROR\r
601 others\r
602\r
603--*/\r
604{\r
605 EFI_STATUS Status;\r
606 USB_IO_DEVICE *Root;\r
607 USB_IO_CONTROLLER_DEVICE *RootHubController;\r
608 USB_BUS_CONTROLLER_DEVICE *UsbBusController;\r
609 EFI_USB_BUS_PROTOCOL *UsbIdentifier;\r
610 UINT8 Index2;\r
611 EFI_USB_HC_PROTOCOL *UsbHCInterface;\r
612 USB_IO_CONTROLLER_DEVICE *UsbController;\r
613 USB_IO_DEVICE *UsbIoDevice;\r
614 USB_IO_CONTROLLER_DEVICE *HubController;\r
615 UINTN Index;\r
616 EFI_USB_IO_PROTOCOL *UsbIo;\r
617\r
618 if (NumberOfChildren > 0) {\r
619\r
620 for (Index = 0; Index < NumberOfChildren; Index++) {\r
621 Status = gBS->OpenProtocol (\r
622 ChildHandleBuffer[Index],\r
623 &gEfiUsbIoProtocolGuid,\r
624 (VOID **) &UsbIo,\r
625 This->DriverBindingHandle,\r
626 Controller,\r
627 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
628 );\r
629 if (EFI_ERROR (Status)) {\r
630 //\r
631 // We are here since the handle passed in does not support\r
632 // UsbIo protocol. There are several reasons that will cause\r
633 // this.\r
634 // For combo device such as keyboard, it may have 2 devices\r
635 // in one, namely, keyboard and mouse. If we deconfigure one\r
636 // of them, the other will be freed at the same time. This will\r
637 // cause the status error. But this is the correct behavior.\r
638 // For hub device, if we deconfigure hub first, the other chile\r
639 // device will be disconnected also, this will also provide us\r
640 // a status error. Now we will only report EFI_SUCCESS since Uhc\r
641 // driver will be disconnected at the second time.(pls see\r
642 // CoreDisconnectController for details)\r
643 //\r
644 continue;\r
645 }\r
646\r
647 UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo);\r
648 UsbIoDevice = UsbController->UsbDevice;\r
649 HubController = UsbController->Parent;\r
650 UsbDeviceDeConfiguration (UsbIoDevice);\r
651 for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) {\r
652 if (HubController->Children[Index2] == UsbIoDevice) {\r
653 HubController->Children[Index2] = NULL;\r
654 }\r
655 }\r
656 }\r
657\r
658 return EFI_SUCCESS;\r
659 }\r
660 //\r
661 // Get the USB_BUS_CONTROLLER_DEVICE\r
662 //\r
663 Status = gBS->OpenProtocol (\r
664 Controller,\r
665 &mUsbBusProtocolGuid,\r
666 (VOID **) &UsbIdentifier,\r
667 This->DriverBindingHandle,\r
668 Controller,\r
669 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
670 );\r
671\r
672 if (EFI_ERROR (Status)) {\r
673 return EFI_DEVICE_ERROR;\r
674 }\r
675\r
676 UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier);\r
677\r
678 //\r
679 // Stop USB Host Controller\r
680 //\r
681 UsbHCInterface = UsbBusController->UsbHCInterface;\r
682\r
683 //\r
684 // Report Status Code here since we will reset the host controller\r
685 //\r
686 ReportUsbStatusCode (\r
687 UsbBusController,\r
688 EFI_PROGRESS_CODE,\r
689 EFI_IO_BUS_USB | EFI_IOB_PC_RESET\r
690 );\r
691\r
692 UsbHCInterface->SetState (\r
693 UsbHCInterface,\r
694 EfiUsbHcStateHalt\r
695 );\r
696\r
697 //\r
698 // Deconfiguration all its devices\r
699 //\r
700 Root = UsbBusController->Root;\r
701 RootHubController = Root->UsbController[0];\r
702\r
703 gBS->CloseEvent (RootHubController->HubNotify);\r
704\r
705 for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) {\r
706 if (RootHubController->Children[Index2]) {\r
707 UsbDeviceDeConfiguration (RootHubController->Children[Index2]);\r
708 RootHubController->Children[Index2] = NULL;\r
709 }\r
710 }\r
711\r
712 gBS->FreePool (RootHubController);\r
713 gBS->FreePool (Root);\r
714\r
715 //\r
716 // Uninstall USB Bus Protocol\r
717 //\r
718 gBS->UninstallProtocolInterface (\r
719 Controller,\r
720 &mUsbBusProtocolGuid,\r
721 &UsbBusController->BusIdentify\r
722 );\r
723\r
724 //\r
725 // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL\r
726 // Opened by this Controller\r
727 //\r
728 gBS->CloseProtocol (\r
729 Controller,\r
730 &gEfiUsbHcProtocolGuid,\r
731 This->DriverBindingHandle,\r
732 Controller\r
733 );\r
734\r
735 gBS->CloseProtocol (\r
736 Controller,\r
737 &gEfiDevicePathProtocolGuid,\r
738 This->DriverBindingHandle,\r
739 Controller\r
740 );\r
741\r
742 gBS->FreePool (UsbBusController);\r
743\r
744 return EFI_SUCCESS;\r
745}\r
746//\r
747// USB Device Configuration\r
748//\r
749STATIC\r
750EFI_STATUS\r
751UsbDeviceConfiguration (\r
752 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,\r
753 IN EFI_HANDLE HostController,\r
754 IN UINT8 ParentPort,\r
755 IN USB_IO_DEVICE *UsbIoDevice\r
756 )\r
757/*++\r
758\r
759 Routine Description:\r
760 Configurate a new device attached to the usb bus\r
761\r
762 Arguments:\r
763 ParentHubController - Parent Hub which this device is connected.\r
764 HostController - Host Controller handle\r
765 ParentPort - Parent Hub port which this device is connected.\r
766 UsbIoDevice - The device to be configured.\r
767\r
768 Returns:\r
769 EFI_SUCCESS\r
770 EFI_DEVICE_ERROR\r
771 EFI_OUT_OF_RESOURCES\r
772\r
773--*/\r
774{\r
775 UINT8 DevAddress;\r
776 UINT8 Index;\r
777 EFI_STATUS Result;\r
778 UINT32 Status;\r
779 CHAR16 *StrManufacturer;\r
780 CHAR16 *StrProduct;\r
781 CHAR16 *StrSerialNumber;\r
782 EFI_USB_IO_PROTOCOL *UsbIo;\r
783 UINT8 NumOfInterface;\r
784 USB_IO_CONTROLLER_DEVICE *FirstController;\r
785 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
786 USB_IO_CONTROLLER_DEVICE *UsbIoController;\r
787\r
788 UsbBusDev = UsbIoDevice->BusController;\r
789 //\r
790 // Since a USB device must have at least on interface,\r
791 // so create this instance first\r
792 //\r
793 FirstController = CreateUsbIoControllerDevice ();\r
794 FirstController->UsbDevice = UsbIoDevice;\r
795 UsbIoDevice->UsbController[0] = FirstController;\r
796 FirstController->InterfaceNumber = 0;\r
797 FirstController->ParentPort = ParentPort;\r
798 FirstController->Parent = ParentHubController;\r
799 FirstController->HostController = HostController;\r
800\r
801 InitializeUsbIoInstance (FirstController);\r
802\r
803 DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort));\r
804\r
805 //\r
806 // Ensure we used the correctly USB I/O instance\r
807 //\r
808 UsbIo = &FirstController->UsbIo;\r
809\r
810 //\r
811 // First retrieve the 1st 8 bytes of\r
812 // in order to get the MaxPacketSize for Endpoint 0\r
813 //\r
814 for (Index = 0; Index < 3; Index++) {\r
815\r
816 UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;\r
817\r
818 ParentPortReset (FirstController, FALSE, Index);\r
819\r
820 Result = UsbGetDescriptor (\r
821 UsbIo,\r
822 (USB_DT_DEVICE << 8),\r
823 0,\r
824 8,\r
825 &UsbIoDevice->DeviceDescriptor,\r
826 &Status\r
827 );\r
828 if (!EFI_ERROR (Result)) {\r
829 DEBUG ((gUSBDebugLevel,\r
830 "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",\r
831 UsbIoDevice->DeviceDescriptor.MaxPacketSize0)\r
832 );\r
833 break;\r
834 }\r
835\r
836 }\r
837\r
838 if (Index == 3) {\r
839 ReportUsbStatusCode (\r
840 UsbBusDev,\r
841 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
842 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR\r
843 );\r
844 DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n"));\r
845 gBS->FreePool (FirstController);\r
846 return EFI_DEVICE_ERROR;\r
847 }\r
848\r
849 DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool);\r
850 if (DevAddress == 0) {\r
851 DEBUG ((gUSBErrorLevel, "Cannot allocate address\n"));\r
852 gBS->FreePool (FirstController);\r
853 return EFI_OUT_OF_RESOURCES;\r
854 }\r
855\r
856 Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status);\r
857\r
858 if (EFI_ERROR (Result)) {\r
859 DEBUG ((gUSBErrorLevel, "Set address error\n"));\r
860 ReportUsbStatusCode (\r
861 UsbBusDev,\r
862 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
863 EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR\r
864 );\r
865\r
866 UsbFreeAddress (\r
867 DevAddress,\r
868 UsbIoDevice->BusController->AddressPool\r
869 );\r
870\r
871 gBS->FreePool (FirstController);\r
872 return EFI_DEVICE_ERROR;\r
873 }\r
874\r
875 UsbIoDevice->DeviceAddress = DevAddress;\r
876\r
877 //\r
878 // Get the whole device descriptor\r
879 //\r
880 Result = UsbGetDescriptor (\r
881 UsbIo,\r
882 (USB_DT_DEVICE << 8),\r
883 0,\r
884 sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
885 &UsbIoDevice->DeviceDescriptor,\r
886 &Status\r
887 );\r
888\r
889 if (EFI_ERROR (Result)) {\r
890 DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n"));\r
891 ReportUsbStatusCode (\r
892 UsbBusDev,\r
893 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
894 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR\r
895 );\r
896 UsbFreeAddress (\r
897 DevAddress,\r
898 UsbIoDevice->BusController->AddressPool\r
899 );\r
900\r
901 gBS->FreePool (FirstController);\r
902 return EFI_DEVICE_ERROR;\r
903 }\r
904 //\r
905 // Get & parse all configurations for this device, including\r
906 // all configuration descriptors, all interface descriptors, all\r
907 // endpoint descriptors\r
908 //\r
909 Result = UsbGetAllConfigurations (UsbIoDevice);\r
910\r
911 if (EFI_ERROR (Result)) {\r
912 DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n"));\r
913 ReportUsbStatusCode (\r
914 UsbBusDev,\r
915 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
916 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR\r
917 );\r
918 UsbFreeAddress (\r
919 DevAddress,\r
920 UsbIoDevice->BusController->AddressPool\r
921 );\r
922\r
923 gBS->FreePool (FirstController);\r
924 return EFI_DEVICE_ERROR;\r
925 }\r
926 //\r
927 // Set the 1st configuration value\r
928 //\r
929 Result = UsbSetDefaultConfiguration (UsbIoDevice);\r
930 if (EFI_ERROR (Result)) {\r
931 DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n"));\r
932 ReportUsbStatusCode (\r
933 UsbBusDev,\r
934 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
935 EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR\r
936 );\r
937 UsbFreeAddress (\r
938 DevAddress,\r
939 UsbIoDevice->BusController->AddressPool\r
940 );\r
941\r
942 gBS->FreePool (FirstController);\r
943 return EFI_DEVICE_ERROR;\r
944 }\r
945\r
946 UsbIoDevice->IsConfigured = TRUE;\r
947\r
948 //\r
949 // Get all string table if applicable\r
950 //\r
951 Result = UsbGetStringtable (UsbIoDevice);\r
952 if (EFI_ERROR (Result)) {\r
953 DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n"));\r
954 } else {\r
955\r
956 StrManufacturer = NULL;\r
957 UsbIo->UsbGetStringDescriptor (\r
958 UsbIo,\r
959 UsbIoDevice->LangID[0],\r
960 (UsbIoDevice->DeviceDescriptor).StrManufacturer,\r
961 &StrManufacturer\r
962 );\r
963\r
964 StrProduct = NULL;\r
965 UsbIo->UsbGetStringDescriptor (\r
966 UsbIo,\r
967 UsbIoDevice->LangID[0],\r
968 (UsbIoDevice->DeviceDescriptor).StrProduct,\r
969 &StrProduct\r
970 );\r
971\r
972 StrSerialNumber = NULL;\r
973 UsbIo->UsbGetStringDescriptor (\r
974 UsbIo,\r
975 UsbIoDevice->LangID[0],\r
976 (UsbIoDevice->DeviceDescriptor).StrSerialNumber,\r
977 &StrSerialNumber\r
978 );\r
979\r
980 if (StrManufacturer) {\r
981 gBS->FreePool (StrManufacturer);\r
982 }\r
983\r
984 if (StrProduct) {\r
985 gBS->FreePool (StrProduct);\r
986 }\r
987\r
988 if (StrSerialNumber) {\r
989 gBS->FreePool (StrSerialNumber);\r
990 }\r
991 }\r
992 //\r
993 // Create USB_IO_CONTROLLER_DEVICE for\r
994 // each detected interface\r
995 //\r
996 FirstController->CurrentConfigValue =\r
997 UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;\r
998\r
999 NumOfInterface =\r
1000 UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces;\r
1001 UsbIoDevice->NumOfControllers = NumOfInterface;\r
1002\r
1003 Result = InitUsbIoController (FirstController);\r
1004 if (EFI_ERROR (Result)) {\r
1005 ReportUsbStatusCode (\r
1006 UsbBusDev,\r
1007 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1008 EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR\r
1009 );\r
1010 gBS->FreePool (FirstController);\r
1011 UsbIoDevice->UsbController[0] = NULL;\r
1012 return EFI_DEVICE_ERROR;\r
1013 }\r
1014\r
1015 for (Index = 1; Index < NumOfInterface; Index++) {\r
1016 UsbIoController = CreateUsbIoControllerDevice ();\r
1017 UsbIoController->UsbDevice = UsbIoDevice;\r
1018 UsbIoController->CurrentConfigValue =\r
1019 UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;\r
1020 UsbIoController->InterfaceNumber = Index;\r
1021 UsbIoDevice->UsbController[Index] = UsbIoController;\r
1022 UsbIoController->ParentPort = ParentPort;\r
1023 UsbIoController->Parent = ParentHubController;\r
1024 UsbIoController->HostController = HostController;\r
1025\r
1026 //\r
1027 // First copy the USB_IO Protocol instance\r
1028 //\r
1029 CopyMem (\r
1030 &UsbIoController->UsbIo,\r
1031 UsbIo,\r
1032 sizeof (EFI_USB_IO_PROTOCOL)\r
1033 );\r
1034\r
1035 Result = InitUsbIoController (UsbIoController);\r
1036 if (EFI_ERROR (Result)) {\r
1037 ReportUsbStatusCode (\r
1038 UsbBusDev,\r
1039 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1040 EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR\r
1041 );\r
1042 gBS->FreePool (UsbIoController);\r
1043 UsbIoDevice->UsbController[Index] = NULL;\r
1044 }\r
1045 }\r
1046\r
1047 return EFI_SUCCESS;\r
1048}\r
1049//\r
1050// USB Device DeConfiguration\r
1051//\r
1052\r
1053EFI_STATUS\r
1054UsbDeviceDeConfiguration (\r
1055 IN USB_IO_DEVICE *UsbIoDevice\r
1056 )\r
1057/*++\r
1058\r
1059 Routine Description:\r
1060 Remove Device, Device Handles, Uninstall Protocols.\r
1061\r
1062 Arguments:\r
1063 UsbIoDevice - The device to be deconfigured.\r
1064\r
1065 Returns: \r
1066 EFI_SUCCESS\r
1067 EFI_DEVICE_ERROR\r
1068\r
1069--*/\r
1070{\r
1071 USB_IO_CONTROLLER_DEVICE *UsbController;\r
1072 UINT8 index;\r
1073 USB_IO_DEVICE *ChildDevice;\r
1074 UINT8 Index;\r
1075 EFI_USB_IO_PROTOCOL *UsbIo;\r
1076\r
1077 DEBUG ((gUSBDebugLevel, "Enter Usb Device Deconfiguration\n"));\r
1078\r
1079 //\r
1080 // Double check UsbIoDevice exists\r
1081 //\r
1082 if (UsbIoDevice == NULL) {\r
1083 return EFI_SUCCESS;\r
1084 }\r
1085\r
1086 for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {\r
1087 //\r
1088 // Check if it is a hub, if so, de configuration all its\r
1089 // downstream ports\r
1090 //\r
1091 UsbController = UsbIoDevice->UsbController[index];\r
1092\r
1093 //\r
1094 // Check the controller pointer\r
1095 //\r
1096 if (UsbController == NULL) {\r
1097 continue;\r
1098 }\r
1099\r
1100 if (UsbController->IsUsbHub) {\r
1101\r
1102 DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n"));\r
1103\r
1104 //\r
1105 // First Remove interrupt transfer request for the status\r
1106 // change port\r
1107 //\r
1108 UsbIo = &UsbController->UsbIo;\r
1109 UsbIo->UsbAsyncInterruptTransfer (\r
1110 UsbIo,\r
1111 UsbController->HubEndpointAddress,\r
1112 FALSE,\r
1113 0,\r
1114 0,\r
1115 NULL,\r
1116 NULL\r
1117 );\r
1118\r
1119 if (NULL != UsbController->HubNotify) {\r
1120 gBS->CloseEvent (UsbController->HubNotify);\r
1121 }\r
1122\r
1123 for (Index = 0; Index < UsbController->DownstreamPorts; Index++) {\r
1124 if (UsbController->Children[Index]) {\r
1125 ChildDevice = UsbController->Children[Index];\r
1126 UsbDeviceDeConfiguration (ChildDevice);\r
1127 UsbController->Children[Index] = NULL;\r
1128 }\r
1129 }\r
1130 }\r
1131 //\r
1132 // If the controller is managed by a device driver, we need to\r
1133 // disconnect them\r
1134 //\r
1135 if (UsbController->IsManagedByDriver) {\r
1136 gBS->DisconnectController (\r
1137 UsbController->Handle,\r
1138 NULL,\r
1139 NULL\r
1140 );\r
1141 }\r
1142 \r
1143 //\r
1144 // remove child handle reference to the USB_HC_PROTOCOL\r
1145 //\r
1146 gBS->CloseProtocol (\r
1147 UsbController->HostController,\r
1148 &gEfiUsbHcProtocolGuid,\r
1149 gUsbBusDriverBinding.DriverBindingHandle,\r
1150 UsbController->Handle\r
1151 );\r
1152\r
1153 //\r
1154 // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL\r
1155 // installed on this handle\r
1156 //\r
1157 gBS->UninstallMultipleProtocolInterfaces (\r
1158 UsbController->Handle,\r
1159 &gEfiDevicePathProtocolGuid,\r
1160 UsbController->DevicePath,\r
1161 &gEfiUsbIoProtocolGuid,\r
1162 &UsbController->UsbIo,\r
1163 NULL\r
1164 );\r
1165\r
1166 if (UsbController->DevicePath != NULL) {\r
1167 gBS->FreePool (UsbController->DevicePath);\r
1168 }\r
1169\r
1170 gBS->FreePool (UsbController);\r
1171 UsbIoDevice->UsbController[index] = NULL;\r
1172 }\r
1173 //\r
1174 // Free address for later use\r
1175 //\r
1176 UsbFreeAddress (\r
1177 UsbIoDevice->DeviceAddress,\r
1178 UsbIoDevice->BusController->AddressPool\r
1179 );\r
1180\r
1181 //\r
1182 // Free all resouces allocated for all its configurations\r
1183 //\r
1184 UsbDestroyAllConfiguration (UsbIoDevice);\r
1185\r
1186 if (UsbIoDevice) {\r
1187 gBS->FreePool (UsbIoDevice);\r
1188 UsbIoDevice = NULL;\r
1189 }\r
1190\r
1191 return EFI_SUCCESS;\r
1192}\r
1193//\r
1194// After interrupt complete, this function will be called,\r
1195// This function need to be well-defined later\r
1196//\r
1197STATIC\r
1198EFI_STATUS\r
1199EFIAPI\r
1200OnHubInterruptComplete (\r
1201 IN VOID *Data,\r
1202 IN UINTN DataLength,\r
1203 IN VOID *Context,\r
1204 IN UINT32 Result\r
1205 )\r
1206/*++\r
1207\r
1208 Routine Description:\r
1209 Whenever hub interrupt occurs, this routine will be called to check\r
1210 which event happens.\r
1211\r
1212 Arguments:\r
1213 Data - Hub interrupt transfer data.\r
1214 DataLength - The length of the Data.\r
1215 Context - Hub Controller Device.\r
1216 Result - Hub interrupt transfer status.\r
1217\r
1218 Returns:\r
1219 EFI_SUCCESS\r
1220 EFI_DEVICE_ERROR\r
1221\r
1222--*/\r
1223{\r
1224 USB_IO_CONTROLLER_DEVICE *HubController;\r
1225 UINT8 Index;\r
1226 UINT8 *ptr;\r
1227 EFI_USB_IO_PROTOCOL *UsbIo;\r
1228 UINT32 UsbResult;\r
1229 BOOLEAN Disconnected;\r
1230 EFI_STATUS Status;\r
1231\r
1232 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;\r
1233 UsbIo = &HubController->UsbIo;\r
1234\r
1235 //\r
1236 // If something error in this interrupt transfer,\r
1237 //\r
1238 if (Result != EFI_USB_NOERROR) {\r
1239 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
1240 UsbClearEndpointHalt (\r
1241 UsbIo,\r
1242 HubController->HubEndpointAddress,\r
1243 &UsbResult\r
1244 );\r
1245 }\r
1246 \r
1247 //\r
1248 // Delete & Submit this interrupt again\r
1249 //\r
1250 UsbIo->UsbAsyncInterruptTransfer (\r
1251 UsbIo,\r
1252 HubController->HubEndpointAddress,\r
1253 FALSE,\r
1254 0,\r
1255 0,\r
1256 NULL,\r
1257 NULL\r
1258 );\r
1259\r
1260 //\r
1261 // try to detect if the hub itself was disconnected or not\r
1262 //\r
1263 Status = IsDeviceDisconnected (\r
1264 HubController,\r
1265 &Disconnected\r
1266 );\r
1267\r
1268 if (!EFI_ERROR (Status) && Disconnected == TRUE) {\r
1269 DEBUG ((gUSBErrorLevel, "Hub is disconnected\n"));\r
1270 return EFI_DEVICE_ERROR;\r
1271 }\r
1272 //\r
1273 // Hub ports < 7\r
1274 //\r
1275 UsbIo->UsbAsyncInterruptTransfer (\r
1276 UsbIo,\r
1277 HubController->HubEndpointAddress,\r
1278 TRUE,\r
1279 100,\r
1280 1,\r
1281 OnHubInterruptComplete,\r
1282 HubController\r
1283 );\r
1284\r
1285 return EFI_DEVICE_ERROR;\r
1286 }\r
1287\r
1288 if (DataLength == 0 || Data == NULL) {\r
1289 return EFI_SUCCESS;\r
1290 }\r
1291 \r
1292 //\r
1293 // Scan which port has status change\r
1294 // Bit 0 stands for hub itself, other bit stands for\r
1295 // the corresponding port\r
1296 //\r
1297 for (Index = 0; Index < DataLength * 8; Index++) {\r
1298 ptr = (UINT8 *) Data + Index / 8;\r
1299 if ((*ptr) & (1 << (Index & 0x7))) {\r
1300 HubController->StatusChangePort = Index;\r
1301 break;\r
1302 }\r
1303 }\r
1304 //\r
1305 // Signal hub notify event\r
1306 //\r
1307 gBS->SignalEvent (HubController->HubNotify);\r
1308\r
1309 return EFI_SUCCESS;\r
1310}\r
1311//\r
1312// USB Root Hub Enumerator\r
1313//\r
1314STATIC\r
1315VOID\r
1316EFIAPI\r
1317UsbEnumeration (\r
1318 IN EFI_EVENT Event,\r
1319 IN VOID *Context\r
1320 )\r
1321/*++\r
1322\r
1323 Routine Description:\r
1324 This is USB enumerator\r
1325\r
1326 Arguments:\r
1327 Event - Indicating which event is signaled\r
1328 Context - actually it is a USB_IO_DEVICE\r
1329\r
1330 Returns:\r
1331 EFI_SUCCESS\r
1332 Others\r
1333\r
1334--*/\r
1335{\r
1336 USB_IO_CONTROLLER_DEVICE *HubController;\r
1337 EFI_USB_PORT_STATUS HubPortStatus;\r
1338 EFI_STATUS Status;\r
1339 UINT8 Index;\r
1340 EFI_USB_HC_PROTOCOL *UsbHCInterface;\r
1341 USB_IO_DEVICE *UsbIoDev;\r
1342 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
1343 EFI_HANDLE HostController;\r
1344 USB_IO_DEVICE *OldUsbIoDevice;\r
1345 USB_IO_DEVICE *NewDevice;\r
1346 USB_IO_CONTROLLER_DEVICE *NewController;\r
1347 UINT8 Index2;\r
1348 EFI_USB_IO_PROTOCOL *UsbIo;\r
1349 UINT8 StatusChangePort;\r
1350\r
1351 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;\r
1352 HostController = HubController->HostController;\r
1353 UsbBusDev = HubController->UsbDevice->BusController;\r
1354\r
1355 if (HubController->UsbDevice->DeviceAddress == 1) {\r
1356 //\r
1357 // Root hub has the address 1\r
1358 //\r
1359 UsbIoDev = HubController->UsbDevice;\r
1360 UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;\r
1361\r
1362 for (Index = 0; Index < HubController->DownstreamPorts; Index++) {\r
1363 UsbHCInterface->GetRootHubPortStatus (\r
1364 UsbHCInterface,\r
1365 Index,\r
1366 (EFI_USB_PORT_STATUS *) &HubPortStatus\r
1367 );\r
1368\r
1369 if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {\r
1370 continue;\r
1371 }\r
1372 //\r
1373 // Clear root hub status change status\r
1374 //\r
1375 ClearRootPortConnectionChangeStatus (\r
1376 Index,\r
1377 UsbHCInterface\r
1378 );\r
1379\r
1380 gBS->Stall (100 * 1000);\r
1381\r
1382 UsbHCInterface->GetRootHubPortStatus (\r
1383 UsbHCInterface,\r
1384 Index,\r
1385 (EFI_USB_PORT_STATUS *) &HubPortStatus\r
1386 );\r
1387\r
1388 if (IsPortConnect (HubPortStatus.PortStatus)) {\r
1389 \r
1390 //\r
1391 // There is something connected to this port\r
1392 //\r
1393 DEBUG ((gUSBDebugLevel, "Something attached from Root Hub in 0x%x\n", Index));\r
1394\r
1395 ReportUsbStatusCode (\r
1396 UsbBusDev,\r
1397 EFI_PROGRESS_CODE,\r
1398 EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG\r
1399 );\r
1400 //\r
1401 // if there is something physically detached, but still logically\r
1402 // attached...\r
1403 //\r
1404 OldUsbIoDevice = HubController->Children[Index];\r
1405\r
1406 if (NULL != OldUsbIoDevice) {\r
1407 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
1408 HubController->Children[Index] = NULL;\r
1409 }\r
1410\r
1411 NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));\r
1412 if (NewDevice == NULL) {\r
1413 return ;\r
1414 }\r
1415 //\r
1416 // Initialize some fields by copying data from\r
1417 // its parents\r
1418 //\r
1419 NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);\r
1420\r
1421 DEBUG ((gUSBDebugLevel, "DeviceSpeed 0x%x\n", NewDevice->IsSlowDevice));\r
1422\r
1423 NewDevice->BusController = UsbIoDev->BusController;\r
1424\r
1425 //\r
1426 // Configure that device\r
1427 //\r
1428 Status = UsbDeviceConfiguration (\r
1429 HubController,\r
1430 HostController,\r
1431 Index,\r
1432 NewDevice\r
1433 );\r
1434 if (EFI_ERROR (Status)) {\r
1435 gBS->FreePool (NewDevice);\r
1436 return ;\r
1437 }\r
1438 //\r
1439 // Add this device to the usb bus tree\r
1440 //\r
1441 HubController->Children[Index] = NewDevice;\r
1442\r
1443 for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {\r
1444 //\r
1445 // If this device is hub, add to the hub index\r
1446 //\r
1447 NewController = NewDevice->UsbController[Index2];\r
1448\r
1449 Status = gBS->ConnectController (\r
1450 NewController->Handle,\r
1451 NULL,\r
1452 NULL,\r
1453 TRUE\r
1454 );\r
1455 //\r
1456 // If connect success, we need to disconnect when\r
1457 // stop the controller, otherwise we need not call\r
1458 // gBS->DisconnectController ()\r
1459 // This is used by those usb devices we don't plan\r
1460 // to support. We can allocate\r
1461 // controller handles for them, but we don't have\r
1462 // device drivers to manage them.\r
1463 //\r
1464 NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));\r
1465\r
1466 if (IsHub (NewController)) {\r
1467\r
1468 NewController->IsUsbHub = TRUE;\r
1469\r
1470 //\r
1471 // Configure Hub Controller\r
1472 //\r
1473 Status = DoHubConfig (NewController);\r
1474 if (EFI_ERROR (Status)) {\r
1475 continue;\r
1476 }\r
1477 //\r
1478 // Create an event to do hub enumeration\r
1479 //\r
1480 gBS->CreateEvent (\r
1481 EFI_EVENT_NOTIFY_SIGNAL,\r
1482 EFI_TPL_CALLBACK,\r
1483 UsbEnumeration,\r
1484 NewController,\r
1485 &NewController->HubNotify\r
1486 );\r
1487\r
1488 //\r
1489 // Add request to do query hub status\r
1490 // change endpoint\r
1491 // Hub ports < 7\r
1492 //\r
1493 UsbIo = &NewController->UsbIo;\r
1494 UsbIo->UsbAsyncInterruptTransfer (\r
1495 UsbIo,\r
1496 NewController->HubEndpointAddress,\r
1497 TRUE,\r
1498 100,\r
1499 1,\r
1500 OnHubInterruptComplete,\r
1501 NewController\r
1502 );\r
1503\r
1504 }\r
1505 }\r
1506 } else {\r
1507 //\r
1508 // Something disconnected from USB root hub\r
1509 //\r
1510 DEBUG ((gUSBDebugLevel, "Something deteached from Root Hub\n"));\r
1511\r
1512 OldUsbIoDevice = HubController->Children[Index];\r
1513\r
1514 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
1515\r
1516 HubController->Children[Index] = NULL;\r
1517\r
1518 UsbHCInterface->ClearRootHubPortFeature (\r
1519 UsbHCInterface,\r
1520 Index,\r
1521 EfiUsbPortEnableChange\r
1522 );\r
1523\r
1524 UsbHCInterface->GetRootHubPortStatus (\r
1525 UsbHCInterface,\r
1526 Index,\r
1527 (EFI_USB_PORT_STATUS *) &HubPortStatus\r
1528 );\r
1529\r
1530 }\r
1531 }\r
1532\r
1533 return ;\r
1534 } else {\r
1535 //\r
1536 // Event from Hub, Get the hub controller handle\r
1537 //\r
1538 //\r
1539 // Get the status change endpoint\r
1540 //\r
1541 StatusChangePort = HubController->StatusChangePort;\r
1542\r
1543 //\r
1544 // Clear HubController Status Change Bit\r
1545 //\r
1546 HubController->StatusChangePort = 0;\r
1547\r
1548 if (StatusChangePort == 0) {\r
1549 //\r
1550 // Hub changes, we don't handle here\r
1551 //\r
1552 return ;\r
1553 }\r
1554 //\r
1555 // Check which event took place at that port\r
1556 //\r
1557 UsbIo = &HubController->UsbIo;\r
1558 Status = HubGetPortStatus (\r
1559 UsbIo,\r
1560 StatusChangePort,\r
1561 (UINT32 *) &HubPortStatus\r
1562 );\r
1563\r
1564 if (EFI_ERROR (Status)) {\r
1565 return ;\r
1566 }\r
1567 //\r
1568 // Clear some change status\r
1569 //\r
1570 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {\r
1571 //\r
1572 // Clear Hub port enable change\r
1573 //\r
1574 DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));\r
1575 HubClearPortFeature (\r
1576 UsbIo,\r
1577 StatusChangePort,\r
1578 EfiUsbPortEnableChange\r
1579 );\r
1580\r
1581 HubGetPortStatus (\r
1582 UsbIo,\r
1583 StatusChangePort,\r
1584 (UINT32 *) &HubPortStatus\r
1585 );\r
1586 }\r
1587\r
1588 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {\r
1589 //\r
1590 // Clear Hub reset change\r
1591 //\r
1592 DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));\r
1593 HubClearPortFeature (\r
1594 UsbIo,\r
1595 StatusChangePort,\r
1596 EfiUsbPortResetChange\r
1597 );\r
1598\r
1599 HubGetPortStatus (\r
1600 UsbIo,\r
1601 StatusChangePort,\r
1602 (UINT32 *) &HubPortStatus\r
1603 );\r
1604 }\r
1605\r
1606 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {\r
1607 //\r
1608 // Clear Hub overcurrent change\r
1609 //\r
1610 DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));\r
1611 HubClearPortFeature (\r
1612 UsbIo,\r
1613 StatusChangePort,\r
1614 EfiUsbPortOverCurrentChange\r
1615 );\r
1616\r
1617 HubGetPortStatus (\r
1618 UsbIo,\r
1619 StatusChangePort,\r
1620 (UINT32 *) &HubPortStatus\r
1621 );\r
1622 }\r
1623\r
1624 if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {\r
1625 //\r
1626 // First clear port connection change\r
1627 //\r
1628 DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));\r
1629 HubClearPortFeature (\r
1630 UsbIo,\r
1631 StatusChangePort,\r
1632 EfiUsbPortConnectChange\r
1633 );\r
1634\r
1635 HubGetPortStatus (\r
1636 UsbIo,\r
1637 StatusChangePort,\r
1638 (UINT32 *) &HubPortStatus\r
1639 );\r
1640\r
1641 if (IsPortConnect (HubPortStatus.PortStatus)) {\r
1642\r
1643 DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));\r
1644\r
1645 ReportUsbStatusCode (\r
1646 UsbBusDev,\r
1647 EFI_PROGRESS_CODE,\r
1648 EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG\r
1649 );\r
1650\r
1651 //\r
1652 // if there is something physically detached, but still logically\r
1653 // attached...\r
1654 //\r
1655 OldUsbIoDevice = HubController->Children[StatusChangePort - 1];\r
1656\r
1657 if (NULL != OldUsbIoDevice) {\r
1658 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
1659 HubController->Children[StatusChangePort - 1] = NULL;\r
1660 }\r
1661\r
1662 NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));\r
1663 if (NewDevice == NULL) {\r
1664 return ;\r
1665 }\r
1666\r
1667 ResetHubPort (HubController, StatusChangePort);\r
1668\r
1669 HubGetPortStatus (\r
1670 UsbIo,\r
1671 StatusChangePort,\r
1672 (UINT32 *) &HubPortStatus\r
1673 );\r
1674\r
1675 //\r
1676 // Initialize some fields\r
1677 //\r
1678 NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);\r
1679\r
1680 NewDevice->BusController = HubController->UsbDevice->BusController;\r
1681\r
1682 //\r
1683 // Configure that device\r
1684 //\r
1685 Status = UsbDeviceConfiguration (\r
1686 HubController,\r
1687 HostController,\r
1688 (UINT8) (StatusChangePort - 1),\r
1689 NewDevice\r
1690 );\r
1691\r
1692 if (EFI_ERROR (Status)) {\r
1693 gBS->FreePool (NewDevice);\r
1694 return ;\r
1695 }\r
1696 //\r
1697 // Add this device to the usb bus tree\r
1698 // StatusChangePort is begin from 1,\r
1699 //\r
1700 HubController->Children[StatusChangePort - 1] = NewDevice;\r
1701\r
1702 for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {\r
1703 //\r
1704 // If this device is hub, add to the hub index\r
1705 //\r
1706 NewController = NewDevice->UsbController[Index2];\r
1707\r
1708 //\r
1709 // Connect the controller to the driver image\r
1710 //\r
1711 Status = gBS->ConnectController (\r
1712 NewController->Handle,\r
1713 NULL,\r
1714 NULL,\r
1715 TRUE\r
1716 );\r
1717 //\r
1718 // If connect success, we need to disconnect when\r
1719 // stop the controller, otherwise we need not call\r
1720 // gBS->DisconnectController ()\r
1721 // This is used by those usb devices we don't plan\r
1722 // to support. We can allocate\r
1723 // controller handles for them, but we don't have\r
1724 // device drivers to manage them.\r
1725 //\r
1726 NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));\r
1727\r
1728 //\r
1729 // If this device is hub, add to the hub index\r
1730 //\r
1731 if (IsHub (NewController)) {\r
1732\r
1733 NewController->IsUsbHub = TRUE;\r
1734\r
1735 //\r
1736 // Configure Hub\r
1737 //\r
1738 Status = DoHubConfig (NewController);\r
1739\r
1740 if (EFI_ERROR (Status)) {\r
1741 continue;\r
1742 }\r
1743 //\r
1744 // Create an event to do hub enumeration\r
1745 //\r
1746 gBS->CreateEvent (\r
1747 EFI_EVENT_NOTIFY_SIGNAL,\r
1748 EFI_TPL_CALLBACK,\r
1749 UsbEnumeration,\r
1750 NewController,\r
1751 &NewController->HubNotify\r
1752 );\r
1753\r
1754 //\r
1755 // Add request to do query hub status\r
1756 // change endpoint\r
1757 //\r
1758 UsbIo = &NewController->UsbIo;\r
1759 UsbIo->UsbAsyncInterruptTransfer (\r
1760 UsbIo,\r
1761 NewController->HubEndpointAddress, // Hub endpoint address\r
1762 TRUE,\r
1763 100,\r
1764 1, // Hub ports < 7\r
1765 OnHubInterruptComplete,\r
1766 NewController\r
1767 );\r
1768 }\r
1769 }\r
1770 } else {\r
1771 //\r
1772 // Something disconnected from USB hub\r
1773 //\r
1774 DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));\r
1775\r
1776 OldUsbIoDevice = HubController->Children[StatusChangePort - 1];\r
1777\r
1778 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
1779\r
1780 HubController->Children[StatusChangePort - 1] = NULL;\r
1781\r
1782 }\r
1783\r
1784 return ;\r
1785 }\r
1786\r
1787 return ;\r
1788 }\r
1789}\r
1790//\r
1791// Clear port connection change status over a given root hub port\r
1792//\r
1793EFI_STATUS\r
1794ClearRootPortConnectionChangeStatus (\r
1795 UINT8 PortNum,\r
1796 EFI_USB_HC_PROTOCOL *UsbHCInterface\r
1797 )\r
1798/*++\r
1799\r
1800 Routine Description:\r
1801 Clear port connection change status over a given root hub port\r
1802\r
1803 Arguments:\r
1804 PortNum - The given port.\r
1805 UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.\r
1806\r
1807 Returns:\r
1808 EFI_SUCCESS\r
1809\r
1810--*/\r
1811{\r
1812 EFI_STATUS Status;\r
1813 Status = UsbHCInterface->ClearRootHubPortFeature (\r
1814 UsbHCInterface,\r
1815 PortNum,\r
1816 EfiUsbPortConnectChange\r
1817 );\r
1818 return Status;\r
1819}\r
1820\r
1821STATIC\r
1822USB_IO_CONTROLLER_DEVICE *\r
1823CreateUsbIoControllerDevice (\r
1824 VOID\r
1825 )\r
1826/*++\r
1827\r
1828 Routine Description:\r
1829 Allocate a structure for USB_IO_CONTROLLER_DEVICE\r
1830\r
1831 Arguments:\r
1832 N/A\r
1833\r
1834 Returns:\r
1835 A pointer to a USB_IO_CONTROLLER_DEVICE structure,\r
1836 Or NULL.\r
1837\r
1838--*/\r
1839{\r
1840 USB_IO_CONTROLLER_DEVICE *UsbIoControllerDev;\r
1841\r
1842 //\r
1843 // Allocate USB_IO_CONTROLLER_DEVICE structure\r
1844 //\r
1845 UsbIoControllerDev = NULL;\r
1846 UsbIoControllerDev = AllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE));\r
1847\r
1848 if (UsbIoControllerDev == NULL) {\r
1849 return NULL;\r
1850 }\r
1851\r
1852 UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE;\r
1853\r
1854 return UsbIoControllerDev;\r
1855}\r
1856\r
1857STATIC\r
1858EFI_STATUS\r
1859InitUsbIoController (\r
1860 IN USB_IO_CONTROLLER_DEVICE *UsbIoController\r
1861 )\r
1862/*++\r
1863\r
1864 Routine Description:\r
1865 Init and install EFI_USB_IO_PROTOCOL onto that controller.\r
1866\r
1867 Arguments:\r
1868 UsbIoController - The Controller to be operated.\r
1869\r
1870 Returns:\r
1871 EFI_SUCCESS\r
1872 Others\r
1873\r
1874--*/\r
1875{\r
1876 USB_DEVICE_PATH UsbNode;\r
1877 EFI_STATUS Status;\r
1878 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
1879 EFI_USB_HC_PROTOCOL *UsbHcProtocol;\r
1880\r
1881 //\r
1882 // Build the child device path for each new USB_IO device\r
1883 //\r
1884 ZeroMem (&UsbNode, sizeof (UsbNode));\r
1885 UsbNode.Header.Type = MESSAGING_DEVICE_PATH;\r
1886 UsbNode.Header.SubType = MSG_USB_DP;\r
1887 SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));\r
1888 UsbNode.InterfaceNumber = UsbIoController->InterfaceNumber;\r
1889 UsbNode.ParentPortNumber = UsbIoController->ParentPort;\r
1890 ParentDevicePath = UsbIoController->Parent->DevicePath;\r
1891\r
1892 UsbIoController->DevicePath =\r
1893 AppendDevicePathNode (ParentDevicePath, &UsbNode.Header);\r
1894 if (UsbIoController->DevicePath == NULL) {\r
1895 return EFI_OUT_OF_RESOURCES;\r
1896 }\r
1897\r
1898 Status = gBS->InstallMultipleProtocolInterfaces (\r
1899 &UsbIoController->Handle,\r
1900 &gEfiDevicePathProtocolGuid,\r
1901 UsbIoController->DevicePath,\r
1902 &gEfiUsbIoProtocolGuid,\r
1903 &UsbIoController->UsbIo,\r
1904 NULL\r
1905 );\r
1906\r
1907 if (EFI_ERROR (Status)) {\r
1908 return Status;\r
1909 }\r
1910\r
1911 Status = gBS->OpenProtocol (\r
1912 UsbIoController->HostController,\r
1913 &gEfiUsbHcProtocolGuid,\r
1914 (VOID **) &UsbHcProtocol,\r
1915 gUsbBusDriverBinding.DriverBindingHandle,\r
1916 UsbIoController->Handle,\r
1917 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1918 );\r
1919\r
1920 return Status;\r
1921}\r
1922\r
1923STATIC\r
1924EFI_STATUS\r
1925ParentPortReset (\r
1926 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
1927 IN BOOLEAN ReConfigure,\r
1928 IN UINT8 RetryTimes\r
1929 )\r
1930/*++\r
1931\r
1932 Routine Description:\r
1933 Reset parent hub port to which this device is connected.\r
1934\r
1935 Arguments:\r
1936 UsbIoController - Indicating the Usb Controller Device.\r
1937 Reconfigure - Do we need to reconfigure it.\r
1938 RetryTimes - Retry Times when failed\r
1939 Returns:\r
1940 EFI_SUCCESS\r
1941 EFI_DEVICE_ERROR\r
1942\r
1943--*/\r
1944{\r
1945 USB_IO_DEVICE *ParentIoDev;\r
1946 USB_IO_DEVICE *UsbIoDev;\r
1947 USB_IO_CONTROLLER_DEVICE *ParentController;\r
1948 UINT8 HubPort;\r
1949 UINT32 Status;\r
1950 EFI_STATUS Result;\r
1951 EFI_USB_IO_PROTOCOL *UsbIo;\r
1952 UINT8 Address;\r
1953\r
1954 ParentController = UsbIoController->Parent;\r
1955 ParentIoDev = ParentController->UsbDevice;\r
1956 UsbIoDev = UsbIoController->UsbDevice;\r
1957 HubPort = UsbIoController->ParentPort;\r
1958\r
1959 gBS->Stall (100 * 1000);\r
1960\r
1961 if (ParentIoDev->DeviceAddress == 1) {\r
1962 DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));\r
1963 ResetRootPort (ParentIoDev->BusController->UsbHCInterface, HubPort, RetryTimes);\r
1964 } else {\r
1965 DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));\r
1966 ResetHubPort (ParentController, HubPort + 1);\r
1967 }\r
1968 //\r
1969 // If we only need port reset, just return\r
1970 //\r
1971 if (!ReConfigure) {\r
1972 return EFI_SUCCESS;\r
1973 }\r
1974 //\r
1975 // Re-config that USB device\r
1976 //\r
1977 UsbIo = &UsbIoController->UsbIo;\r
1978\r
1979 //\r
1980 // Assign a unique address to this device\r
1981 //\r
1982 Address = UsbIoDev->DeviceAddress;\r
1983 UsbIoDev->DeviceAddress = 0;\r
1984\r
1985 Result = UsbSetDeviceAddress (UsbIo, Address, &Status);\r
1986 UsbIoDev->DeviceAddress = Address;\r
1987\r
1988 if (EFI_ERROR (Result)) {\r
1989 return EFI_DEVICE_ERROR;\r
1990 }\r
1991 //\r
1992 // Set the device to the default configuration\r
1993 //\r
1994 Result = UsbSetDefaultConfiguration (UsbIoDev);\r
1995 if (EFI_ERROR (Result)) {\r
1996 return EFI_DEVICE_ERROR;\r
1997 }\r
1998\r
1999 return EFI_SUCCESS;\r
2000}\r
2001\r
2002EFI_STATUS\r
2003EFIAPI\r
2004UsbPortReset (\r
2005 IN EFI_USB_IO_PROTOCOL *This\r
2006 )\r
2007/*++\r
2008\r
2009 Routine Description:\r
2010 Resets and reconfigures the USB controller. This function will\r
2011 work for all USB devices except USB Hub Controllers.\r
2012\r
2013 Arguments:\r
2014 This - Indicates the calling context.\r
2015\r
2016 Returns:\r
2017 EFI_SUCCESS\r
2018 EFI_INVALID_PARAMETER\r
2019 EFI_DEVICE_ERROR\r
2020\r
2021--*/\r
2022{\r
2023 USB_IO_CONTROLLER_DEVICE *UsbIoController;\r
2024 EFI_STATUS Status;\r
2025\r
2026 UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);\r
2027\r
2028 //\r
2029 // Since at this time, this device has already been configured,\r
2030 // it needs to be re-configured.\r
2031 //\r
2032 Status = ParentPortReset (UsbIoController, TRUE, 0);\r
2033\r
2034 return Status;\r
2035}\r
2036\r
2037EFI_STATUS\r
2038ResetRootPort (\r
2039 IN EFI_USB_HC_PROTOCOL *UsbHCInterface,\r
2040 IN UINT8 PortNum,\r
2041 IN UINT8 RetryTimes\r
2042 )\r
2043/*++\r
2044\r
2045 Routine Description:\r
2046 Reset Root Hub port.\r
2047\r
2048 Arguments:\r
2049 UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.\r
2050 PortNum - The given port to be reset.\r
2051 RetryTimes - RetryTimes when failed\r
2052 Returns:\r
2053 N/A\r
2054\r
2055--*/\r
2056{\r
2057 EFI_STATUS Status;\r
2058\r
2059 //\r
2060 // reset root port\r
2061 //\r
2062 Status = UsbHCInterface->SetRootHubPortFeature (\r
2063 UsbHCInterface,\r
2064 PortNum,\r
2065 EfiUsbPortReset\r
2066 );\r
2067\r
2068 if (EFI_ERROR (Status)) {\r
2069 return EFI_DEVICE_ERROR;\r
2070 }\r
2071\r
2072 gBS->Stall (50 * 1000);\r
2073\r
2074 //\r
2075 // clear reset root port\r
2076 //\r
2077 Status = UsbHCInterface->ClearRootHubPortFeature (\r
2078 UsbHCInterface,\r
2079 PortNum,\r
2080 EfiUsbPortReset\r
2081 );\r
2082\r
2083 if (EFI_ERROR (Status)) {\r
2084 return EFI_DEVICE_ERROR;\r
2085 }\r
2086\r
2087 gBS->Stall (1000);\r
2088\r
2089 Status = ClearRootPortConnectionChangeStatus (PortNum, UsbHCInterface);\r
2090\r
2091 if (EFI_ERROR (Status)) {\r
2092 return EFI_DEVICE_ERROR;\r
2093 }\r
2094 //\r
2095 // Set port enable\r
2096 //\r
2097 Status = UsbHCInterface->SetRootHubPortFeature (\r
2098 UsbHCInterface,\r
2099 PortNum,\r
2100 EfiUsbPortEnable\r
2101 );\r
2102 if (EFI_ERROR (Status)) {\r
2103 return EFI_DEVICE_ERROR;\r
2104 }\r
2105\r
2106 Status = UsbHCInterface->ClearRootHubPortFeature (\r
2107 UsbHCInterface,\r
2108 PortNum,\r
2109 EfiUsbPortEnableChange\r
2110 );\r
2111 gBS->Stall ((1 + RetryTimes) * 50 * 1000);\r
2112\r
2113 return EFI_SUCCESS;\r
2114}\r
2115\r
2116\r
2117EFI_STATUS\r
2118ResetHubPort (\r
2119 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
2120 IN UINT8 PortIndex\r
2121 )\r
2122/*++\r
2123\r
2124 Routine Description:\r
2125 Reset Hub port.\r
2126\r
2127 Arguments:\r
2128 UsbIoController - The USB_IO_CONTROLLER_DEVICE instance.\r
2129 PortIndex - The given port to be reset.\r
2130\r
2131 Returns:\r
2132 EFI_SUCCESS\r
2133 EFI_DEVICE_ERROR\r
2134\r
2135--*/\r
2136{\r
2137 EFI_USB_IO_PROTOCOL *UsbIo;\r
2138 EFI_USB_PORT_STATUS HubPortStatus;\r
2139 UINT8 Number;\r
2140\r
2141 ASSERT (UsbIoController->IsUsbHub == TRUE);\r
2142\r
2143 UsbIo = &UsbIoController->UsbIo;\r
2144\r
2145 HubSetPortFeature (\r
2146 UsbIo,\r
2147 PortIndex,\r
2148 EfiUsbPortReset\r
2149 );\r
2150\r
2151 gBS->Stall (10 * 1000);\r
2152\r
2153 //\r
2154 // Wait for port reset complete\r
2155 //\r
2156 Number = 10;\r
2157 do {\r
2158 HubGetPortStatus (\r
2159 UsbIo,\r
2160 PortIndex,\r
2161 (UINT32 *) &HubPortStatus\r
2162 );\r
2163 gBS->Stall (10 * 100);\r
2164 Number -= 1;\r
2165 } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Number > 0);\r
2166\r
2167 if (Number == 0) {\r
2168 //\r
2169 // Cannot reset port, return error\r
2170 //\r
2171 return EFI_DEVICE_ERROR;\r
2172 }\r
2173\r
2174 gBS->Stall (1000);\r
2175\r
2176 HubGetPortStatus (\r
2177 UsbIo,\r
2178 PortIndex,\r
2179 (UINT32 *) &HubPortStatus\r
2180 );\r
2181 //\r
2182 // reset port will cause some bits change, clear them\r
2183 //\r
2184 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {\r
2185 DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));\r
2186 HubClearPortFeature (\r
2187 UsbIo,\r
2188 PortIndex,\r
2189 EfiUsbPortEnableChange\r
2190 );\r
2191 }\r
2192\r
2193 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {\r
2194 DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));\r
2195 HubClearPortFeature (\r
2196 UsbIo,\r
2197 PortIndex,\r
2198 EfiUsbPortResetChange\r
2199 );\r
2200 }\r
2201\r
2202 return EFI_SUCCESS;\r
2203}\r
2204\r
2205\r
2206\r
2207\r
2208\r
2209STATIC\r
2210EFI_STATUS\r
2211ReportUsbStatusCode (\r
2212 IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,\r
2213 IN EFI_STATUS_CODE_TYPE Type,\r
2214 IN EFI_STATUS_CODE_VALUE Code\r
2215 )\r
2216/*++\r
2217\r
2218Routine Description:\r
2219\r
2220 report a error Status code of USB bus driver controller\r
2221\r
2222 Arguments:\r
2223 UsbBusController - USB_BUS_CONTROLLER_DEVICE\r
2224 Type - EFI_STATUS_CODE_TYPE\r
2225 Code - EFI_STATUS_CODE_VALUE\r
2226 Returns:\r
2227\r
2228 None\r
2229\r
2230--*/\r
2231{\r
2232 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
2233 Type,\r
2234 Code,\r
2235 UsbBusController->DevicePath\r
2236 );\r
2237}\r
2238\r
2239\r
2240EFI_STATUS\r
2241IsDeviceDisconnected (\r
2242 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
2243 IN OUT BOOLEAN *Disconnected\r
2244 )\r
2245/*++\r
2246\r
2247 Routine Description:\r
2248 Reset if the device is disconencted or not\r
2249\r
2250 Arguments:\r
2251 UsbIoController - Indicating the Usb Controller Device.\r
2252 Disconnected - Indicate whether the device is disconencted or not\r
2253\r
2254 Returns:\r
2255 EFI_SUCCESS\r
2256 EFI_DEVICE_ERROR\r
2257\r
2258--*/\r
2259{\r
2260 USB_IO_DEVICE *ParentIoDev;\r
2261 USB_IO_DEVICE *UsbIoDev;\r
2262 USB_IO_CONTROLLER_DEVICE *ParentController;\r
2263 UINT8 HubPort;\r
2264 EFI_STATUS Status;\r
2265 EFI_USB_IO_PROTOCOL *UsbIo;\r
2266 EFI_USB_PORT_STATUS PortStatus;\r
2267 EFI_USB_HC_PROTOCOL *UsbHCInterface;\r
2268\r
2269 ParentController = UsbIoController->Parent;\r
2270 ParentIoDev = ParentController->UsbDevice;\r
2271 UsbIoDev = UsbIoController->UsbDevice;\r
2272 HubPort = UsbIoController->ParentPort;\r
2273\r
2274 if (ParentIoDev->DeviceAddress == 1) {\r
2275 //\r
2276 // Connected to the root hub\r
2277 //\r
2278 UsbHCInterface = ParentIoDev->BusController->UsbHCInterface;\r
2279 Status = UsbHCInterface->GetRootHubPortStatus (\r
2280 UsbHCInterface,\r
2281 HubPort,\r
2282 &PortStatus\r
2283 );\r
2284\r
2285 } else {\r
2286 UsbIo = &UsbIoController->UsbIo;\r
2287 Status = HubGetPortStatus (\r
2288 &ParentController->UsbIo,\r
2289 HubPort + 1,\r
2290 (UINT32 *) &PortStatus\r
2291 );\r
2292\r
2293 if (EFI_ERROR (Status)) {\r
2294 return IsDeviceDisconnected (ParentController, Disconnected);\r
2295 }\r
2296 }\r
2297\r
2298 *Disconnected = FALSE;\r
2299\r
2300 if (!IsPortConnect (PortStatus.PortStatus)) {\r
2301 *Disconnected = TRUE;\r
2302 }\r
2303\r
2304 return EFI_SUCCESS;\r
2305}\r