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