]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
Enabling usb3.0 XHCI support.
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbBusDxe / UsbBus.c
1 /** @file
2
3 Usb Bus Driver Binding and Bus IO Protocol.
4
5 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "UsbBus.h"
17
18 //
19 // USB_BUS_PROTOCOL is only used to locate USB_BUS
20 //
21 EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;
22
23 EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
24 UsbIoControlTransfer,
25 UsbIoBulkTransfer,
26 UsbIoAsyncInterruptTransfer,
27 UsbIoSyncInterruptTransfer,
28 UsbIoIsochronousTransfer,
29 UsbIoAsyncIsochronousTransfer,
30 UsbIoGetDeviceDescriptor,
31 UsbIoGetActiveConfigDescriptor,
32 UsbIoGetInterfaceDescriptor,
33 UsbIoGetEndpointDescriptor,
34 UsbIoGetStringDescriptor,
35 UsbIoGetSupportedLanguages,
36 UsbIoPortReset
37 };
38
39 EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding = {
40 UsbBusControllerDriverSupported,
41 UsbBusControllerDriverStart,
42 UsbBusControllerDriverStop,
43 0xa,
44 NULL,
45 NULL
46 };
47
48 UINT16 mMaxUsbDeviceNum = USB_MAX_DEVICES;
49
50 /**
51 USB_IO function to execute a control transfer. This
52 function will execute the USB transfer. If transfer
53 successes, it will sync the internal state of USB bus
54 with device state.
55
56 @param This The USB_IO instance
57 @param Request The control transfer request
58 @param Direction Direction for data stage
59 @param Timeout The time to wait before timeout
60 @param Data The buffer holding the data
61 @param DataLength Then length of the data
62 @param UsbStatus USB result
63
64 @retval EFI_INVALID_PARAMETER The parameters are invalid
65 @retval EFI_SUCCESS The control transfer succeeded.
66 @retval Others Failed to execute the transfer
67
68 **/
69 EFI_STATUS
70 EFIAPI
71 UsbIoControlTransfer (
72 IN EFI_USB_IO_PROTOCOL *This,
73 IN EFI_USB_DEVICE_REQUEST *Request,
74 IN EFI_USB_DATA_DIRECTION Direction,
75 IN UINT32 Timeout,
76 IN OUT VOID *Data, OPTIONAL
77 IN UINTN DataLength, OPTIONAL
78 OUT UINT32 *UsbStatus
79 )
80 {
81 USB_DEVICE *Dev;
82 USB_INTERFACE *UsbIf;
83 USB_ENDPOINT_DESC *EpDesc;
84 EFI_TPL OldTpl;
85 EFI_STATUS Status;
86
87 if (UsbStatus == NULL) {
88 return EFI_INVALID_PARAMETER;
89 }
90
91 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
92
93 UsbIf = USB_INTERFACE_FROM_USBIO (This);
94 Dev = UsbIf->Device;
95
96 Status = UsbHcControlTransfer (
97 Dev->Bus,
98 Dev->Address,
99 Dev->Speed,
100 Dev->MaxPacket0,
101 Request,
102 Direction,
103 Data,
104 &DataLength,
105 (UINTN) Timeout,
106 &Dev->Translator,
107 UsbStatus
108 );
109
110 if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {
111 //
112 // Clear TT buffer when CTRL/BULK split transaction failes
113 // Clear the TRANSLATOR TT buffer, not parent's buffer
114 //
115 ASSERT (Dev->Translator.TranslatorHubAddress < mMaxUsbDeviceNum);
116 if (Dev->Translator.TranslatorHubAddress != 0) {
117 UsbHubCtrlClearTTBuffer (
118 Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
119 Dev->Translator.TranslatorPortNumber,
120 Dev->Address,
121 0,
122 USB_ENDPOINT_CONTROL
123 );
124 }
125
126 goto ON_EXIT;
127 }
128
129 //
130 // Some control transfer will change the device's internal
131 // status, such as Set_Configuration and Set_Interface.
132 // We must synchronize the bus driver's status with that in
133 // device. We ignore the Set_Descriptor request because it's
134 // hardly used by any device, especially in pre-boot environment
135 //
136
137 //
138 // Reset the endpoint toggle when endpoint stall is cleared
139 //
140 if ((Request->Request == USB_REQ_CLEAR_FEATURE) &&
141 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
142 USB_TARGET_ENDPOINT)) &&
143 (Request->Value == USB_FEATURE_ENDPOINT_HALT)) {
144
145 EpDesc = UsbGetEndpointDesc (UsbIf, (UINT8) Request->Index);
146
147 if (EpDesc != NULL) {
148 EpDesc->Toggle = 0;
149 }
150 }
151
152 //
153 // Select a new configuration. This is a dangerous action. Upper driver
154 // should stop use its current UsbIo after calling this driver. The old
155 // UsbIo will be uninstalled and new UsbIo be installed. We can't use
156 // ReinstallProtocol since interfaces in different configuration may be
157 // completely irrelevant.
158 //
159 if ((Request->Request == USB_REQ_SET_CONFIG) &&
160 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
161 USB_TARGET_DEVICE))) {
162 //
163 // Don't re-create the USB interfaces if configuration isn't changed.
164 //
165 if ((Dev->ActiveConfig != NULL) &&
166 (Request->Value == Dev->ActiveConfig->Desc.ConfigurationValue)) {
167
168 goto ON_EXIT;
169 }
170 DEBUG ((EFI_D_INFO, "UsbIoControlTransfer: configure changed!!! Do NOT use old UsbIo!!!\n"));
171
172 if (Dev->ActiveConfig != NULL) {
173 UsbRemoveConfig (Dev);
174 }
175
176 if (Request->Value != 0) {
177 Status = UsbSelectConfig (Dev, (UINT8) Request->Value);
178 }
179
180 //
181 // Exit now, Old USB_IO is invalid now
182 //
183 goto ON_EXIT;
184 }
185
186 //
187 // A new alternative setting is selected for the interface.
188 // No need to reinstall UsbIo in this case because only
189 // underlying communication endpoints are changed. Functionality
190 // should remains the same.
191 //
192 if ((Request->Request == USB_REQ_SET_INTERFACE) &&
193 (Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD,
194 USB_TARGET_INTERFACE)) &&
195 (Request->Index == UsbIf->IfSetting->Desc.InterfaceNumber)) {
196
197 Status = UsbSelectSetting (UsbIf->IfDesc, (UINT8) Request->Value);
198
199 if (!EFI_ERROR (Status)) {
200 ASSERT (UsbIf->IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING);
201 UsbIf->IfSetting = UsbIf->IfDesc->Settings[UsbIf->IfDesc->ActiveIndex];
202 }
203 }
204
205 ON_EXIT:
206 gBS->RestoreTPL (OldTpl);
207 return Status;
208 }
209
210
211 /**
212 Execute a bulk transfer to the device endpoint.
213
214 @param This The USB IO instance.
215 @param Endpoint The device endpoint.
216 @param Data The data to transfer.
217 @param DataLength The length of the data to transfer.
218 @param Timeout Time to wait before timeout.
219 @param UsbStatus The result of USB transfer.
220
221 @retval EFI_SUCCESS The bulk transfer is OK.
222 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
223 @retval Others Failed to execute transfer, reason returned in
224 UsbStatus.
225
226 **/
227 EFI_STATUS
228 EFIAPI
229 UsbIoBulkTransfer (
230 IN EFI_USB_IO_PROTOCOL *This,
231 IN UINT8 Endpoint,
232 IN OUT VOID *Data,
233 IN OUT UINTN *DataLength,
234 IN UINTN Timeout,
235 OUT UINT32 *UsbStatus
236 )
237 {
238 USB_DEVICE *Dev;
239 USB_INTERFACE *UsbIf;
240 USB_ENDPOINT_DESC *EpDesc;
241 UINT8 BufNum;
242 UINT8 Toggle;
243 EFI_TPL OldTpl;
244 EFI_STATUS Status;
245
246 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||
247 (UsbStatus == NULL)) {
248
249 return EFI_INVALID_PARAMETER;
250 }
251
252 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
253
254 UsbIf = USB_INTERFACE_FROM_USBIO (This);
255 Dev = UsbIf->Device;
256
257 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);
258
259 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_BULK)) {
260 Status = EFI_INVALID_PARAMETER;
261 goto ON_EXIT;
262 }
263
264 BufNum = 1;
265 Toggle = EpDesc->Toggle;
266 Status = UsbHcBulkTransfer (
267 Dev->Bus,
268 Dev->Address,
269 Endpoint,
270 Dev->Speed,
271 EpDesc->Desc.MaxPacketSize,
272 BufNum,
273 &Data,
274 DataLength,
275 &Toggle,
276 Timeout,
277 &Dev->Translator,
278 UsbStatus
279 );
280
281 EpDesc->Toggle = Toggle;
282
283 if (EFI_ERROR (Status) || (*UsbStatus != EFI_USB_NOERROR)) {
284 //
285 // Clear TT buffer when CTRL/BULK split transaction failes.
286 // Clear the TRANSLATOR TT buffer, not parent's buffer
287 //
288 ASSERT (Dev->Translator.TranslatorHubAddress < mMaxUsbDeviceNum);
289 if (Dev->Translator.TranslatorHubAddress != 0) {
290 UsbHubCtrlClearTTBuffer (
291 Dev->Bus->Devices[Dev->Translator.TranslatorHubAddress],
292 Dev->Translator.TranslatorPortNumber,
293 Dev->Address,
294 0,
295 USB_ENDPOINT_BULK
296 );
297 }
298 }
299
300 ON_EXIT:
301 gBS->RestoreTPL (OldTpl);
302 return Status;
303 }
304
305
306 /**
307 Execute a synchronous interrupt transfer.
308
309 @param This The USB IO instance.
310 @param Endpoint The device endpoint.
311 @param Data The data to transfer.
312 @param DataLength The length of the data to transfer.
313 @param Timeout Time to wait before timeout.
314 @param UsbStatus The result of USB transfer.
315
316 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
317 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
318 @retval Others Failed to execute transfer, reason returned in
319 UsbStatus.
320
321 **/
322 EFI_STATUS
323 EFIAPI
324 UsbIoSyncInterruptTransfer (
325 IN EFI_USB_IO_PROTOCOL *This,
326 IN UINT8 Endpoint,
327 IN OUT VOID *Data,
328 IN OUT UINTN *DataLength,
329 IN UINTN Timeout,
330 OUT UINT32 *UsbStatus
331 )
332 {
333 USB_DEVICE *Dev;
334 USB_INTERFACE *UsbIf;
335 USB_ENDPOINT_DESC *EpDesc;
336 EFI_TPL OldTpl;
337 UINT8 Toggle;
338 EFI_STATUS Status;
339
340 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR(Endpoint) > 15) ||
341 (UsbStatus == NULL)) {
342
343 return EFI_INVALID_PARAMETER;
344 }
345
346 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
347
348 UsbIf = USB_INTERFACE_FROM_USBIO (This);
349 Dev = UsbIf->Device;
350
351 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);
352
353 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {
354 Status = EFI_INVALID_PARAMETER;
355 goto ON_EXIT;
356 }
357
358 Toggle = EpDesc->Toggle;
359 Status = UsbHcSyncInterruptTransfer (
360 Dev->Bus,
361 Dev->Address,
362 Endpoint,
363 Dev->Speed,
364 EpDesc->Desc.MaxPacketSize,
365 Data,
366 DataLength,
367 &Toggle,
368 Timeout,
369 &Dev->Translator,
370 UsbStatus
371 );
372
373 EpDesc->Toggle = Toggle;
374
375 ON_EXIT:
376 gBS->RestoreTPL (OldTpl);
377 return Status;
378 }
379
380
381 /**
382 Queue a new asynchronous interrupt transfer, or remove the old
383 request if (IsNewTransfer == FALSE).
384
385 @param This The USB_IO instance.
386 @param Endpoint The device endpoint.
387 @param IsNewTransfer Whether this is a new request, if it's old, remove
388 the request.
389 @param PollInterval The interval to poll the transfer result, (in ms).
390 @param DataLength The length of perodic data transfer.
391 @param Callback The function to call periodicaly when transfer is
392 ready.
393 @param Context The context to the callback.
394
395 @retval EFI_SUCCESS New transfer is queued or old request is removed.
396 @retval EFI_INVALID_PARAMETER Some parameters are invalid.
397 @retval Others Failed to queue the new request or remove the old
398 request.
399
400 **/
401 EFI_STATUS
402 EFIAPI
403 UsbIoAsyncInterruptTransfer (
404 IN EFI_USB_IO_PROTOCOL *This,
405 IN UINT8 Endpoint,
406 IN BOOLEAN IsNewTransfer,
407 IN UINTN PollInterval, OPTIONAL
408 IN UINTN DataLength, OPTIONAL
409 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, OPTIONAL
410 IN VOID *Context OPTIONAL
411 )
412 {
413 USB_DEVICE *Dev;
414 USB_INTERFACE *UsbIf;
415 USB_ENDPOINT_DESC *EpDesc;
416 EFI_TPL OldTpl;
417 UINT8 Toggle;
418 EFI_STATUS Status;
419
420 if ((USB_ENDPOINT_ADDR (Endpoint) == 0) || (USB_ENDPOINT_ADDR (Endpoint) > 15)) {
421 return EFI_INVALID_PARAMETER;
422 }
423
424 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
425 UsbIf = USB_INTERFACE_FROM_USBIO (This);
426 Dev = UsbIf->Device;
427
428 EpDesc = UsbGetEndpointDesc (UsbIf, Endpoint);
429
430 if ((EpDesc == NULL) || (USB_ENDPOINT_TYPE (&EpDesc->Desc) != USB_ENDPOINT_INTERRUPT)) {
431 Status = EFI_INVALID_PARAMETER;
432 goto ON_EXIT;
433 }
434
435 Toggle = EpDesc->Toggle;
436 Status = UsbHcAsyncInterruptTransfer (
437 Dev->Bus,
438 Dev->Address,
439 Endpoint,
440 Dev->Speed,
441 EpDesc->Desc.MaxPacketSize,
442 IsNewTransfer,
443 &Toggle,
444 PollInterval,
445 DataLength,
446 &Dev->Translator,
447 Callback,
448 Context
449 );
450
451 EpDesc->Toggle = Toggle;
452
453 ON_EXIT:
454 gBS->RestoreTPL (OldTpl);
455 return Status;
456 }
457
458
459 /**
460 Execute a synchronous isochronous transfer.
461
462 @param This The USB IO instance.
463 @param DeviceEndpoint The device endpoint.
464 @param Data The data to transfer.
465 @param DataLength The length of the data to transfer.
466 @param UsbStatus The result of USB transfer.
467
468 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
469
470 **/
471 EFI_STATUS
472 EFIAPI
473 UsbIoIsochronousTransfer (
474 IN EFI_USB_IO_PROTOCOL *This,
475 IN UINT8 DeviceEndpoint,
476 IN OUT VOID *Data,
477 IN UINTN DataLength,
478 OUT UINT32 *Status
479 )
480 {
481 return EFI_UNSUPPORTED;
482 }
483
484
485 /**
486 Queue an asynchronous isochronous transfer.
487
488 @param This The USB_IO instance.
489 @param DeviceEndpoint The device endpoint.
490 @param Data The data to transfer.
491 @param DataLength The length of perodic data transfer.
492 @param IsochronousCallBack The function to call periodicaly when transfer is
493 ready.
494 @param Context The context to the callback.
495
496 @retval EFI_UNSUPPORTED Currently isochronous transfer isn't supported.
497
498 **/
499 EFI_STATUS
500 EFIAPI
501 UsbIoAsyncIsochronousTransfer (
502 IN EFI_USB_IO_PROTOCOL *This,
503 IN UINT8 DeviceEndpoint,
504 IN OUT VOID *Data,
505 IN UINTN DataLength,
506 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
507 IN VOID *Context OPTIONAL
508 )
509 {
510 return EFI_UNSUPPORTED;
511 }
512
513
514 /**
515 Retrieve the device descriptor of the device.
516
517 @param This The USB IO instance.
518 @param Descriptor The variable to receive the device descriptor.
519
520 @retval EFI_SUCCESS The device descriptor is returned.
521 @retval EFI_INVALID_PARAMETER The parameter is invalid.
522
523 **/
524 EFI_STATUS
525 EFIAPI
526 UsbIoGetDeviceDescriptor (
527 IN EFI_USB_IO_PROTOCOL *This,
528 OUT EFI_USB_DEVICE_DESCRIPTOR *Descriptor
529 )
530 {
531 USB_DEVICE *Dev;
532 USB_INTERFACE *UsbIf;
533 EFI_TPL OldTpl;
534
535 if (Descriptor == NULL) {
536 return EFI_INVALID_PARAMETER;
537 }
538
539 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
540
541 UsbIf = USB_INTERFACE_FROM_USBIO (This);
542 Dev = UsbIf->Device;
543
544 CopyMem (Descriptor, &Dev->DevDesc->Desc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
545
546 gBS->RestoreTPL (OldTpl);
547 return EFI_SUCCESS;
548 }
549
550
551 /**
552 Return the configuration descriptor of the current active configuration.
553
554 @param This The USB IO instance.
555 @param Descriptor The USB configuration descriptor.
556
557 @retval EFI_SUCCESS The active configuration descriptor is returned.
558 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
559 @retval EFI_NOT_FOUND Currently no active configuration is selected.
560
561 **/
562 EFI_STATUS
563 EFIAPI
564 UsbIoGetActiveConfigDescriptor (
565 IN EFI_USB_IO_PROTOCOL *This,
566 OUT EFI_USB_CONFIG_DESCRIPTOR *Descriptor
567 )
568 {
569 USB_DEVICE *Dev;
570 USB_INTERFACE *UsbIf;
571 EFI_STATUS Status;
572 EFI_TPL OldTpl;
573
574 if (Descriptor == NULL) {
575 return EFI_INVALID_PARAMETER;
576 }
577
578 Status = EFI_SUCCESS;
579 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
580
581 UsbIf = USB_INTERFACE_FROM_USBIO (This);
582 Dev = UsbIf->Device;
583
584 if (Dev->ActiveConfig == NULL) {
585 Status = EFI_NOT_FOUND;
586 goto ON_EXIT;
587 }
588
589 CopyMem (Descriptor, &(Dev->ActiveConfig->Desc), sizeof (EFI_USB_CONFIG_DESCRIPTOR));
590
591 ON_EXIT:
592 gBS->RestoreTPL (OldTpl);
593 return Status;
594 }
595
596
597 /**
598 Retrieve the active interface setting descriptor for this USB IO instance.
599
600 @param This The USB IO instance.
601 @param Descriptor The variable to receive active interface setting.
602
603 @retval EFI_SUCCESS The active interface setting is returned.
604 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
605
606 **/
607 EFI_STATUS
608 EFIAPI
609 UsbIoGetInterfaceDescriptor (
610 IN EFI_USB_IO_PROTOCOL *This,
611 OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor
612 )
613 {
614 USB_INTERFACE *UsbIf;
615 EFI_TPL OldTpl;
616
617 if (Descriptor == NULL) {
618 return EFI_INVALID_PARAMETER;
619 }
620
621 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
622
623 UsbIf = USB_INTERFACE_FROM_USBIO (This);
624 CopyMem (Descriptor, &(UsbIf->IfSetting->Desc), sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
625
626 gBS->RestoreTPL (OldTpl);
627 return EFI_SUCCESS;
628 }
629
630
631 /**
632 Retrieve the endpoint descriptor from this interface setting.
633
634 @param This The USB IO instance.
635 @param Index The index (start from zero) of the endpoint to
636 retrieve.
637 @param Descriptor The variable to receive the descriptor.
638
639 @retval EFI_SUCCESS The endpoint descriptor is returned.
640 @retval EFI_INVALID_PARAMETER Some parameter is invalid.
641
642 **/
643 EFI_STATUS
644 EFIAPI
645 UsbIoGetEndpointDescriptor (
646 IN EFI_USB_IO_PROTOCOL *This,
647 IN UINT8 Index,
648 OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor
649 )
650 {
651 USB_INTERFACE *UsbIf;
652 EFI_TPL OldTpl;
653
654 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
655
656 UsbIf = USB_INTERFACE_FROM_USBIO (This);
657
658 if ((Descriptor == NULL) || (Index > 15)) {
659 gBS->RestoreTPL (OldTpl);
660 return EFI_INVALID_PARAMETER;
661 }
662
663 if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {
664 gBS->RestoreTPL (OldTpl);
665 return EFI_NOT_FOUND;
666 }
667
668 CopyMem (
669 Descriptor,
670 &(UsbIf->IfSetting->Endpoints[Index]->Desc),
671 sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
672 );
673
674 gBS->RestoreTPL (OldTpl);
675 return EFI_SUCCESS;
676 }
677
678
679 /**
680 Retrieve the supported language ID table from the device.
681
682 @param This The USB IO instance.
683 @param LangIDTable The table to return the language IDs.
684 @param TableSize The size, in bytes, of the table LangIDTable.
685
686 @retval EFI_SUCCESS The language ID is return.
687
688 **/
689 EFI_STATUS
690 EFIAPI
691 UsbIoGetSupportedLanguages (
692 IN EFI_USB_IO_PROTOCOL *This,
693 OUT UINT16 **LangIDTable,
694 OUT UINT16 *TableSize
695 )
696 {
697 USB_DEVICE *Dev;
698 USB_INTERFACE *UsbIf;
699 EFI_TPL OldTpl;
700
701 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
702
703 UsbIf = USB_INTERFACE_FROM_USBIO (This);
704 Dev = UsbIf->Device;
705
706 *LangIDTable = Dev->LangId;
707 *TableSize = (UINT16) (Dev->TotalLangId * sizeof (UINT16));
708
709 gBS->RestoreTPL (OldTpl);
710 return EFI_SUCCESS;
711 }
712
713
714 /**
715 Retrieve an indexed string in the language of LangID.
716
717 @param This The USB IO instance.
718 @param LangID The language ID of the string to retrieve.
719 @param StringIndex The index of the string.
720 @param String The variable to receive the string.
721
722 @retval EFI_SUCCESS The string is returned.
723 @retval EFI_NOT_FOUND No such string existed.
724
725 **/
726 EFI_STATUS
727 EFIAPI
728 UsbIoGetStringDescriptor (
729 IN EFI_USB_IO_PROTOCOL *This,
730 IN UINT16 LangID,
731 IN UINT8 StringIndex,
732 OUT CHAR16 **String
733 )
734 {
735 USB_DEVICE *Dev;
736 USB_INTERFACE *UsbIf;
737 EFI_USB_STRING_DESCRIPTOR *StrDesc;
738 EFI_TPL OldTpl;
739 UINT8 *Buf;
740 UINT8 Index;
741 EFI_STATUS Status;
742
743 if ((StringIndex == 0) || (LangID == 0)) {
744 return EFI_NOT_FOUND;
745 }
746
747 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
748
749 UsbIf = USB_INTERFACE_FROM_USBIO (This);
750 Dev = UsbIf->Device;
751
752 //
753 // Check whether language ID is supported
754 //
755 Status = EFI_NOT_FOUND;
756
757 for (Index = 0; Index < Dev->TotalLangId; Index++) {
758 ASSERT (Index < USB_MAX_LANG_ID);
759 if (Dev->LangId[Index] == LangID) {
760 break;
761 }
762 }
763
764 if (Index == Dev->TotalLangId) {
765 goto ON_EXIT;
766 }
767
768 //
769 // Retrieve the string descriptor then allocate a buffer
770 // to hold the string itself.
771 //
772 StrDesc = UsbGetOneString (Dev, StringIndex, LangID);
773
774 if (StrDesc == NULL) {
775 goto ON_EXIT;
776 }
777
778 if (StrDesc->Length <= 2) {
779 goto FREE_STR;
780 }
781
782 Buf = AllocateZeroPool (StrDesc->Length);
783
784 if (Buf == NULL) {
785 Status = EFI_OUT_OF_RESOURCES;
786 goto FREE_STR;
787 }
788
789 CopyMem (Buf, StrDesc->String, StrDesc->Length - 2);
790 *String = (CHAR16 *) Buf;
791 Status = EFI_SUCCESS;
792
793 FREE_STR:
794 gBS->FreePool (StrDesc);
795
796 ON_EXIT:
797 gBS->RestoreTPL (OldTpl);
798 return Status;
799 }
800
801
802 /**
803 Reset the device, then if that succeeds, reconfigure the
804 device with its address and current active configuration.
805
806 @param This The USB IO instance.
807
808 @retval EFI_SUCCESS The device is reset and configured.
809 @retval Others Failed to reset the device.
810
811 **/
812 EFI_STATUS
813 EFIAPI
814 UsbIoPortReset (
815 IN EFI_USB_IO_PROTOCOL *This
816 )
817 {
818 USB_INTERFACE *UsbIf;
819 USB_INTERFACE *HubIf;
820 USB_DEVICE *Dev;
821 UINT8 Address;
822 EFI_TPL OldTpl;
823 EFI_STATUS Status;
824
825 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
826
827 UsbIf = USB_INTERFACE_FROM_USBIO (This);
828 Dev = UsbIf->Device;
829
830 if (UsbIf->IsHub) {
831 Status = EFI_INVALID_PARAMETER;
832 goto ON_EXIT;
833 }
834
835 HubIf = Dev->ParentIf;
836 Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
837
838 if (EFI_ERROR (Status)) {
839 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
840 Dev->ParentPort, Dev->ParentAddr, Status));
841
842 goto ON_EXIT;
843 }
844
845 //
846 // Reset the device to its current address. The device now has a
847 // address of ZERO, so need to set Dev->Address to zero first for
848 // host to communicate with the device
849 //
850 Address = Dev->Address;
851 Dev->Address = 0;
852 Status = UsbSetAddress (Dev, Address);
853
854 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
855
856 if (EFI_ERROR (Status)) {
857 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",
858 Address, Status));
859
860 goto ON_EXIT;
861 }
862
863 Dev->Address = Address;
864
865 DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Address));
866
867 //
868 // Reset the current active configure, after this device
869 // is in CONFIGURED state.
870 //
871 if (Dev->ActiveConfig != NULL) {
872 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);
873
874 if (EFI_ERROR (Status)) {
875 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",
876 Address, Status));
877 }
878 }
879
880 ON_EXIT:
881 gBS->RestoreTPL (OldTpl);
882 return Status;
883 }
884
885
886 /**
887 Install Usb Bus Protocol on host controller, and start the Usb bus.
888
889 @param This The USB bus driver binding instance.
890 @param Controller The controller to check.
891 @param RemainingDevicePath The remaining device patch.
892
893 @retval EFI_SUCCESS The controller is controlled by the usb bus.
894 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
895 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
896
897 **/
898 EFI_STATUS
899 EFIAPI
900 UsbBusBuildProtocol (
901 IN EFI_DRIVER_BINDING_PROTOCOL *This,
902 IN EFI_HANDLE Controller,
903 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
904 )
905 {
906 USB_BUS *UsbBus;
907 USB_DEVICE *RootHub;
908 USB_INTERFACE *RootIf;
909 EFI_STATUS Status;
910 EFI_STATUS Status2;
911
912 UsbBus = AllocateZeroPool (sizeof (USB_BUS));
913
914 if (UsbBus == NULL) {
915 return EFI_OUT_OF_RESOURCES;
916 }
917
918 UsbBus->Signature = USB_BUS_SIGNATURE;
919 UsbBus->HostHandle = Controller;
920
921 Status = gBS->OpenProtocol (
922 Controller,
923 &gEfiDevicePathProtocolGuid,
924 (VOID **) &UsbBus->DevicePath,
925 This->DriverBindingHandle,
926 Controller,
927 EFI_OPEN_PROTOCOL_BY_DRIVER
928 );
929
930 if (EFI_ERROR (Status)) {
931 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
932
933 FreePool (UsbBus);
934 return Status;
935 }
936
937 //
938 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
939 // This is for backward compatibility with EFI 1.x. In UEFI
940 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
941 // and USB_HC because EHCI driver will install both protocols
942 // (for the same reason). If we don't consume both of them,
943 // the unconsumed one may be opened by others.
944 //
945 Status = gBS->OpenProtocol (
946 Controller,
947 &gEfiUsb2HcProtocolGuid,
948 (VOID **) &(UsbBus->Usb2Hc),
949 This->DriverBindingHandle,
950 Controller,
951 EFI_OPEN_PROTOCOL_BY_DRIVER
952 );
953
954 Status2 = gBS->OpenProtocol (
955 Controller,
956 &gEfiUsbHcProtocolGuid,
957 (VOID **) &(UsbBus->UsbHc),
958 This->DriverBindingHandle,
959 Controller,
960 EFI_OPEN_PROTOCOL_BY_DRIVER
961 );
962
963 if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
964 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
965
966 Status = EFI_DEVICE_ERROR;
967 goto CLOSE_HC;
968 }
969
970 if (!EFI_ERROR (Status)) {
971 if (UsbBus->Usb2Hc->MajorRevision == 0x3) {
972 //
973 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
974 // Then its max supported devices are 256.
975 //
976 mMaxUsbDeviceNum = 256;
977 }
978 }
979
980 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
981 UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
982
983 //
984 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
985 //
986 Status = gBS->InstallProtocolInterface (
987 &Controller,
988 &mUsbBusProtocolGuid,
989 EFI_NATIVE_INTERFACE,
990 &UsbBus->BusId
991 );
992
993 if (EFI_ERROR (Status)) {
994 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
995 goto CLOSE_HC;
996 }
997
998 //
999 // Initial the wanted child device path list, and add first RemainingDevicePath
1000 //
1001 InitializeListHead (&UsbBus->WantedUsbIoDPList);
1002 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
1003 ASSERT (!EFI_ERROR (Status));
1004 //
1005 // Create a fake usb device for root hub
1006 //
1007 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
1008
1009 if (RootHub == NULL) {
1010 Status = EFI_OUT_OF_RESOURCES;
1011 goto UNINSTALL_USBBUS;
1012 }
1013
1014 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
1015
1016 if (RootIf == NULL) {
1017 FreePool (RootHub);
1018 Status = EFI_OUT_OF_RESOURCES;
1019 goto FREE_ROOTHUB;
1020 }
1021
1022 RootHub->Bus = UsbBus;
1023 RootHub->NumOfInterface = 1;
1024 RootHub->Interfaces[0] = RootIf;
1025 RootHub->Tier = 0;
1026 RootIf->Signature = USB_INTERFACE_SIGNATURE;
1027 RootIf->Device = RootHub;
1028 RootIf->DevicePath = UsbBus->DevicePath;
1029
1030 Status = mUsbRootHubApi.Init (RootIf);
1031
1032 if (EFI_ERROR (Status)) {
1033 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
1034 goto FREE_ROOTHUB;
1035 }
1036
1037 UsbBus->Devices[0] = RootHub;
1038
1039 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));
1040 return EFI_SUCCESS;
1041
1042 FREE_ROOTHUB:
1043 if (RootIf != NULL) {
1044 FreePool (RootIf);
1045 }
1046 if (RootHub != NULL) {
1047 FreePool (RootHub);
1048 }
1049
1050 UNINSTALL_USBBUS:
1051 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
1052
1053 CLOSE_HC:
1054 if (UsbBus->Usb2Hc != NULL) {
1055 gBS->CloseProtocol (
1056 Controller,
1057 &gEfiUsb2HcProtocolGuid,
1058 This->DriverBindingHandle,
1059 Controller
1060 );
1061 }
1062 if (UsbBus->UsbHc != NULL) {
1063 gBS->CloseProtocol (
1064 Controller,
1065 &gEfiUsbHcProtocolGuid,
1066 This->DriverBindingHandle,
1067 Controller
1068 );
1069 }
1070 gBS->CloseProtocol (
1071 Controller,
1072 &gEfiDevicePathProtocolGuid,
1073 This->DriverBindingHandle,
1074 Controller
1075 );
1076 FreePool (UsbBus);
1077
1078 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
1079 return Status;
1080 }
1081
1082
1083 /**
1084 The USB bus driver entry pointer.
1085
1086 @param ImageHandle The driver image handle.
1087 @param SystemTable The system table.
1088
1089 @return EFI_SUCCESS The component name protocol is installed.
1090 @return Others Failed to init the usb driver.
1091
1092 **/
1093 EFI_STATUS
1094 EFIAPI
1095 UsbBusDriverEntryPoint (
1096 IN EFI_HANDLE ImageHandle,
1097 IN EFI_SYSTEM_TABLE *SystemTable
1098 )
1099 {
1100 return EfiLibInstallDriverBindingComponentName2 (
1101 ImageHandle,
1102 SystemTable,
1103 &mUsbBusDriverBinding,
1104 ImageHandle,
1105 &mUsbBusComponentName,
1106 &mUsbBusComponentName2
1107 );
1108 }
1109
1110
1111 /**
1112 Check whether USB bus driver support this device.
1113
1114 @param This The USB bus driver binding protocol.
1115 @param Controller The controller handle to check.
1116 @param RemainingDevicePath The remaining device path.
1117
1118 @retval EFI_SUCCESS The bus supports this controller.
1119 @retval EFI_UNSUPPORTED This device isn't supported.
1120
1121 **/
1122 EFI_STATUS
1123 EFIAPI
1124 UsbBusControllerDriverSupported (
1125 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1126 IN EFI_HANDLE Controller,
1127 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1128 )
1129 {
1130 EFI_DEV_PATH_PTR DevicePathNode;
1131 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1132 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1133 EFI_USB_HC_PROTOCOL *UsbHc;
1134 EFI_STATUS Status;
1135
1136 //
1137 // Check whether device path is valid
1138 //
1139 if (RemainingDevicePath != NULL) {
1140 //
1141 // Check if RemainingDevicePath is the End of Device Path Node,
1142 // if yes, go on checking other conditions
1143 //
1144 if (!IsDevicePathEnd (RemainingDevicePath)) {
1145 //
1146 // If RemainingDevicePath isn't the End of Device Path Node,
1147 // check its validation
1148 //
1149 DevicePathNode.DevPath = RemainingDevicePath;
1150
1151 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
1152 (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
1153 DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
1154 && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
1155 )) {
1156
1157 return EFI_UNSUPPORTED;
1158 }
1159 }
1160 }
1161
1162 //
1163 // Check whether USB_HC2 protocol is installed
1164 //
1165 Status = gBS->OpenProtocol (
1166 Controller,
1167 &gEfiUsb2HcProtocolGuid,
1168 (VOID **) &Usb2Hc,
1169 This->DriverBindingHandle,
1170 Controller,
1171 EFI_OPEN_PROTOCOL_BY_DRIVER
1172 );
1173 if (Status == EFI_ALREADY_STARTED) {
1174 return EFI_SUCCESS;
1175 }
1176
1177 if (EFI_ERROR (Status)) {
1178 //
1179 // If failed to open USB_HC2, fall back to USB_HC
1180 //
1181 Status = gBS->OpenProtocol (
1182 Controller,
1183 &gEfiUsbHcProtocolGuid,
1184 (VOID **) &UsbHc,
1185 This->DriverBindingHandle,
1186 Controller,
1187 EFI_OPEN_PROTOCOL_BY_DRIVER
1188 );
1189 if (Status == EFI_ALREADY_STARTED) {
1190 return EFI_SUCCESS;
1191 }
1192
1193 if (EFI_ERROR (Status)) {
1194 return Status;
1195 }
1196
1197 //
1198 // Close the USB_HC used to perform the supported test
1199 //
1200 gBS->CloseProtocol (
1201 Controller,
1202 &gEfiUsbHcProtocolGuid,
1203 This->DriverBindingHandle,
1204 Controller
1205 );
1206
1207 } else {
1208
1209 //
1210 // Close the USB_HC2 used to perform the supported test
1211 //
1212 gBS->CloseProtocol (
1213 Controller,
1214 &gEfiUsb2HcProtocolGuid,
1215 This->DriverBindingHandle,
1216 Controller
1217 );
1218 }
1219
1220 //
1221 // Open the EFI Device Path protocol needed to perform the supported test
1222 //
1223 Status = gBS->OpenProtocol (
1224 Controller,
1225 &gEfiDevicePathProtocolGuid,
1226 (VOID **) &ParentDevicePath,
1227 This->DriverBindingHandle,
1228 Controller,
1229 EFI_OPEN_PROTOCOL_BY_DRIVER
1230 );
1231 if (Status == EFI_ALREADY_STARTED) {
1232 return EFI_SUCCESS;
1233 }
1234
1235 if (!EFI_ERROR (Status)) {
1236 //
1237 // Close protocol, don't use device path protocol in the Support() function
1238 //
1239 gBS->CloseProtocol (
1240 Controller,
1241 &gEfiDevicePathProtocolGuid,
1242 This->DriverBindingHandle,
1243 Controller
1244 );
1245
1246 return EFI_SUCCESS;
1247 }
1248
1249 return Status;
1250 }
1251
1252
1253 /**
1254 Start to process the controller.
1255
1256 @param This The USB bus driver binding instance.
1257 @param Controller The controller to check.
1258 @param RemainingDevicePath The remaining device patch.
1259
1260 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1261 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1262 bus.
1263 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1264
1265 **/
1266 EFI_STATUS
1267 EFIAPI
1268 UsbBusControllerDriverStart (
1269 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1270 IN EFI_HANDLE Controller,
1271 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1272 )
1273 {
1274 EFI_USB_BUS_PROTOCOL *UsbBusId;
1275 EFI_STATUS Status;
1276
1277 //
1278 // Locate the USB bus protocol, if it is found, USB bus
1279 // is already started on this controller.
1280 //
1281 Status = gBS->OpenProtocol (
1282 Controller,
1283 &mUsbBusProtocolGuid,
1284 (VOID **) &UsbBusId,
1285 This->DriverBindingHandle,
1286 Controller,
1287 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1288 );
1289
1290 if (EFI_ERROR (Status)) {
1291 //
1292 // If first start, build the bus execute environment and install bus protocol
1293 //
1294 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));
1295 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
1296 if (EFI_ERROR (Status)) {
1297 return Status;
1298 }
1299 //
1300 // Try get the Usb Bus protocol interface again
1301 //
1302 Status = gBS->OpenProtocol (
1303 Controller,
1304 &mUsbBusProtocolGuid,
1305 (VOID **) &UsbBusId,
1306 This->DriverBindingHandle,
1307 Controller,
1308 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1309 );
1310 ASSERT (!EFI_ERROR (Status));
1311 } else {
1312 //
1313 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1314 // usb child device will be recursively connected.
1315 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1316 // All wanted usb child devices will be remembered by the usb bus driver itself.
1317 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1318 //
1319 // Save the passed in RemainingDevicePath this time
1320 //
1321 if (RemainingDevicePath != NULL) {
1322 if (IsDevicePathEnd (RemainingDevicePath)) {
1323 //
1324 // If RemainingDevicePath is the End of Device Path Node,
1325 // skip enumerate any device and return EFI_SUCESSS
1326 //
1327 return EFI_SUCCESS;
1328 }
1329 }
1330
1331 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
1332 ASSERT (!EFI_ERROR (Status));
1333 //
1334 // Ensure all wanted child usb devices are fully recursively connected
1335 //
1336 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
1337 ASSERT (!EFI_ERROR (Status));
1338 }
1339
1340
1341 return EFI_SUCCESS;
1342 }
1343
1344
1345 /**
1346 Stop handle the controller by this USB bus driver.
1347
1348 @param This The USB bus driver binding protocol.
1349 @param Controller The controller to release.
1350 @param NumberOfChildren The child of USB bus that opened controller
1351 BY_CHILD.
1352 @param ChildHandleBuffer The array of child handle.
1353
1354 @retval EFI_SUCCESS The controller or children are stopped.
1355 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1356
1357 **/
1358 EFI_STATUS
1359 EFIAPI
1360 UsbBusControllerDriverStop (
1361 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1362 IN EFI_HANDLE Controller,
1363 IN UINTN NumberOfChildren,
1364 IN EFI_HANDLE *ChildHandleBuffer
1365 )
1366 {
1367 USB_BUS *Bus;
1368 USB_DEVICE *RootHub;
1369 USB_DEVICE *UsbDev;
1370 USB_INTERFACE *RootIf;
1371 USB_INTERFACE *UsbIf;
1372 EFI_USB_BUS_PROTOCOL *BusId;
1373 EFI_USB_IO_PROTOCOL *UsbIo;
1374 EFI_TPL OldTpl;
1375 UINTN Index;
1376 EFI_STATUS Status;
1377
1378 Status = EFI_SUCCESS;
1379
1380 if (NumberOfChildren > 0) {
1381 //
1382 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1383 //
1384 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1385
1386 for (Index = 0; Index < NumberOfChildren; Index++) {
1387 Status = gBS->OpenProtocol (
1388 ChildHandleBuffer[Index],
1389 &gEfiUsbIoProtocolGuid,
1390 (VOID **) &UsbIo,
1391 This->DriverBindingHandle,
1392 Controller,
1393 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1394 );
1395
1396 if (EFI_ERROR (Status)) {
1397 //
1398 // It is possible that the child has already been released:
1399 // 1. For combo device, free one device will release others.
1400 // 2. If a hub is released, all devices on its down facing
1401 // ports are released also.
1402 //
1403 continue;
1404 }
1405
1406 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);
1407 UsbDev = UsbIf->Device;
1408
1409 UsbRemoveDevice (UsbDev);
1410 }
1411
1412 gBS->RestoreTPL (OldTpl);
1413 return EFI_SUCCESS;
1414 }
1415
1416 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));
1417
1418 //
1419 // Locate USB_BUS for the current host controller
1420 //
1421 Status = gBS->OpenProtocol (
1422 Controller,
1423 &mUsbBusProtocolGuid,
1424 (VOID **) &BusId,
1425 This->DriverBindingHandle,
1426 Controller,
1427 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1428 );
1429
1430 if (EFI_ERROR (Status)) {
1431 return Status;
1432 }
1433
1434 Bus = USB_BUS_FROM_THIS (BusId);
1435
1436 //
1437 // Stop the root hub, then free all the devices
1438 //
1439 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1440 //
1441 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1442 UsbHcSetState (Bus, EfiUsbHcStateHalt);
1443
1444 RootHub = Bus->Devices[0];
1445 RootIf = RootHub->Interfaces[0];
1446
1447 mUsbRootHubApi.Release (RootIf);
1448
1449 for (Index = 1; Index < mMaxUsbDeviceNum; Index++) {
1450 if (Bus->Devices[Index] != NULL) {
1451 UsbRemoveDevice (Bus->Devices[Index]);
1452 }
1453 }
1454
1455 gBS->RestoreTPL (OldTpl);
1456
1457 gBS->FreePool (RootIf);
1458 gBS->FreePool (RootHub);
1459 Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
1460 ASSERT (!EFI_ERROR (Status));
1461
1462 //
1463 // Uninstall the bus identifier and close USB_HC/USB2_HC protocols
1464 //
1465 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &Bus->BusId);
1466
1467 if (Bus->Usb2Hc != NULL) {
1468 gBS->CloseProtocol (
1469 Controller,
1470 &gEfiUsb2HcProtocolGuid,
1471 This->DriverBindingHandle,
1472 Controller
1473 );
1474 }
1475
1476 if (Bus->UsbHc != NULL) {
1477 gBS->CloseProtocol (
1478 Controller,
1479 &gEfiUsbHcProtocolGuid,
1480 This->DriverBindingHandle,
1481 Controller
1482 );
1483 }
1484
1485 gBS->CloseProtocol (
1486 Controller,
1487 &gEfiDevicePathProtocolGuid,
1488 This->DriverBindingHandle,
1489 Controller
1490 );
1491
1492 gBS->FreePool (Bus);
1493
1494 return Status;
1495 }