private void ReceiveFrameInner(EthernetFrame frame)
        {
            if ((registers.Control & (1u << 1)) == 0)
            {
                //if receiving is disabled discard packet
                return;
            }

            var rd = new receiveDescriptor(machine.SystemBus);

            if (!EthernetFrame.CheckCRC(frame.Bytes))
            {
                rd.CRCError = true;
                this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                return;
            }

            rd.Fetch(receiveDescriptorBase | receiveDescriptorOffset);
            if (!rd.Enable)
            {
                //if receive descritptor disabled discard packet
                return;
            }

            machine.SystemBus.WriteBytes(frame.Bytes, (long)rd.PacketAddress);
            registers.Status = 1u << 2;
            if (rd.Wrap)
            {
                receiveDescriptorOffset = 0;
            }
            else
            {
                if (receiveDescriptorOffset != 0x3f8)
                {
                    receiveDescriptorOffset += 8;
                }
                else
                {
                    receiveDescriptorOffset = 0;
                }
            }
            if (rd.InterruptEnable && ((registers.Control & (1u << 3)) != 0))
            {
                registers.Status |= 1u << 2;
                this.IRQ.Set();
                this.IRQ.Unset();
            }
            rd.Length = (uint)frame.Bytes.Length;
            rd.Enable = false;
            rd.Wrap   = false;
            rd.WriteBack();
        }
Example #2
0
        private void ReceiveFrameInner(EthernetFrame frame)
        {
            lock (sync)
            {
                this.Log(LogLevel.Noisy, "Received packet len {0}", frame.Bytes.Length);
                if ((registers.Control & (1u << 2)) == 0)
                {
                    this.Log(LogLevel.Debug, "Receiver not enabled, dropping frame.");
                    return;
                }

                if (!registers.IgnoreFCS && !EthernetFrame.CheckCRC(frame.Bytes))
                {
                    this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                    return;
                }

                bool interrupt          = false;
                rxBufferDescriptor rxBD = new rxBufferDescriptor(machine.SystemBus);
                rxBD.Fetch(registers.RxQueueBaseAddr);
                if (!rxBD.Ownership)//if we could write data to this BD
                {
                    interrupt         = false;
                    rxBD.Ownership    = true;
                    rxBD.StartOfFrame = true;
                    rxBD.EndOfFrame   = true;
                    rxBD.Length       = (ushort)frame.Bytes.Length;
                    machine.SystemBus.WriteBytes(frame.Bytes, rxBD.BufferAddress);
                    rxBD.WriteBack();
                    if (rxBD.Wrap)
                    {
                        registers.RxQueueBaseAddr = rxBufferBase;
                    }
                    else
                    {
                        registers.RxQueueBaseAddr += 8;
                    }
                    registers.RxStatus |= 1u << 1;
                    if ((registers.InterruptMask & (1u << 1)) == 0)
                    {
                        registers.InterruptStatus |= 1u << 1;
                        interrupt = true;
                    }
                    if (interrupt)
                    {
                        IRQ.Set();
                    }
                }
            }
        }
Example #3
0
        private bool TryReceivePacket(byte[] data)
        {
            // first check whether the packet fits into buffer
            var receiveBufferSize       = receiveBufferEnd - receiveBufferStart + 1;
            var freeSpace               = receiveBufferSize - ((receiveBufferSize + currentReceiveWritePointer - receiveReadPointer) % receiveBufferSize);
            var packetPlusHeadersLength = data.Length + 2 + 4;      // next packet pointer and receive status vector

            packetPlusHeadersLength += packetPlusHeadersLength % 2; // padding byte
            if (freeSpace < packetPlusHeadersLength)
            {
                this.Log(LogLevel.Warning, "No free space for packet. Packet length (+ headers): {0}B, free space: {1}B.",
                         Misc.NormalizeBinary(packetPlusHeadersLength), Misc.NormalizeBinary(freeSpace));
                return(false);
            }

            if (!EthernetFrame.CheckCRC(data) && crcEnabled.Value)
            {
                this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                return(false);
            }

            var nextReceiveWritePointer = currentReceiveWritePointer + packetPlusHeadersLength;

            if (nextReceiveWritePointer > receiveBufferEnd)
            {
                nextReceiveWritePointer -= receiveBufferSize;
            }
            var packetWithHeader = new byte[packetPlusHeadersLength];

            BitConverter.GetBytes((ushort)nextReceiveWritePointer).CopyTo(packetWithHeader, 0);
            BitConverter.GetBytes((ushort)data.Length).CopyTo(packetWithHeader, 2);
            BitConverter.GetBytes((ushort)(1 << 7)).CopyTo(packetWithHeader, 4);
            data.CopyTo(packetWithHeader, 6);

            var firstPartLength = Math.Min(packetPlusHeadersLength, receiveBufferEnd - currentReceiveWritePointer + 1);

            Array.Copy(packetWithHeader, 0, ethernetBuffer, currentReceiveWritePointer, firstPartLength);
            if (firstPartLength < packetPlusHeadersLength)
            {
                // packet overlaps buffer
                Array.Copy(packetWithHeader, firstPartLength, ethernetBuffer, receiveBufferStart, packetWithHeader.Length - firstPartLength);
            }
            currentReceiveWritePointer = nextReceiveWritePointer;

            waitingPacketCount++;
            RefreshInterruptStatus();
            return(true);
        }
