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