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