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