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 Antmicro.Renode.Core;
9 using Antmicro.Renode.Core.Structure;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 using Antmicro.Renode.Exceptions;
13 using Antmicro.Renode.Peripherals.Miscellaneous;
14 
15 namespace Antmicro.Renode.Peripherals.Input
16 {
17     [AllowedTranslations(AllowedTranslation.ByteToDoubleWord)]
18     public class PL050 : NullRegistrationPointPeripheralContainer<IPS2Peripheral>, IPS2Controller, IDoubleWordPeripheral, IKnownSize
19     {
PL050(IMachine machine, int size = 0x1000)20         public PL050(IMachine machine, int size = 0x1000) : base(machine)
21         {
22             this.size = size;
23             idHelper = new PrimeCellIDHelper(size, new byte[] { 0x50, 0x10, 0x04, 0x00, 0x0D, 0xF0, 0x05, 0xB1 }, this);
24             IRQ = new GPIO();
25             Reset();
26         }
27 
28         public long Size
29         {
30             get
31             {
32                 return size;
33             }
34         }
35 
Notify()36         public void Notify()
37         {
38             IRQ.Set();
39         }
40 
Register(IPS2Peripheral peripheral, NullRegistrationPoint registrationPoint)41         public override void Register(IPS2Peripheral peripheral, NullRegistrationPoint registrationPoint)
42         {
43             base.Register(peripheral, registrationPoint);
44             peripheral.Controller = this;
45         }
46 
Unregister(IPS2Peripheral peripheral)47         public override void Unregister(IPS2Peripheral peripheral)
48         {
49             base.Unregister(peripheral);
50             peripheral.Controller = null;
51         }
52 
53         public GPIO IRQ { get; private set; }
54 
ReadDoubleWord(long offset)55         public uint ReadDoubleWord(long offset)
56         {
57             switch((Registers)offset)
58             {
59             case Registers.Control:
60                 return controlRegister;
61             case Registers.Status:
62                 return HandleStatusRegister();
63             case Registers.Data:
64                 IRQ.Unset();
65                 if(RegisteredPeripheral != null)
66                 {
67                     dataRegister = RegisteredPeripheral.Read();
68                 }
69                 return dataRegister;
70             case Registers.ClockDivisor:
71                 return clkDivRegister;
72             case Registers.InterruptIdentification:
73                 return IRQ.IsSet ? 1u : 0u;
74             default:
75                 return idHelper.Read(offset);
76             }
77         }
78 
Reset()79         public override void Reset()
80         {
81             dataRegister = 0;
82             controlRegister = 0;
83             clkDivRegister = 0;
84             IRQ.Unset();
85         }
86 
WriteDoubleWord(long offset, uint value)87         public void WriteDoubleWord(long offset, uint value)
88         {
89             switch((Registers)offset)
90             {
91             case Registers.Control:
92                 controlRegister = value;
93                 break;
94             case Registers.Data:
95                 if(RegisteredPeripheral != null)
96                 {
97                     RegisteredPeripheral.Write((byte)value);
98                 }
99                 break;
100             case Registers.ClockDivisor:
101                 clkDivRegister = value;
102                 break;
103             default:
104                 this.LogUnhandledWrite(offset, value);
105                 break;
106             }
107         }
108 
HandleStatusRegister()109         private uint HandleStatusRegister()
110         {
111             var value = (uint)States.TransmitEmpty;
112             // calculates parity, according to http://www-graphics.stanford.edu/~seander/bithacks.html#ParityWith64Bits
113             if(((((dataRegister * 0x0101010101010101UL) & 0x8040201008040201UL) % 0x1FF) & 1) == 1)
114             {
115                 value |= (uint)States.Parity;
116             }
117             if(IRQ.IsSet)
118             {
119                 value |= (uint)States.ReceiveFull;
120             }
121             return value;
122         }
123 
124         private readonly PrimeCellIDHelper idHelper;
125         private readonly int size;
126         private uint controlRegister;
127         private uint dataRegister;
128         private uint clkDivRegister;
129 
130         private enum Registers
131         {
132             Control = 0,
133             Status = 4,
134             Data = 8,
135             ClockDivisor = 12,
136             InterruptIdentification = 16
137         }
138 
139         private enum States : uint
140         {
141             Parity = 1 << 2,
142             ReceiveFull = 1 << 4,
143             TransmitEmpty = 1 << 6
144         }
145     }
146 }
147 
148