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