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