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