Exemplo n.º 1
0
        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();
        }