1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Linq; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Time; 11 using Antmicro.Renode.Peripherals.Timers; 12 using Antmicro.Renode.Core.Structure; 13 using Antmicro.Renode.Logging; 14 using Antmicro.Renode.Peripherals.Bus; 15 using System.Collections.Generic; 16 using Antmicro.Renode.Network; 17 using Antmicro.Renode.Utilities; 18 using Antmicro.Renode.Core.Structure.Registers; 19 20 namespace Antmicro.Renode.Peripherals.Network 21 { 22 // The register and field names are taken from the UltraScale+ GEM docs, 23 // because it is the most extensive description of this peripheral: 24 // https://www.xilinx.com/html_docs/registers/ug1087/mod___gem.html 25 // For further reference however, here are links to other sources: 26 // https://www.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf 27 // https://www.mouser.com/datasheet/2/268/SAM-E70S70V70V71-Family_DataSheet-DS60001527B-1374834.pdf 28 public class CadenceGEM : NetworkWithPHY, IDoubleWordPeripheral, IMACInterface, IKnownSize 29 { 30 // the default moduleRevision/moduleId are correct for Zynq with GEM p23 CadenceGEM(IMachine machine, ushort moduleRevision = 0x118, ushort moduleId = 0x2)31 public CadenceGEM(IMachine machine, ushort moduleRevision = 0x118, ushort moduleId = 0x2) : base(machine) 32 { 33 ModuleId = moduleId; 34 ModuleRevision = moduleRevision; 35 sysbus = machine.GetSystemBus(this); 36 37 IRQ = new GPIO(); 38 MAC = EmulationManager.Instance.CurrentEmulation.MACRepository.GenerateUniqueMAC(); 39 sync = new object(); 40 41 interruptManager = new InterruptManager<Interrupts>(this); 42 43 nanoTimer = new LimitTimer(machine.ClockSource, NanosPerSecond, this, "PTP nanos", 44 limit: NanosPerSecond, 45 direction: Direction.Ascending, 46 workMode: WorkMode.Periodic, 47 eventEnabled: true); 48 49 nanoTimer.LimitReached += () => secTimer.Value++; 50 51 var registersMap = new Dictionary<long, DoubleWordRegister> 52 { 53 {(long)Registers.NetworkControl, new DoubleWordRegister(this) 54 .WithTag("loopback", 0, 1) 55 .WithTag("loopback_local", 1, 1) 56 .WithFlag(2, out receiveEnabled, name: "enable_receive") 57 .WithFlag(3, name: "enable_transmit", 58 writeCallback: (_, value) => 59 { 60 if(!value) 61 { 62 isTransmissionStarted = false; 63 } 64 if(txDescriptorsQueue != null && !value) 65 { 66 txDescriptorsQueue.GoToBaseAddress(); 67 } 68 }) 69 .WithTag("man_port_en", 4, 1) 70 .WithTag("clear_all_stats_regs", 5, 1) 71 .WithTag("inc_all_stats_regs", 6, 1) 72 .WithTag("stats_write_en", 7, 1) 73 .WithTag("back_pressure", 8, 1) 74 .WithFlag(9, FieldMode.Read | FieldMode.WriteOneToClear, name: "tx_start_pclk", 75 writeCallback: (_, value) => 76 { 77 if(value) 78 { 79 isTransmissionStarted = true; 80 SendFrames(); 81 } 82 }) 83 .WithFlag(10, FieldMode.Read | FieldMode.WriteOneToClear, name: "tx_halt_pclk", 84 writeCallback: (_, value) => 85 { 86 if(value) 87 { 88 isTransmissionStarted = false; 89 } 90 }) 91 .WithTag("tx_pause_frame_req", 11, 1) 92 .WithTag("tx_pause_frame_zero", 12, 1) 93 .WithReservedBits(13, 2) 94 .WithTag("store_rx_ts", 15, 1) 95 .WithTag("pfc_enable", 16, 1) 96 .WithTag("transmit_pfc_priority_based_pause_frame", 17, 1) 97 .WithTag("flush_rx_pkt_pclk", 18, 1) 98 .WithTag("tx_lpi_en", 19, 1) 99 .WithTag("ptp_unicast_ena", 20, 1) 100 .WithTag("alt_sgmii_mode", 21, 1) 101 .WithTag("store_udp_offset", 22, 1) 102 .WithTag("ext_tsu_port_enable", 23, 1) 103 .WithTag("one_step_sync_mode", 24, 1) 104 .WithReservedBits(25, 7) 105 }, 106 107 {(long)Registers.NetworkConfiguration, new DoubleWordRegister(this, 0x80000) 108 .WithTag("speed", 0, 1) 109 .WithTag("full_duplex", 1, 1) 110 .WithTag("discard_non_vlan_frames", 2, 1) 111 .WithTag("jumbo_frames", 3, 1) 112 .WithTag("copy_all_frames", 4, 1) 113 .WithTag("no_broadcast", 5, 1) 114 .WithTag("multicast_hash_enable", 6, 1) 115 .WithTag("unicast_hash_enable", 7, 1) 116 .WithTag("receive_1536_byte_frames", 8, 1) 117 .WithTag("external_address_match_enable", 9, 1) 118 .WithTag("gigabit_mode_enable", 10, 1) 119 .WithTag("pcs_select", 11, 1) 120 .WithTag("retry_test", 12, 1) 121 .WithTag("pause_enable", 13, 1) 122 .WithValueField(14, 2, out receiveBufferOffset, name: "receive_buffer_offset") 123 .WithTag("length_field_error_frame_discard", 16, 1) 124 .WithFlag(17, out removeFrameChecksum, name: "fcs_remove") 125 .WithTag("mdc_clock_division", 18, 3) 126 .WithTag("data_bus_width", 21, 2) 127 .WithTag("disable_copy_of_pause_frames", 23, 1) 128 .WithTag("receive_checksum_offload_enable", 24, 1) 129 .WithTag("en_half_duplex_rx", 25, 1) 130 .WithFlag(26, out ignoreRxFCS, name: "ignore_rx_fcs") 131 .WithTag("sgmii_mode_enable", 27, 1) 132 .WithTag("ipg_stretch_enable", 28, 1) 133 .WithTag("nsp_change", 29, 1) 134 .WithTag("ignore_ipg_rx_er", 30, 1) 135 .WithTag("uni_direction_enable", 31, 1) 136 }, 137 138 {(long)Registers.NetworkStatus, new DoubleWordRegister(this) 139 .WithTag("pcs_link_state", 0, 1) 140 .WithTag("mdio_in", 1, 1) 141 .WithFlag(2, FieldMode.Read, name: "man_done", valueProviderCallback: _ => true) 142 .WithTag("mac_full_duplex", 3, 1) 143 .WithTag("mac_pause_rx_en", 4, 1) 144 .WithTag("mac_pause_tx_en", 5, 1) 145 .WithTag("pfc_negotiate_pclk", 6, 1) 146 .WithTag("lpi_indicate_pclk", 7, 1) 147 .WithReservedBits(8, 24) 148 }, 149 150 {(long)Registers.DmaConfiguration, new DoubleWordRegister(this, 0x00020784) 151 .WithTag("amba_burst_length", 0, 4) 152 .WithReservedBits(5, 1) 153 .WithTag("endian_swap_management", 6, 1) 154 .WithTag("endian_swap_packet", 7, 1) 155 .WithTag("rx_pbuf_size", 8, 2) 156 .WithTag("tx_pbuf_size", 10, 1) 157 .WithFlag(11, out checksumGeneratorEnabled, name: "tx_pbuf_tcp_en") 158 .WithReservedBits(12, 4) 159 .WithTag("rx_buf_size", 16, 8) 160 .WithTag("force_discard_on_err", 24, 1) 161 .WithTag("force_max_amba_burst_rx", 25, 1) 162 .WithTag("force_max_amba_burst_tx", 26, 1) 163 .WithReservedBits(27, 1) 164 .WithFlag(28, out extendedRxBufferDescriptorEnabled, name: "rx_bd_extended_mode_en") 165 .WithFlag(29, out extendedTxBufferDescriptorEnabled, name: "tx_bd_extended_mode_en") 166 .WithEnumField(30, 1, out dmaAddressBusWith, name: "dma_addr_bus_width_1") 167 .WithReservedBits(31, 1) 168 }, 169 170 {(long)Registers.TransmitStatus, new DoubleWordRegister(this) 171 .WithFlag(0, out usedBitRead, FieldMode.Read | FieldMode.WriteOneToClear, name: "used_bit_read") 172 .WithTag("collision_occurred", 1, 1) 173 .WithTag("retry_limit_exceeded", 2, 1) 174 .WithTag("transmit_go", 3, 1) 175 .WithTag("amba_error", 4, 1) 176 .WithFlag(5, out transmitComplete, FieldMode.Read | FieldMode.WriteOneToClear, name: "transmit_complete") 177 .WithTag("transmit_under_run", 6, 1) 178 .WithTag("late_collision_occurred", 7, 1) 179 .WithTag("resp_not_ok", 8, 1) 180 .WithReservedBits(9, 23) 181 }, 182 183 {(long)Registers.ReceiveBufferQueueBaseAddress, new DoubleWordRegister(this) 184 .WithReservedBits(0, 2) 185 .WithValueField(2, 30, name: "dma_rx_q_ptr", 186 valueProviderCallback: _ => 187 { 188 return rxDescriptorsQueue.CurrentDescriptor.LowerDescriptorAddress; 189 }, 190 writeCallback: (oldValue, value) => 191 { 192 if(receiveEnabled.Value) 193 { 194 this.Log(LogLevel.Warning, "Changing value of receive buffer queue base address while reception is enabled is illegal"); 195 return; 196 } 197 rxDescriptorsQueue = new DmaBufferDescriptorsQueue<DmaRxBufferDescriptor>(sysbus, (uint)value << 2, (sb, addr) => new DmaRxBufferDescriptor(sb, addr, dmaAddressBusWith.Value, extendedRxBufferDescriptorEnabled.Value)); 198 }) 199 }, 200 201 {(long)Registers.ReceiveBufferQueueBaseAddressUpper, new DoubleWordRegister(this) 202 .WithValueField(0, 32, name: "upper_rx_q_base_addr", 203 valueProviderCallback: _ => 204 { 205 return rxDescriptorsQueue.CurrentDescriptor.UpperDescriptorAddress; 206 }, 207 writeCallback: (oldValue, value) => 208 { 209 rxDescriptorsQueue.CurrentDescriptor.UpperDescriptorAddress = (uint)value; 210 }) 211 }, 212 213 {(long)Registers.ReceiveBufferDescriptorControl, new DoubleWordRegister(this) 214 .WithReservedBits(0, 4) 215 .WithEnumField(4, 2, out rxBufferDescriptorTimeStampMode, name: "rx_bd_ts_mode") 216 .WithReservedBits(6, 26) 217 }, 218 219 {(long)Registers.TransmitBufferQueueBaseAddress, new DoubleWordRegister(this) 220 .WithReservedBits(0, 2) 221 .WithValueField(2, 30, name: "dma_tx_q_ptr", 222 valueProviderCallback: _ => 223 { 224 return txDescriptorsQueue.CurrentDescriptor.LowerDescriptorAddress; 225 }, 226 writeCallback: (oldValue, value) => 227 { 228 if(isTransmissionStarted) 229 { 230 this.Log(LogLevel.Warning, "Changing value of transmit buffer queue base address while transmission is started is illegal"); 231 return; 232 } 233 txDescriptorsQueue = new DmaBufferDescriptorsQueue<DmaTxBufferDescriptor>(sysbus, (uint)value << 2, (sb, addr) => new DmaTxBufferDescriptor(sb, addr, dmaAddressBusWith.Value, extendedTxBufferDescriptorEnabled.Value)); 234 }) 235 }, 236 237 {(long)Registers.TransmitBufferQueueBaseAddressUpper, new DoubleWordRegister(this) 238 .WithValueField(0, 32, name: "upper_tx_q_base_addr", 239 valueProviderCallback: _ => 240 { 241 return txDescriptorsQueue.CurrentDescriptor.UpperDescriptorAddress; 242 }, 243 writeCallback: (oldValue, value) => 244 { 245 txDescriptorsQueue.CurrentDescriptor.UpperDescriptorAddress = (uint)value; 246 }) 247 }, 248 249 {(long)Registers.TransmitBufferDescriptorControl, new DoubleWordRegister(this) 250 .WithReservedBits(0, 4) 251 .WithEnumField(4, 2, out txBufferDescriptorTimeStampMode, name: "tx_bd_ts_mode") 252 .WithReservedBits(6, 26) 253 }, 254 255 {(long)Registers.ReceiveStatus, new DoubleWordRegister(this) 256 .WithFlag(0, out bufferNotAvailable, FieldMode.Read | FieldMode.WriteOneToClear, name: "buffer_not_available") 257 .WithFlag(1, out frameReceived, FieldMode.Read | FieldMode.WriteOneToClear, name: "frame_received") 258 .WithTag("receive_overrun", 2, 1) 259 .WithTag("resp_not_ok", 3, 1) 260 .WithReservedBits(4, 28) 261 }, 262 263 {(long)Registers.InterruptStatus, interruptManager.GetRegister<DoubleWordRegister>( 264 valueProviderCallback: (interrupt, oldValue) => 265 { 266 var status = interruptManager.IsSet(interrupt) && interruptManager.IsEnabled(interrupt); 267 interruptManager.ClearInterrupt(interrupt); 268 269 return status; 270 }, 271 writeCallback: (interrupt, oldValue, newValue) => 272 { 273 if(newValue) 274 { 275 interruptManager.ClearInterrupt(interrupt); 276 } 277 }) 278 }, 279 280 {(long)Registers.InterruptEnable, interruptManager.GetRegister<DoubleWordRegister>( 281 writeCallback: (interrupt, oldValue, newValue) => 282 { 283 if(newValue) 284 { 285 interruptManager.EnableInterrupt(interrupt); 286 } 287 }) 288 }, 289 290 {(long)Registers.InterruptDisable, interruptManager.GetRegister<DoubleWordRegister>( 291 writeCallback: (interrupt, oldValue, newValue) => 292 { 293 if(newValue) 294 { 295 interruptManager.DisableInterrupt(interrupt); 296 } 297 }) 298 }, 299 300 {(long)Registers.InterruptMaskStatus, interruptManager.GetRegister<DoubleWordRegister>( 301 valueProviderCallback: (interrupt, oldValue) => !interruptManager.IsEnabled(interrupt)) 302 }, 303 304 {(long)Registers.PhyMaintenance, new DoubleWordRegister(this) 305 .WithValueField(0, 31, name: "phy_management", writeCallback: (_, value) => HandlePhyWrite((uint)value), valueProviderCallback: _ => HandlePhyRead()) 306 }, 307 308 {(long)Registers.SpecificAddress1Bottom, new DoubleWordRegister(this) 309 .WithValueField(0, 32, valueProviderCallback: _ => BitConverter.ToUInt32(MAC.Bytes, 0)) 310 }, 311 312 {(long)Registers.SpecificAddress1Top, new DoubleWordRegister(this) 313 .WithValueField(0, 16, valueProviderCallback: _ => BitConverter.ToUInt16(MAC.Bytes, 4)) 314 .WithTag("filter_type", 16, 1) 315 .WithReservedBits(17, 15) 316 }, 317 318 {(long)Registers.ModuleId, new DoubleWordRegister(this) 319 .WithValueField(0, 16, FieldMode.Read, name: "module_revision", valueProviderCallback: _ => ModuleRevision) 320 .WithValueField(16, 12, FieldMode.Read, name: "module_identification_number", valueProviderCallback: _ => ModuleId) 321 .WithTag("fix_number", 28, 4) 322 }, 323 324 {(long)Registers.DesignConfiguration1, new DoubleWordRegister(this) 325 .WithTag("no_pcs", 0, 1) 326 .WithTag("serdes", 1, 1) 327 .WithTag("RDC_50", 2, 1) 328 .WithTag("TDC_50", 3, 1) 329 .WithTag("int_loopback", 4, 1) 330 .WithTag("no_int_loopback", 5, 1) 331 .WithTag("ext_fifo_interface", 6, 1) 332 .WithTag("apb_rev1", 7, 1) 333 .WithTag("apb_rev2", 8, 1) 334 .WithTag("user_io", 9, 1) 335 .WithTag("user_out_width", 10, 5) 336 .WithTag("user_in_width", 15, 5) 337 .WithTag("no_scan_pins", 20, 1) 338 .WithTag("no_stats", 21, 1) 339 .WithTag("no_snapshot", 22, 1) 340 .WithFlag(23, FieldMode.Read, name: "irq_read_clear", valueProviderCallback: _ => false) 341 .WithReservedBits(24, 1) 342 .WithValueField(25, 3, FieldMode.Read, name: "dma_bus_width", valueProviderCallback: _ => 1) // DMA data bus width - 32 bits 343 .WithTag("axi_cache_value", 28, 4) 344 }, 345 346 {(long)Registers.DesignConfiguration2, new DoubleWordRegister(this) 347 .WithTag("jumbo_max_length", 0, 16) 348 .WithTag("hprot_value", 16, 4) 349 .WithFlag(20, FieldMode.Read, name: "rx_pkt_buffer", valueProviderCallback: _ => true) // includes the receiver packet buffer 350 .WithFlag(21, FieldMode.Read, name: "tx_pkt_buffer", valueProviderCallback: _ => true) // includes the transmitter packet buffer 351 .WithTag("rx_pbuf_addr", 22, 4) 352 .WithTag("tx_pbuf_addr", 26, 4) 353 .WithTag("axi", 30, 1) 354 .WithTag("spram", 31, 1) 355 }, 356 357 {(long)Registers.Timer1588SecondsLow, new DoubleWordRegister(this) 358 .WithValueField(0, 32, out secTimer, name: "tsu_timer_sec") 359 }, 360 361 {(long)Registers.Timer1588SecondsHigh, new DoubleWordRegister(this) 362 .WithValueField(0, 16, valueProviderCallback: _ => 0, writeCallback: (_, value) => 363 { 364 if(value != 0) 365 { 366 this.Log(LogLevel.Warning, "Writing a non-zero value to the SecondsHigh register, timer values over 32 bits are not supported."); 367 } 368 }, name: "tsu_timer_msb_sec") 369 .WithReservedBits(16, 16) 370 }, 371 372 {(long)Registers.Timer1588Nanoseconds, new DoubleWordRegister(this) 373 .WithValueField(0, 30, valueProviderCallback: _ => 374 { 375 return (uint)nanoTimer.Value; 376 }, writeCallback: (_, value) => 377 { 378 nanoTimer.Value = value; 379 }, name: "tsu_timer_nsec") 380 .WithReservedBits(30, 2) 381 }, 382 383 {(long)Registers.Timer1588Adjust, new DoubleWordRegister(this) 384 .WithValueField(0, 30, out var timerIncrementDecrement, FieldMode.Write, name: "increment_value") 385 .WithReservedBits(30, 1) 386 .WithFlag(31, out var timerAdjust, FieldMode.Write, name: "add_subtract") 387 .WithWriteCallback((_, __) => 388 { 389 if(timerAdjust.Value) 390 { 391 secTimer.Value -= nanoTimer.Decrement(timerIncrementDecrement.Value); 392 } 393 else 394 { 395 secTimer.Value += nanoTimer.Increment(timerIncrementDecrement.Value); 396 } 397 }) 398 }, 399 400 {(long)Registers.PtpEventFrameTransmittedSecondsHigh, new DoubleWordRegister(this) 401 .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: _ => 0, name: "tsu_ptp_tx_msb_sec") 402 .WithReservedBits(16, 16) 403 }, 404 405 {(long)Registers.PtpEventFrameTransmittedSeconds, new DoubleWordRegister(this) 406 .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => txPacketTimestamp.seconds, name: "tsu_ptp_tx_sec") 407 }, 408 409 {(long)Registers.PtpEventFrameTransmittedNanoseconds, new DoubleWordRegister(this) 410 .WithValueField(0, 30, FieldMode.Read, valueProviderCallback: _ => txPacketTimestamp.nanos, name: "tsu_ptp_tx_nsec") 411 .WithReservedBits(30, 2) 412 }, 413 414 {(long)Registers.PtpEventFrameReceivedSecondsHigh, new DoubleWordRegister(this) 415 .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: _ => 0, name: "tsu_ptp_rx_msb_sec") 416 .WithReservedBits(16, 16) 417 }, 418 419 {(long)Registers.PtpEventFrameReceivedSeconds, new DoubleWordRegister(this) 420 .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => rxPacketTimestamp.seconds, name: "tsu_ptp_rx_sec") 421 }, 422 423 {(long)Registers.PtpEventFrameReceivedNanoseconds, new DoubleWordRegister(this) 424 .WithValueField(0, 30, FieldMode.Read, valueProviderCallback: _ => rxPacketTimestamp.nanos, name: "tsu_ptp_rx_nsec") 425 .WithReservedBits(30, 2) 426 }, 427 428 {(long)Registers.PtpPeerEventFrameTransmittedSecondsHigh, new DoubleWordRegister(this) 429 .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: _ => 0, name: "tsu_peer_tx_msb_sec") 430 .WithReservedBits(16, 16) 431 }, 432 433 {(long)Registers.PtpPeerEventFrameTransmittedSeconds, new DoubleWordRegister(this) 434 .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => txPacketTimestamp.seconds, name: "tsu_peer_tx_sec") 435 }, 436 437 {(long)Registers.PtpPeerEventFrameTransmittedNanoseconds, new DoubleWordRegister(this) 438 .WithValueField(0, 30, FieldMode.Read, valueProviderCallback: _ => txPacketTimestamp.nanos, name: "tsu_peer_tx_nsec") 439 .WithReservedBits(30, 2) 440 }, 441 442 {(long)Registers.PtpPeerEventFrameReceivedSecondsHigh, new DoubleWordRegister(this) 443 .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: _ => 0, name: "tsu_peer_rx_msb_sec") 444 .WithReservedBits(16, 16) 445 }, 446 447 {(long)Registers.PtpPeerEventFrameReceivedSeconds, new DoubleWordRegister(this) 448 .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => rxPacketTimestamp.seconds, name: "tsu_peer_rx_sec") 449 }, 450 451 {(long)Registers.PtpPeerEventFrameReceivedNanoseconds, new DoubleWordRegister(this) 452 .WithValueField(0, 30, FieldMode.Read, valueProviderCallback: _ => rxPacketTimestamp.nanos, name: "tsu_peer_rx_nsec") 453 .WithReservedBits(30, 2) 454 } 455 }; 456 457 registers = new DoubleWordRegisterCollection(this, registersMap); 458 Reset(); 459 } 460 Reset()461 public override void Reset() 462 { 463 registers.Reset(); 464 interruptManager.Reset(); 465 txDescriptorsQueue = null; 466 rxDescriptorsQueue = null; 467 phyDataRead = 0; 468 isTransmissionStarted = false; 469 nanoTimer.Reset(); 470 nanoTimer.Enabled = true; 471 } 472 ReadDoubleWord(long offset)473 public uint ReadDoubleWord(long offset) 474 { 475 lock(sync) 476 { 477 return registers.Read(offset); 478 } 479 } 480 WriteDoubleWord(long offset, uint value)481 public void WriteDoubleWord(long offset, uint value) 482 { 483 lock(sync) 484 { 485 registers.Write(offset, value); 486 } 487 } 488 ReceiveFrame(EthernetFrame frame)489 public void ReceiveFrame(EthernetFrame frame) 490 { 491 lock(sync) 492 { 493 this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length); 494 if(!receiveEnabled.Value) 495 { 496 this.Log(LogLevel.Info, "Receiver not enabled, dropping frame"); 497 return; 498 } 499 500 if(!ignoreRxFCS.Value && !EthernetFrame.CheckCRC(frame.Bytes)) 501 { 502 this.Log(LogLevel.Info, "Invalid CRC, packet discarded"); 503 return; 504 } 505 506 // the time obtained here is not single-instruction-precise (unless maximum block size is set to 1 and block chaining is disabled), 507 // because timers are not updated instruction-by-instruction, but in batches when `TranslationCPU.ExecuteInstructions` finishes 508 rxPacketTimestamp.seconds = (uint)secTimer.Value; 509 rxPacketTimestamp.nanos = (uint)nanoTimer.Value; 510 511 rxDescriptorsQueue.CurrentDescriptor.Invalidate(); 512 if(!rxDescriptorsQueue.CurrentDescriptor.Ownership) 513 { 514 var actualLength = (uint)(removeFrameChecksum.Value ? frame.Bytes.Length - 4 : frame.Bytes.Length); 515 if(!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, actualLength, (uint)receiveBufferOffset.Value)) 516 { 517 // The current implementation doesn't handle packets that do not fit into a single buffer. 518 // In case we encounter this error, we probably should implement partitioning/scattering procedure. 519 this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer: maximum packet length exceeded."); 520 return; 521 } 522 523 rxDescriptorsQueue.CurrentDescriptor.StartOfFrame = true; 524 rxDescriptorsQueue.CurrentDescriptor.EndOfFrame = true; 525 526 if(rxBufferDescriptorTimeStampMode.Value != TimestampingMode.Disabled) 527 { 528 rxDescriptorsQueue.CurrentDescriptor.Timestamp = rxPacketTimestamp; 529 } 530 else 531 { 532 rxDescriptorsQueue.CurrentDescriptor.HasValidTimestamp = false; 533 } 534 535 rxDescriptorsQueue.GoToNextDescriptor(); 536 537 frameReceived.Value = true; 538 interruptManager.SetInterrupt(Interrupts.ReceiveComplete); 539 } 540 else 541 { 542 this.Log(LogLevel.Warning, "Receive DMA buffer overflow"); 543 bufferNotAvailable.Value = true; 544 interruptManager.SetInterrupt(Interrupts.ReceiveUsedBitRead); 545 } 546 } 547 } 548 549 public event Action<EthernetFrame> FrameReady; 550 551 public long Size => 0x1000; 552 553 public MACAddress MAC { get; set; } 554 555 public ushort ModuleRevision { get; private set; } 556 public ushort ModuleId { get; private set; } 557 558 [IrqProvider] 559 public GPIO IRQ { get; private set; } 560 HandlePhyRead()561 private uint HandlePhyRead() 562 { 563 return phyDataRead; 564 } 565 HandlePhyWrite(uint value)566 private void HandlePhyWrite(uint value) 567 { 568 var data = (ushort)(value & 0xFFFF); 569 var reg = (ushort)((value >> 18) & 0x1F); 570 var addr = (uint)((value >> 23) & 0x1F); 571 var op = (PhyOperation)((value >> 28) & 0x3); 572 573 if(!TryGetPhy<ushort>(addr, out var phy)) 574 { 575 this.Log(LogLevel.Warning, "Write to PHY with unknown address {0}", addr); 576 phyDataRead = 0xFFFFU; 577 return; 578 } 579 580 switch(op) 581 { 582 case PhyOperation.Read: 583 phyDataRead = phy.Read(reg); 584 break; 585 case PhyOperation.Write: 586 phy.Write(reg, data); 587 break; 588 default: 589 this.Log(LogLevel.Warning, "Unknown PHY operation code 0x{0:X}", op); 590 break; 591 } 592 593 interruptManager.SetInterrupt(Interrupts.ManagementDone); 594 } 595 SendSingleFrame(IEnumerable<byte> bytes, bool isCRCIncluded)596 private void SendSingleFrame(IEnumerable<byte> bytes, bool isCRCIncluded) 597 { 598 var bytesArray = bytes.ToArray(); 599 EnsureArrayLength(bytesArray, isCRCIncluded ? 64 : 60); 600 601 EthernetFrame frame; 602 var addCrc = !isCRCIncluded && checksumGeneratorEnabled.Value; 603 if(!Misc.TryCreateFrameOrLogWarning(this, bytesArray, out frame, addCrc)) 604 { 605 return; 606 } 607 if(addCrc) 608 { 609 frame.FillWithChecksums(new [] { EtherType.IpV4, EtherType.IpV6 }, 610 new [] { IPProtocolType.TCP, IPProtocolType.UDP }); 611 } 612 613 this.Log(LogLevel.Noisy, "Sending packet, length {0}", frame.Bytes.Length); 614 FrameReady?.Invoke(frame); 615 616 // the time obtained here is not single-instruction-precise (unless maximum block size is set to 1 and block chaining is disabled), 617 // because timers are not updated instruction-by-instruction, but in batches when `TranslationCPU.ExecuteInstructions` finishes 618 txPacketTimestamp.seconds = (uint)secTimer.Value; 619 txPacketTimestamp.nanos = (uint)nanoTimer.Value; 620 621 if(txBufferDescriptorTimeStampMode.Value != TimestampingMode.Disabled) 622 { 623 txDescriptorsQueue.CurrentDescriptor.Timestamp = txPacketTimestamp; 624 } 625 else 626 { 627 rxDescriptorsQueue.CurrentDescriptor.HasValidTimestamp = false; 628 } 629 } 630 EnsureArrayLength(byte[] bytesArray, int length)631 private void EnsureArrayLength(byte[] bytesArray, int length) 632 { 633 if(bytesArray.Length < length) 634 { 635 Array.Resize(ref bytesArray, length); 636 } 637 } 638 SendFrames()639 private void SendFrames() 640 { 641 lock(sync) 642 { 643 var packetBytes = new List<byte>(); 644 bool? isCRCIncluded = null; 645 646 txDescriptorsQueue.CurrentDescriptor.Invalidate(); 647 while(!txDescriptorsQueue.CurrentDescriptor.IsUsed) 648 { 649 if(!isCRCIncluded.HasValue) 650 { 651 // this information is interperted only for the first buffer in a frame 652 isCRCIncluded = txDescriptorsQueue.CurrentDescriptor.IsCRCIncluded; 653 } 654 655 // fill packet with data from memory 656 packetBytes.AddRange(txDescriptorsQueue.CurrentDescriptor.ReadBuffer()); 657 if(txDescriptorsQueue.CurrentDescriptor.IsLast) 658 { 659 SendSingleFrame(packetBytes, isCRCIncluded.Value); 660 packetBytes.Clear(); 661 isCRCIncluded = null; 662 } 663 664 txDescriptorsQueue.GoToNextDescriptor(); 665 } 666 667 transmitComplete.Value = true; 668 usedBitRead.Value = true; 669 670 interruptManager.SetInterrupt(Interrupts.TransmitUsedBitRead); 671 interruptManager.SetInterrupt(Interrupts.TransmitComplete); 672 } 673 } 674 675 private uint phyDataRead; 676 private bool isTransmissionStarted; 677 private DmaBufferDescriptorsQueue<DmaTxBufferDescriptor> txDescriptorsQueue; 678 private DmaBufferDescriptorsQueue<DmaRxBufferDescriptor> rxDescriptorsQueue; 679 680 private readonly IFlagRegisterField checksumGeneratorEnabled; 681 private readonly IFlagRegisterField extendedRxBufferDescriptorEnabled; 682 private readonly IFlagRegisterField extendedTxBufferDescriptorEnabled; 683 private readonly IEnumRegisterField<DMAAddressWidth> dmaAddressBusWith; 684 private readonly IFlagRegisterField transmitComplete; 685 private readonly IFlagRegisterField usedBitRead; 686 private readonly IFlagRegisterField receiveEnabled; 687 private readonly IFlagRegisterField ignoreRxFCS; 688 private readonly IFlagRegisterField bufferNotAvailable; 689 private readonly IFlagRegisterField frameReceived; 690 private readonly IFlagRegisterField removeFrameChecksum; 691 private readonly IValueRegisterField receiveBufferOffset; 692 private readonly IEnumRegisterField<TimestampingMode> rxBufferDescriptorTimeStampMode; 693 private readonly IEnumRegisterField<TimestampingMode> txBufferDescriptorTimeStampMode; 694 private readonly IValueRegisterField secTimer; 695 696 private readonly IBusController sysbus; 697 private readonly InterruptManager<Interrupts> interruptManager; 698 private readonly DoubleWordRegisterCollection registers; 699 private readonly object sync; 700 701 private readonly LimitTimer nanoTimer; 702 703 private PTPTimestamp txPacketTimestamp; 704 private PTPTimestamp rxPacketTimestamp; 705 706 private class DmaBufferDescriptorsQueue<T> where T : DmaBufferDescriptor 707 { DmaBufferDescriptorsQueue(IBusController bus, uint baseAddress, Func<IBusController, uint, T> creator)708 public DmaBufferDescriptorsQueue(IBusController bus, uint baseAddress, Func<IBusController, uint, T> creator) 709 { 710 this.bus = bus; 711 this.creator = creator; 712 this.baseAddress = baseAddress; 713 descriptors = new List<T>(); 714 715 GoToNextDescriptor(); 716 } 717 GoToNextDescriptor()718 public void GoToNextDescriptor() 719 { 720 if(descriptors.Count == 0) 721 { 722 // this is the first descriptor - read it from baseAddress 723 descriptors.Add(creator(bus, baseAddress)); 724 currentDescriptorIndex = 0; 725 } 726 else 727 { 728 CurrentDescriptor.Update(); 729 730 if(CurrentDescriptor.Wrap) 731 { 732 currentDescriptorIndex = 0; 733 } 734 else 735 { 736 if(currentDescriptorIndex == descriptors.Count - 1) 737 { 738 // we need to generate new descriptor 739 descriptors.Add(creator(bus, CurrentDescriptor.LowerDescriptorAddress + CurrentDescriptor.SizeInBytes)); 740 } 741 currentDescriptorIndex++; 742 } 743 } 744 745 CurrentDescriptor.Invalidate(); 746 } 747 GoToBaseAddress()748 public void GoToBaseAddress() 749 { 750 currentDescriptorIndex = 0; 751 CurrentDescriptor.Invalidate(); 752 } 753 754 public T CurrentDescriptor => descriptors[currentDescriptorIndex]; 755 756 private int currentDescriptorIndex; 757 758 private readonly List<T> descriptors; 759 private readonly uint baseAddress; 760 private readonly IBusController bus; 761 private readonly Func<IBusController, uint, T> creator; 762 } 763 764 private abstract class DmaBufferDescriptor 765 { DmaBufferDescriptor(IBusController bus, uint address, DMAAddressWidth dmaAddressWidth, bool isExtendedModeEnabled)766 protected DmaBufferDescriptor(IBusController bus, uint address, DMAAddressWidth dmaAddressWidth, bool isExtendedModeEnabled) 767 { 768 this.dmaAddressWidth = dmaAddressWidth; 769 Bus = bus; 770 LowerDescriptorAddress = address; 771 IsExtendedModeEnabled = isExtendedModeEnabled; 772 SizeInBytes = InitWords(); 773 } 774 Invalidate()775 public void Invalidate() 776 { 777 var tempOffset = 0UL; 778 for(var i = 0; i < words.Length; ++i) 779 { 780 words[i] = Bus.ReadDoubleWord(GetDescriptorAddress() + tempOffset); 781 tempOffset += 4; 782 } 783 } 784 Update()785 public void Update() 786 { 787 var tempOffset = 0UL; 788 foreach(var word in words) 789 { 790 Bus.WriteDoubleWord(GetDescriptorAddress() + tempOffset, word); 791 tempOffset += 4; 792 } 793 } 794 GetBufferAddress()795 public ulong GetBufferAddress() 796 { 797 return dmaAddressWidth == DMAAddressWidth.Bit64 ? (((ulong)UpperBufferAddress << 32) | LowerBufferAddress) : LowerBufferAddress; 798 } 799 800 public IBusController Bus { get; } 801 public uint SizeInBytes { get; } 802 public bool IsExtendedModeEnabled { get; } 803 public uint LowerDescriptorAddress { get; set; } 804 public uint UpperDescriptorAddress { get; set; } 805 806 public uint UpperBufferAddress 807 { 808 get { return BitHelper.GetMaskedValue(words[2], 0, 32); } 809 set { BitHelper.SetMaskedValue(ref words[2], value, 0, 32); } 810 } 811 812 public PTPTimestamp Timestamp 813 { 814 get 815 { 816 var ptpTimestamp = new PTPTimestamp(); 817 if(!IsExtendedModeEnabled) 818 { 819 return ptpTimestamp; 820 } 821 ptpTimestamp.nanos = BitHelper.GetMaskedValue(words[4], 0, 30); 822 ptpTimestamp.seconds = (BitHelper.GetMaskedValue(words[4], 30, 2) << 4) | BitHelper.GetMaskedValue(words[5], 0, 4); 823 return ptpTimestamp; 824 } 825 set 826 { 827 if(IsExtendedModeEnabled) 828 { 829 BitHelper.SetMaskedValue(ref words[4], value.nanos, 0, 30); 830 BitHelper.SetMaskedValue(ref words[4], value.seconds >> 4, 30, 2); 831 BitHelper.SetMaskedValue(ref words[5], value.seconds & 0xF, 0, 4); 832 HasValidTimestamp = true; 833 } 834 } 835 } 836 837 public abstract bool Wrap { get; } 838 public abstract bool HasValidTimestamp { set; } 839 public abstract uint LowerBufferAddress { get; set; } 840 841 protected uint[] words; 842 InitWords()843 private uint InitWords() 844 { 845 if(dmaAddressWidth == DMAAddressWidth.Bit64 && IsExtendedModeEnabled) 846 { 847 words = new uint[6]; 848 } 849 else if((dmaAddressWidth == DMAAddressWidth.Bit32 && IsExtendedModeEnabled) || (dmaAddressWidth == DMAAddressWidth.Bit64 && !IsExtendedModeEnabled)) 850 { 851 words = new uint[4]; 852 } 853 else if(dmaAddressWidth == DMAAddressWidth.Bit32 && !IsExtendedModeEnabled) 854 { 855 words = new uint[2]; 856 } 857 return (uint)words.Length * 4; 858 } 859 GetDescriptorAddress()860 private ulong GetDescriptorAddress() 861 { 862 return dmaAddressWidth == DMAAddressWidth.Bit64 ? (((ulong)UpperDescriptorAddress << 32) | LowerDescriptorAddress) : LowerDescriptorAddress; 863 } 864 865 private readonly DMAAddressWidth dmaAddressWidth; 866 } 867 868 /// RX buffer descriptor format: 869 /// * word 0: 870 /// * 0: Ownership flag 871 /// * 1: Wrap flag 872 /// * 2: Address of beginning of buffer, or in extended buffer descriptor 873 /// mode indicates a valid timestamp in the descriptor entry 874 /// * In basic buffer descriptor mode: 875 /// * 2-31: Address of the buffer [31:2] 876 /// * In extended buffer descriptor mode: 877 /// * 2: Valid timestamp flag 878 /// * 3-31: Address of the buffer [31:3] 879 /// * word 1: 880 /// * 0-12: Length of the received frame 881 /// * 13: Bad FCS flag 882 /// * 14: Start of frame flag 883 /// * 15: End of frame flag 884 /// * 16: Cannonical form indicator flag 885 /// * 17-19: VLAN priority 886 /// * 20: Priority tag detected flag 887 /// * 21: VLAN tag detected flag 888 /// * 22-23: Type ID match 889 /// * 24: Type ID match meaning flag 890 /// * 25-26: Specific address register match 891 /// * 27: Specific address found flag 892 /// * 28: External address match flag 893 /// * 29: Unicast hash match flag 894 /// * 30: Multicast hash match flag 895 /// * 31: Broadcast address detected flag 896 /// * word 2 (64-bit addressing): 897 /// * 0-31: Upper 32-bit address of the data buffer 898 /// * word 3 (64-bit addressing): 899 /// * 0-31: Reserved 900 /// * word 2 (32-bit addressing) or word 4 (64-bit addressing): 901 /// * 0-29: Timestamp nanosecods [29:0] 902 /// * 30-31: Timestamp seconds [1:0] 903 /// * word 3 (32-bit addressing) or word 5 (64-bit addressing): 904 /// * 0-3: Timestamp seconds [5:2] 905 /// * 4-31: Reserved 906 private class DmaRxBufferDescriptor : DmaBufferDescriptor 907 { DmaRxBufferDescriptor(IBusController bus, uint address, DMAAddressWidth addressWidth, bool extendedModeEnabled)908 public DmaRxBufferDescriptor(IBusController bus, uint address, DMAAddressWidth addressWidth, bool extendedModeEnabled) : base(bus, address, addressWidth, extendedModeEnabled) 909 { 910 } 911 WriteBuffer(byte[] bytes, uint length, uint offset = 0)912 public bool WriteBuffer(byte[] bytes, uint length, uint offset = 0) 913 { 914 if(Ownership || bytes.Length > MaximumBufferLength) 915 { 916 return false; 917 } 918 919 Length = length; 920 Bus.WriteBytes(bytes, GetBufferAddress() + offset, true); 921 Ownership = true; 922 923 return true; 924 } 925 926 public override uint LowerBufferAddress 927 { 928 get 929 { 930 if(IsExtendedModeEnabled) 931 { 932 return BitHelper.GetMaskedValue(words[0], 3, 29); 933 } 934 return BitHelper.GetMaskedValue(words[0], 2, 30); 935 } 936 set 937 { 938 if(IsExtendedModeEnabled) 939 { 940 BitHelper.SetMaskedValue(ref words[0], value, 3, 29); 941 } 942 else 943 { 944 BitHelper.SetMaskedValue(ref words[0], value, 2, 30); 945 } 946 } 947 } 948 949 public override bool Wrap => BitHelper.IsBitSet(words[0], 1); 950 951 public override bool HasValidTimestamp 952 { 953 set 954 { 955 if(IsExtendedModeEnabled) 956 { 957 BitHelper.SetBit(ref words[0], 2, value); 958 } 959 } 960 } 961 962 public bool StartOfFrame { set { BitHelper.SetBit(ref words[1], 14, value); } } 963 964 public bool EndOfFrame { set { BitHelper.SetBit(ref words[1], 15, value); } } 965 966 public uint Length { set { BitHelper.SetMaskedValue(ref words[1], value, 0, 13); } } 967 968 public bool Ownership 969 { 970 get { return BitHelper.IsBitSet(words[0], 0); } 971 set { BitHelper.SetBit(ref words[0], 0, value); } 972 } 973 974 private const int MaximumBufferLength = (1 << 13) - 1; 975 } 976 977 /// TX buffer descriptor format: 978 /// * word 0: 979 /// * 0-31: Address of the buffer [31:0] 980 /// * word 1: 981 /// * 0-13: Lenght of the buffer 982 /// * 14: Reserved 983 /// * 15: Last buffer flag 984 /// * 16: CRC appended flag 985 /// * 17-19: Reserved 986 /// * 20-22: Transmit checksum errors 987 /// * In basic buffer descriptor mode: 988 /// * 23: Reserved 989 /// * In extended buffer descriptor mode: 990 /// * 23: Timestamp captured flag 991 /// * 24-25: Reserved 992 /// * 26: Late collision detected flag 993 /// * 27: Transmit frame corruption flag 994 /// * 28: Reserved 995 /// * 29: Retry limit exceeded 996 /// * 30: Wrap flag 997 /// * 31: Used flag 998 /// * word 2 (64-bit addressing): 999 /// * 0-31: Address of the buffer [63:32] 1000 /// * word 3 (64-bit addressing): 1001 /// * 0-31: Reserved 1002 /// * word 2 (32-bit addressing) or word 4 (64-bit addressing): 1003 /// * 0-29: Timestamp nanosecods [29:0] 1004 /// * 30-31: Timestamp seconds [1:0] 1005 /// * word 3 (32-bit addressing) or word 5 (64-bit addressing): 1006 /// * 0-3: Timestamp seconds [5:2] 1007 /// * 4-31: Reserved 1008 private class DmaTxBufferDescriptor : DmaBufferDescriptor 1009 { DmaTxBufferDescriptor(IBusController bus, uint address, DMAAddressWidth addressWidth, bool extendedModeEnabled)1010 public DmaTxBufferDescriptor(IBusController bus, uint address, DMAAddressWidth addressWidth, bool extendedModeEnabled) : base(bus, address, addressWidth, extendedModeEnabled) 1011 { 1012 } 1013 ReadBuffer()1014 public byte[] ReadBuffer() 1015 { 1016 var result = Bus.ReadBytes(GetBufferAddress(), Length, true); 1017 IsUsed = true; 1018 return result; 1019 } 1020 1021 public ushort Length => (ushort)BitHelper.GetMaskedValue(words[1], 0, 14); 1022 1023 public bool IsLast => BitHelper.IsBitSet(words[1], 15); 1024 1025 public bool IsCRCIncluded => BitHelper.IsBitSet(words[1], 16); 1026 1027 public bool IsUsed 1028 { 1029 get { return BitHelper.IsBitSet(words[1], 31); } 1030 set { BitHelper.SetBit(ref words[1], 31, value); } 1031 } 1032 1033 public override bool HasValidTimestamp 1034 { 1035 set 1036 { 1037 if(IsExtendedModeEnabled) 1038 { 1039 BitHelper.SetBit(ref words[1], 23, value); 1040 } 1041 } 1042 } 1043 1044 public override uint LowerBufferAddress 1045 { 1046 get 1047 { 1048 return words[0]; 1049 } 1050 set 1051 { 1052 words[0] = value; 1053 } 1054 } 1055 1056 public override bool Wrap => BitHelper.IsBitSet(words[1], 30); 1057 } 1058 1059 private const uint NanosPerSecond = 1000000000; 1060 1061 private struct PTPTimestamp 1062 { 1063 public uint seconds; 1064 public uint nanos; 1065 } 1066 1067 private enum TimestampingMode 1068 { 1069 Disabled = 0, 1070 PTPEventFrames = 1, 1071 PTPAllFrames = 2, 1072 AllFrames = 3 1073 } 1074 1075 private enum DMAAddressWidth 1076 { 1077 Bit32 = 0, 1078 Bit64 = 1, 1079 } 1080 1081 private enum Interrupts 1082 { 1083 ManagementDone = 0, 1084 ReceiveComplete = 1, 1085 ReceiveUsedBitRead = 2, 1086 TransmitUsedBitRead = 3, 1087 TransmitComplete = 7 1088 } 1089 1090 private enum PhyOperation 1091 { 1092 Write = 0x1, 1093 Read = 0x2 1094 } 1095 1096 private enum Registers : long 1097 { 1098 NetworkControl = 0x0, 1099 NetworkConfiguration = 0x4, 1100 NetworkStatus = 0x8, 1101 UserInputOutput = 0xC, 1102 DmaConfiguration = 0x10, 1103 TransmitStatus = 0x14, 1104 ReceiveBufferQueueBaseAddress = 0x18, 1105 TransmitBufferQueueBaseAddress = 0x1C, 1106 ReceiveStatus = 0x20, 1107 InterruptStatus = 0x24, 1108 InterruptEnable = 0x28, 1109 InterruptDisable = 0x2C, 1110 InterruptMaskStatus = 0x30, 1111 PhyMaintenance = 0x34, 1112 ReceivedPauseQuantum = 0x38, 1113 TransmitPauseQuantum = 0x3C, 1114 // gap intended 1115 HashRegisterBottom = 0x80, 1116 HashRegisterTop = 0x84, 1117 SpecificAddress1Bottom = 0x88, 1118 SpecificAddress1Top = 0x8C, 1119 SpecificAddress2Bottom = 0x90, 1120 SpecificAddress2Top = 0x94, 1121 SpecificAddress3Top = 0x98, 1122 SpecificAddress3Bottom = 0x9C, 1123 SpecificAddress4Top = 0xA0, 1124 SpecificAddress4Bottom = 0xA4, 1125 TypeIDMatch1 = 0xA8, 1126 TypeIDMatch2 = 0xAC, 1127 TypeIDMatch3 = 0xB0, 1128 TypeIDMatch4 = 0xB4, 1129 WakeOnLan = 0xB8, 1130 IpgStretch = 0xBC, 1131 StackedVlan = 0xC0, 1132 TransmitPfcPause = 0xC4, 1133 SpecificAddressMask1Bottom = 0xC8, 1134 SpecificAddressMask1Top = 0xCC, 1135 // gap intended 1136 PtpEventFrameTransmittedSecondsHigh = 0x0E8, 1137 PtpEventFrameReceivedSecondsHigh = 0x0EC, 1138 PtpPeerEventFrameTransmittedSecondsHigh = 0x0F0, 1139 PtpPeerEventFrameReceivedSecondsHigh = 0x0F4, 1140 ModuleId = 0xFC, 1141 OctetsTransmittedLow = 0x100, 1142 OctetsTransmittedHigh = 0x104, 1143 FramesTransmitted = 0x108, 1144 BroadcastFramesTx = 0x10C, 1145 MulticastFramesTx = 0x110, 1146 PauseFramesTx = 0x114, 1147 FramesTx64b = 0x118, 1148 FramesTx127b65b = 0x11C, 1149 FramesTx255b128b = 0x120, 1150 FramesTx511b256b = 0x124, 1151 FramesTx1023b512b = 0x128, 1152 FramesTx1518b1024b = 0x12C, 1153 // gap intended 1154 TransmitUnderRuns = 0x134, 1155 SingleCollisionFrames = 0x138, 1156 MultipleCollisionFrames = 0x13C, 1157 ExcessiveCollisions = 0x140, 1158 LateCollisions = 0x144, 1159 DeferredTransmissionFrames = 0x148, 1160 CarrierSenseErrors = 0x14C, 1161 OctetsReceivedLow = 0x150, 1162 OctetsReceivedHigh = 0x154, 1163 FramesReceived = 0x158, 1164 BroadcastFramesRx = 0x15C, 1165 MulticastFramesRx = 0x160, 1166 PauseFramesRx = 0x164, 1167 FramesRx64b = 0x168, 1168 FramesRx127b65b = 0x16C, 1169 FramesRx255b128b = 0x170, 1170 FramesRx511b256b = 0x174, 1171 FramesRx1023b512b = 0x178, 1172 FramesRx1518b1024b = 0x17C, 1173 UndersizeFramesReceived = 0x184, 1174 OversizeFramesReceived = 0x188, 1175 JabbersReceived = 0x18C, 1176 FrameCheckSequenceErrors = 0x190, 1177 LengthFieldFrameErrors = 0x194, 1178 ReceiveSymbolErrors = 0x198, 1179 AlignmentErrors = 0x19C, 1180 ReceiveResourceErrors = 0x1A0, 1181 ReceiveOverrunErrors = 0x1A4, 1182 IpHeaderChecksumErrors = 0x1A8, 1183 TcpCHecksumErrors = 0x1AC, 1184 UdpChecksumErrors = 0x1B0, 1185 // gap intended 1186 Timer1588IncrementSubnanoseconds = 0x1BC, 1187 Timer1588SecondsHigh = 0x1C0, 1188 // gap intended 1189 Timer1588SyncStrobeSeconds = 0x1C8, 1190 Timer1588SyncStrobeNanoseconds = 0x1CC, 1191 Timer1588SecondsLow = 0x1D0, 1192 Timer1588Nanoseconds = 0x1D4, 1193 Timer1588Adjust = 0x1D8, 1194 Timer1588Increment = 0x1DC, 1195 PtpEventFrameTransmittedSeconds = 0x1E0, 1196 PtpEventFrameTransmittedNanoseconds = 0x1E4, 1197 PtpEventFrameReceivedSeconds = 0x1E8, 1198 PtpEventFrameReceivedNanoseconds = 0x1EC, 1199 PtpPeerEventFrameTransmittedSeconds = 0x1F0, 1200 PtpPeerEventFrameTransmittedNanoseconds = 0x1F4, 1201 PtpPeerEventFrameReceivedSeconds = 0x1F8, 1202 PtpPeerEventFrameReceivedNanoseconds = 0x1FC, 1203 // gap intended 1204 DesignConfiguration1 = 0x280, // this register's implementation is based on linux driver as Zynq-7000 documentation does not mention it 1205 DesignConfiguration2 = 0x284, 1206 DesignConfiguration3 = 0x288, 1207 DesignConfiguration4 = 0x28C, 1208 DesignConfiguration5 = 0x290, 1209 // gap intended 1210 InterruptStatusPriorityQueue1 = 0x400, 1211 InterruptStatusPriorityQueue2 = 0x404, 1212 // gap intended 1213 TransmitBufferQueueBaseAddressPriorityQueue1 = 0x440, 1214 TransmitBufferQueueBaseAddressPriorityQueue2 = 0x444, 1215 // gap intended 1216 ReceiveBufferQueueBaseAddressPriorityQueue1 = 0x480, 1217 ReceiveBufferQueueBaseAddressPriorityQueue2 = 0x484, 1218 // gap intended 1219 ReceiveBufferSizePriorityQueue1 = 0x4A0, 1220 ReceiveBufferSizePriorityQueue2 = 0x4A4, 1221 // gap intended 1222 CreditBasedShapingControl = 0x4BC, 1223 CreditBasedShapingIdleSlopeQueueA = 0x4C0, 1224 CreditBasedShapingIdleSlopeQueueB = 0x4C4, 1225 TransmitBufferQueueBaseAddressUpper = 0x4C8, 1226 TransmitBufferDescriptorControl = 0x4CC, 1227 ReceiveBufferDescriptorControl = 0x4D0, 1228 ReceiveBufferQueueBaseAddressUpper = 0x4D4, 1229 // gap intended 1230 ScreeningType1PriorityQueues0 = 0x500, 1231 ScreeningType1PriorityQueues1 = 0x504, 1232 ScreeningType1PriorityQueues2 = 0x508, 1233 ScreeningType1PriorityQueues3 = 0x50C, 1234 // gap intended 1235 ScreeningType2PriorityQueues0 = 0x540, 1236 ScreeningType2PriorityQueues1 = 0x544, 1237 ScreeningType2PriorityQueues2 = 0x548, 1238 ScreeningType2PriorityQueues3 = 0x54C, 1239 ScreeningType2PriorityQueues4 = 0x550, 1240 ScreeningType2PriorityQueues5 = 0x554, 1241 ScreeningType2PriorityQueues6 = 0x55C, 1242 ScreeningType2PriorityQueues7 = 0x560, 1243 // gap intended 1244 InterruptEnablePriorityQueue1 = 0x600, 1245 InterruptEnablePriorityQueue2 = 0x604, 1246 // gap intended 1247 InterruptDisablePriorityQueue1 = 0x620, 1248 InterruptDisablePriorityQueue2 = 0x624, 1249 // gap intended 1250 InterruptMaskPriorityQueue1 = 0x640, 1251 InterruptMaskPriorityQueue2 = 0x644, 1252 // gap intended 1253 ScreeningType2Ethertype0 = 0x6E0, 1254 ScreeningType2Ethertype1 = 0x6E4, 1255 ScreeningType2Ethertype2 = 0x6E8, 1256 ScreeningType2Ethertype3 = 0x6EC, 1257 // gap intended 1258 ScreeningType2Compare0Word0 = 0x700, 1259 ScreeningType2Compare0Word1 = 0x704, 1260 ScreeningType2Compare1Word0 = 0x708, 1261 ScreeningType2Compare1Word1 = 0x70C, 1262 ScreeningType2Compare2Word0 = 0x710, 1263 ScreeningType2Compare2Word1 = 0x714, 1264 ScreeningType2Compare3Word0 = 0x718, 1265 ScreeningType2Compare3Word1 = 0x71C, 1266 ScreeningType2Compare4Word0 = 0x720, 1267 ScreeningType2Compare4Word1 = 0x724, 1268 ScreeningType2Compare5Word0 = 0x728, 1269 ScreeningType2Compare5Word1 = 0x72C, 1270 ScreeningType2Compare6Word0 = 0x730, 1271 ScreeningType2Compare6Word1 = 0x734, 1272 ScreeningType2Compare7Word0 = 0x738, 1273 ScreeningType2Compare7Word1 = 0x73C, 1274 ScreeningType2Compare8Word0 = 0x740, 1275 ScreeningType2Compare8Word1 = 0x744, 1276 ScreeningType2Compare9Word0 = 0x748, 1277 ScreeningType2Compare9Word1 = 0x74C, 1278 ScreeningType2Compare10Word0 = 0x750, 1279 ScreeningType2Compare10Word1 = 0x754, 1280 ScreeningType2Compare11Word0 = 0x758, 1281 ScreeningType2Compare11Word1 = 0x75C, 1282 ScreeningType2Compare12Word0 = 0x760, 1283 ScreeningType2Compare12Word1 = 0x764, 1284 ScreeningType2Compare13Word0 = 0x768, 1285 ScreeningType2Compare13Word1 = 0x76C, 1286 ScreeningType2Compare14Word0 = 0x770, 1287 ScreeningType2Compare14Word1 = 0x774, 1288 ScreeningType2Compare15Word0 = 0x778, 1289 ScreeningType2Compare15Word1 = 0x77C, 1290 ScreeningType2Compare16Word0 = 0x780, 1291 ScreeningType2Compare16Word1 = 0x784, 1292 ScreeningType2Compare17Word0 = 0x788, 1293 ScreeningType2Compare17Word1 = 0x78C, 1294 ScreeningType2Compare18Word0 = 0x790, 1295 ScreeningType2Compare18Word1 = 0x794, 1296 ScreeningType2Compare19Word0 = 0x798, 1297 ScreeningType2Compare19Word1 = 0x79C, 1298 ScreeningType2Compare20Word0 = 0x7A0, 1299 ScreeningType2Compare20Word1 = 0x7A4, 1300 ScreeningType2Compare21Word0 = 0x7A8, 1301 ScreeningType2Compare21Word1 = 0x7AC, 1302 ScreeningType2Compare22Word0 = 0x7B0, 1303 ScreeningType2Compare22Word1 = 0x7B4, 1304 ScreeningType2Compare23Word0 = 0x7B0, 1305 ScreeningType2Compare23Word1 = 0x7B4 1306 } 1307 } 1308 } 1309