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 Antmicro.Renode.Core; 10 using Antmicro.Renode.Core.Structure; 11 using Antmicro.Renode.Peripherals.SPI; 12 using System.Collections.Generic; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Network; 15 using Antmicro.Renode.Utilities; 16 17 namespace Antmicro.Renode.Peripherals.Network 18 { 19 public class KS8851 : ISPIPeripheral, IMACInterface 20 { KS8851()21 public KS8851() 22 { 23 MAC = EmulationManager.Instance.CurrentEmulation.MACRepository.GenerateUniqueMAC(); 24 currentLength = 4; 25 request = new byte[10240]; 26 response = new byte[10240]; 27 packetQueue = new Queue<EthernetFrame>(); 28 IRQ = new GPIO(); 29 } 30 31 public GPIO IRQ { get; private set; } 32 Reset()33 public void Reset() 34 { 35 interruptsEnabled = true; 36 } 37 38 public MACAddress MAC { get; set; } 39 ReceiveFrame(EthernetFrame frame)40 public void ReceiveFrame(EthernetFrame frame) 41 { 42 if(!frame.DestinationMAC.IsBroadcast && frame.DestinationMAC != MAC) 43 { 44 return; 45 } 46 lock(packetQueue) 47 { 48 packetQueue.Enqueue(frame); 49 SignalInterrupt(); 50 } 51 } 52 Transmit(byte data)53 public byte Transmit(byte data) 54 { 55 if(mode == Mode.SendingPacket) 56 { 57 goto RESULT; 58 } 59 if(counter == 1 && request[0] == 0x80) 60 { 61 mode = Mode.SendingPacket; 62 currentLength = nearestPacketLength; 63 counter = 0; 64 } 65 request[counter] = data; 66 if(counter == 1) 67 { 68 Message(); 69 } 70 RESULT: 71 var result = response[counter]; 72 counter = (counter + 1)%currentLength; 73 if(counter == 0) 74 { 75 Finished(); 76 } 77 return result; 78 } 79 FinishTransmission()80 public void FinishTransmission() 81 { 82 } 83 SignalInterrupt()84 public void SignalInterrupt() 85 { 86 if(!interruptsEnabled) 87 { 88 return; 89 } 90 IRQ.Set(true); 91 IRQ.Set(false); 92 } 93 94 public event Action<EthernetFrame> FrameReady; 95 Align(int value)96 private int Align(int value) 97 { 98 return 4 * (int)Math.Ceiling(1.0 * value / 4); 99 } 100 Message()101 private void Message() 102 { 103 var requestShort = BitConverter.ToUInt16(request, 0); 104 this.NoisyLog("Request 0x{0:X} {1}.", requestShort, mode); 105 var responseShort = (ushort)0; 106 if((byte)requestShort == 0xC0 && mode != Mode.WaitingForPacket) 107 { 108 interruptAfterTransmision = (requestShort & 0x100) != 0; 109 requestShort = 0xC0; 110 } 111 lastPacketType = requestShort; 112 if(mode == Mode.WaitingForPacket) 113 { 114 return; 115 } 116 switch(requestShort) 117 { 118 case 0xF: 119 responseShort = 0x8870; 120 break; 121 case 0xC0: 122 currentLength = 5; 123 break; 124 case 0x4832: 125 if(transmissionEnded) 126 { 127 responseShort = Consts.TransmissionEnded; 128 } 129 lock(packetQueue) 130 { 131 if(packetQueue.Count > 0) 132 { 133 responseShort |= Consts.PacketWaiting; 134 } 135 } 136 break; 137 case 0xE00D: 138 responseShort = 10000; 139 break; 140 case 0x740A: 141 // number of packets? 142 responseShort = 1; 143 currentLength = 3; 144 mode = Mode.Special; 145 break; 146 case 0x5448: 147 currentLength = 3; 148 mode = Mode.Special; 149 break; 150 case 0xF03D: 151 currentLength = 6; 152 mode = Mode.Special; 153 lock(packetQueue) 154 { 155 var frame = packetQueue.Dequeue(); 156 var length = frame.Length + 4; 157 nearestPacketLength = Align(length) + 4; 158 frame.Bytes.CopyTo(response, 8); 159 response[4] = (byte)length; 160 response[5] = (byte)(length >> 8); 161 } 162 break; 163 case 0x5408: 164 PutMACInResponse(0, ref responseShort); 165 break; 166 case 0x5004: 167 PutMACInResponse(1, ref responseShort); 168 break; 169 case 0x4C20: 170 PutMACInResponse(2, ref responseShort); 171 break; 172 case 0x4810: 173 PutMACInResponse(3, ref responseShort); 174 break; 175 case 0x4408: 176 PutMACInResponse(4, ref responseShort); 177 break; 178 case 0x4004: 179 PutMACInResponse(5, ref responseShort); 180 break; 181 case 0x200C: 182 responseShort = 1 << 9; // CCR_EEPROM 183 break; 184 case 0x404E: 185 interruptsEnabled = true; 186 this.DebugLog("Interrupts enabled."); 187 break; 188 } 189 response[2] = (byte)responseShort; 190 response[3] = (byte)(responseShort >> 8); 191 } 192 PutMACInResponse(int number, ref ushort responseShort)193 private void PutMACInResponse(int number, ref ushort responseShort) 194 { 195 currentLength = 3; 196 responseShort = MAC.Bytes[number]; 197 mode = Mode.Special; 198 } 199 Finished()200 private void Finished() 201 { 202 if(mode == Mode.WaitingForPacket) 203 { 204 this.DebugLog("Packet received, LEN {7} {0:x} {1:x} {2:x} {3:x} (...) {4:x} {5:x} {6:x}", request[0], request[1], request[2], request[3], request[currentLength - 5], request[currentLength - 4], request[currentLength - 3], currentLength); 205 var frame = new byte[currentLength]; 206 Array.Copy(request, 0, frame, 0, currentLength); 207 //TODO: CRC handling 208 if(!Misc.TryCreateFrameOrLogWarning(this, frame, out var ethernetFrame, addCrc: false)) 209 { 210 return; 211 } 212 FrameReady?.Invoke(ethernetFrame); 213 mode = Mode.Standard; 214 currentLength = 4; 215 transmissionEnded = true; 216 if(interruptAfterTransmision) 217 { 218 SignalInterrupt(); 219 } 220 } 221 if(mode == Mode.SendingPacket) 222 { 223 mode = Mode.Standard; 224 currentLength = 4; 225 lock(packetQueue) 226 { 227 if(packetQueue.Count > 0) 228 { 229 SignalInterrupt(); 230 } 231 } 232 } 233 if(mode == Mode.Special) 234 { 235 currentLength = 4; 236 mode = Mode.Standard; 237 return; 238 } 239 switch(lastPacketType) 240 { 241 case 0xC0: 242 mode = Mode.WaitingForPacket; 243 var encodedLength = request[3] + (request[4] << 8); 244 this.DebugLog("Encoded length is 0x{0:X}.", encodedLength); 245 currentLength = Align(encodedLength + 1 + 1); 246 transmissionEnded = false; 247 break; 248 case 0xF: 249 lastPacketType = 0; 250 break; 251 } 252 } 253 254 private int counter; 255 private int currentLength = 4; 256 private int nearestPacketLength; 257 private Mode mode; 258 private ushort lastPacketType; 259 private bool interruptAfterTransmision; 260 private bool transmissionEnded; 261 private bool interruptsEnabled; 262 private readonly Queue<EthernetFrame> packetQueue; 263 private readonly byte[] request; 264 private readonly byte[] response; 265 266 private static class Consts 267 { 268 public static ushort TransmissionEnded = 1 << 14; 269 public static ushort PacketWaiting = 1 << 13; 270 } 271 272 private enum Mode 273 { 274 Standard, 275 Special, 276 WaitingForPacket, 277 SendingPacket 278 } 279 } 280 } 281 282