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