/verify/src/Checked/Drivers/Network/Intel/IntelRxRingBuffer.cs
C# | 193 lines | 126 code | 34 blank | 33 comment | 18 complexity | 038a6ed6c45eaaef80315467e77d9ff2 MD5 | raw file
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Microsoft Research Singularity
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // Notes: Adaptor class for the Rx ring buffer.
- //
-
- using Microsoft.Contracts;
- using Microsoft.Singularity.Channels;
- using Microsoft.Singularity.Io;
- using Microsoft.Singularity.Io.Net;
- using Microsoft.Singularity.V1.Services;
- using Microsoft.SingSharp;
-
- using System;
- using ExRefPacketFifo = Microsoft.Singularity.NetStack2.Channels.Nic.ExRefPacketFifo;
- using ByteOrder = Drivers.Net.ByteOrder;
-
- namespace Microsoft.Singularity.Drivers.Network.Intel
- {
- internal class IntelRxRingBuffer
- {
- IntelRingBuffer rxRingBuffer;
- ExRefPacketFifo rxPacketsInDevice;
- internal System.Threading.MonitorLock thisLock = new System.Threading.MonitorLock();
-
- internal IntelRxRingBuffer(uint capacity)
- //requires capacity > 0 && IntelRingBuffer.IsPowerOf2(capacity);
- {
- this.rxRingBuffer = new IntelRingBuffer(capacity);
- this.rxPacketsInDevice = new ExRefPacketFifo(
- new PacketFifo((int) capacity),
- false
- );
- }
-
- internal void Reset()
- {
- rxRingBuffer.Reset();
- }
-
- ///////////////////////////////////////////////////////////////////////
- //
- // Buffer Operations, should only be called when a lock is held
- // this ring buffer.
- //
- private void LockedPushRecvBuffer(int length)
- {
- // (ARM only, not x86) PlatformService.InvalidateDCache(packetVirtAddr, (UIntPtr)length);
-
- ulong controlBits = (ulong) ByteOrder.HostToLittleEndian(length);
-
- rxRingBuffer.Push(controlBits);
- }
-
- static int pass = 0;
-
- internal void LockedPushRecvBuffer(Packet packet)
- {
- DebugStub.Assert(packet.FragmentCount == 1);
- DebugStub.Assert(!rxRingBuffer.IsFull);
-
- int length = packet.GetFragmentLength(0);
-
- this.LockedPushRecvBuffer(length);
- PacketFifo liveFifo = this.rxPacketsInDevice.Acquire();
- liveFifo.Push(packet);
- rxPacketsInDevice.Release(liveFifo);
- }
-
- internal void Dump()
- {
- rxRingBuffer.Dump("rx", 8);
- }
-
- private FromDeviceFlags GetRecvPktFlags(uint stat_err_flags)
- {
- FromDeviceFlags fromDevFlags = 0;
-
- if (((RxErrStatFields.CRC_ERROR | RxErrStatFields.SYMBOL_ERROR |
- RxErrStatFields.SEQUENCE_ERROR | RxErrStatFields.CARRIER_EXT_ERROR |
- RxErrStatFields.RX_DATA_ERROR) & stat_err_flags) != 0) {
- Intel.DebugPrint("Packet Rsv Error\n");
- fromDevFlags |= FromDeviceFlags.ReceiveError;
- } else {
- fromDevFlags |= FromDeviceFlags.ReceiveSuccess;
- }
-
- if (((stat_err_flags & RxErrStatFields.IGNORE_CHECKSUM) == 0) &&
- ((stat_err_flags & RxErrStatFields.IP_CHECKSUM_CALC) != 0)) {
- if ((stat_err_flags & RxErrStatFields.IP_CHECKSUM_ERROR) != 0) {
- Intel.DebugPrint("Bad Ip Checksum\n");
- fromDevFlags |= FromDeviceFlags.BadIp4Checksum;
- } else {
- // Good IP checksum flag???
- }
- }
-
- if (((stat_err_flags & RxErrStatFields.IGNORE_CHECKSUM) == 0) &&
- ((stat_err_flags & RxErrStatFields.TCP_CHECKSUM_CALC)!= 0)) {
- if ((stat_err_flags & RxErrStatFields.TCP_CHECKSUM_ERROR) != 0) {
- fromDevFlags |= (FromDeviceFlags.BadTcp4Checksum |
- FromDeviceFlags.BadUdp4Checksum);
- // don't know if UDP or TCP
- Intel.DebugPrint("Bad TCP/UDP Checksum\n");
- } else {
- fromDevFlags |= (FromDeviceFlags.GoodTcp4Checksum |
- FromDeviceFlags.GoodUdp4Checksum);
- }
- }
-
- //DebugStub.Assert((fromDevFlags == (FromDeviceFlags.ReceiveSuccess)) || (fromDevFlags == (FromDeviceFlags.ReceiveSuccess | FromDeviceFlags.GoodTcp4Checksum | FromDeviceFlags.GoodUdp4Checksum)));
-
- return fromDevFlags;
- }
-
- private Packet MakePacketFromDescriptor(DmaMemory mem, ulong controlBits)
- {
- PacketFifo inDevPkts = rxPacketsInDevice.Acquire();
- Packet packet = inDevPkts.Pop();
- int length = (int) ((controlBits & RxDescriptor.LENGTH_MASK)
- >> RxDescriptor.LENGTH_SHIFT);
- uint stat_err = (uint) ((controlBits & RxDescriptor.ERR_STAT_MASK)
- >> RxDescriptor.ERR_STAT_SHIFT);
-
- // can't deal with fragments yet
- if ((stat_err & RxErrStatFields.END_OF_PACKET) == 0) {
- INucleusCalls.DebugPrintHex(40, 0xd0);
- DebugStub.Print("FRAGMENT\n");
- throw new Exception();
- }
-
- //DebugStub.Assert((stat_err & RxErrStatFields.END_OF_PACKET) != 0);
- //DebugStub.Assert(packet.GetFragmentVirtualAddress(0) == fragmentVirtAddr);
- packet.FromDeviceFlags = GetRecvPktFlags(stat_err);
- packet.SetFragment(0, mem.BytesRef(0, length));
- rxPacketsInDevice.Release(inDevPkts);
-
- return packet;
- }
-
- internal void LockedDrainRecvBuffer(PacketFifo toUser)
- {
- DmaMemory mem;
- ulong controlBits;
- while (rxRingBuffer.Peek(out mem, out controlBits)) {
- Packet packet = MakePacketFromDescriptor(mem, controlBits);
- toUser.Push(packet);
- rxRingBuffer.Pop();
- }
- }
-
- ///////////////////////////////////////////////////////////////////////
- //
- // Ring buffer properties
- //
- internal UIntPtr BaseAddress
- {
- get { return rxRingBuffer.BaseAddress; }
- }
-
- internal bool NewReceiveEvent() {
- DmaMemory mem;
- ulong controlBits;
-
- return rxRingBuffer.Peek(out mem, out controlBits);
- // return rxRingBuffer.Peek();
- }
-
- //[Pure]
- internal uint Capacity { get { return rxRingBuffer.Capacity; } }
-
- //[Pure]
- internal uint Free { get { return rxRingBuffer.Free; } }
-
- //[Pure]
- internal bool IsFull { get { return rxRingBuffer.IsFull; } }
-
- //[Pure]
- internal uint Count { get { return rxRingBuffer.Count; } }
-
- //[Pure]
- internal uint Tail { get { return rxRingBuffer.Tail; } }
-
- //[Pure]
- internal uint Head { get { return rxRingBuffer.Head; } }
-
- //[Pure]
- internal uint DescLength { get { return rxRingBuffer.DescLength; } }
- }
- }