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); } } }
private void ReceiveFrameInner(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.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.Value; 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 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.Length - written); var toWriteArray = new byte[howManyBytes]; var bytes = frame.Bytes; Array.Copy(bytes, written, toWriteArray, 0, howManyBytes); machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address1); written += howManyBytes; //write second buffer if(frame.Length - written > 0 && !receiveDescriptor.IsNextDescriptorChained) { howManyBytes = Math.Min(receiveDescriptor.Buffer2Length, frame.Length - written); toWriteArray = new byte[howManyBytes]; Array.Copy(bytes, written, toWriteArray, 0, howManyBytes); machine.SystemBus.WriteBytes(toWriteArray, receiveDescriptor.Address2); written += howManyBytes; } if(frame.Length - written <= 0) { receiveDescriptor.IsLast = true; this.NoisyLog("Setting descriptor length to {0}", (uint)frame.Length + 4); receiveDescriptor.FrameLength = (uint)frame.Length + 4; //with CRC } 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.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.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.Length); if(written < frame.Length) { this.Log(LogLevel.Error, "Delivered only {0} from {1} bytes!", written, frame.Length); } } }