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