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