1 //
2 // Copyright (c) 2010-2018 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using System;
9 using System.Linq;
10 using Antmicro.Renode.Utilities;
11 using Antmicro.Renode.Peripherals.Bus;
12 
13 namespace Antmicro.Renode.Peripherals.USBDeprecated
14 {
15     public class PortStatusAndControlRegister
16     {
PortStatusAndControlRegister()17         public PortStatusAndControlRegister()
18         {
19         }
20 
setValue(uint value)21         public PortStatusAndControlRegisterChanges setValue(uint value)
22         {
23             PortStatusAndControlRegisterChanges retVal = new PortStatusAndControlRegisterChanges(); //idicates if interrupt should be rised after this fcn
24             retVal.ConnectChange = false;
25             retVal.EnableChange = false;
26             //uint oldValue = portValue;
27             uint tmpValue = portValue & ~(WriteMask);
28             //if(SystemBus != null) this.Log(LogType.Error,"current PC {0:x}", ((IControllableCPU)SystemBus.GetCPUs().First()).PC);
29             portValue = (value & WriteMask) | tmpValue;
30             if((value & ConnectStatusChange) != 0)
31             {
32                 portValue &= ~(ConnectStatusChange);
33             }
34             if((value & PortEnabledDisabledChange) != 0)
35             {
36                 portValue &= ~(PortEnabledDisabledChange);
37             }
38             if((value & PortPower) != 0 && (powered == false))
39             {
40                 retVal = this.powerUp();
41             }
42             if((value & PortReset) != 0)
43             {
44                 this.resetRise();
45                 // this.resetFall();
46             }
47             if(((value & PortReset) == 0) && reset == true)
48             {
49                 resetFall();
50                 //retVal.ConnectChange = true;
51             }
52             if((value & PortEnabledDisabled) != 0)
53             {
54                 retVal = this.Enable();
55             }
56             if((portValue & PortEnabledDisabled) == 0)
57             {
58                 // if(SystemBus != null)
59                 //   this.Log(LogType.Error,"zerowanie Enable current PC {0:x}", ((IControllableCPU)SystemBus.GetCPUs().First()).PC);
60             }
61             /* Remove reset bit */
62             portValue &= ~(0x1000u);
63             return retVal;
64         }
65 
checkChanges(uint oldPortVal, uint newPortVal)66         private PortStatusAndControlRegisterChanges checkChanges(uint oldPortVal, uint newPortVal)
67         {
68             var change = new PortStatusAndControlRegisterChanges();
69             change.ConnectChange = false;
70             change.EnableChange = false;
71             if((oldPortVal & CurrentConnectStatus) != (newPortVal & CurrentConnectStatus))
72             {
73                 change.ConnectChange = true;
74                 portValue |= ConnectStatusChange;
75             }
76             if((oldPortVal & PortEnabledDisabled) != (newPortVal & PortEnabledDisabled))
77             {
78                 change.EnableChange = true;
79                 portValue |= PortEnabledDisabledChange;
80             }
81             return change;
82         }
83 
Attach()84         public PortStatusAndControlRegisterChanges Attach()
85         {
86             uint oldPortValue = portValue;
87             portValue |= CurrentConnectStatus | PortEnabledDisabled | PortEnabledDisabledChange | ConnectStatusChange;
88             attached = true;
89             return checkChanges(oldPortValue, portValue);
90         }
91 
Attach(IUSBPeripheral portDevice)92         public PortStatusAndControlRegisterChanges Attach(IUSBPeripheral portDevice)
93         {
94             uint oldPortValue = portValue;
95             portValue |= CurrentConnectStatus | PortEnabledDisabled | PortEnabledDisabledChange | ConnectStatusChange;
96             device = portDevice;
97             attached = true;
98             return checkChanges(oldPortValue, portValue);
99         }
100 
Detach()101         public PortStatusAndControlRegisterChanges Detach()
102         {
103             uint oldPortValue = portValue;
104             portValue |= ConnectStatusChange;
105             portValue &= (~CurrentConnectStatus) & (~PortEnabledDisabled);
106             attached = false;
107             return checkChanges(oldPortValue, portValue);
108         }
109 
getValue()110         public uint getValue()
111         {
112             if(attached && device != null)
113                 if(device.GetSpeed() == USBDeviceSpeed.High)
114                     portValue |= HighSpeed;
115             return portValue;
116         }
117 
powerUp()118         public PortStatusAndControlRegisterChanges powerUp()
119         {
120             uint oldPortValue = portValue;
121             //  portValue |= PortEnabledDisabled | CurrentConnectStatus | PortPower; //TODO: Port Power bit should be dependent on PPC
122             //portValue |= PortEnabledDisabled | PortPower;
123             //powered = true;
124             if(attached)
125             {
126                 portValue |= (CurrentConnectStatus); //set connected bit
127                 portValue |= (ConnectStatusChange); //clear connect change bit
128             }
129             return checkChanges(oldPortValue, portValue);
130         }
131 
Enable()132         public PortStatusAndControlRegisterChanges Enable()
133         {
134             uint oldPortValue = portValue;
135             portValue |= PortEnabledDisabled;
136             return checkChanges(oldPortValue, portValue);
137         }
138 
getReset()139         public bool getReset()
140         {
141             return reset;
142         }
143 
resetRise()144         public void resetRise()
145         {
146             reset = true;
147         }
148 
resetFall()149         public void resetFall()
150         {
151             portValue &= ~(PortReset); //clear reset bit
152             //portValue &= ~(PortPower); //clear power bit
153             if(attached)
154             {
155                 portValue |= (CurrentConnectStatus); //set connected bit
156                 portValue &= ~(ConnectStatusChange); //clear connect change bit
157                 portValue |= (PortEnabledDisabled); //set enable bit
158                 portValue &= ~(PortEnabledDisabledChange);
159                 if(device != null)
160                     device.Reset();
161             }
162             reset = false;
163 
164         }
165 
166         private bool reset = false;
167         private bool powered = false;
168         private uint portValue;
169         private bool attached = false;
170         public const uint CurrentConnectStatus = 1 << 0;
171         public const uint ConnectStatusChange = 1 << 1;
172         public const uint PortEnabledDisabled = 1 << 2;
173         public const uint PortEnabledDisabledChange = 1 << 3;
174         public const uint PortReset = 1 << 8;
175         public const uint PortPower = 1 << 12;
176         public const uint HighSpeed = 1 << 27;
177         protected IUSBPeripheral device;
178         //FIXME: correct
179         public const uint WriteMask = 0x007FE1CC;
180     }
181 }
182 
183