]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
Make EdkModulePkg pass Intel IPF compiler with /W4 /WX switches, solving warning...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / Uhci / Dxe / uhci.c
1 /*++
2
3 Copyright (c) 2006, 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
19 Revision History
20 --*/
21
22 #include "uhci.h"
23
24 //
25 // UHCI Driver Global Variables
26 //
27 EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {
28 UHCIDriverBindingSupported,
29 UHCIDriverBindingStart,
30 UHCIDriverBindingStop,
31 0xa,
32 NULL,
33 NULL
34 };
35
36 EFI_STATUS
37 EFIAPI
38 UHCIDriverBindingSupported (
39 IN EFI_DRIVER_BINDING_PROTOCOL *This,
40 IN EFI_HANDLE Controller,
41 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
42 )
43 /*++
44
45 Routine Description:
46 Test to see if this driver supports ControllerHandle. Any ControllerHandle
47 that has UsbHcProtocol installed will be supported.
48
49 Arguments:
50 This - Protocol instance pointer.
51 Controller - Handle of device to test
52 RemainingDevicePath - Not used
53
54 Returns:
55 EFI_SUCCESS - This driver supports this device.
56 EFI_UNSUPPORTED - This driver does not support this device.
57
58 --*/
59 {
60 EFI_STATUS OpenStatus;
61 EFI_STATUS Status;
62 EFI_PCI_IO_PROTOCOL *PciIo;
63 USB_CLASSC UsbClassCReg;
64
65 //
66 // Test whether there is PCI IO Protocol attached on the controller handle.
67 //
68 OpenStatus = gBS->OpenProtocol (
69 Controller,
70 &gEfiPciIoProtocolGuid,
71 (VOID **) &PciIo,
72 This->DriverBindingHandle,
73 Controller,
74 EFI_OPEN_PROTOCOL_BY_DRIVER
75 );
76 if (EFI_ERROR (OpenStatus)) {
77 return OpenStatus;
78 }
79
80 Status = PciIo->Pci.Read (
81 PciIo,
82 EfiPciIoWidthUint8,
83 CLASSC,
84 sizeof (USB_CLASSC) / sizeof (UINT8),
85 &UsbClassCReg
86 );
87 if (EFI_ERROR (Status)) {
88 gBS->CloseProtocol (
89 Controller,
90 &gEfiPciIoProtocolGuid,
91 This->DriverBindingHandle,
92 Controller
93 );
94 return EFI_UNSUPPORTED;
95 }
96 //
97 // Test whether the controller belongs to UHCI type
98 //
99 if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
100 (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
101 (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) {
102
103 gBS->CloseProtocol (
104 Controller,
105 &gEfiPciIoProtocolGuid,
106 This->DriverBindingHandle,
107 Controller
108 );
109
110 return EFI_UNSUPPORTED;
111 }
112 gBS->CloseProtocol (
113 Controller,
114 &gEfiPciIoProtocolGuid,
115 This->DriverBindingHandle,
116 Controller
117 );
118 return EFI_SUCCESS;
119
120 }
121
122 EFI_STATUS
123 EFIAPI
124 UHCIDriverBindingStart (
125 IN EFI_DRIVER_BINDING_PROTOCOL *This,
126 IN EFI_HANDLE Controller,
127 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
128 )
129 /*++
130
131 Routine Description:
132 Starting the Usb UHCI Driver
133
134 Arguments:
135 This - Protocol instance pointer.
136 Controller - Handle of device to test
137 RemainingDevicePath - Not used
138
139 Returns:
140 EFI_SUCCESS - This driver supports this device.
141 EFI_UNSUPPORTED - This driver does not support this device.
142 EFI_DEVICE_ERROR - This driver cannot be started due to device
143 Error
144 EFI_OUT_OF_RESOURCES
145
146 --*/
147 {
148 EFI_STATUS Status;
149 UINTN FlBaseAddrReg;
150 EFI_PCI_IO_PROTOCOL *PciIo;
151 USB_HC_DEV *HcDev;
152 UINT64 Supports;
153
154 HcDev = NULL;
155
156 Status = gBS->OpenProtocol (
157 Controller,
158 &gEfiPciIoProtocolGuid,
159 (VOID **) &PciIo,
160 This->DriverBindingHandle,
161 Controller,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
163 );
164 if (EFI_ERROR (Status)) {
165 return Status;
166 }
167
168 //
169 // Turn off USB emulation
170 //
171 TurnOffUSBEmulation (PciIo);
172
173 //
174 // Enable the USB Host Controller
175 //
176 Status = PciIo->Attributes (
177 PciIo,
178 EfiPciIoAttributeOperationSupported,
179 0,
180 &Supports
181 );
182 if (!EFI_ERROR (Status)) {
183 Supports &= EFI_PCI_DEVICE_ENABLE;
184 Status = PciIo->Attributes (
185 PciIo,
186 EfiPciIoAttributeOperationEnable,
187 Supports,
188 NULL
189 );
190 }
191 if (EFI_ERROR (Status)) {
192 gBS->CloseProtocol (
193 Controller,
194 &gEfiPciIoProtocolGuid,
195 This->DriverBindingHandle,
196 Controller
197 );
198 return EFI_UNSUPPORTED;
199 }
200
201 //
202 // allocate memory for UHC private data structure
203 //
204 HcDev = AllocateZeroPool (sizeof (USB_HC_DEV));
205 if (HcDev == NULL) {
206 gBS->CloseProtocol (
207 Controller,
208 &gEfiPciIoProtocolGuid,
209 This->DriverBindingHandle,
210 Controller
211 );
212 return EFI_OUT_OF_RESOURCES;
213 }
214
215 //
216 // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
217 //
218 HcDev->UsbHc.Reset = UHCIReset;
219 HcDev->UsbHc.GetState = UHCIGetState;
220 HcDev->UsbHc.SetState = UHCISetState;
221 HcDev->UsbHc.ControlTransfer = UHCIControlTransfer;
222 HcDev->UsbHc.BulkTransfer = UHCIBulkTransfer;
223 HcDev->UsbHc.AsyncInterruptTransfer = UHCIAsyncInterruptTransfer;
224 HcDev->UsbHc.SyncInterruptTransfer = UHCISyncInterruptTransfer;
225 HcDev->UsbHc.IsochronousTransfer = UHCIIsochronousTransfer;
226 HcDev->UsbHc.AsyncIsochronousTransfer = UHCIAsyncIsochronousTransfer;
227 HcDev->UsbHc.GetRootHubPortNumber = UHCIGetRootHubPortNumber;
228 HcDev->UsbHc.GetRootHubPortStatus = UHCIGetRootHubPortStatus;
229 HcDev->UsbHc.SetRootHubPortFeature = UHCISetRootHubPortFeature;
230 HcDev->UsbHc.ClearRootHubPortFeature = UHCIClearRootHubPortFeature;
231
232 HcDev->UsbHc.MajorRevision = 0x1;
233 HcDev->UsbHc.MinorRevision = 0x1;
234
235 //
236 //
237 // init EFI_USB2_HC_PROTOCOL protocol interface and install the protocol
238 //
239 HcDev->Usb2Hc.GetCapability = UHCI2GetCapability;
240 HcDev->Usb2Hc.Reset = UHCI2Reset;
241 HcDev->Usb2Hc.GetState = UHCI2GetState;
242 HcDev->Usb2Hc.SetState = UHCI2SetState;
243 HcDev->Usb2Hc.ControlTransfer = UHCI2ControlTransfer;
244 HcDev->Usb2Hc.BulkTransfer = UHCI2BulkTransfer;
245 HcDev->Usb2Hc.AsyncInterruptTransfer = UHCI2AsyncInterruptTransfer;
246 HcDev->Usb2Hc.SyncInterruptTransfer = UHCI2SyncInterruptTransfer;
247 HcDev->Usb2Hc.IsochronousTransfer = UHCI2IsochronousTransfer;
248 HcDev->Usb2Hc.AsyncIsochronousTransfer = UHCI2AsyncIsochronousTransfer;
249 HcDev->Usb2Hc.GetRootHubPortStatus = UHCI2GetRootHubPortStatus;
250 HcDev->Usb2Hc.SetRootHubPortFeature = UHCI2SetRootHubPortFeature;
251 HcDev->Usb2Hc.ClearRootHubPortFeature = UHCI2ClearRootHubPortFeature;
252
253 HcDev->Usb2Hc.MajorRevision = 0x1;
254 HcDev->Usb2Hc.MinorRevision = 0x1;
255
256 //
257 // Init UHCI private data structures
258 //
259 HcDev->Signature = USB_HC_DEV_SIGNATURE;
260 HcDev->PciIo = PciIo;
261
262 FlBaseAddrReg = USBFLBASEADD;
263
264 //
265 // Allocate and Init Host Controller's Frame List Entry
266 //
267 Status = CreateFrameList (HcDev, (UINT32) FlBaseAddrReg);
268 if (EFI_ERROR (Status)) {
269
270 if (HcDev != NULL) {
271 gBS->FreePool (HcDev);
272 }
273
274 gBS->CloseProtocol (
275 Controller,
276 &gEfiPciIoProtocolGuid,
277 This->DriverBindingHandle,
278 Controller
279 );
280 return EFI_OUT_OF_RESOURCES;
281 }
282
283 //
284 // Init interrupt list head in the HcDev structure.
285 //
286 InitializeListHead (&(HcDev->InterruptListHead));
287
288 //
289 // Create timer for interrupt transfer result polling
290 //
291 Status = gBS->CreateEvent (
292 EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
293 EFI_TPL_NOTIFY,
294 MonitorInterruptTrans,
295 HcDev,
296 &HcDev->InterruptTransTimer
297 );
298 if (EFI_ERROR (Status)) {
299
300 FreeFrameListEntry (HcDev);
301
302 if (HcDev != NULL) {
303 gBS->FreePool (HcDev);
304 }
305
306 gBS->CloseProtocol (
307 Controller,
308 &gEfiPciIoProtocolGuid,
309 This->DriverBindingHandle,
310 Controller
311 );
312 return EFI_UNSUPPORTED;
313 }
314
315 //
316 // Here set interrupt transfer polling timer in 50ms unit.
317 //
318 Status = gBS->SetTimer (
319 HcDev->InterruptTransTimer,
320 TimerPeriodic,
321 INTERRUPT_POLLING_TIME
322 );
323 if (EFI_ERROR (Status)) {
324 gBS->CloseEvent (HcDev->InterruptTransTimer);
325
326 FreeFrameListEntry (HcDev);
327
328 if (HcDev != NULL) {
329 gBS->FreePool (HcDev);
330 }
331
332 gBS->CloseProtocol (
333 Controller,
334 &gEfiPciIoProtocolGuid,
335 This->DriverBindingHandle,
336 Controller
337 );
338 return EFI_UNSUPPORTED;
339 }
340
341 //
342 // QH,TD structures must in common buffer that will be
343 // accessed by both cpu and usb bus master at the same time.
344 // so, there must has memory management for QH,TD structures.
345 //
346 Status = InitializeMemoryManagement (HcDev);
347 if (EFI_ERROR (Status)) {
348
349 gBS->CloseEvent (HcDev->InterruptTransTimer);
350
351 FreeFrameListEntry (HcDev);
352
353 if (HcDev != NULL) {
354 gBS->FreePool (HcDev);
355 }
356
357 gBS->CloseProtocol (
358 Controller,
359 &gEfiPciIoProtocolGuid,
360 This->DriverBindingHandle,
361 Controller
362 );
363 return Status;
364 }
365
366 //
367 // Install Host Controller Protocol
368 //
369 Status = gBS->InstallProtocolInterface (
370 &Controller,
371 &gEfiUsbHcProtocolGuid,
372 EFI_NATIVE_INTERFACE,
373 &HcDev->UsbHc
374 );
375 if (EFI_ERROR (Status)) {
376 gBS->CloseEvent (HcDev->InterruptTransTimer);
377 FreeFrameListEntry (HcDev);
378 DelMemoryManagement (HcDev);
379
380 if (HcDev != NULL) {
381 gBS->FreePool (HcDev);
382 }
383
384 gBS->CloseProtocol (
385 Controller,
386 &gEfiPciIoProtocolGuid,
387 This->DriverBindingHandle,
388 Controller
389 );
390 return Status;
391 }
392
393 //
394 // Install USB2.0 Host Controller Protocol
395 //
396 Status = gBS->InstallProtocolInterface (
397 &Controller,
398 &gEfiUsb2HcProtocolGuid,
399 EFI_NATIVE_INTERFACE,
400 &HcDev->Usb2Hc
401 );
402 if (EFI_ERROR (Status)) {
403 gBS->CloseEvent (HcDev->InterruptTransTimer);
404 FreeFrameListEntry (HcDev);
405 DelMemoryManagement (HcDev);
406
407 if (HcDev != NULL) {
408 gBS->FreePool (HcDev);
409 }
410
411 gBS->CloseProtocol (
412 Controller,
413 &gEfiPciIoProtocolGuid,
414 This->DriverBindingHandle,
415 Controller
416 );
417
418 return Status;
419 }
420
421 //
422 // component name protocol.
423 //
424
425 HcDev->ControllerNameTable = NULL;
426 AddUnicodeString (
427 "eng",
428 gUhciComponentName.SupportedLanguages,
429 &HcDev->ControllerNameTable,
430 (CHAR16 *) L"Usb Universal Host Controller"
431 );
432
433 return EFI_SUCCESS;
434 }
435
436 STATIC
437 EFI_STATUS
438 UnInstallUHCInterface (
439 IN EFI_HANDLE Controller,
440 IN EFI_USB_HC_PROTOCOL *This
441 )
442 /*++
443 Routine Description:
444 UnInstall UHCInterface
445 Arguments:
446 Controller - Controller handle
447 This - Protocol instance pointer.
448 Returns:
449 EFI_SUCCESS
450 others
451 --*/
452 {
453 USB_HC_DEV *HcDev;
454 EFI_STATUS Status;
455 UINT64 Supports;
456
457 HcDev = USB_HC_DEV_FROM_THIS (This);
458
459 gBS->UninstallProtocolInterface (
460 Controller,
461 &gEfiUsbHcProtocolGuid,
462 &HcDev->UsbHc
463 );
464
465 gBS->UninstallProtocolInterface (
466 Controller,
467 &gEfiUsb2HcProtocolGuid,
468 &HcDev->Usb2Hc
469 );
470 //
471 // first stop USB Host Controller
472 //
473 This->SetState (This, EfiUsbHcStateHalt);
474
475 //
476 // Delete interrupt transfer polling timer
477 //
478 gBS->CloseEvent (HcDev->InterruptTransTimer);
479
480 //
481 // Delete all the asynchronous interrupt transfers in the interrupt list
482 // and free associated memory
483 //
484 ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));
485
486 //
487 // free Frame List Entry.
488 //
489 FreeFrameListEntry (HcDev);
490
491 //
492 // Free common buffer allocated for QH,TD structures
493 //
494 DelMemoryManagement (HcDev);
495
496 if (HcDev->ControllerNameTable) {
497 FreeUnicodeStringTable (HcDev->ControllerNameTable);
498 }
499 //
500 // Disable the USB Host Controller
501 //
502 Status = HcDev->PciIo->Attributes (
503 HcDev->PciIo,
504 EfiPciIoAttributeOperationSupported,
505 0,
506 &Supports
507 );
508 if (!EFI_ERROR (Status)) {
509 Supports &= EFI_PCI_DEVICE_ENABLE;
510 Status = HcDev->PciIo->Attributes (
511 HcDev->PciIo,
512 EfiPciIoAttributeOperationDisable,
513 Supports,
514 NULL
515 );
516 }
517
518 gBS->FreePool (HcDev);
519
520 return EFI_SUCCESS;
521 }
522
523
524 EFI_STATUS
525 EFIAPI
526 UHCIDriverBindingStop (
527 IN EFI_DRIVER_BINDING_PROTOCOL *This,
528 IN EFI_HANDLE Controller,
529 IN UINTN NumberOfChildren,
530 IN EFI_HANDLE *ChildHandleBuffer
531 )
532 /*++
533
534 Routine Description:
535 Stop this driver on ControllerHandle. Support stoping any child handles
536 created by this driver.
537
538 Arguments:
539 This - Protocol instance pointer.
540 Controller - Handle of device to stop driver on
541 NumberOfChildren - Number of Children in the ChildHandleBuffer
542 ChildHandleBuffer - List of handles for the children we need to stop.
543
544 Returns:
545 EFI_SUCCESS
546 others
547
548 --*/
549 {
550 EFI_USB_HC_PROTOCOL *UsbHc;
551 EFI_USB2_HC_PROTOCOL *Usb2Hc;
552 EFI_STATUS OpenStatus;
553
554 OpenStatus = gBS->OpenProtocol (
555 Controller,
556 &gEfiUsbHcProtocolGuid,
557 (VOID **)&UsbHc,
558 This->DriverBindingHandle,
559 Controller,
560 EFI_OPEN_PROTOCOL_GET_PROTOCOL
561 );
562
563 //
564 // Test whether the Controller handler passed in is a valid
565 // Usb controller handle that should be supported, if not,
566 // return the error status directly
567 //
568 if (EFI_ERROR (OpenStatus)) {
569 return OpenStatus;
570 }
571
572 OpenStatus = gBS->OpenProtocol (
573 Controller,
574 &gEfiUsb2HcProtocolGuid,
575 (VOID **) &Usb2Hc,
576 This->DriverBindingHandle,
577 Controller,
578 EFI_OPEN_PROTOCOL_GET_PROTOCOL
579 );
580
581 //
582 // Test whether the Controller handler passed in is a valid
583 // Usb controller handle that should be supported, if not,
584 // return the error status directly
585 //
586 if (EFI_ERROR (OpenStatus)) {
587 return OpenStatus;
588 }
589 //
590 // free all the controller related memory and uninstall UHCI Protocol.
591 //
592 UnInstallUHCInterface (Controller, UsbHc);
593
594 gBS->CloseProtocol (
595 Controller,
596 &gEfiPciIoProtocolGuid,
597 This->DriverBindingHandle,
598 Controller
599 );
600
601 return EFI_SUCCESS;
602
603 }
604
605
606 EFI_STATUS
607 EFIAPI
608 UHCIReset (
609 IN EFI_USB_HC_PROTOCOL *This,
610 IN UINT16 Attributes
611 )
612 /*++
613
614 Routine Description:
615 Provides software reset for the USB host controller.
616
617 Arguments:
618
619 This A pointer to the EFI_USB_HC_PROTOCOL instance.
620
621 Attributes A bit mask of the reset operation to perform.
622 See below for a list of the supported bit mask values.
623
624 #define EFI_USB_HC_RESET_GLOBAL 0x0001
625 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
626
627 EFI_USB_HC_RESET_GLOBAL
628 If this bit is set, a global reset signal will be sent to the USB bus.
629 This resets all of the USB bus logic, including the USB host
630 controller hardware and all the devices attached on the USB bus.
631 EFI_USB_HC_RESET_HOST_CONTROLLER
632 If this bit is set, the USB host controller hardware will be reset.
633 No reset signal will be sent to the USB bus.
634
635 Returns:
636 EFI_SUCCESS
637 The reset operation succeeded.
638 EFI_INVALID_PARAMETER
639 Attributes is not valid.
640 EFI_DEVICE_ERROR
641 An error was encountered while attempting to perform
642 the reset operation.
643 --*/
644 {
645 BOOLEAN Match;
646 USB_HC_DEV *HcDev;
647 UINT32 CommandRegAddr;
648 UINT32 FlBaseAddrReg;
649 UINT16 Command;
650 EFI_STATUS Status;
651
652 Match = FALSE;
653 HcDev = USB_HC_DEV_FROM_THIS (This);
654
655 CommandRegAddr = (UINT32) (USBCMD);
656 FlBaseAddrReg = (UINT32) (USBFLBASEADD);
657
658 if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {
659 Match = TRUE;
660 //
661 // set the Global Reset bit in the command register
662 //
663 Status = ReadUHCCommandReg (
664 HcDev->PciIo,
665 CommandRegAddr,
666 &Command
667 );
668 if (EFI_ERROR (Status)) {
669 return EFI_DEVICE_ERROR;
670 }
671
672 Command |= USBCMD_GRESET;
673 Status = WriteUHCCommandReg (
674 HcDev->PciIo,
675 CommandRegAddr,
676 Command
677 );
678 if (EFI_ERROR (Status)) {
679 return EFI_DEVICE_ERROR;
680 }
681
682 //
683 // Wait 50ms for root port to let reset complete
684 // See UHCI spec page122 Reset signaling
685 //
686 gBS->Stall (ROOT_PORT_REST_TIME);
687
688 //
689 // Clear the Global Reset bit to zero.
690 //
691 Command &= ~USBCMD_GRESET;
692 Status = WriteUHCCommandReg (
693 HcDev->PciIo,
694 CommandRegAddr,
695 Command
696 );
697 if (EFI_ERROR (Status)) {
698 return EFI_DEVICE_ERROR;
699 }
700 //
701 // UHCI spec page120 reset recovery time
702 //
703 gBS->Stall (PORT_RESET_RECOVERY_TIME);
704 }
705
706 if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
707 Match = TRUE;
708 //
709 // set Host Controller Reset bit to 1
710 //
711 Status = ReadUHCCommandReg (
712 HcDev->PciIo,
713 CommandRegAddr,
714 &Command
715 );
716 if (EFI_ERROR (Status)) {
717 return EFI_DEVICE_ERROR;
718 }
719
720 Command |= USBCMD_HCRESET;
721 Status = WriteUHCCommandReg (
722 HcDev->PciIo,
723 CommandRegAddr,
724 Command
725 );
726 if (EFI_ERROR (Status)) {
727 return EFI_DEVICE_ERROR;
728 }
729 //
730 // this bit will be reset by Host Controller when reset is completed.
731 // wait 10ms to let reset complete
732 //
733 gBS->Stall (PORT_RESET_RECOVERY_TIME);
734 }
735
736 if (!Match) {
737 return EFI_INVALID_PARAMETER;
738 }
739
740 //
741 // Delete all old transactions on the USB bus
742 //
743 CleanUsbTransactions (HcDev);
744
745 //
746 // Initialize Universal Host Controller's Frame List Data Structure
747 //
748 InitFrameList (HcDev);
749
750 //
751 // Reset may cause Frame List Base Address Register reset to zero,
752 // so set the original value back again.
753 //
754 SetFrameListBaseAddress (
755 HcDev->PciIo,
756 FlBaseAddrReg,
757 (UINT32) ((UINTN) HcDev->FrameListEntry)
758 );
759
760 return EFI_SUCCESS;
761 }
762
763 EFI_STATUS
764 EFIAPI
765 UHCIGetState (
766 IN EFI_USB_HC_PROTOCOL *This,
767 OUT EFI_USB_HC_STATE *State
768 )
769 /*++
770
771 Routine Description:
772 Retrieves current state of the USB host controller.
773
774 Arguments:
775
776 This A pointer to the EFI_USB_HC_PROTOCOL instance.
777
778 State A pointer to the EFI_USB_HC_STATE data structure that
779 indicates current state of the USB host controller.
780 Type EFI_USB_HC_STATE is defined below.
781
782 typedef enum {
783 EfiUsbHcStateHalt,
784 EfiUsbHcStateOperational,
785 EfiUsbHcStateSuspend,
786 EfiUsbHcStateMaximum
787 } EFI_USB_HC_STATE;
788
789 Returns:
790 EFI_SUCCESS
791 The state information of the host controller was returned in State.
792 EFI_INVALID_PARAMETER
793 State is NULL.
794 EFI_DEVICE_ERROR
795 An error was encountered while attempting to retrieve the
796 host controller's current state.
797 --*/
798 {
799 USB_HC_DEV *HcDev;
800 UINT32 CommandRegAddr;
801 UINT32 StatusRegAddr;
802 UINT16 UhcCommand;
803 UINT16 UhcStatus;
804 EFI_STATUS Status;
805
806 if (State == NULL) {
807 return EFI_INVALID_PARAMETER;
808 }
809
810 HcDev = USB_HC_DEV_FROM_THIS (This);
811
812 CommandRegAddr = (UINT32) (USBCMD);
813 StatusRegAddr = (UINT32) (USBSTS);
814
815 Status = ReadUHCCommandReg (
816 HcDev->PciIo,
817 CommandRegAddr,
818 &UhcCommand
819 );
820
821 if (EFI_ERROR (Status)) {
822 return EFI_DEVICE_ERROR;
823 }
824
825 Status = ReadUHCCommandReg (
826 HcDev->PciIo,
827 StatusRegAddr,
828 &UhcStatus
829 );
830 if (EFI_ERROR (Status)) {
831 return EFI_DEVICE_ERROR;
832 }
833
834 if (UhcCommand & USBCMD_EGSM) {
835 *State = EfiUsbHcStateSuspend;
836 return EFI_SUCCESS;
837 }
838
839 if ((UhcStatus & USBSTS_HCH) == 0) {
840 *State = EfiUsbHcStateOperational;
841 } else {
842 *State = EfiUsbHcStateHalt;
843 }
844
845 return EFI_SUCCESS;
846 }
847
848
849 EFI_STATUS
850 EFIAPI
851 UHCISetState (
852 IN EFI_USB_HC_PROTOCOL *This,
853 IN EFI_USB_HC_STATE State
854 )
855 /*++
856
857 Routine Description:
858 Sets the USB host controller to a specific state.
859
860 Arguments:
861
862 This A pointer to the EFI_USB_HC_PROTOCOL instance.
863
864 State Indicates the state of the host controller that will be set.
865
866 Returns:
867 EFI_SUCCESS
868 The USB host controller was successfully placed in the state
869 specified by State.
870 EFI_INVALID_PARAMETER
871 State is invalid.
872 EFI_DEVICE_ERROR
873 Failed to set the state specified by State due to device error.
874 --*/
875 {
876 USB_HC_DEV *HcDev;
877 UINT32 CommandRegAddr;
878 UINT32 StatusRegAddr;
879 UINT16 Command;
880 EFI_USB_HC_STATE CurrentState;
881 EFI_STATUS Status;
882
883 HcDev = USB_HC_DEV_FROM_THIS (This);
884
885 CommandRegAddr = (UINT32) (USBCMD);
886 StatusRegAddr = (UINT32) (USBSTS);
887
888 Status = UHCIGetState (This, &CurrentState);
889 if (EFI_ERROR (Status)) {
890 return EFI_DEVICE_ERROR;
891 }
892
893 switch (State) {
894
895 case EfiUsbHcStateHalt:
896 if (CurrentState == EfiUsbHcStateHalt) {
897 return EFI_SUCCESS;
898 }
899
900 Status = ReadUHCCommandReg (
901 HcDev->PciIo,
902 CommandRegAddr,
903 &Command
904 );
905 if (EFI_ERROR (Status)) {
906 return EFI_DEVICE_ERROR;
907 }
908
909 Command &= ~USBCMD_RS;
910
911 Status = WriteUHCCommandReg (
912 HcDev->PciIo,
913 CommandRegAddr,
914 Command
915 );
916 if (EFI_ERROR (Status)) {
917 return EFI_DEVICE_ERROR;
918 }
919
920 StatusRegAddr = (UINT32) (USBSTS);
921 //
922 // ensure the HC is in halt status after send the stop command
923 //
924 if (WaitForUHCHalt (HcDev->PciIo, StatusRegAddr, STALL_1_SECOND) == EFI_TIMEOUT) {
925 return EFI_DEVICE_ERROR;
926 }
927 break;
928
929 case EfiUsbHcStateOperational:
930 if (IsHostSysOrProcessErr (HcDev->PciIo, StatusRegAddr)) {
931 return EFI_DEVICE_ERROR;
932 }
933
934 switch (CurrentState) {
935
936 case EfiUsbHcStateOperational:
937 return EFI_SUCCESS;
938
939 case EfiUsbHcStateHalt:
940 //
941 // Set Run/Stop bit to 1.
942 //
943 Status = ReadUHCCommandReg (
944 HcDev->PciIo,
945 CommandRegAddr,
946 &Command
947 );
948 if (EFI_ERROR (Status)) {
949 return EFI_DEVICE_ERROR;
950 }
951
952 Command |= USBCMD_RS | USBCMD_MAXP;
953 Status = WriteUHCCommandReg (
954 HcDev->PciIo,
955 CommandRegAddr,
956 Command
957 );
958 if (EFI_ERROR (Status)) {
959 return EFI_DEVICE_ERROR;
960 }
961
962 break;
963
964 case EfiUsbHcStateSuspend:
965 Status = ReadUHCCommandReg (
966 HcDev->PciIo,
967 CommandRegAddr,
968 &Command
969 );
970 if (EFI_ERROR (Status)) {
971 return EFI_DEVICE_ERROR;
972 }
973
974 //
975 // FGR(Force Global Resume) bit is 0
976 //
977 if ((Command | (~USBCMD_FGR)) != 0xFF) {
978 //
979 // Write FGR bit to 1
980 //
981 Command |= USBCMD_FGR;
982 WriteUHCCommandReg (
983 HcDev->PciIo,
984 CommandRegAddr,
985 Command
986 );
987 }
988
989 //
990 // wait 20ms to let resume complete
991 // (20ms is specified by UHCI spec)
992 //
993 gBS->Stall (FORCE_GLOBAL_RESUME_TIME);
994
995 //
996 // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
997 //
998 Command &= ~USBCMD_FGR;
999 Command &= ~USBCMD_EGSM;
1000 Command |= USBCMD_RS;
1001 WriteUHCCommandReg (
1002 HcDev->PciIo,
1003 CommandRegAddr,
1004 Command
1005 );
1006 break;
1007
1008 default:
1009 break;
1010 }
1011 break;
1012
1013 case EfiUsbHcStateSuspend:
1014 if (CurrentState == EfiUsbHcStateSuspend) {
1015 return EFI_SUCCESS;
1016 }
1017
1018 Status = UHCISetState (This, EfiUsbHcStateHalt);
1019 if (EFI_ERROR (Status)) {
1020 return EFI_DEVICE_ERROR;
1021 }
1022 //
1023 // Set Enter Global Suspend Mode bit to 1.
1024 //
1025 Status = ReadUHCCommandReg (
1026 HcDev->PciIo,
1027 CommandRegAddr,
1028 &Command
1029 );
1030 if (EFI_ERROR (Status)) {
1031 return EFI_DEVICE_ERROR;
1032 }
1033
1034 Command |= USBCMD_EGSM;
1035 Status = WriteUHCCommandReg (
1036 HcDev->PciIo,
1037 CommandRegAddr,
1038 Command
1039 );
1040 if (EFI_ERROR (Status)) {
1041 return EFI_DEVICE_ERROR;
1042 }
1043 break;
1044
1045 default:
1046 return EFI_INVALID_PARAMETER;
1047 }
1048
1049 return EFI_SUCCESS;
1050 }
1051
1052 EFI_STATUS
1053 EFIAPI
1054 UHCIGetRootHubPortNumber (
1055 IN EFI_USB_HC_PROTOCOL *This,
1056 OUT UINT8 *PortNumber
1057 )
1058 /*++
1059
1060 Routine Description:
1061 Retrieves the number of root hub ports.
1062
1063 Arguments:
1064
1065 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1066
1067 PortNumber A pointer to the number of the root hub ports.
1068
1069 Returns:
1070 EFI_SUCCESS
1071 The port number was retrieved successfully.
1072 EFI_INVALID_PARAMETER
1073 PortNumber is NULL.
1074 EFI_DEVICE_ERROR
1075 An error was encountered while attempting to
1076 retrieve the port number.
1077 --*/
1078 {
1079 USB_HC_DEV *HcDev;
1080 UINT32 PSAddr;
1081 UINT16 RHPortControl;
1082 UINT32 Index;
1083 EFI_STATUS Status;
1084
1085 HcDev = USB_HC_DEV_FROM_THIS (This);
1086
1087 if (PortNumber == NULL) {
1088 return EFI_INVALID_PARAMETER;
1089 }
1090
1091 *PortNumber = 0;
1092
1093 for (Index = 0; Index < 2; Index++) {
1094 PSAddr = (UINT32) (USBPORTSC1 + Index * 2);
1095 Status = ReadRootPortReg (
1096 HcDev->PciIo,
1097 PSAddr,
1098 &RHPortControl
1099 );
1100 if (EFI_ERROR (Status)) {
1101 return EFI_DEVICE_ERROR;
1102 }
1103 //
1104 // Port Register content is valid
1105 //
1106 if (RHPortControl != 0xff) {
1107 (*PortNumber)++;
1108 }
1109 }
1110
1111 return EFI_SUCCESS;
1112 }
1113
1114 EFI_STATUS
1115 EFIAPI
1116 UHCIGetRootHubPortStatus (
1117 IN EFI_USB_HC_PROTOCOL *This,
1118 IN UINT8 PortNumber,
1119 OUT EFI_USB_PORT_STATUS *PortStatus
1120 )
1121 /*++
1122
1123 Routine Description:
1124 Retrieves the current status of a USB root hub port.
1125
1126 Arguments:
1127
1128 This A pointer to the EFI_USB_HC_PROTOCOL.
1129
1130 PortNumber Specifies the root hub port from which the status
1131 is to be retrieved. This value is zero-based. For example,
1132 if a root hub has two ports, then the first port is numbered 0,
1133 and the second port is numbered 1.
1134
1135 PortStatus A pointer to the current port status bits and
1136 port status change bits.
1137
1138 Returns:
1139 EFI_SUCCESS
1140 The status of the USB root hub port specified by PortNumber
1141 was returned in PortStatus.
1142 EFI_INVALID_PARAMETER
1143 PortNumber is invalid.
1144 EFI_DEVICE_ERROR - Can't read register
1145 --*/
1146 {
1147 USB_HC_DEV *HcDev;
1148 UINT32 PSAddr;
1149 UINT16 RHPortStatus;
1150 UINT8 TotalPortNumber;
1151 EFI_STATUS Status;
1152
1153 if (PortStatus == NULL) {
1154 return EFI_INVALID_PARAMETER;
1155 }
1156
1157 UHCIGetRootHubPortNumber (This, &TotalPortNumber);
1158 if (PortNumber >= TotalPortNumber) {
1159 return EFI_INVALID_PARAMETER;
1160 }
1161
1162 HcDev = USB_HC_DEV_FROM_THIS (This);
1163 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
1164
1165 //
1166 // Clear port status
1167 //
1168 PortStatus->PortStatus = 0;
1169 PortStatus->PortChangeStatus = 0;
1170
1171 Status = ReadRootPortReg (
1172 HcDev->PciIo,
1173 PSAddr,
1174 &RHPortStatus
1175 );
1176
1177 if (EFI_ERROR (Status)) {
1178 return EFI_DEVICE_ERROR;
1179 }
1180 //
1181 // Fill Port Status bits
1182 //
1183
1184 //
1185 // Current Connect Status
1186 //
1187 if (RHPortStatus & USBPORTSC_CCS) {
1188 PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
1189 }
1190 //
1191 // Port Enabled/Disabled
1192 //
1193 if (RHPortStatus & USBPORTSC_PED) {
1194 PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
1195 }
1196
1197 //
1198 // Port Suspend
1199 //
1200 if (RHPortStatus & USBPORTSC_SUSP) {
1201 PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
1202 }
1203
1204 //
1205 // Port Reset
1206 //
1207 if (RHPortStatus & USBPORTSC_PR) {
1208 PortStatus->PortStatus |= USB_PORT_STAT_RESET;
1209 }
1210
1211 //
1212 // Low Speed Device Attached
1213 //
1214 if (RHPortStatus & USBPORTSC_LSDA) {
1215 PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
1216 }
1217 //
1218 // CHC will always return one in this bit
1219 //
1220 PortStatus->PortStatus |= USB_PORT_STAT_OWNER;
1221 //
1222 // Fill Port Status Change bits
1223 //
1224
1225 //
1226 // Connect Status Change
1227 //
1228 if (RHPortStatus & USBPORTSC_CSC) {
1229 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
1230 }
1231
1232 //
1233 // Port Enabled/Disabled Change
1234 //
1235 if (RHPortStatus & USBPORTSC_PEDC) {
1236 PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
1237 }
1238
1239 return EFI_SUCCESS;
1240 }
1241
1242 EFI_STATUS
1243 EFIAPI
1244 UHCISetRootHubPortFeature (
1245 IN EFI_USB_HC_PROTOCOL *This,
1246 IN UINT8 PortNumber,
1247 IN EFI_USB_PORT_FEATURE PortFeature
1248 )
1249 /*++
1250
1251 Routine Description:
1252 Sets a feature for the specified root hub port.
1253
1254 Arguments:
1255
1256 This A pointer to the EFI_USB_HC_PROTOCOL.
1257
1258 PortNumber Specifies the root hub port whose feature
1259 is requested to be set.
1260
1261 PortFeature Indicates the feature selector associated
1262 with the feature set request.
1263
1264 Returns:
1265 EFI_SUCCESS
1266 The feature specified by PortFeature was set for the
1267 USB root hub port specified by PortNumber.
1268 EFI_INVALID_PARAMETER
1269 PortNumber is invalid or PortFeature is invalid.
1270 EFI_DEVICE_ERROR
1271 Can't read register
1272 --*/
1273 {
1274 USB_HC_DEV *HcDev;
1275 UINT32 PSAddr;
1276 UINT32 CommandRegAddr;
1277 //
1278 // root hub port status
1279 //
1280 UINT16 RHPortControl;
1281 UINT16 Command;
1282 UINT8 TotalPortNumber;
1283 EFI_STATUS Status;
1284
1285 UHCIGetRootHubPortNumber (This, &TotalPortNumber);
1286 if (PortNumber >= TotalPortNumber) {
1287 return EFI_INVALID_PARAMETER;
1288 }
1289
1290 HcDev = USB_HC_DEV_FROM_THIS (This);
1291
1292 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
1293 CommandRegAddr = (UINT32) (USBCMD);
1294
1295 Status = ReadRootPortReg (
1296 HcDev->PciIo,
1297 PSAddr,
1298 &RHPortControl
1299 );
1300 if (EFI_ERROR (Status)) {
1301 return EFI_DEVICE_ERROR;
1302 }
1303
1304 switch (PortFeature) {
1305
1306 case EfiUsbPortSuspend:
1307 Status = ReadUHCCommandReg (
1308 HcDev->PciIo,
1309 CommandRegAddr,
1310 &Command
1311 );
1312 if (EFI_ERROR (Status)) {
1313 return EFI_DEVICE_ERROR;
1314 }
1315
1316 if (!(Command & USBCMD_EGSM)) {
1317 //
1318 // if global suspend is not active, can set port suspend
1319 //
1320 RHPortControl &= 0xfff5;
1321 RHPortControl |= USBPORTSC_SUSP;
1322 }
1323 break;
1324
1325 case EfiUsbPortReset:
1326 RHPortControl &= 0xfff5;
1327 //
1328 // Set the reset bit
1329 //
1330 RHPortControl |= USBPORTSC_PR;
1331 break;
1332
1333 case EfiUsbPortPower:
1334 break;
1335
1336 case EfiUsbPortEnable:
1337 RHPortControl &= 0xfff5;
1338 RHPortControl |= USBPORTSC_PED;
1339 break;
1340
1341 default:
1342 return EFI_INVALID_PARAMETER;
1343 }
1344
1345 WriteRootPortReg (
1346 HcDev->PciIo,
1347 PSAddr,
1348 RHPortControl
1349 );
1350
1351 return EFI_SUCCESS;
1352 }
1353
1354 EFI_STATUS
1355 EFIAPI
1356 UHCIClearRootHubPortFeature (
1357 IN EFI_USB_HC_PROTOCOL *This,
1358 IN UINT8 PortNumber,
1359 IN EFI_USB_PORT_FEATURE PortFeature
1360 )
1361 /*++
1362
1363 Routine Description:
1364 Clears a feature for the specified root hub port.
1365
1366 Arguments:
1367
1368 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1369
1370 PortNumber Specifies the root hub port whose feature
1371 is requested to be cleared.
1372
1373 PortFeature Indicates the feature selector associated with the
1374 feature clear request.
1375
1376 Returns:
1377 EFI_SUCCESS
1378 The feature specified by PortFeature was cleared for the
1379 USB root hub port specified by PortNumber.
1380 EFI_INVALID_PARAMETER
1381 PortNumber is invalid or PortFeature is invalid.
1382 EFI_DEVICE_ERROR
1383 Can't read register
1384 --*/
1385 {
1386 USB_HC_DEV *HcDev;
1387 UINT32 PSAddr;
1388 UINT16 RHPortControl;
1389 UINT8 TotalPortNumber;
1390 EFI_STATUS Status;
1391
1392 UHCIGetRootHubPortNumber (This, &TotalPortNumber);
1393
1394 if (PortNumber >= TotalPortNumber) {
1395 return EFI_INVALID_PARAMETER;
1396 }
1397
1398 HcDev = USB_HC_DEV_FROM_THIS (This);
1399 PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
1400
1401 Status = ReadRootPortReg (
1402 HcDev->PciIo,
1403 PSAddr,
1404 &RHPortControl
1405 );
1406 if (EFI_ERROR (Status)) {
1407 return EFI_DEVICE_ERROR;
1408 }
1409
1410 switch (PortFeature) {
1411 //
1412 // clear PORT_ENABLE feature means disable port.
1413 //
1414 case EfiUsbPortEnable:
1415 RHPortControl &= 0xfff5;
1416 RHPortControl &= ~USBPORTSC_PED;
1417 break;
1418
1419 //
1420 // clear PORT_SUSPEND feature means resume the port.
1421 // (cause a resume on the specified port if in suspend mode)
1422 //
1423 case EfiUsbPortSuspend:
1424 RHPortControl &= 0xfff5;
1425 RHPortControl &= ~USBPORTSC_SUSP;
1426 break;
1427
1428 //
1429 // no operation
1430 //
1431 case EfiUsbPortPower:
1432 break;
1433
1434 //
1435 // clear PORT_RESET means clear the reset signal.
1436 //
1437 case EfiUsbPortReset:
1438 RHPortControl &= 0xfff5;
1439 RHPortControl &= ~USBPORTSC_PR;
1440 break;
1441
1442 //
1443 // clear connect status change
1444 //
1445 case EfiUsbPortConnectChange:
1446 RHPortControl &= 0xfff5;
1447 RHPortControl |= USBPORTSC_CSC;
1448 break;
1449
1450 //
1451 // clear enable/disable status change
1452 //
1453 case EfiUsbPortEnableChange:
1454 RHPortControl &= 0xfff5;
1455 RHPortControl |= USBPORTSC_PEDC;
1456 break;
1457
1458 //
1459 // root hub does not support this request
1460 //
1461 case EfiUsbPortSuspendChange:
1462 break;
1463
1464 //
1465 // root hub does not support this request
1466 //
1467 case EfiUsbPortOverCurrentChange:
1468 break;
1469
1470 //
1471 // root hub does not support this request
1472 //
1473 case EfiUsbPortResetChange:
1474 break;
1475
1476 default:
1477 return EFI_INVALID_PARAMETER;
1478 }
1479
1480 WriteRootPortReg (
1481 HcDev->PciIo,
1482 PSAddr,
1483 RHPortControl
1484 );
1485
1486 return EFI_SUCCESS;
1487 }
1488
1489 EFI_STATUS
1490 EFIAPI
1491 UHCIControlTransfer (
1492 IN EFI_USB_HC_PROTOCOL *This,
1493 IN UINT8 DeviceAddress,
1494 IN BOOLEAN IsSlowDevice,
1495 IN UINT8 MaximumPacketLength,
1496 IN EFI_USB_DEVICE_REQUEST *Request,
1497 IN EFI_USB_DATA_DIRECTION TransferDirection,
1498 IN OUT VOID *Data, OPTIONAL
1499 IN OUT UINTN *DataLength, OPTIONAL
1500 IN UINTN TimeOut,
1501 OUT UINT32 *TransferResult
1502 )
1503 /*++
1504
1505 Routine Description:
1506 Submits control transfer to a target USB device.
1507
1508 Arguments:
1509
1510 This A pointer to the EFI_USB_HC_PROTOCOL instance.
1511
1512 DeviceAddress Represents the address of the target device on the USB,
1513 which is assigned during USB enumeration.
1514
1515 IsSlowDevice Indicates whether the target device is slow device
1516 or full-speed device.
1517
1518 MaximumPacketLength Indicates the maximum packet size that the
1519 default control transfer endpoint is capable of
1520 sending or receiving.
1521
1522 Request A pointer to the USB device request that will be sent
1523 to the USB device.
1524
1525 TransferDirection Specifies the data direction for the transfer.
1526 There are three values available, DataIn, DataOut
1527 and NoData.
1528
1529 Data A pointer to the buffer of data that will be transmitted
1530 to USB device or received from USB device.
1531
1532 DataLength Indicates the size, in bytes, of the data buffer
1533 specified by Data.
1534
1535 TimeOut Indicates the maximum time, in microseconds,
1536 which the transfer is allowed to complete.
1537
1538 TransferResult A pointer to the detailed result information generated
1539 by this control transfer.
1540
1541 Returns:
1542 EFI_SUCCESS
1543 The control transfer was completed successfully.
1544 EFI_OUT_OF_RESOURCES
1545 The control transfer could not be completed due to a lack of resources.
1546 EFI_INVALID_PARAMETER
1547 Some parameters are invalid.
1548 EFI_TIMEOUT
1549 The control transfer failed due to timeout.
1550 EFI_DEVICE_ERROR
1551 The control transfer failed due to host controller or device error.
1552 Caller should check TranferResult for detailed error information.
1553
1554 --*/
1555 {
1556 USB_HC_DEV *HcDev;
1557 UINT32 StatusReg;
1558 UINT32 FrameNumReg;
1559 UINT8 PktID;
1560 QH_STRUCT *PtrQH;
1561 TD_STRUCT *PtrTD;
1562 TD_STRUCT *PtrPreTD;
1563 TD_STRUCT *PtrSetupTD;
1564 TD_STRUCT *PtrStatusTD;
1565 EFI_STATUS Status;
1566 UINTN Index;
1567 UINTN DataLen;
1568 UINT8 *PtrDataSource;
1569 UINT8 *Ptr;
1570 UINT8 DataToggle;
1571 UINT16 LoadFrameListIndex;
1572 UINT8 PktSize;
1573
1574 UINT8 *RequestMappedAddress;
1575 VOID *RequestMapping;
1576 UINTN RequestLen;
1577
1578 EFI_PHYSICAL_ADDRESS TempPtr;
1579 VOID *Mapping;
1580
1581 TD_STRUCT *PtrFirstDataTD;
1582 TD_STRUCT *ptrLastDataTD;
1583 BOOLEAN FirstTD;
1584
1585 FirstTD = FALSE;
1586 RequestMappedAddress = NULL;
1587 RequestMapping = NULL;
1588 Mapping = NULL;
1589 PtrFirstDataTD = NULL;
1590 ptrLastDataTD = NULL;
1591 PktID = INPUT_PACKET_ID;
1592 Mapping = NULL;
1593 HcDev = USB_HC_DEV_FROM_THIS (This);
1594 StatusReg = (UINT32) (USBSTS);
1595 FrameNumReg = (UINT32) (USBFRNUM);
1596 PtrPreTD = NULL;
1597 PtrTD = NULL;
1598
1599 //
1600 // Parameters Checking
1601 //
1602 if (Request == NULL || TransferResult == NULL) {
1603 return EFI_INVALID_PARAMETER;
1604 }
1605
1606 //
1607 // if errors exist that cause host controller halt,
1608 // then return EFI_DEVICE_ERROR.
1609 //
1610 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
1611
1612 ClearStatusReg (HcDev->PciIo, StatusReg);
1613 *TransferResult = EFI_USB_ERR_SYSTEM;
1614 return EFI_DEVICE_ERROR;
1615 }
1616
1617 //
1618 // low speed usb devices are limited to only an eight-byte
1619 // maximum data payload size
1620 //
1621 if (IsSlowDevice && (MaximumPacketLength != 8)) {
1622 return EFI_INVALID_PARAMETER;
1623 }
1624
1625 if (MaximumPacketLength != 8 &&
1626 MaximumPacketLength != 16 &&
1627 MaximumPacketLength != 32 &&
1628 MaximumPacketLength != 64) {
1629 return EFI_INVALID_PARAMETER;
1630 }
1631
1632 if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {
1633 return EFI_INVALID_PARAMETER;
1634 }
1635
1636 switch (TransferDirection) {
1637
1638 case EfiUsbDataIn:
1639 PktID = INPUT_PACKET_ID;
1640 PtrDataSource = Data;
1641 DataLen = *DataLength;
1642
1643 //
1644 // map the source data buffer for bus master access.
1645 // BusMasterWrite means cpu read
1646 //
1647 Status = HcDev->PciIo->Map (
1648 HcDev->PciIo,
1649 EfiPciIoOperationBusMasterWrite,
1650 PtrDataSource,
1651 &DataLen,
1652 &TempPtr,
1653 &Mapping
1654 );
1655 if (EFI_ERROR (Status)) {
1656 return Status;
1657 }
1658
1659 Ptr = (UINT8 *) ((UINTN) TempPtr);
1660 break;
1661
1662 case EfiUsbDataOut:
1663 PktID = OUTPUT_PACKET_ID;
1664 PtrDataSource = Data;
1665 DataLen = *DataLength;
1666
1667 //
1668 // map the source data buffer for bus master access.
1669 // BusMasterRead means cpu write
1670 //
1671 Status = HcDev->PciIo->Map (
1672 HcDev->PciIo,
1673 EfiPciIoOperationBusMasterRead,
1674 PtrDataSource,
1675 &DataLen,
1676 &TempPtr,
1677 &Mapping
1678 );
1679 if (EFI_ERROR (Status)) {
1680 return Status;
1681 }
1682
1683 Ptr = (UINT8 *) ((UINTN) TempPtr);
1684 break;
1685
1686 //
1687 // no data stage
1688 //
1689 case EfiUsbNoData:
1690 if ((DataLength != NULL) && (*DataLength != 0)) {
1691 return EFI_INVALID_PARAMETER;
1692 }
1693
1694 PktID = OUTPUT_PACKET_ID;
1695 PtrDataSource = NULL;
1696 DataLen = 0;
1697 Ptr = NULL;
1698 break;
1699
1700 default:
1701 return EFI_INVALID_PARAMETER;
1702 }
1703
1704 Status = ClearStatusReg (HcDev->PciIo, StatusReg);
1705 if (EFI_ERROR (Status)) {
1706 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
1707 return EFI_DEVICE_ERROR;
1708 }
1709 //
1710 // create QH structure and init
1711 //
1712 Status = CreateQH (HcDev, &PtrQH);
1713 if (EFI_ERROR (Status)) {
1714 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
1715 return Status;
1716 }
1717
1718 //
1719 // map the Request for bus master access.
1720 // BusMasterRead means cpu write
1721 //
1722 RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
1723 Status = HcDev->PciIo->Map (
1724 HcDev->PciIo,
1725 EfiPciIoOperationBusMasterRead,
1726 (UINT8 *) Request,
1727 &RequestLen,
1728 &TempPtr,
1729 &RequestMapping
1730 );
1731
1732 if (EFI_ERROR (Status)) {
1733 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
1734 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
1735 return Status;
1736 }
1737
1738 RequestMappedAddress = (UINT8 *) ((UINTN) TempPtr);
1739
1740 //
1741 // generate Setup Stage TD
1742 //
1743 Status = GenSetupStageTD (
1744 HcDev,
1745 DeviceAddress,
1746 0,
1747 IsSlowDevice,
1748 (UINT8 *) RequestMappedAddress,
1749 sizeof (EFI_USB_DEVICE_REQUEST),
1750 &PtrSetupTD
1751 );
1752
1753 if (EFI_ERROR (Status)) {
1754 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
1755 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
1756 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
1757 return Status;
1758 }
1759
1760 //
1761 // Data Stage of Control Transfer
1762 //
1763 DataToggle = 1;
1764 FirstTD = TRUE;
1765 while (DataLen > 0) {
1766 //
1767 // create TD structures and link together
1768 //
1769
1770 //
1771 // PktSize is the data load size that each TD carries.
1772 //
1773 PktSize = (UINT8) DataLen;
1774 if (DataLen > MaximumPacketLength) {
1775 PktSize = MaximumPacketLength;
1776 }
1777
1778 Status = GenDataTD (
1779 HcDev,
1780 DeviceAddress,
1781 0,
1782 Ptr,
1783 PktSize,
1784 PktID,
1785 DataToggle,
1786 IsSlowDevice,
1787 &PtrTD
1788 );
1789
1790 if (EFI_ERROR (Status)) {
1791 //
1792 // free all resources occupied
1793 //
1794 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
1795 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
1796 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
1797 DeleteQueuedTDs (HcDev, PtrSetupTD);
1798 DeleteQueuedTDs (HcDev, PtrFirstDataTD);
1799 return Status;
1800 }
1801
1802 //
1803 // Link two TDs in vertical depth
1804 //
1805 if (FirstTD) {
1806 PtrFirstDataTD = PtrTD;
1807 PtrFirstDataTD->ptrNextTD = NULL;
1808 FirstTD = FALSE;
1809 } else {
1810 LinkTDToTD (PtrPreTD, PtrTD);
1811 }
1812
1813 PtrPreTD = PtrTD;
1814
1815 DataToggle ^= 1;
1816 Ptr += PktSize;
1817 DataLen -= PktSize;
1818 }
1819
1820 ptrLastDataTD = PtrTD;
1821
1822 //
1823 // Status Stage of Control Transfer
1824 //
1825 if (PktID == OUTPUT_PACKET_ID) {
1826 PktID = INPUT_PACKET_ID;
1827 } else {
1828 PktID = OUTPUT_PACKET_ID;
1829 }
1830
1831 //
1832 // create Status Stage TD structure
1833 //
1834 Status = CreateStatusTD (
1835 HcDev,
1836 DeviceAddress,
1837 0,
1838 PktID,
1839 IsSlowDevice,
1840 &PtrStatusTD
1841 );
1842
1843 if (EFI_ERROR (Status)) {
1844 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
1845 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
1846 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
1847 DeleteQueuedTDs (HcDev, PtrSetupTD);
1848 DeleteQueuedTDs (HcDev, PtrFirstDataTD);
1849 return Status;
1850 }
1851
1852 if (IsSlowDevice) {
1853 //
1854 // link setup TD structures to QH structure
1855 //
1856 LinkTDToQH (PtrQH, PtrSetupTD);
1857
1858 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
1859
1860 //
1861 // link QH-TDs to total 100 frame list entry to speed up the execution.
1862 //
1863 for (Index = 0; Index < 100; Index++) {
1864 LinkQHToFrameList (
1865 HcDev->FrameListEntry,
1866 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
1867 PtrQH
1868 );
1869 }
1870 //
1871 // Poll QH-TDs execution and get result.
1872 // detail status is returned
1873 //
1874 Status = ExecuteControlTransfer (
1875 HcDev,
1876 PtrSetupTD,
1877 LoadFrameListIndex,
1878 DataLength,
1879 TimeOut,
1880 TransferResult
1881 );
1882 //
1883 // Remove Control Transfer QH-TDs structure from the frame list
1884 // and update the pointers in the Frame List
1885 // and other pointers in other related QH structures.
1886 //
1887 for (Index = 0; Index < 100; Index++) {
1888 DelLinkSingleQH (
1889 HcDev,
1890 PtrQH,
1891 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
1892 FALSE,
1893 FALSE
1894 );
1895 }
1896 //
1897 // delete setup stage TD; the QH is reserved for the next stages.
1898 //
1899 DeleteQueuedTDs (HcDev, PtrSetupTD);
1900
1901 //
1902 // if setup stage error, return error
1903 //
1904 if (EFI_ERROR (Status)) {
1905 goto Done;
1906 }
1907 //
1908 // some control transfers do not have Data Stage
1909 //
1910 if (PtrFirstDataTD != NULL) {
1911
1912 LinkTDToQH (PtrQH, PtrFirstDataTD);
1913 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
1914
1915 for (Index = 0; Index < 500; Index++) {
1916 LinkQHToFrameList (
1917 HcDev->FrameListEntry,
1918 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
1919 PtrQH
1920 );
1921 }
1922
1923 Status = ExecuteControlTransfer (
1924 HcDev,
1925 PtrFirstDataTD,
1926 LoadFrameListIndex,
1927 DataLength,
1928 TimeOut,
1929 TransferResult
1930 );
1931
1932 for (Index = 0; Index < 500; Index++) {
1933 DelLinkSingleQH (
1934 HcDev,
1935 PtrQH,
1936 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
1937 FALSE,
1938 FALSE
1939 );
1940 }
1941 //
1942 // delete data stage TD; the QH is reserved for the next stage.
1943 //
1944 DeleteQueuedTDs (HcDev, PtrFirstDataTD);
1945 }
1946 //
1947 // if data stage error, goto done and return error
1948 //
1949 if (EFI_ERROR (Status)) {
1950 goto Done;
1951 }
1952
1953 LinkTDToQH (PtrQH, PtrStatusTD);
1954 //
1955 // get the frame list index that the QH-TDs will be linked to.
1956 //
1957 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
1958
1959 for (Index = 0; Index < 100; Index++) {
1960 //
1961 // put the QH-TDs directly or indirectly into the proper place
1962 // in the Frame List
1963 //
1964 LinkQHToFrameList (
1965 HcDev->FrameListEntry,
1966 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
1967 PtrQH
1968 );
1969 }
1970 //
1971 // Poll QH-TDs execution and get result.
1972 // detail status is returned
1973 //
1974 Status = ExecuteControlTransfer (
1975 HcDev,
1976 PtrStatusTD,
1977 LoadFrameListIndex,
1978 DataLength,
1979 TimeOut,
1980 TransferResult
1981 );
1982
1983 //
1984 // Delete Control Transfer QH-TDs structure
1985 // and update the pointers in the Frame List
1986 // and other pointers in other related QH structures.
1987 //
1988 // TRUE means must search other framelistindex
1989 //
1990 for (Index = 0; Index < 100; Index++) {
1991 DelLinkSingleQH (
1992 HcDev,
1993 PtrQH,
1994 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
1995 FALSE,
1996 FALSE
1997 );
1998 }
1999
2000 DeleteQueuedTDs (HcDev, PtrStatusTD);
2001
2002 } else {
2003 //
2004 // link setup stage TD with data stage TD
2005 //
2006 PtrPreTD = PtrSetupTD;
2007 if (PtrFirstDataTD != NULL) {
2008 LinkTDToTD (PtrSetupTD, PtrFirstDataTD);
2009 PtrPreTD = ptrLastDataTD;
2010 }
2011 //
2012 // link status TD with previous TD
2013 //
2014 LinkTDToTD (PtrPreTD, PtrStatusTD);
2015
2016 //
2017 // link QH with TD
2018 //
2019 LinkTDToQH (PtrQH, PtrSetupTD);
2020
2021 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
2022 for (Index = 0; Index < 500; Index++) {
2023 //
2024 // put the QH-TDs directly or indirectly into the proper place
2025 // in the Frame List
2026 //
2027 LinkQHToFrameList (
2028 HcDev->FrameListEntry,
2029 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
2030 PtrQH
2031 );
2032 }
2033 //
2034 // Poll QH-TDs execution and get result.
2035 // detail status is returned
2036 //
2037 Status = ExecuteControlTransfer (
2038 HcDev,
2039 PtrSetupTD,
2040 LoadFrameListIndex,
2041 DataLength,
2042 TimeOut,
2043 TransferResult
2044 );
2045 //
2046 // Remove Control Transfer QH-TDs structure from the frame list
2047 // and update the pointers in the Frame List
2048 // and other pointers in other related QH structures.
2049 //
2050 for (Index = 0; Index < 500; Index++) {
2051 DelLinkSingleQH (
2052 HcDev,
2053 PtrQH,
2054 (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
2055 FALSE,
2056 FALSE
2057 );
2058 }
2059
2060 DeleteQueuedTDs (HcDev, PtrSetupTD);
2061 }
2062
2063 Done:
2064
2065 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
2066
2067 if (Mapping != NULL) {
2068 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
2069 }
2070
2071 if (RequestMapping != NULL) {
2072 HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
2073 }
2074 //
2075 // if has errors that cause host controller halt,
2076 // then return EFI_DEVICE_ERROR directly.
2077 //
2078 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
2079
2080 ClearStatusReg (HcDev->PciIo, StatusReg);
2081 *TransferResult |= EFI_USB_ERR_SYSTEM;
2082 return EFI_DEVICE_ERROR;
2083 }
2084
2085 ClearStatusReg (HcDev->PciIo, StatusReg);
2086 HcDev->PciIo->Flush (HcDev->PciIo);
2087 return Status;
2088 }
2089
2090 EFI_STATUS
2091 EFIAPI
2092 UHCIBulkTransfer (
2093 IN EFI_USB_HC_PROTOCOL *This,
2094 IN UINT8 DeviceAddress,
2095 IN UINT8 EndPointAddress,
2096 IN UINT8 MaximumPacketLength,
2097 IN OUT VOID *Data,
2098 IN OUT UINTN *DataLength,
2099 IN OUT UINT8 *DataToggle,
2100 IN UINTN TimeOut,
2101 OUT UINT32 *TransferResult
2102 )
2103 /*++
2104
2105 Routine Description:
2106 Submits bulk transfer to a bulk endpoint of a USB device.
2107
2108 Arguments:
2109
2110 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2111
2112 DeviceAddress Represents the address of the target device on the USB,
2113 which is assigned during USB enumeration.
2114 EndPointAddress The combination of an endpoint number and an
2115 endpoint direction of the target USB device.
2116 Each endpoint address supports data transfer in
2117 one direction except the control endpoint
2118 (whose default endpoint address is 0).
2119 It is the caller's responsibility to make sure that
2120 the EndPointAddress represents a bulk endpoint.
2121
2122 MaximumPacketLength Indicates the maximum packet size the target endpoint
2123 is capable of sending or receiving.
2124
2125 Data A pointer to the buffer of data that will be transmitted
2126 to USB device or received from USB device.
2127 DataLength When input, indicates the size, in bytes, of the data buffer
2128 specified by Data. When output, indicates the actually
2129 transferred data size.
2130
2131 DataToggle A pointer to the data toggle value. On input, it indicates
2132 the initial data toggle value the bulk transfer should adopt;
2133 on output, it is updated to indicate the data toggle value
2134 of the subsequent bulk transfer.
2135
2136 TimeOut Indicates the maximum time, in microseconds, which the
2137 transfer is allowed to complete.
2138
2139 TransferResult A pointer to the detailed result information of the
2140 bulk transfer.
2141
2142 Returns:
2143 EFI_SUCCESS
2144 The bulk transfer was completed successfully.
2145 EFI_OUT_OF_RESOURCES
2146 The bulk transfer could not be submitted due to lack of resource.
2147 EFI_INVALID_PARAMETER
2148 Some parameters are invalid.
2149 EFI_TIMEOUT
2150 The bulk transfer failed due to timeout.
2151 EFI_DEVICE_ERROR
2152 The bulk transfer failed due to host controller or device error.
2153 Caller should check TranferResult for detailed error information.
2154
2155 --*/
2156 {
2157 USB_HC_DEV *HcDev;
2158 UINT32 StatusReg;
2159 UINT32 FrameNumReg;
2160 UINTN DataLen;
2161 QH_STRUCT *PtrQH;
2162 TD_STRUCT *PtrFirstTD;
2163 TD_STRUCT *PtrTD;
2164 TD_STRUCT *PtrPreTD;
2165 UINT16 LoadFrameListIndex;
2166 UINT16 SavedFrameListIndex;
2167 UINT8 PktID;
2168 UINT8 *PtrDataSource;
2169 UINT8 *Ptr;
2170 BOOLEAN IsFirstTD;
2171 EFI_STATUS Status;
2172 UINT32 Index;
2173 UINT8 PktSize;
2174
2175 EFI_USB_DATA_DIRECTION TransferDirection;
2176 //
2177 // Used to calculate how many entries are linked to the
2178 // specified bulk transfer QH-TDs
2179 //
2180 UINT32 LinkTimes;
2181
2182 BOOLEAN ShortPacketEnable;
2183 EFI_PHYSICAL_ADDRESS TempPtr;
2184 VOID *Mapping;
2185
2186 HcDev = USB_HC_DEV_FROM_THIS (This);
2187 StatusReg = (UINT32) (USBSTS);
2188 FrameNumReg = (UINT32) (USBFRNUM);
2189 PktID = INPUT_PACKET_ID;
2190 PtrTD = NULL;
2191 PtrFirstTD = NULL;
2192 PtrPreTD = NULL;
2193 LinkTimes = 1;
2194 DataLen = 0;
2195 Ptr = NULL;
2196 ShortPacketEnable = FALSE;
2197 Mapping = NULL;
2198
2199 //
2200 // Parameters Checking
2201 //
2202
2203 if ((DataLength == NULL) ||
2204 (Data == NULL) ||
2205 (TransferResult == NULL)) {
2206 return EFI_INVALID_PARAMETER;
2207 }
2208
2209 //
2210 // if has errors that cause host controller halt,
2211 // then return EFI_DEVICE_ERROR directly.
2212 //
2213 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
2214
2215 ClearStatusReg (HcDev->PciIo, StatusReg);
2216 *TransferResult = EFI_USB_ERR_SYSTEM;
2217 return EFI_DEVICE_ERROR;
2218 }
2219
2220 if (*DataLength == 0) {
2221 return EFI_INVALID_PARAMETER;
2222 }
2223
2224 if ((*DataToggle != 1) && (*DataToggle != 0)) {
2225 return EFI_INVALID_PARAMETER;
2226 }
2227
2228 if (MaximumPacketLength != 8 &&
2229 MaximumPacketLength != 16 &&
2230 MaximumPacketLength != 32 &&
2231 MaximumPacketLength != 64) {
2232 return EFI_INVALID_PARAMETER;
2233 }
2234
2235 //
2236 // Enable the maximum packet size (64bytes)
2237 // that can be used for full speed bandwidth reclamation
2238 // at the end of a frame.
2239 //
2240 EnableMaxPacketSize (HcDev);
2241
2242 Status = ClearStatusReg (HcDev->PciIo, StatusReg);
2243 if (EFI_ERROR (Status)) {
2244 return EFI_DEVICE_ERROR;
2245 }
2246
2247 //
2248 // construct QH and TD data structures,
2249 // and link them together
2250 //
2251 if (EndPointAddress & 0x80) {
2252 TransferDirection = EfiUsbDataIn;
2253 } else {
2254 TransferDirection = EfiUsbDataOut;
2255 }
2256
2257 switch (TransferDirection) {
2258
2259 case EfiUsbDataIn:
2260 ShortPacketEnable = TRUE;
2261 PktID = INPUT_PACKET_ID;
2262 PtrDataSource = Data;
2263 DataLen = *DataLength;
2264
2265 //
2266 // BusMasterWrite means cpu read
2267 //
2268 Status = HcDev->PciIo->Map (
2269 HcDev->PciIo,
2270 EfiPciIoOperationBusMasterWrite,
2271 PtrDataSource,
2272 &DataLen,
2273 &TempPtr,
2274 &Mapping
2275 );
2276 if (EFI_ERROR (Status)) {
2277 return Status;
2278 }
2279
2280 Ptr = (UINT8 *) ((UINTN) TempPtr);
2281 break;
2282
2283 case EfiUsbDataOut:
2284 PktID = OUTPUT_PACKET_ID;
2285 PtrDataSource = Data;
2286 DataLen = *DataLength;
2287
2288 //
2289 // BusMasterRead means cpu write
2290 //
2291 Status = HcDev->PciIo->Map (
2292 HcDev->PciIo,
2293 EfiPciIoOperationBusMasterRead,
2294 PtrDataSource,
2295 &DataLen,
2296 &TempPtr,
2297 &Mapping
2298 );
2299 if (EFI_ERROR (Status)) {
2300 return Status;
2301 }
2302
2303 Ptr = (UINT8 *) ((UINTN) TempPtr);
2304 break;
2305
2306 default:
2307 return EFI_INVALID_PARAMETER;
2308 }
2309
2310 //
2311 // create QH structure and init
2312 //
2313 Status = CreateQH (HcDev, &PtrQH);
2314 if (EFI_ERROR (Status)) {
2315 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
2316 return Status;
2317 }
2318
2319 //
2320 // i is used to calculate the total number of TDs.
2321 //
2322 Index = 0;
2323
2324 IsFirstTD = TRUE;
2325 while (DataLen > 0) {
2326
2327 //
2328 // create TD structures and link together
2329 //
2330
2331 PktSize = (UINT8) DataLen;
2332 if (DataLen > MaximumPacketLength) {
2333 PktSize = MaximumPacketLength;
2334 }
2335
2336 Status = GenDataTD (
2337 HcDev,
2338 DeviceAddress,
2339 EndPointAddress,
2340 Ptr,
2341 PktSize,
2342 PktID,
2343 *DataToggle,
2344 FALSE,
2345 &PtrTD
2346 );
2347
2348 if (EFI_ERROR (Status)) {
2349 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
2350 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
2351 DeleteQueuedTDs (HcDev, PtrFirstTD);
2352 return Status;
2353 }
2354
2355 //
2356 // Enable short packet detection.
2357 // (default action is disabling short packet detection)
2358 //
2359 if (ShortPacketEnable) {
2360 EnableorDisableTDShortPacket (PtrTD, TRUE);
2361 }
2362
2363 if (IsFirstTD) {
2364 PtrFirstTD = PtrTD;
2365 PtrFirstTD->ptrNextTD = NULL;
2366 IsFirstTD = FALSE;
2367 } else {
2368 //
2369 // Link two TDs in vertical depth
2370 //
2371 LinkTDToTD (PtrPreTD, PtrTD);
2372 }
2373
2374 Index++;
2375
2376 PtrPreTD = PtrTD;
2377
2378 *DataToggle ^= 1;
2379 Ptr += PktSize;
2380 DataLen -= PktSize;
2381 }
2382
2383 //
2384 // link TD structures to QH structure
2385 //
2386 LinkTDToQH (PtrQH, PtrFirstTD);
2387
2388 //
2389 // calculate how many entries are linked to the specified bulk transfer QH-TDs
2390 // the below values are referred to the USB spec revision1.1.
2391 //
2392 switch (MaximumPacketLength) {
2393 case 8:
2394 LinkTimes = Index / 71 + 1;
2395 break;
2396
2397 case 16:
2398 LinkTimes = Index / 51 + 1;
2399 break;
2400
2401 case 32:
2402 LinkTimes = Index / 33 + 1;
2403 break;
2404
2405 case 64:
2406 LinkTimes = Index / 19 + 1;
2407 break;
2408 }
2409
2410 LinkTimes += 500;
2411
2412 //
2413 // put QH-TDs into Frame list
2414 //
2415 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
2416 SavedFrameListIndex = LoadFrameListIndex;
2417
2418 for (Index = 0; Index <= LinkTimes; Index++) {
2419
2420 //
2421 // put the QH-TD directly or indirectly into the proper place
2422 // in the Frame List
2423 //
2424 LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);
2425
2426 LoadFrameListIndex += 1;
2427 LoadFrameListIndex &= 0x3FF;
2428 }
2429
2430 LoadFrameListIndex = SavedFrameListIndex;
2431
2432 //
2433 // Execute QH-TD and get result
2434 //
2435 //
2436 // detail status is put into the Result field in the pIRP
2437 // the Data Toggle value is also re-updated to the value
2438 // of the last successful TD
2439 //
2440 Status = ExecBulkorSyncInterruptTransfer (
2441 HcDev,
2442 PtrFirstTD,
2443 LoadFrameListIndex,
2444 DataLength,
2445 DataToggle,
2446 TimeOut,
2447 TransferResult
2448 );
2449
2450 //
2451 // Delete Bulk transfer QH-TD structure
2452 // and maitain the pointers in the Frame List
2453 // and other pointers in related QH structure
2454 //
2455 // TRUE means must search other framelistindex
2456 //
2457 for (Index = 0; Index <= LinkTimes; Index++) {
2458 DelLinkSingleQH (
2459 HcDev,
2460 PtrQH,
2461 LoadFrameListIndex,
2462 FALSE,
2463 FALSE
2464 );
2465 LoadFrameListIndex += 1;
2466 LoadFrameListIndex &= 0x3FF;
2467 }
2468
2469 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
2470
2471 DeleteQueuedTDs (HcDev, PtrFirstTD);
2472
2473 if (Mapping != NULL) {
2474 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
2475 }
2476
2477 //
2478 // if has errors that cause host controller halt,
2479 // then return EFI_DEVICE_ERROR directly.
2480 //
2481 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
2482
2483 ClearStatusReg (HcDev->PciIo, StatusReg);
2484 *TransferResult |= EFI_USB_ERR_SYSTEM;
2485 return EFI_DEVICE_ERROR;
2486 }
2487
2488 ClearStatusReg (HcDev->PciIo, StatusReg);
2489
2490 HcDev->PciIo->Flush (HcDev->PciIo);
2491
2492 return Status;
2493 }
2494
2495 EFI_STATUS
2496 EFIAPI
2497 UHCIAsyncInterruptTransfer (
2498 IN EFI_USB_HC_PROTOCOL * This,
2499 IN UINT8 DeviceAddress,
2500 IN UINT8 EndPointAddress,
2501 IN BOOLEAN IsSlowDevice,
2502 IN UINT8 MaximumPacketLength,
2503 IN BOOLEAN IsNewTransfer,
2504 IN OUT UINT8 *DataToggle,
2505 IN UINTN PollingInterval, OPTIONAL
2506 IN UINTN DataLength, OPTIONAL
2507 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL
2508 IN VOID *Context OPTIONAL
2509 )
2510 /*++
2511
2512 Routine Description:
2513 Submits an asynchronous interrupt transfer to an
2514 interrupt endpoint of a USB device.
2515
2516 Arguments:
2517
2518 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2519
2520 DeviceAddress Represents the address of the target device on the USB,
2521 which is assigned during USB enumeration.
2522
2523 EndPointAddress The combination of an endpoint number and an endpoint
2524 direction of the target USB device. Each endpoint address
2525 supports data transfer in one direction except the
2526 control endpoint (whose default endpoint address is 0).
2527 It is the caller's responsibility to make sure that
2528 the EndPointAddress represents an interrupt endpoint.
2529
2530 IsSlowDevice Indicates whether the target device is slow device
2531 or full-speed device.
2532
2533 MaximumPacketLength Indicates the maximum packet size the target endpoint
2534 is capable of sending or receiving.
2535
2536 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
2537 the host and the target interrupt endpoint.
2538 If FALSE, the specified asynchronous interrupt pipe
2539 is canceled.
2540
2541 DataToggle A pointer to the data toggle value. On input, it is valid
2542 when IsNewTransfer is TRUE, and it indicates the initial
2543 data toggle value the asynchronous interrupt transfer
2544 should adopt.
2545 On output, it is valid when IsNewTransfer is FALSE,
2546 and it is updated to indicate the data toggle value of
2547 the subsequent asynchronous interrupt transfer.
2548
2549 PollingInterval Indicates the interval, in milliseconds, that the
2550 asynchronous interrupt transfer is polled.
2551 This parameter is required when IsNewTransfer is TRUE.
2552
2553 DataLength Indicates the length of data to be received at the
2554 rate specified by PollingInterval from the target
2555 asynchronous interrupt endpoint. This parameter
2556 is only required when IsNewTransfer is TRUE.
2557
2558 CallBackFunction The Callback function.This function is called at the
2559 rate specified by PollingInterval.This parameter is
2560 only required when IsNewTransfer is TRUE.
2561
2562 Context The context that is passed to the CallBackFunction.
2563 This is an optional parameter and may be NULL.
2564
2565 Returns:
2566 EFI_SUCCESS
2567 The asynchronous interrupt transfer request has been successfully
2568 submitted or canceled.
2569 EFI_INVALID_PARAMETER
2570 Some parameters are invalid.
2571 EFI_OUT_OF_RESOURCES
2572 The request could not be completed due to a lack of resources.
2573 EFI_DEVICE_ERROR
2574 Can't read register
2575 --*/
2576 {
2577 USB_HC_DEV *HcDev;
2578 UINT32 StatusReg;
2579 UINT32 FrameNumReg;
2580 UINTN DataLen;
2581 QH_STRUCT *ptrFirstQH;
2582 QH_STRUCT *PtrQH;
2583 QH_STRUCT *ptrPreQH;
2584 TD_STRUCT *PtrFirstTD;
2585 TD_STRUCT *PtrTD;
2586 TD_STRUCT *PtrPreTD;
2587 UINT16 LoadFrameListIndex;
2588 UINT16 Index;
2589 UINT8 PktID;
2590 UINT8 *Ptr;
2591 UINT8 *MappedPtr;
2592 BOOLEAN IsFirstTD;
2593 BOOLEAN IsFirstQH;
2594 EFI_STATUS Status;
2595 BOOLEAN ShortPacketEnable;
2596 UINT8 CurrentDataToggle;
2597 EFI_PHYSICAL_ADDRESS TempPtr;
2598 VOID *Mapping;
2599 UINT8 PktSize;
2600 QH_STRUCT *TempQH;
2601 EFI_TPL OldTpl;
2602
2603 HcDev = USB_HC_DEV_FROM_THIS (This);
2604 StatusReg = (UINT32) (USBSTS);
2605 FrameNumReg = (UINT32) (USBFRNUM);
2606 Mapping = NULL;
2607 ShortPacketEnable = FALSE;
2608
2609 PktID = INPUT_PACKET_ID;
2610 PtrTD = NULL;
2611 PtrFirstTD = NULL;
2612 PtrPreTD = NULL;
2613 Ptr = NULL;
2614 PtrQH = NULL;
2615 ptrPreQH = NULL;
2616 ptrFirstQH = NULL;
2617
2618 if ((EndPointAddress & 0x80) == 0) {
2619 return EFI_INVALID_PARAMETER;
2620 }
2621
2622 //
2623 // delete Async interrupt transfer request
2624 //
2625 if (!IsNewTransfer) {
2626
2627 OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
2628
2629 Status = DeleteAsyncINTQHTDs (
2630 HcDev,
2631 DeviceAddress,
2632 EndPointAddress,
2633 DataToggle
2634 );
2635
2636 gBS->RestoreTPL (OldTpl);
2637
2638 return Status;
2639 }
2640 //
2641 // if has errors that cause host controller halt,
2642 // then return EFI_DEVICE_ERROR directly.
2643 //
2644 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
2645
2646 ClearStatusReg (HcDev->PciIo, StatusReg);
2647 return EFI_DEVICE_ERROR;
2648 }
2649
2650 ClearStatusReg (HcDev->PciIo, StatusReg);
2651
2652 //
2653 // submit Async interrupt transfer request
2654 //
2655 if (PollingInterval < 1 || PollingInterval > 255) {
2656 return EFI_INVALID_PARAMETER;
2657 }
2658
2659 if (DataLength == 0) {
2660 return EFI_INVALID_PARAMETER;
2661 }
2662
2663 if ((*DataToggle != 1) && (*DataToggle != 0)) {
2664 return EFI_INVALID_PARAMETER;
2665 }
2666
2667 ShortPacketEnable = TRUE;
2668 PktID = INPUT_PACKET_ID;
2669 DataLen = DataLength;
2670 Ptr = AllocatePool (DataLen);
2671 if (Ptr == NULL) {
2672 return EFI_OUT_OF_RESOURCES;
2673 }
2674
2675 //
2676 // BusMasterWrite means cpu read
2677 //
2678 Status = HcDev->PciIo->Map (
2679 HcDev->PciIo,
2680 EfiPciIoOperationBusMasterWrite,
2681 Ptr,
2682 &DataLen,
2683 &TempPtr,
2684 &Mapping
2685 );
2686 if (EFI_ERROR (Status)) {
2687 gBS->FreePool (Ptr);
2688 return Status;
2689 }
2690
2691 MappedPtr = (UINT8 *) ((UINTN) TempPtr);
2692
2693 CurrentDataToggle = *DataToggle;
2694
2695 IsFirstTD = TRUE;
2696
2697 while (DataLen > 0) {
2698 //
2699 // create TD structures and link together
2700 //
2701
2702 PktSize = (UINT8) DataLen;
2703 if (DataLen > MaximumPacketLength) {
2704 PktSize = MaximumPacketLength;
2705 }
2706
2707 Status = GenDataTD (
2708 HcDev,
2709 DeviceAddress,
2710 EndPointAddress,
2711 MappedPtr,
2712 PktSize,
2713 PktID,
2714 CurrentDataToggle,
2715 IsSlowDevice,
2716 &PtrTD
2717 );
2718 if (EFI_ERROR (Status)) {
2719 gBS->FreePool (Ptr);
2720 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
2721 DeleteQueuedTDs (HcDev, PtrFirstTD);
2722 return Status;
2723 }
2724 //
2725 // Enable short packet detection.
2726 //
2727 if (ShortPacketEnable) {
2728 EnableorDisableTDShortPacket (PtrTD, TRUE);
2729 }
2730
2731 if (IsFirstTD) {
2732 PtrFirstTD = PtrTD;
2733 PtrFirstTD->ptrNextTD = NULL;
2734 IsFirstTD = FALSE;
2735 } else {
2736 //
2737 // Link two TDs in vertical depth
2738 //
2739 LinkTDToTD (PtrPreTD, PtrTD);
2740 }
2741
2742 PtrPreTD = PtrTD;
2743
2744 CurrentDataToggle ^= 1;
2745 MappedPtr += PktSize;
2746 DataLen -= PktSize;
2747 }
2748
2749 //
2750 // roll one value back
2751 //
2752 CurrentDataToggle ^= 1;
2753
2754 //
2755 // create a list of QH structures and init,
2756 // link TDs to all the QHs, and link all the QHs together using internal
2757 // defined pointer of the QH_STRUCT.
2758 //
2759 IsFirstQH = TRUE;
2760 ptrPreQH = NULL;
2761 for (Index = 0; Index < 1024;) {
2762
2763 Status = CreateQH (HcDev, &PtrQH);
2764 if (EFI_ERROR (Status)) {
2765 gBS->FreePool (Ptr);
2766 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
2767 DeleteQueuedTDs (HcDev, PtrFirstTD);
2768 PtrQH = ptrFirstQH;
2769 while (PtrQH) {
2770 TempQH = PtrQH;
2771 PtrQH = TempQH->ptrNextIntQH;
2772 UhciFreePool (HcDev, (UINT8 *) TempQH, sizeof (QH_STRUCT));
2773 }
2774
2775 return Status;
2776 }
2777
2778 //
2779 // link TD structures to QH structure
2780 //
2781 LinkTDToQH (PtrQH, PtrFirstTD);
2782
2783 if (IsFirstQH) {
2784 ptrFirstQH = PtrQH;
2785 ptrFirstQH->ptrNextIntQH = NULL;
2786 IsFirstQH = FALSE;
2787 } else {
2788 //
2789 // link neighbor QH structures together
2790 //
2791 ptrPreQH->ptrNextIntQH = PtrQH;
2792 }
2793
2794 ptrPreQH = PtrQH;
2795
2796 Index = (UINT16) (PollingInterval + Index);
2797 }
2798 //
2799 // last QH in QH list should set its next QH pointer to NULL.
2800 //
2801 PtrQH->ptrNextIntQH = NULL;
2802
2803 //
2804 // Save QH-TD structures in Interrupt transfer list,
2805 // for monitor interrupt transfer execution routine use.
2806 //
2807 InsertQHTDToINTList (
2808 HcDev,
2809 ptrFirstQH,
2810 PtrFirstTD,
2811 DeviceAddress,
2812 EndPointAddress,
2813 CurrentDataToggle,
2814 DataLength,
2815 PollingInterval,
2816 Mapping,
2817 Ptr,
2818 CallBackFunction,
2819 Context
2820 );
2821
2822 //
2823 // put QHs-TDs into Frame list
2824 //
2825 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
2826
2827 PtrQH = ptrFirstQH;
2828
2829 for (Index = LoadFrameListIndex; Index < (1024 + LoadFrameListIndex);) {
2830
2831 //
2832 // put the QH-TD directly or indirectly into the proper place
2833 // in the Frame List
2834 //
2835 LinkQHToFrameList (HcDev->FrameListEntry, (UINT16) (Index & 0x3FF), PtrQH);
2836
2837 Index = (UINT16) (PollingInterval + Index);
2838
2839 PtrQH = PtrQH->ptrNextIntQH;
2840 }
2841
2842 HcDev->PciIo->Flush (HcDev->PciIo);
2843
2844 return EFI_SUCCESS;
2845 }
2846
2847 EFI_STATUS
2848 EFIAPI
2849 UHCISyncInterruptTransfer (
2850 IN EFI_USB_HC_PROTOCOL *This,
2851 IN UINT8 DeviceAddress,
2852 IN UINT8 EndPointAddress,
2853 IN BOOLEAN IsSlowDevice,
2854 IN UINT8 MaximumPacketLength,
2855 IN OUT VOID *Data,
2856 IN OUT UINTN *DataLength,
2857 IN OUT UINT8 *DataToggle,
2858 IN UINTN TimeOut,
2859 OUT UINT32 *TransferResult
2860 )
2861 /*++
2862
2863 Routine Description:
2864 Submits synchronous interrupt transfer to an interrupt endpoint
2865 of a USB device.
2866
2867 Arguments:
2868
2869 This A pointer to the EFI_USB_HC_PROTOCOL instance.
2870
2871 DeviceAddress Represents the address of the target device on the USB,
2872 which is assigned during USB enumeration.
2873
2874 EndPointAddress The combination of an endpoint number and an endpoint
2875 direction of the target USB device. Each endpoint
2876 address supports data transfer in one direction
2877 except the control endpoint (whose default
2878 endpoint address is 0). It is the caller's responsibility
2879 to make sure that the EndPointAddress represents
2880 an interrupt endpoint.
2881
2882 IsSlowDevice Indicates whether the target device is slow device
2883 or full-speed device.
2884
2885 MaximumPacketLength Indicates the maximum packet size the target endpoint
2886 is capable of sending or receiving.
2887
2888 Data A pointer to the buffer of data that will be transmitted
2889 to USB device or received from USB device.
2890
2891 DataLength On input, the size, in bytes, of the data buffer specified
2892 by Data. On output, the number of bytes transferred.
2893
2894 DataToggle A pointer to the data toggle value. On input, it indicates
2895 the initial data toggle value the synchronous interrupt
2896 transfer should adopt;
2897 on output, it is updated to indicate the data toggle value
2898 of the subsequent synchronous interrupt transfer.
2899
2900 TimeOut Indicates the maximum time, in microseconds, which the
2901 transfer is allowed to complete.
2902
2903 TransferResult A pointer to the detailed result information from
2904 the synchronous interrupt transfer.
2905
2906 Returns:
2907 EFI_SUCCESS
2908 The synchronous interrupt transfer was completed successfully.
2909 EFI_OUT_OF_RESOURCES
2910 The synchronous interrupt transfer could not be submitted due
2911 to lack of resource.
2912 EFI_INVALID_PARAMETER
2913 Some parameters are invalid.
2914 EFI_TIMEOUT
2915 The synchronous interrupt transfer failed due to timeout.
2916 EFI_DEVICE_ERROR
2917 The synchronous interrupt transfer failed due to host controller
2918 or device error. Caller should check TranferResult for detailed
2919 error information.
2920 --*/
2921 {
2922 USB_HC_DEV *HcDev;
2923 UINT32 StatusReg;
2924 UINT32 FrameNumReg;
2925 UINTN DataLen;
2926 QH_STRUCT *PtrQH;
2927 TD_STRUCT *PtrFirstTD;
2928 TD_STRUCT *PtrTD;
2929 TD_STRUCT *PtrPreTD;
2930 UINT16 LoadFrameListIndex;
2931 UINT16 SavedFrameListIndex;
2932 UINT32 Index;
2933 UINT32 LinkTimes;
2934 UINT8 PktID;
2935 UINT8 *PtrDataSource;
2936 UINT8 *Ptr;
2937 BOOLEAN IsFirstTD;
2938 EFI_STATUS Status;
2939 BOOLEAN ShortPacketEnable;
2940 EFI_PHYSICAL_ADDRESS TempPtr;
2941 VOID *Mapping;
2942 UINT8 PktSize;
2943
2944 HcDev = USB_HC_DEV_FROM_THIS (This);
2945 StatusReg = (UINT32) (USBSTS);
2946 FrameNumReg = (UINT32) (USBFRNUM);
2947 ShortPacketEnable = FALSE;
2948 Mapping = NULL;
2949 PktID = INPUT_PACKET_ID;
2950 PtrTD = NULL;
2951 PtrFirstTD = NULL;
2952 PtrPreTD = NULL;
2953 DataLen = 0;
2954 Ptr = NULL;
2955 Index = 0;
2956 LinkTimes = 0;
2957
2958 //
2959 // Parameters Checking
2960 //
2961
2962 if ((DataLength == NULL) ||
2963 (Data == NULL) ||
2964 (TransferResult == NULL)) {
2965 return EFI_INVALID_PARAMETER;
2966 }
2967
2968 //
2969 // if has errors that cause host controller halt,
2970 // then return EFI_DEVICE_ERROR directly.
2971 //
2972 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
2973
2974 ClearStatusReg (HcDev->PciIo, StatusReg);
2975 *TransferResult = EFI_USB_ERR_SYSTEM;
2976 return EFI_DEVICE_ERROR;
2977 }
2978
2979 if ((EndPointAddress & 0x80) == 0) {
2980 return EFI_INVALID_PARAMETER;
2981 }
2982
2983 if (*DataLength == 0) {
2984 return EFI_INVALID_PARAMETER;
2985 }
2986
2987 if ((*DataToggle != 1) && (*DataToggle != 0)) {
2988 return EFI_INVALID_PARAMETER;
2989 }
2990
2991 if (MaximumPacketLength > 64) {
2992 return EFI_INVALID_PARAMETER;
2993 }
2994
2995 if (IsSlowDevice && (MaximumPacketLength > 8)) {
2996 return EFI_INVALID_PARAMETER;
2997 }
2998
2999 if (TransferResult == NULL) {
3000 return EFI_INVALID_PARAMETER;
3001 }
3002
3003 ClearStatusReg (HcDev->PciIo, StatusReg);
3004
3005 //
3006 // submit Sync interrupt transfer request
3007 //
3008 ShortPacketEnable = TRUE;
3009 PktID = INPUT_PACKET_ID;
3010 DataLen = *DataLength;
3011 PtrDataSource = Data;
3012
3013 //
3014 // create QH structure and init
3015 //
3016 Status = CreateQH (HcDev, &PtrQH);
3017 if (EFI_ERROR (Status)) {
3018 return Status;
3019 }
3020
3021 //
3022 // BusMasterWrite means cpu read
3023 //
3024 Status = HcDev->PciIo->Map (
3025 HcDev->PciIo,
3026 EfiPciIoOperationBusMasterWrite,
3027 PtrDataSource,
3028 &DataLen,
3029 &TempPtr,
3030 &Mapping
3031 );
3032 if (EFI_ERROR (Status)) {
3033 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
3034 return Status;
3035 }
3036
3037 Ptr = (UINT8 *) ((UINTN) TempPtr);
3038
3039 IsFirstTD = TRUE;
3040 while (DataLen > 0) {
3041 //
3042 // create TD structures and link together
3043 //
3044 PktSize = (UINT8) DataLen;
3045 if (DataLen > MaximumPacketLength) {
3046 PktSize = MaximumPacketLength;
3047 }
3048
3049 Status = GenDataTD (
3050 HcDev,
3051 DeviceAddress,
3052 EndPointAddress,
3053 Ptr,
3054 PktSize,
3055 PktID,
3056 *DataToggle,
3057 IsSlowDevice,
3058 &PtrTD
3059 );
3060 if (EFI_ERROR (Status)) {
3061 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
3062 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
3063 DeleteQueuedTDs (HcDev, PtrFirstTD);
3064 return Status;
3065 }
3066 //
3067 // Enable short packet detection.
3068 //
3069 if (ShortPacketEnable) {
3070 EnableorDisableTDShortPacket (PtrTD, TRUE);
3071 }
3072
3073 if (IsFirstTD) {
3074 PtrFirstTD = PtrTD;
3075 PtrFirstTD->ptrNextTD = NULL;
3076 IsFirstTD = FALSE;
3077 } else {
3078 //
3079 // Link two TDs in vertical depth
3080 //
3081 LinkTDToTD (PtrPreTD, PtrTD);
3082 }
3083
3084 Index++;
3085
3086 PtrPreTD = PtrTD;
3087
3088 *DataToggle ^= 1;
3089 Ptr += PktSize;
3090 DataLen -= PktSize;
3091 }
3092
3093 //
3094 // link TD structures to QH structure
3095 //
3096 LinkTDToQH (PtrQH, PtrFirstTD);
3097
3098 switch (MaximumPacketLength) {
3099 case 8:
3100 LinkTimes = Index / 71 + 1;
3101 break;
3102
3103 case 16:
3104 LinkTimes = Index / 51 + 1;
3105 break;
3106
3107 case 32:
3108 LinkTimes = Index / 33 + 1;
3109 break;
3110
3111 case 64:
3112 LinkTimes = Index / 19 + 1;
3113 break;
3114 }
3115
3116 LinkTimes += 100;
3117
3118 LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
3119 SavedFrameListIndex = LoadFrameListIndex;
3120
3121 for (Index = 0; Index < LinkTimes; Index++) {
3122
3123 //
3124 // put the QH-TD directly or indirectly into the proper place
3125 // in the Frame List
3126 //
3127 LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);
3128
3129 LoadFrameListIndex += 1;
3130 LoadFrameListIndex &= 0x3FF;
3131 }
3132
3133 LoadFrameListIndex = SavedFrameListIndex;
3134 //
3135 // detail status is put into the Result field in the pIRP
3136 // the Data Toggle value is also re-updated to the value
3137 // of the last successful TD
3138 //
3139 Status = ExecBulkorSyncInterruptTransfer (
3140 HcDev,
3141 PtrFirstTD,
3142 LoadFrameListIndex,
3143 DataLength,
3144 DataToggle,
3145 TimeOut,
3146 TransferResult
3147 );
3148 //
3149 // Delete Sync Interrupt transfer QH-TD structure
3150 // and maintain the pointers in the Frame List
3151 // and other pointers in related QH structure
3152 //
3153 // TRUE means must search other framelistindex
3154 //
3155 for (Index = 0; Index <= LinkTimes; Index++) {
3156 DelLinkSingleQH (
3157 HcDev,
3158 PtrQH,
3159 LoadFrameListIndex,
3160 FALSE,
3161 FALSE
3162 );
3163 LoadFrameListIndex += 1;
3164 LoadFrameListIndex &= 0x3FF;
3165 }
3166
3167 UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
3168
3169 DeleteQueuedTDs (HcDev, PtrFirstTD);
3170
3171 HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
3172
3173 //
3174 // if has errors that cause host controller halt,
3175 // then return EFI_DEVICE_ERROR directly.
3176 //
3177 if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
3178
3179 ClearStatusReg (HcDev->PciIo, StatusReg);
3180 *TransferResult |= EFI_USB_ERR_SYSTEM;
3181 return EFI_DEVICE_ERROR;
3182 }
3183
3184 ClearStatusReg (HcDev->PciIo, StatusReg);
3185
3186 HcDev->PciIo->Flush (HcDev->PciIo);
3187
3188 return Status;
3189 }
3190
3191 EFI_STATUS
3192 EFIAPI
3193 UHCIIsochronousTransfer (
3194 IN EFI_USB_HC_PROTOCOL *This,
3195 IN UINT8 DeviceAddress,
3196 IN UINT8 EndPointAddress,
3197 IN UINT8 MaximumPacketLength,
3198 IN OUT VOID *Data,
3199 IN UINTN DataLength,
3200 OUT UINT32 *TransferResult
3201 )
3202 /*++
3203
3204 Routine Description:
3205 Submits isochronous transfer to a target USB device.
3206
3207 Arguments:
3208
3209 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3210 DeviceAddress - Represents the address of the target device on the USB,
3211 which is assigned during USB enumeration.
3212 EndPointAddress - End point address
3213 MaximumPacketLength - Indicates the maximum packet size that the
3214 default control transfer endpoint is capable of
3215 sending or receiving.
3216 Data - A pointer to the buffer of data that will be transmitted
3217 to USB device or received from USB device.
3218 DataLength - Indicates the size, in bytes, of the data buffer
3219 specified by Data.
3220 TransferResult - A pointer to the detailed result information generated
3221 by this control transfer.
3222 Returns:
3223 EFI_UNSUPPORTED
3224
3225 --*/
3226 {
3227 return EFI_UNSUPPORTED;
3228 }
3229
3230
3231 EFI_STATUS
3232 EFIAPI
3233 UHCIAsyncIsochronousTransfer (
3234 IN EFI_USB_HC_PROTOCOL * This,
3235 IN UINT8 DeviceAddress,
3236 IN UINT8 EndPointAddress,
3237 IN UINT8 MaximumPacketLength,
3238 IN OUT VOID *Data,
3239 IN UINTN DataLength,
3240 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
3241 IN VOID *Context OPTIONAL
3242 )
3243 /*++
3244
3245 Routine Description:
3246 Submits Async isochronous transfer to a target USB device.
3247
3248 Arguments:
3249
3250 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3251
3252 DeviceAddress - Represents the address of the target device on the USB,
3253 which is assigned during USB enumeration.
3254
3255 EndPointAddress - End point address
3256
3257 MaximumPacketLength - Indicates the maximum packet size that the
3258 default control transfer endpoint is capable of
3259 sending or receiving.
3260
3261 Data - A pointer to the buffer of data that will be transmitted
3262 to USB device or received from USB device.
3263
3264 IsochronousCallBack - When the transfer complete, the call back function will be called
3265
3266 Context - Pass to the call back function as parameter
3267
3268 Returns:
3269 EFI_UNSUPPORTED
3270
3271 --*/
3272 {
3273 return EFI_UNSUPPORTED;
3274 }
3275
3276 //
3277 // UEFI 2.0 Protocol
3278 //
3279 EFI_STATUS
3280 EFIAPI
3281 UHCI2GetCapability(
3282 IN EFI_USB2_HC_PROTOCOL * This,
3283 OUT UINT8 *MaxSpeed,
3284 OUT UINT8 *PortNumber,
3285 OUT UINT8 *Is64BitCapable
3286 )
3287 /*++
3288
3289 Routine Description:
3290 Retrieves capabilities of USB host controller according to UEFI 2.0 spec.
3291
3292 Arguments:
3293 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3294
3295 MaxSpeed - A pointer to the max speed USB host controller supports.
3296
3297 PortNumber - A pointer to the number of root hub ports.
3298
3299 Is64BitCapable - A pointer to an integer to show whether USB host controller
3300 supports 64-bit memory addressing.
3301 Returns:
3302 EFI_SUCCESS
3303 The host controller capabilities were retrieved successfully.
3304 EFI_INVALID_PARAMETER
3305 MaxSpeed or PortNumber or Is64BitCapable is NULL.
3306 EFI_DEVICE_ERROR
3307 An error was encountered while attempting to retrieve the capabilities.
3308
3309 --*/
3310 {
3311 USB_HC_DEV *HcDev;
3312
3313 HcDev = USB2_HC_DEV_FROM_THIS (This);
3314
3315 if ((NULL == MaxSpeed)
3316 ||(NULL == PortNumber)
3317 || (NULL == Is64BitCapable))
3318 {
3319 return EFI_INVALID_PARAMETER;
3320 }
3321
3322 *MaxSpeed = EFI_USB_SPEED_FULL;
3323 *Is64BitCapable = (UINT8)FALSE;
3324 return UHCIGetRootHubPortNumber(&HcDev->UsbHc, PortNumber);
3325 }
3326
3327 EFI_STATUS
3328 EFIAPI
3329 UHCI2Reset (
3330 IN EFI_USB2_HC_PROTOCOL * This,
3331 IN UINT16 Attributes
3332 )
3333 /*++
3334
3335 Routine Description:
3336 Provides software reset for the USB host controller according to UEFI 2.0 spec.
3337
3338 Arguments:
3339 This - A pointer to the EFI_USB2_HC_PROTOCOL instance.
3340
3341 Attributes - A bit mask of the reset operation to perform.
3342 See below for a list of the supported bit mask values.
3343
3344 #define EFI_USB_HC_RESET_GLOBAL 0x0001
3345 #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
3346 #define EFI_USB_HC_RESET_GLOBAL _WITH_DEBUG 0x0004
3347 #define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008
3348
3349 EFI_USB_HC_RESET_GLOBAL
3350 If this bit is set, a global reset signal will be sent to the USB bus.
3351 This resets all of the USB bus logic, including the USB host
3352 controller hardware and all the devices attached on the USB bus.
3353 EFI_USB_HC_RESET_HOST_CONTROLLER
3354 If this bit is set, the USB host controller hardware will be reset.
3355 No reset signal will be sent to the USB bus.
3356
3357 Returns:
3358 EFI_SUCCESS
3359 The reset operation succeeded.
3360 EFI_INVALID_PARAMETER
3361 Attributes is not valid.
3362 EFI_UNSUPPORTED
3363 The type of reset specified by Attributes is not currently supported by the host controller hardware.
3364 EFI_ACCESS_DENIED
3365 Reset operation is rejected due to the debug port being configured and active.
3366 EFI_DEVICE_ERROR
3367 An error was encountered while attempting to perform
3368 the reset operation.
3369 --*/
3370 {
3371 USB_HC_DEV *HcDev;
3372
3373 HcDev = USB2_HC_DEV_FROM_THIS (This);
3374
3375 if (Attributes==EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG || Attributes==EFI_USB_HC_RESET_HOST_WITH_DEBUG)
3376 return EFI_UNSUPPORTED;
3377
3378 return UHCIReset(
3379 &HcDev->UsbHc,
3380 Attributes
3381 );
3382 }
3383
3384 EFI_STATUS
3385 EFIAPI
3386 UHCI2GetState (
3387 IN EFI_USB2_HC_PROTOCOL * This,
3388 OUT EFI_USB_HC_STATE * State
3389 )
3390 /*++
3391
3392 Routine Description:
3393 Retrieves current state of the USB host controller according to UEFI 2.0 spec.
3394
3395 Arguments:
3396
3397 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3398
3399 State - A pointer to the EFI_USB_HC_STATE data structure that
3400 indicates current state of the USB host controller.
3401 Type EFI_USB_HC_STATE is defined below.
3402
3403 typedef enum {
3404 EfiUsbHcStateHalt,
3405 EfiUsbHcStateOperational,
3406 EfiUsbHcStateSuspend,
3407 EfiUsbHcStateMaximum
3408 } EFI_USB_HC_STATE;
3409
3410 Returns:
3411 EFI_SUCCESS
3412 The state information of the host controller was returned in State.
3413 EFI_INVALID_PARAMETER
3414 State is NULL.
3415 EFI_DEVICE_ERROR
3416 An error was encountered while attempting to retrieve the
3417 host controller's current state.
3418 --*/
3419 {
3420 USB_HC_DEV *HcDev;
3421
3422 HcDev = USB2_HC_DEV_FROM_THIS (This);
3423 return UHCIGetState(
3424 &HcDev->UsbHc,
3425 State
3426 );
3427 }
3428
3429 EFI_STATUS
3430 EFIAPI
3431 UHCI2SetState (
3432 IN EFI_USB2_HC_PROTOCOL * This,
3433 IN EFI_USB_HC_STATE State
3434 )
3435 /*++
3436
3437 Routine Description:
3438 Sets the USB host controller to a specific state according to UEFI 2.0 spec.
3439
3440 Arguments:
3441
3442 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3443
3444 State - Indicates the state of the host controller that will be set.
3445
3446 Returns:
3447 EFI_SUCCESS
3448 The USB host controller was successfully placed in the state
3449 specified by State.
3450 EFI_INVALID_PARAMETER
3451 State is invalid.
3452 EFI_DEVICE_ERROR
3453 Failed to set the state specified by State due to device error.
3454 --*/
3455 {
3456 USB_HC_DEV *HcDev;
3457
3458 HcDev = USB2_HC_DEV_FROM_THIS (This);
3459 return UHCISetState(
3460 &HcDev->UsbHc,
3461 State
3462 );
3463 }
3464
3465 EFI_STATUS
3466 EFIAPI
3467 UHCI2ControlTransfer (
3468 IN EFI_USB2_HC_PROTOCOL * This,
3469 IN UINT8 DeviceAddress,
3470 IN UINT8 DeviceSpeed,
3471 IN UINTN MaximumPacketLength,
3472 IN EFI_USB_DEVICE_REQUEST * Request,
3473 IN EFI_USB_DATA_DIRECTION TransferDirection,
3474 IN OUT VOID *Data,
3475 IN OUT UINTN *DataLength,
3476 IN UINTN TimeOut,
3477 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
3478 OUT UINT32 *TransferResult
3479 )
3480 /*++
3481
3482 Routine Description:
3483 Submits control transfer to a target USB device accroding to UEFI 2.0 spec..
3484
3485 Arguments:
3486
3487 This - A pointer to the EFI_USB_HC_PROTOCOL instance.
3488
3489 DeviceAddress -Represents the address of the target device on the USB,
3490 which is assigned during USB enumeration.
3491
3492 DeviceSpeed - Indicates transfer speed of device.
3493
3494 MaximumPacketLength - Indicates the maximum packet size that the
3495 default control transfer endpoint is capable of
3496 sending or receiving.
3497
3498 Request - A pointer to the USB device request that will be sent
3499 to the USB device.
3500
3501 TransferDirection - Specifies the data direction for the transfer.
3502 There are three values available, DataIn, DataOut
3503 and NoData.
3504
3505 Data -A pointer to the buffer of data that will be transmitted
3506 to USB device or received from USB device.
3507
3508 DataLength - Indicates the size, in bytes, of the data buffer
3509 specified by Data.
3510
3511 TimeOut - Indicates the maximum time, in microseconds,
3512 which the transfer is allowed to complete.
3513
3514 TransferResult - A pointer to the detailed result information generated
3515 by this control transfer.
3516
3517 Returns:
3518 EFI_SUCCESS
3519 The control transfer was completed successfully.
3520 EFI_OUT_OF_RESOURCES
3521 The control transfer could not be completed due to a lack of resources.
3522 EFI_INVALID_PARAMETER
3523 Some parameters are invalid.
3524 EFI_TIMEOUT
3525 The control transfer failed due to timeout.
3526 EFI_DEVICE_ERROR
3527 The control transfer failed due to host controller or device error.
3528 Caller should check TranferResult for detailed error information.
3529
3530 --*/
3531 {
3532 USB_HC_DEV *HcDev;
3533 BOOLEAN IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
3534
3535 HcDev = USB2_HC_DEV_FROM_THIS (This);
3536
3537 return UHCIControlTransfer(
3538 &HcDev->UsbHc,
3539 DeviceAddress,
3540 IsSlowDevice,
3541 (UINT8) MaximumPacketLength,
3542 Request,
3543 TransferDirection,
3544 Data,
3545 DataLength,
3546 TimeOut,
3547 TransferResult
3548 );
3549 }
3550
3551 EFI_STATUS
3552 EFIAPI
3553 UHCI2BulkTransfer (
3554 IN EFI_USB2_HC_PROTOCOL * This,
3555 IN UINT8 DeviceAddress,
3556 IN UINT8 EndPointAddress,
3557 IN UINT8 DeviceSpeed,
3558 IN UINTN MaximumPacketLength,
3559 IN UINT8 DataBuffersNumber,
3560 IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM],
3561 IN OUT UINTN *DataLength,
3562 IN OUT UINT8 *DataToggle,
3563 IN UINTN TimeOut,
3564 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
3565 OUT UINT32 *TransferResult
3566 )
3567 /*++
3568
3569 Routine Description:
3570 Submits bulk transfer to a bulk endpoint of a USB device according to UEFI 2.0 spec.
3571
3572 Arguments:
3573
3574 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3575
3576 DeviceAddress Represents the address of the target device on the USB,
3577 which is assigned during USB enumeration.
3578
3579 EndPointAddress The combination of an endpoint number and an
3580 endpoint direction of the target USB device.
3581 Each endpoint address supports data transfer in
3582 one direction except the control endpoint
3583 (whose default endpoint address is 0).
3584 It is the caller's responsibility to make sure that
3585 the EndPointAddress represents a bulk endpoint.
3586
3587 DeviceSpeed Indicates device speed. The supported values are EFI_USB_SPEED_FULL
3588 and EFI_USB_SPEED_HIGH.
3589
3590 MaximumPacketLength Indicates the maximum packet size the target endpoint
3591 is capable of sending or receiving.
3592
3593 DataBuffersNumber Number of data buffers prepared for the transfer.
3594
3595 Data Array of pointers to the buffers of data that will be transmitted
3596 to USB device or received from USB device.
3597
3598 DataLength When input, indicates the size, in bytes, of the data buffer
3599 specified by Data. When output, indicates the actually
3600 transferred data size.
3601
3602 DataToggle A pointer to the data toggle value. On input, it indicates
3603 the initial data toggle value the bulk transfer should adopt;
3604 on output, it is updated to indicate the data toggle value
3605 of the subsequent bulk transfer.
3606
3607 Translator A pointr to the transaction translator data.
3608
3609 TimeOut Indicates the maximum time, in microseconds, which the
3610 transfer is allowed to complete.
3611
3612 TransferResult A pointer to the detailed result information of the
3613 bulk transfer.
3614
3615 Returns:
3616 EFI_SUCCESS
3617 The bulk transfer was completed successfully.
3618
3619 EFI_OUT_OF_RESOURCES
3620 The bulk transfer could not be submitted due to lack of resource.
3621
3622 EFI_INVALID_PARAMETER
3623 Some parameters are invalid.
3624
3625 EFI_TIMEOUT
3626 The bulk transfer failed due to timeout.
3627
3628 EFI_DEVICE_ERROR
3629 The bulk transfer failed due to host controller or device error.
3630 Caller should check TranferResult for detailed error information.
3631
3632 --*/
3633 {
3634 USB_HC_DEV *HcDev;
3635
3636 HcDev = USB2_HC_DEV_FROM_THIS (This);
3637
3638 if( Data == NULL || DeviceSpeed==EFI_USB_SPEED_LOW)
3639 return EFI_INVALID_PARAMETER;
3640 /* For full-speed bulk transfers only the data pointed by Data[0] shall be used */
3641
3642 return UHCIBulkTransfer (
3643 &HcDev->UsbHc,
3644 DeviceAddress,
3645 EndPointAddress,
3646 (UINT8) MaximumPacketLength,
3647 *Data,
3648 DataLength,
3649 DataToggle,
3650 TimeOut,
3651 TransferResult
3652 );
3653 }
3654
3655 EFI_STATUS
3656 EFIAPI
3657 UHCI2AsyncInterruptTransfer (
3658 IN EFI_USB2_HC_PROTOCOL * This,
3659 IN UINT8 DeviceAddress,
3660 IN UINT8 EndPointAddress,
3661 IN UINT8 DeviceSpeed,
3662 IN UINTN MaximumPacketLength,
3663 IN BOOLEAN IsNewTransfer,
3664 IN OUT UINT8 *DataToggle,
3665 IN UINTN PollingInterval,
3666 IN UINTN DataLength,
3667 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
3668 IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
3669 IN VOID *Context
3670 )
3671 /*++
3672
3673 Routine Description:
3674 Submits an asynchronous interrupt transfer to an
3675 interrupt endpoint of a USB device according to UEFI 2.0 spec.
3676
3677 Arguments:
3678
3679 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3680
3681 DeviceAddress Represents the address of the target device on the USB,
3682 which is assigned during USB enumeration.
3683
3684 EndPointAddress The combination of an endpoint number and an endpoint
3685 direction of the target USB device. Each endpoint address
3686 supports data transfer in one direction except the
3687 control endpoint (whose default endpoint address is 0).
3688 It is the caller's responsibility to make sure that
3689 the EndPointAddress represents an interrupt endpoint.
3690
3691 DeviceSpeed Indicates device speed.
3692
3693 MaximumPacketLength Indicates the maximum packet size the target endpoint
3694 is capable of sending or receiving.
3695
3696 IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
3697 the host and the target interrupt endpoint.
3698 If FALSE, the specified asynchronous interrupt pipe
3699 is canceled.
3700
3701 DataToggle A pointer to the data toggle value. On input, it is valid
3702 when IsNewTransfer is TRUE, and it indicates the initial
3703 data toggle value the asynchronous interrupt transfer
3704 should adopt.
3705 On output, it is valid when IsNewTransfer is FALSE,
3706 and it is updated to indicate the data toggle value of
3707 the subsequent asynchronous interrupt transfer.
3708
3709 PollingInterval Indicates the interval, in milliseconds, that the
3710 asynchronous interrupt transfer is polled.
3711 This parameter is required when IsNewTransfer is TRUE.
3712
3713 DataLength Indicates the length of data to be received at the
3714 rate specified by PollingInterval from the target
3715 asynchronous interrupt endpoint. This parameter
3716 is only required when IsNewTransfer is TRUE.
3717
3718 Translator A pointr to the transaction translator data.
3719
3720 CallBackFunction The Callback function.This function is called at the
3721 rate specified by PollingInterval.This parameter is
3722 only required when IsNewTransfer is TRUE.
3723
3724 Context The context that is passed to the CallBackFunction.
3725 This is an optional parameter and may be NULL.
3726
3727 Returns:
3728
3729 EFI_SUCCESS
3730 The asynchronous interrupt transfer request has been successfully
3731 submitted or canceled.
3732
3733 EFI_INVALID_PARAMETER
3734 Some parameters are invalid.
3735
3736 EFI_OUT_OF_RESOURCES
3737 The request could not be completed due to a lack of resources.
3738
3739 EFI_DEVICE_ERROR
3740 Can't read register
3741 --*/
3742 {
3743 USB_HC_DEV *HcDev;
3744 BOOLEAN IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
3745
3746 HcDev = USB2_HC_DEV_FROM_THIS (This);
3747 return UHCIAsyncInterruptTransfer(
3748 &HcDev->UsbHc,
3749 DeviceAddress,
3750 EndPointAddress,
3751 IsSlowDevice,
3752 (UINT8) MaximumPacketLength,
3753 IsNewTransfer,
3754 DataToggle,
3755 PollingInterval,
3756 DataLength,
3757 CallBackFunction,
3758 Context
3759 );
3760 }
3761
3762 EFI_STATUS
3763 EFIAPI
3764 UHCI2SyncInterruptTransfer (
3765 IN EFI_USB2_HC_PROTOCOL * This,
3766 IN UINT8 DeviceAddress,
3767 IN UINT8 EndPointAddress,
3768 IN UINT8 DeviceSpeed,
3769 IN UINTN MaximumPacketLength,
3770 IN OUT VOID *Data,
3771 IN OUT UINTN *DataLength,
3772 IN OUT UINT8 *DataToggle,
3773 IN UINTN TimeOut,
3774 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
3775 OUT UINT32 *TransferResult
3776 )
3777 /*++
3778
3779 Routine Description:
3780 Submits synchronous interrupt transfer to an interrupt endpoint
3781 of a USB device according to UEFI 2.0 spec.
3782
3783 Arguments:
3784
3785 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3786
3787 DeviceAddress Represents the address of the target device on the USB,
3788 which is assigned during USB enumeration.
3789
3790 EndPointAddress The combination of an endpoint number and an endpoint
3791 direction of the target USB device. Each endpoint
3792 address supports data transfer in one direction
3793 except the control endpoint (whose default
3794 endpoint address is 0). It is the caller's responsibility
3795 to make sure that the EndPointAddress represents
3796 an interrupt endpoint.
3797
3798 DeviceSpeed Indicates device speed.
3799
3800 MaximumPacketLength Indicates the maximum packet size the target endpoint
3801 is capable of sending or receiving.
3802
3803 Data A pointer to the buffer of data that will be transmitted
3804 to USB device or received from USB device.
3805
3806 DataLength On input, the size, in bytes, of the data buffer specified
3807 by Data. On output, the number of bytes transferred.
3808
3809 DataToggle A pointer to the data toggle value. On input, it indicates
3810 the initial data toggle value the synchronous interrupt
3811 transfer should adopt;
3812 on output, it is updated to indicate the data toggle value
3813 of the subsequent synchronous interrupt transfer.
3814
3815 TimeOut Indicates the maximum time, in microseconds, which the
3816 transfer is allowed to complete.
3817 Translator A pointr to the transaction translator data.
3818 TransferResult A pointer to the detailed result information from
3819 the synchronous interrupt transfer.
3820
3821 Returns:
3822 EFI_SUCCESS
3823 The synchronous interrupt transfer was completed successfully.
3824 EFI_OUT_OF_RESOURCES
3825 The synchronous interrupt transfer could not be submitted due
3826 to lack of resource.
3827 EFI_INVALID_PARAMETER
3828 Some parameters are invalid.
3829 EFI_TIMEOUT
3830 The synchronous interrupt transfer failed due to timeout.
3831 EFI_DEVICE_ERROR
3832 The synchronous interrupt transfer failed due to host controller
3833 or device error. Caller should check TranferResult for detailed
3834 error information.
3835 --*/
3836 {
3837 USB_HC_DEV *HcDev;
3838 BOOLEAN IsSlowDevice;
3839
3840 if(DeviceSpeed==EFI_USB_SPEED_HIGH)
3841 return EFI_INVALID_PARAMETER;
3842
3843 IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DeviceSpeed) ? TRUE : FALSE);
3844 HcDev = USB2_HC_DEV_FROM_THIS (This);
3845
3846 return UHCISyncInterruptTransfer(
3847 &HcDev->UsbHc,
3848 DeviceAddress,
3849 EndPointAddress,
3850 IsSlowDevice,
3851 (UINT8) MaximumPacketLength,
3852 Data,
3853 DataLength,
3854 DataToggle,
3855 TimeOut,
3856 TransferResult
3857 );
3858 }
3859
3860 EFI_STATUS
3861 EFIAPI
3862 UHCI2IsochronousTransfer (
3863 IN EFI_USB2_HC_PROTOCOL * This,
3864 IN UINT8 DeviceAddress,
3865 IN UINT8 EndPointAddress,
3866 IN UINT8 DeviceSpeed,
3867 IN UINTN MaximumPacketLength,
3868 IN UINT8 DataBuffersNumber,
3869 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
3870 IN UINTN DataLength,
3871 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
3872 OUT UINT32 *TransferResult
3873 )
3874 /*++
3875
3876 Routine Description:
3877
3878 Submits isochronous transfer to a target USB device according to UEFI 2.0 spec.
3879
3880 Arguments:
3881
3882 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3883
3884 DeviceAddress Represents the address of the target device on the USB,
3885 which is assigned during USB enumeration.
3886
3887 EndPointAddress End point address
3888
3889 DeviceSpeed Indicates device speed.
3890
3891 MaximumPacketLength Indicates the maximum packet size that the
3892 default control transfer endpoint is capable of
3893 sending or receiving.
3894
3895 DataBuffersNumber Number of data buffers prepared for the transfer.
3896
3897 Data Array of pointers to the buffers of data that will be
3898 transmitted to USB device or received from USB device.
3899
3900 DataLength Indicates the size, in bytes, of the data buffer
3901 specified by Data.
3902
3903 Translator A pointr to the transaction translator data.
3904
3905 TransferResult A pointer to the detailed result information generated
3906 by this control transfer.
3907 Returns:
3908
3909 EFI_UNSUPPORTED
3910
3911 --*/
3912 {
3913 return EFI_UNSUPPORTED;
3914 }
3915
3916 EFI_STATUS
3917 EFIAPI
3918 UHCI2AsyncIsochronousTransfer (
3919 IN EFI_USB2_HC_PROTOCOL * This,
3920 IN UINT8 DeviceAddress,
3921 IN UINT8 EndPointAddress,
3922 IN UINT8 DeviceSpeed,
3923 IN UINTN MaximumPacketLength,
3924 IN UINT8 DataBuffersNumber,
3925 IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM],
3926 IN UINTN DataLength,
3927 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator,
3928 IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
3929 IN VOID *Context
3930 )
3931 /*++
3932
3933 Routine Description:
3934
3935 Submits Async isochronous transfer to a target USB device according to UEFI 2.0 spec.
3936
3937 Arguments:
3938
3939 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
3940
3941 DeviceAddress Represents the address of the target device on the USB,
3942 which is assigned during USB enumeration.
3943
3944 EndPointAddress End point address
3945
3946 DeviceSpeed Indicates device speed.
3947
3948 MaximumPacketLength Indicates the maximum packet size that the
3949 default control transfer endpoint is capable of
3950 sending or receiving.
3951
3952 DataBuffersNumber Number of data buffers prepared for the transfer.
3953
3954 Data Array of pointers to the buffers of data that will be transmitted
3955 to USB device or received from USB device.
3956
3957 Translator A pointr to the transaction translator data.
3958
3959 IsochronousCallBack When the transfer complete, the call back function will be called
3960
3961 Context Pass to the call back function as parameter
3962
3963 Returns:
3964
3965 EFI_UNSUPPORTED
3966
3967 --*/
3968 {
3969 return EFI_UNSUPPORTED;
3970 }
3971
3972 EFI_STATUS
3973 EFIAPI
3974 UHCI2GetRootHubPortStatus (
3975 IN EFI_USB2_HC_PROTOCOL * This,
3976 IN UINT8 PortNumber,
3977 OUT EFI_USB_PORT_STATUS * PortStatus
3978 )
3979 /*++
3980
3981 Routine Description:
3982 Retrieves the current status of a USB root hub port according to UEFI 2.0 spec.
3983
3984 Arguments:
3985
3986 This A pointer to the EFI_USB2_HC_PROTOCOL.
3987
3988 PortNumber Specifies the root hub port from which the status
3989 is to be retrieved. This value is zero-based. For example,
3990 if a root hub has two ports, then the first port is numbered 0,
3991 and the second port is numbered 1.
3992
3993 PortStatus A pointer to the current port status bits and
3994 port status change bits.
3995
3996 Returns:
3997 EFI_SUCCESS
3998 The status of the USB root hub port specified by PortNumber
3999 was returned in PortStatus.
4000 EFI_INVALID_PARAMETER
4001 PortNumber is invalid.
4002 EFI_DEVICE_ERROR - Can't read register
4003 --*/
4004 {
4005 USB_HC_DEV *HcDev;
4006
4007 HcDev = USB2_HC_DEV_FROM_THIS (This);
4008
4009 return UHCIGetRootHubPortStatus(
4010 &HcDev->UsbHc,
4011 PortNumber,
4012 PortStatus
4013 );
4014 }
4015
4016 EFI_STATUS
4017 EFIAPI
4018 UHCI2SetRootHubPortFeature (
4019 IN EFI_USB2_HC_PROTOCOL * This,
4020 IN UINT8 PortNumber,
4021 IN EFI_USB_PORT_FEATURE PortFeature
4022 )
4023 /*++
4024
4025 Routine Description:
4026 Sets a feature for the specified root hub port according to UEFI 2.0 spec.
4027
4028 Arguments:
4029
4030 This A pointer to the EFI_USB2_HC_PROTOCOL.
4031
4032 PortNumber Specifies the root hub port whose feature
4033 is requested to be set.
4034
4035 PortFeature Indicates the feature selector associated
4036 with the feature set request.
4037
4038 Returns:
4039 EFI_SUCCESS
4040 The feature specified by PortFeature was set for the
4041 USB root hub port specified by PortNumber.
4042 EFI_INVALID_PARAMETER
4043 PortNumber is invalid or PortFeature is invalid.
4044 EFI_DEVICE_ERROR
4045 Can't read register
4046 --*/
4047 {
4048 USB_HC_DEV *HcDev;
4049
4050 HcDev = USB2_HC_DEV_FROM_THIS (This);
4051 return UHCISetRootHubPortFeature(
4052 &HcDev->UsbHc,
4053 PortNumber,
4054 PortFeature
4055 );
4056 }
4057
4058 EFI_STATUS
4059 EFIAPI
4060 UHCI2ClearRootHubPortFeature (
4061 IN EFI_USB2_HC_PROTOCOL * This,
4062 IN UINT8 PortNumber,
4063 IN EFI_USB_PORT_FEATURE PortFeature
4064 )
4065 /*++
4066
4067 Routine Description:
4068 Clears a feature for the specified root hub port according to Uefi 2.0 spec.
4069
4070 Arguments:
4071
4072 This A pointer to the EFI_USB2_HC_PROTOCOL instance.
4073
4074 PortNumber Specifies the root hub port whose feature
4075 is requested to be cleared.
4076
4077 PortFeature Indicates the feature selector associated with the
4078 feature clear request.
4079
4080 Returns:
4081 EFI_SUCCESS
4082 The feature specified by PortFeature was cleared for the
4083 USB root hub port specified by PortNumber.
4084 EFI_INVALID_PARAMETER
4085 PortNumber is invalid or PortFeature is invalid.
4086 EFI_DEVICE_ERROR
4087 Can't read register
4088 --*/
4089 {
4090 USB_HC_DEV *HcDev;
4091
4092 HcDev = USB2_HC_DEV_FROM_THIS (This);
4093 return UHCIClearRootHubPortFeature(
4094 &HcDev->UsbHc,
4095 PortNumber,
4096 PortFeature
4097 );
4098 }
4099
4100 VOID
4101 EFIAPI
4102 MonitorInterruptTrans (
4103 IN EFI_EVENT Event,
4104 IN VOID *Context
4105 )
4106 /*++
4107 Routine Description:
4108 Interrupt transfer periodic check handler
4109 Arguments:
4110 Event - Interrupt event
4111 Contex - Pointer to USB_HC_DEV
4112 Returns:
4113 None
4114 --*/
4115 {
4116
4117 USB_HC_DEV *HcDev;
4118 INTERRUPT_LIST *PtrList;
4119 LIST_ENTRY *Link;
4120 UINT32 Result;
4121 VOID *DataBuffer;
4122 UINTN DataLen;
4123 UINTN ActualLen;
4124 UINTN ErrTDPos;
4125 LIST_ENTRY *NextLink;
4126
4127 HcDev = (USB_HC_DEV *) Context;
4128
4129 //
4130 // interrupt transfer list is empty, means that no interrupt transfer
4131 // is submitted by far.
4132 //
4133 if (IsListEmpty (&(HcDev->InterruptListHead))) {
4134 return ;
4135 }
4136
4137 NextLink = HcDev->InterruptListHead.ForwardLink;
4138 do {
4139
4140 Link = NextLink;
4141 NextLink = Link->ForwardLink;
4142
4143 PtrList = INTERRUPT_LIST_FROM_LINK (Link);
4144
4145 //
4146 // get TD execution results.
4147 // ErrTDPos is zero-based value indicating the first error TD's position
4148 // in the TDs' list.
4149 // This value is only valid when Result not equal NOERROR.
4150 //
4151 ExecuteAsyncINTTDs (
4152 HcDev,
4153 PtrList,
4154 &Result,
4155 &ErrTDPos,
4156 &ActualLen
4157 );
4158
4159 //
4160 // interrupt transfer has not been executed yet.
4161 //
4162 if (((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK) ||
4163 ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {
4164 continue;
4165 }
4166 //
4167 // get actual data length transferred data and its data length.
4168 //
4169 DataLen = ActualLen;
4170 DataBuffer = AllocatePool (DataLen);
4171 if (DataBuffer == NULL) {
4172 return ;
4173 }
4174
4175 CopyMem (
4176 DataBuffer,
4177 PtrList->PtrFirstTD->pTDBuffer,
4178 DataLen
4179 );
4180
4181 //
4182 // only if interrupt endpoint responds
4183 // and the interrupt transfer stops because of completion
4184 // or error, then we will call callback function.
4185 //
4186 if (Result == EFI_USB_NOERROR) {
4187 //
4188 // add for real platform debug
4189 //
4190 if (PtrList->InterruptCallBack != NULL) {
4191 (PtrList->InterruptCallBack) (
4192 DataBuffer,
4193 DataLen,
4194 PtrList->InterruptContext,
4195 Result
4196 );
4197 }
4198
4199 if (DataBuffer) {
4200 gBS->FreePool (DataBuffer);
4201 }
4202
4203 //
4204 // update should done after data buffer got.
4205 //
4206 UpdateAsyncINTQHTDs (PtrList, Result, (UINT32) ErrTDPos);
4207
4208 } else {
4209
4210 DEBUG ((EFI_D_ERROR, "interrupt transfer error code is %x\n", Result));
4211
4212 if (DataBuffer) {
4213 gBS->FreePool (DataBuffer);
4214 }
4215 //
4216 // leave error recovery to its related device driver.
4217 // A common case of the error recovery is to re-submit the interrupt
4218 // transfer.
4219 // When an interrupt transfer is re-submitted, its position in the linked
4220 // list is changed. It is inserted to the head of the linked list, while
4221 // this function scans the whole list from head to tail. Thus, the
4222 // re-submitted interrupt transfer's callback function will not be called
4223 // again in this round.
4224 //
4225 if (PtrList->InterruptCallBack != NULL) {
4226 (PtrList->InterruptCallBack) (
4227 NULL,
4228 0,
4229 PtrList->InterruptContext,
4230 Result
4231 );
4232 }
4233 }
4234 } while (NextLink != &(HcDev->InterruptListHead));
4235
4236 }