Example #4
0
        public void ReceiveFrame(EthernetFrame frame)
        {
            lock (innerLock)
            {
                this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length);
                if (!receiverEnabled.Value)
                {
                    this.Log(LogLevel.Info, "Receiver not enabled, dropping frame");
                    return;
                }

                if (!EthernetFrame.CheckCRC(frame.Bytes))
                {
                    this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                    return;
                }

                rxDescriptorsQueue.CurrentDescriptor.Read();
                if (rxDescriptorsQueue.CurrentDescriptor.IsEmpty)
                {
                    if (!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, (uint)frame.Bytes.Length))
                    {
                        // The current implementation doesn't handle packets that do not fit into a single buffer.
                        // In case we encounter this error, we probably should implement partitioning/scattering procedure.
                        this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer: maximum packet length exceeded.");
                        return;
                    }

                    rxDescriptorsQueue.CurrentDescriptor.Length = (ushort)frame.Bytes.Length;
                    // Packets going over several buffers not supported
                    rxDescriptorsQueue.CurrentDescriptor.IsLast  = true;
                    rxDescriptorsQueue.CurrentDescriptor.IsEmpty = false;
                    // write this back to memory
                    rxDescriptorsQueue.CurrentDescriptor.Update();

                    rxDescriptorsQueue.GoToNextDescriptor();

                    interruptManager.SetInterrupt(Interrupts.ReceiveBufferInterrupt);
                    interruptManager.SetInterrupt(Interrupts.ReceiveFrameInterrupt);
                }
                else
                {
                    this.Log(LogLevel.Warning, "Receive DMA buffer overflow");
                }
            }
        }
Example #5
0
        public void ReceiveFrame(EthernetFrame frame)//when data is send to us
        {
            lock (sync)
            {
                if (!frame.DestinationMAC.Value.IsBroadcast && frame.DestinationMAC.Value != MAC)
                {
                    return;
                }

                if (!EthernetFrame.CheckCRC(frame.Bytes))
                {
                    this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                    return;
                }

                rxPacketQueue.Enqueue(frame);
            }
        }
        public void ReceiveFrame(EthernetFrame frame)
        {
            lock (sync)
            {
                this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length);
                if (!receiveEnabled.Value)
                {
                    this.Log(LogLevel.Info, "Receiver not enabled, dropping frame");
                    return;
                }

                if (!ignoreRxFCS.Value && !EthernetFrame.CheckCRC(frame.Bytes))
                {
                    this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                    return;
                }

                rxDescriptorsQueue.CurrentDescriptor.Invalidate();
                if (!rxDescriptorsQueue.CurrentDescriptor.Ownership)
                {
                    if (!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, receiveBufferOffset.Value))
                    {
                        this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer");
                        return;
                    }

                    rxDescriptorsQueue.CurrentDescriptor.StartOfFrame = true;
                    rxDescriptorsQueue.CurrentDescriptor.EndOfFrame   = true;

                    rxDescriptorsQueue.GoToNextDescriptor();

                    frameReceived.Value = true;
                    interruptManager.SetInterrupt(Interrupts.ReceiveComplete);
                }
                else
                {
                    this.Log(LogLevel.Warning, "Receive DMA buffer overflow");
                    bufferNotAvailable.Value = true;
                    interruptManager.SetInterrupt(Interrupts.ReceiveUsedBitRead);
                }
            }
        }
