예제 #1
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
        private void TxExchange()
        {
            int toCount   = 0;
            int fromCount = 0;

            NicDeviceContract /*.Imp*/ imp = (NicDeviceContract)nicChannel.Acquire();

            try {
                PacketFifo src  = this.txFifo.Acquire();
                PacketFifo free = this.txFreeFifo.Acquire();

                toCount = src.Count;
                try {
                    src = imp.GiveTxPacketsToDevice(src);

                    fromCount = src.Count;
                    free.Push(src);
                }
                finally {
                    this.txFreeFifo.Release(free);
                    this.txFifo.Release(src);
                }
            }
            catch (Exception e) {
                DebugStub.Print("TxExchange FAILED arg {0}\n", DebugStub.ArgList(e.ToString()));
                DebugStub.Break();
            }
            finally {
                nicChannel.Release(imp);
            }
            DebugPrint("TxExchange out: {0} in: {1}\n",
                       toCount, fromCount);
        }
예제 #2
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
 //push a single packet onto the ring
 void IAdapter.PopulateTxRing(Bytes header, Bytes data)
 {
     try {
         PacketFifo txFree     = this.txFreeFifo.Acquire();
         PacketFifo txToDevice = this.txFifo.Acquire();
         DebugPrint("populate tx ring\n");
         try {
             Packet packet = txFree.Pop();
             packet.SetFragment(0, header);
             packet.SetFragment(1, data);
             txToDevice.Push(packet);
         }
         finally {
             this.txFreeFifo.Release(txFree);
             this.txFifo.Release(txToDevice);
         }
     }
     catch (Exception e) {
         DebugStub.Print("Populate tx ring failed?? {0}\n", DebugStub.ArgList(e));
         DebugStub.Break();
     }
     //When to exchange?
     //how do we best manage the tradeoff of throughput and latency?
     //to begin let's just send one at a time.
     //I think i'd rather have another thread....
     using (thisLock.Lock()) {
         TxExchange();
     }
 }
예제 #3
0
        ///////////////////////////////////////////////////////////////////////
        //
        // Tx buffer operations
        //

        internal void PopulateTsmtBuffer(PacketFifo fromUser)
        {
            DebugStub.Assert(this.ioRunning);

            // since no transmit interrupts are sent, we must check for
            // transmission events here
            if (txRingBuffer.NewTransmitEvent())
            {
                NicEventType ev = NicEventType.TransmitEvent;
                if (eventRelay != null)
                {
                    eventRelay.ForwardEvent(ev);
                }
            }

            using (txRingBuffer.thisLock.Lock()) {
                while (fromUser.Count > 0)
                {
                    Packet packet = fromUser.Pop();
                    txRingBuffer.LockedPushTsmtBuffer(packet);
                }
                // update hardware tail pointer
                // so that hardware knows it has new packets to transmit
                Write32(Register.TSMT_DESC_TAIL, txRingBuffer.Head);  // sw head is hw tail
            }
        }
예제 #4
0
        private Packet MakePacketFromDescriptor(ulong controlBits)
        {
            PacketFifo inDevPkts = txPacketsInDevice.Acquire();
            Packet     packet    = inDevPkts.Pop();

            // int length   = (int) ((controlBits & TxDescriptor.LENGTH_MASK)
            //                      >> TxDescriptor.LENGTH_SHIFT);
            int stat_err = (int)((controlBits & TxDescriptor.ERR_STAT_MASK)
                                 >> TxDescriptor.ERR_STAT_SHIFT);


            //DebugStub.Assert(packet.GetFragmentVirtualAddress(0) == fragmentVirtAddr);

            if (((TxStatErrFields.LATE_COLLISION |
                  TxStatErrFields.EXCESS_COLLISIONS |
                  TxStatErrFields.TRANSMIT_UNDERRUN) & stat_err) == 0)
            {
                packet.FromDeviceFlags = FromDeviceFlags.TransmitSuccess;
            }
            else
            {
                packet.FromDeviceFlags = FromDeviceFlags.TransmitError;
            }

            txPacketsInDevice.Release(inDevPkts);

            return(packet);
        }
        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);
        }
예제 #6
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
        private void RxProvision()
        {
            PacketFifo toDevice = this.rxFifo.Acquire();

            RxProvisionInternal(toDevice);
            this.rxFifo.Release(toDevice);
        }
