]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
After identified as a High-Speed device, the port has been reset successfully, so...
[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
71a62114 26\r
27GLOBAL_REMOVE_IF_UNREFERENCED UINTN gUSBDebugLevel = EFI_D_INFO;\r
28GLOBAL_REMOVE_IF_UNREFERENCED UINTN gUSBErrorLevel = EFI_D_ERROR;\r
562d2849 29\r
878ddf1f 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
562d2849 124RootHubEnumeration (\r
125 IN EFI_EVENT Event,\r
126 IN VOID *Context\r
127 );\r
128\r
129STATIC\r
130VOID\r
131HubEnumeration (\r
878ddf1f 132 IN EFI_EVENT Event,\r
133 IN VOID *Context\r
134 );\r
135\r
562d2849 136STATIC\r
137EFI_STATUS\r
138UsbSetTransactionTranslator (\r
139 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,\r
140 IN UINT8 ParentPort,\r
141 IN OUT USB_IO_DEVICE *Device\r
142 );\r
143\r
144STATIC\r
145EFI_STATUS\r
146UsbUnsetTransactionTranslator (\r
147 USB_IO_DEVICE *Device\r
148 );\r
149\r
150STATIC\r
151EFI_STATUS\r
152IdentifyDeviceSpeed (\r
153 USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
154 USB_IO_DEVICE *NewDevice,\r
155 UINT8 Index\r
156 );\r
157\r
158STATIC\r
159EFI_STATUS\r
160ReleasePortToCHC (\r
161 USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
162 UINT8 PortNum\r
163 );\r
164\r
878ddf1f 165EFI_STATUS\r
166ResetRootPort (\r
562d2849 167 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
168 IN UINT8 PortNum,\r
169 IN UINT8 RetryTimes\r
878ddf1f 170 );\r
171\r
172EFI_STATUS\r
173ResetHubPort (\r
174 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
175 IN UINT8 PortIndex\r
176 );\r
177\r
878ddf1f 178STATIC\r
179EFI_STATUS\r
180ParentPortReset (\r
181 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
182 IN BOOLEAN ReConfigure,\r
183 IN UINT8 RetryTimes\r
184 );\r
185\r
186//\r
187// Following are address allocate and free functions\r
188//\r
189STATIC\r
190UINT8\r
191UsbAllocateAddress (\r
192 IN UINT8 *AddressPool\r
193 )\r
562d2849 194/*++\r
195\r
196 Routine Description:\r
197 Allocate address for usb device\r
198\r
199 Arguments:\r
200 AddressPool - Pool of usb device address\r
201\r
202 Returns:\r
203 Usb device address\r
204\r
205--*/\r
878ddf1f 206{\r
207 UINT8 ByteIndex;\r
208 UINT8 BitIndex;\r
209\r
210 for (ByteIndex = 0; ByteIndex < 16; ByteIndex++) {\r
211 for (BitIndex = 0; BitIndex < 8; BitIndex++) {\r
212 if ((AddressPool[ByteIndex] & (1 << BitIndex)) == 0) {\r
213 //\r
214 // Found one, covert to address, and mark it use\r
215 //\r
216 AddressPool[ByteIndex] |= (1 << BitIndex);\r
217 return (UINT8) (ByteIndex * 8 + BitIndex);\r
218 }\r
219 }\r
220 }\r
221\r
222 return 0;\r
223\r
224}\r
225\r
226STATIC\r
227VOID\r
228UsbFreeAddress (\r
229 IN UINT8 DevAddress,\r
230 IN UINT8 *AddressPool\r
231 )\r
562d2849 232/*++\r
233\r
234 Routine Description:\r
235 Free address for usb device\r
236\r
237 Arguments:\r
238 DevAddress - Usb device address\r
239 AddressPool - Pool of usb device address\r
240 \r
241 Returns:\r
242 VOID\r
243\r
244--*/\r
878ddf1f 245{\r
246 UINT8 WhichByte;\r
247 UINT8 WhichBit;\r
248 //\r
249 // Locate the position\r
250 //\r
251 WhichByte = (UINT8) (DevAddress / 8);\r
252 WhichBit = (UINT8) (DevAddress & 0x7);\r
253\r
254 AddressPool[WhichByte] &= (~(1 << WhichBit));\r
255}\r
256\r
257EFI_STATUS\r
258EFIAPI\r
259UsbBusControllerDriverSupported (\r
260 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
261 IN EFI_HANDLE Controller,\r
262 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
263 )\r
264/*++\r
265\r
266 Routine Description:\r
267 Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
268 that has UsbHcProtocol installed will be supported.\r
269\r
270 Arguments:\r
271 This - Protocol instance pointer.\r
562d2849 272 Controller - Handle of device to test\r
273 RemainingDevicePath - Device Path Protocol instance pointer\r
878ddf1f 274\r
275 Returns:\r
276 EFI_SUCCESS - This driver supports this device.\r
277 EFI_UNSUPPORTED - This driver does not support this device.\r
278\r
279--*/\r
280{\r
562d2849 281 EFI_STATUS Status;\r
282 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
283 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
284 EFI_USB_HC_PROTOCOL *UsbHc;\r
285 EFI_DEV_PATH_PTR Node;\r
286\r
287 //\r
288 // Check Device Path\r
289 //\r
290 if (RemainingDevicePath != NULL) {\r
291 Node.DevPath = RemainingDevicePath;\r
292 if (Node.DevPath->Type != MESSAGING_DEVICE_PATH ||\r
293 Node.DevPath->SubType != MSG_USB_DP ||\r
294 DevicePathNodeLength(Node.DevPath) != sizeof(USB_DEVICE_PATH)) {\r
295 return EFI_UNSUPPORTED;\r
296 }\r
297 }\r
298 \r
299 //\r
300 // Open the IO Abstraction(s) needed to perform the supported test\r
301 //\r
302 Status = gBS->OpenProtocol (\r
303 Controller,\r
304 &gEfiDevicePathProtocolGuid,\r
305 (VOID **) &ParentDevicePath,\r
306 This->DriverBindingHandle,\r
307 Controller,\r
308 EFI_OPEN_PROTOCOL_BY_DRIVER\r
309 );\r
310 if (Status == EFI_ALREADY_STARTED) {\r
311 return EFI_SUCCESS;\r
312 }\r
878ddf1f 313\r
562d2849 314 if (EFI_ERROR (Status)) {\r
315 return Status;\r
316 }\r
317\r
318 gBS->CloseProtocol (\r
319 Controller,\r
320 &gEfiDevicePathProtocolGuid,\r
321 This->DriverBindingHandle,\r
322 Controller\r
323 );\r
324 \r
878ddf1f 325 //\r
326 // Check whether USB Host Controller Protocol is already\r
327 // installed on this handle. If it is installed, we can start\r
328 // USB Bus Driver now.\r
329 //\r
562d2849 330 Status = gBS->OpenProtocol (\r
331 Controller,\r
332 &gEfiUsb2HcProtocolGuid,\r
333 (VOID **) &Usb2Hc,\r
334 This->DriverBindingHandle,\r
335 Controller,\r
336 EFI_OPEN_PROTOCOL_BY_DRIVER\r
337 );\r
338 if (Status == EFI_ALREADY_STARTED) {\r
339 return EFI_SUCCESS;\r
340 }\r
341 \r
342 if (EFI_ERROR (Status)) {\r
343 Status = gBS->OpenProtocol (\r
344 Controller,\r
345 &gEfiUsbHcProtocolGuid,\r
346 (VOID **) &UsbHc,\r
347 This->DriverBindingHandle,\r
348 Controller,\r
349 EFI_OPEN_PROTOCOL_BY_DRIVER\r
350 );\r
351 if (Status == EFI_ALREADY_STARTED) {\r
352 return EFI_SUCCESS;\r
353 }\r
354\r
355 if (EFI_ERROR (Status)) {\r
356 return Status;\r
357 }\r
878ddf1f 358\r
562d2849 359 gBS->CloseProtocol (\r
360 Controller,\r
361 &gEfiUsbHcProtocolGuid,\r
362 This->DriverBindingHandle,\r
363 Controller\r
364 );\r
365 return EFI_SUCCESS;\r
878ddf1f 366 }\r
562d2849 367 \r
368 gBS->CloseProtocol (\r
369 Controller,\r
370 &gEfiUsb2HcProtocolGuid,\r
371 This->DriverBindingHandle,\r
372 Controller\r
373 );\r
878ddf1f 374\r
562d2849 375 return EFI_SUCCESS;\r
878ddf1f 376}\r
377\r
878ddf1f 378EFI_STATUS\r
379EFIAPI\r
380UsbBusControllerDriverStart (\r
381 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
382 IN EFI_HANDLE Controller,\r
383 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
384 )\r
385/*++\r
386\r
387 Routine Description:\r
388\r
389 Starting the Usb Bus Driver\r
390\r
391 Arguments:\r
392\r
393 This - Protocol instance pointer.\r
394 Controller - Handle of device to test\r
395 RemainingDevicePath - Not used\r
396\r
397 Returns:\r
398\r
399 EFI_SUCCESS - This driver supports this device.\r
878ddf1f 400 EFI_DEVICE_ERROR - This driver cannot be started due to device\r
878ddf1f 401 EFI_OUT_OF_RESOURCES- Can't allocate memory resources\r
878ddf1f 402\r
403--*/\r
404{\r
405 EFI_STATUS Status;\r
406 EFI_STATUS OpenStatus;\r
407 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
408 USB_IO_DEVICE *RootHub;\r
409 USB_IO_CONTROLLER_DEVICE *RootHubController;\r
562d2849 410 UINT8 MaxSpeed;\r
411 UINT8 PortNumber;\r
412 UINT8 Is64BitCapable;\r
878ddf1f 413\r
414 //\r
415 // Allocate USB_BUS_CONTROLLER_DEVICE structure\r
416 //\r
417 UsbBusDev = NULL;\r
418 UsbBusDev = AllocateZeroPool (sizeof (USB_BUS_CONTROLLER_DEVICE));\r
419 if (UsbBusDev == NULL) {\r
420 return EFI_OUT_OF_RESOURCES;\r
421 }\r
422\r
423 UsbBusDev->Signature = USB_BUS_DEVICE_SIGNATURE;\r
424 UsbBusDev->AddressPool[0] = 1;\r
425\r
426 //\r
427 // Get the Device Path Protocol on Controller's handle\r
428 //\r
429 OpenStatus = gBS->OpenProtocol (\r
430 Controller,\r
431 &gEfiDevicePathProtocolGuid,\r
432 (VOID **) &UsbBusDev->DevicePath,\r
433 This->DriverBindingHandle,\r
434 Controller,\r
435 EFI_OPEN_PROTOCOL_BY_DRIVER\r
436 );\r
437\r
438 if (EFI_ERROR (OpenStatus)) {\r
439 gBS->FreePool (UsbBusDev);\r
562d2849 440 return OpenStatus;\r
878ddf1f 441 }\r
442 //\r
443 // Locate the Host Controller Interface\r
444 //\r
445 OpenStatus = gBS->OpenProtocol (\r
446 Controller,\r
562d2849 447 &gEfiUsb2HcProtocolGuid,\r
448 (VOID **) &(UsbBusDev->Usb2HCInterface),\r
878ddf1f 449 This->DriverBindingHandle,\r
450 Controller,\r
451 EFI_OPEN_PROTOCOL_BY_DRIVER\r
452 );\r
562d2849 453 if (EFI_ERROR (OpenStatus)) {\r
878ddf1f 454\r
562d2849 455 UsbBusDev->Hc2ProtocolSupported = FALSE;\r
456 OpenStatus = gBS->OpenProtocol (\r
457 Controller,\r
458 &gEfiUsbHcProtocolGuid,\r
459 (VOID **) &(UsbBusDev->UsbHCInterface),\r
460 This->DriverBindingHandle,\r
461 Controller,\r
462 EFI_OPEN_PROTOCOL_BY_DRIVER\r
463 );\r
464 if (EFI_ERROR (OpenStatus)) {\r
465 //\r
466 // Report Status Code here since we will reset the host controller\r
467 //\r
468 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
469 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
470 EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,\r
471 UsbBusDev->DevicePath\r
472 );\r
878ddf1f 473\r
562d2849 474 gBS->CloseProtocol (\r
475 Controller,\r
476 &gEfiDevicePathProtocolGuid,\r
477 This->DriverBindingHandle,\r
478 Controller\r
479 );\r
480 gBS->FreePool (UsbBusDev);\r
481 return OpenStatus;\r
482 }\r
878ddf1f 483\r
562d2849 484 DEBUG ((gUSBDebugLevel, "UsbHcProtocol Opened.\n"));\r
485 } else {\r
486 DEBUG ((gUSBDebugLevel, "Usb2HcProtocol Opened.\n"));\r
487 UsbBusDev->Hc2ProtocolSupported = TRUE;\r
878ddf1f 488 }\r
489\r
878ddf1f 490 //\r
491 // Attach EFI_USB_BUS_PROTOCOL to controller handle,\r
492 // for locate UsbBusDev later\r
493 //\r
494 Status = gBS->InstallProtocolInterface (\r
495 &Controller,\r
496 &mUsbBusProtocolGuid,\r
497 EFI_NATIVE_INTERFACE,\r
498 &UsbBusDev->BusIdentify\r
499 );\r
500\r
501 if (EFI_ERROR (Status)) {\r
502\r
503 gBS->CloseProtocol (\r
504 Controller,\r
505 &gEfiDevicePathProtocolGuid,\r
506 This->DriverBindingHandle,\r
507 Controller\r
508 );\r
562d2849 509 if (UsbBusDev->Hc2ProtocolSupported) {\r
510 gBS->CloseProtocol (\r
511 Controller,\r
512 &gEfiUsb2HcProtocolGuid,\r
513 This->DriverBindingHandle,\r
514 Controller\r
515 );\r
516 } else {\r
517 gBS->CloseProtocol (\r
518 Controller,\r
519 &gEfiUsbHcProtocolGuid,\r
520 This->DriverBindingHandle,\r
521 Controller\r
522 );\r
523 }\r
524\r
878ddf1f 525 gBS->FreePool (UsbBusDev);\r
526 return Status;\r
527 }\r
528 //\r
529 // Add root hub to the tree\r
530 //\r
531 RootHub = NULL;\r
532 RootHub = AllocateZeroPool (sizeof (USB_IO_DEVICE));\r
533 if (RootHub == NULL) {\r
534 gBS->UninstallProtocolInterface (\r
535 Controller,\r
536 &mUsbBusProtocolGuid,\r
537 &UsbBusDev->BusIdentify\r
538 );\r
539 gBS->CloseProtocol (\r
540 Controller,\r
541 &gEfiDevicePathProtocolGuid,\r
542 This->DriverBindingHandle,\r
543 Controller\r
544 );\r
562d2849 545 if (UsbBusDev->Hc2ProtocolSupported) {\r
546 gBS->CloseProtocol (\r
547 Controller,\r
548 &gEfiUsb2HcProtocolGuid,\r
549 This->DriverBindingHandle,\r
550 Controller\r
551 );\r
552 } else {\r
553 gBS->CloseProtocol (\r
554 Controller,\r
555 &gEfiUsbHcProtocolGuid,\r
556 This->DriverBindingHandle,\r
557 Controller\r
558 );\r
559 }\r
560\r
878ddf1f 561 gBS->FreePool (UsbBusDev);\r
562 return EFI_OUT_OF_RESOURCES;\r
563 }\r
564\r
565 RootHub->BusController = UsbBusDev;\r
566 RootHub->DeviceAddress = UsbAllocateAddress (UsbBusDev->AddressPool);\r
567\r
568 UsbBusDev->Root = RootHub;\r
569\r
570 //\r
571 // Allocate Root Hub Controller\r
572 //\r
573 RootHubController = CreateUsbIoControllerDevice ();\r
574 if (RootHubController == NULL) {\r
575 gBS->UninstallProtocolInterface (\r
576 Controller,\r
577 &mUsbBusProtocolGuid,\r
578 &UsbBusDev->BusIdentify\r
579 );\r
580 gBS->CloseProtocol (\r
581 Controller,\r
582 &gEfiDevicePathProtocolGuid,\r
583 This->DriverBindingHandle,\r
584 Controller\r
585 );\r
562d2849 586 if (UsbBusDev->Hc2ProtocolSupported) {\r
587 gBS->CloseProtocol (\r
588 Controller,\r
589 &gEfiUsb2HcProtocolGuid,\r
590 This->DriverBindingHandle,\r
591 Controller\r
592 );\r
593 } else {\r
594 gBS->CloseProtocol (\r
595 Controller,\r
596 &gEfiUsbHcProtocolGuid,\r
597 This->DriverBindingHandle,\r
598 Controller\r
599 );\r
600 }\r
878ddf1f 601 gBS->FreePool (UsbBusDev);\r
602 gBS->FreePool (RootHub);\r
603 return EFI_OUT_OF_RESOURCES;\r
604 }\r
605\r
562d2849 606 UsbVirtualHcGetCapability (\r
607 UsbBusDev,\r
608 &MaxSpeed,\r
609 &PortNumber,\r
610 &Is64BitCapable\r
611 );\r
612 RootHubController->DownstreamPorts = PortNumber;\r
613 RootHubController->UsbDevice = RootHub;\r
614 RootHubController->IsUsbHub = TRUE;\r
615 RootHubController->DevicePath = UsbBusDev->DevicePath;\r
616 RootHubController->HostController = Controller;\r
878ddf1f 617\r
562d2849 618 RootHub->NumOfControllers = 1;\r
619 RootHub->UsbController[0] = RootHubController;\r
620 RootHub->DeviceSpeed = MaxSpeed;\r
878ddf1f 621\r
622 //\r
623 // Report Status Code here since we will reset the host controller\r
624 //\r
625 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
626 EFI_PROGRESS_CODE,\r
627 EFI_IO_BUS_USB | EFI_IOB_PC_RESET,\r
628 UsbBusDev->DevicePath\r
629 );\r
630\r
631 //\r
632 // Reset USB Host Controller\r
633 //\r
562d2849 634 UsbVirtualHcReset (\r
635 UsbBusDev,\r
636 EFI_USB_HC_RESET_GLOBAL\r
637 );\r
878ddf1f 638\r
639 //\r
640 // Report Status Code while we are going to bring up the Host Controller\r
641 // and start bus enumeration\r
642 //\r
643 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
644 EFI_PROGRESS_CODE,\r
645 EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE,\r
646 UsbBusDev->DevicePath\r
647 );\r
648\r
649 //\r
650 // Start USB Host Controller\r
651 //\r
562d2849 652 UsbVirtualHcSetState (\r
653 UsbBusDev,\r
654 EfiUsbHcStateOperational\r
655 );\r
878ddf1f 656\r
657 //\r
658 // Create a timer to query root ports periodically\r
659 //\r
660 Status = gBS->CreateEvent (\r
661 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,\r
662 EFI_TPL_CALLBACK,\r
562d2849 663 RootHubEnumeration,\r
878ddf1f 664 RootHubController,\r
665 &RootHubController->HubNotify\r
666 );\r
667 if (EFI_ERROR (Status)) {\r
668 gBS->UninstallProtocolInterface (\r
669 Controller,\r
670 &mUsbBusProtocolGuid,\r
671 &UsbBusDev->BusIdentify\r
672 );\r
673\r
674 gBS->CloseProtocol (\r
675 Controller,\r
676 &gEfiDevicePathProtocolGuid,\r
677 This->DriverBindingHandle,\r
678 Controller\r
679 );\r
680\r
562d2849 681 if (UsbBusDev->Hc2ProtocolSupported) {\r
682 gBS->CloseProtocol (\r
683 Controller,\r
684 &gEfiUsb2HcProtocolGuid,\r
685 This->DriverBindingHandle,\r
686 Controller\r
687 );\r
688 } else {\r
689 gBS->CloseProtocol (\r
690 Controller,\r
691 &gEfiUsbHcProtocolGuid,\r
692 This->DriverBindingHandle,\r
693 Controller\r
694 );\r
695 }\r
878ddf1f 696\r
697 gBS->FreePool (RootHubController);\r
698 gBS->FreePool (RootHub);\r
699 gBS->FreePool (UsbBusDev);\r
562d2849 700 return EFI_OUT_OF_RESOURCES;\r
878ddf1f 701 }\r
702\r
703 //\r
704 // Before depending on the timer to check root ports periodically,\r
705 // here we should check them immediately for the first time, or\r
706 // there will be an interval between bus start and devices start.\r
707 //\r
708 gBS->SignalEvent (RootHubController->HubNotify);\r
709 \r
710 Status = gBS->SetTimer (\r
711 RootHubController->HubNotify,\r
712 TimerPeriodic,\r
713 BUSPOLLING_PERIOD\r
714 );\r
715 if (EFI_ERROR (Status)) {\r
716 gBS->UninstallProtocolInterface (\r
717 Controller,\r
718 &mUsbBusProtocolGuid,\r
719 &UsbBusDev->BusIdentify\r
720 );\r
721\r
722 gBS->CloseProtocol (\r
723 Controller,\r
724 &gEfiDevicePathProtocolGuid,\r
725 This->DriverBindingHandle,\r
726 Controller\r
727 );\r
728\r
562d2849 729 if (UsbBusDev->Hc2ProtocolSupported) {\r
730 gBS->CloseProtocol (\r
731 Controller,\r
732 &gEfiUsb2HcProtocolGuid,\r
733 This->DriverBindingHandle,\r
734 Controller\r
735 );\r
736 } else {\r
737 gBS->CloseProtocol (\r
738 Controller,\r
739 &gEfiUsbHcProtocolGuid,\r
740 This->DriverBindingHandle,\r
741 Controller\r
742 );\r
743 }\r
878ddf1f 744\r
745 gBS->CloseEvent (RootHubController->HubNotify);\r
746 gBS->FreePool (RootHubController);\r
747 gBS->FreePool (RootHub);\r
748 gBS->FreePool (UsbBusDev);\r
562d2849 749 return EFI_DEVICE_ERROR;\r
878ddf1f 750 }\r
751\r
752 return EFI_SUCCESS;\r
753}\r
562d2849 754\r
878ddf1f 755//\r
756// Stop the bus controller\r
757//\r
758EFI_STATUS\r
759EFIAPI\r
760UsbBusControllerDriverStop (\r
761 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
762 IN EFI_HANDLE Controller,\r
763 IN UINTN NumberOfChildren,\r
764 IN EFI_HANDLE *ChildHandleBuffer\r
765 )\r
766/*++\r
767\r
768 Routine Description:\r
769 Stop this driver on ControllerHandle. Support stoping any child handles\r
770 created by this driver.\r
771\r
772 Arguments:\r
773 This - Protocol instance pointer.\r
774 Controller - Handle of device to stop driver on\r
775 NumberOfChildren - Number of Children in the ChildHandleBuffer\r
776 ChildHandleBuffer - List of handles for the children we need to stop.\r
777\r
778 Returns:\r
779 EFI_SUCCESS\r
780 EFI_DEVICE_ERROR\r
781 others\r
782\r
783--*/\r
784{\r
785 EFI_STATUS Status;\r
786 USB_IO_DEVICE *Root;\r
787 USB_IO_CONTROLLER_DEVICE *RootHubController;\r
788 USB_BUS_CONTROLLER_DEVICE *UsbBusController;\r
789 EFI_USB_BUS_PROTOCOL *UsbIdentifier;\r
790 UINT8 Index2;\r
878ddf1f 791 USB_IO_CONTROLLER_DEVICE *UsbController;\r
792 USB_IO_DEVICE *UsbIoDevice;\r
793 USB_IO_CONTROLLER_DEVICE *HubController;\r
794 UINTN Index;\r
795 EFI_USB_IO_PROTOCOL *UsbIo;\r
796\r
797 if (NumberOfChildren > 0) {\r
798\r
799 for (Index = 0; Index < NumberOfChildren; Index++) {\r
800 Status = gBS->OpenProtocol (\r
801 ChildHandleBuffer[Index],\r
802 &gEfiUsbIoProtocolGuid,\r
803 (VOID **) &UsbIo,\r
804 This->DriverBindingHandle,\r
805 Controller,\r
806 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
807 );\r
808 if (EFI_ERROR (Status)) {\r
809 //\r
810 // We are here since the handle passed in does not support\r
811 // UsbIo protocol. There are several reasons that will cause\r
812 // this.\r
813 // For combo device such as keyboard, it may have 2 devices\r
814 // in one, namely, keyboard and mouse. If we deconfigure one\r
815 // of them, the other will be freed at the same time. This will\r
816 // cause the status error. But this is the correct behavior.\r
817 // For hub device, if we deconfigure hub first, the other chile\r
818 // device will be disconnected also, this will also provide us\r
819 // a status error. Now we will only report EFI_SUCCESS since Uhc\r
820 // driver will be disconnected at the second time.(pls see\r
821 // CoreDisconnectController for details)\r
822 //\r
823 continue;\r
824 }\r
825\r
826 UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo);\r
827 UsbIoDevice = UsbController->UsbDevice;\r
828 HubController = UsbController->Parent;\r
829 UsbDeviceDeConfiguration (UsbIoDevice);\r
830 for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) {\r
831 if (HubController->Children[Index2] == UsbIoDevice) {\r
832 HubController->Children[Index2] = NULL;\r
833 }\r
834 }\r
835 }\r
836\r
837 return EFI_SUCCESS;\r
838 }\r
839 //\r
840 // Get the USB_BUS_CONTROLLER_DEVICE\r
841 //\r
842 Status = gBS->OpenProtocol (\r
843 Controller,\r
844 &mUsbBusProtocolGuid,\r
845 (VOID **) &UsbIdentifier,\r
846 This->DriverBindingHandle,\r
847 Controller,\r
848 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
849 );\r
850\r
851 if (EFI_ERROR (Status)) {\r
852 return EFI_DEVICE_ERROR;\r
853 }\r
854\r
855 UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier);\r
856\r
857 //\r
858 // Stop USB Host Controller\r
859 //\r
878ddf1f 860\r
861 //\r
862 // Report Status Code here since we will reset the host controller\r
863 //\r
864 ReportUsbStatusCode (\r
865 UsbBusController,\r
866 EFI_PROGRESS_CODE,\r
867 EFI_IO_BUS_USB | EFI_IOB_PC_RESET\r
868 );\r
869\r
562d2849 870 UsbVirtualHcSetState (\r
871 UsbBusController,\r
872 EfiUsbHcStateHalt\r
873 );\r
878ddf1f 874\r
875 //\r
876 // Deconfiguration all its devices\r
877 //\r
878 Root = UsbBusController->Root;\r
879 RootHubController = Root->UsbController[0];\r
880\r
881 gBS->CloseEvent (RootHubController->HubNotify);\r
882\r
883 for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) {\r
884 if (RootHubController->Children[Index2]) {\r
885 UsbDeviceDeConfiguration (RootHubController->Children[Index2]);\r
886 RootHubController->Children[Index2] = NULL;\r
887 }\r
888 }\r
889\r
890 gBS->FreePool (RootHubController);\r
891 gBS->FreePool (Root);\r
892\r
893 //\r
894 // Uninstall USB Bus Protocol\r
895 //\r
896 gBS->UninstallProtocolInterface (\r
897 Controller,\r
898 &mUsbBusProtocolGuid,\r
899 &UsbBusController->BusIdentify\r
900 );\r
901\r
902 //\r
903 // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL\r
904 // Opened by this Controller\r
905 //\r
562d2849 906 if (UsbBusController->Hc2ProtocolSupported) {\r
907 gBS->CloseProtocol (\r
908 Controller,\r
909 &gEfiUsb2HcProtocolGuid,\r
910 This->DriverBindingHandle,\r
911 Controller\r
912 );\r
913 } else {\r
914 gBS->CloseProtocol (\r
915 Controller,\r
916 &gEfiUsbHcProtocolGuid,\r
917 This->DriverBindingHandle,\r
918 Controller\r
919 );\r
920 }\r
878ddf1f 921\r
922 gBS->CloseProtocol (\r
923 Controller,\r
924 &gEfiDevicePathProtocolGuid,\r
925 This->DriverBindingHandle,\r
926 Controller\r
927 );\r
928\r
929 gBS->FreePool (UsbBusController);\r
930\r
931 return EFI_SUCCESS;\r
932}\r
933//\r
934// USB Device Configuration\r
935//\r
936STATIC\r
937EFI_STATUS\r
938UsbDeviceConfiguration (\r
939 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,\r
940 IN EFI_HANDLE HostController,\r
941 IN UINT8 ParentPort,\r
942 IN USB_IO_DEVICE *UsbIoDevice\r
943 )\r
944/*++\r
945\r
946 Routine Description:\r
947 Configurate a new device attached to the usb bus\r
948\r
949 Arguments:\r
950 ParentHubController - Parent Hub which this device is connected.\r
951 HostController - Host Controller handle\r
952 ParentPort - Parent Hub port which this device is connected.\r
953 UsbIoDevice - The device to be configured.\r
954\r
955 Returns:\r
956 EFI_SUCCESS\r
957 EFI_DEVICE_ERROR\r
958 EFI_OUT_OF_RESOURCES\r
959\r
960--*/\r
961{\r
962 UINT8 DevAddress;\r
963 UINT8 Index;\r
964 EFI_STATUS Result;\r
965 UINT32 Status;\r
966 CHAR16 *StrManufacturer;\r
967 CHAR16 *StrProduct;\r
968 CHAR16 *StrSerialNumber;\r
969 EFI_USB_IO_PROTOCOL *UsbIo;\r
970 UINT8 NumOfInterface;\r
971 USB_IO_CONTROLLER_DEVICE *FirstController;\r
972 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
973 USB_IO_CONTROLLER_DEVICE *UsbIoController;\r
974\r
975 UsbBusDev = UsbIoDevice->BusController;\r
562d2849 976\r
977 UsbSetTransactionTranslator (\r
978 ParentHubController,\r
979 ParentPort,\r
980 UsbIoDevice\r
981 );\r
982\r
878ddf1f 983 //\r
984 // Since a USB device must have at least on interface,\r
985 // so create this instance first\r
986 //\r
987 FirstController = CreateUsbIoControllerDevice ();\r
988 FirstController->UsbDevice = UsbIoDevice;\r
989 UsbIoDevice->UsbController[0] = FirstController;\r
990 FirstController->InterfaceNumber = 0;\r
991 FirstController->ParentPort = ParentPort;\r
992 FirstController->Parent = ParentHubController;\r
993 FirstController->HostController = HostController;\r
994\r
995 InitializeUsbIoInstance (FirstController);\r
996\r
997 DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort));\r
998\r
999 //\r
1000 // Ensure we used the correctly USB I/O instance\r
1001 //\r
1002 UsbIo = &FirstController->UsbIo;\r
1003\r
bd518502 1004 if (UsbIoDevice->DeviceSpeed != EFI_USB_SPEED_HIGH) {\r
1005 ParentPortReset (FirstController, FALSE, 0);\r
1006 }\r
562d2849 1007\r
878ddf1f 1008 //\r
1009 // First retrieve the 1st 8 bytes of\r
1010 // in order to get the MaxPacketSize for Endpoint 0\r
1011 //\r
1012 for (Index = 0; Index < 3; Index++) {\r
1013\r
1014 UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;\r
1015\r
562d2849 1016 gBS->Stall (100 * 1000);\r
878ddf1f 1017\r
1018 Result = UsbGetDescriptor (\r
1019 UsbIo,\r
1020 (USB_DT_DEVICE << 8),\r
1021 0,\r
1022 8,\r
1023 &UsbIoDevice->DeviceDescriptor,\r
1024 &Status\r
1025 );\r
1026 if (!EFI_ERROR (Result)) {\r
562d2849 1027 DEBUG (\r
1028 (gUSBDebugLevel,\r
878ddf1f 1029 "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",\r
1030 UsbIoDevice->DeviceDescriptor.MaxPacketSize0)\r
1031 );\r
1032 break;\r
1033 }\r
1034\r
1035 }\r
1036\r
1037 if (Index == 3) {\r
1038 ReportUsbStatusCode (\r
1039 UsbBusDev,\r
1040 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1041 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR\r
1042 );\r
1043 DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n"));\r
1044 gBS->FreePool (FirstController);\r
1045 return EFI_DEVICE_ERROR;\r
1046 }\r
1047\r
1048 DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool);\r
1049 if (DevAddress == 0) {\r
1050 DEBUG ((gUSBErrorLevel, "Cannot allocate address\n"));\r
1051 gBS->FreePool (FirstController);\r
1052 return EFI_OUT_OF_RESOURCES;\r
1053 }\r
1054\r
1055 Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status);\r
1056\r
1057 if (EFI_ERROR (Result)) {\r
1058 DEBUG ((gUSBErrorLevel, "Set address error\n"));\r
1059 ReportUsbStatusCode (\r
1060 UsbBusDev,\r
1061 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1062 EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR\r
1063 );\r
1064\r
1065 UsbFreeAddress (\r
1066 DevAddress,\r
1067 UsbIoDevice->BusController->AddressPool\r
1068 );\r
1069\r
1070 gBS->FreePool (FirstController);\r
1071 return EFI_DEVICE_ERROR;\r
1072 }\r
1073\r
1074 UsbIoDevice->DeviceAddress = DevAddress;\r
1075\r
562d2849 1076 //\r
1077 // SetAddress Complete Time by Spec, Max 50ms\r
1078 //\r
1079 gBS->Stall (10 * 1000);\r
1080\r
878ddf1f 1081 //\r
1082 // Get the whole device descriptor\r
1083 //\r
1084 Result = UsbGetDescriptor (\r
1085 UsbIo,\r
1086 (USB_DT_DEVICE << 8),\r
1087 0,\r
1088 sizeof (EFI_USB_DEVICE_DESCRIPTOR),\r
1089 &UsbIoDevice->DeviceDescriptor,\r
1090 &Status\r
1091 );\r
1092\r
1093 if (EFI_ERROR (Result)) {\r
1094 DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n"));\r
1095 ReportUsbStatusCode (\r
1096 UsbBusDev,\r
1097 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1098 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR\r
1099 );\r
1100 UsbFreeAddress (\r
1101 DevAddress,\r
1102 UsbIoDevice->BusController->AddressPool\r
1103 );\r
1104\r
1105 gBS->FreePool (FirstController);\r
1106 return EFI_DEVICE_ERROR;\r
1107 }\r
1108 //\r
1109 // Get & parse all configurations for this device, including\r
1110 // all configuration descriptors, all interface descriptors, all\r
1111 // endpoint descriptors\r
1112 //\r
1113 Result = UsbGetAllConfigurations (UsbIoDevice);\r
1114\r
1115 if (EFI_ERROR (Result)) {\r
1116 DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n"));\r
1117 ReportUsbStatusCode (\r
1118 UsbBusDev,\r
1119 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1120 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR\r
1121 );\r
1122 UsbFreeAddress (\r
1123 DevAddress,\r
1124 UsbIoDevice->BusController->AddressPool\r
1125 );\r
1126\r
1127 gBS->FreePool (FirstController);\r
1128 return EFI_DEVICE_ERROR;\r
1129 }\r
1130 //\r
1131 // Set the 1st configuration value\r
1132 //\r
1133 Result = UsbSetDefaultConfiguration (UsbIoDevice);\r
1134 if (EFI_ERROR (Result)) {\r
1135 DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n"));\r
1136 ReportUsbStatusCode (\r
1137 UsbBusDev,\r
1138 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1139 EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR\r
1140 );\r
1141 UsbFreeAddress (\r
1142 DevAddress,\r
1143 UsbIoDevice->BusController->AddressPool\r
1144 );\r
1145\r
1146 gBS->FreePool (FirstController);\r
1147 return EFI_DEVICE_ERROR;\r
1148 }\r
1149\r
1150 UsbIoDevice->IsConfigured = TRUE;\r
1151\r
1152 //\r
1153 // Get all string table if applicable\r
1154 //\r
1155 Result = UsbGetStringtable (UsbIoDevice);\r
1156 if (EFI_ERROR (Result)) {\r
1157 DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n"));\r
1158 } else {\r
1159\r
1160 StrManufacturer = NULL;\r
1161 UsbIo->UsbGetStringDescriptor (\r
1162 UsbIo,\r
1163 UsbIoDevice->LangID[0],\r
1164 (UsbIoDevice->DeviceDescriptor).StrManufacturer,\r
1165 &StrManufacturer\r
1166 );\r
1167\r
1168 StrProduct = NULL;\r
1169 UsbIo->UsbGetStringDescriptor (\r
1170 UsbIo,\r
1171 UsbIoDevice->LangID[0],\r
1172 (UsbIoDevice->DeviceDescriptor).StrProduct,\r
1173 &StrProduct\r
1174 );\r
1175\r
1176 StrSerialNumber = NULL;\r
1177 UsbIo->UsbGetStringDescriptor (\r
1178 UsbIo,\r
1179 UsbIoDevice->LangID[0],\r
1180 (UsbIoDevice->DeviceDescriptor).StrSerialNumber,\r
1181 &StrSerialNumber\r
1182 );\r
1183\r
1184 if (StrManufacturer) {\r
1185 gBS->FreePool (StrManufacturer);\r
1186 }\r
1187\r
1188 if (StrProduct) {\r
1189 gBS->FreePool (StrProduct);\r
1190 }\r
1191\r
1192 if (StrSerialNumber) {\r
1193 gBS->FreePool (StrSerialNumber);\r
1194 }\r
1195 }\r
1196 //\r
1197 // Create USB_IO_CONTROLLER_DEVICE for\r
1198 // each detected interface\r
1199 //\r
1200 FirstController->CurrentConfigValue =\r
1201 UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;\r
1202\r
1203 NumOfInterface =\r
1204 UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces;\r
1205 UsbIoDevice->NumOfControllers = NumOfInterface;\r
1206\r
1207 Result = InitUsbIoController (FirstController);\r
1208 if (EFI_ERROR (Result)) {\r
1209 ReportUsbStatusCode (\r
1210 UsbBusDev,\r
1211 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1212 EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR\r
1213 );\r
1214 gBS->FreePool (FirstController);\r
1215 UsbIoDevice->UsbController[0] = NULL;\r
1216 return EFI_DEVICE_ERROR;\r
1217 }\r
1218\r
1219 for (Index = 1; Index < NumOfInterface; Index++) {\r
1220 UsbIoController = CreateUsbIoControllerDevice ();\r
1221 UsbIoController->UsbDevice = UsbIoDevice;\r
1222 UsbIoController->CurrentConfigValue =\r
1223 UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;\r
1224 UsbIoController->InterfaceNumber = Index;\r
1225 UsbIoDevice->UsbController[Index] = UsbIoController;\r
1226 UsbIoController->ParentPort = ParentPort;\r
1227 UsbIoController->Parent = ParentHubController;\r
1228 UsbIoController->HostController = HostController;\r
1229\r
1230 //\r
1231 // First copy the USB_IO Protocol instance\r
1232 //\r
1233 CopyMem (\r
1234 &UsbIoController->UsbIo,\r
1235 UsbIo,\r
1236 sizeof (EFI_USB_IO_PROTOCOL)\r
1237 );\r
1238\r
1239 Result = InitUsbIoController (UsbIoController);\r
1240 if (EFI_ERROR (Result)) {\r
1241 ReportUsbStatusCode (\r
1242 UsbBusDev,\r
1243 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
1244 EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR\r
1245 );\r
1246 gBS->FreePool (UsbIoController);\r
1247 UsbIoDevice->UsbController[Index] = NULL;\r
1248 }\r
1249 }\r
1250\r
1251 return EFI_SUCCESS;\r
1252}\r
1253//\r
1254// USB Device DeConfiguration\r
1255//\r
878ddf1f 1256EFI_STATUS\r
1257UsbDeviceDeConfiguration (\r
1258 IN USB_IO_DEVICE *UsbIoDevice\r
1259 )\r
1260/*++\r
1261\r
1262 Routine Description:\r
1263 Remove Device, Device Handles, Uninstall Protocols.\r
1264\r
1265 Arguments:\r
1266 UsbIoDevice - The device to be deconfigured.\r
1267\r
1268 Returns: \r
1269 EFI_SUCCESS\r
1270 EFI_DEVICE_ERROR\r
1271\r
1272--*/\r
1273{\r
1274 USB_IO_CONTROLLER_DEVICE *UsbController;\r
1275 UINT8 index;\r
1276 USB_IO_DEVICE *ChildDevice;\r
1277 UINT8 Index;\r
1278 EFI_USB_IO_PROTOCOL *UsbIo;\r
1279\r
878ddf1f 1280 //\r
1281 // Double check UsbIoDevice exists\r
1282 //\r
1283 if (UsbIoDevice == NULL) {\r
1284 return EFI_SUCCESS;\r
1285 }\r
1286\r
562d2849 1287 UsbUnsetTransactionTranslator (UsbIoDevice);\r
1288\r
878ddf1f 1289 for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {\r
1290 //\r
1291 // Check if it is a hub, if so, de configuration all its\r
1292 // downstream ports\r
1293 //\r
1294 UsbController = UsbIoDevice->UsbController[index];\r
1295\r
1296 //\r
1297 // Check the controller pointer\r
1298 //\r
1299 if (UsbController == NULL) {\r
1300 continue;\r
1301 }\r
1302\r
1303 if (UsbController->IsUsbHub) {\r
1304\r
1305 DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n"));\r
1306\r
1307 //\r
1308 // First Remove interrupt transfer request for the status\r
1309 // change port\r
1310 //\r
1311 UsbIo = &UsbController->UsbIo;\r
1312 UsbIo->UsbAsyncInterruptTransfer (\r
1313 UsbIo,\r
1314 UsbController->HubEndpointAddress,\r
1315 FALSE,\r
1316 0,\r
1317 0,\r
1318 NULL,\r
1319 NULL\r
1320 );\r
1321\r
1322 if (NULL != UsbController->HubNotify) {\r
1323 gBS->CloseEvent (UsbController->HubNotify);\r
1324 }\r
1325\r
1326 for (Index = 0; Index < UsbController->DownstreamPorts; Index++) {\r
1327 if (UsbController->Children[Index]) {\r
1328 ChildDevice = UsbController->Children[Index];\r
1329 UsbDeviceDeConfiguration (ChildDevice);\r
1330 UsbController->Children[Index] = NULL;\r
1331 }\r
1332 }\r
1333 }\r
1334 //\r
1335 // If the controller is managed by a device driver, we need to\r
1336 // disconnect them\r
1337 //\r
1338 if (UsbController->IsManagedByDriver) {\r
1339 gBS->DisconnectController (\r
1340 UsbController->Handle,\r
1341 NULL,\r
1342 NULL\r
1343 );\r
1344 }\r
1345 \r
1346 //\r
1347 // remove child handle reference to the USB_HC_PROTOCOL\r
1348 //\r
562d2849 1349 if (UsbIoDevice->BusController->Hc2ProtocolSupported) {\r
1350 gBS->CloseProtocol (\r
1351 UsbController->HostController,\r
1352 &gEfiUsb2HcProtocolGuid,\r
1353 gUsbBusDriverBinding.DriverBindingHandle,\r
1354 UsbController->Handle\r
1355 );\r
1356 } else {\r
1357 gBS->CloseProtocol (\r
1358 UsbController->HostController,\r
1359 &gEfiUsbHcProtocolGuid,\r
1360 gUsbBusDriverBinding.DriverBindingHandle,\r
1361 UsbController->Handle\r
1362 );\r
1363 }\r
878ddf1f 1364 //\r
1365 // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL\r
1366 // installed on this handle\r
1367 //\r
1368 gBS->UninstallMultipleProtocolInterfaces (\r
1369 UsbController->Handle,\r
1370 &gEfiDevicePathProtocolGuid,\r
1371 UsbController->DevicePath,\r
1372 &gEfiUsbIoProtocolGuid,\r
1373 &UsbController->UsbIo,\r
1374 NULL\r
1375 );\r
1376\r
1377 if (UsbController->DevicePath != NULL) {\r
1378 gBS->FreePool (UsbController->DevicePath);\r
1379 }\r
1380\r
1381 gBS->FreePool (UsbController);\r
1382 UsbIoDevice->UsbController[index] = NULL;\r
1383 }\r
1384 //\r
1385 // Free address for later use\r
1386 //\r
1387 UsbFreeAddress (\r
1388 UsbIoDevice->DeviceAddress,\r
1389 UsbIoDevice->BusController->AddressPool\r
1390 );\r
1391\r
1392 //\r
1393 // Free all resouces allocated for all its configurations\r
1394 //\r
1395 UsbDestroyAllConfiguration (UsbIoDevice);\r
1396\r
1397 if (UsbIoDevice) {\r
1398 gBS->FreePool (UsbIoDevice);\r
1399 UsbIoDevice = NULL;\r
1400 }\r
1401\r
1402 return EFI_SUCCESS;\r
1403}\r
1404//\r
1405// After interrupt complete, this function will be called,\r
1406// This function need to be well-defined later\r
1407//\r
1408STATIC\r
1409EFI_STATUS\r
1410EFIAPI\r
1411OnHubInterruptComplete (\r
1412 IN VOID *Data,\r
1413 IN UINTN DataLength,\r
1414 IN VOID *Context,\r
1415 IN UINT32 Result\r
1416 )\r
1417/*++\r
1418\r
1419 Routine Description:\r
1420 Whenever hub interrupt occurs, this routine will be called to check\r
1421 which event happens.\r
1422\r
1423 Arguments:\r
1424 Data - Hub interrupt transfer data.\r
1425 DataLength - The length of the Data.\r
1426 Context - Hub Controller Device.\r
1427 Result - Hub interrupt transfer status.\r
1428\r
1429 Returns:\r
1430 EFI_SUCCESS\r
1431 EFI_DEVICE_ERROR\r
1432\r
1433--*/\r
1434{\r
1435 USB_IO_CONTROLLER_DEVICE *HubController;\r
1436 UINT8 Index;\r
1437 UINT8 *ptr;\r
1438 EFI_USB_IO_PROTOCOL *UsbIo;\r
1439 UINT32 UsbResult;\r
1440 BOOLEAN Disconnected;\r
1441 EFI_STATUS Status;\r
1442\r
1443 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;\r
1444 UsbIo = &HubController->UsbIo;\r
1445\r
1446 //\r
1447 // If something error in this interrupt transfer,\r
1448 //\r
1449 if (Result != EFI_USB_NOERROR) {\r
1450 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {\r
1451 UsbClearEndpointHalt (\r
1452 UsbIo,\r
1453 HubController->HubEndpointAddress,\r
1454 &UsbResult\r
1455 );\r
1456 }\r
1457 \r
1458 //\r
1459 // Delete & Submit this interrupt again\r
1460 //\r
1461 UsbIo->UsbAsyncInterruptTransfer (\r
1462 UsbIo,\r
1463 HubController->HubEndpointAddress,\r
1464 FALSE,\r
1465 0,\r
1466 0,\r
1467 NULL,\r
1468 NULL\r
1469 );\r
1470\r
1471 //\r
1472 // try to detect if the hub itself was disconnected or not\r
1473 //\r
1474 Status = IsDeviceDisconnected (\r
1475 HubController,\r
1476 &Disconnected\r
1477 );\r
1478\r
1479 if (!EFI_ERROR (Status) && Disconnected == TRUE) {\r
1480 DEBUG ((gUSBErrorLevel, "Hub is disconnected\n"));\r
1481 return EFI_DEVICE_ERROR;\r
1482 }\r
1483 //\r
1484 // Hub ports < 7\r
1485 //\r
1486 UsbIo->UsbAsyncInterruptTransfer (\r
1487 UsbIo,\r
1488 HubController->HubEndpointAddress,\r
1489 TRUE,\r
1490 100,\r
1491 1,\r
1492 OnHubInterruptComplete,\r
1493 HubController\r
1494 );\r
1495\r
1496 return EFI_DEVICE_ERROR;\r
1497 }\r
1498\r
1499 if (DataLength == 0 || Data == NULL) {\r
1500 return EFI_SUCCESS;\r
1501 }\r
1502 \r
1503 //\r
1504 // Scan which port has status change\r
1505 // Bit 0 stands for hub itself, other bit stands for\r
1506 // the corresponding port\r
1507 //\r
1508 for (Index = 0; Index < DataLength * 8; Index++) {\r
1509 ptr = (UINT8 *) Data + Index / 8;\r
1510 if ((*ptr) & (1 << (Index & 0x7))) {\r
1511 HubController->StatusChangePort = Index;\r
1512 break;\r
1513 }\r
1514 }\r
1515 //\r
1516 // Signal hub notify event\r
1517 //\r
1518 gBS->SignalEvent (HubController->HubNotify);\r
1519\r
1520 return EFI_SUCCESS;\r
1521}\r
1522//\r
1523// USB Root Hub Enumerator\r
1524//\r
1525STATIC\r
1526VOID\r
1527EFIAPI\r
562d2849 1528RootHubEnumeration (\r
878ddf1f 1529 IN EFI_EVENT Event,\r
1530 IN VOID *Context\r
1531 )\r
1532/*++\r
1533\r
1534 Routine Description:\r
562d2849 1535 \r
1536 This is USB RootHub enumerator\r
878ddf1f 1537\r
1538 Arguments:\r
562d2849 1539 \r
878ddf1f 1540 Event - Indicating which event is signaled\r
1541 Context - actually it is a USB_IO_DEVICE\r
1542\r
1543 Returns:\r
562d2849 1544 \r
1545 VOID\r
1546 \r
878ddf1f 1547--*/\r
1548{\r
1549 USB_IO_CONTROLLER_DEVICE *HubController;\r
1550 EFI_USB_PORT_STATUS HubPortStatus;\r
1551 EFI_STATUS Status;\r
1552 UINT8 Index;\r
878ddf1f 1553 USB_IO_DEVICE *UsbIoDev;\r
1554 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
1555 EFI_HANDLE HostController;\r
1556 USB_IO_DEVICE *OldUsbIoDevice;\r
1557 USB_IO_DEVICE *NewDevice;\r
1558 USB_IO_CONTROLLER_DEVICE *NewController;\r
1559 UINT8 Index2;\r
1560 EFI_USB_IO_PROTOCOL *UsbIo;\r
878ddf1f 1561\r
1562 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;\r
1563 HostController = HubController->HostController;\r
1564 UsbBusDev = HubController->UsbDevice->BusController;\r
1565\r
562d2849 1566 //\r
1567 // Root hub has the address 1\r
1568 //\r
1569 UsbIoDev = HubController->UsbDevice;\r
1570\r
1571 for (Index = 0; Index < HubController->DownstreamPorts; Index++) {\r
1572\r
1573 UsbVirtualHcGetRootHubPortStatus (\r
1574 UsbBusDev,\r
1575 Index,\r
1576 (EFI_USB_PORT_STATUS *) &HubPortStatus\r
1577 );\r
1578\r
1579 if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {\r
1580 continue;\r
1581 }\r
878ddf1f 1582 //\r
562d2849 1583 // Clear root hub status change status\r
878ddf1f 1584 //\r
562d2849 1585 UsbVirtualHcClearRootHubPortFeature (\r
1586 UsbBusDev,\r
1587 Index,\r
1588 EfiUsbPortConnectChange\r
1589 );\r
878ddf1f 1590\r
562d2849 1591 gBS->Stall (100 * 1000);\r
1592\r
1593 UsbVirtualHcGetRootHubPortStatus (\r
1594 UsbBusDev,\r
1595 Index,\r
1596 (EFI_USB_PORT_STATUS *) &HubPortStatus\r
1597 );\r
1598\r
1599 if (IsPortConnect (HubPortStatus.PortStatus)) {\r
1600 \r
878ddf1f 1601 //\r
562d2849 1602 // There is something connected to this port\r
878ddf1f 1603 //\r
562d2849 1604 DEBUG ((gUSBDebugLevel, "Something connected to Root Hub at Port0x%x\n", Index));\r
1605\r
1606 ReportUsbStatusCode (\r
1607 UsbBusDev,\r
1608 EFI_PROGRESS_CODE,\r
1609 EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG\r
878ddf1f 1610 );\r
562d2849 1611 //\r
1612 // if there is something physically detached, but still logically\r
1613 // attached...\r
1614 //\r
1615 OldUsbIoDevice = HubController->Children[Index];\r
878ddf1f 1616\r
562d2849 1617 if (NULL != OldUsbIoDevice) {\r
1618 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
1619 HubController->Children[Index] = NULL;\r
1620 }\r
878ddf1f 1621\r
562d2849 1622 NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));\r
1623 if (NewDevice == NULL) {\r
1624 return ;\r
1625 }\r
1626 //\r
1627 // Initialize some fields by copying data from\r
1628 // its parents\r
1629 //\r
1630 NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;\r
1631 NewDevice->BusController = UsbIoDev->BusController;\r
878ddf1f 1632\r
562d2849 1633 //\r
1634 // Process of identify device speed\r
1635 //\r
1636 Status = IdentifyDeviceSpeed (\r
1637 UsbBusDev, \r
1638 NewDevice, \r
1639 Index\r
1640 );\r
1641 if (EFI_ERROR (Status)) {\r
1642 gBS->FreePool (NewDevice);\r
1643 continue;\r
1644 }\r
1645\r
1646 //\r
1647 // Configure that device\r
1648 //\r
1649 Status = UsbDeviceConfiguration (\r
1650 HubController,\r
1651 HostController,\r
1652 Index,\r
1653 NewDevice\r
1654 );\r
1655 if (EFI_ERROR (Status)) {\r
1656 gBS->FreePool (NewDevice);\r
1657 return ;\r
1658 }\r
1659 //\r
1660 // Add this device to the usb bus tree\r
1661 //\r
1662 HubController->Children[Index] = NewDevice;\r
1663\r
1664 for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {\r
878ddf1f 1665 //\r
562d2849 1666 // If this device is hub, add to the hub index\r
878ddf1f 1667 //\r
562d2849 1668 NewController = NewDevice->UsbController[Index2];\r
878ddf1f 1669\r
562d2849 1670 Status = gBS->ConnectController (\r
1671 NewController->Handle,\r
1672 NULL,\r
1673 NULL,\r
1674 TRUE\r
1675 );\r
878ddf1f 1676 //\r
562d2849 1677 // If connect success, we need to disconnect when\r
1678 // stop the controller, otherwise we need not call\r
1679 // gBS->DisconnectController ()\r
1680 // This is used by those usb devices we don't plan\r
1681 // to support. We can allocate\r
1682 // controller handles for them, but we don't have\r
1683 // device drivers to manage them.\r
878ddf1f 1684 //\r
562d2849 1685 NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));\r
878ddf1f 1686\r
562d2849 1687 if (IsHub (NewController)) {\r
878ddf1f 1688\r
562d2849 1689 NewController->IsUsbHub = TRUE;\r
878ddf1f 1690\r
878ddf1f 1691 //\r
562d2849 1692 // Configure Hub Controller\r
878ddf1f 1693 //\r
562d2849 1694 Status = DoHubConfig (NewController);\r
1695 if (EFI_ERROR (Status)) {\r
1696 continue;\r
1697 }\r
878ddf1f 1698 //\r
562d2849 1699 // Create an event to do hub enumeration\r
878ddf1f 1700 //\r
562d2849 1701 gBS->CreateEvent (\r
1702 EFI_EVENT_NOTIFY_SIGNAL,\r
1703 EFI_TPL_CALLBACK,\r
1704 HubEnumeration,\r
1705 NewController,\r
1706 &NewController->HubNotify\r
1707 );\r
878ddf1f 1708\r
562d2849 1709 //\r
1710 // Add request to do query hub status\r
1711 // change endpoint\r
1712 // Hub ports < 7\r
1713 //\r
1714 UsbIo = &NewController->UsbIo;\r
1715 UsbIo->UsbAsyncInterruptTransfer (\r
1716 UsbIo,\r
1717 NewController->HubEndpointAddress,\r
1718 TRUE,\r
1719 100,\r
1720 1,\r
1721 OnHubInterruptComplete,\r
1722 NewController\r
1723 );\r
878ddf1f 1724\r
878ddf1f 1725 }\r
562d2849 1726 }\r
1727 } else {\r
1728 //\r
1729 // Something disconnected from USB root hub\r
1730 //\r
1731 DEBUG ((gUSBDebugLevel, "Something disconnected from Root Hub at Port0x%x\n", Index));\r
878ddf1f 1732\r
562d2849 1733 OldUsbIoDevice = HubController->Children[Index];\r
878ddf1f 1734\r
562d2849 1735 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
878ddf1f 1736\r
562d2849 1737 HubController->Children[Index] = NULL;\r
1738\r
1739 UsbVirtualHcClearRootHubPortFeature (\r
1740 UsbBusDev,\r
1741 Index,\r
1742 EfiUsbPortEnableChange\r
1743 );\r
1744 }\r
1745 }\r
1746\r
1747 return ;\r
1748}\r
1749//\r
1750// USB Root Hub Enumerator\r
1751//\r
1752STATIC\r
1753VOID\r
1754EFIAPI\r
1755HubEnumeration (\r
1756 IN EFI_EVENT Event,\r
1757 IN VOID *Context\r
1758 )\r
1759/*++\r
878ddf1f 1760\r
562d2849 1761 Routine Description:\r
1762 \r
1763 This is Usb Hub enumerator\r
878ddf1f 1764\r
562d2849 1765 Arguments:\r
1766 \r
1767 Event - Indicating which event is signaled\r
1768 Context - actually it is a USB_IO_DEVICE\r
878ddf1f 1769\r
562d2849 1770 Returns:\r
878ddf1f 1771\r
562d2849 1772 VOID\r
1773\r
1774--*/\r
1775{\r
1776 USB_IO_CONTROLLER_DEVICE *HubController;\r
1777 EFI_USB_PORT_STATUS HubPortStatus;\r
1778 EFI_STATUS Status;\r
1779 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;\r
1780 EFI_HANDLE HostController;\r
1781 USB_IO_DEVICE *OldUsbIoDevice;\r
1782 USB_IO_DEVICE *NewDevice;\r
1783 USB_IO_CONTROLLER_DEVICE *NewController;\r
1784 UINT8 Index2;\r
1785 EFI_USB_IO_PROTOCOL *UsbIo;\r
1786 UINT8 StatusChangePort;\r
1787 UINT8 Number;\r
1788\r
1789 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;\r
1790 HostController = HubController->HostController;\r
1791 UsbBusDev = HubController->UsbDevice->BusController;\r
1792\r
1793 //\r
1794 // Event from Hub, Get the hub controller handle\r
1795 //\r
1796 //\r
1797 // Get the status change endpoint\r
1798 //\r
1799 StatusChangePort = HubController->StatusChangePort;\r
1800\r
1801 //\r
1802 // Clear HubController Status Change Bit\r
1803 //\r
1804 HubController->StatusChangePort = 0;\r
1805\r
1806 if (StatusChangePort == 0) {\r
878ddf1f 1807 //\r
562d2849 1808 // Hub changes, we don't handle here\r
878ddf1f 1809 //\r
562d2849 1810 return ;\r
1811 }\r
1812 //\r
1813 // Check which event took place at that port\r
1814 //\r
1815 UsbIo = &HubController->UsbIo;\r
1816 Status = HubGetPortStatus (\r
1817 UsbIo,\r
1818 StatusChangePort,\r
1819 (UINT32 *) &HubPortStatus\r
1820 );\r
1821\r
1822 if (EFI_ERROR (Status)) {\r
1823 return ;\r
1824 }\r
1825 //\r
1826 // Clear some change status\r
1827 //\r
1828 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {\r
878ddf1f 1829 //\r
562d2849 1830 // Clear Hub port enable change\r
878ddf1f 1831 //\r
562d2849 1832 DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));\r
1833 HubClearPortFeature (\r
1834 UsbIo,\r
1835 StatusChangePort,\r
1836 EfiUsbPortEnableChange\r
1837 );\r
1838\r
1839 HubGetPortStatus (\r
1840 UsbIo,\r
1841 StatusChangePort,\r
1842 (UINT32 *) &HubPortStatus\r
1843 );\r
1844 }\r
878ddf1f 1845\r
562d2849 1846 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {\r
878ddf1f 1847 //\r
562d2849 1848 // Clear Hub reset change\r
878ddf1f 1849 //\r
562d2849 1850 DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));\r
1851 HubClearPortFeature (\r
1852 UsbIo,\r
1853 StatusChangePort,\r
1854 EfiUsbPortResetChange\r
1855 );\r
878ddf1f 1856\r
562d2849 1857 HubGetPortStatus (\r
1858 UsbIo,\r
1859 StatusChangePort,\r
1860 (UINT32 *) &HubPortStatus\r
1861 );\r
1862 }\r
1863\r
1864 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {\r
878ddf1f 1865 //\r
562d2849 1866 // Clear Hub overcurrent change\r
878ddf1f 1867 //\r
562d2849 1868 DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));\r
1869 HubClearPortFeature (\r
1870 UsbIo,\r
1871 StatusChangePort,\r
1872 EfiUsbPortOverCurrentChange\r
1873 );\r
878ddf1f 1874\r
562d2849 1875 HubGetPortStatus (\r
1876 UsbIo,\r
1877 StatusChangePort,\r
1878 (UINT32 *) &HubPortStatus\r
1879 );\r
1880 }\r
1881\r
1882 if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {\r
878ddf1f 1883 //\r
562d2849 1884 // First clear port connection change\r
878ddf1f 1885 //\r
562d2849 1886 DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));\r
1887 HubClearPortFeature (\r
1888 UsbIo,\r
1889 StatusChangePort,\r
1890 EfiUsbPortConnectChange\r
1891 );\r
878ddf1f 1892\r
562d2849 1893 HubGetPortStatus (\r
1894 UsbIo,\r
1895 StatusChangePort,\r
1896 (UINT32 *) &HubPortStatus\r
1897 );\r
1898\r
1899 if (IsPortConnect (HubPortStatus.PortStatus)) {\r
1900\r
1901 DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));\r
1902\r
1903 ReportUsbStatusCode (\r
1904 UsbBusDev,\r
1905 EFI_PROGRESS_CODE,\r
1906 EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG\r
878ddf1f 1907 );\r
878ddf1f 1908\r
878ddf1f 1909 //\r
562d2849 1910 // if there is something physically detached, but still logically\r
1911 // attached...\r
878ddf1f 1912 //\r
562d2849 1913 OldUsbIoDevice = HubController->Children[StatusChangePort - 1];\r
878ddf1f 1914\r
562d2849 1915 if (NULL != OldUsbIoDevice) {\r
1916 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
1917 HubController->Children[StatusChangePort - 1] = NULL;\r
1918 }\r
878ddf1f 1919\r
562d2849 1920 NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));\r
1921 if (NewDevice == NULL) {\r
1922 return ;\r
1923 }\r
878ddf1f 1924 //\r
562d2849 1925 // Initialize some fields\r
878ddf1f 1926 //\r
562d2849 1927 NewDevice->DeviceDescriptor.MaxPacketSize0 = 8;\r
1928 NewDevice->BusController = HubController->UsbDevice->BusController;\r
878ddf1f 1929\r
878ddf1f 1930 //\r
562d2849 1931 // There is something connected to this port,\r
1932 // reset that port\r
1933 //\r
1934 // Disable the enable bit in port status\r
878ddf1f 1935 //\r
878ddf1f 1936 HubClearPortFeature (\r
1937 UsbIo,\r
1938 StatusChangePort,\r
562d2849 1939 EfiUsbPortEnable\r
878ddf1f 1940 );\r
1941\r
562d2849 1942 gBS->Stall (50 * 1000);\r
878ddf1f 1943\r
562d2849 1944 //\r
1945 // Wait for bit change\r
1946 //\r
1947 Number = 10;\r
1948 do {\r
1949 HubGetPortStatus (\r
1950 UsbIo,\r
1951 StatusChangePort,\r
1952 (UINT32 *) &HubPortStatus\r
878ddf1f 1953 );\r
562d2849 1954 gBS->Stall (10 * 1000);\r
1955 Number -= 1;\r
1956 } while ((HubPortStatus.PortStatus & USB_PORT_STAT_ENABLE) == 1 && Number > 0);\r
878ddf1f 1957\r
562d2849 1958 if (Number == 0) {\r
878ddf1f 1959 //\r
562d2849 1960 // Cannot disable port, return error\r
878ddf1f 1961 //\r
562d2849 1962 DEBUG ((gUSBErrorLevel, "Disable Port Failed\n"));\r
1963 gBS->FreePool (NewDevice);\r
1964 return ;\r
1965 }\r
878ddf1f 1966\r
562d2849 1967 HubSetPortFeature (\r
1968 UsbIo,\r
1969 StatusChangePort,\r
1970 EfiUsbPortReset\r
1971 );\r
878ddf1f 1972\r
562d2849 1973 gBS->Stall (50 * 1000);\r
878ddf1f 1974\r
562d2849 1975 //\r
1976 // Wait for port reset complete\r
1977 //\r
1978 Number = 10;\r
1979 do {\r
878ddf1f 1980 HubGetPortStatus (\r
1981 UsbIo,\r
1982 StatusChangePort,\r
1983 (UINT32 *) &HubPortStatus\r
1984 );\r
562d2849 1985 gBS->Stall (10 * 1000);\r
1986 Number -= 1;\r
1987 } while ((HubPortStatus.PortStatus & USB_PORT_STAT_RESET) == 1 && Number > 0);\r
878ddf1f 1988\r
562d2849 1989 if (Number == 0) {\r
878ddf1f 1990 //\r
562d2849 1991 // Cannot reset port, return error\r
878ddf1f 1992 //\r
562d2849 1993 DEBUG ((gUSBErrorLevel, "Reset Port Failed\n"));\r
1994 gBS->FreePool (NewDevice);\r
1995 return ;\r
1996 }\r
1997 //\r
1998 // Check high speed or full speed device\r
1999 //\r
2000 if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {\r
2001 DEBUG ((gUSBDebugLevel, "Low Speed Device Attached to Hub\n"));\r
2002 NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW;\r
2003 } else if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {\r
2004 DEBUG ((gUSBDebugLevel, "High Speed Device Attached to Hub\n"));\r
2005 NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH;\r
2006 } else {\r
2007 DEBUG ((gUSBDebugLevel, "Full Speed Device Attached to Hub\n"));\r
2008 NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL;\r
2009 }\r
2010 //\r
2011 // Configure that device\r
2012 //\r
2013 Status = UsbDeviceConfiguration (\r
2014 HubController,\r
2015 HostController,\r
2016 (UINT8) (StatusChangePort - 1),\r
2017 NewDevice\r
2018 );\r
878ddf1f 2019\r
562d2849 2020 if (EFI_ERROR (Status)) {\r
2021 gBS->FreePool (NewDevice);\r
2022 return ;\r
2023 }\r
2024 //\r
2025 // Add this device to the usb bus tree\r
2026 // StatusChangePort is begin from 1,\r
2027 //\r
2028 HubController->Children[StatusChangePort - 1] = NewDevice;\r
878ddf1f 2029\r
562d2849 2030 for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {\r
878ddf1f 2031 //\r
562d2849 2032 // If this device is hub, add to the hub index\r
878ddf1f 2033 //\r
562d2849 2034 NewController = NewDevice->UsbController[Index2];\r
878ddf1f 2035\r
878ddf1f 2036 //\r
562d2849 2037 // Connect the controller to the driver image\r
2038 //\r
2039 Status = gBS->ConnectController (\r
2040 NewController->Handle,\r
2041 NULL,\r
2042 NULL,\r
2043 TRUE\r
2044 );\r
2045 //\r
2046 // If connect success, we need to disconnect when\r
2047 // stop the controller, otherwise we need not call\r
2048 // gBS->DisconnectController ()\r
2049 // This is used by those usb devices we don't plan\r
2050 // to support. We can allocate\r
2051 // controller handles for them, but we don't have\r
2052 // device drivers to manage them.\r
878ddf1f 2053 //\r
562d2849 2054 NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));\r
878ddf1f 2055\r
562d2849 2056 //\r
2057 // If this device is hub, add to the hub index\r
2058 //\r
2059 if (IsHub (NewController)) {\r
2060\r
2061 NewController->IsUsbHub = TRUE;\r
878ddf1f 2062\r
2063 //\r
562d2849 2064 // Configure Hub\r
878ddf1f 2065 //\r
562d2849 2066 Status = DoHubConfig (NewController);\r
2067\r
2068 if (EFI_ERROR (Status)) {\r
2069 continue;\r
2070 }\r
878ddf1f 2071 //\r
562d2849 2072 // Create an event to do hub enumeration\r
878ddf1f 2073 //\r
562d2849 2074 gBS->CreateEvent (\r
2075 EFI_EVENT_NOTIFY_SIGNAL,\r
2076 EFI_TPL_CALLBACK,\r
2077 HubEnumeration,\r
2078 NewController,\r
2079 &NewController->HubNotify\r
2080 );\r
878ddf1f 2081\r
2082 //\r
562d2849 2083 // Add request to do query hub status\r
2084 // change endpoint\r
878ddf1f 2085 //\r
562d2849 2086 UsbIo = &NewController->UsbIo;\r
2087 UsbIo->UsbAsyncInterruptTransfer (\r
2088 UsbIo,\r
2089 NewController->HubEndpointAddress, // Hub endpoint address\r
2090 TRUE,\r
2091 100,\r
2092 1, // Hub ports < 7\r
2093 OnHubInterruptComplete,\r
2094 NewController\r
878ddf1f 2095 );\r
878ddf1f 2096 }\r
562d2849 2097 }\r
2098 } else {\r
2099 //\r
2100 // Something disconnected from USB hub\r
2101 //\r
2102 DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));\r
878ddf1f 2103\r
562d2849 2104 OldUsbIoDevice = HubController->Children[StatusChangePort - 1];\r
878ddf1f 2105\r
562d2849 2106 UsbDeviceDeConfiguration (OldUsbIoDevice);\r
878ddf1f 2107\r
562d2849 2108 HubController->Children[StatusChangePort - 1] = NULL;\r
878ddf1f 2109\r
878ddf1f 2110 }\r
2111\r
2112 return ;\r
2113 }\r
878ddf1f 2114\r
562d2849 2115 return ;\r
878ddf1f 2116}\r
2117\r
2118STATIC\r
2119USB_IO_CONTROLLER_DEVICE *\r
2120CreateUsbIoControllerDevice (\r
2121 VOID\r
2122 )\r
2123/*++\r
2124\r
2125 Routine Description:\r
2126 Allocate a structure for USB_IO_CONTROLLER_DEVICE\r
2127\r
2128 Arguments:\r
2129 N/A\r
2130\r
2131 Returns:\r
2132 A pointer to a USB_IO_CONTROLLER_DEVICE structure,\r
2133 Or NULL.\r
2134\r
2135--*/\r
2136{\r
2137 USB_IO_CONTROLLER_DEVICE *UsbIoControllerDev;\r
2138\r
2139 //\r
2140 // Allocate USB_IO_CONTROLLER_DEVICE structure\r
2141 //\r
2142 UsbIoControllerDev = NULL;\r
2143 UsbIoControllerDev = AllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE));\r
2144\r
2145 if (UsbIoControllerDev == NULL) {\r
2146 return NULL;\r
2147 }\r
2148\r
2149 UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE;\r
2150\r
2151 return UsbIoControllerDev;\r
2152}\r
2153\r
2154STATIC\r
2155EFI_STATUS\r
2156InitUsbIoController (\r
2157 IN USB_IO_CONTROLLER_DEVICE *UsbIoController\r
2158 )\r
2159/*++\r
2160\r
2161 Routine Description:\r
2162 Init and install EFI_USB_IO_PROTOCOL onto that controller.\r
2163\r
2164 Arguments:\r
2165 UsbIoController - The Controller to be operated.\r
2166\r
2167 Returns:\r
2168 EFI_SUCCESS\r
2169 Others\r
2170\r
2171--*/\r
2172{\r
2173 USB_DEVICE_PATH UsbNode;\r
2174 EFI_STATUS Status;\r
2175 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
2176 EFI_USB_HC_PROTOCOL *UsbHcProtocol;\r
562d2849 2177 EFI_USB2_HC_PROTOCOL *Usb2HcProtocol;\r
878ddf1f 2178\r
2179 //\r
2180 // Build the child device path for each new USB_IO device\r
2181 //\r
2182 ZeroMem (&UsbNode, sizeof (UsbNode));\r
2183 UsbNode.Header.Type = MESSAGING_DEVICE_PATH;\r
2184 UsbNode.Header.SubType = MSG_USB_DP;\r
2185 SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));\r
2186 UsbNode.InterfaceNumber = UsbIoController->InterfaceNumber;\r
2187 UsbNode.ParentPortNumber = UsbIoController->ParentPort;\r
2188 ParentDevicePath = UsbIoController->Parent->DevicePath;\r
2189\r
2190 UsbIoController->DevicePath =\r
2191 AppendDevicePathNode (ParentDevicePath, &UsbNode.Header);\r
2192 if (UsbIoController->DevicePath == NULL) {\r
2193 return EFI_OUT_OF_RESOURCES;\r
2194 }\r
2195\r
2196 Status = gBS->InstallMultipleProtocolInterfaces (\r
2197 &UsbIoController->Handle,\r
2198 &gEfiDevicePathProtocolGuid,\r
2199 UsbIoController->DevicePath,\r
2200 &gEfiUsbIoProtocolGuid,\r
2201 &UsbIoController->UsbIo,\r
2202 NULL\r
2203 );\r
2204\r
2205 if (EFI_ERROR (Status)) {\r
2206 return Status;\r
2207 }\r
2208\r
562d2849 2209 if (UsbIoController->UsbDevice->BusController->Hc2ProtocolSupported) {\r
2210 Status = gBS->OpenProtocol (\r
2211 UsbIoController->HostController,\r
2212 &gEfiUsb2HcProtocolGuid,\r
2213 (VOID **)&Usb2HcProtocol,\r
2214 gUsbBusDriverBinding.DriverBindingHandle,\r
2215 UsbIoController->Handle,\r
2216 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
2217 );\r
2218 } else {\r
2219 Status = gBS->OpenProtocol (\r
2220 UsbIoController->HostController,\r
2221 &gEfiUsbHcProtocolGuid,\r
2222 (VOID **)&UsbHcProtocol,\r
2223 gUsbBusDriverBinding.DriverBindingHandle,\r
2224 UsbIoController->Handle,\r
2225 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
2226 );\r
2227 }\r
878ddf1f 2228\r
2229 return Status;\r
2230}\r
2231\r
2232STATIC\r
2233EFI_STATUS\r
2234ParentPortReset (\r
2235 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
2236 IN BOOLEAN ReConfigure,\r
2237 IN UINT8 RetryTimes\r
2238 )\r
2239/*++\r
2240\r
2241 Routine Description:\r
2242 Reset parent hub port to which this device is connected.\r
2243\r
2244 Arguments:\r
2245 UsbIoController - Indicating the Usb Controller Device.\r
562d2849 2246 ReConfigure - Do we need to reconfigure it.\r
878ddf1f 2247 RetryTimes - Retry Times when failed\r
562d2849 2248 \r
878ddf1f 2249 Returns:\r
2250 EFI_SUCCESS\r
2251 EFI_DEVICE_ERROR\r
2252\r
2253--*/\r
2254{\r
2255 USB_IO_DEVICE *ParentIoDev;\r
2256 USB_IO_DEVICE *UsbIoDev;\r
2257 USB_IO_CONTROLLER_DEVICE *ParentController;\r
2258 UINT8 HubPort;\r
2259 UINT32 Status;\r
2260 EFI_STATUS Result;\r
2261 EFI_USB_IO_PROTOCOL *UsbIo;\r
2262 UINT8 Address;\r
2263\r
2264 ParentController = UsbIoController->Parent;\r
2265 ParentIoDev = ParentController->UsbDevice;\r
2266 UsbIoDev = UsbIoController->UsbDevice;\r
2267 HubPort = UsbIoController->ParentPort;\r
2268\r
2269 gBS->Stall (100 * 1000);\r
2270\r
2271 if (ParentIoDev->DeviceAddress == 1) {\r
2272 DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));\r
562d2849 2273 ResetRootPort (ParentIoDev->BusController, HubPort, RetryTimes);\r
878ddf1f 2274 } else {\r
2275 DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));\r
2276 ResetHubPort (ParentController, HubPort + 1);\r
2277 }\r
2278 //\r
2279 // If we only need port reset, just return\r
2280 //\r
2281 if (!ReConfigure) {\r
2282 return EFI_SUCCESS;\r
2283 }\r
2284 //\r
2285 // Re-config that USB device\r
2286 //\r
2287 UsbIo = &UsbIoController->UsbIo;\r
2288\r
2289 //\r
2290 // Assign a unique address to this device\r
2291 //\r
2292 Address = UsbIoDev->DeviceAddress;\r
2293 UsbIoDev->DeviceAddress = 0;\r
2294\r
2295 Result = UsbSetDeviceAddress (UsbIo, Address, &Status);\r
2296 UsbIoDev->DeviceAddress = Address;\r
2297\r
2298 if (EFI_ERROR (Result)) {\r
2299 return EFI_DEVICE_ERROR;\r
2300 }\r
2301 //\r
2302 // Set the device to the default configuration\r
2303 //\r
2304 Result = UsbSetDefaultConfiguration (UsbIoDev);\r
2305 if (EFI_ERROR (Result)) {\r
2306 return EFI_DEVICE_ERROR;\r
2307 }\r
2308\r
2309 return EFI_SUCCESS;\r
2310}\r
2311\r
2312EFI_STATUS\r
2313EFIAPI\r
2314UsbPortReset (\r
2315 IN EFI_USB_IO_PROTOCOL *This\r
2316 )\r
2317/*++\r
2318\r
2319 Routine Description:\r
2320 Resets and reconfigures the USB controller. This function will\r
2321 work for all USB devices except USB Hub Controllers.\r
2322\r
2323 Arguments:\r
2324 This - Indicates the calling context.\r
2325\r
2326 Returns:\r
2327 EFI_SUCCESS\r
2328 EFI_INVALID_PARAMETER\r
2329 EFI_DEVICE_ERROR\r
2330\r
2331--*/\r
2332{\r
2333 USB_IO_CONTROLLER_DEVICE *UsbIoController;\r
878ddf1f 2334\r
2335 UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);\r
2336\r
71a62114 2337 if (IsHub (UsbIoController)) {\r
2338 return EFI_INVALID_PARAMETER;\r
2339 }\r
2340 \r
878ddf1f 2341 //\r
2342 // Since at this time, this device has already been configured,\r
2343 // it needs to be re-configured.\r
2344 //\r
71a62114 2345 return ParentPortReset (UsbIoController, TRUE, 0);\r
878ddf1f 2346}\r
2347\r
2348EFI_STATUS\r
2349ResetRootPort (\r
562d2849 2350 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
2351 IN UINT8 PortNum,\r
2352 IN UINT8 RetryTimes\r
878ddf1f 2353 )\r
2354/*++\r
2355\r
2356 Routine Description:\r
2357 Reset Root Hub port.\r
2358\r
2359 Arguments:\r
562d2849 2360 UsbBusDev - Bus controller of the device.\r
2361 PortNum - The given port to be reset.\r
2362 RetryTimes - RetryTimes when failed\r
2363 \r
878ddf1f 2364 Returns:\r
562d2849 2365 EFI_SUCCESS\r
2366 EFI_DEVICE_ERROR\r
878ddf1f 2367\r
2368--*/\r
2369{\r
562d2849 2370 EFI_STATUS Status;\r
2371 EFI_USB_PORT_STATUS PortStatus;\r
878ddf1f 2372\r
2373 //\r
2374 // reset root port\r
2375 //\r
562d2849 2376 Status = UsbVirtualHcSetRootHubPortFeature (\r
2377 UsbBusDev,\r
2378 PortNum,\r
2379 EfiUsbPortReset\r
2380 );\r
878ddf1f 2381 if (EFI_ERROR (Status)) {\r
2382 return EFI_DEVICE_ERROR;\r
2383 }\r
2384\r
2385 gBS->Stall (50 * 1000);\r
2386\r
2387 //\r
2388 // clear reset root port\r
2389 //\r
562d2849 2390 Status = UsbVirtualHcClearRootHubPortFeature (\r
2391 UsbBusDev,\r
2392 PortNum,\r
2393 EfiUsbPortReset\r
2394 );\r
878ddf1f 2395 if (EFI_ERROR (Status)) {\r
2396 return EFI_DEVICE_ERROR;\r
2397 }\r
2398\r
2399 gBS->Stall (1000);\r
2400\r
562d2849 2401 Status = UsbVirtualHcClearRootHubPortFeature (\r
2402 UsbBusDev,\r
2403 PortNum,\r
2404 EfiUsbPortConnectChange\r
2405 );\r
878ddf1f 2406 if (EFI_ERROR (Status)) {\r
2407 return EFI_DEVICE_ERROR;\r
2408 }\r
562d2849 2409\r
2410 UsbVirtualHcGetRootHubPortStatus (\r
2411 UsbBusDev,\r
2412 PortNum,\r
2413 &PortStatus\r
2414 );\r
2415 if (PortStatus.PortStatus & USB_PORT_STAT_OWNER) {\r
2416 //\r
2417 // Set port enable\r
2418 //\r
2419 Status = UsbVirtualHcSetRootHubPortFeature (\r
2420 UsbBusDev,\r
2421 PortNum,\r
2422 EfiUsbPortEnable\r
2423 );\r
2424 if (EFI_ERROR (Status)) {\r
2425 return EFI_DEVICE_ERROR;\r
2426 }\r
2427\r
2428 Status = UsbVirtualHcClearRootHubPortFeature (\r
2429 UsbBusDev,\r
2430 PortNum,\r
2431 EfiUsbPortEnableChange\r
2432 );\r
878ddf1f 2433 }\r
2434\r
878ddf1f 2435 gBS->Stall ((1 + RetryTimes) * 50 * 1000);\r
2436\r
2437 return EFI_SUCCESS;\r
2438}\r
2439\r
878ddf1f 2440EFI_STATUS\r
2441ResetHubPort (\r
2442 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
2443 IN UINT8 PortIndex\r
2444 )\r
2445/*++\r
2446\r
2447 Routine Description:\r
2448 Reset Hub port.\r
2449\r
2450 Arguments:\r
2451 UsbIoController - The USB_IO_CONTROLLER_DEVICE instance.\r
2452 PortIndex - The given port to be reset.\r
2453\r
2454 Returns:\r
2455 EFI_SUCCESS\r
2456 EFI_DEVICE_ERROR\r
2457\r
2458--*/\r
2459{\r
2460 EFI_USB_IO_PROTOCOL *UsbIo;\r
2461 EFI_USB_PORT_STATUS HubPortStatus;\r
2462 UINT8 Number;\r
2463\r
2464 ASSERT (UsbIoController->IsUsbHub == TRUE);\r
2465\r
2466 UsbIo = &UsbIoController->UsbIo;\r
2467\r
2468 HubSetPortFeature (\r
2469 UsbIo,\r
2470 PortIndex,\r
2471 EfiUsbPortReset\r
2472 );\r
2473\r
2474 gBS->Stall (10 * 1000);\r
2475\r
2476 //\r
2477 // Wait for port reset complete\r
2478 //\r
2479 Number = 10;\r
2480 do {\r
2481 HubGetPortStatus (\r
2482 UsbIo,\r
2483 PortIndex,\r
2484 (UINT32 *) &HubPortStatus\r
2485 );\r
2486 gBS->Stall (10 * 100);\r
2487 Number -= 1;\r
2488 } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Number > 0);\r
2489\r
2490 if (Number == 0) {\r
2491 //\r
2492 // Cannot reset port, return error\r
2493 //\r
2494 return EFI_DEVICE_ERROR;\r
2495 }\r
2496\r
2497 gBS->Stall (1000);\r
2498\r
2499 HubGetPortStatus (\r
2500 UsbIo,\r
2501 PortIndex,\r
2502 (UINT32 *) &HubPortStatus\r
2503 );\r
2504 //\r
2505 // reset port will cause some bits change, clear them\r
2506 //\r
2507 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {\r
2508 DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));\r
2509 HubClearPortFeature (\r
2510 UsbIo,\r
2511 PortIndex,\r
2512 EfiUsbPortEnableChange\r
2513 );\r
2514 }\r
2515\r
2516 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {\r
2517 DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));\r
2518 HubClearPortFeature (\r
2519 UsbIo,\r
2520 PortIndex,\r
2521 EfiUsbPortResetChange\r
2522 );\r
2523 }\r
2524\r
2525 return EFI_SUCCESS;\r
2526}\r
2527\r
878ddf1f 2528STATIC\r
2529EFI_STATUS\r
2530ReportUsbStatusCode (\r
2531 IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,\r
2532 IN EFI_STATUS_CODE_TYPE Type,\r
2533 IN EFI_STATUS_CODE_VALUE Code\r
2534 )\r
2535/*++\r
2536\r
2537Routine Description:\r
2538\r
2539 report a error Status code of USB bus driver controller\r
2540\r
2541 Arguments:\r
2542 UsbBusController - USB_BUS_CONTROLLER_DEVICE\r
2543 Type - EFI_STATUS_CODE_TYPE\r
2544 Code - EFI_STATUS_CODE_VALUE\r
2545 Returns:\r
2546\r
2547 None\r
2548\r
2549--*/\r
2550{\r
2551 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
2552 Type,\r
2553 Code,\r
2554 UsbBusController->DevicePath\r
2555 );\r
2556}\r
2557\r
878ddf1f 2558EFI_STATUS\r
2559IsDeviceDisconnected (\r
2560 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,\r
2561 IN OUT BOOLEAN *Disconnected\r
2562 )\r
2563/*++\r
2564\r
2565 Routine Description:\r
2566 Reset if the device is disconencted or not\r
2567\r
2568 Arguments:\r
2569 UsbIoController - Indicating the Usb Controller Device.\r
2570 Disconnected - Indicate whether the device is disconencted or not\r
2571\r
2572 Returns:\r
2573 EFI_SUCCESS\r
2574 EFI_DEVICE_ERROR\r
2575\r
2576--*/\r
2577{\r
2578 USB_IO_DEVICE *ParentIoDev;\r
2579 USB_IO_DEVICE *UsbIoDev;\r
2580 USB_IO_CONTROLLER_DEVICE *ParentController;\r
2581 UINT8 HubPort;\r
2582 EFI_STATUS Status;\r
2583 EFI_USB_IO_PROTOCOL *UsbIo;\r
2584 EFI_USB_PORT_STATUS PortStatus;\r
878ddf1f 2585\r
2586 ParentController = UsbIoController->Parent;\r
2587 ParentIoDev = ParentController->UsbDevice;\r
2588 UsbIoDev = UsbIoController->UsbDevice;\r
2589 HubPort = UsbIoController->ParentPort;\r
2590\r
2591 if (ParentIoDev->DeviceAddress == 1) {\r
2592 //\r
2593 // Connected to the root hub\r
2594 //\r
562d2849 2595 UsbVirtualHcGetRootHubPortStatus (\r
2596 ParentIoDev->BusController,\r
2597 HubPort,\r
2598 &PortStatus\r
2599 );\r
878ddf1f 2600\r
2601 } else {\r
2602 UsbIo = &UsbIoController->UsbIo;\r
2603 Status = HubGetPortStatus (\r
2604 &ParentController->UsbIo,\r
2605 HubPort + 1,\r
2606 (UINT32 *) &PortStatus\r
2607 );\r
2608\r
2609 if (EFI_ERROR (Status)) {\r
2610 return IsDeviceDisconnected (ParentController, Disconnected);\r
2611 }\r
2612 }\r
2613\r
2614 *Disconnected = FALSE;\r
2615\r
2616 if (!IsPortConnect (PortStatus.PortStatus)) {\r
2617 *Disconnected = TRUE;\r
2618 }\r
2619\r
2620 return EFI_SUCCESS;\r
2621}\r
562d2849 2622\r
2623STATIC\r
2624EFI_STATUS\r
2625UsbSetTransactionTranslator (\r
2626 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,\r
2627 IN UINT8 ParentPort,\r
2628 IN OUT USB_IO_DEVICE *Device\r
2629 )\r
2630/*++\r
2631 \r
2632 Routine Description:\r
2633 \r
2634 Set Transaction Translator parameter\r
2635 \r
2636 Arguments:\r
2637 \r
2638 ParentHubController - Controller structure of the parent Hub device\r
2639 ParentPort - Number of parent port\r
2640 Device - Structure of the device\r
2641 \r
2642 Returns:\r
2643 \r
2644 EFI_SUCCESS Success\r
2645 EFI_OUT_OF_RESOURCES Cannot allocate resources\r
2646 \r
2647--*/\r
2648{\r
2649 USB_IO_CONTROLLER_DEVICE *AncestorHubController;\r
2650\r
2651 AncestorHubController = ParentHubController;\r
2652 Device->Translator = NULL;\r
2653\r
2654 if (EFI_USB_SPEED_HIGH == Device->DeviceSpeed) {\r
2655 return EFI_SUCCESS;\r
2656 }\r
2657\r
2658 do {\r
2659 if (EFI_USB_SPEED_HIGH == AncestorHubController->UsbDevice->DeviceSpeed) {\r
2660 break;\r
2661 }\r
2662\r
2663 if (NULL == AncestorHubController->Parent) {\r
2664 return EFI_SUCCESS;\r
2665 }\r
2666\r
2667 AncestorHubController = AncestorHubController->Parent;\r
2668 } while (1);\r
2669\r
2670 Device->Translator = AllocatePool (sizeof (EFI_USB2_HC_TRANSACTION_TRANSLATOR));\r
2671 if (NULL == Device->Translator) {\r
2672 return EFI_OUT_OF_RESOURCES;\r
2673 }\r
2674\r
2675 Device->Translator->TranslatorHubAddress = AncestorHubController->UsbDevice->DeviceAddress;\r
2676 Device->Translator->TranslatorPortNumber = ParentPort;\r
2677\r
2678 return EFI_SUCCESS;\r
2679}\r
2680\r
2681STATIC\r
2682EFI_STATUS\r
2683UsbUnsetTransactionTranslator (\r
2684 USB_IO_DEVICE *Device\r
2685 )\r
2686/*++\r
2687 \r
2688 Routine Description:\r
2689 \r
2690 Unset Transaction Translator parameter\r
2691 \r
2692 Arguments:\r
2693 \r
2694 Device - Structure of the device\r
2695 \r
2696 Returns:\r
2697 \r
2698 EFI_SUCCESS Success\r
2699 \r
2700--*/\r
2701{\r
2702 if (Device->Translator) {\r
2703 gBS->FreePool (Device->Translator);\r
2704 Device->Translator = NULL;\r
2705 }\r
2706\r
2707 return EFI_SUCCESS;\r
2708}\r
2709\r
2710STATIC\r
2711EFI_STATUS\r
2712IdentifyDeviceSpeed (\r
2713 USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
2714 USB_IO_DEVICE *NewDevice,\r
2715 UINT8 Index\r
2716 )\r
2717/*++\r
2718 \r
2719 Routine Description:\r
2720 \r
2721 Identify speed of USB device\r
2722 \r
2723 Arguments:\r
2724 \r
2725 UsbBusDev - UsbBus controller structure of the device\r
2726 NewDevice - Devcie controller structure\r
2727 Index - Number of the port\r
2728 \r
2729 Returns:\r
2730 \r
2731 EFI_SUCCESS Success\r
2732 EFI_NOT_FOUND Device release to CHC or can't be found\r
2733 \r
2734--*/\r
2735{\r
2736 EFI_STATUS Status;\r
2737 EFI_USB_PORT_STATUS HubPortStatus;\r
2738\r
2739 UsbVirtualHcGetRootHubPortStatus (\r
2740 UsbBusDev,\r
2741 Index,\r
2742 (EFI_USB_PORT_STATUS *) &HubPortStatus\r
2743 );\r
2744 \r
2745 //\r
2746 // Check device device\r
2747 //\r
2748 if (!(HubPortStatus.PortStatus & USB_PORT_STAT_OWNER)) {\r
2749 //\r
2750 // EHC Port Owner\r
2751 //\r
2752 if (HubPortStatus.PortStatus & USB_PORT_STAT_HIGH_SPEED) {\r
2753 DEBUG ((gUSBDebugLevel, "High Speed Device attached to EHC\n"));\r
2754 NewDevice->DeviceSpeed = EFI_USB_SPEED_HIGH; \r
2755 } else {\r
2756 Status = ReleasePortToCHC (UsbBusDev, Index);\r
2757 if (EFI_ERROR (Status)) {\r
2758 DEBUG ((gUSBErrorLevel, "Fail to release port to CHC\n"));\r
2759 } else {\r
2760 DEBUG ((gUSBDebugLevel, "Success to release port to CHC\n"));\r
2761 }\r
2762 return EFI_DEVICE_ERROR;\r
2763 }\r
2764 } else {\r
2765 //\r
2766 // CHC Port Owner\r
2767 //\r
2768 if (HubPortStatus.PortStatus & USB_PORT_STAT_LOW_SPEED) {\r
2769 DEBUG ((gUSBDebugLevel, "Low Speed Device attached to CHC\n"));\r
2770 NewDevice->DeviceSpeed = EFI_USB_SPEED_LOW; \r
2771 } else {\r
2772 DEBUG ((gUSBDebugLevel, "FULL Speed Device attached to CHC\n"));\r
2773 NewDevice->DeviceSpeed = EFI_USB_SPEED_FULL; \r
2774 }\r
2775 }\r
2776 \r
2777 return EFI_SUCCESS;\r
2778}\r
2779\r
2780STATIC\r
2781EFI_STATUS\r
2782ReleasePortToCHC (\r
2783 USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
2784 UINT8 PortNum\r
2785 )\r
2786/*++\r
2787 \r
2788 Routine Description:\r
2789 \r
2790 Set bit to release the port owner to CHC\r
2791 \r
2792 Arguments:\r
2793 \r
2794 UsbBusDev - UsbBus controller structure of the device\r
2795 PortNum - Number of the port\r
2796 \r
2797 Returns:\r
2798 \r
2799 EFI_SUCCESS Success\r
2800 EFI_DEVICE_ERROR Fail\r
2801 \r
2802--*/\r
2803{\r
2804 EFI_STATUS Status;\r
2805\r
2806 Status = UsbVirtualHcSetRootHubPortFeature (\r
2807 UsbBusDev,\r
2808 PortNum,\r
2809 EfiUsbPortOwner\r
2810 );\r
2811\r
2812 gBS->Stall (100 * 1000);\r
2813\r
2814 return Status;\r
2815}\r
2816\r
2817EFI_STATUS\r
2818EFIAPI\r
2819UsbVirtualHcGetCapability (\r
2820 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
2821 OUT UINT8 *MaxSpeed,\r
2822 OUT UINT8 *PortNumber,\r
2823 OUT UINT8 *Is64BitCapable\r
2824 )\r
2825/*++\r
2826 \r
2827 Routine Description:\r
2828 \r
2829 Virtual interface to Retrieves the capablility of root hub ports \r
2830 for both Hc2 and Hc protocol.\r
2831 \r
2832 Arguments:\r
2833 \r
2834 UsbBusDev - A pointer to bus controller of the device.\r
2835 MaxSpeed - A pointer to the number of the host controller.\r
2836 PortNumber - A pointer to the number of the root hub ports.\r
2837 Is64BitCapable - A pointer to the flag for whether controller supports \r
2838 64-bit memory addressing.\r
2839 \r
2840 Returns:\r
2841 \r
2842 EFI_SUCCESS \r
2843 The host controller capability were retrieved successfully.\r
2844 EFI_INVALID_PARAMETER \r
2845 MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
2846 EFI_DEVICE_ERROR \r
2847 An error was encountered while attempting to retrieve the capabilities. \r
2848 \r
2849--*/\r
2850{\r
2851 EFI_STATUS Status;\r
2852\r
2853 Status = EFI_SUCCESS;\r
2854\r
2855 if (UsbBusDev->Hc2ProtocolSupported) {\r
2856 Status = UsbBusDev->Usb2HCInterface->GetCapability (\r
2857 UsbBusDev->Usb2HCInterface,\r
2858 MaxSpeed,\r
2859 PortNumber,\r
2860 Is64BitCapable\r
2861 );\r
2862 } else {\r
2863 Status = UsbBusDev->UsbHCInterface->GetRootHubPortNumber (\r
2864 UsbBusDev->UsbHCInterface,\r
2865 PortNumber\r
2866 );\r
2867 *MaxSpeed = EFI_USB_SPEED_FULL;\r
2868 *Is64BitCapable = (UINT8) FALSE;\r
2869 }\r
2870\r
2871 return Status;\r
2872}\r
2873\r
2874EFI_STATUS\r
2875EFIAPI\r
2876UsbVirtualHcReset (\r
2877 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
2878 IN UINT16 Attributes\r
2879 )\r
2880/*++\r
2881 \r
2882 Routine Description:\r
2883 \r
2884 Virtual interface to provides software reset for the USB host controller\r
2885 for both Hc2 and Hc protocol.\r
2886 \r
2887 Arguments:\r
2888 \r
2889 UsbBusDev - A pointer to bus controller of the device.\r
2890 Attributes - A bit mask of the reset operation to perform. \r
2891 See below for a list of the supported bit mask values.\r
2892 \r
2893 #define EFI_USB_HC_RESET_GLOBAL 0x0001 // Hc2 and Hc\r
2894 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 // Hc2 and Hc\r
2895 #define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 // Hc2\r
2896 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 // Hc2\r
2897\r
2898 EFI_USB_HC_RESET_GLOBAL \r
2899 If this bit is set, a global reset signal will be sent to the USB bus.\r
2900 This resets all of the USB bus logic, including the USB host \r
2901 controller hardware and all the devices attached on the USB bus.\r
2902 EFI_USB_HC_RESET_HOST_CONTROLLER \r
2903 If this bit is set, the USB host controller hardware will be reset. \r
2904 No reset signal will be sent to the USB bus.\r
2905 EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG\r
2906 If this bit is set, a global reset signal will be sent to the USB bus.\r
2907 This resets all of the USB bus logic, including the USB host \r
2908 controller hardware and all the devices attached on the USB bus. \r
2909 If this is an EHCI controller and the debug port has configured, then \r
2910 this is will still reset the host controller.\r
2911 EFI_USB_HC_RESET_HOST_WITH_DEBUG\r
2912 If this bit is set, the USB host controller hardware will be reset. \r
2913 If this is an EHCI controller and the debug port has been configured,\r
2914 then this will still reset the host controller.\r
2915 \r
2916 Returns:\r
2917 \r
2918 EFI_SUCCESS \r
2919 The reset operation succeeded.\r
2920 EFI_INVALID_PARAMETER \r
2921 Attributes is not valid.\r
2922 EFI_UNSUPPOURTED\r
2923 The type of reset specified by Attributes is not currently supported by\r
2924 the host controller hardware.\r
2925 EFI_ACCESS_DENIED\r
2926 Reset operation is rejected due to the debug port being configured and \r
2927 active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or \r
2928 EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Atrributes can be used to\r
2929 perform reset operation for this host controller.\r
2930 EFI_DEVICE_ERROR \r
2931 An error was encountered while attempting to perform \r
2932 the reset operation.\r
2933 \r
2934--*/\r
2935{\r
2936 EFI_STATUS Status;\r
2937\r
2938 Status = EFI_SUCCESS;\r
2939\r
2940 if (UsbBusDev->Hc2ProtocolSupported) {\r
2941 Status = UsbBusDev->Usb2HCInterface->Reset (\r
2942 UsbBusDev->Usb2HCInterface,\r
2943 EFI_USB_HC_RESET_GLOBAL\r
2944 );\r
2945 } else {\r
2946 Status = UsbBusDev->UsbHCInterface->Reset (\r
2947 UsbBusDev->UsbHCInterface,\r
2948 EFI_USB_HC_RESET_GLOBAL\r
2949 );\r
2950 }\r
2951\r
2952 return Status;\r
2953}\r
2954\r
2955EFI_STATUS\r
2956EFIAPI\r
2957UsbVirtualHcGetState (\r
2958 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
2959 OUT EFI_USB_HC_STATE *State\r
2960 )\r
2961/*++\r
2962 \r
2963 Routine Description:\r
2964 \r
2965 Virtual interface to retrieves current state of the USB host controller\r
2966 for both Hc2 and Hc protocol.\r
2967 \r
2968 Arguments:\r
2969 \r
2970 UsbBusDev - A pointer to bus controller of the device.\r
2971 State - A pointer to the EFI_USB_HC_STATE data structure that \r
2972 indicates current state of the USB host controller. \r
2973 Type EFI_USB_HC_STATE is defined below.\r
2974 \r
2975 typedef enum {\r
2976 EfiUsbHcStateHalt,\r
2977 EfiUsbHcStateOperational,\r
2978 EfiUsbHcStateSuspend,\r
2979 EfiUsbHcStateMaximum\r
2980 } EFI_USB_HC_STATE;\r
2981 \r
2982 Returns:\r
2983 \r
2984 EFI_SUCCESS \r
2985 The state information of the host controller was returned in State.\r
2986 EFI_INVALID_PARAMETER \r
2987 State is NULL.\r
2988 EFI_DEVICE_ERROR \r
2989 An error was encountered while attempting to retrieve the \r
2990 host controller's current state. \r
2991 \r
2992--*/\r
2993{\r
2994 EFI_STATUS Status;\r
2995\r
2996 Status = EFI_SUCCESS;\r
2997\r
2998 if (UsbBusDev->Hc2ProtocolSupported) {\r
2999 Status = UsbBusDev->Usb2HCInterface->GetState (\r
3000 UsbBusDev->Usb2HCInterface,\r
3001 State\r
3002 );\r
3003 } else {\r
3004 Status = UsbBusDev->UsbHCInterface->GetState (\r
3005 UsbBusDev->UsbHCInterface,\r
3006 State\r
3007 );\r
3008 }\r
3009\r
3010 return Status;\r
3011}\r
3012\r
3013EFI_STATUS\r
3014EFIAPI\r
3015UsbVirtualHcSetState (\r
3016 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3017 IN EFI_USB_HC_STATE State\r
3018 )\r
3019/*++\r
3020 \r
3021 Routine Description:\r
3022 \r
3023 Virtual interface to sets the USB host controller to a specific state\r
3024 for both Hc2 and Hc protocol.\r
3025 \r
3026 Arguments:\r
3027 \r
3028 UsbBusDev - A pointer to bus controller of the device.\r
3029 State - Indicates the state of the host controller that will be set.\r
3030 \r
3031 Returns:\r
3032 \r
3033 EFI_SUCCESS \r
3034 The USB host controller was successfully placed in the state \r
3035 specified by State.\r
3036 EFI_INVALID_PARAMETER \r
3037 State is invalid.\r
3038 EFI_DEVICE_ERROR \r
3039 Failed to set the state specified by State due to device error. \r
3040 \r
3041--*/\r
3042{\r
3043 EFI_STATUS Status;\r
3044\r
3045 Status = EFI_SUCCESS;\r
3046\r
3047 if (UsbBusDev->Hc2ProtocolSupported) {\r
3048 Status = UsbBusDev->Usb2HCInterface->SetState (\r
3049 UsbBusDev->Usb2HCInterface,\r
3050 State\r
3051 );\r
3052 } else {\r
3053 Status = UsbBusDev->UsbHCInterface->SetState (\r
3054 UsbBusDev->UsbHCInterface,\r
3055 State\r
3056 );\r
3057 }\r
3058\r
3059 return Status;\r
3060}\r
3061\r
3062EFI_STATUS\r
3063EFIAPI\r
3064UsbVirtualHcGetRootHubPortStatus (\r
3065 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3066 IN UINT8 PortNumber,\r
3067 OUT EFI_USB_PORT_STATUS *PortStatus\r
3068 )\r
3069/*++\r
3070 \r
3071 Routine Description:\r
3072 \r
3073 Virtual interface to retrieves the current status of a USB root hub port\r
3074 both for Hc2 and Hc protocol.\r
3075 \r
3076 Arguments:\r
3077 \r
3078 UsbBusDev - A pointer to bus controller of the device.\r
3079 PortNumber - Specifies the root hub port from which the status \r
3080 is to be retrieved. This value is zero-based. For example, \r
3081 if a root hub has two ports, then the first port is numbered 0,\r
3082 and the second port is numbered 1.\r
3083 PortStatus - A pointer to the current port status bits and \r
3084 port status change bits. \r
3085 \r
3086 Returns:\r
3087 \r
3088 EFI_SUCCESS The status of the USB root hub port specified by PortNumber \r
3089 was returned in PortStatus.\r
3090 EFI_INVALID_PARAMETER PortNumber is invalid. \r
3091 EFI_DEVICE_ERROR Can't read register \r
3092 \r
3093--*/\r
3094{\r
3095 EFI_STATUS Status;\r
3096\r
3097 Status = EFI_SUCCESS;\r
3098\r
3099 if (UsbBusDev->Hc2ProtocolSupported) {\r
3100 Status = UsbBusDev->Usb2HCInterface->GetRootHubPortStatus (\r
3101 UsbBusDev->Usb2HCInterface,\r
3102 PortNumber,\r
3103 PortStatus\r
3104 );\r
3105 } else {\r
3106 Status = UsbBusDev->UsbHCInterface->GetRootHubPortStatus (\r
3107 UsbBusDev->UsbHCInterface,\r
3108 PortNumber,\r
3109 PortStatus\r
3110 );\r
3111 }\r
3112\r
3113 return Status;\r
3114}\r
3115\r
3116EFI_STATUS\r
3117EFIAPI\r
3118UsbVirtualHcSetRootHubPortFeature (\r
3119 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3120 IN UINT8 PortNumber,\r
3121 IN EFI_USB_PORT_FEATURE PortFeature\r
3122 )\r
3123/*++\r
3124 \r
3125 Routine Description:\r
3126 Virual interface to sets a feature for the specified root hub port\r
3127 for both Hc2 and Hc protocol.\r
3128 \r
3129 Arguments:\r
3130 \r
3131 UsbBusDev - A pointer to bus controller of the device.\r
3132 PortNumber - Specifies the root hub port whose feature \r
3133 is requested to be set.\r
3134 PortFeature - Indicates the feature selector associated \r
3135 with the feature set request. \r
3136 \r
3137 Returns:\r
3138 \r
3139 EFI_SUCCESS \r
3140 The feature specified by PortFeature was set for the \r
3141 USB root hub port specified by PortNumber.\r
3142 EFI_INVALID_PARAMETER \r
3143 PortNumber is invalid or PortFeature is invalid.\r
3144 EFI_DEVICE_ERROR\r
3145 Can't read register\r
3146 \r
3147--*/\r
3148{\r
3149 EFI_STATUS Status;\r
3150\r
3151 Status = EFI_SUCCESS;\r
3152\r
3153 if (UsbBusDev->Hc2ProtocolSupported) {\r
3154 Status = UsbBusDev->Usb2HCInterface->SetRootHubPortFeature (\r
3155 UsbBusDev->Usb2HCInterface,\r
3156 PortNumber,\r
3157 PortFeature\r
3158 );\r
3159 } else {\r
3160 Status = UsbBusDev->UsbHCInterface->SetRootHubPortFeature (\r
3161 UsbBusDev->UsbHCInterface,\r
3162 PortNumber,\r
3163 PortFeature\r
3164 );\r
3165 }\r
3166\r
3167 return Status;\r
3168}\r
3169\r
3170EFI_STATUS\r
3171EFIAPI\r
3172UsbVirtualHcClearRootHubPortFeature (\r
3173 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3174 IN UINT8 PortNumber,\r
3175 IN EFI_USB_PORT_FEATURE PortFeature\r
3176 )\r
3177/*++\r
3178 \r
3179 Routine Description:\r
3180 \r
3181 Virtual interface to clears a feature for the specified root hub port\r
3182 for both Hc2 and Hc protocol.\r
3183 \r
3184 Arguments:\r
3185 \r
3186 UsbBusDev - A pointer to bus controller of the device.\r
3187 PortNumber - Specifies the root hub port whose feature \r
3188 is requested to be cleared.\r
3189 PortFeature - Indicates the feature selector associated with the \r
3190 feature clear request.\r
3191 \r
3192 Returns:\r
3193 \r
3194 EFI_SUCCESS \r
3195 The feature specified by PortFeature was cleared for the \r
3196 USB root hub port specified by PortNumber.\r
3197 EFI_INVALID_PARAMETER \r
3198 PortNumber is invalid or PortFeature is invalid.\r
3199 EFI_DEVICE_ERROR\r
3200 Can't read register\r
3201 \r
3202--*/\r
3203{\r
3204 EFI_STATUS Status;\r
3205\r
3206 Status = EFI_SUCCESS;\r
3207\r
3208 if (UsbBusDev->Hc2ProtocolSupported) {\r
3209 Status = UsbBusDev->Usb2HCInterface->ClearRootHubPortFeature (\r
3210 UsbBusDev->Usb2HCInterface,\r
3211 PortNumber,\r
3212 PortFeature\r
3213 );\r
3214 } else {\r
3215 Status = UsbBusDev->UsbHCInterface->ClearRootHubPortFeature (\r
3216 UsbBusDev->UsbHCInterface,\r
3217 PortNumber,\r
3218 PortFeature\r
3219 );\r
3220 }\r
3221\r
3222 return Status;\r
3223}\r
3224\r
3225EFI_STATUS\r
3226EFIAPI\r
3227UsbVirtualHcControlTransfer (\r
3228 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3229 IN UINT8 DeviceAddress,\r
3230 IN UINT8 DeviceSpeed,\r
3231 IN UINTN MaximumPacketLength,\r
3232 IN EFI_USB_DEVICE_REQUEST *Request,\r
3233 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
3234 IN OUT VOID *Data,\r
3235 IN OUT UINTN *DataLength,\r
3236 IN UINTN TimeOut,\r
3237 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3238 OUT UINT32 *TransferResult\r
3239 )\r
3240/*++\r
3241 \r
3242 Routine Description:\r
3243 \r
3244 Virtual interface to submits control transfer to a target USB device\r
3245 for both Hc2 and Hc protocol.\r
3246 \r
3247 Arguments:\r
3248 \r
3249 UsbBusDev - A pointer to bus controller of the device.\r
3250 DeviceAddress - Represents the address of the target device on the USB,\r
3251 which is assigned during USB enumeration.\r
3252 DeviceSpeed - Indicates target device speed.\r
3253 MaximumPacketLength - Indicates the maximum packet size that the \r
3254 default control transfer endpoint is capable of \r
3255 sending or receiving.\r
3256 Request - A pointer to the USB device request that will be sent \r
3257 to the USB device. \r
3258 TransferDirection - Specifies the data direction for the transfer.\r
3259 There are three values available, DataIn, DataOut \r
3260 and NoData.\r
3261 Data - A pointer to the buffer of data that will be transmitted \r
3262 to USB device or received from USB device.\r
3263 DataLength - Indicates the size, in bytes, of the data buffer \r
3264 specified by Data.\r
3265 TimeOut - Indicates the maximum time, in microseconds, \r
3266 which the transfer is allowed to complete.\r
3267 Translator - A pointr to the transaction translator data.\r
3268 TransferResult - A pointer to the detailed result information generated \r
3269 by this control transfer.\r
3270 \r
3271 Returns:\r
3272 \r
3273 EFI_SUCCESS \r
3274 The control transfer was completed successfully.\r
3275 EFI_OUT_OF_RESOURCES \r
3276 The control transfer could not be completed due to a lack of resources.\r
3277 EFI_INVALID_PARAMETER \r
3278 Some parameters are invalid.\r
3279 EFI_TIMEOUT \r
3280 The control transfer failed due to timeout.\r
3281 EFI_DEVICE_ERROR \r
3282 The control transfer failed due to host controller or device error. \r
3283 Caller should check TranferResult for detailed error information.\r
3284\r
3285--*/\r
3286{\r
3287 EFI_STATUS Status;\r
3288 BOOLEAN IsSlowDevice;\r
3289\r
3290 Status = EFI_SUCCESS;\r
3291\r
3292 if (UsbBusDev->Hc2ProtocolSupported) {\r
3293 Status = UsbBusDev->Usb2HCInterface->ControlTransfer (\r
3294 UsbBusDev->Usb2HCInterface,\r
3295 DeviceAddress,\r
3296 DeviceSpeed,\r
3297 MaximumPacketLength,\r
3298 Request,\r
3299 TransferDirection,\r
3300 Data,\r
3301 DataLength,\r
3302 TimeOut,\r
3303 Translator,\r
3304 TransferResult\r
3305 );\r
3306 } else {\r
3307 IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;\r
3308 Status = UsbBusDev->UsbHCInterface->ControlTransfer (\r
3309 UsbBusDev->UsbHCInterface,\r
3310 DeviceAddress,\r
3311 IsSlowDevice,\r
3312 (UINT8) MaximumPacketLength,\r
3313 Request,\r
3314 TransferDirection,\r
3315 Data,\r
3316 DataLength,\r
3317 TimeOut,\r
3318 TransferResult\r
3319 );\r
3320 }\r
3321\r
3322 return Status;\r
3323}\r
3324\r
3325EFI_STATUS\r
3326EFIAPI\r
3327UsbVirtualHcBulkTransfer (\r
3328 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3329 IN UINT8 DeviceAddress,\r
3330 IN UINT8 EndPointAddress,\r
3331 IN UINT8 DeviceSpeed,\r
3332 IN UINTN MaximumPacketLength,\r
3333 IN UINT8 DataBuffersNumber,\r
3334 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
3335 IN OUT UINTN *DataLength,\r
3336 IN OUT UINT8 *DataToggle,\r
3337 IN UINTN TimeOut,\r
3338 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3339 OUT UINT32 *TransferResult\r
3340 )\r
3341/*++\r
3342 \r
3343 Routine Description:\r
3344 \r
3345 Virtual interface to submits bulk transfer to a bulk endpoint of a USB device\r
3346 both for Hc2 and Hc protocol.\r
3347 \r
3348 Arguments:\r
3349 \r
3350 UsbBusDev - A pointer to bus controller of the device.\r
3351 DeviceAddress - Represents the address of the target device on the USB,\r
3352 which is assigned during USB enumeration. \r
3353 EndPointAddress - The combination of an endpoint number and an \r
3354 endpoint direction of the target USB device. \r
3355 Each endpoint address supports data transfer in \r
3356 one direction except the control endpoint \r
3357 (whose default endpoint address is 0). \r
3358 It is the caller's responsibility to make sure that \r
3359 the EndPointAddress represents a bulk endpoint. \r
3360 DeviceSpeed - Indicates device speed. The supported values are EFI_USB_SPEED_FULL\r
3361 and EFI_USB_SPEED_HIGH.\r
3362 MaximumPacketLength - Indicates the maximum packet size the target endpoint\r
3363 is capable of sending or receiving. \r
3364 DataBuffersNumber - Number of data buffers prepared for the transfer.\r
3365 Data - Array of pointers to the buffers of data that will be transmitted \r
3366 to USB device or received from USB device. \r
3367 DataLength - When input, indicates the size, in bytes, of the data buffer\r
3368 specified by Data. When output, indicates the actually \r
3369 transferred data size. \r
3370 DataToggle - A pointer to the data toggle value. On input, it indicates \r
3371 the initial data toggle value the bulk transfer should adopt;\r
3372 on output, it is updated to indicate the data toggle value \r
3373 of the subsequent bulk transfer. \r
3374 Translator - A pointr to the transaction translator data. \r
3375 TimeOut - Indicates the maximum time, in microseconds, which the \r
3376 transfer is allowed to complete. \r
3377 TransferResult - A pointer to the detailed result information of the \r
3378 bulk transfer.\r
3379\r
3380 Returns:\r
3381 \r
3382 EFI_SUCCESS \r
3383 The bulk transfer was completed successfully.\r
3384 EFI_OUT_OF_RESOURCES \r
3385 The bulk transfer could not be submitted due to lack of resource.\r
3386 EFI_INVALID_PARAMETER \r
3387 Some parameters are invalid.\r
3388 EFI_TIMEOUT \r
3389 The bulk transfer failed due to timeout.\r
3390 EFI_DEVICE_ERROR \r
3391 The bulk transfer failed due to host controller or device error.\r
3392 Caller should check TranferResult for detailed error information.\r
3393\r
3394--*/\r
3395{\r
3396 EFI_STATUS Status;\r
3397\r
3398 Status = EFI_SUCCESS;\r
3399\r
3400 if (UsbBusDev->Hc2ProtocolSupported) {\r
3401 Status = UsbBusDev->Usb2HCInterface->BulkTransfer (\r
3402 UsbBusDev->Usb2HCInterface,\r
3403 DeviceAddress,\r
3404 EndPointAddress,\r
3405 DeviceSpeed,\r
3406 MaximumPacketLength,\r
3407 DataBuffersNumber,\r
3408 Data,\r
3409 DataLength,\r
3410 DataToggle,\r
3411 TimeOut,\r
3412 Translator,\r
3413 TransferResult\r
3414 );\r
3415 } else {\r
3416 Status = UsbBusDev->UsbHCInterface->BulkTransfer (\r
3417 UsbBusDev->UsbHCInterface,\r
3418 DeviceAddress,\r
3419 EndPointAddress,\r
3420 (UINT8) MaximumPacketLength,\r
3421 *Data,\r
3422 DataLength,\r
3423 DataToggle,\r
3424 TimeOut,\r
3425 TransferResult\r
3426 );\r
3427 }\r
3428\r
3429 return Status;\r
3430}\r
3431\r
3432EFI_STATUS\r
3433EFIAPI\r
3434UsbVirtualHcAsyncInterruptTransfer (\r
3435 IN USB_BUS_CONTROLLER_DEVICE * UsbBusDev,\r
3436 IN UINT8 DeviceAddress,\r
3437 IN UINT8 EndPointAddress,\r
3438 IN UINT8 DeviceSpeed,\r
3439 IN UINTN MaximumPacketLength,\r
3440 IN BOOLEAN IsNewTransfer,\r
3441 IN OUT UINT8 *DataToggle,\r
3442 IN UINTN PollingInterval,\r
3443 IN UINTN DataLength,\r
3444 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR * Translator,\r
3445 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
3446 IN VOID *Context OPTIONAL\r
3447 )\r
3448/*++\r
3449 \r
3450 Routine Description:\r
3451 \r
3452 Virtual interface to submits an asynchronous interrupt transfer to an \r
3453 interrupt endpoint of a USB device for both Hc2 and Hc protocol.\r
3454 \r
3455 Arguments:\r
3456 \r
3457 UsbBusDev - A pointer to bus controller of the device.\r
3458 DeviceAddress - Represents the address of the target device on the USB,\r
3459 which is assigned during USB enumeration. \r
3460 EndPointAddress - The combination of an endpoint number and an endpoint \r
3461 direction of the target USB device. Each endpoint address \r
3462 supports data transfer in one direction except the \r
3463 control endpoint (whose default endpoint address is 0). \r
3464 It is the caller's responsibility to make sure that \r
3465 the EndPointAddress represents an interrupt endpoint. \r
3466 DeviceSpeed - Indicates device speed.\r
3467 MaximumPacketLength - Indicates the maximum packet size the target endpoint\r
3468 is capable of sending or receiving. \r
3469 IsNewTransfer - If TRUE, an asynchronous interrupt pipe is built between\r
3470 the host and the target interrupt endpoint. \r
3471 If FALSE, the specified asynchronous interrupt pipe \r
3472 is canceled. \r
3473 DataToggle - A pointer to the data toggle value. On input, it is valid \r
3474 when IsNewTransfer is TRUE, and it indicates the initial \r
3475 data toggle value the asynchronous interrupt transfer \r
3476 should adopt. \r
3477 On output, it is valid when IsNewTransfer is FALSE, \r
3478 and it is updated to indicate the data toggle value of \r
3479 the subsequent asynchronous interrupt transfer. \r
3480 PollingInterval - Indicates the interval, in milliseconds, that the \r
3481 asynchronous interrupt transfer is polled. \r
3482 This parameter is required when IsNewTransfer is TRUE. \r
3483 DataLength - Indicates the length of data to be received at the \r
3484 rate specified by PollingInterval from the target \r
3485 asynchronous interrupt endpoint. This parameter \r
3486 is only required when IsNewTransfer is TRUE. \r
3487 Translator - A pointr to the transaction translator data.\r
3488 CallBackFunction - The Callback function.This function is called at the \r
3489 rate specified by PollingInterval.This parameter is \r
3490 only required when IsNewTransfer is TRUE. \r
3491 Context - The context that is passed to the CallBackFunction.\r
3492 - This is an optional parameter and may be NULL.\r
3493 \r
3494 Returns:\r
3495 \r
3496 EFI_SUCCESS \r
3497 The asynchronous interrupt transfer request has been successfully \r
3498 submitted or canceled.\r
3499 EFI_INVALID_PARAMETER \r
3500 Some parameters are invalid.\r
3501 EFI_OUT_OF_RESOURCES \r
3502 The request could not be completed due to a lack of resources. \r
3503 EFI_DEVICE_ERROR\r
3504 Can't read register\r
3505 \r
3506--*/\r
3507{\r
3508 EFI_STATUS Status;\r
3509 BOOLEAN IsSlowDevice;\r
3510\r
3511 Status = EFI_SUCCESS;\r
3512\r
3513 if (UsbBusDev->Hc2ProtocolSupported) {\r
3514 Status = UsbBusDev->Usb2HCInterface->AsyncInterruptTransfer (\r
3515 UsbBusDev->Usb2HCInterface,\r
3516 DeviceAddress,\r
3517 EndPointAddress,\r
3518 DeviceSpeed,\r
3519 MaximumPacketLength,\r
3520 IsNewTransfer,\r
3521 DataToggle,\r
3522 PollingInterval,\r
3523 DataLength,\r
3524 Translator,\r
3525 CallBackFunction,\r
3526 Context\r
3527 );\r
3528 } else {\r
3529 IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;\r
3530 Status = UsbBusDev->UsbHCInterface->AsyncInterruptTransfer (\r
3531 UsbBusDev->UsbHCInterface,\r
3532 DeviceAddress,\r
3533 EndPointAddress,\r
3534 IsSlowDevice,\r
3535 (UINT8) MaximumPacketLength,\r
3536 IsNewTransfer,\r
3537 DataToggle,\r
3538 PollingInterval,\r
3539 DataLength,\r
3540 CallBackFunction,\r
3541 Context\r
3542 );\r
3543 }\r
3544\r
3545 return Status;\r
3546}\r
3547\r
3548EFI_STATUS\r
3549EFIAPI\r
3550UsbVirtualHcSyncInterruptTransfer (\r
3551 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3552 IN UINT8 DeviceAddress,\r
3553 IN UINT8 EndPointAddress,\r
3554 IN UINT8 DeviceSpeed,\r
3555 IN UINTN MaximumPacketLength,\r
3556 IN OUT VOID *Data,\r
3557 IN OUT UINTN *DataLength,\r
3558 IN OUT UINT8 *DataToggle,\r
3559 IN UINTN TimeOut,\r
3560 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3561 OUT UINT32 *TransferResult\r
3562 )\r
3563/*++\r
3564 \r
3565 Routine Description:\r
3566 \r
3567 Vitual interface to submits synchronous interrupt transfer to an interrupt endpoint \r
3568 of a USB device for both Hc2 and Hc protocol.\r
3569 \r
3570 Arguments:\r
3571 \r
3572 UsbBusDev - A pointer to bus controller of the device.\r
3573 DeviceAddress - Represents the address of the target device on the USB, \r
3574 which is assigned during USB enumeration.\r
3575 EndPointAddress - The combination of an endpoint number and an endpoint \r
3576 direction of the target USB device. Each endpoint \r
3577 address supports data transfer in one direction \r
3578 except the control endpoint (whose default \r
3579 endpoint address is 0). It is the caller's responsibility\r
3580 to make sure that the EndPointAddress represents \r
3581 an interrupt endpoint. \r
3582 DeviceSpeed - Indicates device speed.\r
3583 MaximumPacketLength - Indicates the maximum packet size the target endpoint \r
3584 is capable of sending or receiving.\r
3585 Data - A pointer to the buffer of data that will be transmitted \r
3586 to USB device or received from USB device.\r
3587 DataLength - On input, the size, in bytes, of the data buffer specified \r
3588 by Data. On output, the number of bytes transferred.\r
3589 DataToggle - A pointer to the data toggle value. On input, it indicates\r
3590 the initial data toggle value the synchronous interrupt \r
3591 transfer should adopt; \r
3592 on output, it is updated to indicate the data toggle value \r
3593 of the subsequent synchronous interrupt transfer. \r
3594 TimeOut - Indicates the maximum time, in microseconds, which the \r
3595 transfer is allowed to complete.\r
3596 Translator - A pointr to the transaction translator data.\r
3597 TransferResult - A pointer to the detailed result information from \r
3598 the synchronous interrupt transfer. \r
3599\r
3600 Returns:\r
3601 \r
3602 EFI_SUCCESS \r
3603 The synchronous interrupt transfer was completed successfully.\r
3604 EFI_OUT_OF_RESOURCES \r
3605 The synchronous interrupt transfer could not be submitted due \r
3606 to lack of resource.\r
3607 EFI_INVALID_PARAMETER \r
3608 Some parameters are invalid.\r
3609 EFI_TIMEOUT \r
3610 The synchronous interrupt transfer failed due to timeout.\r
3611 EFI_DEVICE_ERROR \r
3612 The synchronous interrupt transfer failed due to host controller \r
3613 or device error. Caller should check TranferResult for detailed \r
3614 error information. \r
3615 \r
3616--*/\r
3617{\r
3618 EFI_STATUS Status;\r
3619 BOOLEAN IsSlowDevice;\r
3620\r
3621 Status = EFI_SUCCESS;\r
3622\r
3623 if (UsbBusDev->Hc2ProtocolSupported) {\r
3624 Status = UsbBusDev->Usb2HCInterface->SyncInterruptTransfer (\r
3625 UsbBusDev->Usb2HCInterface,\r
3626 DeviceAddress,\r
3627 EndPointAddress,\r
3628 DeviceSpeed,\r
3629 MaximumPacketLength,\r
3630 Data,\r
3631 DataLength,\r
3632 DataToggle,\r
3633 TimeOut,\r
3634 Translator,\r
3635 TransferResult\r
3636 );\r
3637 } else {\r
3638 IsSlowDevice = (EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE;\r
3639 Status = UsbBusDev->UsbHCInterface->SyncInterruptTransfer (\r
3640 UsbBusDev->UsbHCInterface,\r
3641 DeviceAddress,\r
3642 EndPointAddress,\r
3643 IsSlowDevice,\r
3644 (UINT8) MaximumPacketLength,\r
3645 Data,\r
3646 DataLength,\r
3647 DataToggle,\r
3648 TimeOut,\r
3649 TransferResult\r
3650 );\r
3651 }\r
3652\r
3653 return Status;\r
3654}\r
3655\r
3656EFI_STATUS\r
3657EFIAPI\r
3658UsbVirtualHcIsochronousTransfer (\r
3659 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3660 IN UINT8 DeviceAddress,\r
3661 IN UINT8 EndPointAddress,\r
3662 IN UINT8 DeviceSpeed,\r
3663 IN UINTN MaximumPacketLength,\r
3664 IN UINT8 DataBuffersNumber,\r
3665 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
3666 IN UINTN DataLength,\r
3667 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3668 OUT UINT32 *TransferResult\r
3669 )\r
3670/*++\r
3671 \r
3672 Routine Description:\r
3673 \r
3674 Virtual interface to submits isochronous transfer to a target USB device\r
3675 for both Hc2 and Hc protocol.\r
3676 \r
3677 Arguments:\r
3678 \r
3679 UsbBusDev - A pointer to bus controller of the device.\r
3680 DeviceAddress - Represents the address of the target device on the USB,\r
3681 which is assigned during USB enumeration.\r
3682 EndPointAddress - End point address\r
3683 DeviceSpeed - Indicates device speed.\r
3684 MaximumPacketLength - Indicates the maximum packet size that the \r
3685 default control transfer endpoint is capable of \r
3686 sending or receiving.\r
3687 DataBuffersNumber - Number of data buffers prepared for the transfer.\r
3688 Data - Array of pointers to the buffers of data that will be \r
3689 transmitted to USB device or received from USB device.\r
3690 DataLength - Indicates the size, in bytes, of the data buffer \r
3691 specified by Data.\r
3692 Translator - A pointr to the transaction translator data.\r
3693 TransferResult - A pointer to the detailed result information generated \r
3694 by this control transfer. \r
3695 \r
3696 Returns:\r
3697 \r
3698 EFI_UNSUPPORTED \r
3699\r
3700--*/\r
3701{\r
3702 return EFI_UNSUPPORTED;\r
3703}\r
3704\r
3705EFI_STATUS\r
3706EFIAPI\r
3707UsbVirtualHcAsyncIsochronousTransfer (\r
3708 IN USB_BUS_CONTROLLER_DEVICE *UsbBusDev,\r
3709 IN UINT8 DeviceAddress,\r
3710 IN UINT8 EndPointAddress,\r
3711 IN UINT8 DeviceSpeed,\r
3712 IN UINTN MaximumPacketLength,\r
3713 IN UINT8 DataBuffersNumber,\r
3714 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
3715 IN UINTN DataLength,\r
3716 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
3717 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
3718 IN VOID *Context\r
3719 )\r
3720/*++\r
3721 \r
3722 Routine Description:\r
3723 \r
3724 Vitual interface to submits Async isochronous transfer to a target USB device\r
3725 for both Hc2 and Hc protocol.\r
3726 \r
3727 Arguments:\r
3728 \r
3729 UsbBusDev - A pointer to bus controller of the device.\r
3730 DeviceAddress - Represents the address of the target device on the USB,\r
3731 which is assigned during USB enumeration.\r
3732 EndPointAddress - End point address\r
3733 DeviceSpeed - Indicates device speed.\r
3734 MaximumPacketLength - Indicates the maximum packet size that the \r
3735 default control transfer endpoint is capable of \r
3736 sending or receiving.\r
3737 DataBuffersNumber - Number of data buffers prepared for the transfer.\r
3738 Data - Array of pointers to the buffers of data that will be transmitted \r
3739 to USB device or received from USB device.\r
3740 DataLength - Indicates the size, in bytes, of the data buffer \r
3741 specified by Data.\r
3742 Translator - A pointr to the transaction translator data.\r
3743 IsochronousCallBack - When the transfer complete, the call back function will be called\r
3744 Context - Pass to the call back function as parameter\r
3745 \r
3746 Returns:\r
3747 \r
3748 EFI_UNSUPPORTED \r
3749\r
3750--*/\r
3751{\r
3752 return EFI_UNSUPPORTED;\r
3753}\r