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