]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
Error handling refinement at UsbIoResetPort() to avoid device state machine getting...
[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 EFI_TPL OldTpl;
822 EFI_STATUS Status;
823
824 OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
825
826 UsbIf = USB_INTERFACE_FROM_USBIO (This);
827 Dev = UsbIf->Device;
828
829 if (UsbIf->IsHub) {
830 Status = EFI_INVALID_PARAMETER;
831 goto ON_EXIT;
832 }
833
834 HubIf = Dev->ParentIf;
835 Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
836
837 if (EFI_ERROR (Status)) {
838 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to reset hub port %d@hub %d, %r \n",
839 Dev->ParentPort, Dev->ParentAddr, Status));
840
841 goto ON_EXIT;
842 }
843
844 //
845 // Reset the device to its current address. The device now has an address
846 // of ZERO after port reset, so need to set Dev->Address to the device again for
847 // host to communicate with it.
848 //
849 Status = UsbSetAddress (Dev, Dev->Address);
850
851 gBS->Stall (USB_SET_DEVICE_ADDRESS_STALL);
852
853 if (EFI_ERROR (Status)) {
854 //
855 // It may fail due to device disconnection or other reasons.
856 //
857 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set address for device %d - %r\n",
858 Dev->Address, Status));
859
860 goto ON_EXIT;
861 }
862
863 DEBUG (( EFI_D_INFO, "UsbIoPortReset: device is now ADDRESSED at %d\n", Dev->Address));
864
865 //
866 // Reset the current active configure, after this device
867 // is in CONFIGURED state.
868 //
869 if (Dev->ActiveConfig != NULL) {
870 Status = UsbSetConfig (Dev, Dev->ActiveConfig->Desc.ConfigurationValue);
871
872 if (EFI_ERROR (Status)) {
873 DEBUG (( EFI_D_ERROR, "UsbIoPortReset: failed to set configure for device %d - %r\n",
874 Dev->Address, Status));
875 }
876 }
877
878 ON_EXIT:
879 gBS->RestoreTPL (OldTpl);
880 return Status;
881 }
882
883
884 /**
885 Install Usb Bus Protocol on host controller, and start the Usb bus.
886
887 @param This The USB bus driver binding instance.
888 @param Controller The controller to check.
889 @param RemainingDevicePath The remaining device patch.
890
891 @retval EFI_SUCCESS The controller is controlled by the usb bus.
892 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus.
893 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
894
895 **/
896 EFI_STATUS
897 EFIAPI
898 UsbBusBuildProtocol (
899 IN EFI_DRIVER_BINDING_PROTOCOL *This,
900 IN EFI_HANDLE Controller,
901 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
902 )
903 {
904 USB_BUS *UsbBus;
905 USB_DEVICE *RootHub;
906 USB_INTERFACE *RootIf;
907 EFI_STATUS Status;
908 EFI_STATUS Status2;
909
910 UsbBus = AllocateZeroPool (sizeof (USB_BUS));
911
912 if (UsbBus == NULL) {
913 return EFI_OUT_OF_RESOURCES;
914 }
915
916 UsbBus->Signature = USB_BUS_SIGNATURE;
917 UsbBus->HostHandle = Controller;
918
919 Status = gBS->OpenProtocol (
920 Controller,
921 &gEfiDevicePathProtocolGuid,
922 (VOID **) &UsbBus->DevicePath,
923 This->DriverBindingHandle,
924 Controller,
925 EFI_OPEN_PROTOCOL_BY_DRIVER
926 );
927
928 if (EFI_ERROR (Status)) {
929 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
930
931 FreePool (UsbBus);
932 return Status;
933 }
934
935 //
936 // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
937 // This is for backward compatibility with EFI 1.x. In UEFI
938 // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
939 // and USB_HC because EHCI driver will install both protocols
940 // (for the same reason). If we don't consume both of them,
941 // the unconsumed one may be opened by others.
942 //
943 Status = gBS->OpenProtocol (
944 Controller,
945 &gEfiUsb2HcProtocolGuid,
946 (VOID **) &(UsbBus->Usb2Hc),
947 This->DriverBindingHandle,
948 Controller,
949 EFI_OPEN_PROTOCOL_BY_DRIVER
950 );
951
952 Status2 = gBS->OpenProtocol (
953 Controller,
954 &gEfiUsbHcProtocolGuid,
955 (VOID **) &(UsbBus->UsbHc),
956 This->DriverBindingHandle,
957 Controller,
958 EFI_OPEN_PROTOCOL_BY_DRIVER
959 );
960
961 if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
962 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
963
964 Status = EFI_DEVICE_ERROR;
965 goto CLOSE_HC;
966 }
967
968 if (!EFI_ERROR (Status)) {
969 if (UsbBus->Usb2Hc->MajorRevision == 0x3) {
970 //
971 // The EFI_USB2_HC_PROTOCOL is produced for XHCI support.
972 // Then its max supported devices are 256.
973 //
974 mMaxUsbDeviceNum = 256;
975 }
976 }
977
978 UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
979 UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
980
981 //
982 // Install an EFI_USB_BUS_PROTOCOL to host controller to identify it.
983 //
984 Status = gBS->InstallProtocolInterface (
985 &Controller,
986 &mUsbBusProtocolGuid,
987 EFI_NATIVE_INTERFACE,
988 &UsbBus->BusId
989 );
990
991 if (EFI_ERROR (Status)) {
992 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
993 goto CLOSE_HC;
994 }
995
996 //
997 // Initial the wanted child device path list, and add first RemainingDevicePath
998 //
999 InitializeListHead (&UsbBus->WantedUsbIoDPList);
1000 Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
1001 ASSERT (!EFI_ERROR (Status));
1002 //
1003 // Create a fake usb device for root hub
1004 //
1005 RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
1006
1007 if (RootHub == NULL) {
1008 Status = EFI_OUT_OF_RESOURCES;
1009 goto UNINSTALL_USBBUS;
1010 }
1011
1012 RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
1013
1014 if (RootIf == NULL) {
1015 FreePool (RootHub);
1016 Status = EFI_OUT_OF_RESOURCES;
1017 goto FREE_ROOTHUB;
1018 }
1019
1020 RootHub->Bus = UsbBus;
1021 RootHub->NumOfInterface = 1;
1022 RootHub->Interfaces[0] = RootIf;
1023 RootHub->Tier = 0;
1024 RootIf->Signature = USB_INTERFACE_SIGNATURE;
1025 RootIf->Device = RootHub;
1026 RootIf->DevicePath = UsbBus->DevicePath;
1027
1028 Status = mUsbRootHubApi.Init (RootIf);
1029
1030 if (EFI_ERROR (Status)) {
1031 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
1032 goto FREE_ROOTHUB;
1033 }
1034
1035 UsbBus->Devices[0] = RootHub;
1036
1037 DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %p, root hub %p\n", Controller, RootIf));
1038 return EFI_SUCCESS;
1039
1040 FREE_ROOTHUB:
1041 if (RootIf != NULL) {
1042 FreePool (RootIf);
1043 }
1044 if (RootHub != NULL) {
1045 FreePool (RootHub);
1046 }
1047
1048 UNINSTALL_USBBUS:
1049 gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
1050
1051 CLOSE_HC:
1052 if (UsbBus->Usb2Hc != NULL) {
1053 gBS->CloseProtocol (
1054 Controller,
1055 &gEfiUsb2HcProtocolGuid,
1056 This->DriverBindingHandle,
1057 Controller
1058 );
1059 }
1060 if (UsbBus->UsbHc != NULL) {
1061 gBS->CloseProtocol (
1062 Controller,
1063 &gEfiUsbHcProtocolGuid,
1064 This->DriverBindingHandle,
1065 Controller
1066 );
1067 }
1068 gBS->CloseProtocol (
1069 Controller,
1070 &gEfiDevicePathProtocolGuid,
1071 This->DriverBindingHandle,
1072 Controller
1073 );
1074 FreePool (UsbBus);
1075
1076 DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
1077 return Status;
1078 }
1079
1080
1081 /**
1082 The USB bus driver entry pointer.
1083
1084 @param ImageHandle The driver image handle.
1085 @param SystemTable The system table.
1086
1087 @return EFI_SUCCESS The component name protocol is installed.
1088 @return Others Failed to init the usb driver.
1089
1090 **/
1091 EFI_STATUS
1092 EFIAPI
1093 UsbBusDriverEntryPoint (
1094 IN EFI_HANDLE ImageHandle,
1095 IN EFI_SYSTEM_TABLE *SystemTable
1096 )
1097 {
1098 return EfiLibInstallDriverBindingComponentName2 (
1099 ImageHandle,
1100 SystemTable,
1101 &mUsbBusDriverBinding,
1102 ImageHandle,
1103 &mUsbBusComponentName,
1104 &mUsbBusComponentName2
1105 );
1106 }
1107
1108
1109 /**
1110 Check whether USB bus driver support this device.
1111
1112 @param This The USB bus driver binding protocol.
1113 @param Controller The controller handle to check.
1114 @param RemainingDevicePath The remaining device path.
1115
1116 @retval EFI_SUCCESS The bus supports this controller.
1117 @retval EFI_UNSUPPORTED This device isn't supported.
1118
1119 **/
1120 EFI_STATUS
1121 EFIAPI
1122 UsbBusControllerDriverSupported (
1123 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1124 IN EFI_HANDLE Controller,
1125 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1126 )
1127 {
1128 EFI_DEV_PATH_PTR DevicePathNode;
1129 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1130 EFI_USB2_HC_PROTOCOL *Usb2Hc;
1131 EFI_USB_HC_PROTOCOL *UsbHc;
1132 EFI_STATUS Status;
1133
1134 //
1135 // Check whether device path is valid
1136 //
1137 if (RemainingDevicePath != NULL) {
1138 //
1139 // Check if RemainingDevicePath is the End of Device Path Node,
1140 // if yes, go on checking other conditions
1141 //
1142 if (!IsDevicePathEnd (RemainingDevicePath)) {
1143 //
1144 // If RemainingDevicePath isn't the End of Device Path Node,
1145 // check its validation
1146 //
1147 DevicePathNode.DevPath = RemainingDevicePath;
1148
1149 if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
1150 (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
1151 DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
1152 && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
1153 )) {
1154
1155 return EFI_UNSUPPORTED;
1156 }
1157 }
1158 }
1159
1160 //
1161 // Check whether USB_HC2 protocol is installed
1162 //
1163 Status = gBS->OpenProtocol (
1164 Controller,
1165 &gEfiUsb2HcProtocolGuid,
1166 (VOID **) &Usb2Hc,
1167 This->DriverBindingHandle,
1168 Controller,
1169 EFI_OPEN_PROTOCOL_BY_DRIVER
1170 );
1171 if (Status == EFI_ALREADY_STARTED) {
1172 return EFI_SUCCESS;
1173 }
1174
1175 if (EFI_ERROR (Status)) {
1176 //
1177 // If failed to open USB_HC2, fall back to USB_HC
1178 //
1179 Status = gBS->OpenProtocol (
1180 Controller,
1181 &gEfiUsbHcProtocolGuid,
1182 (VOID **) &UsbHc,
1183 This->DriverBindingHandle,
1184 Controller,
1185 EFI_OPEN_PROTOCOL_BY_DRIVER
1186 );
1187 if (Status == EFI_ALREADY_STARTED) {
1188 return EFI_SUCCESS;
1189 }
1190
1191 if (EFI_ERROR (Status)) {
1192 return Status;
1193 }
1194
1195 //
1196 // Close the USB_HC used to perform the supported test
1197 //
1198 gBS->CloseProtocol (
1199 Controller,
1200 &gEfiUsbHcProtocolGuid,
1201 This->DriverBindingHandle,
1202 Controller
1203 );
1204
1205 } else {
1206
1207 //
1208 // Close the USB_HC2 used to perform the supported test
1209 //
1210 gBS->CloseProtocol (
1211 Controller,
1212 &gEfiUsb2HcProtocolGuid,
1213 This->DriverBindingHandle,
1214 Controller
1215 );
1216 }
1217
1218 //
1219 // Open the EFI Device Path protocol needed to perform the supported test
1220 //
1221 Status = gBS->OpenProtocol (
1222 Controller,
1223 &gEfiDevicePathProtocolGuid,
1224 (VOID **) &ParentDevicePath,
1225 This->DriverBindingHandle,
1226 Controller,
1227 EFI_OPEN_PROTOCOL_BY_DRIVER
1228 );
1229 if (Status == EFI_ALREADY_STARTED) {
1230 return EFI_SUCCESS;
1231 }
1232
1233 if (!EFI_ERROR (Status)) {
1234 //
1235 // Close protocol, don't use device path protocol in the Support() function
1236 //
1237 gBS->CloseProtocol (
1238 Controller,
1239 &gEfiDevicePathProtocolGuid,
1240 This->DriverBindingHandle,
1241 Controller
1242 );
1243
1244 return EFI_SUCCESS;
1245 }
1246
1247 return Status;
1248 }
1249
1250
1251 /**
1252 Start to process the controller.
1253
1254 @param This The USB bus driver binding instance.
1255 @param Controller The controller to check.
1256 @param RemainingDevicePath The remaining device patch.
1257
1258 @retval EFI_SUCCESS The controller is controlled by the usb bus.
1259 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb
1260 bus.
1261 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
1262
1263 **/
1264 EFI_STATUS
1265 EFIAPI
1266 UsbBusControllerDriverStart (
1267 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1268 IN EFI_HANDLE Controller,
1269 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1270 )
1271 {
1272 EFI_USB_BUS_PROTOCOL *UsbBusId;
1273 EFI_STATUS Status;
1274
1275 //
1276 // Locate the USB bus protocol, if it is found, USB bus
1277 // is already started on this controller.
1278 //
1279 Status = gBS->OpenProtocol (
1280 Controller,
1281 &mUsbBusProtocolGuid,
1282 (VOID **) &UsbBusId,
1283 This->DriverBindingHandle,
1284 Controller,
1285 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1286 );
1287
1288 if (EFI_ERROR (Status)) {
1289 //
1290 // If first start, build the bus execute environment and install bus protocol
1291 //
1292 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_IO_BUS_USB | EFI_P_PC_ENABLE));
1293 Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
1294 if (EFI_ERROR (Status)) {
1295 return Status;
1296 }
1297 //
1298 // Try get the Usb Bus protocol interface again
1299 //
1300 Status = gBS->OpenProtocol (
1301 Controller,
1302 &mUsbBusProtocolGuid,
1303 (VOID **) &UsbBusId,
1304 This->DriverBindingHandle,
1305 Controller,
1306 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1307 );
1308 ASSERT (!EFI_ERROR (Status));
1309 } else {
1310 //
1311 // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
1312 // usb child device will be recursively connected.
1313 // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
1314 // All wanted usb child devices will be remembered by the usb bus driver itself.
1315 // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
1316 //
1317 // Save the passed in RemainingDevicePath this time
1318 //
1319 if (RemainingDevicePath != NULL) {
1320 if (IsDevicePathEnd (RemainingDevicePath)) {
1321 //
1322 // If RemainingDevicePath is the End of Device Path Node,
1323 // skip enumerate any device and return EFI_SUCESSS
1324 //
1325 return EFI_SUCCESS;
1326 }
1327 }
1328
1329 Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
1330 ASSERT (!EFI_ERROR (Status));
1331 //
1332 // Ensure all wanted child usb devices are fully recursively connected
1333 //
1334 Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
1335 ASSERT (!EFI_ERROR (Status));
1336 }
1337
1338
1339 return EFI_SUCCESS;
1340 }
1341
1342
1343 /**
1344 Stop handle the controller by this USB bus driver.
1345
1346 @param This The USB bus driver binding protocol.
1347 @param Controller The controller to release.
1348 @param NumberOfChildren The child of USB bus that opened controller
1349 BY_CHILD.
1350 @param ChildHandleBuffer The array of child handle.
1351
1352 @retval EFI_SUCCESS The controller or children are stopped.
1353 @retval EFI_DEVICE_ERROR Failed to stop the driver.
1354
1355 **/
1356 EFI_STATUS
1357 EFIAPI
1358 UsbBusControllerDriverStop (
1359 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1360 IN EFI_HANDLE Controller,
1361 IN UINTN NumberOfChildren,
1362 IN EFI_HANDLE *ChildHandleBuffer
1363 )
1364 {
1365 USB_BUS *Bus;
1366 USB_DEVICE *RootHub;
1367 USB_DEVICE *UsbDev;
1368 USB_INTERFACE *RootIf;
1369 USB_INTERFACE *UsbIf;
1370 EFI_USB_BUS_PROTOCOL *BusId;
1371 EFI_USB_IO_PROTOCOL *UsbIo;
1372 EFI_TPL OldTpl;
1373 UINTN Index;
1374 EFI_STATUS Status;
1375
1376 Status = EFI_SUCCESS;
1377
1378 if (NumberOfChildren > 0) {
1379 //
1380 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1381 //
1382 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1383
1384 for (Index = 0; Index < NumberOfChildren; Index++) {
1385 Status = gBS->OpenProtocol (
1386 ChildHandleBuffer[Index],
1387 &gEfiUsbIoProtocolGuid,
1388 (VOID **) &UsbIo,
1389 This->DriverBindingHandle,
1390 Controller,
1391 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1392 );
1393
1394 if (EFI_ERROR (Status)) {
1395 //
1396 // It is possible that the child has already been released:
1397 // 1. For combo device, free one device will release others.
1398 // 2. If a hub is released, all devices on its down facing
1399 // ports are released also.
1400 //
1401 continue;
1402 }
1403
1404 UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);
1405 UsbDev = UsbIf->Device;
1406
1407 UsbRemoveDevice (UsbDev);
1408 }
1409
1410 gBS->RestoreTPL (OldTpl);
1411 return EFI_SUCCESS;
1412 }
1413
1414 DEBUG (( EFI_D_INFO, "UsbBusStop: usb bus stopped on %p\n", Controller));
1415
1416 //
1417 // Locate USB_BUS for the current host controller
1418 //
1419 Status = gBS->OpenProtocol (
1420 Controller,
1421 &mUsbBusProtocolGuid,
1422 (VOID **) &BusId,
1423 This->DriverBindingHandle,
1424 Controller,
1425 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1426 );
1427
1428 if (EFI_ERROR (Status)) {
1429 return Status;
1430 }
1431
1432 Bus = USB_BUS_FROM_THIS (BusId);
1433
1434 //
1435 // Stop the root hub, then free all the devices
1436 //
1437 // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
1438 //
1439 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1440 UsbHcSetState (Bus, EfiUsbHcStateHalt);
1441
1442 RootHub = Bus->Devices[0];
1443 RootIf = RootHub->Interfaces[0];
1444
1445 mUsbRootHubApi.Release (RootIf);
1446
1447 for (Index = 1; Index < mMaxUsbDeviceNum; 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 }