internal IntelRingBuffer(uint capacity) //requires capacity > 0 && IsPowerOf2(capacity); { uint length = capacity * DescriptorBytes; DmaMemory region = new DmaMemory((int)length); //TODO: DmaMemory.AllocatePhysical(length, AlignmentBytes); // (ARM only, not x86) PlatformService.SetCacheAttributes(region.VirtualAddress, // (UIntPtr)region.Length, // false, // false); this.region = region; this.mapEntries = new MapEntry [capacity]; for (int i = 0; i < capacity; i++) { this.mapEntries[i].mem = new DmaMemory((int)Intel.IEEE8023FrameBytes); } this.capacity = capacity; this.head = 0; this.tail = 0; this.count = 0; // Clear out ring buffer for (int i = 0; i < region.Length; i += 4) { region.Write32(i, 0); } }
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); }
// Returns true if hardware is done with this descriptor. internal bool Peek(out DmaMemory mem, out ulong controlBits) { if (this.count > 0) { UIntPtr pa; ReadDescriptor(this.tail, out pa, out controlBits); DebugStub.Assert(pa == this.mapEntries[tail].PhysicalAddress); mem = this.mapEntries[tail].mem; return ((controlBits & Descriptor.DESCRIPTOR_DONE) != 0); } else { mem = null; controlBits = 0; return false; } }
/////////////////////////////////////////////////////////////////////// // // Buffer Operations, should only be called when a lock is held // this ring buffer. // private void _LockedPushTsmtBuffer(Packet packet) { // (ARM only, not x86) PlatformService.CleanAndInvalidateDCache(packetVirtAddr, (UIntPtr)length); int length = packet.GetLength(); ulong controlBits = (ulong)ByteOrder.HostToLittleEndian(length); // set necessary command fields controlBits |= (TxCmdFields.END_OF_PACKET | TxCmdFields.INSERT_FCS | TxCmdFields.REPORT_STATUS); DmaMemory mem = txRingBuffer.PeekHead(); packet.CopyToBytes(mem.BytesRef()); txRingBuffer.Push(controlBits); }