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);
        }
Beispiel #2
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
            }
        }
Beispiel #3
0
 //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();
     }
 }
        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);
        }
Beispiel #5
0
 //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();
     }
 }
Beispiel #6
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);
            }
        }
Beispiel #7
0
        // 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);
            }
        }