예제 #7
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
 private void RxProvisionInternal(PacketFifo toDevice)
 {
     for (int i = 0; i < toDevice.Capacity; i++)
     {
         toDevice.Push(
             new Packet(
                 new Bytes(new byte[this.mtu])
                 )
             );
     }
 }
        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();
            }
        }
예제 #9
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
        //since data comes from the user, the packets are empty shells
        //with a default of two fragments; one for the header and one for
        //the packet body
        private void TxProvision()
        {
            PacketFifo txFree = this.txFreeFifo.Acquire();

            for (int i = 0; i < txFree.Capacity; i++)
            {
                txFree.Push(
                    new Packet(2)
                    );
            }
            this.txFreeFifo.Release(txFree);
        }
예제 #10
0
        internal void LockedPushTsmtBuffer(Packet packet)
        {
            DebugStub.Assert(packet.FragmentCount == 1);
            DebugStub.Assert(!txRingBuffer.IsFull);

            this._LockedPushTsmtBuffer(packet);

            PacketFifo liveFifo = this.txPacketsInDevice.Acquire();

            liveFifo.Push(packet);
            txPacketsInDevice.Release(liveFifo);
        }
예제 #11
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
 //push a single packet onto the ring
 void IAdapter.PopulateTxRing(Bytes header, Bytes data)
 {
     try {
         PacketFifo txFree     = this.txFreeFifo.Acquire();
         PacketFifo txCoalesce = this.txCoalesceFifo.Acquire();
         try {
             DebugStub.Assert(txFree.Count > 0);
             int cnt = 0;
             while (txFree.Count <= 0)
             {
                 //try again...
                 //this happens when we're hammering the outgoing connection
                 this.txCoalesceFifo.Release(txCoalesce);
                 this.txFreeFifo.Release(txFree);
                 this.muxEvent.Set();
                 Thread.Yield();
                 txFree     = this.txFreeFifo.Acquire();
                 txCoalesce = this.txCoalesceFifo.Acquire();
                 if (cnt > 100)
                 {
                     DebugStub.Print("txFree empty???\n");
                     //DebugStub.Break();
                 }
                 cnt++;
             }
             Packet packet = txFree.Pop();
             packet.SetFragment(0, header);
             packet.SetFragment(1, data);
             if ((txCoalesce.Count + 1) > txCoalesce.Capacity)
             {
                 DebugStub.Break();
             }
             DebugStub.Assert((txCoalesce.Count + 1) <= txCoalesce.Capacity);
             txCoalesce.Push(packet);
         }
         catch {
             DebugStub.Print("failure in populate tx ring\n");
             DebugStub.Break();
             DebugStub.Assert(false);
         }
         finally {
             this.txCoalesceFifo.Release(txCoalesce);
             this.txFreeFifo.Release(txFree);
             //notify the mux that there are waiting packets
             this.muxEvent.Set();
         }
     }
     catch (Exception e) {
         DebugStub.Print("Populate tx ring failed?? {0}\n", DebugStub.ArgList(e));
         DebugStub.Break();
     }
 }
예제 #12
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);
        }
예제 #13
0
        ///////////////////////////////////////////////////////////////////////
        //
        // Rx buffer operations
        //

        internal void PopulateRecvBuffer(PacketFifo fromUser)
        {
            if (fromUser.Count < 1)
            {
                return;
            }
            using (rxRingBuffer.thisLock.Lock()) {
                while (fromUser.Count > 0)
                {
                    rxRingBuffer.LockedPushRecvBuffer(fromUser.Pop());
                }
                Write32(Register.RECV_DESC_TAIL, rxRingBuffer.Head);
            }
        }
예제 #14
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
        //XXX On the first exchange we receive an empty fifo from the Nic
        //We fill it here...this should be special cased in the startio
        //routine...
        private void RxExchangeInternal(NicDeviceContract /*.Imp*/ imp)
        {
            int        toCount, fromCount;
            PacketFifo exFifo = this.rxFifo.Acquire();

            toCount = exFifo.Count;
            try {
                exFifo    = imp.GiveRxPacketsToDevice(exFifo);
                fromCount = exFifo.Count;
            }
            finally {
                this.rxFifo.Release(exFifo);
            }
            DebugPrint("RxExchange out: {0} in: {1}\n",
                       toCount, fromCount);
        }
