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) { var frame = new EthernetFrame(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(); } } } }
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(); } } } }