private void Finished() { if (mode == Mode.WaitingForPacket) { this.DebugLog("Packet received, LEN {7} {0:x} {1:x} {2:x} {3:x} (...) {4:x} {5:x} {6:x}", request[0], request[1], request[2], request[3], request[currentLength - 5], request[currentLength - 4], request[currentLength - 3], currentLength); var frame = new byte[currentLength]; Array.Copy(request, 0, frame, 0, currentLength); //TODO: CRC handling var ethernetFrame = EthernetFrame.CreateEthernetFrameWithoutCRC(frame); Link.TransmitFrameFromInterface(ethernetFrame); mode = Mode.Standard; currentLength = 4; transmissionEnded = true; if (interruptAfterTransmision) { SignalInterrupt(); } } if (mode == Mode.SendingPacket) { mode = Mode.Standard; currentLength = 4; lock (packetQueue) { if (packetQueue.Count > 0) { SignalInterrupt(); } } } if (mode == Mode.Special) { currentLength = 4; mode = Mode.Standard; return; } switch (lastPacketType) { case 0xC0: mode = Mode.WaitingForPacket; var encodedLength = request[3] + (request[4] << 8); this.DebugLog("Encoded length is 0x{0:X}.", encodedLength); currentLength = Align(encodedLength + 1 + 1); transmissionEnded = false; break; case 0xF: lastPacketType = 0; break; } }
private void SendSingleFrame(IEnumerable <byte> bytes, bool isCRCIncluded) { var frame = EthernetFrame.CreateEthernetFrameWithoutCRC(bytes.ToArray()); if (!isCRCIncluded) { if (checksumGeneratorEnabled.Value) { this.Log(LogLevel.Noisy, "Generating checksum for the frame"); frame.FillWithChecksums(new [] { EtherType.IpV4 }, new [] { IPProtocolType.TCP, IPProtocolType.UDP }); } else { this.Log(LogLevel.Warning, "The frame has no CRC, but the automatic checksum generation is disabled"); } } this.Log(LogLevel.Noisy, "Sending packet, length {0}", frame.Bytes.Length); FrameReady?.Invoke(frame); }
private void SendFrames() { this.Log(LogLevel.Noisy, "Sending frame"); var transmitDescriptor = new TxDescriptor(machine.SystemBus); var packetData = new List <byte>(); transmitDescriptor.Fetch(dmaTransmitDescriptorListAddress); while (!transmitDescriptor.IsUsed) { transmitDescriptor.IsUsed = true; this.Log(LogLevel.Noisy, "GOING TO READ FROM {0:X}, len={1}", transmitDescriptor.Address1, transmitDescriptor.Buffer1Length); packetData.AddRange(machine.SystemBus.ReadBytes(transmitDescriptor.Address1, transmitDescriptor.Buffer1Length)); if (!transmitDescriptor.IsNextDescriptorChained) { packetData.AddRange(machine.SystemBus.ReadBytes(transmitDescriptor.Address2, transmitDescriptor.Buffer2Length)); } transmitDescriptor.WriteBack(); if (transmitDescriptor.IsEndOfRing) { dmaTransmitDescriptorListAddress = dmaTransmitDescriptorListAddressBegin; } else if (transmitDescriptor.IsNextDescriptorChained) { dmaTransmitDescriptorListAddress = transmitDescriptor.Address2; } else { dmaTransmitDescriptorListAddress += 8; } if (transmitDescriptor.IsLast) { this.Log(LogLevel.Noisy, "Sending frame of {0} bytes.", packetData.Count); if (Link.IsConnected) { var frame = EthernetFrame.CreateEthernetFrameWithoutCRC(packetData.ToArray()); if (transmitDescriptor.ChecksumInstertionControl > 0) { this.Log(LogLevel.Noisy, "Calculating checksum (mode {0}).", transmitDescriptor.ChecksumInstertionControl); if (transmitDescriptor.ChecksumInstertionControl == 1) { //IP only frame.FillWithChecksums(supportedEtherChecksums, null); } else { //IP and payload frame.FillWithChecksums(supportedEtherChecksums, supportedIPChecksums); } } this.Log(LogLevel.Debug, Misc.DumpPacket(frame, true, machine)); packetSent = true; //We recreate the EthernetFrame because the CRC should be appended after creating inner checksums. var frameWithCrc = EthernetFrame.CreateEthernetFrameWithCRC(frame.Bytes); Link.TransmitFrameFromInterface(frameWithCrc); } } transmitDescriptor.Fetch(dmaTransmitDescriptorListAddress); } //set TransmitBufferUnavailable dmaStatus |= TransmitBufferUnavailableStatus; if ((dmaInterruptEnable & (StartStopTransmission)) == 0) { IRQ.Set(); } this.Log(LogLevel.Noisy, "Frame sent."); }
private void SendFrames() { lock (sync) { txBufferDescriptor txBD = new txBufferDescriptor(machine.SystemBus); bool interrupt = false; List <byte> packet = new List <byte>(); txBD.Fetch(registers.TxQueueBaseAddr); while (!txBD.Used) { while (!txBD.Last) { packet.AddRange(machine.SystemBus.ReadBytes(txBD.Word0, txBD.Length)); txBD.Used = true; txBD.WriteBack(); if (txBD.Wrap) { registers.TxQueueBaseAddr = txBufferBase; } else { registers.TxQueueBaseAddr += 8; } txBD.Fetch(registers.TxQueueBaseAddr); } interrupt = false; txBD.Used = true; packet.AddRange(machine.SystemBus.ReadBytes(txBD.Word0, txBD.Length)); if ((registers.DMAConfig & 1u << 11) != 0) //if checksum offload enable { if ((packet[14] & 0xF0) == 0x40) //IP packet { ushort cksum; IPHeaderLength = (ushort)((packet[14] & 0x0F) * 4); if (packet[23] == 0x06) // TCP packet { IPpacket tcpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.TCP); tcpPacket.ReadFromBuffer(packet.ToArray()); cksum = tcpPacket.GetChecksum(); cksum -= 1; packet[MACHeaderLegth + IPHeaderLength + 16] = (byte)((cksum >> 8) & 0xFF); packet[MACHeaderLegth + IPHeaderLength + 17] = (byte)((cksum) & 0xFF); } else if (packet[23] == 0x11) // UDP packet { IPpacket udpPacket = new IPpacket(IPHeaderLength, IPpacket.PacketType.UDP); udpPacket.ReadFromBuffer(packet.ToArray()); cksum = udpPacket.GetChecksum(); cksum -= 1; packet[MACHeaderLegth + IPHeaderLength + 6] = (byte)((cksum >> 8) & 0xFF); packet[MACHeaderLegth + IPHeaderLength + 7] = (byte)((cksum) & 0xFF); } } } if (Link.IsConnected) { EthernetFrame frame; if (!txBD.NoCRC) { frame = EthernetFrame.CreateEthernetFrameWithCRC(packet.ToArray()); } else { frame = EthernetFrame.CreateEthernetFrameWithoutCRC(packet.ToArray()); } this.Log(LogLevel.Noisy, "Sending packet length {0}", packet.ToArray().Length); Link.TransmitFrameFromInterface(frame); } txBD.WriteBack(); if (txBD.Wrap) { registers.TxQueueBaseAddr = txBufferBase; } else { registers.TxQueueBaseAddr += 8; } registers.TxStatus |= 1u << 5; //tx complete txBD.Fetch(registers.TxQueueBaseAddr); if (txBD.Used) { registers.TxStatus |= 0x01; if ((registers.InterruptMask & (1u << 3)) == 0) { registers.InterruptStatus |= 1u << 3; interrupt = true; } } if ((registers.InterruptMask & (1u << 7)) == 0) { registers.InterruptStatus |= 1u << 7; interrupt = true; } if (interrupt) { IRQ.Set(); } } } }