]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
1. UINTN & INTN issue for EBC architecture:
[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 //#ifdef EFI_DEBUG
27 UINTN gUSBDebugLevel = EFI_D_ERROR;
28 UINTN gUSBErrorLevel = EFI_D_ERROR;
29 //#endif
30 //
31 // The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER
32 // structure in the UsbBusDriverControllerDriverStop(). Then we can
33 // Close all opened protocols and release this structure.
34 //
35 STATIC EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;
36
37
38
39 //
40 // EFI_DRIVER_BINDING_PROTOCOL Protocol Interface
41 //
42 EFI_STATUS
43 EFIAPI
44 UsbBusControllerDriverSupported (
45 IN EFI_DRIVER_BINDING_PROTOCOL *This,
46 IN EFI_HANDLE Controller,
47 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
48 );
49
50 EFI_STATUS
51 EFIAPI
52 UsbBusControllerDriverStart (
53 IN EFI_DRIVER_BINDING_PROTOCOL *This,
54 IN EFI_HANDLE Controller,
55 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
56 );
57
58 EFI_STATUS
59 EFIAPI
60 UsbBusControllerDriverStop (
61 IN EFI_DRIVER_BINDING_PROTOCOL *This,
62 IN EFI_HANDLE Controller,
63 IN UINTN NumberOfChildren,
64 IN EFI_HANDLE *ChildHandleBuffer
65 );
66
67 EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding = {
68 UsbBusControllerDriverSupported,
69 UsbBusControllerDriverStart,
70 UsbBusControllerDriverStop,
71 0x10,
72 NULL,
73 NULL
74 };
75
76 //
77 // Internal use only
78 //
79 STATIC
80 EFI_STATUS
81 ReportUsbStatusCode (
82 IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,
83 IN EFI_STATUS_CODE_TYPE Type,
84 IN EFI_STATUS_CODE_VALUE Code
85 );
86
87 //
88 // Supported function
89 //
90 VOID
91 InitializeUsbIoInstance (
92 IN USB_IO_CONTROLLER_DEVICE *UsbIoController
93 );
94
95 STATIC
96 USB_IO_CONTROLLER_DEVICE *
97 CreateUsbIoControllerDevice (
98 VOID
99 );
100
101 STATIC
102 EFI_STATUS
103 InitUsbIoController (
104 IN USB_IO_CONTROLLER_DEVICE *UsbIoController
105 );
106
107 //
108 // USB Device Configuration / Deconfiguration
109 //
110 STATIC
111 EFI_STATUS
112 UsbDeviceConfiguration (
113 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
114 IN EFI_HANDLE HostController,
115 IN UINT8 ParentPort,
116 IN USB_IO_DEVICE *UsbIoDevice
117 );
118
119 //
120 // Usb Bus enumeration function
121 //
122 STATIC
123 VOID
124 EFIAPI
125 UsbEnumeration (
126 IN EFI_EVENT Event,
127 IN VOID *Context
128 );
129
130 EFI_STATUS
131 ResetRootPort (
132 IN EFI_USB_HC_PROTOCOL *UsbHCInterface,
133 IN UINT8 PortNum,
134 IN UINT8 RetryTimes
135 );
136
137 EFI_STATUS
138 ResetHubPort (
139 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
140 IN UINT8 PortIndex
141 );
142
143 EFI_STATUS
144 ClearRootPortConnectionChangeStatus (
145 IN UINT8 PortNum,
146 IN EFI_USB_HC_PROTOCOL *UsbHCInterface
147 );
148
149 STATIC
150 EFI_STATUS
151 ParentPortReset (
152 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
153 IN BOOLEAN ReConfigure,
154 IN UINT8 RetryTimes
155 );
156
157 //
158 // Following are address allocate and free functions
159 //
160 STATIC
161 UINT8
162 UsbAllocateAddress (
163 IN UINT8 *AddressPool
164 )
165 {
166 UINT8 ByteIndex;
167 UINT8 BitIndex;
168
169 for (ByteIndex = 0; ByteIndex < 16; ByteIndex++) {
170 for (BitIndex = 0; BitIndex < 8; BitIndex++) {
171 if ((AddressPool[ByteIndex] & (1 << BitIndex)) == 0) {
172 //
173 // Found one, covert to address, and mark it use
174 //
175 AddressPool[ByteIndex] |= (1 << BitIndex);
176 return (UINT8) (ByteIndex * 8 + BitIndex);
177 }
178 }
179 }
180
181 return 0;
182
183 }
184
185 STATIC
186 VOID
187 UsbFreeAddress (
188 IN UINT8 DevAddress,
189 IN UINT8 *AddressPool
190 )
191 {
192 UINT8 WhichByte;
193 UINT8 WhichBit;
194 //
195 // Locate the position
196 //
197 WhichByte = (UINT8) (DevAddress / 8);
198 WhichBit = (UINT8) (DevAddress & 0x7);
199
200 AddressPool[WhichByte] &= (~(1 << WhichBit));
201 }
202
203 EFI_STATUS
204 EFIAPI
205 UsbBusControllerDriverSupported (
206 IN EFI_DRIVER_BINDING_PROTOCOL *This,
207 IN EFI_HANDLE Controller,
208 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
209 )
210 /*++
211
212 Routine Description:
213 Test to see if this driver supports ControllerHandle. Any ControllerHandle
214 that has UsbHcProtocol installed will be supported.
215
216 Arguments:
217 This - Protocol instance pointer.
218 Controller - Handle of device to test
219 RemainingDevicePath - Not used
220
221 Returns:
222 EFI_SUCCESS - This driver supports this device.
223 EFI_UNSUPPORTED - This driver does not support this device.
224
225 --*/
226 {
227 EFI_STATUS OpenStatus;
228
229 //
230 // Check whether USB Host Controller Protocol is already
231 // installed on this handle. If it is installed, we can start
232 // USB Bus Driver now.
233 //
234 OpenStatus = gBS->OpenProtocol (
235 Controller,
236 &gEfiUsbHcProtocolGuid,
237 NULL,
238 This->DriverBindingHandle,
239 Controller,
240 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
241 );
242
243 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
244 return EFI_UNSUPPORTED;
245 }
246
247 return OpenStatus;
248 }
249
250
251 EFI_STATUS
252 EFIAPI
253 UsbBusControllerDriverStart (
254 IN EFI_DRIVER_BINDING_PROTOCOL *This,
255 IN EFI_HANDLE Controller,
256 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
257 )
258 /*++
259
260 Routine Description:
261
262 Starting the Usb Bus Driver
263
264 Arguments:
265
266 This - Protocol instance pointer.
267 Controller - Handle of device to test
268 RemainingDevicePath - Not used
269
270 Returns:
271
272 EFI_SUCCESS - This driver supports this device.
273 EFI_UNSUPPORTED - This driver does not support this device.
274 EFI_DEVICE_ERROR - This driver cannot be started due to device
275 Error
276 EFI_OUT_OF_RESOURCES- Can't allocate memory resources
277 EFI_ALREADY_STARTED - This driver has been started
278
279 --*/
280 {
281 EFI_STATUS Status;
282 EFI_STATUS OpenStatus;
283 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
284 USB_IO_DEVICE *RootHub;
285 USB_IO_CONTROLLER_DEVICE *RootHubController;
286 EFI_USB_HC_PROTOCOL *UsbHCInterface;
287
288 //
289 // Allocate USB_BUS_CONTROLLER_DEVICE structure
290 //
291 UsbBusDev = NULL;
292 UsbBusDev = AllocateZeroPool (sizeof (USB_BUS_CONTROLLER_DEVICE));
293 if (UsbBusDev == NULL) {
294 return EFI_OUT_OF_RESOURCES;
295 }
296
297 UsbBusDev->Signature = USB_BUS_DEVICE_SIGNATURE;
298 UsbBusDev->AddressPool[0] = 1;
299
300 //
301 // Get the Device Path Protocol on Controller's handle
302 //
303 OpenStatus = gBS->OpenProtocol (
304 Controller,
305 &gEfiDevicePathProtocolGuid,
306 (VOID **) &UsbBusDev->DevicePath,
307 This->DriverBindingHandle,
308 Controller,
309 EFI_OPEN_PROTOCOL_BY_DRIVER
310 );
311
312 if (EFI_ERROR (OpenStatus)) {
313 gBS->FreePool (UsbBusDev);
314 return EFI_UNSUPPORTED;
315 }
316 //
317 // Locate the Host Controller Interface
318 //
319 OpenStatus = gBS->OpenProtocol (
320 Controller,
321 &gEfiUsbHcProtocolGuid,
322 (VOID **) &UsbHCInterface,
323 This->DriverBindingHandle,
324 Controller,
325 EFI_OPEN_PROTOCOL_BY_DRIVER
326 );
327
328 if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
329
330 //
331 // Report Status Code here since we will reset the host controller
332 //
333 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
334 EFI_ERROR_CODE | EFI_ERROR_MINOR,
335 EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,
336 UsbBusDev->DevicePath
337 );
338
339 gBS->CloseProtocol (
340 Controller,
341 &gEfiDevicePathProtocolGuid,
342 This->DriverBindingHandle,
343 Controller
344 );
345 gBS->FreePool (UsbBusDev);
346 return EFI_UNSUPPORTED;
347 }
348
349 if (OpenStatus == EFI_ALREADY_STARTED) {
350 gBS->CloseProtocol (
351 Controller,
352 &gEfiDevicePathProtocolGuid,
353 This->DriverBindingHandle,
354 Controller
355 );
356 gBS->FreePool (UsbBusDev);
357 return EFI_ALREADY_STARTED;
358 }
359
360 UsbBusDev->UsbHCInterface = UsbHCInterface;
361
362 //
363 // Attach EFI_USB_BUS_PROTOCOL to controller handle,
364 // for locate UsbBusDev later
365 //
366 Status = gBS->InstallProtocolInterface (
367 &Controller,
368 &mUsbBusProtocolGuid,
369 EFI_NATIVE_INTERFACE,
370 &UsbBusDev->BusIdentify
371 );
372
373 if (EFI_ERROR (Status)) {
374
375 gBS->CloseProtocol (
376 Controller,
377 &gEfiDevicePathProtocolGuid,
378 This->DriverBindingHandle,
379 Controller
380 );
381 gBS->CloseProtocol (
382 Controller,
383 &gEfiUsbHcProtocolGuid,
384 This->DriverBindingHandle,
385 Controller
386 );
387 gBS->FreePool (UsbBusDev);
388 return Status;
389 }
390 //
391 // Add root hub to the tree
392 //
393 RootHub = NULL;
394 RootHub = AllocateZeroPool (sizeof (USB_IO_DEVICE));
395 if (RootHub == NULL) {
396 gBS->UninstallProtocolInterface (
397 Controller,
398 &mUsbBusProtocolGuid,
399 &UsbBusDev->BusIdentify
400 );
401 gBS->CloseProtocol (
402 Controller,
403 &gEfiDevicePathProtocolGuid,
404 This->DriverBindingHandle,
405 Controller
406 );
407 gBS->CloseProtocol (
408 Controller,
409 &gEfiUsbHcProtocolGuid,
410 This->DriverBindingHandle,
411 Controller
412 );
413 gBS->FreePool (UsbBusDev);
414 return EFI_OUT_OF_RESOURCES;
415 }
416
417 RootHub->BusController = UsbBusDev;
418 RootHub->DeviceAddress = UsbAllocateAddress (UsbBusDev->AddressPool);
419
420 UsbBusDev->Root = RootHub;
421
422 //
423 // Allocate Root Hub Controller
424 //
425 RootHubController = CreateUsbIoControllerDevice ();
426 if (RootHubController == NULL) {
427 gBS->UninstallProtocolInterface (
428 Controller,
429 &mUsbBusProtocolGuid,
430 &UsbBusDev->BusIdentify
431 );
432 gBS->CloseProtocol (
433 Controller,
434 &gEfiDevicePathProtocolGuid,
435 This->DriverBindingHandle,
436 Controller
437 );
438 gBS->CloseProtocol (
439 Controller,
440 &gEfiUsbHcProtocolGuid,
441 This->DriverBindingHandle,
442 Controller
443 );
444 gBS->FreePool (UsbBusDev);
445 gBS->FreePool (RootHub);
446 return EFI_OUT_OF_RESOURCES;
447 }
448
449 UsbHCInterface->GetRootHubPortNumber (
450 UsbHCInterface,
451 &RootHubController->DownstreamPorts
452 );
453 RootHubController->UsbDevice = RootHub;
454 RootHubController->IsUsbHub = TRUE;
455 RootHubController->DevicePath = UsbBusDev->DevicePath;
456 RootHubController->HostController = Controller;
457
458 RootHub->NumOfControllers = 1;
459 RootHub->UsbController[0] = RootHubController;
460
461 //
462 // Report Status Code here since we will reset the host controller
463 //
464 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
465 EFI_PROGRESS_CODE,
466 EFI_IO_BUS_USB | EFI_IOB_PC_RESET,
467 UsbBusDev->DevicePath
468 );
469
470 //
471 // Reset USB Host Controller
472 //
473 UsbHCInterface->Reset (
474 UsbHCInterface,
475 EFI_USB_HC_RESET_GLOBAL
476 );
477
478 //
479 // Report Status Code while we are going to bring up the Host Controller
480 // and start bus enumeration
481 //
482 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
483 EFI_PROGRESS_CODE,
484 EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE,
485 UsbBusDev->DevicePath
486 );
487
488 //
489 // Start USB Host Controller
490 //
491 UsbHCInterface->SetState (
492 UsbHCInterface,
493 EfiUsbHcStateOperational
494 );
495
496 //
497 // Create a timer to query root ports periodically
498 //
499 Status = gBS->CreateEvent (
500 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
501 EFI_TPL_CALLBACK,
502 UsbEnumeration,
503 RootHubController,
504 &RootHubController->HubNotify
505 );
506 if (EFI_ERROR (Status)) {
507 gBS->UninstallProtocolInterface (
508 Controller,
509 &mUsbBusProtocolGuid,
510 &UsbBusDev->BusIdentify
511 );
512
513 gBS->CloseProtocol (
514 Controller,
515 &gEfiDevicePathProtocolGuid,
516 This->DriverBindingHandle,
517 Controller
518 );
519
520 gBS->CloseProtocol (
521 Controller,
522 &gEfiUsbHcProtocolGuid,
523 This->DriverBindingHandle,
524 Controller
525 );
526
527 gBS->FreePool (RootHubController);
528 gBS->FreePool (RootHub);
529 gBS->FreePool (UsbBusDev);
530 return EFI_UNSUPPORTED;
531 }
532
533 //
534 // Before depending on the timer to check root ports periodically,
535 // here we should check them immediately for the first time, or
536 // there will be an interval between bus start and devices start.
537 //
538 gBS->SignalEvent (RootHubController->HubNotify);
539
540 Status = gBS->SetTimer (
541 RootHubController->HubNotify,
542 TimerPeriodic,
543 BUSPOLLING_PERIOD
544 );
545 if (EFI_ERROR (Status)) {
546 gBS->UninstallProtocolInterface (
547 Controller,
548 &mUsbBusProtocolGuid,
549 &UsbBusDev->BusIdentify
550 );
551
552 gBS->CloseProtocol (
553 Controller,
554 &gEfiDevicePathProtocolGuid,
555 This->DriverBindingHandle,
556 Controller
557 );
558
559 gBS->CloseProtocol (
560 Controller,
561 &gEfiUsbHcProtocolGuid,
562 This->DriverBindingHandle,
563 Controller
564 );
565
566 gBS->CloseEvent (RootHubController->HubNotify);
567 gBS->FreePool (RootHubController);
568 gBS->FreePool (RootHub);
569 gBS->FreePool (UsbBusDev);
570 return EFI_UNSUPPORTED;
571 }
572
573 return EFI_SUCCESS;
574 }
575 //
576 // Stop the bus controller
577 //
578 EFI_STATUS
579 EFIAPI
580 UsbBusControllerDriverStop (
581 IN EFI_DRIVER_BINDING_PROTOCOL *This,
582 IN EFI_HANDLE Controller,
583 IN UINTN NumberOfChildren,
584 IN EFI_HANDLE *ChildHandleBuffer
585 )
586 /*++
587
588 Routine Description:
589 Stop this driver on ControllerHandle. Support stoping any child handles
590 created by this driver.
591
592 Arguments:
593 This - Protocol instance pointer.
594 Controller - Handle of device to stop driver on
595 NumberOfChildren - Number of Children in the ChildHandleBuffer
596 ChildHandleBuffer - List of handles for the children we need to stop.
597
598 Returns:
599 EFI_SUCCESS
600 EFI_DEVICE_ERROR
601 others
602
603 --*/
604 {
605 EFI_STATUS Status;
606 USB_IO_DEVICE *Root;
607 USB_IO_CONTROLLER_DEVICE *RootHubController;
608 USB_BUS_CONTROLLER_DEVICE *UsbBusController;
609 EFI_USB_BUS_PROTOCOL *UsbIdentifier;
610 UINT8 Index2;
611 EFI_USB_HC_PROTOCOL *UsbHCInterface;
612 USB_IO_CONTROLLER_DEVICE *UsbController;
613 USB_IO_DEVICE *UsbIoDevice;
614 USB_IO_CONTROLLER_DEVICE *HubController;
615 UINTN Index;
616 EFI_USB_IO_PROTOCOL *UsbIo;
617
618 if (NumberOfChildren > 0) {
619
620 for (Index = 0; Index < NumberOfChildren; Index++) {
621 Status = gBS->OpenProtocol (
622 ChildHandleBuffer[Index],
623 &gEfiUsbIoProtocolGuid,
624 (VOID **) &UsbIo,
625 This->DriverBindingHandle,
626 Controller,
627 EFI_OPEN_PROTOCOL_GET_PROTOCOL
628 );
629 if (EFI_ERROR (Status)) {
630 //
631 // We are here since the handle passed in does not support
632 // UsbIo protocol. There are several reasons that will cause
633 // this.
634 // For combo device such as keyboard, it may have 2 devices
635 // in one, namely, keyboard and mouse. If we deconfigure one
636 // of them, the other will be freed at the same time. This will
637 // cause the status error. But this is the correct behavior.
638 // For hub device, if we deconfigure hub first, the other chile
639 // device will be disconnected also, this will also provide us
640 // a status error. Now we will only report EFI_SUCCESS since Uhc
641 // driver will be disconnected at the second time.(pls see
642 // CoreDisconnectController for details)
643 //
644 continue;
645 }
646
647 UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo);
648 UsbIoDevice = UsbController->UsbDevice;
649 HubController = UsbController->Parent;
650 UsbDeviceDeConfiguration (UsbIoDevice);
651 for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) {
652 if (HubController->Children[Index2] == UsbIoDevice) {
653 HubController->Children[Index2] = NULL;
654 }
655 }
656 }
657
658 return EFI_SUCCESS;
659 }
660 //
661 // Get the USB_BUS_CONTROLLER_DEVICE
662 //
663 Status = gBS->OpenProtocol (
664 Controller,
665 &mUsbBusProtocolGuid,
666 (VOID **) &UsbIdentifier,
667 This->DriverBindingHandle,
668 Controller,
669 EFI_OPEN_PROTOCOL_GET_PROTOCOL
670 );
671
672 if (EFI_ERROR (Status)) {
673 return EFI_DEVICE_ERROR;
674 }
675
676 UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier);
677
678 //
679 // Stop USB Host Controller
680 //
681 UsbHCInterface = UsbBusController->UsbHCInterface;
682
683 //
684 // Report Status Code here since we will reset the host controller
685 //
686 ReportUsbStatusCode (
687 UsbBusController,
688 EFI_PROGRESS_CODE,
689 EFI_IO_BUS_USB | EFI_IOB_PC_RESET
690 );
691
692 UsbHCInterface->SetState (
693 UsbHCInterface,
694 EfiUsbHcStateHalt
695 );
696
697 //
698 // Deconfiguration all its devices
699 //
700 Root = UsbBusController->Root;
701 RootHubController = Root->UsbController[0];
702
703 gBS->CloseEvent (RootHubController->HubNotify);
704
705 for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) {
706 if (RootHubController->Children[Index2]) {
707 UsbDeviceDeConfiguration (RootHubController->Children[Index2]);
708 RootHubController->Children[Index2] = NULL;
709 }
710 }
711
712 gBS->FreePool (RootHubController);
713 gBS->FreePool (Root);
714
715 //
716 // Uninstall USB Bus Protocol
717 //
718 gBS->UninstallProtocolInterface (
719 Controller,
720 &mUsbBusProtocolGuid,
721 &UsbBusController->BusIdentify
722 );
723
724 //
725 // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL
726 // Opened by this Controller
727 //
728 gBS->CloseProtocol (
729 Controller,
730 &gEfiUsbHcProtocolGuid,
731 This->DriverBindingHandle,
732 Controller
733 );
734
735 gBS->CloseProtocol (
736 Controller,
737 &gEfiDevicePathProtocolGuid,
738 This->DriverBindingHandle,
739 Controller
740 );
741
742 gBS->FreePool (UsbBusController);
743
744 return EFI_SUCCESS;
745 }
746 //
747 // USB Device Configuration
748 //
749 STATIC
750 EFI_STATUS
751 UsbDeviceConfiguration (
752 IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
753 IN EFI_HANDLE HostController,
754 IN UINT8 ParentPort,
755 IN USB_IO_DEVICE *UsbIoDevice
756 )
757 /*++
758
759 Routine Description:
760 Configurate a new device attached to the usb bus
761
762 Arguments:
763 ParentHubController - Parent Hub which this device is connected.
764 HostController - Host Controller handle
765 ParentPort - Parent Hub port which this device is connected.
766 UsbIoDevice - The device to be configured.
767
768 Returns:
769 EFI_SUCCESS
770 EFI_DEVICE_ERROR
771 EFI_OUT_OF_RESOURCES
772
773 --*/
774 {
775 UINT8 DevAddress;
776 UINT8 Index;
777 EFI_STATUS Result;
778 UINT32 Status;
779 CHAR16 *StrManufacturer;
780 CHAR16 *StrProduct;
781 CHAR16 *StrSerialNumber;
782 EFI_USB_IO_PROTOCOL *UsbIo;
783 UINT8 NumOfInterface;
784 USB_IO_CONTROLLER_DEVICE *FirstController;
785 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
786 USB_IO_CONTROLLER_DEVICE *UsbIoController;
787
788 UsbBusDev = UsbIoDevice->BusController;
789 //
790 // Since a USB device must have at least on interface,
791 // so create this instance first
792 //
793 FirstController = CreateUsbIoControllerDevice ();
794 FirstController->UsbDevice = UsbIoDevice;
795 UsbIoDevice->UsbController[0] = FirstController;
796 FirstController->InterfaceNumber = 0;
797 FirstController->ParentPort = ParentPort;
798 FirstController->Parent = ParentHubController;
799 FirstController->HostController = HostController;
800
801 InitializeUsbIoInstance (FirstController);
802
803 DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort));
804
805 //
806 // Ensure we used the correctly USB I/O instance
807 //
808 UsbIo = &FirstController->UsbIo;
809
810 //
811 // First retrieve the 1st 8 bytes of
812 // in order to get the MaxPacketSize for Endpoint 0
813 //
814 for (Index = 0; Index < 3; Index++) {
815
816 UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;
817
818 ParentPortReset (FirstController, FALSE, Index);
819
820 Result = UsbGetDescriptor (
821 UsbIo,
822 (USB_DT_DEVICE << 8),
823 0,
824 8,
825 &UsbIoDevice->DeviceDescriptor,
826 &Status
827 );
828 if (!EFI_ERROR (Result)) {
829 DEBUG ((gUSBDebugLevel,
830 "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",
831 UsbIoDevice->DeviceDescriptor.MaxPacketSize0)
832 );
833 break;
834 }
835
836 }
837
838 if (Index == 3) {
839 ReportUsbStatusCode (
840 UsbBusDev,
841 EFI_ERROR_CODE | EFI_ERROR_MINOR,
842 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
843 );
844 DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n"));
845 gBS->FreePool (FirstController);
846 return EFI_DEVICE_ERROR;
847 }
848
849 DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool);
850 if (DevAddress == 0) {
851 DEBUG ((gUSBErrorLevel, "Cannot allocate address\n"));
852 gBS->FreePool (FirstController);
853 return EFI_OUT_OF_RESOURCES;
854 }
855
856 Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status);
857
858 if (EFI_ERROR (Result)) {
859 DEBUG ((gUSBErrorLevel, "Set address error\n"));
860 ReportUsbStatusCode (
861 UsbBusDev,
862 EFI_ERROR_CODE | EFI_ERROR_MINOR,
863 EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
864 );
865
866 UsbFreeAddress (
867 DevAddress,
868 UsbIoDevice->BusController->AddressPool
869 );
870
871 gBS->FreePool (FirstController);
872 return EFI_DEVICE_ERROR;
873 }
874
875 UsbIoDevice->DeviceAddress = DevAddress;
876
877 //
878 // Get the whole device descriptor
879 //
880 Result = UsbGetDescriptor (
881 UsbIo,
882 (USB_DT_DEVICE << 8),
883 0,
884 sizeof (EFI_USB_DEVICE_DESCRIPTOR),
885 &UsbIoDevice->DeviceDescriptor,
886 &Status
887 );
888
889 if (EFI_ERROR (Result)) {
890 DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n"));
891 ReportUsbStatusCode (
892 UsbBusDev,
893 EFI_ERROR_CODE | EFI_ERROR_MINOR,
894 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
895 );
896 UsbFreeAddress (
897 DevAddress,
898 UsbIoDevice->BusController->AddressPool
899 );
900
901 gBS->FreePool (FirstController);
902 return EFI_DEVICE_ERROR;
903 }
904 //
905 // Get & parse all configurations for this device, including
906 // all configuration descriptors, all interface descriptors, all
907 // endpoint descriptors
908 //
909 Result = UsbGetAllConfigurations (UsbIoDevice);
910
911 if (EFI_ERROR (Result)) {
912 DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n"));
913 ReportUsbStatusCode (
914 UsbBusDev,
915 EFI_ERROR_CODE | EFI_ERROR_MINOR,
916 EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
917 );
918 UsbFreeAddress (
919 DevAddress,
920 UsbIoDevice->BusController->AddressPool
921 );
922
923 gBS->FreePool (FirstController);
924 return EFI_DEVICE_ERROR;
925 }
926 //
927 // Set the 1st configuration value
928 //
929 Result = UsbSetDefaultConfiguration (UsbIoDevice);
930 if (EFI_ERROR (Result)) {
931 DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n"));
932 ReportUsbStatusCode (
933 UsbBusDev,
934 EFI_ERROR_CODE | EFI_ERROR_MINOR,
935 EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
936 );
937 UsbFreeAddress (
938 DevAddress,
939 UsbIoDevice->BusController->AddressPool
940 );
941
942 gBS->FreePool (FirstController);
943 return EFI_DEVICE_ERROR;
944 }
945
946 UsbIoDevice->IsConfigured = TRUE;
947
948 //
949 // Get all string table if applicable
950 //
951 Result = UsbGetStringtable (UsbIoDevice);
952 if (EFI_ERROR (Result)) {
953 DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n"));
954 } else {
955
956 StrManufacturer = NULL;
957 UsbIo->UsbGetStringDescriptor (
958 UsbIo,
959 UsbIoDevice->LangID[0],
960 (UsbIoDevice->DeviceDescriptor).StrManufacturer,
961 &StrManufacturer
962 );
963
964 StrProduct = NULL;
965 UsbIo->UsbGetStringDescriptor (
966 UsbIo,
967 UsbIoDevice->LangID[0],
968 (UsbIoDevice->DeviceDescriptor).StrProduct,
969 &StrProduct
970 );
971
972 StrSerialNumber = NULL;
973 UsbIo->UsbGetStringDescriptor (
974 UsbIo,
975 UsbIoDevice->LangID[0],
976 (UsbIoDevice->DeviceDescriptor).StrSerialNumber,
977 &StrSerialNumber
978 );
979
980 if (StrManufacturer) {
981 gBS->FreePool (StrManufacturer);
982 }
983
984 if (StrProduct) {
985 gBS->FreePool (StrProduct);
986 }
987
988 if (StrSerialNumber) {
989 gBS->FreePool (StrSerialNumber);
990 }
991 }
992 //
993 // Create USB_IO_CONTROLLER_DEVICE for
994 // each detected interface
995 //
996 FirstController->CurrentConfigValue =
997 UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
998
999 NumOfInterface =
1000 UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces;
1001 UsbIoDevice->NumOfControllers = NumOfInterface;
1002
1003 Result = InitUsbIoController (FirstController);
1004 if (EFI_ERROR (Result)) {
1005 ReportUsbStatusCode (
1006 UsbBusDev,
1007 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1008 EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
1009 );
1010 gBS->FreePool (FirstController);
1011 UsbIoDevice->UsbController[0] = NULL;
1012 return EFI_DEVICE_ERROR;
1013 }
1014
1015 for (Index = 1; Index < NumOfInterface; Index++) {
1016 UsbIoController = CreateUsbIoControllerDevice ();
1017 UsbIoController->UsbDevice = UsbIoDevice;
1018 UsbIoController->CurrentConfigValue =
1019 UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
1020 UsbIoController->InterfaceNumber = Index;
1021 UsbIoDevice->UsbController[Index] = UsbIoController;
1022 UsbIoController->ParentPort = ParentPort;
1023 UsbIoController->Parent = ParentHubController;
1024 UsbIoController->HostController = HostController;
1025
1026 //
1027 // First copy the USB_IO Protocol instance
1028 //
1029 CopyMem (
1030 &UsbIoController->UsbIo,
1031 UsbIo,
1032 sizeof (EFI_USB_IO_PROTOCOL)
1033 );
1034
1035 Result = InitUsbIoController (UsbIoController);
1036 if (EFI_ERROR (Result)) {
1037 ReportUsbStatusCode (
1038 UsbBusDev,
1039 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1040 EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
1041 );
1042 gBS->FreePool (UsbIoController);
1043 UsbIoDevice->UsbController[Index] = NULL;
1044 }
1045 }
1046
1047 return EFI_SUCCESS;
1048 }
1049 //
1050 // USB Device DeConfiguration
1051 //
1052
1053 EFI_STATUS
1054 UsbDeviceDeConfiguration (
1055 IN USB_IO_DEVICE *UsbIoDevice
1056 )
1057 /*++
1058
1059 Routine Description:
1060 Remove Device, Device Handles, Uninstall Protocols.
1061
1062 Arguments:
1063 UsbIoDevice - The device to be deconfigured.
1064
1065 Returns:
1066 EFI_SUCCESS
1067 EFI_DEVICE_ERROR
1068
1069 --*/
1070 {
1071 USB_IO_CONTROLLER_DEVICE *UsbController;
1072 UINT8 index;
1073 USB_IO_DEVICE *ChildDevice;
1074 UINT8 Index;
1075 EFI_USB_IO_PROTOCOL *UsbIo;
1076
1077 DEBUG ((gUSBDebugLevel, "Enter Usb Device Deconfiguration\n"));
1078
1079 //
1080 // Double check UsbIoDevice exists
1081 //
1082 if (UsbIoDevice == NULL) {
1083 return EFI_SUCCESS;
1084 }
1085
1086 for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {
1087 //
1088 // Check if it is a hub, if so, de configuration all its
1089 // downstream ports
1090 //
1091 UsbController = UsbIoDevice->UsbController[index];
1092
1093 //
1094 // Check the controller pointer
1095 //
1096 if (UsbController == NULL) {
1097 continue;
1098 }
1099
1100 if (UsbController->IsUsbHub) {
1101
1102 DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n"));
1103
1104 //
1105 // First Remove interrupt transfer request for the status
1106 // change port
1107 //
1108 UsbIo = &UsbController->UsbIo;
1109 UsbIo->UsbAsyncInterruptTransfer (
1110 UsbIo,
1111 UsbController->HubEndpointAddress,
1112 FALSE,
1113 0,
1114 0,
1115 NULL,
1116 NULL
1117 );
1118
1119 if (NULL != UsbController->HubNotify) {
1120 gBS->CloseEvent (UsbController->HubNotify);
1121 }
1122
1123 for (Index = 0; Index < UsbController->DownstreamPorts; Index++) {
1124 if (UsbController->Children[Index]) {
1125 ChildDevice = UsbController->Children[Index];
1126 UsbDeviceDeConfiguration (ChildDevice);
1127 UsbController->Children[Index] = NULL;
1128 }
1129 }
1130 }
1131 //
1132 // If the controller is managed by a device driver, we need to
1133 // disconnect them
1134 //
1135 if (UsbController->IsManagedByDriver) {
1136 gBS->DisconnectController (
1137 UsbController->Handle,
1138 NULL,
1139 NULL
1140 );
1141 }
1142
1143 //
1144 // remove child handle reference to the USB_HC_PROTOCOL
1145 //
1146 gBS->CloseProtocol (
1147 UsbController->HostController,
1148 &gEfiUsbHcProtocolGuid,
1149 gUsbBusDriverBinding.DriverBindingHandle,
1150 UsbController->Handle
1151 );
1152
1153 //
1154 // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL
1155 // installed on this handle
1156 //
1157 gBS->UninstallMultipleProtocolInterfaces (
1158 UsbController->Handle,
1159 &gEfiDevicePathProtocolGuid,
1160 UsbController->DevicePath,
1161 &gEfiUsbIoProtocolGuid,
1162 &UsbController->UsbIo,
1163 NULL
1164 );
1165
1166 if (UsbController->DevicePath != NULL) {
1167 gBS->FreePool (UsbController->DevicePath);
1168 }
1169
1170 gBS->FreePool (UsbController);
1171 UsbIoDevice->UsbController[index] = NULL;
1172 }
1173 //
1174 // Free address for later use
1175 //
1176 UsbFreeAddress (
1177 UsbIoDevice->DeviceAddress,
1178 UsbIoDevice->BusController->AddressPool
1179 );
1180
1181 //
1182 // Free all resouces allocated for all its configurations
1183 //
1184 UsbDestroyAllConfiguration (UsbIoDevice);
1185
1186 if (UsbIoDevice) {
1187 gBS->FreePool (UsbIoDevice);
1188 UsbIoDevice = NULL;
1189 }
1190
1191 return EFI_SUCCESS;
1192 }
1193 //
1194 // After interrupt complete, this function will be called,
1195 // This function need to be well-defined later
1196 //
1197 STATIC
1198 EFI_STATUS
1199 EFIAPI
1200 OnHubInterruptComplete (
1201 IN VOID *Data,
1202 IN UINTN DataLength,
1203 IN VOID *Context,
1204 IN UINT32 Result
1205 )
1206 /*++
1207
1208 Routine Description:
1209 Whenever hub interrupt occurs, this routine will be called to check
1210 which event happens.
1211
1212 Arguments:
1213 Data - Hub interrupt transfer data.
1214 DataLength - The length of the Data.
1215 Context - Hub Controller Device.
1216 Result - Hub interrupt transfer status.
1217
1218 Returns:
1219 EFI_SUCCESS
1220 EFI_DEVICE_ERROR
1221
1222 --*/
1223 {
1224 USB_IO_CONTROLLER_DEVICE *HubController;
1225 UINT8 Index;
1226 UINT8 *ptr;
1227 EFI_USB_IO_PROTOCOL *UsbIo;
1228 UINT32 UsbResult;
1229 BOOLEAN Disconnected;
1230 EFI_STATUS Status;
1231
1232 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
1233 UsbIo = &HubController->UsbIo;
1234
1235 //
1236 // If something error in this interrupt transfer,
1237 //
1238 if (Result != EFI_USB_NOERROR) {
1239 if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
1240 UsbClearEndpointHalt (
1241 UsbIo,
1242 HubController->HubEndpointAddress,
1243 &UsbResult
1244 );
1245 }
1246
1247 //
1248 // Delete & Submit this interrupt again
1249 //
1250 UsbIo->UsbAsyncInterruptTransfer (
1251 UsbIo,
1252 HubController->HubEndpointAddress,
1253 FALSE,
1254 0,
1255 0,
1256 NULL,
1257 NULL
1258 );
1259
1260 //
1261 // try to detect if the hub itself was disconnected or not
1262 //
1263 Status = IsDeviceDisconnected (
1264 HubController,
1265 &Disconnected
1266 );
1267
1268 if (!EFI_ERROR (Status) && Disconnected == TRUE) {
1269 DEBUG ((gUSBErrorLevel, "Hub is disconnected\n"));
1270 return EFI_DEVICE_ERROR;
1271 }
1272 //
1273 // Hub ports < 7
1274 //
1275 UsbIo->UsbAsyncInterruptTransfer (
1276 UsbIo,
1277 HubController->HubEndpointAddress,
1278 TRUE,
1279 100,
1280 1,
1281 OnHubInterruptComplete,
1282 HubController
1283 );
1284
1285 return EFI_DEVICE_ERROR;
1286 }
1287
1288 if (DataLength == 0 || Data == NULL) {
1289 return EFI_SUCCESS;
1290 }
1291
1292 //
1293 // Scan which port has status change
1294 // Bit 0 stands for hub itself, other bit stands for
1295 // the corresponding port
1296 //
1297 for (Index = 0; Index < DataLength * 8; Index++) {
1298 ptr = (UINT8 *) Data + Index / 8;
1299 if ((*ptr) & (1 << (Index & 0x7))) {
1300 HubController->StatusChangePort = Index;
1301 break;
1302 }
1303 }
1304 //
1305 // Signal hub notify event
1306 //
1307 gBS->SignalEvent (HubController->HubNotify);
1308
1309 return EFI_SUCCESS;
1310 }
1311 //
1312 // USB Root Hub Enumerator
1313 //
1314 STATIC
1315 VOID
1316 EFIAPI
1317 UsbEnumeration (
1318 IN EFI_EVENT Event,
1319 IN VOID *Context
1320 )
1321 /*++
1322
1323 Routine Description:
1324 This is USB enumerator
1325
1326 Arguments:
1327 Event - Indicating which event is signaled
1328 Context - actually it is a USB_IO_DEVICE
1329
1330 Returns:
1331 EFI_SUCCESS
1332 Others
1333
1334 --*/
1335 {
1336 USB_IO_CONTROLLER_DEVICE *HubController;
1337 EFI_USB_PORT_STATUS HubPortStatus;
1338 EFI_STATUS Status;
1339 UINT8 Index;
1340 EFI_USB_HC_PROTOCOL *UsbHCInterface;
1341 USB_IO_DEVICE *UsbIoDev;
1342 USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
1343 EFI_HANDLE HostController;
1344 USB_IO_DEVICE *OldUsbIoDevice;
1345 USB_IO_DEVICE *NewDevice;
1346 USB_IO_CONTROLLER_DEVICE *NewController;
1347 UINT8 Index2;
1348 EFI_USB_IO_PROTOCOL *UsbIo;
1349 UINT8 StatusChangePort;
1350
1351 HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
1352 HostController = HubController->HostController;
1353 UsbBusDev = HubController->UsbDevice->BusController;
1354
1355 if (HubController->UsbDevice->DeviceAddress == 1) {
1356 //
1357 // Root hub has the address 1
1358 //
1359 UsbIoDev = HubController->UsbDevice;
1360 UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
1361
1362 for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
1363 UsbHCInterface->GetRootHubPortStatus (
1364 UsbHCInterface,
1365 Index,
1366 (EFI_USB_PORT_STATUS *) &HubPortStatus
1367 );
1368
1369 if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
1370 continue;
1371 }
1372 //
1373 // Clear root hub status change status
1374 //
1375 ClearRootPortConnectionChangeStatus (
1376 Index,
1377 UsbHCInterface
1378 );
1379
1380 gBS->Stall (100 * 1000);
1381
1382 UsbHCInterface->GetRootHubPortStatus (
1383 UsbHCInterface,
1384 Index,
1385 (EFI_USB_PORT_STATUS *) &HubPortStatus
1386 );
1387
1388 if (IsPortConnect (HubPortStatus.PortStatus)) {
1389
1390 //
1391 // There is something connected to this port
1392 //
1393 DEBUG ((gUSBDebugLevel, "Something attached from Root Hub in 0x%x\n", Index));
1394
1395 ReportUsbStatusCode (
1396 UsbBusDev,
1397 EFI_PROGRESS_CODE,
1398 EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
1399 );
1400 //
1401 // if there is something physically detached, but still logically
1402 // attached...
1403 //
1404 OldUsbIoDevice = HubController->Children[Index];
1405
1406 if (NULL != OldUsbIoDevice) {
1407 UsbDeviceDeConfiguration (OldUsbIoDevice);
1408 HubController->Children[Index] = NULL;
1409 }
1410
1411 NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
1412 if (NewDevice == NULL) {
1413 return ;
1414 }
1415 //
1416 // Initialize some fields by copying data from
1417 // its parents
1418 //
1419 NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);
1420
1421 DEBUG ((gUSBDebugLevel, "DeviceSpeed 0x%x\n", NewDevice->IsSlowDevice));
1422
1423 NewDevice->BusController = UsbIoDev->BusController;
1424
1425 //
1426 // Configure that device
1427 //
1428 Status = UsbDeviceConfiguration (
1429 HubController,
1430 HostController,
1431 Index,
1432 NewDevice
1433 );
1434 if (EFI_ERROR (Status)) {
1435 gBS->FreePool (NewDevice);
1436 return ;
1437 }
1438 //
1439 // Add this device to the usb bus tree
1440 //
1441 HubController->Children[Index] = NewDevice;
1442
1443 for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
1444 //
1445 // If this device is hub, add to the hub index
1446 //
1447 NewController = NewDevice->UsbController[Index2];
1448
1449 Status = gBS->ConnectController (
1450 NewController->Handle,
1451 NULL,
1452 NULL,
1453 TRUE
1454 );
1455 //
1456 // If connect success, we need to disconnect when
1457 // stop the controller, otherwise we need not call
1458 // gBS->DisconnectController ()
1459 // This is used by those usb devices we don't plan
1460 // to support. We can allocate
1461 // controller handles for them, but we don't have
1462 // device drivers to manage them.
1463 //
1464 NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
1465
1466 if (IsHub (NewController)) {
1467
1468 NewController->IsUsbHub = TRUE;
1469
1470 //
1471 // Configure Hub Controller
1472 //
1473 Status = DoHubConfig (NewController);
1474 if (EFI_ERROR (Status)) {
1475 continue;
1476 }
1477 //
1478 // Create an event to do hub enumeration
1479 //
1480 gBS->CreateEvent (
1481 EFI_EVENT_NOTIFY_SIGNAL,
1482 EFI_TPL_CALLBACK,
1483 UsbEnumeration,
1484 NewController,
1485 &NewController->HubNotify
1486 );
1487
1488 //
1489 // Add request to do query hub status
1490 // change endpoint
1491 // Hub ports < 7
1492 //
1493 UsbIo = &NewController->UsbIo;
1494 UsbIo->UsbAsyncInterruptTransfer (
1495 UsbIo,
1496 NewController->HubEndpointAddress,
1497 TRUE,
1498 100,
1499 1,
1500 OnHubInterruptComplete,
1501 NewController
1502 );
1503
1504 }
1505 }
1506 } else {
1507 //
1508 // Something disconnected from USB root hub
1509 //
1510 DEBUG ((gUSBDebugLevel, "Something deteached from Root Hub\n"));
1511
1512 OldUsbIoDevice = HubController->Children[Index];
1513
1514 UsbDeviceDeConfiguration (OldUsbIoDevice);
1515
1516 HubController->Children[Index] = NULL;
1517
1518 UsbHCInterface->ClearRootHubPortFeature (
1519 UsbHCInterface,
1520 Index,
1521 EfiUsbPortEnableChange
1522 );
1523
1524 UsbHCInterface->GetRootHubPortStatus (
1525 UsbHCInterface,
1526 Index,
1527 (EFI_USB_PORT_STATUS *) &HubPortStatus
1528 );
1529
1530 }
1531 }
1532
1533 return ;
1534 } else {
1535 //
1536 // Event from Hub, Get the hub controller handle
1537 //
1538 //
1539 // Get the status change endpoint
1540 //
1541 StatusChangePort = HubController->StatusChangePort;
1542
1543 //
1544 // Clear HubController Status Change Bit
1545 //
1546 HubController->StatusChangePort = 0;
1547
1548 if (StatusChangePort == 0) {
1549 //
1550 // Hub changes, we don't handle here
1551 //
1552 return ;
1553 }
1554 //
1555 // Check which event took place at that port
1556 //
1557 UsbIo = &HubController->UsbIo;
1558 Status = HubGetPortStatus (
1559 UsbIo,
1560 StatusChangePort,
1561 (UINT32 *) &HubPortStatus
1562 );
1563
1564 if (EFI_ERROR (Status)) {
1565 return ;
1566 }
1567 //
1568 // Clear some change status
1569 //
1570 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
1571 //
1572 // Clear Hub port enable change
1573 //
1574 DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
1575 HubClearPortFeature (
1576 UsbIo,
1577 StatusChangePort,
1578 EfiUsbPortEnableChange
1579 );
1580
1581 HubGetPortStatus (
1582 UsbIo,
1583 StatusChangePort,
1584 (UINT32 *) &HubPortStatus
1585 );
1586 }
1587
1588 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
1589 //
1590 // Clear Hub reset change
1591 //
1592 DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
1593 HubClearPortFeature (
1594 UsbIo,
1595 StatusChangePort,
1596 EfiUsbPortResetChange
1597 );
1598
1599 HubGetPortStatus (
1600 UsbIo,
1601 StatusChangePort,
1602 (UINT32 *) &HubPortStatus
1603 );
1604 }
1605
1606 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {
1607 //
1608 // Clear Hub overcurrent change
1609 //
1610 DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));
1611 HubClearPortFeature (
1612 UsbIo,
1613 StatusChangePort,
1614 EfiUsbPortOverCurrentChange
1615 );
1616
1617 HubGetPortStatus (
1618 UsbIo,
1619 StatusChangePort,
1620 (UINT32 *) &HubPortStatus
1621 );
1622 }
1623
1624 if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
1625 //
1626 // First clear port connection change
1627 //
1628 DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));
1629 HubClearPortFeature (
1630 UsbIo,
1631 StatusChangePort,
1632 EfiUsbPortConnectChange
1633 );
1634
1635 HubGetPortStatus (
1636 UsbIo,
1637 StatusChangePort,
1638 (UINT32 *) &HubPortStatus
1639 );
1640
1641 if (IsPortConnect (HubPortStatus.PortStatus)) {
1642
1643 DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));
1644
1645 ReportUsbStatusCode (
1646 UsbBusDev,
1647 EFI_PROGRESS_CODE,
1648 EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
1649 );
1650
1651 //
1652 // if there is something physically detached, but still logically
1653 // attached...
1654 //
1655 OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
1656
1657 if (NULL != OldUsbIoDevice) {
1658 UsbDeviceDeConfiguration (OldUsbIoDevice);
1659 HubController->Children[StatusChangePort - 1] = NULL;
1660 }
1661
1662 NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
1663 if (NewDevice == NULL) {
1664 return ;
1665 }
1666
1667 ResetHubPort (HubController, StatusChangePort);
1668
1669 HubGetPortStatus (
1670 UsbIo,
1671 StatusChangePort,
1672 (UINT32 *) &HubPortStatus
1673 );
1674
1675 //
1676 // Initialize some fields
1677 //
1678 NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);
1679
1680 NewDevice->BusController = HubController->UsbDevice->BusController;
1681
1682 //
1683 // Configure that device
1684 //
1685 Status = UsbDeviceConfiguration (
1686 HubController,
1687 HostController,
1688 (UINT8) (StatusChangePort - 1),
1689 NewDevice
1690 );
1691
1692 if (EFI_ERROR (Status)) {
1693 gBS->FreePool (NewDevice);
1694 return ;
1695 }
1696 //
1697 // Add this device to the usb bus tree
1698 // StatusChangePort is begin from 1,
1699 //
1700 HubController->Children[StatusChangePort - 1] = NewDevice;
1701
1702 for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
1703 //
1704 // If this device is hub, add to the hub index
1705 //
1706 NewController = NewDevice->UsbController[Index2];
1707
1708 //
1709 // Connect the controller to the driver image
1710 //
1711 Status = gBS->ConnectController (
1712 NewController->Handle,
1713 NULL,
1714 NULL,
1715 TRUE
1716 );
1717 //
1718 // If connect success, we need to disconnect when
1719 // stop the controller, otherwise we need not call
1720 // gBS->DisconnectController ()
1721 // This is used by those usb devices we don't plan
1722 // to support. We can allocate
1723 // controller handles for them, but we don't have
1724 // device drivers to manage them.
1725 //
1726 NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
1727
1728 //
1729 // If this device is hub, add to the hub index
1730 //
1731 if (IsHub (NewController)) {
1732
1733 NewController->IsUsbHub = TRUE;
1734
1735 //
1736 // Configure Hub
1737 //
1738 Status = DoHubConfig (NewController);
1739
1740 if (EFI_ERROR (Status)) {
1741 continue;
1742 }
1743 //
1744 // Create an event to do hub enumeration
1745 //
1746 gBS->CreateEvent (
1747 EFI_EVENT_NOTIFY_SIGNAL,
1748 EFI_TPL_CALLBACK,
1749 UsbEnumeration,
1750 NewController,
1751 &NewController->HubNotify
1752 );
1753
1754 //
1755 // Add request to do query hub status
1756 // change endpoint
1757 //
1758 UsbIo = &NewController->UsbIo;
1759 UsbIo->UsbAsyncInterruptTransfer (
1760 UsbIo,
1761 NewController->HubEndpointAddress, // Hub endpoint address
1762 TRUE,
1763 100,
1764 1, // Hub ports < 7
1765 OnHubInterruptComplete,
1766 NewController
1767 );
1768 }
1769 }
1770 } else {
1771 //
1772 // Something disconnected from USB hub
1773 //
1774 DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));
1775
1776 OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
1777
1778 UsbDeviceDeConfiguration (OldUsbIoDevice);
1779
1780 HubController->Children[StatusChangePort - 1] = NULL;
1781
1782 }
1783
1784 return ;
1785 }
1786
1787 return ;
1788 }
1789 }
1790 //
1791 // Clear port connection change status over a given root hub port
1792 //
1793 EFI_STATUS
1794 ClearRootPortConnectionChangeStatus (
1795 UINT8 PortNum,
1796 EFI_USB_HC_PROTOCOL *UsbHCInterface
1797 )
1798 /*++
1799
1800 Routine Description:
1801 Clear port connection change status over a given root hub port
1802
1803 Arguments:
1804 PortNum - The given port.
1805 UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.
1806
1807 Returns:
1808 EFI_SUCCESS
1809
1810 --*/
1811 {
1812 EFI_STATUS Status;
1813 Status = UsbHCInterface->ClearRootHubPortFeature (
1814 UsbHCInterface,
1815 PortNum,
1816 EfiUsbPortConnectChange
1817 );
1818 return Status;
1819 }
1820
1821 STATIC
1822 USB_IO_CONTROLLER_DEVICE *
1823 CreateUsbIoControllerDevice (
1824 VOID
1825 )
1826 /*++
1827
1828 Routine Description:
1829 Allocate a structure for USB_IO_CONTROLLER_DEVICE
1830
1831 Arguments:
1832 N/A
1833
1834 Returns:
1835 A pointer to a USB_IO_CONTROLLER_DEVICE structure,
1836 Or NULL.
1837
1838 --*/
1839 {
1840 USB_IO_CONTROLLER_DEVICE *UsbIoControllerDev;
1841
1842 //
1843 // Allocate USB_IO_CONTROLLER_DEVICE structure
1844 //
1845 UsbIoControllerDev = NULL;
1846 UsbIoControllerDev = AllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE));
1847
1848 if (UsbIoControllerDev == NULL) {
1849 return NULL;
1850 }
1851
1852 UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE;
1853
1854 return UsbIoControllerDev;
1855 }
1856
1857 STATIC
1858 EFI_STATUS
1859 InitUsbIoController (
1860 IN USB_IO_CONTROLLER_DEVICE *UsbIoController
1861 )
1862 /*++
1863
1864 Routine Description:
1865 Init and install EFI_USB_IO_PROTOCOL onto that controller.
1866
1867 Arguments:
1868 UsbIoController - The Controller to be operated.
1869
1870 Returns:
1871 EFI_SUCCESS
1872 Others
1873
1874 --*/
1875 {
1876 USB_DEVICE_PATH UsbNode;
1877 EFI_STATUS Status;
1878 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1879 EFI_USB_HC_PROTOCOL *UsbHcProtocol;
1880
1881 //
1882 // Build the child device path for each new USB_IO device
1883 //
1884 ZeroMem (&UsbNode, sizeof (UsbNode));
1885 UsbNode.Header.Type = MESSAGING_DEVICE_PATH;
1886 UsbNode.Header.SubType = MSG_USB_DP;
1887 SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
1888 UsbNode.InterfaceNumber = UsbIoController->InterfaceNumber;
1889 UsbNode.ParentPortNumber = UsbIoController->ParentPort;
1890 ParentDevicePath = UsbIoController->Parent->DevicePath;
1891
1892 UsbIoController->DevicePath =
1893 AppendDevicePathNode (ParentDevicePath, &UsbNode.Header);
1894 if (UsbIoController->DevicePath == NULL) {
1895 return EFI_OUT_OF_RESOURCES;
1896 }
1897
1898 Status = gBS->InstallMultipleProtocolInterfaces (
1899 &UsbIoController->Handle,
1900 &gEfiDevicePathProtocolGuid,
1901 UsbIoController->DevicePath,
1902 &gEfiUsbIoProtocolGuid,
1903 &UsbIoController->UsbIo,
1904 NULL
1905 );
1906
1907 if (EFI_ERROR (Status)) {
1908 return Status;
1909 }
1910
1911 Status = gBS->OpenProtocol (
1912 UsbIoController->HostController,
1913 &gEfiUsbHcProtocolGuid,
1914 (VOID **) &UsbHcProtocol,
1915 gUsbBusDriverBinding.DriverBindingHandle,
1916 UsbIoController->Handle,
1917 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1918 );
1919
1920 return Status;
1921 }
1922
1923 STATIC
1924 EFI_STATUS
1925 ParentPortReset (
1926 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
1927 IN BOOLEAN ReConfigure,
1928 IN UINT8 RetryTimes
1929 )
1930 /*++
1931
1932 Routine Description:
1933 Reset parent hub port to which this device is connected.
1934
1935 Arguments:
1936 UsbIoController - Indicating the Usb Controller Device.
1937 Reconfigure - Do we need to reconfigure it.
1938 RetryTimes - Retry Times when failed
1939 Returns:
1940 EFI_SUCCESS
1941 EFI_DEVICE_ERROR
1942
1943 --*/
1944 {
1945 USB_IO_DEVICE *ParentIoDev;
1946 USB_IO_DEVICE *UsbIoDev;
1947 USB_IO_CONTROLLER_DEVICE *ParentController;
1948 UINT8 HubPort;
1949 UINT32 Status;
1950 EFI_STATUS Result;
1951 EFI_USB_IO_PROTOCOL *UsbIo;
1952 UINT8 Address;
1953
1954 ParentController = UsbIoController->Parent;
1955 ParentIoDev = ParentController->UsbDevice;
1956 UsbIoDev = UsbIoController->UsbDevice;
1957 HubPort = UsbIoController->ParentPort;
1958
1959 gBS->Stall (100 * 1000);
1960
1961 if (ParentIoDev->DeviceAddress == 1) {
1962 DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));
1963 ResetRootPort (ParentIoDev->BusController->UsbHCInterface, HubPort, RetryTimes);
1964 } else {
1965 DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));
1966 ResetHubPort (ParentController, HubPort + 1);
1967 }
1968 //
1969 // If we only need port reset, just return
1970 //
1971 if (!ReConfigure) {
1972 return EFI_SUCCESS;
1973 }
1974 //
1975 // Re-config that USB device
1976 //
1977 UsbIo = &UsbIoController->UsbIo;
1978
1979 //
1980 // Assign a unique address to this device
1981 //
1982 Address = UsbIoDev->DeviceAddress;
1983 UsbIoDev->DeviceAddress = 0;
1984
1985 Result = UsbSetDeviceAddress (UsbIo, Address, &Status);
1986 UsbIoDev->DeviceAddress = Address;
1987
1988 if (EFI_ERROR (Result)) {
1989 return EFI_DEVICE_ERROR;
1990 }
1991 //
1992 // Set the device to the default configuration
1993 //
1994 Result = UsbSetDefaultConfiguration (UsbIoDev);
1995 if (EFI_ERROR (Result)) {
1996 return EFI_DEVICE_ERROR;
1997 }
1998
1999 return EFI_SUCCESS;
2000 }
2001
2002 EFI_STATUS
2003 EFIAPI
2004 UsbPortReset (
2005 IN EFI_USB_IO_PROTOCOL *This
2006 )
2007 /*++
2008
2009 Routine Description:
2010 Resets and reconfigures the USB controller. This function will
2011 work for all USB devices except USB Hub Controllers.
2012
2013 Arguments:
2014 This - Indicates the calling context.
2015
2016 Returns:
2017 EFI_SUCCESS
2018 EFI_INVALID_PARAMETER
2019 EFI_DEVICE_ERROR
2020
2021 --*/
2022 {
2023 USB_IO_CONTROLLER_DEVICE *UsbIoController;
2024 EFI_STATUS Status;
2025
2026 UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
2027
2028 //
2029 // Since at this time, this device has already been configured,
2030 // it needs to be re-configured.
2031 //
2032 Status = ParentPortReset (UsbIoController, TRUE, 0);
2033
2034 return Status;
2035 }
2036
2037 EFI_STATUS
2038 ResetRootPort (
2039 IN EFI_USB_HC_PROTOCOL *UsbHCInterface,
2040 IN UINT8 PortNum,
2041 IN UINT8 RetryTimes
2042 )
2043 /*++
2044
2045 Routine Description:
2046 Reset Root Hub port.
2047
2048 Arguments:
2049 UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.
2050 PortNum - The given port to be reset.
2051 RetryTimes - RetryTimes when failed
2052 Returns:
2053 N/A
2054
2055 --*/
2056 {
2057 EFI_STATUS Status;
2058
2059 //
2060 // reset root port
2061 //
2062 Status = UsbHCInterface->SetRootHubPortFeature (
2063 UsbHCInterface,
2064 PortNum,
2065 EfiUsbPortReset
2066 );
2067
2068 if (EFI_ERROR (Status)) {
2069 return EFI_DEVICE_ERROR;
2070 }
2071
2072 gBS->Stall (50 * 1000);
2073
2074 //
2075 // clear reset root port
2076 //
2077 Status = UsbHCInterface->ClearRootHubPortFeature (
2078 UsbHCInterface,
2079 PortNum,
2080 EfiUsbPortReset
2081 );
2082
2083 if (EFI_ERROR (Status)) {
2084 return EFI_DEVICE_ERROR;
2085 }
2086
2087 gBS->Stall (1000);
2088
2089 Status = ClearRootPortConnectionChangeStatus (PortNum, UsbHCInterface);
2090
2091 if (EFI_ERROR (Status)) {
2092 return EFI_DEVICE_ERROR;
2093 }
2094 //
2095 // Set port enable
2096 //
2097 Status = UsbHCInterface->SetRootHubPortFeature (
2098 UsbHCInterface,
2099 PortNum,
2100 EfiUsbPortEnable
2101 );
2102 if (EFI_ERROR (Status)) {
2103 return EFI_DEVICE_ERROR;
2104 }
2105
2106 Status = UsbHCInterface->ClearRootHubPortFeature (
2107 UsbHCInterface,
2108 PortNum,
2109 EfiUsbPortEnableChange
2110 );
2111 gBS->Stall ((1 + RetryTimes) * 50 * 1000);
2112
2113 return EFI_SUCCESS;
2114 }
2115
2116
2117 EFI_STATUS
2118 ResetHubPort (
2119 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
2120 IN UINT8 PortIndex
2121 )
2122 /*++
2123
2124 Routine Description:
2125 Reset Hub port.
2126
2127 Arguments:
2128 UsbIoController - The USB_IO_CONTROLLER_DEVICE instance.
2129 PortIndex - The given port to be reset.
2130
2131 Returns:
2132 EFI_SUCCESS
2133 EFI_DEVICE_ERROR
2134
2135 --*/
2136 {
2137 EFI_USB_IO_PROTOCOL *UsbIo;
2138 EFI_USB_PORT_STATUS HubPortStatus;
2139 UINT8 Number;
2140
2141 ASSERT (UsbIoController->IsUsbHub == TRUE);
2142
2143 UsbIo = &UsbIoController->UsbIo;
2144
2145 HubSetPortFeature (
2146 UsbIo,
2147 PortIndex,
2148 EfiUsbPortReset
2149 );
2150
2151 gBS->Stall (10 * 1000);
2152
2153 //
2154 // Wait for port reset complete
2155 //
2156 Number = 10;
2157 do {
2158 HubGetPortStatus (
2159 UsbIo,
2160 PortIndex,
2161 (UINT32 *) &HubPortStatus
2162 );
2163 gBS->Stall (10 * 100);
2164 Number -= 1;
2165 } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Number > 0);
2166
2167 if (Number == 0) {
2168 //
2169 // Cannot reset port, return error
2170 //
2171 return EFI_DEVICE_ERROR;
2172 }
2173
2174 gBS->Stall (1000);
2175
2176 HubGetPortStatus (
2177 UsbIo,
2178 PortIndex,
2179 (UINT32 *) &HubPortStatus
2180 );
2181 //
2182 // reset port will cause some bits change, clear them
2183 //
2184 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
2185 DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
2186 HubClearPortFeature (
2187 UsbIo,
2188 PortIndex,
2189 EfiUsbPortEnableChange
2190 );
2191 }
2192
2193 if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
2194 DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
2195 HubClearPortFeature (
2196 UsbIo,
2197 PortIndex,
2198 EfiUsbPortResetChange
2199 );
2200 }
2201
2202 return EFI_SUCCESS;
2203 }
2204
2205
2206
2207
2208
2209 STATIC
2210 EFI_STATUS
2211 ReportUsbStatusCode (
2212 IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,
2213 IN EFI_STATUS_CODE_TYPE Type,
2214 IN EFI_STATUS_CODE_VALUE Code
2215 )
2216 /*++
2217
2218 Routine Description:
2219
2220 report a error Status code of USB bus driver controller
2221
2222 Arguments:
2223 UsbBusController - USB_BUS_CONTROLLER_DEVICE
2224 Type - EFI_STATUS_CODE_TYPE
2225 Code - EFI_STATUS_CODE_VALUE
2226 Returns:
2227
2228 None
2229
2230 --*/
2231 {
2232 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2233 Type,
2234 Code,
2235 UsbBusController->DevicePath
2236 );
2237 }
2238
2239
2240 EFI_STATUS
2241 IsDeviceDisconnected (
2242 IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
2243 IN OUT BOOLEAN *Disconnected
2244 )
2245 /*++
2246
2247 Routine Description:
2248 Reset if the device is disconencted or not
2249
2250 Arguments:
2251 UsbIoController - Indicating the Usb Controller Device.
2252 Disconnected - Indicate whether the device is disconencted or not
2253
2254 Returns:
2255 EFI_SUCCESS
2256 EFI_DEVICE_ERROR
2257
2258 --*/
2259 {
2260 USB_IO_DEVICE *ParentIoDev;
2261 USB_IO_DEVICE *UsbIoDev;
2262 USB_IO_CONTROLLER_DEVICE *ParentController;
2263 UINT8 HubPort;
2264 EFI_STATUS Status;
2265 EFI_USB_IO_PROTOCOL *UsbIo;
2266 EFI_USB_PORT_STATUS PortStatus;
2267 EFI_USB_HC_PROTOCOL *UsbHCInterface;
2268
2269 ParentController = UsbIoController->Parent;
2270 ParentIoDev = ParentController->UsbDevice;
2271 UsbIoDev = UsbIoController->UsbDevice;
2272 HubPort = UsbIoController->ParentPort;
2273
2274 if (ParentIoDev->DeviceAddress == 1) {
2275 //
2276 // Connected to the root hub
2277 //
2278 UsbHCInterface = ParentIoDev->BusController->UsbHCInterface;
2279 Status = UsbHCInterface->GetRootHubPortStatus (
2280 UsbHCInterface,
2281 HubPort,
2282 &PortStatus
2283 );
2284
2285 } else {
2286 UsbIo = &UsbIoController->UsbIo;
2287 Status = HubGetPortStatus (
2288 &ParentController->UsbIo,
2289 HubPort + 1,
2290 (UINT32 *) &PortStatus
2291 );
2292
2293 if (EFI_ERROR (Status)) {
2294 return IsDeviceDisconnected (ParentController, Disconnected);
2295 }
2296 }
2297
2298 *Disconnected = FALSE;
2299
2300 if (!IsPortConnect (PortStatus.PortStatus)) {
2301 *Disconnected = TRUE;
2302 }
2303
2304 return EFI_SUCCESS;
2305 }