Example #7
0
        public void ReceiveFrame(EthernetFrame frame)
        {
            /*if(machine.ElapsedTime < TimeSpan.FromSeconds(30))
             * {
             *  return;
             * }*/
            lock (receiveLock)
            {
                if ((dmaStatus & ReceiveStatus) != 0)
                {
                    queue.Enqueue(frame);
                    return;
                }
                if (!packetSent)
                {
                    this.Log(LogLevel.Error, "Dropping - no packets sent.");
                    return;
                }
                if (frame.Bytes.Length < 14)
                {
                    this.Log(LogLevel.Error, "DROPPING - packet too short.");
                    return;
                }
                if (this.machine.IsPaused)
                {
                    this.Log(LogLevel.Debug, "DROPPING - cpu is halted.");
                    return;
                }
                var destinationMac = frame.DestinationMAC;
                if (!destinationMac.IsBroadcast && !destinationMac.Equals(MAC))
                {
                    this.Log(LogLevel.Debug, "DROPPING - not for us.");
                    return;
                }

                /*
                 * if((dmaInterruptEnable & (ReceiveStatus)) == 0)
                 * {
                 *  this.Log(LogLevel.Debug, "DROPPING - rx irq is turned off.");
                 *  return;
                 * }
                 */
                this.Log(LogLevel.Noisy, Misc.DumpPacket(frame, false, machine));
                if (dmaReceiveDescriptorListAddress < 0x20000000)
                {
                    // TODO: not in ram
                    this.Log(LogLevel.Error, "DROPPING - descriptor is not valid.");
                    return;
                }
                var written = 0;
                var first   = true;
                var bytes   = frame.Bytes;

                if (!EthernetFrame.CheckCRC(bytes))
                {
                    if (!(crcStrippingForTypeFrames && bytes.Length > 1536) || !(automaticPadCRCStripping && bytes.Length < 1500))
                    {
                        this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                        return;
                    }
                }

                var receiveDescriptor = new RxDescriptor(machine.SystemBus);
                receiveDescriptor.Fetch(dmaReceiveDescriptorListAddress);
                if (receiveDescriptor.IsUsed)
                {
                    this.Log(LogLevel.Error, "DROPPING  - descriptor is used.");
                    return;
                }
                this.Log(LogLevel.Noisy, "DESCRIPTOR ADDR1={0:X}, ADDR2={1:X}", receiveDescriptor.Address1, receiveDescriptor.Address2);
                while (!receiveDescriptor.IsUsed)
                {
                    if (receiveDescriptor.Address1 < 0x20000000)
                    {
                        this.Log(LogLevel.Error, "Descriptor points outside of ram, aborting... This should not happen!");
                        break;
                    }
                    receiveDescriptor.IsUsed  = true;
                    receiveDescriptor.IsFirst = first;
                    first = false;
                    var howManyBytes = Math.Min(receiveDescriptor.Buffer1Length, frame.Bytes.Length - written);
                    var toWriteArray = new byte[howManyBytes];

                    Array.Copy(bytes, written, toWriteArray, 0, howManyBytes);
                    machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address1);
                    written += howManyBytes;
                    //write second buffer
                    if (frame.Bytes.Length - written > 0 && !receiveDescriptor.IsNextDescriptorChained)
                    {
                        howManyBytes = Math.Min(receiveDescriptor.Buffer2Length, frame.Bytes.Length - written);
                        toWriteArray = new byte[howManyBytes];
                        Array.Copy(bytes, written, toWriteArray, 0, howManyBytes);
                        machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address2);
                        written += howManyBytes;
                    }
                    if (frame.Bytes.Length - written <= 0)
                    {
                        receiveDescriptor.IsLast = true;
                        this.NoisyLog("Setting descriptor length to {0}", (uint)frame.Bytes.Length);
                        receiveDescriptor.FrameLength = (uint)frame.Bytes.Length;
                    }
                    this.NoisyLog("Writing descriptor at 0x{6:X}, first={0}, last={1}, written {2} of {3}. next_chained={4}, endofring={5}", receiveDescriptor.IsFirst, receiveDescriptor.IsLast, written, frame.Bytes.Length, receiveDescriptor.IsNextDescriptorChained, receiveDescriptor.IsEndOfRing, dmaReceiveDescriptorListAddress);
                    receiveDescriptor.WriteBack();
                    if (!receiveDescriptor.IsNextDescriptorChained)
                    {
                        dmaReceiveDescriptorListAddress += 8;
                    }
                    else if (receiveDescriptor.IsEndOfRing)
                    {
                        dmaReceiveDescriptorListAddress = dmaReceiveDescriptorListAddressBegin;
                    }
                    else
                    {
                        dmaReceiveDescriptorListAddress = receiveDescriptor.Address2;
                    }
                    if (frame.Bytes.Length - written <= 0)
                    {
                        if ((dmaInterruptEnable & (ReceiveStatus)) != 0)// receive interrupt
                        {
                            dmaStatus |= ReceiveStatus;
                            IRQ.Set();
                        }
                        else
                        {
                            this.DebugLog("Exiting but not scheduling an interrupt!");
                        }
                        break;
                    }
                    receiveDescriptor.Fetch(dmaReceiveDescriptorListAddress);
                }
                this.DebugLog("Packet of length {0} delivered.", frame.Bytes.Length);
                if (written < frame.Bytes.Length)
                {
                    this.Log(LogLevel.Error, "Delivered only {0} from {1} bytes!", written, frame.Bytes.Length);
                }
            }
        }
