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