1 /** @file
2 The OHCI register operation routines.
3 
4 Copyright (c) 2013-2015 Intel Corporation.
5 
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 
17 #include "Ohci.h"
18 
19 /**
20 
21   Get OHCI operational reg value
22 
23   @param  PciIo                 PciIo protocol instance
24   @param  Offset                Offset of the operational reg
25 
26   @retval                       Value of the register
27 
28 **/
29 UINT32
OhciGetOperationalReg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Offset)30 OhciGetOperationalReg (
31   IN EFI_PCI_IO_PROTOCOL  *PciIo,
32   IN UINT32               Offset
33   )
34 {
35   UINT32                  Value;
36 
37   PciIo->Mem.Read(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, &Value);
38 
39   return Value;
40 }
41 /**
42 
43   Set OHCI operational reg value
44 
45   @param  PciIo                  PCI Bus Io protocol instance
46   @param  Offset                 Offset of the operational reg
47   @param  Value                  Value to set
48 
49   @retval EFI_SUCCESS            Value set to the reg
50 
51 **/
52 
53 
54 EFI_STATUS
OhciSetOperationalReg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Offset,IN VOID * Value)55 OhciSetOperationalReg (
56   IN EFI_PCI_IO_PROTOCOL  *PciIo,
57   IN UINT32               Offset,
58   IN VOID                 *Value
59   )
60 {
61   EFI_STATUS Status;
62 
63   Status = PciIo->Mem.Write(PciIo, EfiPciIoWidthUint32, OHC_BAR_INDEX, Offset, 1, Value);
64 
65   return Status;
66 }
67 /**
68 
69   Get HcRevision reg value
70 
71   @param  PciIo                 PCI Bus Io protocol instance
72 
73   @retval                       Value of the register
74 
75 **/
76 
77 
78 UINT32
OhciGetHcRevision(IN EFI_PCI_IO_PROTOCOL * PciIo)79 OhciGetHcRevision (
80   IN EFI_PCI_IO_PROTOCOL  *PciIo
81   )
82 {
83   return OhciGetOperationalReg (PciIo, HC_REVISION);
84 }
85 /**
86 
87   Set HcReset reg value
88 
89   @param  Ohc                   UHC private data
90   @param  Field                 Field to set
91   @param  Value                 Value to set
92 
93   @retval EFI_SUCCESS           Value set
94 
95 **/
96 
97 EFI_STATUS
OhciSetHcReset(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Field,IN UINT32 Value)98 OhciSetHcReset (
99   IN USB_OHCI_HC_DEV            *Ohc,
100   IN UINT32                     Field,
101   IN UINT32                     Value
102   )
103 {
104   HcRESET                       Reset;
105 
106   *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);
107 
108   if (Field & RESET_SYSTEM_BUS) {
109     Reset.FSBIR = Value;
110   }
111 
112   if (Field & RESET_HOST_CONTROLLER) {
113     Reset.FHR = Value;
114   }
115 
116   if (Field & RESET_CLOCK_GENERATION) {
117     Reset.CGR = Value;
118   }
119 
120   if (Field & RESET_SSE_GLOBAL) {
121     Reset.SSE = Value;
122   }
123 
124   if (Field & RESET_PSPL) {
125     Reset.PSPL = Value;
126   }
127 
128   if (Field & RESET_PCPL) {
129     Reset.PCPL = Value;
130   }
131 
132   if (Field & RESET_SSEP1) {
133     Reset.SSEP1 = Value;
134   }
135 
136   if (Field & RESET_SSEP2) {
137     Reset.SSEP2 = Value;
138   }
139 
140   if (Field & RESET_SSEP3) {
141     Reset.SSEP3 = Value;
142   }
143 
144   OhciSetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR, &Reset);
145 
146   return EFI_SUCCESS;
147 }
148 
149 /**
150 
151   Get specific field of HcReset reg value
152 
153   @param  Ohc                   UHC private data
154   @param  Field                 Field to get
155 
156   @retval                       Value of the field
157 
158 **/
159 
160 UINT32
OhciGetHcReset(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Field)161 OhciGetHcReset (
162   IN USB_OHCI_HC_DEV      *Ohc,
163   IN UINT32               Field
164   )
165 {
166   HcRESET                 Reset;
167   UINT32                  Value;
168 
169 
170   *(UINT32 *) &Reset = OhciGetOperationalReg (Ohc->PciIo, USBHOST_OFFSET_UHCHR);
171   Value = 0;
172 
173   switch (Field) {
174   case RESET_SYSTEM_BUS:
175     Value = Reset.FSBIR;
176     break;
177 
178   case RESET_HOST_CONTROLLER:
179     Value = Reset.FHR;
180     break;
181 
182   case RESET_CLOCK_GENERATION:
183     Value = Reset.CGR;
184     break;
185 
186   case RESET_SSE_GLOBAL:
187     Value = Reset.SSE;
188     break;
189 
190   case RESET_PSPL:
191     Value = Reset.PSPL;
192     break;
193 
194   case RESET_PCPL:
195     Value = Reset.PCPL;
196     break;
197 
198   case RESET_SSEP1:
199     Value = Reset.SSEP1;
200     break;
201 
202   case RESET_SSEP2:
203     Value = Reset.SSEP2;
204     break;
205 
206   case RESET_SSEP3:
207     Value = Reset.SSEP3;
208     break;
209 
210   default:
211     ASSERT (FALSE);
212   }
213 
214 
215   return Value;
216 }
217 
218 /**
219 
220   Set HcControl reg value
221 
222   @param  Ohc                   UHC private data
223   @param  Field                 Field to set
224   @param  Value                 Value to set
225 
226   @retval  EFI_SUCCESS          Value set
227 
228 **/
229 
230 EFI_STATUS
OhciSetHcControl(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field,IN UINT32 Value)231 OhciSetHcControl (
232   IN USB_OHCI_HC_DEV      *Ohc,
233   IN UINTN                Field,
234   IN UINT32               Value
235   )
236 {
237   EFI_STATUS              Status;
238   HcCONTROL               Control;
239 
240 
241 
242   *(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);
243 
244   if (Field & CONTROL_BULK_RATIO) {
245     Control.ControlBulkRatio = Value;
246   }
247 
248   if (Field & HC_FUNCTIONAL_STATE) {
249     Control.FunctionalState = Value;
250   }
251 
252   if (Field & PERIODIC_ENABLE) {
253     Control.PeriodicEnable = Value;
254   }
255 
256   if (Field & CONTROL_ENABLE) {
257     Control.ControlEnable = Value;
258   }
259 
260   if (Field & ISOCHRONOUS_ENABLE) {
261     Control.IsochronousEnable = Value;
262   }
263 
264   if (Field & BULK_ENABLE) {
265     Control.BulkEnable = Value;
266   }
267 
268   if (Field & INTERRUPT_ROUTING) {
269     Control.InterruptRouting = Value;
270   }
271 
272   Status = OhciSetOperationalReg (Ohc->PciIo, HC_CONTROL, &Control);
273 
274   return Status;
275 }
276 
277 
278 /**
279 
280   Get specific field of HcControl reg value
281 
282   @param  Ohc                   UHC private data
283   @param  Field                 Field to get
284 
285   @retval                       Value of the field
286 
287 **/
288 
289 
290 UINT32
OhciGetHcControl(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)291 OhciGetHcControl (
292   IN USB_OHCI_HC_DEV   *Ohc,
293   IN UINTN             Field
294   )
295 {
296   HcCONTROL     Control;
297 
298   *(UINT32 *) &Control = OhciGetOperationalReg (Ohc->PciIo, HC_CONTROL);
299 
300   switch (Field) {
301   case CONTROL_BULK_RATIO:
302     return Control.ControlBulkRatio;
303     break;
304   case PERIODIC_ENABLE:
305     return Control.PeriodicEnable;
306     break;
307   case CONTROL_ENABLE:
308     return Control.ControlEnable;
309     break;
310   case BULK_ENABLE:
311     return Control.BulkEnable;
312     break;
313   case ISOCHRONOUS_ENABLE:
314     return Control.IsochronousEnable;
315     break;
316   case HC_FUNCTIONAL_STATE:
317     return Control.FunctionalState;
318     break;
319   case INTERRUPT_ROUTING:
320     return Control.InterruptRouting;
321     break;
322   default:
323     ASSERT (FALSE);
324   }
325 
326   return 0;
327 }
328 
329 /**
330 
331   Set HcCommand reg value
332 
333   @param  Ohc                   UHC private data
334   @param  Field                 Field to set
335   @param  Value                 Value to set
336 
337   @retval EFI_SUCCESS           Value set
338 
339 **/
340 
341 EFI_STATUS
OhciSetHcCommandStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field,IN UINT32 Value)342 OhciSetHcCommandStatus (
343   IN USB_OHCI_HC_DEV      *Ohc,
344   IN UINTN                Field,
345   IN UINT32               Value
346   )
347 {
348   EFI_STATUS              Status;
349   HcCOMMAND_STATUS        CommandStatus;
350 
351   ZeroMem (&CommandStatus, sizeof (HcCOMMAND_STATUS));
352 
353   if(Field & HC_RESET){
354     CommandStatus.HcReset = Value;
355   }
356 
357   if(Field & CONTROL_LIST_FILLED){
358     CommandStatus.ControlListFilled = Value;
359   }
360 
361   if(Field & BULK_LIST_FILLED){
362     CommandStatus.BulkListFilled = Value;
363   }
364 
365   if(Field & CHANGE_OWNER_REQUEST){
366     CommandStatus.ChangeOwnerRequest = Value;
367   }
368 
369   if(Field & SCHEDULE_OVERRUN_COUNT){
370     CommandStatus.ScheduleOverrunCount = Value;
371   }
372 
373   Status = OhciSetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS, &CommandStatus);
374 
375   return Status;
376 }
377 
378 /**
379 
380   Get specific field of HcCommand reg value
381 
382   @param  Ohc                   UHC private data
383   @param  Field                 Field to get
384 
385   @retval                       Value of the field
386 
387 **/
388 
389 UINT32
OhciGetHcCommandStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)390 OhciGetHcCommandStatus (
391   IN USB_OHCI_HC_DEV      *Ohc,
392   IN UINTN                Field
393   )
394 {
395   HcCOMMAND_STATUS        CommandStatus;
396 
397   *(UINT32 *) &CommandStatus = OhciGetOperationalReg (Ohc->PciIo, HC_COMMAND_STATUS);
398 
399   switch (Field){
400   case HC_RESET:
401     return CommandStatus.HcReset;
402     break;
403   case CONTROL_LIST_FILLED:
404     return CommandStatus.ControlListFilled;
405     break;
406   case BULK_LIST_FILLED:
407     return CommandStatus.BulkListFilled;
408     break;
409   case CHANGE_OWNER_REQUEST:
410     return CommandStatus.ChangeOwnerRequest;
411     break;
412   case SCHEDULE_OVERRUN_COUNT:
413     return CommandStatus.ScheduleOverrunCount;
414     break;
415   default:
416     ASSERT (FALSE);
417   }
418 
419   return 0;
420 }
421 
422 /**
423 
424   Clear specific fields of Interrupt Status
425 
426   @param  Ohc                   UHC private data
427   @param  Field                 Field to clear
428 
429   @retval EFI_SUCCESS           Fields cleared
430 
431 **/
432 
433 EFI_STATUS
OhciClearInterruptStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)434 OhciClearInterruptStatus (
435   IN USB_OHCI_HC_DEV      *Ohc,
436   IN UINTN                Field
437   )
438 {
439   EFI_STATUS              Status;
440   HcINTERRUPT_STATUS      InterruptStatus;
441 
442   ZeroMem (&InterruptStatus, sizeof (HcINTERRUPT_STATUS));
443 
444   if(Field & SCHEDULE_OVERRUN){
445     InterruptStatus.SchedulingOverrun = 1;
446   }
447 
448   if(Field & WRITEBACK_DONE_HEAD){
449     InterruptStatus.WriteBackDone = 1;
450   }
451   if(Field & START_OF_FRAME){
452     InterruptStatus.Sof = 1;
453   }
454 
455   if(Field & RESUME_DETECT){
456     InterruptStatus.ResumeDetected = 1;
457   }
458 
459   if(Field & UNRECOVERABLE_ERROR){
460     InterruptStatus.UnrecoverableError = 1;
461   }
462 
463   if(Field & FRAME_NUMBER_OVERFLOW){
464     InterruptStatus.FrameNumOverflow = 1;
465   }
466 
467   if(Field & ROOTHUB_STATUS_CHANGE){
468     InterruptStatus.RHStatusChange = 1;
469   }
470 
471   if(Field & OWNERSHIP_CHANGE){
472     InterruptStatus.OwnerChange = 1;
473   }
474 
475   Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS, &InterruptStatus);
476 
477   return Status;
478 }
479 
480 /**
481 
482   Get fields of HcInterrupt reg value
483 
484   @param  Ohc                   UHC private data
485   @param  Field                 Field to get
486 
487   @retval                       Value of the field
488 
489 **/
490 
491 UINT32
OhciGetHcInterruptStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)492 OhciGetHcInterruptStatus (
493   IN USB_OHCI_HC_DEV      *Ohc,
494   IN UINTN                Field
495   )
496 {
497   HcINTERRUPT_STATUS      InterruptStatus;
498 
499   *(UINT32 *) &InterruptStatus = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_STATUS);
500 
501   switch (Field){
502   case SCHEDULE_OVERRUN:
503     return InterruptStatus.SchedulingOverrun;
504     break;
505 
506   case  WRITEBACK_DONE_HEAD:
507     return InterruptStatus.WriteBackDone;
508     break;
509 
510   case START_OF_FRAME:
511     return InterruptStatus.Sof;
512     break;
513 
514   case RESUME_DETECT:
515     return InterruptStatus.ResumeDetected;
516     break;
517 
518   case UNRECOVERABLE_ERROR:
519     return InterruptStatus.UnrecoverableError;
520     break;
521 
522   case FRAME_NUMBER_OVERFLOW:
523     return InterruptStatus.FrameNumOverflow;
524     break;
525 
526   case ROOTHUB_STATUS_CHANGE:
527     return InterruptStatus.RHStatusChange;
528     break;
529 
530   case OWNERSHIP_CHANGE:
531     return InterruptStatus.OwnerChange;
532     break;
533 
534   default:
535     ASSERT (FALSE);
536   }
537 
538   return 0;
539 }
540 
541 /**
542 
543   Set Interrupt Control reg value
544 
545   @param  Ohc                   UHC private data
546   @param  StatEnable            Enable or Disable
547   @param  Field                 Field to set
548   @param  Value                 Value to set
549 
550   @retval EFI_SUCCESS           Value set
551 
552 **/
553 
554 EFI_STATUS
OhciSetInterruptControl(IN USB_OHCI_HC_DEV * Ohc,IN BOOLEAN StatEnable,IN UINTN Field,IN UINT32 Value)555 OhciSetInterruptControl (
556   IN USB_OHCI_HC_DEV      *Ohc,
557   IN BOOLEAN              StatEnable,
558   IN UINTN                Field,
559   IN UINT32               Value
560   )
561 {
562   EFI_STATUS              Status;
563   HcINTERRUPT_CONTROL     InterruptState;
564 
565 
566   ZeroMem (&InterruptState, sizeof (HcINTERRUPT_CONTROL));
567 
568   if(Field & SCHEDULE_OVERRUN) {
569     InterruptState.SchedulingOverrunInt = Value;
570   }
571 
572   if(Field & WRITEBACK_DONE_HEAD) {
573     InterruptState.WriteBackDoneInt = Value;
574   }
575   if(Field & START_OF_FRAME) {
576     InterruptState.SofInt = Value;
577   }
578 
579   if(Field & RESUME_DETECT) {
580     InterruptState.ResumeDetectedInt = Value;
581   }
582 
583   if(Field & UNRECOVERABLE_ERROR) {
584     InterruptState.UnrecoverableErrorInt = Value;
585   }
586 
587   if(Field & FRAME_NUMBER_OVERFLOW) {
588     InterruptState.FrameNumOverflowInt = Value;
589   }
590 
591   if(Field & ROOTHUB_STATUS_CHANGE) {
592     InterruptState.RHStatusChangeInt = Value;
593   }
594 
595   if(Field & OWNERSHIP_CHANGE) {
596     InterruptState.OwnerChangedInt = Value;
597   }
598 
599   if(Field & MASTER_INTERRUPT) {
600     InterruptState.MasterInterruptEnable = Value;
601   }
602 
603   if (StatEnable) {
604     Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE, &InterruptState);
605   } else {
606     Status = OhciSetOperationalReg (Ohc->PciIo, HC_INTERRUPT_DISABLE, &InterruptState);
607   }
608 
609   return Status;
610 }
611 
612 /**
613 
614   Get field of HcInterruptControl reg value
615 
616   @param  Ohc                   UHC private data
617   @param  Field                 Field to get
618 
619   @retval                       Value of the field
620 
621 **/
622 
623 UINT32
OhciGetHcInterruptControl(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)624 OhciGetHcInterruptControl (
625   IN USB_OHCI_HC_DEV      *Ohc,
626   IN UINTN                Field
627   )
628 {
629   HcINTERRUPT_CONTROL     InterruptState;
630 
631   *(UINT32 *) &InterruptState = OhciGetOperationalReg (Ohc->PciIo, HC_INTERRUPT_ENABLE);
632 
633   switch (Field){
634     case SCHEDULE_OVERRUN:
635       return InterruptState.SchedulingOverrunInt;
636       break;
637 
638     case WRITEBACK_DONE_HEAD:
639       return InterruptState.WriteBackDoneInt;
640       break;
641 
642     case START_OF_FRAME:
643       return InterruptState.SofInt;
644       break;
645 
646     case RESUME_DETECT:
647       return InterruptState.ResumeDetectedInt;
648       break;
649 
650     case UNRECOVERABLE_ERROR:
651       return InterruptState.UnrecoverableErrorInt;
652       break;
653 
654     case FRAME_NUMBER_OVERFLOW:
655       return InterruptState.FrameNumOverflowInt;
656       break;
657 
658     case ROOTHUB_STATUS_CHANGE:
659       return InterruptState.RHStatusChangeInt;
660       break;
661 
662     case OWNERSHIP_CHANGE:
663       return InterruptState.OwnerChangedInt;
664       break;
665 
666     case MASTER_INTERRUPT:
667       return InterruptState.MasterInterruptEnable;
668       break;
669 
670     default:
671       ASSERT (FALSE);
672   }
673 
674   return 0;
675 }
676 
677 /**
678 
679   Set memory pointer of specific type
680 
681   @param  Ohc                   UHC private data
682   @param  PointerType           Type of the pointer to set
683   @param  Value                 Value to set
684 
685   @retval EFI_SUCCESS           Memory pointer set
686 
687 **/
688 
689 EFI_STATUS
OhciSetMemoryPointer(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 PointerType,IN VOID * Value)690 OhciSetMemoryPointer(
691   IN USB_OHCI_HC_DEV      *Ohc,
692   IN UINT32               PointerType,
693   IN VOID                 *Value
694   )
695 {
696   EFI_STATUS              Status;
697   UINT32                  Verify;
698 
699   Status = OhciSetOperationalReg (Ohc->PciIo, PointerType, &Value);
700 
701   if (EFI_ERROR (Status)) {
702     return Status;
703   }
704 
705   Verify = OhciGetOperationalReg (Ohc->PciIo, PointerType);
706 
707   while (Verify != (UINT32)(UINTN) Value) {
708     gBS->Stall(1000);
709     Verify = OhciGetOperationalReg (Ohc->PciIo, PointerType);
710   };
711 
712 
713   return Status;
714 }
715 
716 /**
717 
718   Get memory pointer of specific type
719 
720   @param  Ohc                   UHC private data
721   @param  PointerType           Type of pointer
722 
723   @retval                       Memory pointer of the specific type
724 
725 **/
726 
727 VOID *
OhciGetMemoryPointer(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 PointerType)728 OhciGetMemoryPointer (
729   IN USB_OHCI_HC_DEV      *Ohc,
730   IN UINT32               PointerType
731   )
732 {
733 
734   return (VOID *)(UINTN) OhciGetOperationalReg (Ohc->PciIo, PointerType);
735 }
736 
737 
738 /**
739 
740   Set Frame Interval value
741 
742   @param  Ohc                   UHC private data
743   @param  Field                 Field to set
744   @param  Value                 Value to set
745 
746   @retval  EFI_SUCCESS          Value set
747 
748 **/
749 
750 EFI_STATUS
OhciSetFrameInterval(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field,IN UINT32 Value)751 OhciSetFrameInterval (
752   IN USB_OHCI_HC_DEV      *Ohc,
753   IN UINTN                Field,
754   IN UINT32               Value
755   )
756 {
757   EFI_STATUS              Status;
758   HcFRM_INTERVAL          FrameInterval;
759 
760 
761   *(UINT32 *) &FrameInterval = OhciGetOperationalReg(Ohc->PciIo, HC_FRM_INTERVAL);
762 
763   if (Field & FRAME_INTERVAL) {
764     FrameInterval.FrmIntervalToggle = !FrameInterval.FrmIntervalToggle;
765     FrameInterval.FrameInterval = Value;
766   }
767 
768   if (Field & FS_LARGEST_DATA_PACKET) {
769     FrameInterval.FSMaxDataPacket = Value;
770   }
771 
772   if (Field & FRMINT_TOGGLE) {
773     FrameInterval.FrmIntervalToggle = Value;
774   }
775 
776   Status = OhciSetOperationalReg (
777              Ohc->PciIo,
778              HC_FRM_INTERVAL,
779              &FrameInterval
780              );
781 
782   return Status;
783 }
784 
785 
786 /**
787 
788   Get field of frame interval reg value
789 
790   @param  Ohc                   UHC private data
791   @param  Field                 Field to get
792 
793   @retval                       Value of the field
794 
795 **/
796 
797 UINT32
OhciGetFrameInterval(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)798 OhciGetFrameInterval (
799   IN USB_OHCI_HC_DEV      *Ohc,
800   IN UINTN                Field
801   )
802 {
803   HcFRM_INTERVAL          FrameInterval;
804 
805   *(UINT32 *) &FrameInterval = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_INTERVAL);
806 
807   switch (Field){
808     case FRAME_INTERVAL:
809       return FrameInterval.FrameInterval;
810       break;
811 
812     case FS_LARGEST_DATA_PACKET:
813       return FrameInterval.FSMaxDataPacket;
814       break;
815 
816     case FRMINT_TOGGLE:
817       return FrameInterval.FrmIntervalToggle;
818       break;
819 
820     default:
821       ASSERT (FALSE);
822   }
823 
824   return 0;
825 }
826 
827 /**
828 
829   Set Frame Remaining reg value
830 
831   @param  Ohc                   UHC private data
832   @param  Value                 Value to set
833 
834   @retval  EFI_SUCCESS          Value set
835 
836 **/
837 
838 EFI_STATUS
OhciSetFrameRemaining(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Value)839 OhciSetFrameRemaining (
840   IN USB_OHCI_HC_DEV      *Ohc,
841   IN UINT32               Value
842   )
843 {
844   EFI_STATUS              Status;
845   HcFRAME_REMAINING       FrameRemaining;
846 
847 
848   *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);
849 
850   FrameRemaining.FrameRemaining = Value;
851   FrameRemaining.FrameRemainingToggle = !FrameRemaining.FrameRemainingToggle;
852 
853   Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING, &FrameRemaining);
854 
855   return Status;
856 }
857 /**
858 
859   Get value of frame remaining reg
860 
861   @param  Ohc                   UHC private data
862   @param  Field                 Field to get
863 
864   @retval                       Value of frame remaining reg
865 
866 **/
867 UINT32
OhciGetFrameRemaining(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)868 OhciGetFrameRemaining (
869   IN USB_OHCI_HC_DEV      *Ohc,
870   IN UINTN                Field
871   )
872 
873 {
874   HcFRAME_REMAINING       FrameRemaining;
875 
876 
877   *(UINT32 *) &FrameRemaining = OhciGetOperationalReg (Ohc->PciIo, HC_FRM_REMAINING);
878 
879   switch (Field){
880     case FRAME_REMAINING:
881       return FrameRemaining.FrameRemaining;
882       break;
883 
884     case FRAME_REMAIN_TOGGLE:
885       return FrameRemaining.FrameRemainingToggle;
886       break;
887 
888     default:
889       ASSERT (FALSE);
890   }
891 
892   return 0;
893 }
894 
895 /**
896 
897   Set frame number reg value
898 
899   @param  Ohc                   UHC private data
900   @param  Value                 Value to set
901 
902   @retval  EFI_SUCCESS          Value set
903 
904 **/
905 
906 EFI_STATUS
OhciSetFrameNumber(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Value)907 OhciSetFrameNumber(
908   IN USB_OHCI_HC_DEV      *Ohc,
909   IN UINT32               Value
910   )
911 {
912   EFI_STATUS              Status;
913 
914   Status = OhciSetOperationalReg (Ohc->PciIo, HC_FRM_NUMBER, &Value);
915 
916   return Status;
917 }
918 
919 /**
920 
921   Get frame number reg value
922 
923   @param  Ohc                   UHC private data
924 
925   @retval                       Value of frame number reg
926 
927 **/
928 
929 UINT32
OhciGetFrameNumber(IN USB_OHCI_HC_DEV * Ohc)930 OhciGetFrameNumber (
931   IN USB_OHCI_HC_DEV      *Ohc
932   )
933 {
934   return OhciGetOperationalReg(Ohc->PciIo, HC_FRM_NUMBER);
935 }
936 
937 /**
938 
939   Set period start reg value
940 
941   @param  Ohc                   UHC private data
942   @param  Value                 Value to set
943 
944   @retval EFI_SUCCESS           Value set
945 
946 **/
947 
948 EFI_STATUS
OhciSetPeriodicStart(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Value)949 OhciSetPeriodicStart (
950   IN USB_OHCI_HC_DEV      *Ohc,
951   IN UINT32               Value
952   )
953 {
954   EFI_STATUS              Status;
955 
956 
957   Status = OhciSetOperationalReg (Ohc->PciIo, HC_PERIODIC_START, &Value);
958 
959   return Status;
960 }
961 
962 
963 /**
964 
965   Get periodic start reg value
966 
967   @param  Ohc                   UHC private data
968 
969   @param                        Value of periodic start reg
970 
971 **/
972 
973 UINT32
OhciGetPeriodicStart(IN USB_OHCI_HC_DEV * Ohc)974 OhciGetPeriodicStart (
975   IN USB_OHCI_HC_DEV      *Ohc
976   )
977 {
978   return OhciGetOperationalReg(Ohc->PciIo, HC_PERIODIC_START);
979 }
980 
981 
982 /**
983 
984   Set Ls Threshold reg value
985 
986   @param  Ohc                   UHC private data
987   @param  Value                 Value to set
988 
989   @retval  EFI_SUCCESS          Value set
990 
991 **/
992 
993 EFI_STATUS
OhciSetLsThreshold(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Value)994 OhciSetLsThreshold (
995   IN USB_OHCI_HC_DEV      *Ohc,
996   IN UINT32               Value
997   )
998 {
999   EFI_STATUS              Status;
1000 
1001 
1002   Status = OhciSetOperationalReg (Ohc->PciIo, HC_LS_THREASHOLD, &Value);
1003 
1004   return Status;
1005 }
1006 
1007 
1008 /**
1009 
1010   Get Ls Threshold reg value
1011 
1012   @param  Ohc                   UHC private data
1013 
1014   @retval                       Value of Ls Threshold reg
1015 
1016 **/
1017 
1018 UINT32
OhciGetLsThreshold(IN USB_OHCI_HC_DEV * Ohc)1019 OhciGetLsThreshold (
1020   IN USB_OHCI_HC_DEV      *Ohc
1021   )
1022 {
1023   return OhciGetOperationalReg(Ohc->PciIo, HC_LS_THREASHOLD);
1024 }
1025 
1026 /**
1027 
1028   Set Root Hub Descriptor reg value
1029 
1030   @param  Ohc                   UHC private data
1031   @param  Field                 Field to set
1032   @param  Value                 Value to set
1033 
1034   @retval  EFI_SUCCESS          Value set
1035 
1036 **/
1037 EFI_STATUS
OhciSetRootHubDescriptor(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field,IN UINT32 Value)1038 OhciSetRootHubDescriptor (
1039   IN USB_OHCI_HC_DEV      *Ohc,
1040   IN UINTN                Field,
1041   IN UINT32               Value
1042   )
1043 {
1044   EFI_STATUS              Status;
1045   HcRH_DESC_A             DescriptorA;
1046   HcRH_DESC_B             DescriptorB;
1047 
1048 
1049   if (Field & (RH_DEV_REMOVABLE | RH_PORT_PWR_CTRL_MASK)) {
1050     *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);
1051 
1052     if(Field & RH_DEV_REMOVABLE) {
1053       DescriptorB.DeviceRemovable = Value;
1054     }
1055     if(Field & RH_PORT_PWR_CTRL_MASK) {
1056       DescriptorB.PortPowerControlMask = Value;
1057     }
1058 
1059     Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_B, &DescriptorB);
1060 
1061     return Status;
1062   }
1063 
1064   *(UINT32 *)&DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);
1065 
1066   if(Field & RH_NUM_DS_PORTS) {
1067     DescriptorA.NumDownStrmPorts = Value;
1068   }
1069   if(Field & RH_NO_PSWITCH) {
1070     DescriptorA.NoPowerSwitch = Value;
1071   }
1072   if(Field & RH_PSWITCH_MODE) {
1073     DescriptorA.PowerSwitchMode = Value;
1074   }
1075   if(Field & RH_DEVICE_TYPE) {
1076     DescriptorA.DeviceType = Value;
1077   }
1078   if(Field & RH_OC_PROT_MODE) {
1079     DescriptorA.OverCurrentProtMode = Value;
1080   }
1081   if(Field & RH_NOC_PROT) {
1082     DescriptorA.NoOverCurrentProtMode = Value;
1083   }
1084   if(Field & RH_NO_POTPGT) {
1085     DescriptorA.PowerOnToPowerGoodTime = Value;
1086   }
1087 
1088   Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_DESC_A, &DescriptorA);
1089 
1090   return Status;
1091 }
1092 
1093 
1094 /**
1095 
1096   Get Root Hub Descriptor reg value
1097 
1098   @param  Ohc                   UHC private data
1099   @param  Field                 Field to get
1100 
1101   @retval                       Value of the field
1102 
1103 **/
1104 
1105 UINT32
OhciGetRootHubDescriptor(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)1106 OhciGetRootHubDescriptor (
1107   IN USB_OHCI_HC_DEV     *Ohc,
1108   IN UINTN               Field
1109   )
1110 {
1111   HcRH_DESC_A             DescriptorA;
1112   HcRH_DESC_B             DescriptorB;
1113 
1114 
1115   *(UINT32 *) &DescriptorA = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_A);
1116   *(UINT32 *) &DescriptorB = OhciGetOperationalReg (Ohc->PciIo, HC_RH_DESC_B);
1117 
1118   switch (Field){
1119     case RH_DEV_REMOVABLE:
1120       return DescriptorB.DeviceRemovable;
1121       break;
1122 
1123     case RH_PORT_PWR_CTRL_MASK:
1124       return DescriptorB.PortPowerControlMask;
1125       break;
1126 
1127     case RH_NUM_DS_PORTS:
1128       return DescriptorA.NumDownStrmPorts;
1129       break;
1130 
1131     case RH_NO_PSWITCH:
1132       return DescriptorA.NoPowerSwitch;
1133       break;
1134 
1135     case RH_PSWITCH_MODE:
1136       return DescriptorA.PowerSwitchMode;
1137       break;
1138 
1139     case RH_DEVICE_TYPE:
1140       return DescriptorA.DeviceType;
1141       break;
1142 
1143     case RH_OC_PROT_MODE:
1144       return DescriptorA.OverCurrentProtMode;
1145       break;
1146 
1147     case RH_NOC_PROT:
1148       return DescriptorA.NoOverCurrentProtMode;
1149       break;
1150 
1151     case RH_NO_POTPGT:
1152       return DescriptorA.PowerOnToPowerGoodTime;
1153       break;
1154 
1155     default:
1156       ASSERT (FALSE);
1157   }
1158 
1159   return 0;
1160 }
1161 
1162 
1163 /**
1164 
1165   Set Root Hub Status reg value
1166 
1167   @param  Ohc                   UHC private data
1168   @param  Field                 Field to set
1169 
1170   @retval  EFI_SUCCESS          Value set
1171 
1172 **/
1173 
1174 EFI_STATUS
OhciSetRootHubStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)1175 OhciSetRootHubStatus (
1176   IN USB_OHCI_HC_DEV      *Ohc,
1177   IN UINTN                Field
1178   )
1179 {
1180   EFI_STATUS              Status;
1181   HcRH_STATUS             RootHubStatus;
1182 
1183 
1184   ZeroMem (&RootHubStatus, sizeof(HcRH_STATUS));
1185 
1186   if(Field & RH_LOCAL_PSTAT){
1187     RootHubStatus.LocalPowerStat = 1;
1188   }
1189   if(Field & RH_OC_ID){
1190     RootHubStatus.OverCurrentIndicator = 1;
1191   }
1192   if(Field & RH_REMOTE_WK_ENABLE){
1193     RootHubStatus.DevRemoteWakeupEnable = 1;
1194   }
1195   if(Field & RH_LOCAL_PSTAT_CHANGE){
1196     RootHubStatus.LocalPowerStatChange = 1;
1197   }
1198   if(Field & RH_OC_ID_CHANGE){
1199     RootHubStatus.OverCurrentIndicatorChange = 1;
1200   }
1201   if(Field & RH_CLR_RMT_WK_ENABLE){
1202     RootHubStatus.ClearRemoteWakeupEnable = 1;
1203   }
1204 
1205   Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_STATUS, &RootHubStatus);
1206 
1207   return Status;
1208 }
1209 
1210 
1211 /**
1212 
1213   Get Root Hub Status reg value
1214 
1215   @param  Ohc                   UHC private data
1216   @param  Field                 Field to get
1217 
1218   @retval                       Value of the field
1219 
1220 **/
1221 
1222 UINT32
OhciGetRootHubStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINTN Field)1223 OhciGetRootHubStatus (
1224   IN USB_OHCI_HC_DEV      *Ohc,
1225   IN UINTN                Field
1226   )
1227 {
1228   HcRH_STATUS             RootHubStatus;
1229 
1230 
1231   *(UINT32 *) &RootHubStatus = OhciGetOperationalReg (Ohc->PciIo, HC_RH_STATUS);
1232 
1233   switch (Field) {
1234     case RH_LOCAL_PSTAT:
1235       return RootHubStatus.LocalPowerStat;
1236       break;
1237     case RH_OC_ID:
1238       return RootHubStatus.OverCurrentIndicator;
1239       break;
1240     case RH_REMOTE_WK_ENABLE:
1241       return RootHubStatus.DevRemoteWakeupEnable;
1242       break;
1243     case RH_LOCAL_PSTAT_CHANGE:
1244       return RootHubStatus.LocalPowerStatChange;
1245       break;
1246     case RH_OC_ID_CHANGE:
1247       return RootHubStatus.OverCurrentIndicatorChange;
1248       break;
1249     case RH_CLR_RMT_WK_ENABLE:
1250       return RootHubStatus.ClearRemoteWakeupEnable;
1251       break;
1252     default:
1253       ASSERT (FALSE);
1254   }
1255 
1256   return 0;
1257 }
1258 
1259 
1260 /**
1261 
1262   Set Root Hub Port Status reg value
1263 
1264   @param  Ohc                   UHC private data
1265   @param  Index                 Index of the port
1266   @param  Field                 Field to set
1267 
1268   @retval  EFI_SUCCESS          Value set
1269 
1270 **/
1271 
1272 EFI_STATUS
OhciSetRootHubPortStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Index,IN UINTN Field)1273 OhciSetRootHubPortStatus (
1274   IN USB_OHCI_HC_DEV      *Ohc,
1275   IN UINT32               Index,
1276   IN UINTN                Field
1277   )
1278 {
1279   EFI_STATUS              Status;
1280   HcRHPORT_STATUS         PortStatus;
1281 
1282 
1283   ZeroMem (&PortStatus, sizeof(HcRHPORT_STATUS));
1284 
1285   if (Field & RH_CLEAR_PORT_ENABLE) {
1286     PortStatus.CurrentConnectStat = 1;
1287   }
1288   if (Field & RH_SET_PORT_ENABLE) {
1289     PortStatus.EnableStat = 1;
1290   }
1291   if (Field & RH_SET_PORT_SUSPEND) {
1292     PortStatus.SuspendStat = 1;
1293   }
1294   if (Field & RH_CLEAR_SUSPEND_STATUS) {
1295     PortStatus.OCIndicator = 1;
1296   }
1297   if (Field & RH_SET_PORT_RESET) {
1298     PortStatus.ResetStat = 1;
1299   }
1300   if (Field & RH_SET_PORT_POWER) {
1301     PortStatus.PowerStat = 1;
1302   }
1303   if (Field & RH_CLEAR_PORT_POWER) {
1304     PortStatus.LsDeviceAttached = 1;
1305   }
1306   if (Field & RH_CONNECT_STATUS_CHANGE) {
1307     PortStatus.ConnectStatChange = 1;
1308   }
1309   if (Field & RH_PORT_ENABLE_STAT_CHANGE) {
1310     PortStatus.EnableStatChange = 1;
1311   }
1312   if (Field & RH_PORT_SUSPEND_STAT_CHANGE) {
1313     PortStatus.SuspendStatChange = 1;
1314   }
1315   if (Field & RH_OC_INDICATOR_CHANGE) {
1316     PortStatus.OCIndicatorChange = 1;
1317   }
1318   if (Field & RH_PORT_RESET_STAT_CHANGE ) {
1319     PortStatus.ResetStatChange = 1;
1320   }
1321 
1322   Status = OhciSetOperationalReg (Ohc->PciIo, HC_RH_PORT_STATUS + (Index * 4), &PortStatus);
1323 
1324   return Status;
1325 }
1326 
1327 
1328 /**
1329 
1330   Get Root Hub Port Status reg value
1331 
1332   @param  Ohc                   UHC private data
1333   @param  Index                 Index of the port
1334   @param  Field                 Field to get
1335 
1336   @retval                       Value of the field and index
1337 
1338 **/
1339 
1340 UINT32
OhciReadRootHubPortStatus(IN USB_OHCI_HC_DEV * Ohc,IN UINT32 Index,IN UINTN Field)1341 OhciReadRootHubPortStatus (
1342   IN USB_OHCI_HC_DEV      *Ohc,
1343   IN UINT32               Index,
1344   IN UINTN                Field
1345   )
1346 {
1347   HcRHPORT_STATUS         PortStatus;
1348 
1349   *(UINT32 *) &PortStatus = OhciGetOperationalReg (
1350                               Ohc->PciIo,
1351                               HC_RH_PORT_STATUS + (Index * 4)
1352                               );
1353 
1354   switch (Field){
1355   case RH_CURR_CONNECT_STAT:
1356     return PortStatus.CurrentConnectStat;
1357     break;
1358   case RH_PORT_ENABLE_STAT:
1359     return PortStatus.EnableStat;
1360     break;
1361   case RH_PORT_SUSPEND_STAT:
1362     return PortStatus.SuspendStat;
1363     break;
1364   case RH_PORT_OC_INDICATOR:
1365     return PortStatus.OCIndicator;
1366     break;
1367   case RH_PORT_RESET_STAT:
1368     return PortStatus.ResetStat;
1369     break;
1370   case RH_PORT_POWER_STAT:
1371     return PortStatus.PowerStat;
1372     break;
1373   case RH_LSDEVICE_ATTACHED:
1374     return PortStatus.LsDeviceAttached;
1375     break;
1376   case RH_CONNECT_STATUS_CHANGE:
1377     return PortStatus.ConnectStatChange;
1378     break;
1379   case RH_PORT_ENABLE_STAT_CHANGE:
1380     return PortStatus.EnableStatChange;
1381     break;
1382   case RH_PORT_SUSPEND_STAT_CHANGE:
1383     return PortStatus.SuspendStatChange;
1384     break;
1385   case RH_OC_INDICATOR_CHANGE:
1386     return PortStatus.OCIndicatorChange;
1387     break;
1388   case RH_PORT_RESET_STAT_CHANGE:
1389     return PortStatus.ResetStatChange;
1390     break;
1391   default:
1392     ASSERT (FALSE);
1393   }
1394 
1395   return 0;
1396 }
1397