Example #8
0
        public void ReceiveFrame(EthernetFrame frame)
        {
            lock (innerLock)
            {
                this.Log(LogLevel.Debug, "Received packet, length {0}", frame.Bytes.Length);
                if (!receiverEnabled.Value)
                {
                    this.Log(LogLevel.Info, "Receiver not enabled, dropping frame");
                    return;
                }

                if (discardWithMACLayerError.Value && !EthernetFrame.CheckCRC(frame.Bytes))
                {
                    this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                    return;
                }

                if (discardIPHeaderInvalidChecksum.Value)
                {
                    var packet = (IPv4Packet)frame.UnderlyingPacket.Extract(typeof(IPv4Packet));
                    if (packet != null && !packet.ValidChecksum)
                    {
                        this.Log(LogLevel.Info, "Invalid IpV4 checksum, packet discarded");
                        return;
                    }
                }

                if (discardProtocolInvalidChecksum.Value)
                {
                    var tcpPacket = (TcpPacket)frame.UnderlyingPacket.Extract(typeof(TcpPacket));
                    if (tcpPacket != null && !tcpPacket.ValidChecksum)
                    {
                        this.Log(LogLevel.Info, "Invalid TCP checksum, packet discarded");
                        return;
                    }

                    var udpPacket = (UdpPacket)frame.UnderlyingPacket.Extract(typeof(UdpPacket));
                    if (udpPacket != null && !udpPacket.ValidChecksum)
                    {
                        this.Log(LogLevel.Info, "Invalid UDP checksum, packet discarded");
                        return;
                    }

                    var icmpv4Packet = (ICMPv4Packet)frame.UnderlyingPacket.Extract(typeof(ICMPv4Packet));
                    if (icmpv4Packet != null)
                    {
                        var checksum = icmpv4Packet.Checksum;
                        icmpv4Packet.Checksum = 0x0;
                        icmpv4Packet.UpdateCalculatedValues();
                        if (checksum != icmpv4Packet.Checksum)
                        {
                            this.Log(LogLevel.Info, "Invalid ICMPv4 checksum, packet discarded");
                            return;
                        }
                    }

                    var icmpv6Packet = (ICMPv6Packet)frame.UnderlyingPacket.Extract(typeof(ICMPv6Packet));
                    if (icmpv6Packet != null)
                    {
                        var checksum = icmpv6Packet.Checksum;
                        icmpv6Packet.Checksum = 0x0;
                        icmpv6Packet.UpdateCalculatedValues();
                        if (checksum != icmpv6Packet.Checksum)
                        {
                            this.Log(LogLevel.Info, "Invalid ICMPv6 checksum, packet discarded");
                            return;
                        }
                    }
                }

                rxDescriptorsQueue.CurrentDescriptor.Read();
                if (rxDescriptorsQueue.CurrentDescriptor.IsEmpty)
                {
                    if (!rxDescriptorsQueue.CurrentDescriptor.WriteBuffer(frame.Bytes, (uint)frame.Bytes.Length))
                    {
                        // The current implementation doesn't handle packets that do not fit into a single buffer.
                        // In case we encounter this error, we probably should implement partitioning/scattering procedure.
                        this.Log(LogLevel.Warning, "Could not write the incoming packet to the DMA buffer: maximum packet length exceeded.");
                        return;
                    }

                    rxDescriptorsQueue.CurrentDescriptor.Length = (ushort)frame.Bytes.Length;
                    // Packets going over several buffers not supported
                    rxDescriptorsQueue.CurrentDescriptor.IsLast  = true;
                    rxDescriptorsQueue.CurrentDescriptor.IsEmpty = false;
                    // write this back to memory
                    rxDescriptorsQueue.CurrentDescriptor.Update();

                    rxDescriptorsQueue.GoToNextDescriptor();

                    interruptManager.SetInterrupt(Interrupts.ReceiveBufferInterrupt);
                    interruptManager.SetInterrupt(Interrupts.ReceiveFrameInterrupt);
                }
                else
                {
                    this.Log(LogLevel.Warning, "Receive DMA buffer overflow");
                }
            }
        }
 public void ReceiveFrame(EthernetFrame frame)
 {
     lock (lockObj)
     {
         this.NoisyLog("Received frame on MAC {0}. Frame destination MAC is {1}", this.MAC.ToString(), frame.DestinationMAC);
         var size   = frame.Bytes.Length;
         var isEven = (size & 1) == 0;
         if ((receiveControl & ReceiveEnabled) == 0 || (receiveControl & SoftwareReset) != 0)
         {
             //Drop if reset is on or receiving is not enabled.
             return;
         }
         var packetSize = Math.Max(64, size & ~1);
         //64 is the minimal length
         packetSize += 6;
         var withCRC = (receiveControl & StripCRC) == 0;
         if (withCRC)
         {
             packetSize += 4;
         }
         if (packetSize > MaxPacketSize)
         {
             //Maybe we should react to overruns. Now we just drop.
             return;
         }
         byte whichPacket;
         if (!TryAllocatePacket(out whichPacket))
         {
             return;
         }
         rxFifo.Enqueue(whichPacket);
         var status = 0;
         if (size > 1518)
         {
             status |= 0x0800;
         }
         if (!isEven)
         {
             status |= 0x1000;
         }
         var currentBuffer = memoryBuffer[whichPacket];
         currentBuffer.Data[0] = (byte)(status & 0xff);
         currentBuffer.Data[1] = (byte)(status >> 8);
         currentBuffer.Data[2] = (byte)(packetSize & 0xff);
         currentBuffer.Data[3] = (byte)(packetSize >> 8);
         var frameBytes = frame.Bytes;
         for (int i = 0; i < (size & ~1); i++)
         {
             currentBuffer.Data[4 + i] = frameBytes[i];
         }
         //Pad with 0s
         if (size < 64)
         {
             var pad = 64 - size;
             if (!isEven)
             {
                 for (int i = 0; i < pad; i++)
                 {
                     currentBuffer.Data[4 + i + size] = 0;
                 }
             }
             else
             {
                 for (int i = 0; i < pad; i++)
                 {
                     currentBuffer.Data[4 + i + size + 1] = 0;
                 }
             }
             size = 64;
         }
         if (withCRC)
         {
             if (!EthernetFrame.CheckCRC(frame.Bytes))
             {
                 this.Log(LogLevel.Info, "Invalid CRC, packet discarded");
                 return;
             }
         }
         if (!isEven)
         {
             //TODO: For a short, odd-length packet, will it work? Should it not be written before?
             currentBuffer.Data[packetSize - 2] = frameBytes[size - 1];
             currentBuffer.Data[packetSize - 1] = 0x60;
         }
         else
         {
             currentBuffer.Data[packetSize - 1] = 0x40;
         }
         interruptStatus |= RxInterrupt;
         Update();
     }
 }