public K6xF_Ethernet(Machine machine) : base(machine) { rxIRQ = new GPIO(); txIRQ = new GPIO(); ptpIRQ = new GPIO(); miscIRQ = new GPIO(); innerLock = new object(); interruptManager = new InterruptManager <Interrupts>(this); var registerMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.InterruptEvent, interruptManager.GetRegister <DoubleWordRegister>( valueProviderCallback: (interrupt, oldValue) => { return(interruptManager.IsSet(interrupt)); }, writeCallback: (interrupt, oldValue, newValue) => { if (newValue) { interruptManager.ClearInterrupt(interrupt); } }) }, { (long)Registers.InterruptMask, interruptManager.GetRegister <DoubleWordRegister>( valueProviderCallback: (interrupt, oldValue) => { return(interruptManager.IsEnabled(interrupt)); }, writeCallback: (interrupt, oldValue, newValue) => { if (newValue) { interruptManager.EnableInterrupt(interrupt); } else { interruptManager.DisableInterrupt(interrupt); interruptManager.ClearInterrupt(interrupt); } }) }, { (long)Registers.ReceiveDescriptorActive, new DoubleWordRegister(this) .WithReservedBits(25, 7) .WithFlag(24, out receiverEnabled, name: "RDAR") .WithReservedBits(0, 24) }, { (long)Registers.TransmitDescriptorActive, new DoubleWordRegister(this) .WithReservedBits(25, 7) .WithFlag(24, FieldMode.Read | FieldMode.WriteOneToClear, name: "TDAR", writeCallback: (_, value) => { if (value) { isTransmissionStarted = true; this.Log(LogLevel.Debug, "Sending Frames"); SendFrames(); } }) .WithReservedBits(0, 24) }, { (long)Registers.EthernetControl, new DoubleWordRegister(this) .WithReservedBits(17, 15) .WithReservedBits(12, 5) .WithReservedBits(11, 1) .WithReservedBits(10, 1) .WithReservedBits(9, 1) .WithTaggedFlag("DBSWP", 8) .WithTaggedFlag("STOPEN", 7) .WithTaggedFlag("DBGEN", 6) .WithReservedBits(5, 1) .WithFlag(4, out extendedMode, name: "EN1588") .WithTaggedFlag("SLEEP", 3) .WithTaggedFlag("MAGICEN", 2) .WithTaggedFlag("ETHEREN", 1) .WithFlag(0, FieldMode.Write, writeCallback: (_, b) => { if (b) { Reset(); } }, name: "RESET") }, { (long)Registers.ReceiveControl, new DoubleWordRegister(this) .WithTaggedFlag("GRS", 31) .WithTaggedFlag("NLC", 30) .WithValueField(16, 14, name: "MAX_FL") .WithTaggedFlag("CFEN", 15) .WithTaggedFlag("CRCFWD", 14) .WithTaggedFlag("PAUFWD", 13) .WithTaggedFlag("PADEN", 12) .WithReservedBits(10, 2) .WithTaggedFlag("RMII_10T", 9) .WithTaggedFlag("RMII_MODE", 8) .WithReservedBits(7, 1) .WithReservedBits(6, 1) .WithTaggedFlag("FCE", 5) .WithTaggedFlag("BC_REJ", 4) .WithTaggedFlag("PROM", 3) .WithTaggedFlag("MII_MODE", 2) .WithTaggedFlag("DRT", 1) .WithTaggedFlag("LOOP", 0) }, { (long)Registers.TransmitControl, new DoubleWordRegister(this) .WithReservedBits(11, 21) .WithReservedBits(10, 1) .WithFlag(9, out forwardCRCFromApplication, name: "CRCFWD") .WithTaggedFlag("ADDINS", 8) .WithValueField(5, 3, name: "ADDSEL") .WithTaggedFlag("RFC_PAUSE", 4) .WithTaggedFlag("TFC_PAUSE", 3) .WithTaggedFlag("FDEN", 2) .WithReservedBits(1, 1) .WithTaggedFlag("GTS", 0) }, { (long)Registers.PhysicalAddressLower, new DoubleWordRegister(this) .WithValueField(0, 32, out lowerMAC, writeCallback: (_, value) => { UpdateMac(); }, name: "PADDR1") }, { (long)Registers.PhysicalAddressUpper, new DoubleWordRegister(this) .WithValueField(16, 16, out upperMAC, writeCallback: (_, value) => { UpdateMac(); }, name: "PADDR2") .WithValueField(0, 16, name: "TYPE") }, { (long)Registers.TransmitFIFOWatermark, new DoubleWordRegister(this) .WithReservedBits(9, 22) .WithTaggedFlag("STRFWD", 8) .WithReservedBits(6, 2) .WithValueField(0, 6, name: "TFWR") }, { (long)Registers.ReceiveDescriptorRingStart, new DoubleWordRegister(this) .WithValueField(2, 30, name: "R_DES_START", writeCallback: (oldValue, value) => { if (receiverEnabled.Value) { this.Log(LogLevel.Warning, "Changing value of receive buffer queue base address while reception is enabled is illegal"); return; } rxDescriptorsQueue = new DmaBufferDescriptorsQueue <DmaRxBufferDescriptor>(machine.SystemBus, value << 2, (sb, addr) => new DmaRxBufferDescriptor(sb, addr, extendedMode.Value)); }) .WithReservedBits(1, 1) .WithReservedBits(0, 1) }, { (long)Registers.TransmitBufferDescriptorRingStart, new DoubleWordRegister(this) .WithValueField(2, 30, name: "X_DES_START", writeCallback: (oldValue, value) => { if (isTransmissionStarted) { this.Log(LogLevel.Warning, "Changing value of transmit buffer descriptor ring start address while transmission is started is illegal"); return; } txDescriptorsQueue = new DmaBufferDescriptorsQueue <DmaTxBufferDescriptor>(machine.SystemBus, value << 2, (sb, addr) => new DmaTxBufferDescriptor(sb, addr, extendedMode.Value)); }) .WithReservedBits(1, 1) .WithReservedBits(0, 1) } }; registers = new DoubleWordRegisterCollection(this, registerMap); }
public CadenceGEM(Machine machine) : base(machine) { IRQ = new GPIO(); MAC = EmulationManager.Instance.CurrentEmulation.MACRepository.GenerateUniqueMAC(); sync = new object(); interruptManager = new InterruptManager <Interrupts>(this); var registersMap = new Dictionary <long, DoubleWordRegister> { { (long)Registers.NetworkControl, new DoubleWordRegister(this) .WithFlag(2, out receiveEnabled, name: "RXEN") .WithFlag(9, FieldMode.Write, name: "STARTTX", writeCallback: (_, value) => { if (value) { SendFrames(); } }) }, { (long)Registers.NetworkConfiguration, new DoubleWordRegister(this, 0x80000) .WithValueField(14, 2, out receiveBufferOffset, name: "RXOFFS") .WithFlag(26, out ignoreRxFCS, name: "FCSIGNORE") }, { (long)Registers.NetworkStatus, new DoubleWordRegister(this, 0x4) }, { (long)Registers.DmaConfiguration, new DoubleWordRegister(this, 0x00020784) .WithFlag(11, out checksumGeneratorEnabled, name: "TCPCKSUM") }, { (long)Registers.TransmitStatus, new DoubleWordRegister(this) .WithFlag(0, out usedBitRead, FieldMode.Read | FieldMode.WriteOneToClear, name: "USEDREAD") .WithFlag(5, out transmitComplete, FieldMode.Read | FieldMode.WriteOneToClear, name: "TXCOMPL") }, { (long)Registers.ReceiveBufferQueueBaseAddress, new DoubleWordRegister(this) .WithValueField(2, 30, name: "RXQBASEADDR", valueProviderCallback: _ => { return(rxDescriptorsQueue.CurrentDescriptor.BaseAddress); }, writeCallback: (oldValue, value) => { if (receiveEnabled.Value) { // TODO: this write should be ignored this.Log(LogLevel.Warning, "Changing value of receive buffer queue base address when receiving is enabled is illegal"); } rxDescriptorsQueue = new DmaBufferDescriptorsQueue <DmaRxBufferDescriptor>(machine.SystemBus, value << 2, (sb, addr) => new DmaRxBufferDescriptor(sb, addr)); }) }, { (long)Registers.TransmitBufferQueueBaseAddress, new DoubleWordRegister(this) .WithValueField(2, 30, name: "TXQBASEADDR", valueProviderCallback: _ => { return(txDescriptorsQueue.CurrentDescriptor.BaseAddress); }, writeCallback: (oldValue, value) => { txDescriptorsQueue = new DmaBufferDescriptorsQueue <DmaTxBufferDescriptor>(machine.SystemBus, value << 2, (sb, addr) => new DmaTxBufferDescriptor(sb, addr)); }) }, { (long)Registers.ReceiveStatus, new DoubleWordRegister(this) .WithFlag(0, out bufferNotAvailable, FieldMode.Read | FieldMode.WriteOneToClear, name: "BUFFNA") .WithFlag(1, out frameReceived, FieldMode.Read | FieldMode.WriteOneToClear, name: "FRAMERX") }, { (long)Registers.InterruptStatus, interruptManager.GetRegister <DoubleWordRegister>( valueProviderCallback: (interrupt, oldValue) => interruptManager.IsSet(interrupt) && interruptManager.IsEnabled(interrupt), writeCallback: (interrupt, oldValue, newValue) => { if (newValue) { interruptManager.ClearInterrupt(interrupt); } }) }, { (long)Registers.InterruptEnable, interruptManager.GetRegister <DoubleWordRegister>( writeCallback: (interrupt, oldValue, newValue) => { if (newValue) { interruptManager.EnableInterrupt(interrupt); } }) }, { (long)Registers.InterruptDisable, interruptManager.GetRegister <DoubleWordRegister>( writeCallback: (interrupt, oldValue, newValue) => { if (newValue) { interruptManager.DisableInterrupt(interrupt); } }) }, { (long)Registers.InterruptMaskStatus, interruptManager.GetRegister <DoubleWordRegister>( valueProviderCallback: (interrupt, oldValue) => !interruptManager.IsEnabled(interrupt)) }, { (long)Registers.PhyMaintenance, new DoubleWordRegister(this) .WithValueField(0, 31, name: "PHYMNTNC", writeCallback: (_, value) => HandlePhyWrite(value), valueProviderCallback: _ => HandlePhyRead()) }, { (long)Registers.SpecificAddress1Bottom, new DoubleWordRegister(this) .WithValueField(0, 32, valueProviderCallback: _ => BitConverter.ToUInt32(MAC.Bytes, 0)) }, { (long)Registers.SpecificAddress1Top, new DoubleWordRegister(this) .WithValueField(0, 32, valueProviderCallback: _ => BitConverter.ToUInt16(MAC.Bytes, 4)) }, { (long)Registers.ModuleId, new DoubleWordRegister(this, 0x00020118) }, }; registers = new DoubleWordRegisterCollection(this, registersMap); Reset(); }