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