예제 #15
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
        // Get the received packets from the adapter
        void DeMuxReceivedPackets()
        {
            //Grab the latest set of packets
            RxExchange();

            PacketFifo newPackets = this.rxFifo.Acquire();

            try {
                int count = newPackets.Count;
                for (int i = 0; i < count; i++)
                {
                    Packet packet = newPackets.Pop();

                    // If packet from device has an error
                    // recycle it right away.
                    FromDeviceFlags fromFlags = packet.FromDeviceFlags;
                    if ((fromFlags & FromDeviceFlags.ReceiveError) != 0)
                    {
                        DebugStub.Print("Packet had error???\n");
                        newPackets.Push(packet);
                        continue;
                    }
                    Bytes data = packet.ReleaseFragment(0);
                    Ethernet.ProcessIncomingPacket(data, this);
#if  false
                    if (filterAdapter == null ||
                        filterAdapter.ProcessIncomingPacket(data))
                    {
                        Ethernet.ProcessIncomingPacket(data, this);
                    }
                    else
                    {
                        //delete data;
                    }
#endif
                    //XXX Totally inefficient first try immediately replaces
                    //the lost data.
                    Bytes nxtPacket = new Bytes(new byte[this.mtu]);
                    packet.SetFragment(0, nxtPacket);
                    newPackets.Push(packet);
                }
            }
            finally {
                this.rxFifo.Release(newPackets);
            }
        }
        public EOSS3_PacketFIFO(Machine machine) : base(machine)
        {
            queueNames = new Dictionary <long, string>()
            {
                { 0, "PacketFifo0" },
                { 1, "PacketFifo1" },
                { 2, "PacketFifo2" },
                { 3, "PacketFifo8k" }
            };

            packetFifos = new PacketFifoBase[NumberOfQueues];

            for (var i = 0; i < NumberOfRegularQueues; i++)
            {
                packetFifos[i] = new PacketFifo(this, queueNames[i], fifoSizes[i]);
            }

            packetFifos[NumberOfQueues - 1] = new PacketFifoSwitchable(this, queueNames[NumberOfQueues - 1], fifoSizes[NumberOfQueues - 1]);

            DefineRegisters();
        }
예제 #17
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
        public void Run()
        {
            System.DebugStub.Print("Nic@" + Kernel.CurrentThread + ". ");
            while (true)
            {
                this.muxEvent.WaitOne();
                PacketFifo txCoalesce = this.txCoalesceFifo.Acquire();
                PacketFifo txToDevice = this.txFifo.Acquire();

                try {
                    DebugPrint("coalescing {0} packets\n", txCoalesce.Count);
                    txToDevice.Push(txCoalesce);
                }
                catch (Exception e) {
                    DebugStub.Print("Mux FAILED! arg {0}\n", DebugStub.ArgList(e.ToString()));
                    DebugStub.Break();
                }
                finally {
                    this.txCoalesceFifo.Release(txCoalesce);
                    this.txFifo.Release(txToDevice);
                    TxExchange();
                }
            }
        }
예제 #18
0
 internal void DrainTsmtBuffer(PacketFifo toUser)
 {
     using (txRingBuffer.thisLock.Lock()) {
         txRingBuffer.LockedDrainTsmtBuffer(toUser);
     }
 }
예제 #19
0
 internal void DrainRecvBuffer(PacketFifo toUser)
 {
     using (rxRingBuffer.thisLock.Lock()) {
         rxRingBuffer.LockedDrainRecvBuffer(toUser);
     }
 }
예제 #20
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
 internal ExRefPacketFifo(PacketFifo o, bool dummy)
 {
     VTable.Assert(o != null);
     this.o = o;
 }
예제 #21
0
파일: Nic.cs 프로젝트: Paul1nh0/Singularity
 public void Release(PacketFifo v)
 {
     o = v;
     thisLock.Release();
 }
예제 #22
0
 public PacketFifo GiveTxPacketsToDevice(PacketFifo txFifo)
 {
     device.PopulateTsmtBuffer(txFifo);
     device.DrainTsmtBuffer(txFifo);
     return(txFifo);
 }
예제 #23
0
 public PacketFifo GiveRxPacketsToDevice(PacketFifo rxFifo)
 {
     device.PopulateRecvBuffer(rxFifo);
     device.DrainRecvBuffer(rxFifo);
     return(rxFifo);
 }