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