]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
1. Sync Tcp4 protocol definitions to match UEFI 2.1
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UhciDxe / Uhci.c
CommitLineData
913cb9dc 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
12Module Name:\r
13\r
14 Uhci.c\r
15\r
16Abstract:\r
17\r
18 The UHCI driver model and HC protocol routines.\r
19\r
20Revision History\r
21\r
22\r
23**/\r
24\r
25#include "Uhci.h"\r
26\r
27\r
28/**\r
29 Provides software reset for the USB host controller.\r
30\r
31 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
32 Attributes: A bit mask of the reset operation to perform.\r
33\r
34 @return EFI_SUCCESS : The reset operation succeeded.\r
35 @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
36 @return EFI_DEVICE_ERROR : An error was encountered while attempting\r
37 @return to perform the reset operation.\r
38\r
39**/\r
40STATIC\r
41EFI_STATUS\r
42EFIAPI\r
43UhciReset (\r
44 IN EFI_USB_HC_PROTOCOL *This,\r
45 IN UINT16 Attributes\r
46 )\r
47{\r
48 USB_HC_DEV *Uhc;\r
49 EFI_TPL OldTpl;\r
50\r
51 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
52 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
53\r
54 switch (Attributes) {\r
55 case EFI_USB_HC_RESET_GLOBAL:\r
56 //\r
57 // Stop schedule and set the Global Reset bit in the command register\r
58 //\r
59 UhciStopHc (Uhc, STALL_1_SECOND);\r
60 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
61\r
62 //\r
63 // Wait 50ms for root port to let reset complete\r
64 // See UHCI spec page122 Reset signaling\r
65 //\r
66 gBS->Stall (ROOT_PORT_REST_TIME);\r
67\r
68 //\r
69 // Clear the Global Reset bit to zero.\r
70 //\r
71 UhciClearRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_GRESET);\r
72\r
73 //\r
74 // UHCI spec page120 reset recovery time\r
75 //\r
76 gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
77 break;\r
78\r
79 case EFI_USB_HC_RESET_HOST_CONTROLLER:\r
80 //\r
81 // Stop schedule and set Host Controller Reset bit to 1\r
82 //\r
83 UhciStopHc (Uhc, STALL_1_SECOND);\r
84 UhciSetRegBit (Uhc->PciIo, USBCMD_OFFSET, USBCMD_HCRESET);\r
85\r
86 //\r
87 // this bit will be reset by Host Controller when reset is completed.\r
88 // wait 10ms to let reset complete\r
89 //\r
90 gBS->Stall (PORT_RESET_RECOVERY_TIME);\r
91 break;\r
92\r
93 default:\r
94 goto ON_INVAILD_PARAMETER;\r
95 }\r
96\r
97 //\r
98 // Delete all old transactions on the USB bus, then\r
99 // reinitialize the frame list\r
100 //\r
101 UhciFreeAllAsyncReq (Uhc);\r
102 UhciDestoryFrameList (Uhc);\r
103 UhciInitFrameList (Uhc);\r
104\r
105 gBS->RestoreTPL (OldTpl);\r
106\r
107 return EFI_SUCCESS;\r
108\r
109ON_INVAILD_PARAMETER:\r
110\r
111 gBS->RestoreTPL (OldTpl);\r
112\r
113 return EFI_INVALID_PARAMETER;\r
114}\r
115\r
116\r
117/**\r
118 Retrieves current state of the USB host controller.\r
119\r
120 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
121 State : A pointer to the EFI_USB_HC_STATE data structure that\r
122 indicates current state of the USB host controller.\r
123\r
124 @return EFI_SUCCESS : State was returned\r
125 @return EFI_INVALID_PARAMETER : State is NULL.\r
126 @return EFI_DEVICE_ERROR : An error was encountered\r
127\r
128**/\r
129STATIC\r
130EFI_STATUS\r
131EFIAPI\r
132UhciGetState (\r
133 IN EFI_USB_HC_PROTOCOL *This,\r
134 OUT EFI_USB_HC_STATE *State\r
135 )\r
136{\r
137 USB_HC_DEV *Uhc;\r
138 UINT16 UsbSts;\r
139 UINT16 UsbCmd;\r
140\r
141 if (State == NULL) {\r
142 return EFI_INVALID_PARAMETER;\r
143 }\r
144\r
145 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
146\r
147 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
148 UsbSts = UhciReadReg (Uhc->PciIo, USBSTS_OFFSET);\r
149\r
150 if (UsbCmd & USBCMD_EGSM) {\r
151 *State = EfiUsbHcStateSuspend;\r
152\r
153 } else if ((UsbSts & USBSTS_HCH) != 0) {\r
154 *State = EfiUsbHcStateHalt;\r
155\r
156 } else {\r
157 *State = EfiUsbHcStateOperational;\r
158 }\r
159\r
160 return EFI_SUCCESS;\r
161}\r
162\r
163\r
164/**\r
165 Sets the USB host controller to a specific state.\r
166\r
167 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
168 State : Indicates the state of the host controller that will be set.\r
169\r
170 @return EFI_SUCCESS : The USB host controller was successfully set\r
171 @return EFI_INVALID_PARAMETER : State is invalid.\r
172 @return EFI_DEVICE_ERROR : Failed to set the state specified\r
173\r
174**/\r
175STATIC\r
176EFI_STATUS\r
177EFIAPI\r
178UhciSetState (\r
179 IN EFI_USB_HC_PROTOCOL *This,\r
180 IN EFI_USB_HC_STATE State\r
181 )\r
182{\r
183 EFI_USB_HC_STATE CurState;\r
184 USB_HC_DEV *Uhc;\r
185 EFI_TPL OldTpl;\r
186 EFI_STATUS Status;\r
187 UINT16 UsbCmd;\r
188\r
189 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
190 Status = UhciGetState (This, &CurState);\r
191\r
192 if (EFI_ERROR (Status)) {\r
193 return EFI_DEVICE_ERROR;\r
194 }\r
195\r
196 if (CurState == State) {\r
197 return EFI_SUCCESS;\r
198 }\r
199\r
200 Status = EFI_SUCCESS;\r
201 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
202\r
203 switch (State) {\r
204 case EfiUsbHcStateHalt:\r
205 Status = UhciStopHc (Uhc, STALL_1_SECOND);\r
206 break;\r
207\r
208 case EfiUsbHcStateOperational:\r
209 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
210\r
211 if (CurState == EfiUsbHcStateHalt) {\r
212 //\r
213 // Set Run/Stop bit to 1, also set the bandwidht reclamation\r
214 // point to 64 bytes\r
215 //\r
216 UsbCmd |= USBCMD_RS | USBCMD_MAXP;\r
217 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
218\r
219 } else if (CurState == EfiUsbHcStateSuspend) {\r
220 //\r
221 // If FGR(Force Global Resume) bit is 0, set it\r
222 //\r
223 if ((UsbCmd & USBCMD_FGR) == 0) {\r
224 UsbCmd |= USBCMD_FGR;\r
225 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
226 }\r
227\r
228 //\r
229 // wait 20ms to let resume complete (20ms is specified by UHCI spec)\r
230 //\r
231 gBS->Stall (FORCE_GLOBAL_RESUME_TIME);\r
232\r
233 //\r
234 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0\r
235 //\r
236 UsbCmd &= ~USBCMD_FGR;\r
237 UsbCmd &= ~USBCMD_EGSM;\r
238 UsbCmd |= USBCMD_RS;\r
239 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
240 }\r
241\r
242 break;\r
243\r
244 case EfiUsbHcStateSuspend:\r
245 Status = UhciSetState (This, EfiUsbHcStateHalt);\r
246\r
247 if (EFI_ERROR (Status)) {\r
248 Status = EFI_DEVICE_ERROR;\r
249 goto ON_EXIT;\r
250 }\r
251\r
252 //\r
253 // Set Enter Global Suspend Mode bit to 1.\r
254 //\r
255 UsbCmd = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
256 UsbCmd |= USBCMD_EGSM;\r
257 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, UsbCmd);\r
258 break;\r
259\r
260 default:\r
261 Status = EFI_INVALID_PARAMETER;\r
262 break;\r
263 }\r
264\r
265ON_EXIT:\r
266 gBS->RestoreTPL (OldTpl);\r
267 return Status;\r
268}\r
269\r
270\r
271/**\r
272 Retrieves the number of root hub ports.\r
273\r
274 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
275 PortNumber : A pointer to the number of the root hub ports.\r
276\r
277 @return EFI_SUCCESS : The port number was retrieved successfully.\r
278 @return EFI_INVALID_PARAMETER : PortNumber is NULL.\r
279 @return EFI_DEVICE_ERROR : An error was encountered\r
280\r
281**/\r
282STATIC\r
283EFI_STATUS\r
284EFIAPI\r
285UhciGetRootHubPortNumber (\r
286 IN EFI_USB_HC_PROTOCOL *This,\r
287 OUT UINT8 *PortNumber\r
288 )\r
289{\r
290 USB_HC_DEV *Uhc;\r
291 UINT32 Offset;\r
292 UINT16 PortSC;\r
293 UINT32 Index;\r
294\r
295 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
296\r
297 if (PortNumber == NULL) {\r
298 return EFI_INVALID_PARAMETER;\r
299 }\r
300\r
301 *PortNumber = 0;\r
302\r
303 for (Index = 0; Index < USB_MAX_ROOTHUB_PORT; Index++) {\r
304 Offset = USBPORTSC_OFFSET + Index * 2;\r
305 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
306\r
307 //\r
308 // Port status's bit 7 is reserved and always returns 1 if\r
309 // the port number is valid. Intel's UHCI (in EHCI controller)\r
310 // returns 0 in this bit if port number is invalid. Also, if\r
311 // PciIo IoRead returns error, 0xFFFF is returned to caller.\r
312 //\r
313 if (((PortSC & 0x80) != 0) && (PortSC != 0xFFFF)) {\r
314 (*PortNumber)++;\r
315 }\r
316 }\r
317\r
318 Uhc->RootPorts = *PortNumber;\r
319\r
320 UHCI_DEBUG (("UhciGetRootHubPortNumber: %d ports\n", Uhc->RootPorts));\r
321 return EFI_SUCCESS;\r
322}\r
323\r
324\r
325/**\r
326 Retrieves the current status of a USB root hub port.\r
327\r
328 This : A pointer to the EFI_USB_HC_PROTOCOL.\r
329 PortNumber : Specifies the root hub port. This value is zero-based.\r
330 PortStatus : A pointer to the current port status bits and port status change bits.\r
331\r
332 @return EFI_SUCCESS : The port status was returned in PortStatus.\r
333 @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
334 @return EFI_DEVICE_ERROR : Can't read register\r
335\r
336**/\r
337EFI_STATUS\r
338EFIAPI\r
339UhciGetRootHubPortStatus (\r
340 IN EFI_USB_HC_PROTOCOL *This,\r
341 IN UINT8 PortNumber,\r
342 OUT EFI_USB_PORT_STATUS *PortStatus\r
343 )\r
344{\r
345 USB_HC_DEV *Uhc;\r
346 UINT32 Offset;\r
347 UINT16 PortSC;\r
348\r
349 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
350\r
351 if (PortStatus == NULL) {\r
352 return EFI_INVALID_PARAMETER;\r
353 }\r
354\r
355 if (PortNumber >= Uhc->RootPorts) {\r
356 return EFI_INVALID_PARAMETER;\r
357 }\r
358\r
359 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
360 PortStatus->PortStatus = 0;\r
361 PortStatus->PortChangeStatus = 0;\r
362\r
363 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
364\r
365 if (PortSC & USBPORTSC_CCS) {\r
366 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;\r
367 }\r
368\r
369 if (PortSC & USBPORTSC_PED) {\r
370 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;\r
371 }\r
372\r
373 if (PortSC & USBPORTSC_SUSP) {\r
374 UHCI_DEBUG (("UhciGetRootHubPortStatus: port %d is suspended\n", PortNumber));\r
375 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;\r
376 }\r
377\r
378 if (PortSC & USBPORTSC_PR) {\r
379 PortStatus->PortStatus |= USB_PORT_STAT_RESET;\r
380 }\r
381\r
382 if (PortSC & USBPORTSC_LSDA) {\r
383 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;\r
384 }\r
385\r
386 //\r
387 // CHC will always return one in port owner bit\r
388 //\r
389 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;\r
390\r
391 if (PortSC & USBPORTSC_CSC) {\r
392 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;\r
393 }\r
394\r
395 if (PortSC & USBPORTSC_PEDC) {\r
396 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;\r
397 }\r
398\r
399 return EFI_SUCCESS;\r
400}\r
401\r
402\r
403/**\r
404 Sets a feature for the specified root hub port.\r
405\r
406 This : A pointer to the EFI_USB_HC_PROTOCOL.\r
407 PortNumber : Specifies the root hub port whose feature\r
408 is requested to be set.\r
409 PortFeature : Indicates the feature selector associated\r
410 with the feature set request.\r
411\r
412 @return EFI_SUCCESS : The feature was set for the port.\r
413 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
414 @return EFI_DEVICE_ERROR : Can't read register\r
415\r
416**/\r
417STATIC\r
418EFI_STATUS\r
419EFIAPI\r
420UhciSetRootHubPortFeature (\r
421 IN EFI_USB_HC_PROTOCOL *This,\r
422 IN UINT8 PortNumber,\r
423 IN EFI_USB_PORT_FEATURE PortFeature\r
424 )\r
425{\r
426 USB_HC_DEV *Uhc;\r
427 EFI_TPL OldTpl;\r
428 UINT32 Offset;\r
429 UINT16 PortSC;\r
430 UINT16 Command;\r
431\r
432 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
433\r
434 if (PortNumber >= Uhc->RootPorts) {\r
435 return EFI_INVALID_PARAMETER;\r
436 }\r
437\r
438 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
439\r
440 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
441 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
442\r
443 switch (PortFeature) {\r
444 case EfiUsbPortSuspend:\r
445 Command = UhciReadReg (Uhc->PciIo, USBCMD_OFFSET);\r
446 if (!(Command & USBCMD_EGSM)) {\r
447 //\r
448 // if global suspend is not active, can set port suspend\r
449 //\r
450 PortSC &= 0xfff5;\r
451 PortSC |= USBPORTSC_SUSP;\r
452 }\r
453 break;\r
454\r
455 case EfiUsbPortReset:\r
456 PortSC &= 0xfff5;\r
457 PortSC |= USBPORTSC_PR;\r
458 break;\r
459\r
460 case EfiUsbPortPower:\r
461 //\r
462 // No action\r
463 //\r
464 break;\r
465\r
466 case EfiUsbPortEnable:\r
467 PortSC &= 0xfff5;\r
468 PortSC |= USBPORTSC_PED;\r
469 break;\r
470\r
471 default:\r
472 gBS->RestoreTPL (OldTpl);\r
473 return EFI_INVALID_PARAMETER;\r
474 }\r
475\r
476 UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
477 gBS->RestoreTPL (OldTpl);\r
478\r
479 return EFI_SUCCESS;\r
480}\r
481\r
482\r
483/**\r
484 Clears a feature for the specified root hub port.\r
485\r
486 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
487 PortNumber : Specifies the root hub port whose feature\r
488 is requested to be cleared.\r
489 PortFeature : Indicates the feature selector associated with the\r
490 feature clear request.\r
491\r
492 @return EFI_SUCCESS : The feature was cleared for the port.\r
493 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
494 @return EFI_DEVICE_ERROR : Can't read register\r
495\r
496**/\r
497STATIC\r
498EFI_STATUS\r
499EFIAPI\r
500UhciClearRootHubPortFeature (\r
501 IN EFI_USB_HC_PROTOCOL *This,\r
502 IN UINT8 PortNumber,\r
503 IN EFI_USB_PORT_FEATURE PortFeature\r
504 )\r
505{\r
506 USB_HC_DEV *Uhc;\r
507 EFI_TPL OldTpl;\r
508 UINT32 Offset;\r
509 UINT16 PortSC;\r
510\r
511 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
512\r
513 if (PortNumber >= Uhc->RootPorts) {\r
514 return EFI_INVALID_PARAMETER;\r
515 }\r
516\r
517 Offset = USBPORTSC_OFFSET + PortNumber * 2;\r
518\r
519 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
520 PortSC = UhciReadReg (Uhc->PciIo, Offset);\r
521\r
522 switch (PortFeature) {\r
523 case EfiUsbPortEnable:\r
524 PortSC &= 0xfff5;\r
525 PortSC &= ~USBPORTSC_PED;\r
526 break;\r
527\r
528 case EfiUsbPortSuspend:\r
529 //\r
530 // Cause a resume on the specified port if in suspend mode.\r
531 //\r
532 PortSC &= 0xfff5;\r
533 PortSC &= ~USBPORTSC_SUSP;\r
534 break;\r
535\r
536 case EfiUsbPortPower:\r
537 //\r
538 // No action\r
539 //\r
540 break;\r
541\r
542 case EfiUsbPortReset:\r
543 PortSC &= 0xfff5;\r
544 PortSC &= ~USBPORTSC_PR;\r
545 break;\r
546\r
547 case EfiUsbPortConnectChange:\r
548 PortSC &= 0xfff5;\r
549 PortSC |= USBPORTSC_CSC;\r
550 break;\r
551\r
552 case EfiUsbPortEnableChange:\r
553 PortSC &= 0xfff5;\r
554 PortSC |= USBPORTSC_PEDC;\r
555 break;\r
556\r
557 case EfiUsbPortSuspendChange:\r
558 //\r
559 // Root hub does not support this\r
560 //\r
561 break;\r
562\r
563 case EfiUsbPortOverCurrentChange:\r
564 //\r
565 // Root hub does not support this\r
566 //\r
567 break;\r
568\r
569 case EfiUsbPortResetChange:\r
570 //\r
571 // Root hub does not support this\r
572 //\r
573 break;\r
574\r
575 default:\r
576 gBS->RestoreTPL (OldTpl);\r
577 return EFI_INVALID_PARAMETER;\r
578 }\r
579\r
580 UhciWriteReg (Uhc->PciIo, Offset, PortSC);\r
581 gBS->RestoreTPL (OldTpl);\r
582\r
583 return EFI_SUCCESS;\r
584}\r
585\r
586\r
587/**\r
588 Submits control transfer to a target USB device.\r
589\r
590 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
591 DeviceAddress : Usb device address\r
592 IsSlowDevice : Whether the device is of slow speed or full speed\r
593 MaximumPacketLength : maximum packet size of the default control endpoint\r
594 Request : USB device request to send\r
595 TransferDirection : Specifies the data direction for the transfer.\r
596 Data : Data buffer to transmit from or receive into\r
597 DataLength : Number of bytes of the data\r
598 TimeOut : Maximum time, in microseconds\r
599 TransferResult : Return result in this\r
600\r
601 @return EFI_SUCCESS : Transfer was completed successfully.\r
602 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.\r
603 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
604 @return EFI_TIMEOUT : Failed due to timeout.\r
605 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
606\r
607**/\r
608STATIC\r
609EFI_STATUS\r
610EFIAPI\r
611UhciControlTransfer (\r
612 IN EFI_USB_HC_PROTOCOL *This,\r
613 IN UINT8 DeviceAddress,\r
614 IN BOOLEAN IsSlowDevice,\r
615 IN UINT8 MaximumPacketLength,\r
616 IN EFI_USB_DEVICE_REQUEST *Request,\r
617 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
618 IN OUT VOID *Data, OPTIONAL\r
619 IN OUT UINTN *DataLength, OPTIONAL\r
620 IN UINTN TimeOut,\r
621 OUT UINT32 *TransferResult\r
622 )\r
623{\r
624 USB_HC_DEV *Uhc;\r
625 UHCI_TD_SW *TDs;\r
626 EFI_TPL OldTpl;\r
627 EFI_STATUS Status;\r
628 UHCI_QH_RESULT QhResult;\r
629 UINT8 PktId;\r
630 UINT8 *RequestPhy;\r
631 VOID *RequestMap;\r
632 UINT8 *DataPhy;\r
633 VOID *DataMap;\r
634\r
635 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
636 TDs = NULL;\r
637 DataPhy = NULL;\r
638 DataMap = NULL;\r
639 RequestPhy = NULL;\r
640 RequestMap = NULL;\r
641\r
642 //\r
643 // Parameters Checking\r
644 //\r
645 if (Request == NULL || TransferResult == NULL) {\r
646 return EFI_INVALID_PARAMETER;\r
647 }\r
648\r
649 if (IsSlowDevice && (MaximumPacketLength != 8)) {\r
650 return EFI_INVALID_PARAMETER;\r
651 }\r
652\r
653 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
654 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
655\r
656 return EFI_INVALID_PARAMETER;\r
657 }\r
658\r
659 if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {\r
660 return EFI_INVALID_PARAMETER;\r
661 }\r
662\r
663 *TransferResult = EFI_USB_ERR_SYSTEM;\r
664 Status = EFI_DEVICE_ERROR;\r
665\r
666 //\r
667 // If errors exist that cause host controller halt,\r
668 // clear status then return EFI_DEVICE_ERROR.\r
669 //\r
670 UhciAckAllInterrupt (Uhc);\r
671\r
672 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
673 return EFI_DEVICE_ERROR;\r
674 }\r
675\r
676 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
677\r
678 //\r
679 // Map the Request and data for bus master access,\r
680 // then create a list of TD for this transfer\r
681 //\r
682 Status = UhciMapUserRequest (Uhc, Request, &RequestPhy, &RequestMap);\r
683\r
684 if (EFI_ERROR (Status)) {\r
685 goto ON_EXIT;\r
686 }\r
687\r
688 Status = UhciMapUserData (Uhc, TransferDirection, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
689\r
690 if (EFI_ERROR (Status)) {\r
691 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
692 goto ON_EXIT;\r
693 }\r
694\r
695 TDs = UhciCreateCtrlTds (\r
696 Uhc,\r
697 DeviceAddress,\r
698 PktId,\r
699 RequestPhy,\r
700 DataPhy,\r
701 *DataLength,\r
702 MaximumPacketLength,\r
703 IsSlowDevice\r
704 );\r
705\r
706 if (TDs == NULL) {\r
707 Status = EFI_OUT_OF_RESOURCES;\r
708 goto UNMAP_DATA;\r
709 }\r
710\r
711 //\r
712 // According to the speed of the end point, link\r
713 // the TD to corrosponding queue head, then check\r
714 // the execution result\r
715 //\r
716 UhciLinkTdToQh (Uhc->CtrlQh, TDs);\r
717 Status = UhciExecuteTransfer (Uhc, Uhc->CtrlQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
718 UhciUnlinkTdFromQh (Uhc->CtrlQh, TDs);\r
719\r
720 Uhc->PciIo->Flush (Uhc->PciIo);\r
721\r
722 *TransferResult = QhResult.Result;\r
723\r
724 if (DataLength != NULL) {\r
725 *DataLength = QhResult.Complete;\r
726 }\r
727\r
728 UhciDestoryTds (Uhc, TDs);\r
729\r
730UNMAP_DATA:\r
731 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
732 Uhc->PciIo->Unmap (Uhc->PciIo, RequestMap);\r
733\r
734ON_EXIT:\r
735 gBS->RestoreTPL (OldTpl);\r
736 return Status;\r
737}\r
738\r
739\r
740/**\r
741 Submits bulk transfer to a bulk endpoint of a USB device.\r
742\r
743 This :A pointer to the EFI_USB_HC_PROTOCOL instance.\r
744 DeviceAddress : Usb device address\r
745 EndPointAddress : Endpoint number and endpoint direction\r
746 MaximumPacketLength : Maximum packet size of the target endpoint\r
747 Data : Data buffer to transmit from or receive into\r
748 DataLength : Length of the data buffer\r
749 DataToggle : On input, data toggle to use, on output, the next toggle\r
750 TimeOut : Indicates the maximum time\r
751 TransferResult : Variable to receive the transfer result\r
752\r
753 @return EFI_SUCCESS : The bulk transfer was completed successfully.\r
754 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
755 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
756 @return EFI_TIMEOUT : Failed due to timeout.\r
757 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
758\r
759**/\r
760STATIC\r
761EFI_STATUS\r
762EFIAPI\r
763UhciBulkTransfer (\r
764 IN EFI_USB_HC_PROTOCOL *This,\r
765 IN UINT8 DeviceAddress,\r
766 IN UINT8 EndPointAddress,\r
767 IN UINT8 MaximumPacketLength,\r
768 IN OUT VOID *Data,\r
769 IN OUT UINTN *DataLength,\r
770 IN OUT UINT8 *DataToggle,\r
771 IN UINTN TimeOut,\r
772 OUT UINT32 *TransferResult\r
773 )\r
774{\r
775 EFI_USB_DATA_DIRECTION Direction;\r
776 EFI_TPL OldTpl;\r
777 USB_HC_DEV *Uhc;\r
778 UHCI_TD_SW *TDs;\r
779 UHCI_QH_SW *BulkQh;\r
780 UHCI_QH_RESULT QhResult;\r
781 EFI_STATUS Status;\r
782 UINT8 PktId;\r
783 UINT8 *DataPhy;\r
784 VOID *DataMap;\r
785\r
786 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
787 DataPhy = NULL;\r
788 DataMap = NULL;\r
789\r
790 if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
791 return EFI_INVALID_PARAMETER;\r
792 }\r
793\r
794 if (*DataLength == 0) {\r
795 return EFI_INVALID_PARAMETER;\r
796 }\r
797\r
798 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
799 return EFI_INVALID_PARAMETER;\r
800 }\r
801\r
802 if ((MaximumPacketLength != 8) && (MaximumPacketLength != 16) &&\r
803 (MaximumPacketLength != 32) && (MaximumPacketLength != 64)) {\r
804 return EFI_INVALID_PARAMETER;\r
805 }\r
806\r
807 *TransferResult = EFI_USB_ERR_SYSTEM;\r
808 Status = EFI_OUT_OF_RESOURCES;\r
809\r
810 //\r
811 // If has errors that cause host controller halt,\r
812 // then return EFI_DEVICE_ERROR directly.\r
813 //\r
814 UhciAckAllInterrupt (Uhc);\r
815\r
816 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
817 return EFI_DEVICE_ERROR;\r
818 }\r
819\r
820 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
821\r
822 //\r
823 // Map the source data buffer for bus master access,\r
824 // then create a list of TDs\r
825 //\r
826 if (EndPointAddress & 0x80) {\r
827 Direction = EfiUsbDataIn;\r
828 } else {\r
829 Direction = EfiUsbDataOut;\r
830 }\r
831\r
832 Status = UhciMapUserData (Uhc, Direction, Data, DataLength, &PktId, &DataPhy, &DataMap);\r
833\r
834 if (EFI_ERROR (Status)) {\r
835 goto ON_EXIT;\r
836 }\r
837\r
838 Status = EFI_OUT_OF_RESOURCES;\r
839 TDs = UhciCreateBulkOrIntTds (\r
840 Uhc,\r
841 DeviceAddress,\r
842 EndPointAddress,\r
843 PktId,\r
844 DataPhy,\r
845 *DataLength,\r
846 DataToggle,\r
847 MaximumPacketLength,\r
848 FALSE\r
849 );\r
850\r
851 if (TDs == NULL) {\r
852 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
853 goto ON_EXIT;\r
854 }\r
855\r
856\r
857 //\r
858 // Link the TDs to bulk queue head. According to the platfore\r
859 // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured\r
860 // to do full speed bandwidth reclamation or not.\r
861 //\r
862 BulkQh = Uhc->BulkQh;\r
863\r
864 UhciLinkTdToQh (BulkQh, TDs);\r
865 Status = UhciExecuteTransfer (Uhc, BulkQh, TDs, TimeOut, FALSE, &QhResult);\r
866 UhciUnlinkTdFromQh (BulkQh, TDs);\r
867\r
868 Uhc->PciIo->Flush (Uhc->PciIo);\r
869\r
870 *TransferResult = QhResult.Result;\r
871 *DataToggle = QhResult.NextToggle;\r
872 *DataLength = QhResult.Complete;\r
873\r
874 UhciDestoryTds (Uhc, TDs);\r
875 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
876\r
877ON_EXIT:\r
878 gBS->RestoreTPL (OldTpl);\r
879 return Status;\r
880}\r
881\r
882\r
883/**\r
884 Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device.\r
885\r
886 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
887 DeviceAddress : Target device address\r
888 EndPointAddress : Endpoint number with direction\r
889 IsSlowDevice : Whether the target device is slow device or full-speed device.\r
890 MaximumPacketLength : Maximum packet size of the target endpoint\r
891 IsNewTransfer : If TRUE, submit a new async interrupt transfer, otherwise\r
892 cancel an existed one\r
893 DataToggle : On input, the data toggle to use; On output, next data toggle\r
894 PollingInterval : Interrupt poll rate in milliseconds\r
895 DataLength : Length of data to receive\r
896 CallBackFunction : Function to call periodically\r
897 Context : User context\r
898\r
899 @return EFI_SUCCESS : Request is submitted or cancelled\r
900 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
901 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.\r
902 @return EFI_DEVICE_ERROR : Failed to due to device error\r
903\r
904**/\r
905STATIC\r
906EFI_STATUS\r
907EFIAPI\r
908UhciAsyncInterruptTransfer (\r
909 IN EFI_USB_HC_PROTOCOL * This,\r
910 IN UINT8 DeviceAddress,\r
911 IN UINT8 EndPointAddress,\r
912 IN BOOLEAN IsSlowDevice,\r
913 IN UINT8 MaximumPacketLength,\r
914 IN BOOLEAN IsNewTransfer,\r
915 IN OUT UINT8 *DataToggle,\r
916 IN UINTN PollingInterval, OPTIONAL\r
917 IN UINTN DataLength, OPTIONAL\r
918 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL\r
919 IN VOID *Context OPTIONAL\r
920 )\r
921{\r
922 USB_HC_DEV *Uhc;\r
923 UHCI_QH_SW *Qh;\r
924 UHCI_TD_SW *IntTds;\r
925 EFI_TPL OldTpl;\r
926 EFI_STATUS Status;\r
927 UINT8 *DataPtr;\r
928 UINT8 *DataPhy;\r
929 VOID *DataMap;\r
930 UINT8 PktId;\r
931\r
932 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
933 Qh = NULL;\r
934 IntTds = NULL;\r
935 DataPtr = NULL;\r
936 DataPhy = NULL;\r
937 DataMap = NULL;\r
938\r
939 if ((EndPointAddress & 0x80) == 0) {\r
940 return EFI_INVALID_PARAMETER;\r
941 }\r
942\r
943 //\r
944 // Delete Async interrupt transfer request\r
945 //\r
946 if (!IsNewTransfer) {\r
947 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
948 Status = UhciRemoveAsyncReq (Uhc, DeviceAddress, EndPointAddress, DataToggle);\r
949\r
950 gBS->RestoreTPL (OldTpl);\r
951 return Status;\r
952 }\r
953\r
954 if (PollingInterval < 1 || PollingInterval > 255) {\r
955 return EFI_INVALID_PARAMETER;\r
956 }\r
957\r
958 if (DataLength == 0) {\r
959 return EFI_INVALID_PARAMETER;\r
960 }\r
961\r
962 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
963 return EFI_INVALID_PARAMETER;\r
964 }\r
965\r
966 //\r
967 // If has errors that cause host controller halt,\r
968 // then return EFI_DEVICE_ERROR directly.\r
969 //\r
970 UhciAckAllInterrupt (Uhc);\r
971\r
972 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
973 return EFI_DEVICE_ERROR;\r
974 }\r
975\r
976 //\r
977 // Allocate and map source data buffer for bus master access.\r
978 //\r
979 DataPtr = AllocatePool (DataLength);\r
980\r
981 if (DataPtr == NULL) {\r
982 return EFI_OUT_OF_RESOURCES;\r
983 }\r
984\r
985 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
986\r
987 //\r
988 // Map the user data then create a queue head and\r
989 // list of TD for it.\r
990 //\r
991 Status = UhciMapUserData (\r
992 Uhc,\r
993 EfiUsbDataIn,\r
994 DataPtr,\r
995 &DataLength,\r
996 &PktId,\r
997 &DataPhy,\r
998 &DataMap\r
999 );\r
1000\r
1001 if (EFI_ERROR (Status)) {\r
1002 goto FREE_DATA;\r
1003 }\r
1004\r
1005 Qh = UhciCreateQh (Uhc, PollingInterval);\r
1006\r
1007 if (Qh == NULL) {\r
1008 Status = EFI_OUT_OF_RESOURCES;\r
1009 goto UNMAP_DATA;\r
1010 }\r
1011\r
1012 IntTds = UhciCreateBulkOrIntTds (\r
1013 Uhc,\r
1014 DeviceAddress,\r
1015 EndPointAddress,\r
1016 PktId,\r
1017 DataPhy,\r
1018 DataLength,\r
1019 DataToggle,\r
1020 MaximumPacketLength,\r
1021 IsSlowDevice\r
1022 );\r
1023\r
1024 if (IntTds == NULL) {\r
1025 Status = EFI_OUT_OF_RESOURCES;\r
1026 goto DESTORY_QH;\r
1027 }\r
1028\r
1029 UhciLinkTdToQh (Qh, IntTds);\r
1030\r
1031 //\r
1032 // Save QH-TD structures to async Interrupt transfer list,\r
1033 // for monitor interrupt transfer execution routine use.\r
1034 //\r
1035 Status = UhciCreateAsyncReq (\r
1036 Uhc,\r
1037 Qh,\r
1038 IntTds,\r
1039 DeviceAddress,\r
1040 EndPointAddress,\r
1041 DataLength,\r
1042 PollingInterval,\r
1043 DataMap,\r
1044 DataPtr,\r
1045 CallBackFunction,\r
1046 Context,\r
1047 IsSlowDevice\r
1048 );\r
1049\r
1050 if (EFI_ERROR (Status)) {\r
1051 goto DESTORY_QH;\r
1052 }\r
1053\r
1054 UhciLinkQhToFrameList (Uhc->FrameBase, Qh);\r
1055\r
1056 gBS->RestoreTPL (OldTpl);\r
1057 return EFI_SUCCESS;\r
1058\r
1059DESTORY_QH:\r
1060 UsbHcFreeMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_SW));\r
1061\r
1062UNMAP_DATA:\r
1063 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1064\r
1065FREE_DATA:\r
1066 gBS->FreePool (DataPtr);\r
1067 Uhc->PciIo->Flush (Uhc->PciIo);\r
1068\r
1069 gBS->RestoreTPL (OldTpl);\r
1070 return Status;\r
1071}\r
1072\r
1073\r
1074/**\r
1075 Submits synchronous interrupt transfer to an interrupt endpoint of a USB device.\r
1076\r
1077 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1078 DeviceAddress : Device address of the target USB device\r
1079 EndPointAddress : Endpoint number and direction\r
1080 IsSlowDevice : Whether the target device is of slow speed or full speed\r
1081 MaximumPacketLength : Maximum packet size of target endpoint\r
1082 Data : Data to transmit or receive\r
1083 DataLength : On input, data length to transmit or buffer size.\r
1084 On output, the number of bytes transferred.\r
1085 DataToggle : On input, data toggle to use; On output, next data toggle\r
1086 TimeOut : Maximum time, in microseconds, transfer is allowed to complete.\r
1087 TransferResult : Variable to receive transfer result\r
1088\r
1089 @return EFI_SUCCESS : Transfer was completed successfully.\r
1090 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1091 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1092 @return EFI_TIMEOUT : Failed due to timeout.\r
1093 @return EFI_DEVICE_ERROR : Failed due to host controller or device error\r
1094\r
1095**/\r
1096STATIC\r
1097EFI_STATUS\r
1098EFIAPI\r
1099UhciSyncInterruptTransfer (\r
1100 IN EFI_USB_HC_PROTOCOL *This,\r
1101 IN UINT8 DeviceAddress,\r
1102 IN UINT8 EndPointAddress,\r
1103 IN BOOLEAN IsSlowDevice,\r
1104 IN UINT8 MaximumPacketLength,\r
1105 IN OUT VOID *Data,\r
1106 IN OUT UINTN *DataLength,\r
1107 IN OUT UINT8 *DataToggle,\r
1108 IN UINTN TimeOut,\r
1109 OUT UINT32 *TransferResult\r
1110 )\r
1111{\r
1112 EFI_STATUS Status;\r
1113 USB_HC_DEV *Uhc;\r
1114 UHCI_TD_SW *TDs;\r
1115 UHCI_QH_RESULT QhResult;\r
1116 EFI_TPL OldTpl;\r
1117 UINT8 *DataPhy;\r
1118 VOID *DataMap;\r
1119 UINT8 PktId;\r
1120\r
1121 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
1122 DataPhy = NULL;\r
1123 DataMap = NULL;\r
1124 TDs = NULL;\r
1125\r
1126 if ((DataLength == NULL) || (Data == NULL) || (TransferResult == NULL)) {\r
1127 return EFI_INVALID_PARAMETER;\r
1128 }\r
1129\r
1130 if ((EndPointAddress & 0x80) == 0) {\r
1131 return EFI_INVALID_PARAMETER;\r
1132 }\r
1133\r
1134 if ((*DataToggle != 1) && (*DataToggle != 0)) {\r
1135 return EFI_INVALID_PARAMETER;\r
1136 }\r
1137\r
1138 if ((*DataLength == 0) || (MaximumPacketLength > 64)) {\r
1139 return EFI_INVALID_PARAMETER;\r
1140 }\r
1141\r
1142 if (IsSlowDevice && (MaximumPacketLength > 8)) {\r
1143 return EFI_INVALID_PARAMETER;\r
1144 }\r
1145\r
1146 *TransferResult = EFI_USB_ERR_SYSTEM;\r
1147 Status = EFI_DEVICE_ERROR;\r
1148\r
1149\r
1150 UhciAckAllInterrupt (Uhc);\r
1151\r
1152 if (!UhciIsHcWorking (Uhc->PciIo)) {\r
1153 return Status;\r
1154 }\r
1155\r
1156 OldTpl = gBS->RaiseTPL (UHCI_TPL);\r
1157\r
1158 //\r
1159 // Map the source data buffer for bus master access.\r
1160 // Create Tds list, then link it to the UHC's interrupt list\r
1161 //\r
1162 Status = UhciMapUserData (\r
1163 Uhc,\r
1164 EfiUsbDataIn,\r
1165 Data,\r
1166 DataLength,\r
1167 &PktId,\r
1168 &DataPhy,\r
1169 &DataMap\r
1170 );\r
1171\r
1172 if (EFI_ERROR (Status)) {\r
1173 goto ON_EXIT;\r
1174 }\r
1175\r
1176 TDs = UhciCreateBulkOrIntTds (\r
1177 Uhc,\r
1178 DeviceAddress,\r
1179 EndPointAddress,\r
1180 PktId,\r
1181 DataPhy,\r
1182 *DataLength,\r
1183 DataToggle,\r
1184 MaximumPacketLength,\r
1185 IsSlowDevice\r
1186 );\r
1187\r
1188 if (TDs == NULL) {\r
1189 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1190\r
1191 Status = EFI_OUT_OF_RESOURCES;\r
1192 goto ON_EXIT;\r
1193 }\r
1194\r
1195\r
1196 UhciLinkTdToQh (Uhc->SyncIntQh, TDs);\r
1197\r
1198 Status = UhciExecuteTransfer (Uhc, Uhc->SyncIntQh, TDs, TimeOut, IsSlowDevice, &QhResult);\r
1199\r
1200 UhciUnlinkTdFromQh (Uhc->SyncIntQh, TDs);\r
1201 Uhc->PciIo->Flush (Uhc->PciIo);\r
1202\r
1203 *TransferResult = QhResult.Result;\r
1204 *DataToggle = QhResult.NextToggle;\r
1205 *DataLength = QhResult.Complete;\r
1206\r
1207 UhciDestoryTds (Uhc, TDs);\r
1208 Uhc->PciIo->Unmap (Uhc->PciIo, DataMap);\r
1209\r
1210ON_EXIT:\r
1211 gBS->RestoreTPL (OldTpl);\r
1212 return Status;\r
1213}\r
1214\r
1215\r
1216/**\r
1217 Submits isochronous transfer to a target USB device.\r
1218\r
1219 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1220 DeviceAddress : Target device address\r
1221 EndPointAddress : End point address withdirection\r
1222 MaximumPacketLength : Maximum packet size of the endpoint\r
1223 Data : Data to transmit or receive\r
1224 DataLength : Bytes of the data\r
1225 TransferResult : Variable to receive the result\r
1226\r
1227 @return EFI_UNSUPPORTED\r
1228\r
1229**/\r
1230STATIC\r
1231EFI_STATUS\r
1232EFIAPI\r
1233UhciIsochronousTransfer (\r
1234 IN EFI_USB_HC_PROTOCOL *This,\r
1235 IN UINT8 DeviceAddress,\r
1236 IN UINT8 EndPointAddress,\r
1237 IN UINT8 MaximumPacketLength,\r
1238 IN OUT VOID *Data,\r
1239 IN UINTN DataLength,\r
1240 OUT UINT32 *TransferResult\r
1241 )\r
1242{\r
1243 return EFI_UNSUPPORTED;\r
1244}\r
1245\r
1246\r
1247/**\r
1248 Submits Async isochronous transfer to a target USB device.\r
1249\r
1250 This : A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1251 DeviceAddress : Target device address\r
1252 EndPointAddress : End point address withdirection\r
1253 MaximumPacketLength : Maximum packet size of the endpoint\r
1254 Data : Data to transmit or receive\r
1255 IsochronousCallBack : Function to call when the transfer completes\r
1256 Context : User context\r
1257\r
1258 @return EFI_UNSUPPORTED\r
1259\r
1260**/\r
1261STATIC\r
1262EFI_STATUS\r
1263EFIAPI\r
1264UhciAsyncIsochronousTransfer (\r
1265 IN EFI_USB_HC_PROTOCOL * This,\r
1266 IN UINT8 DeviceAddress,\r
1267 IN UINT8 EndPointAddress,\r
1268 IN UINT8 MaximumPacketLength,\r
1269 IN OUT VOID *Data,\r
1270 IN UINTN DataLength,\r
1271 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1272 IN VOID *Context OPTIONAL\r
1273 )\r
1274{\r
1275 return EFI_UNSUPPORTED;\r
1276}\r
1277\r
1278\r
1279\r
1280/**\r
1281 Provides software reset for the USB host controller according to UEFI 2.0 spec.\r
1282\r
1283 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1284 @param Attributes A bit mask of the reset operation to perform. See\r
1285 below for a list of the supported bit mask values.\r
1286\r
1287 @return EFI_SUCCESS : The reset operation succeeded.\r
1288 @return EFI_INVALID_PARAMETER : Attributes is not valid.\r
1289 @return EFI_UNSUPPORTED : This type of reset is not currently supported\r
1290 @return EFI_DEVICE_ERROR : Other errors\r
1291\r
1292**/\r
1293STATIC\r
1294EFI_STATUS\r
1295EFIAPI\r
1296Uhci2Reset (\r
1297 IN EFI_USB2_HC_PROTOCOL *This,\r
1298 IN UINT16 Attributes\r
1299 )\r
1300{\r
1301 USB_HC_DEV *UhciDev;\r
1302\r
1303 UhciDev = UHC_FROM_USB2_HC_PROTO (This);\r
1304\r
1305 if ((Attributes == EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG) ||\r
1306 (Attributes == EFI_USB_HC_RESET_HOST_WITH_DEBUG)) {\r
1307 return EFI_UNSUPPORTED;\r
1308 }\r
1309\r
1310 return UhciReset (&UhciDev->UsbHc, Attributes);\r
1311}\r
1312\r
1313\r
1314/**\r
1315 Retrieves current state of the USB host controller according to UEFI 2.0 spec.\r
1316\r
1317 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1318 @param State Variable to receive current device state\r
1319\r
1320 @return EFI_SUCCESS : The state is returned\r
1321 @return EFI_INVALID_PARAMETER : State is not valid.\r
1322 @return EFI_DEVICE_ERROR : Other errors2006\r
1323\r
1324**/\r
1325STATIC\r
1326EFI_STATUS\r
1327EFIAPI\r
1328Uhci2GetState (\r
1329 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
1330 OUT EFI_USB_HC_STATE *State\r
1331 )\r
1332{\r
1333 USB_HC_DEV *Uhc;\r
1334\r
1335 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1336 return UhciGetState (&Uhc->UsbHc, State);\r
1337}\r
1338\r
1339\r
1340/**\r
1341 Sets the USB host controller to a specific state according to UEFI 2.0 spec.\r
1342\r
1343 @param This A pointer to the EFI_USB_HC_PROTOCOL instance.\r
1344 @param State Indicates the state of the host controller that will\r
1345 be set.\r
1346\r
1347 @return EFI_SUCCESS : Host controller was successfully placed in the state\r
1348 @return EFI_INVALID_PARAMETER : State is invalid.\r
1349 @return EFI_DEVICE_ERROR : Failed to set the state\r
1350\r
1351**/\r
1352STATIC\r
1353EFI_STATUS\r
1354EFIAPI\r
1355Uhci2SetState (\r
1356 IN EFI_USB2_HC_PROTOCOL *This,\r
1357 IN EFI_USB_HC_STATE State\r
1358 )\r
1359{\r
1360 USB_HC_DEV *Uhc;\r
1361\r
1362 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1363 return UhciSetState (&Uhc->UsbHc, State);\r
1364}\r
1365\r
1366\r
1367/**\r
1368 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.\r
1369\r
1370 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance\r
1371 @param MaxSpeed A pointer to the max speed USB host controller\r
1372 supports.\r
1373 @param PortNumber A pointer to the number of root hub ports.\r
1374 @param Is64BitCapable A pointer to an integer to show whether USB host\r
1375 controller supports 64-bit memory addressing.\r
1376\r
1377 @return EFI_SUCCESS : capabilities were retrieved successfully.\r
1378 @return EFI_INVALID_PARAMETER : MaxSpeed or PortNumber or Is64BitCapable is NULL.\r
1379 @return EFI_DEVICE_ERROR : An error was encountered\r
1380\r
1381**/\r
1382STATIC\r
1383EFI_STATUS\r
1384EFIAPI\r
1385Uhci2GetCapability (\r
1386 IN EFI_USB2_HC_PROTOCOL *This,\r
1387 OUT UINT8 *MaxSpeed,\r
1388 OUT UINT8 *PortNumber,\r
1389 OUT UINT8 *Is64BitCapable\r
1390 )\r
1391{\r
1392 USB_HC_DEV *Uhc;\r
1393\r
1394 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1395\r
1396 if ((NULL == MaxSpeed) || (NULL == PortNumber) || (NULL == Is64BitCapable)) {\r
1397 return EFI_INVALID_PARAMETER;\r
1398 }\r
1399\r
1400 *MaxSpeed = EFI_USB_SPEED_FULL;\r
1401 *Is64BitCapable = (UINT8) FALSE;\r
1402\r
1403 return UhciGetRootHubPortNumber (&Uhc->UsbHc, PortNumber);\r
1404}\r
1405\r
1406\r
1407/**\r
1408 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.\r
1409\r
1410 @param This A pointer to the EFI_USB2_HC_PROTOCOL.\r
1411 @param PortNumber The port to get status\r
1412 @param PortStatus A pointer to the current port status bits and port\r
1413 status change bits.\r
1414\r
1415 @return EFI_SUCCESS : status of the USB root hub port was returned in PortStatus.\r
1416 @return EFI_INVALID_PARAMETER : PortNumber is invalid.\r
1417 @return EFI_DEVICE_ERROR : Can't read register\r
1418\r
1419**/\r
1420STATIC\r
1421EFI_STATUS\r
1422EFIAPI\r
1423Uhci2GetRootHubPortStatus (\r
1424 IN CONST EFI_USB2_HC_PROTOCOL *This,\r
1425 IN CONST UINT8 PortNumber,\r
1426 OUT EFI_USB_PORT_STATUS *PortStatus\r
1427 )\r
1428{\r
1429 USB_HC_DEV *Uhc;\r
1430\r
1431 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1432\r
1433 return UhciGetRootHubPortStatus (&Uhc->UsbHc, PortNumber, PortStatus);\r
1434}\r
1435\r
1436\r
1437/**\r
1438 Sets a feature for the specified root hub port according to UEFI 2.0 spec.\r
1439\r
1440 @param This A pointer to the EFI_USB2_HC_PROTOCOL.\r
1441 @param PortNumber Specifies the root hub port whose feature is\r
1442 requested to be set.\r
1443 @param PortFeature Indicates the feature selector associated with the\r
1444 feature set request.\r
1445\r
1446 @return EFI_SUCCESS : PortFeature was set for the root port\r
1447 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
1448 @return EFI_DEVICE_ERROR : Can't read register\r
1449\r
1450**/\r
1451STATIC\r
1452EFI_STATUS\r
1453EFIAPI\r
1454Uhci2SetRootHubPortFeature (\r
1455 IN EFI_USB2_HC_PROTOCOL *This,\r
1456 IN UINT8 PortNumber,\r
1457 IN EFI_USB_PORT_FEATURE PortFeature\r
1458 )\r
1459{\r
1460 USB_HC_DEV *Uhc;\r
1461\r
1462 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1463\r
1464 return UhciSetRootHubPortFeature (&Uhc->UsbHc, PortNumber, PortFeature);\r
1465}\r
1466\r
1467\r
1468/**\r
1469 Clears a feature for the specified root hub port according to Uefi 2.0 spec.\r
1470\r
1471 @param This A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1472 @param PortNumber Specifies the root hub port whose feature is\r
1473 requested to be cleared.\r
1474 @param PortFeature Indicates the feature selector associated with the\r
1475 feature clear request.\r
1476\r
1477 @return EFI_SUCCESS : PortFeature was cleared for the USB root hub port\r
1478 @return EFI_INVALID_PARAMETER : PortNumber is invalid or PortFeature is invalid.\r
1479 @return EFI_DEVICE_ERROR : Can't read register\r
1480\r
1481**/\r
1482STATIC\r
1483EFI_STATUS\r
1484EFIAPI\r
1485Uhci2ClearRootHubPortFeature (\r
1486 IN EFI_USB2_HC_PROTOCOL *This,\r
1487 IN UINT8 PortNumber,\r
1488 IN EFI_USB_PORT_FEATURE PortFeature\r
1489 )\r
1490{\r
1491 USB_HC_DEV *Uhc;\r
1492\r
1493 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1494\r
1495 return UhciClearRootHubPortFeature (&Uhc->UsbHc, PortNumber, PortFeature);\r
1496}\r
1497\r
1498\r
1499/**\r
1500 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..\r
1501\r
1502 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1503 DeviceAddress : Target device address\r
1504 DeviceSpeed : Device speed\r
1505 MaximumPacketLength : Maximum packet size of the target endpoint\r
1506 Request : USB device request to send\r
1507 TransferDirection : Data direction of the Data stage in control transfer\r
1508 Data : Data to transmit/receive in data stage\r
1509 DataLength : Length of the data\r
1510 TimeOut : Maximum time, in microseconds, for transfer to complete.\r
1511 TransferResult : Variable to receive the transfer result\r
1512\r
1513 @return EFI_SUCCESS : The control transfer was completed successfully.\r
1514 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1515 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1516 @return EFI_TIMEOUT : Failed due to timeout.\r
1517 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
1518\r
1519**/\r
1520STATIC\r
1521EFI_STATUS\r
1522EFIAPI\r
1523Uhci2ControlTransfer (\r
1524 IN EFI_USB2_HC_PROTOCOL *This,\r
1525 IN UINT8 DeviceAddress,\r
1526 IN UINT8 DeviceSpeed,\r
1527 IN UINTN MaximumPacketLength,\r
1528 IN EFI_USB_DEVICE_REQUEST *Request,\r
1529 IN EFI_USB_DATA_DIRECTION TransferDirection,\r
1530 IN OUT VOID *Data,\r
1531 IN OUT UINTN *DataLength,\r
1532 IN UINTN TimeOut,\r
1533 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1534 OUT UINT32 *TransferResult\r
1535 )\r
1536{\r
1537 USB_HC_DEV *Uhc;\r
1538 BOOLEAN IsSlow;\r
1539\r
1540 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
c52fa98c 1541 IsSlow = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
913cb9dc 1542\r
1543 return UhciControlTransfer (\r
1544 &Uhc->UsbHc,\r
1545 DeviceAddress,\r
1546 IsSlow,\r
1547 (UINT8) MaximumPacketLength,\r
1548 Request,\r
1549 TransferDirection,\r
1550 Data,\r
1551 DataLength,\r
1552 TimeOut,\r
1553 TransferResult\r
1554 );\r
1555}\r
1556\r
1557\r
1558/**\r
1559 Submits bulk transfer to a bulk endpoint of a USB device\r
1560\r
1561 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1562 DeviceAddress : Target device address\r
1563 EndPointAddress : Endpoint number and direction\r
1564 DeviceSpeed : Device speed\r
1565 MaximumPacketLength : Maximum packet size of the target endpoint\r
1566 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1567 Data : Array of pointers to the buffers of data\r
1568 DataLength : On input, size of the data buffer, On output,\r
1569 actually transferred data size.\r
1570 DataToggle : On input, data toggle to use; On output, next data toggle\r
1571 Translator : A pointr to the transaction translator data.\r
1572 TimeOut : Maximum time out, in microseconds\r
1573 TransferResult : Variable to receive transfer result\r
1574\r
1575 @return EFI_SUCCESS : The bulk transfer was completed successfully.\r
1576 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1577 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1578 @return EFI_TIMEOUT : Failed due to timeout.\r
1579 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
1580\r
1581**/\r
1582STATIC\r
1583EFI_STATUS\r
1584EFIAPI\r
1585Uhci2BulkTransfer (\r
1586 IN EFI_USB2_HC_PROTOCOL *This,\r
1587 IN UINT8 DeviceAddress,\r
1588 IN UINT8 EndPointAddress,\r
1589 IN UINT8 DeviceSpeed,\r
1590 IN UINTN MaximumPacketLength,\r
1591 IN UINT8 DataBuffersNumber,\r
1592 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],\r
1593 IN OUT UINTN *DataLength,\r
1594 IN OUT UINT8 *DataToggle,\r
1595 IN UINTN TimeOut,\r
1596 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1597 OUT UINT32 *TransferResult\r
1598 )\r
1599{\r
1600 USB_HC_DEV *Uhc;\r
1601\r
1602 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
1603\r
1604 if (Data == NULL || DeviceSpeed == EFI_USB_SPEED_LOW) {\r
1605 return EFI_INVALID_PARAMETER;\r
1606 }\r
1607\r
1608 //\r
1609 // For full-speed bulk transfers only the data pointed by Data[0] shall be used\r
1610 //\r
1611 return UhciBulkTransfer (\r
1612 &Uhc->UsbHc,\r
1613 DeviceAddress,\r
1614 EndPointAddress,\r
1615 (UINT8) MaximumPacketLength,\r
1616 *Data,\r
1617 DataLength,\r
1618 DataToggle,\r
1619 TimeOut,\r
1620 TransferResult\r
1621 );\r
1622}\r
1623\r
1624\r
1625/**\r
1626 Submits an asynchronous interrupt transfer to an\r
1627 interrupt endpoint of a USB device according to UEFI 2.0 spec.\r
1628\r
1629 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1630 DeviceAddress : Target device address\r
1631 EndPointAddress : Endpoint number and direction\r
1632 DeviceSpeed : Device speed\r
1633 MaximumPacketLength : Maximum packet size of the target endpoint\r
1634 IsNewTransfer : If TRUE, submit a new transfer, if FALSE cancel old transfer\r
1635 DataToggle : On input, data toggle to use; On output, next data toggle\r
1636 PollingInterval : Interrupt poll rate in milliseconds\r
1637 DataLength : On input, size of the data buffer, On output,\r
1638 actually transferred data size.\r
1639 Translator : A pointr to the transaction translator data.\r
1640 CallBackFunction : Function to call periodically\r
1641 Context : User context\r
1642\r
1643 @return EFI_SUCCESS : Transfer was submitted\r
1644 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1645 @return EFI_OUT_OF_RESOURCES : Failed due to a lack of resources.\r
1646 @return EFI_DEVICE_ERROR : Can't read register\r
1647\r
1648**/\r
1649STATIC\r
1650EFI_STATUS\r
1651EFIAPI\r
1652Uhci2AsyncInterruptTransfer (\r
1653 IN EFI_USB2_HC_PROTOCOL *This,\r
1654 IN UINT8 DeviceAddress,\r
1655 IN UINT8 EndPointAddress,\r
1656 IN UINT8 DeviceSpeed,\r
1657 IN UINTN MaximumPacketLength,\r
1658 IN BOOLEAN IsNewTransfer,\r
1659 IN OUT UINT8 *DataToggle,\r
1660 IN UINTN PollingInterval,\r
1661 IN UINTN DataLength,\r
1662 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1663 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,\r
1664 IN VOID *Context\r
1665 )\r
1666{\r
1667 USB_HC_DEV *Uhc;\r
1668 BOOLEAN IsSlow;\r
1669\r
1670 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
c52fa98c 1671 IsSlow = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
913cb9dc 1672\r
1673 return UhciAsyncInterruptTransfer (\r
1674 &Uhc->UsbHc,\r
1675 DeviceAddress,\r
1676 EndPointAddress,\r
1677 IsSlow,\r
1678 (UINT8) MaximumPacketLength,\r
1679 IsNewTransfer,\r
1680 DataToggle,\r
1681 PollingInterval,\r
1682 DataLength,\r
1683 CallBackFunction,\r
1684 Context\r
1685 );\r
1686}\r
1687\r
1688\r
1689/**\r
1690 Submits synchronous interrupt transfer to an interrupt endpoint\r
1691 of a USB device according to UEFI 2.0 spec.\r
1692\r
1693 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1694 DeviceAddress : Target device address\r
1695 EndPointAddress : Endpoint number and direction\r
1696 DeviceSpeed : Device speed\r
1697 MaximumPacketLength : Maximum packet size of the target endpoint\r
1698 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1699 Data : Array of pointers to the buffers of data\r
1700 DataLength : On input, size of the data buffer, On output,\r
1701 actually transferred data size.\r
1702 DataToggle : On input, data toggle to use; On output, next data toggle\r
1703 TimeOut : Maximum time out, in microseconds\r
1704 Translator : A pointr to the transaction translator data.\r
1705 TransferResult : Variable to receive transfer result\r
1706\r
1707 @return EFI_SUCCESS : The transfer was completed successfully.\r
1708 @return EFI_OUT_OF_RESOURCES : Failed due to lack of resource.\r
1709 @return EFI_INVALID_PARAMETER : Some parameters are invalid.\r
1710 @return EFI_TIMEOUT : Failed due to timeout.\r
1711 @return EFI_DEVICE_ERROR : Failed due to host controller or device error.\r
1712\r
1713**/\r
1714STATIC\r
1715EFI_STATUS\r
1716EFIAPI\r
1717Uhci2SyncInterruptTransfer (\r
1718 IN EFI_USB2_HC_PROTOCOL *This,\r
1719 IN UINT8 DeviceAddress,\r
1720 IN UINT8 EndPointAddress,\r
1721 IN UINT8 DeviceSpeed,\r
1722 IN UINTN MaximumPacketLength,\r
1723 IN OUT VOID *Data,\r
1724 IN OUT UINTN *DataLength,\r
1725 IN OUT UINT8 *DataToggle,\r
1726 IN UINTN TimeOut,\r
1727 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1728 OUT UINT32 *TransferResult\r
1729 )\r
1730{\r
1731 USB_HC_DEV *Uhc;\r
1732 BOOLEAN IsSlow;\r
1733\r
1734 if (DeviceSpeed == EFI_USB_SPEED_HIGH) {\r
1735 return EFI_INVALID_PARAMETER;\r
1736 }\r
1737\r
1738 Uhc = UHC_FROM_USB2_HC_PROTO (This);\r
c52fa98c 1739 IsSlow = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);\r
913cb9dc 1740\r
1741 return UhciSyncInterruptTransfer (\r
1742 &Uhc->UsbHc,\r
1743 DeviceAddress,\r
1744 EndPointAddress,\r
1745 IsSlow,\r
1746 (UINT8) MaximumPacketLength,\r
1747 Data,\r
1748 DataLength,\r
1749 DataToggle,\r
1750 TimeOut,\r
1751 TransferResult\r
1752 );\r
1753}\r
1754\r
1755\r
1756/**\r
1757 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1758\r
1759 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1760 DeviceAddress : Target device address\r
1761 EndPointAddress : Endpoint number and direction\r
1762 DeviceSpeed : Device speed\r
1763 MaximumPacketLength : Maximum packet size of the target endpoint\r
1764 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1765 Data : Array of pointers to the buffers of data\r
1766 DataLength : On input, size of the data buffer, On output,\r
1767 actually transferred data size.\r
1768 Translator : A pointr to the transaction translator data.\r
1769 TransferResult : Variable to receive transfer result\r
1770\r
1771 @return EFI_UNSUPPORTED\r
1772\r
1773**/\r
1774STATIC\r
1775EFI_STATUS\r
1776EFIAPI\r
1777Uhci2IsochronousTransfer (\r
1778 IN EFI_USB2_HC_PROTOCOL *This,\r
1779 IN UINT8 DeviceAddress,\r
1780 IN UINT8 EndPointAddress,\r
1781 IN UINT8 DeviceSpeed,\r
1782 IN UINTN MaximumPacketLength,\r
1783 IN UINT8 DataBuffersNumber,\r
1784 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1785 IN UINTN DataLength,\r
1786 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1787 OUT UINT32 *TransferResult\r
1788 )\r
1789{\r
1790 return EFI_UNSUPPORTED;\r
1791}\r
1792\r
1793\r
1794/**\r
1795 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.\r
1796\r
1797 This : A pointer to the EFI_USB2_HC_PROTOCOL instance.\r
1798 DeviceAddress : Target device address\r
1799 EndPointAddress : Endpoint number and direction\r
1800 DeviceSpeed : Device speed\r
1801 MaximumPacketLength : Maximum packet size of the target endpoint\r
1802 DataBuffersNumber : Number of data buffers prepared for the transfer.\r
1803 Data : Array of pointers to the buffers of data\r
1804 Translator : A pointr to the transaction translator data.\r
1805 IsochronousCallBack : Function to call when the transfer complete\r
1806 Context : Pass to the call back function as parameter\r
1807\r
1808 @return EFI_UNSUPPORTED\r
1809\r
1810**/\r
1811STATIC\r
1812EFI_STATUS\r
1813EFIAPI\r
1814Uhci2AsyncIsochronousTransfer (\r
1815 IN EFI_USB2_HC_PROTOCOL *This,\r
1816 IN UINT8 DeviceAddress,\r
1817 IN UINT8 EndPointAddress,\r
1818 IN UINT8 DeviceSpeed,\r
1819 IN UINTN MaximumPacketLength,\r
1820 IN UINT8 DataBuffersNumber,\r
1821 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],\r
1822 IN UINTN DataLength,\r
1823 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,\r
1824 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,\r
1825 IN VOID *Context\r
1826 )\r
1827{\r
1828 return EFI_UNSUPPORTED;\r
1829}\r
1830\r
913cb9dc 1831EFI_STATUS\r
1832EFIAPI\r
1833UhciDriverEntryPoint (\r
1834 IN EFI_HANDLE ImageHandle,\r
1835 IN EFI_SYSTEM_TABLE *SystemTable\r
1836 )\r
1837/*++\r
1838\r
1839 Routine Description:\r
1840\r
1841 Entry point for EFI drivers.\r
1842\r
1843 Arguments:\r
1844\r
1845 ImageHandle - EFI_HANDLE\r
1846 SystemTable - EFI_SYSTEM_TABLE\r
1847\r
1848 Returns:\r
1849\r
1850 EFI_SUCCESS : Driver is successfully loaded\r
1851 Others : Failed\r
1852\r
1853--*/\r
1854{\r
1855 return EfiLibInstallAllDriverProtocols (\r
1856 ImageHandle,\r
1857 SystemTable,\r
1858 &gUhciDriverBinding,\r
1859 ImageHandle,\r
1860 &gUhciComponentName,\r
1861 NULL,\r
1862 NULL\r
1863 );\r
1864}\r
1865\r
1866\r
1867/**\r
1868 Test to see if this driver supports ControllerHandle. Any\r
1869 ControllerHandle that has UsbHcProtocol installed will be supported.\r
1870\r
1871 @param This Protocol instance pointer.\r
1872 @param Controller Handle of device to test\r
1873 @param RemainingDevicePath Not used\r
1874\r
1875 @return EFI_SUCCESS : This driver supports this device.\r
1876 @return EFI_UNSUPPORTED : This driver does not support this device.\r
1877\r
1878**/\r
1879EFI_STATUS\r
1880EFIAPI\r
1881UhciDriverBindingSupported (\r
1882 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1883 IN EFI_HANDLE Controller,\r
1884 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
1885 )\r
1886{\r
1887 EFI_STATUS OpenStatus;\r
1888 EFI_STATUS Status;\r
1889 EFI_PCI_IO_PROTOCOL *PciIo;\r
1890 USB_CLASSC UsbClassCReg;\r
1891\r
1892 //\r
1893 // Test whether there is PCI IO Protocol attached on the controller handle.\r
1894 //\r
1895 OpenStatus = gBS->OpenProtocol (\r
1896 Controller,\r
1897 &gEfiPciIoProtocolGuid,\r
c52fa98c 1898 (VOID **) &PciIo,\r
913cb9dc 1899 This->DriverBindingHandle,\r
1900 Controller,\r
1901 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1902 );\r
1903\r
1904 if (EFI_ERROR (OpenStatus)) {\r
1905 return OpenStatus;\r
1906 }\r
1907\r
1908 Status = PciIo->Pci.Read (\r
1909 PciIo,\r
1910 EfiPciIoWidthUint8,\r
1911 CLASSC_OFFSET,\r
1912 sizeof (USB_CLASSC) / sizeof (UINT8),\r
1913 &UsbClassCReg\r
1914 );\r
1915\r
1916 if (EFI_ERROR (Status)) {\r
1917 Status = EFI_UNSUPPORTED;\r
1918 goto ON_EXIT;\r
1919 }\r
1920\r
1921 //\r
1922 // Test whether the controller belongs to UHCI type\r
1923 //\r
1924 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||\r
1925 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||\r
1926 (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)\r
1927 ) {\r
1928\r
1929 Status = EFI_UNSUPPORTED;\r
1930 }\r
1931\r
1932ON_EXIT:\r
1933 gBS->CloseProtocol (\r
1934 Controller,\r
1935 &gEfiPciIoProtocolGuid,\r
1936 This->DriverBindingHandle,\r
1937 Controller\r
1938 );\r
1939\r
1940 return Status;\r
1941\r
1942}\r
1943\r
1944\r
1945/**\r
1946 Allocate and initialize the empty UHCI device\r
1947\r
1948 @param PciIo The PCIIO to use\r
1949\r
1950 @return Allocated UHCI device\r
1951\r
1952**/\r
1953STATIC\r
1954USB_HC_DEV *\r
1955UhciAllocateDev (\r
1956 IN EFI_PCI_IO_PROTOCOL *PciIo\r
1957 )\r
1958{\r
1959 USB_HC_DEV *Uhc;\r
1960 EFI_STATUS Status;\r
1961\r
1962 Uhc = AllocateZeroPool (sizeof (USB_HC_DEV));\r
1963\r
1964 if (Uhc == NULL) {\r
1965 return NULL;\r
1966 }\r
1967\r
1968 //\r
1969 // This driver supports both USB_HC_PROTOCOL and USB2_HC_PROTOCOL.\r
1970 // USB_HC_PROTOCOL is for EFI 1.1 backward compability.\r
1971 //\r
1972 Uhc->Signature = USB_HC_DEV_SIGNATURE;\r
1973 Uhc->UsbHc.Reset = UhciReset;\r
1974 Uhc->UsbHc.GetState = UhciGetState;\r
1975 Uhc->UsbHc.SetState = UhciSetState;\r
1976 Uhc->UsbHc.ControlTransfer = UhciControlTransfer;\r
1977 Uhc->UsbHc.BulkTransfer = UhciBulkTransfer;\r
1978 Uhc->UsbHc.AsyncInterruptTransfer = UhciAsyncInterruptTransfer;\r
1979 Uhc->UsbHc.SyncInterruptTransfer = UhciSyncInterruptTransfer;\r
1980 Uhc->UsbHc.IsochronousTransfer = UhciIsochronousTransfer;\r
1981 Uhc->UsbHc.AsyncIsochronousTransfer = UhciAsyncIsochronousTransfer;\r
1982 Uhc->UsbHc.GetRootHubPortNumber = UhciGetRootHubPortNumber;\r
1983 Uhc->UsbHc.GetRootHubPortStatus = UhciGetRootHubPortStatus;\r
1984 Uhc->UsbHc.SetRootHubPortFeature = UhciSetRootHubPortFeature;\r
1985 Uhc->UsbHc.ClearRootHubPortFeature = UhciClearRootHubPortFeature;\r
1986 Uhc->UsbHc.MajorRevision = 0x1;\r
1987 Uhc->UsbHc.MinorRevision = 0x1;\r
1988\r
1989 Uhc->Usb2Hc.GetCapability = Uhci2GetCapability;\r
1990 Uhc->Usb2Hc.Reset = Uhci2Reset;\r
1991 Uhc->Usb2Hc.GetState = Uhci2GetState;\r
1992 Uhc->Usb2Hc.SetState = Uhci2SetState;\r
1993 Uhc->Usb2Hc.ControlTransfer = Uhci2ControlTransfer;\r
1994 Uhc->Usb2Hc.BulkTransfer = Uhci2BulkTransfer;\r
1995 Uhc->Usb2Hc.AsyncInterruptTransfer = Uhci2AsyncInterruptTransfer;\r
1996 Uhc->Usb2Hc.SyncInterruptTransfer = Uhci2SyncInterruptTransfer;\r
1997 Uhc->Usb2Hc.IsochronousTransfer = Uhci2IsochronousTransfer;\r
1998 Uhc->Usb2Hc.AsyncIsochronousTransfer = Uhci2AsyncIsochronousTransfer;\r
1999 Uhc->Usb2Hc.GetRootHubPortStatus = Uhci2GetRootHubPortStatus;\r
2000 Uhc->Usb2Hc.SetRootHubPortFeature = Uhci2SetRootHubPortFeature;\r
2001 Uhc->Usb2Hc.ClearRootHubPortFeature = Uhci2ClearRootHubPortFeature;\r
2002 Uhc->Usb2Hc.MajorRevision = 0x1;\r
2003 Uhc->Usb2Hc.MinorRevision = 0x1;\r
2004\r
2005 Uhc->PciIo = PciIo;\r
2006 Uhc->MemPool = UsbHcInitMemPool (PciIo, TRUE, 0);\r
2007\r
2008 if (Uhc->MemPool == NULL) {\r
2009 Status = EFI_OUT_OF_RESOURCES;\r
2010 goto ON_ERROR;\r
2011 }\r
2012\r
2013 InitializeListHead (&Uhc->AsyncIntList);\r
2014\r
2015 Status = gBS->CreateEvent (\r
2016 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
2017 TPL_CALLBACK,\r
2018 UhciMonitorAsyncReqList,\r
2019 Uhc,\r
2020 &Uhc->AsyncIntMonitor\r
2021 );\r
2022\r
2023 if (EFI_ERROR (Status)) {\r
2024 UsbHcFreeMemPool (Uhc->MemPool);\r
2025 goto ON_ERROR;\r
2026 }\r
2027\r
2028 return Uhc;\r
2029\r
2030ON_ERROR:\r
2031 gBS->FreePool (Uhc);\r
2032 return NULL;\r
2033}\r
2034\r
2035\r
2036/**\r
2037 Free the UHCI device and release its associated resources\r
2038\r
2039 @param Uhc The UHCI device to release\r
2040\r
2041 @return None\r
2042\r
2043**/\r
2044STATIC\r
2045VOID\r
2046UhciFreeDev (\r
2047 IN USB_HC_DEV *Uhc\r
2048 )\r
2049{\r
2050 if (Uhc->AsyncIntMonitor != NULL) {\r
2051 gBS->CloseEvent (Uhc->AsyncIntMonitor);\r
2052 }\r
2053\r
2054 if (Uhc->MemPool != NULL) {\r
2055 UsbHcFreeMemPool (Uhc->MemPool);\r
2056 }\r
2057\r
2058 if (Uhc->CtrlNameTable) {\r
2059 FreeUnicodeStringTable (Uhc->CtrlNameTable);\r
2060 }\r
2061\r
2062 gBS->FreePool (Uhc);\r
2063}\r
2064\r
2065\r
2066/**\r
2067 Uninstall all Uhci Interface\r
2068\r
2069 @param Controller Controller handle\r
2070 @param This Protocol instance pointer.\r
2071\r
2072 @return VOID\r
2073\r
2074**/\r
2075STATIC\r
2076VOID\r
2077UhciCleanDevUp (\r
2078 IN EFI_HANDLE Controller,\r
2079 IN EFI_USB_HC_PROTOCOL *This\r
2080 )\r
2081{\r
2082 USB_HC_DEV *Uhc;\r
2083\r
2084 //\r
2085 // Uninstall the USB_HC and USB_HC2 protocol, then disable the controller\r
2086 //\r
2087 Uhc = UHC_FROM_USB_HC_PROTO (This);\r
2088 UhciStopHc (Uhc, STALL_1_SECOND);\r
2089\r
2090 gBS->UninstallProtocolInterface (\r
2091 Controller,\r
2092 &gEfiUsbHcProtocolGuid,\r
2093 &Uhc->UsbHc\r
2094 );\r
2095\r
2096 gBS->UninstallProtocolInterface (\r
2097 Controller,\r
2098 &gEfiUsb2HcProtocolGuid,\r
2099 &Uhc->Usb2Hc\r
2100 );\r
2101\r
2102 UhciFreeAllAsyncReq (Uhc);\r
2103 UhciDestoryFrameList (Uhc);\r
2104\r
2105 Uhc->PciIo->Attributes (\r
2106 Uhc->PciIo,\r
2107 EfiPciIoAttributeOperationDisable,\r
2108 EFI_PCI_DEVICE_ENABLE,\r
2109 NULL\r
2110 );\r
2111\r
2112 UhciFreeDev (Uhc);\r
2113}\r
2114\r
2115\r
2116/**\r
2117 Starting the Usb UHCI Driver\r
2118\r
2119 @param This Protocol instance pointer.\r
2120 @param Controller Handle of device to test\r
2121 @param RemainingDevicePath Not used\r
2122\r
2123 @retval EFI_SUCCESS This driver supports this device.\r
2124 @retval EFI_UNSUPPORTED This driver does not support this device.\r
2125 @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error\r
2126 EFI_OUT_OF_RESOURCES- Failed due to resource\r
2127 shortage\r
2128\r
2129**/\r
2130EFI_STATUS\r
2131EFIAPI\r
2132UhciDriverBindingStart (\r
2133 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2134 IN EFI_HANDLE Controller,\r
2135 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
2136 )\r
2137{\r
2138 EFI_STATUS Status;\r
2139 EFI_PCI_IO_PROTOCOL *PciIo;\r
2140 USB_HC_DEV *Uhc;\r
2141\r
2142 //\r
2143 // Open PCIIO, then enable the EHC device and turn off emulation\r
2144 //\r
2145 Uhc = NULL;\r
2146 Status = gBS->OpenProtocol (\r
2147 Controller,\r
2148 &gEfiPciIoProtocolGuid,\r
c52fa98c 2149 (VOID **) &PciIo,\r
913cb9dc 2150 This->DriverBindingHandle,\r
2151 Controller,\r
2152 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2153 );\r
2154\r
2155 if (EFI_ERROR (Status)) {\r
2156 return Status;\r
2157 }\r
2158\r
2159 UhciTurnOffUsbEmulation (PciIo);\r
2160\r
2161 Status = PciIo->Attributes (\r
2162 PciIo,\r
2163 EfiPciIoAttributeOperationEnable,\r
2164 EFI_PCI_DEVICE_ENABLE,\r
2165 NULL\r
2166 );\r
2167\r
2168 if (EFI_ERROR (Status)) {\r
2169 goto CLOSE_PCIIO;\r
2170 }\r
2171\r
2172 Uhc = UhciAllocateDev (PciIo);\r
2173\r
2174 if (Uhc == NULL) {\r
2175 Status = EFI_OUT_OF_RESOURCES;\r
2176 goto CLOSE_PCIIO;\r
2177 }\r
2178\r
2179 //\r
2180 // Allocate and Init Host Controller's Frame List Entry\r
2181 //\r
2182 Status = UhciInitFrameList (Uhc);\r
2183\r
2184 if (EFI_ERROR (Status)) {\r
2185 Status = EFI_OUT_OF_RESOURCES;\r
2186 goto FREE_UHC;\r
2187 }\r
2188\r
2189 Status = gBS->SetTimer (\r
2190 Uhc->AsyncIntMonitor,\r
2191 TimerPeriodic,\r
2192 INTERRUPT_POLLING_TIME\r
2193 );\r
2194\r
2195 if (EFI_ERROR (Status)) {\r
2196 goto FREE_UHC;\r
2197 }\r
2198\r
2199 //\r
2200 // Install both USB_HC_PROTOCOL and USB2_HC_PROTOCOL\r
2201 //\r
2202 Status = gBS->InstallMultipleProtocolInterfaces (\r
2203 &Controller,\r
2204 &gEfiUsbHcProtocolGuid,\r
2205 &Uhc->UsbHc,\r
2206 &gEfiUsb2HcProtocolGuid,\r
2207 &Uhc->Usb2Hc,\r
2208 NULL\r
2209 );\r
2210\r
2211 if (EFI_ERROR (Status)) {\r
2212 goto FREE_UHC;\r
2213 }\r
2214\r
2215 //\r
2216 // Install the component name protocol\r
2217 //\r
2218 Uhc->CtrlNameTable = NULL;\r
2219\r
2220 AddUnicodeString (\r
2221 "eng",\r
2222 gUhciComponentName.SupportedLanguages,\r
2223 &Uhc->CtrlNameTable,\r
2224 L"Usb Universal Host Controller"\r
2225 );\r
2226\r
2227 //\r
2228 // Start the UHCI hardware, also set its reclamation point to 64 bytes\r
2229 //\r
2230 UhciWriteReg (Uhc->PciIo, USBCMD_OFFSET, USBCMD_RS | USBCMD_MAXP);\r
2231\r
2232 return EFI_SUCCESS;\r
2233\r
2234FREE_UHC:\r
2235 UhciFreeDev (Uhc);\r
2236\r
2237CLOSE_PCIIO:\r
2238 gBS->CloseProtocol (\r
2239 Controller,\r
2240 &gEfiPciIoProtocolGuid,\r
2241 This->DriverBindingHandle,\r
2242 Controller\r
2243 );\r
2244\r
2245 return Status;\r
2246}\r
2247\r
2248\r
2249/**\r
2250 Stop this driver on ControllerHandle. Support stoping any child handles\r
2251 created by this driver.\r
2252\r
2253 @param This Protocol instance pointer.\r
2254 @param Controller Handle of device to stop driver on\r
2255 @param NumberOfChildren Number of Children in the ChildHandleBuffer\r
2256 @param ChildHandleBuffer List of handles for the children we need to stop.\r
2257\r
2258 @return EFI_SUCCESS\r
2259 @return others\r
2260\r
2261**/\r
2262EFI_STATUS\r
2263EFIAPI\r
2264UhciDriverBindingStop (\r
2265 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2266 IN EFI_HANDLE Controller,\r
2267 IN UINTN NumberOfChildren,\r
2268 IN EFI_HANDLE *ChildHandleBuffer\r
2269 )\r
2270{\r
2271 EFI_USB_HC_PROTOCOL *UsbHc;\r
2272 EFI_USB2_HC_PROTOCOL *Usb2Hc;\r
2273 EFI_STATUS Status;\r
2274\r
2275 Status = gBS->OpenProtocol (\r
2276 Controller,\r
2277 &gEfiUsbHcProtocolGuid,\r
c52fa98c 2278 (VOID **) &UsbHc,\r
913cb9dc 2279 This->DriverBindingHandle,\r
2280 Controller,\r
2281 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2282 );\r
2283 //\r
2284 // Test whether the Controller handler passed in is a valid\r
2285 // Usb controller handle that should be supported, if not,\r
2286 // return the error status directly\r
2287 //\r
2288 if (EFI_ERROR (Status)) {\r
2289 return Status;\r
2290 }\r
2291\r
2292 Status = gBS->OpenProtocol (\r
2293 Controller,\r
2294 &gEfiUsb2HcProtocolGuid,\r
c52fa98c 2295 (VOID **) &Usb2Hc,\r
913cb9dc 2296 This->DriverBindingHandle,\r
2297 Controller,\r
2298 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2299 );\r
2300\r
2301 //\r
2302 // Test whether the Controller handler passed in is a valid\r
2303 // Usb controller handle that should be supported, if not,\r
2304 // return the error status directly\r
2305 //\r
2306 if (EFI_ERROR (Status)) {\r
2307 return Status;\r
2308 }\r
2309\r
2310 UhciCleanDevUp (Controller, UsbHc);\r
2311\r
2312 gBS->CloseProtocol (\r
2313 Controller,\r
2314 &gEfiPciIoProtocolGuid,\r
2315 This->DriverBindingHandle,\r
2316 Controller\r
2317 );\r
2318\r
2319 return EFI_SUCCESS;\r
2320}\r
2321\r
2322EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {\r
2323 UhciDriverBindingSupported,\r
2324 UhciDriverBindingStart,\r
2325 UhciDriverBindingStop,\r
2326 0x20,\r
2327 NULL,\r
2328 NULL\r
2329};\r